Skip to content
Snippets Groups Projects
Commit 44b603b2 authored by Maiykol's avatar Maiykol
Browse files

clean up and retrieve data from backend

parent e29b4ee8
No related branches found
No related tags found
No related merge requests found
Showing
with 230 additions and 89 deletions
This diff is collapsed.
......@@ -199,7 +199,7 @@
</a>
<a *ngFor="let tissue of analysis.getTissues()"
(click)="selectTissue(tissue)"
[class.is-active]="selectedTissue && tissue.id === selectedTissue.id"
[class.is-active]="selectedTissue && tissue.netexId === selectedTissue.netexId"
class="dropdown-item">
{{tissue.name}}
</a>
......
......@@ -162,7 +162,6 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
this.tableDrugs = table;
this.tableDrugs.forEach((r) => {
r.rawScore = r.score;
r.closestViralProteins = (r.closestViralProteins as any).split(',');
});
}));
promises.push(this.http.get<any>(`${environment.backend}task_result/?token=${this.token}&view=proteins`).toPromise()
......@@ -172,8 +171,8 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
this.tableProteins.forEach((r) => {
r.rawScore = r.score;
r.isSeed = isSeed[r.id];
r.closestViralProteins = (r.closestViralProteins as any).split(',');
if (this.analysis.inSelection(r)) {
const wrapper = getWrapperFromNode(r)
if (this.analysis.inSelection(wrapper)) {
this.tableSelectedProteins.push(r);
}
});
......@@ -378,6 +377,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
const details = attributes.details || {};
const wrappers: { [key: string]: Wrapper } = {};
for (const node of network.nodes) {
if (nodeTypes[node] === 'protein') {
this.proteins.push(details[node]);
wrappers[node] = getWrapperFromNode(details[node]);
......@@ -420,14 +420,13 @@ export class AnalysisPanelComponent implements OnInit, OnChanges {
nodeLabel = drug.drugId;
}
}*/
const node = NetworkSettings.getNodeStyle('gene', isSeed, this.analysis.inSelection(details));
const wrapper = getWrapperFromNode(details)
const node = NetworkSettings.getNodeStyle('gene', isSeed, this.analysis.inSelection(wrapper));
node.id = details.id;
node.label = details.name;
node.nodeType = nodeType;
node.isSeed = isSeed;
node.wrapper = details;
return node;
}
......
<div *ngIf="wrapper">
<div>
<p>
<p *ngIf="wrapper.data.name">
<b><span>Name:</span></b>
{{ wrapper.name }}
<span class="is-capitalized"> {{ wrapper.data.name }}</span>
</p>
<p>
<p *ngIf="wrapper.type">
<b><span>Type:</span></b>
<span class="is-capitalized"> {{ wrapper.type }}</span>
</p>
<p *ngIf="wrapper.data.group">
<b><span>Group:</span></b>
<span class="is-capitalized"> {{ wrapper.data.group }}</span>
</p>
<p *ngIf="wrapper.data.uniprotAc">
<b><span>Access:</span></b>
<a href="https://www.uniprot.org/uniprot/{{ wrapper.access }}" target="_blank">
{{ wrapper.access }}
<a href="https://www.uniprot.org/uniprot/{{ wrapper.data.uniprotAc }}" target="_blank">
<span class="is-capitalized"> {{ wrapper.data.uniprotAc }}</span>
</a>
</p>
</div>
<app-toggle [value]="analysis.inSelection(wrapper)"
......
import {Component, Input, OnInit} from '@angular/core';
import {Node} from '../../interfaces';
import {Wrapper} from '../../interfaces';
import {AnalysisService} from '../../services/analysis/analysis.service';
......@@ -11,7 +11,7 @@ import {AnalysisService} from '../../services/analysis/analysis.service';
export class InfoTileComponent implements OnInit {
@Input()
public wrapper: Node;
public wrapper: Wrapper;
constructor(public analysis: AnalysisService) { }
......
<div class="content">
<ng-select [items]="queryItems" bindLabel="backendId" bindValue="data" [virtualScroll]="true" class="custom"
<ng-select [items]="queryItems" bindLabel="id" bindValue="data" [virtualScroll]="true" class="custom"
placeholder="Search..." [hideSelected]="true" [searchFn]="querySearch" (change)="select($event)" data-tooltip="Find proteins in the network.">
<ng-template ng-option-tmp let-item="item">
<b *ngIf="item.type == 'protein'"> {{item.data.name}}</b>
......
......@@ -37,7 +37,7 @@ export class AddExpressedProteinsComponent implements OnChanges {
public async addProteins() {
this.loading = true;
const result = await this.http.post<any>(`${environment.backend}query_tissue_proteins/`,
{tissueId: this.selectedTissue.id, threshold: this.threshold}).toPromise();
{tissueId: this.selectedTissue.netexId, threshold: this.threshold}).toPromise();
const items = [];
for (const detail of result) {
items.push(getWrapperFromNode(detail));
......
import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core';
import { NetexControllerService } from 'src/app/services/netex-controller/netex-controller.service';
import {
Algorithm,
AlgorithmType,
......
......@@ -3,16 +3,20 @@ import {AlgorithmType, QuickAlgorithmType} from './services/analysis/analysis.se
export interface Node {
name: string;
id: string;
access: string;
netexId?: string;
uniprotAc?: string;
group?: string;
color?: string;
shape?: string;
interactions?: Node[];
x?: number;
y?: number;
expressionLevel?: number;
label?: string;
}
export interface Tissue {
id: number;
netexId: number;
name: string;
}
......@@ -83,18 +87,18 @@ export function getNodeIdsFromPDI(edge: NetworkEdge) {
}
export function getDrugNodeId(drug: Drug) {
return `d_${drug.drugId}`;
return `d_${drug.id}`;
}
export function getDrugBackendId(drug: Drug) {
return drug.drugId;
return drug.id;
}
export function getGeneBackendId(gene: Node) {
export function getNodeId(node: Node) {
/**
* Returns backend_id of Gene object
*/
return gene.id.toString();
return node.id.toString();
}
export function getGeneNodeId(gene: Node) {
......@@ -110,7 +114,7 @@ export function getWrapperFromNode(gene: Node): Wrapper {
* Constructs wrapper interface for gene
*/
return {
backendId: getGeneBackendId(gene),
id: getNodeId(gene),
nodeId: getGeneNodeId(gene),
type: 'gene',
data: gene,
......@@ -120,7 +124,7 @@ export function getWrapperFromNode(gene: Node): Wrapper {
export function getWrapperFromDrug(drug: Drug): Wrapper {
return {
backendId: getDrugBackendId(drug),
id: getDrugBackendId(drug),
nodeId: getDrugNodeId(drug),
type: 'drug',
data: drug,
......@@ -130,19 +134,38 @@ export function getWrapperFromDrug(drug: Drug): Wrapper {
export type WrapperType = 'gene' | 'drug';
export interface Wrapper {
backendId: string;
id: string;
nodeId: string;
type: WrapperType;
data: any;
data: {
id: string;
name: string;
netexId?: string;
shape?: string;
color?: string;
interactions?: any;
group?: string;
uniprotAc?: string;
label?: string;
expressionLevel?: number;
x?: number;
y?: number;
drugId?: string;
status?: 'approved' | 'investigational';
inTrial?: boolean;
inLiterature?: boolean;
trialLinks?: string[];
};
}
export interface Drug {
drugId: string;
id: string;
name: string;
status: 'approved' | 'investigational';
inTrial: boolean;
inLiterature: boolean;
trialLinks: string[];
netexId: string;
}
export interface Dataset {
......@@ -153,6 +176,6 @@ export interface Dataset {
source: Array<string> | null;
year: number;
datasetNames: string;
backendId: string;
id: string;
data: Array<[string, string]>;
}
<div class="is-hidden-mobile" [style.color]="textColor">
<app-launch-analysis [(show)]="showAnalysisDialog"
[target]="analysisDialogTarget">
</app-launch-analysis>
......@@ -151,7 +153,7 @@
</a>
<a *ngFor="let tissue of analysis.getTissues()"
(click)="selectTissue(tissue)"
[class.is-active]="selectedTissue && tissue.id === selectedTissue.id"
[class.is-active]="selectedTissue && tissue.netexId === selectedTissue.netexId"
class="dropdown-item">
{{tissue.name}}
</a>
......@@ -420,9 +422,8 @@
</thead>
<tbody>
<tr *ngFor="let p of analysis.getSelection()">
<td>
</td>
<td>{{p.name}}</td>
<td><p class="is-capitalized">{{p.type}}</p></td>
<td><p class="is-capitalized">{{p.data.label}}</p></td>
<td>
<button (click)="analysis.removeItems([p])" class="button is-small is-danger is-outlined has-tooltip"
data-tooltip="Remove from selection.">
......
......@@ -19,6 +19,7 @@ import {OmnipathControllerService} from '../../services/omnipath-controller/omni
import html2canvas from 'html2canvas';
import {NetworkSettings} from '../../network-settings';
import {defaultConfig, EdgeGroup, IConfig, NodeGroup} from '../../config';
import { NetexControllerService } from 'src/app/services/netex-controller/netex-controller.service';
declare var vis: any;
......@@ -65,13 +66,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
if (typeof network === 'undefined') {
return;
}
console.log(network)
console.log( this.myConfig)
this.networkJSON = network;
this.createNetwork();
}
......@@ -98,6 +93,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
public edges: any;
private networkInternal: any;
// this will store the vis Dataset
public nodeData: { nodes: any, edges: any } = {nodes: null, edges: null};
private dumpPositions = false;
......@@ -116,7 +112,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
public currentViewProteins: Node[];
public currentViewSelectedTissue: Tissue | null = null;
public currentViewNodes: any[];
public currentViewNodes: Node[];
public expressionExpanded = false;
public selectedTissue: Tissue | null = null;
......@@ -126,7 +122,10 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
@ViewChild('network', {static: false}) networkEl: ElementRef;
constructor(public omnipath: OmnipathControllerService, public analysis: AnalysisService) {
constructor(
public omnipath: OmnipathControllerService,
public analysis: AnalysisService,
public netex: NetexControllerService) {
this.showDetails = false;
......@@ -147,8 +146,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
const pos = this.networkInternal.getPositions([item.id]);
node.x = pos[item.id].x;
node.y = pos[item.id].y;
node.x = pos[item.id].x;
node.y = pos[item.id].y;
Object.assign(node, this.myConfig.nodeGroups[node.group]);
updatedNodes.push(node);
}
......@@ -177,12 +174,10 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
}
private setColorPrimary(color: string) {
console.log(color);
document.documentElement.style.setProperty('$primary', color);
}
async getInteractions() {
const names = this.nodeData.nodes.map( (node) => node.label);
const nameToNetworkId = {};
......@@ -192,9 +187,19 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
this.nodeData.edges.update(edges);
}
private getNetwork() {
private async getNetwork() {
const network = JSON.parse(this.networkJSON);
// map data to nodes in backend
console.log('before')
console.log( this.myConfig.identifier)
console.log(network.nodes)
if (network.nodes.length) {
network.nodes = await this.netex.mapNodes(network.nodes, this.myConfig.identifier)
}
console.log('after')
console.log(network.nodes)
this.proteins = network.nodes;
this.edges = network.edges;
}
......@@ -220,7 +225,6 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
public async openSummary(item: Wrapper, zoom: boolean) {
this.selectedWrapper = item;
console.log(this.selectedWrapper)
if (zoom) {
this.zoomToNode(item.nodeId);
}
......@@ -235,13 +239,12 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
public async createNetwork() {
this.analysis.resetSelection();
this.selectedWrapper = null;
this.getNetwork();
await this.getNetwork();
this.proteinData = new ProteinNetwork(this.proteins, this.edges);
this.proteinData.linkNodes();
console.log(this.proteinData)
const {nodes, edges} = this.mapDataToNodes(this.proteinData);
this.nodeData.nodes = new vis.DataSet(nodes);
this.nodeData.edges = new vis.DataSet(edges);
......@@ -253,10 +256,11 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
if (nodeIds.length > 0) {
const nodeId = nodeIds[0];
const node = this.nodeData.nodes.get(nodeId);
const wrapper = getWrapperFromNode(node);
if (this.analysis.inSelection(node)) {
this.analysis.removeItems([node]);
this.analysis.removeItems([wrapper]);
} else {
this.analysis.addItems([node]);
this.analysis.addItems([wrapper]);
}
}
});
......@@ -266,8 +270,7 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
if (nodeIds.length > 0) {
const nodeId = nodeIds[0];
const node = this.nodeData.nodes.get(nodeId);
console.log(node)
const wrapper = node.wrapper;
const wrapper = getWrapperFromNode(node);
this.openSummary(wrapper, false);
} else {
this.closeSummary();
......@@ -322,17 +325,29 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
this.myConfig[key] = {...this.myConfig[key], ...values};
}
private mapCustomNode(customNode: Node): any {
const wrapper = getWrapperFromNode(customNode);
/** Convert input nodes into node objects
*
* @param customNode
* @returns
*/
private mapCustomNode(customNode: any): Node {
let group = customNode.group;
if (typeof group === 'undefined' || typeof this.myConfig.nodeGroups[group] === 'undefined') {
group = 'default';
}
const node = JSON.parse(JSON.stringify(this.myConfig.nodeGroups[group]));
// label is only used for network visualization
let nodeLabel = customNode.name;
if (customNode.name.length === 0) {
nodeLabel = customNode.id;
nodeLabel = customNode.userId;
}
// node.name is actually group name since it comes from the group configuration
// this property is already stored in the wrapper object
// instead, node.name should reflect the actual node name
node.name = customNode.name;
if (node.image) {
node.shape = 'image';
}
......@@ -340,7 +355,8 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
node.id = customNode.id;
node.x = customNode.x;
node.y = customNode.y;
node.wrapper = wrapper;
node.uniprotAc = customNode.uniprotAc
console.log(node)
return node;
}
......@@ -397,8 +413,8 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit {
gProfilerLink(): string {
const queryString = this.analysis.getSelection()
.filter(wrapper => wrapper.group === 'protein')
.map(wrapper => wrapper.access)
.filter(wrapper => wrapper.type === 'gene')
.map(wrapper => wrapper.data.uniprotAc)
.join('%0A');
return 'http://biit.cs.ut.ee/gprofiler/gost?' +
'organism=hsapiens&' +
......
......@@ -4,6 +4,7 @@ import {HttpClient} from '@angular/common/http';
import {environment} from '../../../environments/environment';
import {toast} from 'bulma-toast';
import {Injectable} from '@angular/core';
import { NetexControllerService } from '../netex-controller/netex-controller.service';
export type AlgorithmType = 'trustrank' | 'keypathwayminer' | 'multisteiner' | 'closeness' | 'degree' | 'proximity' | 'betweenness';
export type QuickAlgorithmType = 'quick' | 'super';
......@@ -42,10 +43,10 @@ export class AnalysisService {
private selection = 'main';
private selectedItems = new Map<string, Node>();
private selectListSubject = new Subject<{ items: Node[], selected: boolean | null }>();
private selectedItems = new Map<string, Wrapper>();
private selectListSubject = new Subject<{ items: Wrapper[], selected: boolean | null }>();
private selections = new Map<string, Map<string, Node>>();
private selections = new Map<string, Map<string, Wrapper>>();
public tokens: string[] = [];
public finishedTokens: string[] = [];
......@@ -58,7 +59,7 @@ export class AnalysisService {
private tissues: Tissue[] = [];
constructor(private http: HttpClient) {
constructor(private http: HttpClient, public netex: NetexControllerService) {
const tokens = localStorage.getItem('tokens');
const finishedTokens = localStorage.getItem('finishedTokens');
......@@ -68,7 +69,7 @@ export class AnalysisService {
if (finishedTokens) {
this.finishedTokens = JSON.parse(finishedTokens);
}
// this.startWatching();
this.startWatching();
this.http.get<Tissue[]>(`${environment.backend}tissues/`).subscribe((tissues) => {
this.tissues = tissues;
......@@ -90,7 +91,7 @@ export class AnalysisService {
}
async getTasks() {
return await this.http.get<any>(`${environment.backend}tasks/?tokens=${JSON.stringify(this.tokens)}`).toPromise().catch((e) => {
return await this.netex.getTasks(this.tokens).catch((e) => {
clearInterval(this.intervalId);
});
}
......@@ -104,14 +105,14 @@ export class AnalysisService {
if (this.selections.has(id)) {
this.selectedItems = this.selections.get(id);
} else {
this.selectedItems = new Map<string, Node>();
this.selectedItems = new Map<string, Wrapper>();
}
this.selectListSubject.next({items: Array.from(this.selectedItems.values()), selected: null});
this.selection = id;
}
public addItems(wrappers: Node[]): number {
const addedWrappers: Node[] = [];
public addItems(wrappers: Wrapper[]): number {
const addedWrappers: Wrapper[] = [];
for (const wrapper of wrappers) {
if (!this.inSelection(wrapper)) {
addedWrappers.push(wrapper);
......@@ -122,8 +123,8 @@ export class AnalysisService {
return addedWrappers.length;
}
public removeItems(wrappers: Node[]) {
const removedWrappers: Node[] = [];
public removeItems(wrappers: Wrapper[]) {
const removedWrappers: Wrapper[] = [];
for (const wrapper of wrappers) {
if (this.selectedItems.delete(wrapper.id)) {
removedWrappers.push(wrapper);
......@@ -133,7 +134,7 @@ export class AnalysisService {
}
public addSeeds(nodes) {
const addedWrappers: Node[] = [];
const addedWrappers: Wrapper[] = [];
nodes.forEach((node) => {
if (node.isSeed === true && !this.inSelection(node)) {
addedWrappers.push(node);
......@@ -144,7 +145,7 @@ export class AnalysisService {
}
public removeSeeds(nodes) {
const removedWrappers: Node[] = [];
const removedWrappers: Wrapper[] = [];
nodes.forEach((node) => {
if (node.isSeed === true && this.inSelection(node)) {
removedWrappers.push(node);
......@@ -215,11 +216,11 @@ export class AnalysisService {
return this.selectedItems.has(nodeId);
}
inSelection(wrapper: Node): boolean {
inSelection(wrapper: Wrapper): boolean {
return this.selectedItems.has(wrapper.id);
}
getSelection(): Node[] {
getSelection(): Wrapper[] {
return Array.from(this.selectedItems.values());
}
......@@ -227,7 +228,7 @@ export class AnalysisService {
return this.selectedItems.size;
}
subscribeList(cb: (items: Array<Node>, selected: boolean | null) => void) {
subscribeList(cb: (items: Array<Wrapper>, selected: boolean | null) => void) {
this.selectListSubject.subscribe((event) => {
cb(event.items, event.selected);
});
......@@ -253,14 +254,14 @@ export class AnalysisService {
algorithm: isSuper ? 'super' : 'quick',
target: 'drug',
parameters: {
strain_or_drugs: dataset.backendId,
strain_or_drugs: dataset.id,
bait_datasets: dataset.data,
seeds: isSuper ? [] : this.getSelection().map((i) => i.id),
},
}).toPromise();
this.tokens.push(resp.token);
localStorage.setItem('tokens', JSON.stringify(this.tokens));
// this.startWatching();
this.startWatching();
toast({
message: 'Quick analysis started. This may take a while.' +
......@@ -293,9 +294,10 @@ export class AnalysisService {
target,
parameters,
}).toPromise();
this.tokens.push(resp.token);
localStorage.setItem('tokens', JSON.stringify(this.tokens));
// this.startWatching();
this.startWatching();
}
public isLaunchingQuick(): boolean {
......
import { TestBed } from '@angular/core/testing';
import { NetexControllerService } from './netex-controller.service';
describe('NetexControllerService', () => {
let service: NetexControllerService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(NetexControllerService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import {environment} from '../../../environments/environment';
import {HttpClient, HttpParams} from '@angular/common/http';
import {AlgorithmType, QuickAlgorithmType} from '../analysis/analysis.service';
@Injectable({
providedIn: 'root'
})
export class NetexControllerService {
constructor(private http: HttpClient) { }
public async getTask(token): Promise<any> {
/**
* returns promise of task status
*/
return this.http.get(`${environment.backend}task/?tokens=${token}`).toPromise();
}
public async getTasks(tokens): Promise<any> {
/**
* returns promise of tasks status
*/
return this.http.post<any>(`${environment.backend}tasks/`, {tokens: JSON.stringify(tokens)}).toPromise();
}
public async getTaskResult(token): Promise<any> {
/**
* returns promise of task result of COMPLETED task
*/
return this.http.get<any>(`${environment.backend}task_result/?token=${token}`).toPromise();
}
public async getTaskResultDrug(token): Promise<any> {
/**
* returns promise of drug view of task result of COMPLETED task
*/
return this.http.get<any>(`${environment.backend}task_result/?token=${token}&view=drugs`).toPromise();
}
public async getTaskResultGene(token): Promise<any> {
/**
* returns promise of gene view of task result of COMPLETED task
*/
return this.http.get<any>(`${environment.backend}task_result/?token=${token}&view=genes`).toPromise();
}
public async getTaskResultCancerNode(token): Promise<any> {
/**
* returns promise of cancer driver gene view of task result of COMPLETED task
*/
return this.http.get<any>(`${environment.backend}task_result/?token=${token}&view=cancer_driver_genes`).toPromise();
}
public async postTask(algorithm: QuickAlgorithmType | AlgorithmType, target, parameters, ) {
/**
* sends a task to task service
*/
return this.http.post<any>(`${environment.backend}task/`, {
algorithm,
target,
parameters,
}).toPromise();
}
public async mapNodes(nodes, identifier): Promise<any> {
/**
* Tries to map every node to a node object in out database
* Returns list of mapped nodes if node was found, otherwise original node to not lose information
*/
const payload = {nodes: JSON.stringify(nodes), identifier: JSON.stringify(identifier)};
return this.http.post(`${environment.backend}map_nodes/`, payload).toPromise();
}
}
......@@ -4,7 +4,7 @@
export const environment = {
production: false,
backend: 'http://10.162.163.20/',
backend: 'http://10.162.163.20:8001/',
};
/*
......
......@@ -5,9 +5,10 @@
<title>Network Expander</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/ico" href="src/assets/covex_logo_small.png">
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
<script src="https://kit.fontawesome.com/3ad4fe992f.js" crossorigin="anonymous"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- <link rel="stylesheet" href="netex-build/styles.css">-->
<!-- <script type="text/javascript" src="netex-build/netex.js"></script>-->
......@@ -72,15 +73,13 @@
netexp.setAttribute('network', JSON.stringify({
nodes: [
{
name: "PTEN",
id: "1",
access: "A",
label: "PTEN",
id: "PTEN",
group: "genes"
},
{
name: "TP53",
id: "2",
access: "B",
label: "TP53",
id: "TP53",
group: "genes"
}
],
......
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