diff --git a/src/app/analysis.service.ts b/src/app/analysis.service.ts index aaf632bd7b32d92b3a99b5a843731a70e6411f36..7b274f49907765d1f5a82dafd5e4cdd28c20b77e 100644 --- a/src/app/analysis.service.ts +++ b/src/app/analysis.service.ts @@ -36,9 +36,13 @@ export const MAX_TASKS = 3; }) export class AnalysisService { + private selection = 'main'; + private selectedItems = new Map<string, Wrapper>(); private selectListSubject = new Subject<{ items: Wrapper[], selected: boolean | null }>(); + private selections = new Map<string, Map<string, Wrapper>>(); + public tokens: string[] = []; public finishedTokens: string[] = []; public tasks: Task[] = []; @@ -52,7 +56,6 @@ export class AnalysisService { const tokens = localStorage.getItem('tokens'); const finishedTokens = localStorage.getItem('finishedTokens'); - if (tokens) { this.tokens = JSON.parse(tokens); } @@ -82,6 +85,17 @@ export class AnalysisService { }); } + public switchSelection(id: string) { + this.selections.set(this.selection, this.selectedItems); + if (this.selections.has(id)) { + this.selectedItems = this.selections.get(id); + } else { + this.selectedItems = new Map<string, Wrapper>(); + } + this.selectListSubject.next({items: Array.from(this.selectedItems.values()), selected: null}); + this.selection = id; + } + public addItems(wrappers: Wrapper[]): number { const addedWrappers: Wrapper[] = []; for (const wrapper of wrappers) { @@ -104,6 +118,47 @@ export class AnalysisService { this.selectListSubject.next({items: removedWrappers, selected: false}); } + public addSeeds(nodes) { + const addedWrappers: Wrapper[] = []; + nodes.forEach((node) => { + const wrapper: Wrapper = node.wrapper; + if (node.isSeed === true && !this.inSelection(wrapper)) { + addedWrappers.push(wrapper); + this.selectedItems.set(wrapper.nodeId, wrapper); + } + }); + this.selectListSubject.next({items: addedWrappers, selected: true}); + } + + public removeSeeds(nodes) { + const removedWrappers: Wrapper[] = []; + nodes.forEach((node) => { + const wrapper: Wrapper = node.wrapper; + if (node.isSeed === true && this.inSelection(wrapper)) { + removedWrappers.push(wrapper); + this.selectedItems.delete(wrapper.nodeId); + } + }); + this.selectListSubject.next({items: removedWrappers, selected: false}); + } + + public invertSelection(nodes) { + const newSelection = []; + nodes.forEach((node) => { + const wrapper: Wrapper = node.wrapper; + if (wrapper.type === 'host' || wrapper.type === 'virus') { + if (!this.inSelection(wrapper)) { + newSelection.push(wrapper); + } + } + }); + this.selectedItems.clear(); + for (const wrapper of newSelection) { + this.selectedItems.set(wrapper.nodeId, wrapper); + } + this.selectListSubject.next({items: newSelection, selected: null}); + } + public addVisibleHostProteins(nodes, proteins): number { const items: Wrapper[] = []; const visibleIds = new Set<string>(nodes.getIds()); @@ -151,8 +206,8 @@ export class AnalysisService { } resetSelection() { - this.selectListSubject.next({items: [], selected: null}); this.selectedItems.clear(); + this.selectListSubject.next({items: [], selected: null}); } idInSelection(nodeId: string): boolean { diff --git a/src/app/app.component.html b/src/app/app.component.html index 1197c795f5d8ff1ea8c4f7ce382b28f82354049b..0b629bc97d450992e426898145d6ff620da96d11 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -28,7 +28,7 @@ <div class="navbar-item"> <div class="field is-grouped"> <p class="control"> - Version 1.0 + Version 1.1 </p> </div> </div> diff --git a/src/app/components/analysis-panel/analysis-panel.component.html b/src/app/components/analysis-panel/analysis-panel.component.html index 02cf7ec80e0f2f551e4f8e0ad57a1569fc57c90e..590ae7ca3b762912922917d3acbba848b438b9c4 100644 --- a/src/app/components/analysis-panel/analysis-panel.component.html +++ b/src/app/components/analysis-panel/analysis-panel.component.html @@ -93,19 +93,19 @@ </tr> <tr> <td>Tolerance</td> - <td>10</td> + <td>0</td> + </tr> + <tr> + <td>Hub Penality</td> + <td>1</td> </tr> </tbody> </table> <p> - Algorithm: <strong>{{algorithmNames['trustrank']}}</strong> + Algorithm: <strong>{{algorithmNames['closeness']}}</strong> </p> <table class="table is-narrow"> <tbody> - <tr> - <td>Damping Factor</td> - <td>0.85</td> - </tr> <tr> <td>Include indirect drugs</td> <td> @@ -115,12 +115,16 @@ <tr> <td>Include non-approved drugs</td> <td> - <i class="fa fa-times"></i> + <i class="fa fa-check"></i> </td> </tr> + <tr> + <td>Hub Penality</td> + <td>1</td> + </tr> <tr> <td>Result Size</td> - <td>30</td> + <td>10</td> </tr> </tbody> </table> @@ -228,17 +232,28 @@ <p-sortIcon [field]="'name'"></p-sortIcon> </th> <th [pSortableColumn]="'status'"> - Status + Approved <p-sortIcon [field]="'status'"></p-sortIcon> </th> <th [pSortableColumn]="'inTrial'"> - Trial + In Trial <p-sortIcon [field]="'inTrial'"></p-sortIcon> </th> + <th [pSortableColumn]="'inLiterature'"> + In Literature + <p-sortIcon [field]="'inLiterature'"></p-sortIcon> + </th> <th *ngIf="tableHasScores" [pSortableColumn]="'score'"> Score <p-sortIcon [field]="'score'"></p-sortIcon> </th> + <th> + Closest viral proteins + </th> + <th [pSortableColumn]="'closestDistance'"> + Viral protein distance + <p-sortIcon [field]="'closestDistance'"></p-sortIcon> + </th> </tr> </ng-template> <ng-template pTemplate="body" let-e> @@ -248,20 +263,37 @@ <td> <span *ngIf="e.status === 'approved'"> <i class="fa fa-check"></i> - approved + Approved </span> <span *ngIf="e.status === 'unapproved'"> <i class="fa fa-times"></i> - not approved </span> </td> <td> <span *ngIf="e.inTrial"> <i class="fa fa-microscope has-text-primary"></i> - in Trial + Trial + </span> + <span *ngIf="!e.inTrial"> + <i class="fa fa-times"></i> + </span> + </td> + <td> + <span *ngIf="e.inLiterature"> + <i class="fa fa-book has-text-primary"></i> + Literature + </span> + <span *ngIf="!e.inLiterature"> + <i class="fa fa-times"></i> </span> </td> <td *ngIf="tableHasScores">{{e.score | number}}</td> + <td title="{{previewStringArray(e.closestViralProteins, 100)}}"> + {{previewStringArray(e.closestViralProteins, 3)}} + </td> + <td> + {{e.closestDistance}} + </td> </tr> </ng-template> </p-table> @@ -292,10 +324,25 @@ Gene <p-sortIcon [field]="'name'"></p-sortIcon> </th> + <th [pSortableColumn]="'proteinName'"> + Name + <p-sortIcon [field]="'proteinName'"></p-sortIcon> + </th> <th *ngIf="tableHasScores" [pSortableColumn]="'score'"> Score <p-sortIcon [field]="'score'"></p-sortIcon> </th> + <th [pSortableColumn]="'isSeed'"> + Seed + <p-sortIcon [field]="'isSeed'"></p-sortIcon> + </th> + <th> + Closest viral proteins + </th> + <th [pSortableColumn]="'closestDistance'"> + Closest distance + <p-sortIcon [field]="'closestDistance'"></p-sortIcon> + </th> </tr> </ng-template> <ng-template pTemplate="body" let-e> @@ -305,7 +352,23 @@ </td> <td><a href="https://www.uniprot.org/uniprot/{{ e.proteinAc }}" target="_blank">{{ e.proteinAc }}</a></td> <td>{{e.name}}</td> + <td>{{e.proteinName}}</td> <td *ngIf="tableHasScores">{{e.score | number}}</td> + <td> + <span *ngIf="e.isSeed"> + <i class="fa fa-check"></i> + Seed + </span> + <span *ngIf="!e.isSeed"> + <i class="fa fa-times"></i> + </span> + </td> + <td title="{{previewStringArray(e.closestViralProteins, 100)}}"> + {{previewStringArray(e.closestViralProteins, 3)}} + </td> + <td> + {{e.closestDistance}} + </td> </tr> </ng-template> </p-table> @@ -340,6 +403,10 @@ Score <p-sortIcon [field]="'score'"></p-sortIcon> </th> + <th [pSortableColumn]="'isSeed'"> + Seed + <p-sortIcon [field]="'isSeed'"></p-sortIcon> + </th> </tr> </ng-template> <ng-template pTemplate="body" let-e> @@ -350,6 +417,15 @@ <td>{{e.effectName}}</td> <td>{{e.virusName}}</td> <td *ngIf="tableHasScores">{{e.score | number}}</td> + <td> + <span *ngIf="e.isSeed"> + <i class="fa fa-asterisk has-text-primary"></i> + Seed + </span> + <span *ngIf="!e.isSeed"> + <i class="fa fa-times"></i> + </span> + </td> </tr> </ng-template> </p-table> diff --git a/src/app/components/analysis-panel/analysis-panel.component.ts b/src/app/components/analysis-panel/analysis-panel.component.ts index c50a8e8a02a6b66ef55846d652cd4febac90d078..aea6445261e2252511dcdf795b4d77be86b12931 100644 --- a/src/app/components/analysis-panel/analysis-panel.component.ts +++ b/src/app/components/analysis-panel/analysis-panel.component.ts @@ -38,6 +38,15 @@ interface Scored { rawScore: number; // Unnormalized (kept to restore unnormalized value) } +interface Seeded { + isSeed: boolean; +} + +interface Baited { + closestViralProteins: string[]; + closestDistance: number; +} + @Component({ selector: 'app-analysis-panel', templateUrl: './analysis-panel.component.html', @@ -66,11 +75,11 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { private proteins: any; public effects: any; - public tableDrugs: Array<Drug & Scored> = []; - public tableProteins: Array<Protein & Scored> = []; - public tableSelectedProteins: Array<Protein & Scored> = []; - public tableViralProteins: Array<ViralProtein & Scored> = []; - public tableSelectedViralProteins: Array<ViralProtein & Scored> = []; + public tableDrugs: Array<Drug & Scored & Baited> = []; + public tableProteins: Array<Protein & Scored & Seeded & Baited> = []; + public tableSelectedProteins: Array<Protein & Scored & Seeded & Baited> = []; + public tableViralProteins: Array<ViralProtein & Scored & Seeded> = []; + public tableSelectedViralProteins: Array<ViralProtein & Scored & Seeded> = []; public tableNormalize = false; public tableHasScores = false; @@ -89,9 +98,12 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { private async refresh() { if (this.token) { this.task = await this.getTask(this.token); + this.analysis.switchSelection(this.token); if (this.task && this.task.info.done) { const result = await this.http.get<any>(`${environment.backend}task_result/?token=${this.token}`).toPromise(); + const nodeAttributes = result.nodeAttributes || {}; + const isSeed: {[key: string]: boolean} = nodeAttributes.isSeed || {}; // Reset this.nodeData = {nodes: null, edges: null}; @@ -112,12 +124,22 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { 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=drugs`).toPromise() + .then((table) => { + 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() .then((table) => { this.tableProteins = table; this.tableSelectedProteins = []; this.tableProteins.forEach((r) => { r.rawScore = r.score; + r.isSeed = isSeed[r.proteinAc]; + r.closestViralProteins = (r.closestViralProteins as any).split(','); if (this.analysis.proteinInSelection(r)) { this.tableSelectedProteins.push(r); } @@ -126,12 +148,10 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { 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); + this.tableViralProteins.forEach((r) => { + r.rawScore = r.score; + r.isSeed = isSeed[r.effectId]; + }); })); await Promise.all(promises); @@ -221,10 +241,8 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { const updatedNodes = []; this.nodeData.nodes.forEach((node) => { const nodeSelected = this.analysis.idInSelection(node.id); - if (selected !== nodeSelected) { - Object.assign(node, NetworkSettings.getNodeStyle(node.wrapper.type, node.isSeed, selected)); - updatedNodes.push(node); - } + Object.assign(node, NetworkSettings.getNodeStyle(node.wrapper.type, node.isSeed, nodeSelected)); + updatedNodes.push(node); }); this.nodeData.nodes.update(updatedNodes); @@ -266,6 +284,7 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { } close() { + this.analysis.switchSelection('main'); this.token = null; this.tokenChange.emit(this.token); this.emitVisibleItems(false); @@ -541,4 +560,13 @@ export class AnalysisPanelComponent implements OnInit, OnChanges { this.analysis.removeItems(removeItems); } + public previewStringArray(arr: string[], count: number): string { + if (arr.length < count) { + return arr.join(', '); + } else { + return arr.slice(0, count).join(', ') + `, ... (${arr.length})`; + } + } } + + diff --git a/src/app/components/info-tile/info-tile.component.html b/src/app/components/info-tile/info-tile.component.html index 743e71785ba6f4e38881bd264331dee29ea6b419..bc3986c80da16cfa86dee0e9f7899b93636c8a3d 100644 --- a/src/app/components/info-tile/info-tile.component.html +++ b/src/app/components/info-tile/info-tile.component.html @@ -11,6 +11,10 @@ {{ wrapper.data.proteinAc }} </a> </p> + <p> + <b><span>Name: </span></b> + {{ wrapper.data.proteinName }} + </p> </div> <div *ngIf="wrapper.type === 'virus'"> <p> diff --git a/src/app/dialogs/launch-analysis/launch-analysis.component.html b/src/app/dialogs/launch-analysis/launch-analysis.component.html index e9a0ed4f002fb4102648d94d3deb78bd15adc5b7..3096d581541ddd4bf3503d941d7d5e0f99732937 100644 --- a/src/app/dialogs/launch-analysis/launch-analysis.component.html +++ b/src/app/dialogs/launch-analysis/launch-analysis.component.html @@ -82,7 +82,7 @@ placeholder="Maximum degree" min="0" max="1" required> </div> <p class="help"> - All nodes with degree greater than this value times number of vertices will be ignored. + All nodes with degree greater than this value times number of vertices will be ignored. Disabled if equal to 0. </p> </div> @@ -162,7 +162,7 @@ placeholder="Maximum degree" min="0" max="1" required> </div> <p class="help"> - All nodes with degree greater than this value times number of vertices will be ignored. + All nodes with degree greater than this value times number of vertices will be ignored. Disabled if equal to 0. </p> </div> @@ -229,7 +229,7 @@ placeholder="Maximum degree" min="0" max="1" required> </div> <p class="help"> - All nodes with degree greater than this value times number of vertices will be ignored. + All nodes with degree greater than this value times number of vertices will be ignored. Disabled if equal to 0. </p> </div> @@ -273,18 +273,27 @@ </div> <div class="field"> - <label class="label" for="keypathwayminer-k">K</label> + <label class="label" for="keypathwayminer-k">Additional proteins</label> <div class="control"> <div class="select"> <select id="keypathwayminer-k" [(ngModel)]="keypathwayminerK"> <option [ngValue]="1">1</option> <option [ngValue]="2">2</option> <option [ngValue]="3">3</option> - <option [ngValue]="4">4</option> <option [ngValue]="5">5</option> + <option [ngValue]="10">10</option> + <option [ngValue]="15">15</option> + <option [ngValue]="20">20</option> + <option [ngValue]="25">25</option> + <option [ngValue]="30">30</option> + <option [ngValue]="40">40</option> + <option [ngValue]="50">50</option> </select> </div> </div> + <p class="help"> + Number of new proteins to be found. + </p> </div> <div class="box"> @@ -352,7 +361,7 @@ placeholder="Maximum degree" min="0" max="1" required> </div> <p class="help"> - All nodes with degree greater than this value times number of vertices will be ignored. + All nodes with degree greater than this value times number of vertices will be ignored. Disabled if equal to 0. </p> </div> diff --git a/src/app/dialogs/launch-analysis/launch-analysis.component.ts b/src/app/dialogs/launch-analysis/launch-analysis.component.ts index 3dfb9de948b6f1da77f7c40d39ab6a60e494e2e8..83e9c35c1169d5c82e95fa56cec19272b7e5fb57 100644 --- a/src/app/dialogs/launch-analysis/launch-analysis.component.ts +++ b/src/app/dialogs/launch-analysis/launch-analysis.component.ts @@ -9,6 +9,7 @@ import { QuickAlgorithmType, TRUSTRANK } from '../../analysis.service'; +import {Dataset} from '../../interfaces'; @Component({ selector: 'app-launch-analysis', @@ -22,7 +23,7 @@ export class LaunchAnalysisComponent implements OnInit, OnChanges { @Input() public target: 'drug' | 'drug-target'; @Input() - public dataset; + public dataset: Dataset; @Output() public showChange = new EventEmitter<boolean>(); @@ -35,7 +36,7 @@ export class LaunchAnalysisComponent implements OnInit, OnChanges { public trustrankIncludeNonApprovedDrugs = false; public trustrankIncludeViralNonSeeds = true; public trustrankDampingFactor = 0.85; - public trustrankMaxDeg = 1.0; + public trustrankMaxDeg = 0; public trustrankHubPenalty = 0.0; public trustrankResultSize = 20; @@ -43,24 +44,24 @@ export class LaunchAnalysisComponent implements OnInit, OnChanges { public closenessIncludeIndirectDrugs = false; public closenessIncludeNonApprovedDrugs = false; public closenessIncludeViralNonSeeds = true; - public closenessMaxDeg = 1.0; + public closenessMaxDeg = 0; public closenessHubPenalty = 0.0; public closenessResultSize = 20; // Degree Parameters public degreeIncludeNonApprovedDrugs = false; public degreeIncludeViralNonSeeds = true; - public degreeMaxDeg = 1.0; + public degreeMaxDeg = 0; public degreeResultSize = 20; // Keypathwayminer Parameters - public keypathwayminerK = 1; + public keypathwayminerK = 5; // Multisteiner Parameters public multisteinerNumTrees = 5; public multisteinerTolerance = 10; public multisteinerIncludeViralNonSeeds = true; - public multisteinerMaxDeg = 1.0; + public multisteinerMaxDeg = 0; public multisteinerHubPenalty = 0.0; public hasBaits; @@ -97,37 +98,44 @@ export class LaunchAnalysisComponent implements OnInit, OnChanges { seeds: this.analysis.getSelection().map((item) => item.backendId), }; + parameters.strain_or_drugs = this.target === 'drug' ? 'drugs' : this.dataset.backendId; + parameters.bait_datasets = this.dataset.data; + if (this.algorithm === 'trustrank') { - parameters.strain_or_drugs = this.target === 'drug' ? 'drugs' : this.dataset; parameters.damping_factor = this.trustrankDampingFactor; parameters.include_indirect_drugs = this.trustrankIncludeIndirectDrugs; parameters.include_non_approved_drugs = this.trustrankIncludeNonApprovedDrugs; parameters.ignore_non_seed_baits = !this.trustrankIncludeViralNonSeeds; - parameters.max_deg = this.trustrankMaxDeg; + if (this.trustrankMaxDeg && this.trustrankMaxDeg > 0) { + parameters.max_deg = this.trustrankMaxDeg; + } parameters.hub_penalty = this.trustrankHubPenalty; parameters.result_size = this.trustrankResultSize; } else if (this.algorithm === 'closeness') { - parameters.strain_or_drugs = this.target === 'drug' ? 'drugs' : this.dataset; parameters.include_indirect_drugs = this.closenessIncludeIndirectDrugs; parameters.include_non_approved_drugs = this.closenessIncludeNonApprovedDrugs; parameters.ignore_non_seed_baits = !this.closenessIncludeViralNonSeeds; - parameters.max_deg = this.closenessMaxDeg; + if (this.closenessMaxDeg && this.closenessMaxDeg > 0) { + parameters.max_deg = this.closenessMaxDeg; + } parameters.hub_penalty = this.closenessHubPenalty; parameters.result_size = this.closenessResultSize; } else if (this.algorithm === 'degree') { - parameters.strain_or_drugs = this.target === 'drug' ? 'drugs' : this.dataset; parameters.include_non_approved_drugs = this.degreeIncludeNonApprovedDrugs; parameters.ignore_non_seed_baits = !this.degreeIncludeViralNonSeeds; - parameters.max_deg = this.degreeMaxDeg; + if (this.degreeMaxDeg && this.degreeMaxDeg > 0) { + parameters.max_deg = this.degreeMaxDeg; + } parameters.result_size = this.degreeResultSize; } else if (this.algorithm === 'keypathwayminer') { parameters.k = this.keypathwayminerK; } else if (this.algorithm === 'multisteiner') { - parameters.strain_or_drugs = this.dataset; parameters.num_trees = this.multisteinerNumTrees; parameters.tolerance = this.multisteinerTolerance; parameters.ignore_non_seed_baits = !this.multisteinerIncludeViralNonSeeds; - parameters.max_deg = this.multisteinerMaxDeg; + if (this.multisteinerMaxDeg && this.multisteinerMaxDeg > 0) { + parameters.max_deg = this.multisteinerMaxDeg; + } parameters.hub_penalty = this.multisteinerHubPenalty; } diff --git a/src/app/interfaces.ts b/src/app/interfaces.ts index f2448d717b1e03279199f3f5c8c7ce05b694603d..77e8b841f76b87f7955008e34ca5850cd866e18b 100644 --- a/src/app/interfaces.ts +++ b/src/app/interfaces.ts @@ -1,10 +1,9 @@ import {AlgorithmType, QuickAlgorithmType} from './analysis.service'; -export type NodeType = 'host' | 'virus' | 'drug'; - export interface Protein { name: string; proteinAc: string; + proteinName: string; effects?: ViralProtein[]; x?: number; y?: number; @@ -132,22 +131,10 @@ export function getWrapperFromDrug(drug: Drug): Wrapper { export type WrapperType = 'host' | 'virus' | 'drug'; -export function getTypeFromNodeId(nodeId: string): WrapperType { - if (nodeId.startsWith('p_')) { - return 'host'; - } - if (nodeId.startsWith('v_')) { - return 'virus'; - } - if (nodeId.startsWith('d_')) { - return 'drug'; - } -} - export interface Wrapper { backendId: string; nodeId: string; - type: 'host' | 'virus' | 'drug'; + type: WrapperType; data: any; } @@ -156,6 +143,7 @@ export interface Drug { name: string; status: 'approved' | 'investigational'; inTrial: boolean; + inLiterature: boolean; } export interface Dataset { diff --git a/src/app/pages/explorer-page/explorer-page.component.html b/src/app/pages/explorer-page/explorer-page.component.html index be655e2aa1b2ce1c366b286d4fc6fa75d448c7d9..83d9bae024020c1993275743f7a8835bf0ace660 100644 --- a/src/app/pages/explorer-page/explorer-page.component.html +++ b/src/app/pages/explorer-page/explorer-page.component.html @@ -1,7 +1,7 @@ <div class="is-hidden-mobile"> <app-launch-analysis [(show)]="showAnalysisDialog" [target]="analysisDialogTarget" - [dataset]="selectedDataset.backendId"> + [dataset]="selectedDataset"> </app-launch-analysis> <app-custom-proteins [(show)]="showCustomProteinsDialog" [visibleNodes]="currentViewNodes"> @@ -133,7 +133,7 @@ <footer class="card-footer"> <a (click)="reset($event);" class="card-footer-item has-text-danger" data-tooltip="Remove filter and show all proteins."> <span class="icon"> - <i class="fa fa-refresh"></i> + <i class="fa fa-broom"></i> </span> <span> Reset @@ -313,12 +313,12 @@ class="button is-primary is-fullwidth is-rounded has-tooltip" data-tooltip="Find drug targets for the selected proteins." [disabled]="analysis.getCount() === 0"> - <span class="icon"> - <i class="fa fa-crosshairs"></i> - </span> + <span class="icon"> + <i class="fa fa-crosshairs"></i> + </span> <span> - Find Drug Targets - </span> + Find Drug Targets + </span> </button> </div> </div> @@ -328,15 +328,39 @@ class="button is-primary is-fullwidth is-rounded has-tooltip" data-tooltip="Find drugs for the selected proteins." [disabled]="analysis.getCount() === 0"> - <span class="icon"> - <i class="fa fa-capsules"></i> - </span> + <span class="icon"> + <i class="fa fa-capsules"></i> + </span> <span> - Find Drugs - </span> + Find Drugs + </span> </button> </div> </div> + <div class="field"> + <div class="control"> + <a *ngIf="analysis.getCount() > 0" [href]="gProfilerLink()" target="_blank" + class="button is-primary is-fullwidth is-rounded has-tooltip" + data-tooltip="Use enrichment analysis via g:Profiler (external)."> + <span class="icon"> + <i class="fa fa-external-link-alt"></i> + </span> + <span> + Enrichment Analysis + </span> + </a> + <a *ngIf="analysis.getCount() === 0" disabled + class="button is-primary is-fullwidth is-rounded has-tooltip" + data-tooltip="Use enrichment analysis via g:Profiler (external)."> + <span class="icon"> + <i class="fa fa-external-link-alt"></i> + </span> + <span> + Enrichment Analysis + </span> + </a> + </div> + </div> </div> </div> </div> @@ -368,7 +392,7 @@ <i class="fa fa-trash"></i> </span> <span> - Delete All + Delete all </span> </a> </footer> @@ -423,34 +447,36 @@ Double-click on a protein to select it for the analysis. </i> </div> + <footer class="card-footer"> <a (click)="analysis.addVisibleHostProteins(currentViewNodes, currentViewProteins)" class="card-footer-item has-text-success" data-tooltip="Add all visible host proteins."> <span class="icon"> - <i class="fa fa-eye"></i> + <i class="fa fa-plus"></i> </span> <span> - Host Proteins + Add host proteins </span> </a> - <a (click)="analysis.addVisibleViralProteins(currentViewNodes, currentViewViralProteins)" - class="card-footer-item has-text-success" data-tooltip="Add all visible viral proteins."> + <a (click)="analysis.removeAllHostProteins()" + class="card-footer-item has-text-danger" data-tooltip="Remove all host proteins."> <span class="icon"> - <i class="fa fa-eye"></i> + <i class="fa fa-minus"></i> </span> <span> - Viral Proteins + Remove host proteins </span> </a> </footer> + <footer class="card-footer"> - <a (click)="analysis.removeAllHostProteins()" - class="card-footer-item has-text-danger" data-tooltip="Remove all host proteins."> + <a (click)="analysis.addVisibleViralProteins(currentViewNodes, currentViewViralProteins)" + class="card-footer-item has-text-success" data-tooltip="Add all visible viral proteins."> <span class="icon"> - <i class="fa fa-minus"></i> + <i class="fa fa-plus"></i> </span> <span> - Host Proteins + Add viral proteins </span> </a> <a (click)="analysis.removeAllViralProteins()" @@ -459,10 +485,32 @@ <i class="fa fa-minus"></i> </span> <span> - Viral Proteins + Remove viral proteins </span> </a> </footer> + + <footer class="card-footer" *ngIf="selectedAnalysisToken"> + <a (click)="analysis.addSeeds(currentViewNodes)" + class="card-footer-item has-text-success" data-tooltip="Add all visible seeds."> + <span class="icon"> + <i class="fa fa-plus"></i> + </span> + <span> + Add seeds + </span> + </a> + <a (click)="analysis.removeSeeds(currentViewNodes)" + class="card-footer-item has-text-danger" data-tooltip="Remove all seeds."> + <span class="icon"> + <i class="fa fa-minus"></i> + </span> + <span> + Remove seeds + </span> + </a> + </footer> + <footer class="card-footer"> <a (click)="showCustomProteinsDialog = true" class="card-footer-item has-text-primary" data-tooltip="Add a custom list of proteins."> @@ -470,21 +518,32 @@ <i class="fa fa-upload"></i> </span> <span> - Custom Proteins + Custom proteins </span> </a> </footer> + <footer class="card-footer"> + <a (click)="analysis.invertSelection(currentViewNodes)" class="card-footer-item has-text-primary" + data-tooltip="Invert the current selection."> + <span class="icon"> + <i class="fa fa-sync"></i> + </span> + <span> + Invert + </span> + </a> <a (click)="analysis.resetSelection()" class="card-footer-item has-text-danger" - data-tooltip="Remove all entries of the selection."> + data-tooltip="Remove all entries from the selection."> <span class="icon"> - <i class="fa fa-refresh"></i> + <i class="fa fa-broom"></i> </span> <span> Reset </span> </a> </footer> + </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 a92060ae1ce055aef23be9a9885816401301723b..f76477839398fa60bfb5b2c4cfe1cea2bc928219 100644 --- a/src/app/pages/explorer-page/explorer-page.component.ts +++ b/src/app/pages/explorer-page/explorer-page.component.ts @@ -141,10 +141,8 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { const updatedNodes = []; this.nodeData.nodes.forEach((node) => { const nodeSelected = this.analysis.idInSelection(node.id); - if (selected !== nodeSelected) { - Object.assign(node, NetworkSettings.getNodeStyle(node.wrapper.type, true, selected)); - updatedNodes.push(node); - } + Object.assign(node, NetworkSettings.getNodeStyle(node.wrapper.type, true, nodeSelected)); + updatedNodes.push(node); }); this.nodeData.nodes.update(updatedNodes); } @@ -466,4 +464,26 @@ export class ExplorerPageComponent implements OnInit, AfterViewInit { this.currentViewViralProteins = this.effects; } } + + gProfilerLink(): string { + const queryString = this.analysis.getSelection() + .filter(wrapper => wrapper.type === 'host') + .map(wrapper => wrapper.data.proteinAc) + .join('%0A'); + return 'http://biit.cs.ut.ee/gprofiler/gost?' + + 'organism=hsapiens&' + + `query=${queryString}&` + + 'ordered=false&' + + 'all_results=false&' + + 'no_iea=false&' + + 'combined=false&' + + 'measure_underrepresentation=false&' + + 'domain_scope=annotated&' + + 'significance_threshold_method=g_SCS&' + + 'user_threshold=0.05&' + + 'numeric_namespace=ENTREZGENE_ACC&' + + 'sources=GO:MF,GO:CC,GO:BP,KEGG,TF,REAC,MIRNA,HPA,CORUM,HP,WP&' + + 'background='; + } + } diff --git a/src/app/pages/home-page/home-page.component.html b/src/app/pages/home-page/home-page.component.html index a9661338f8de01fbff22d1641942b7fb9d2359dc..32eadb29e2a2be65a8ce8aea81cd435925462b3b 100644 --- a/src/app/pages/home-page/home-page.component.html +++ b/src/app/pages/home-page/home-page.component.html @@ -3,7 +3,7 @@ <div class="container has-text-centered"> <div class="column"> <div class="logo-box is-hidden-mobile"> - <img src="assets/covex_logo.png" style="height: 200px; width: 600px"> + <img src="assets/covex_logo.png" style="height: 233px; width: 600px"> </div> <div class="has-text-centered video-box"> diff --git a/src/app/pages/home-page/home-page.component.scss b/src/app/pages/home-page/home-page.component.scss index b3d5ed64d5fad618213b3ca0dd6ff6f571976d9a..27f2eb600561869c396767ac3809d433db1e1f39 100644 --- a/src/app/pages/home-page/home-page.component.scss +++ b/src/app/pages/home-page/home-page.component.scss @@ -1,6 +1,4 @@ img { - width: 600px; - height: 200px; padding: 30px; background-color: rgba(255, 255, 255, 0.7); border-radius: 25px; diff --git a/src/assets/covex_logo.jpg b/src/assets/covex_logo.jpg deleted file mode 100644 index cb3c06274b7173d8752b4ea508a7c1a826b39de7..0000000000000000000000000000000000000000 Binary files a/src/assets/covex_logo.jpg and /dev/null differ diff --git a/src/assets/covex_logo.png b/src/assets/covex_logo.png index ff01400851865ccb47bec645a3cc22895377ffed..da0a57d1171e27eee1d8693d3ad6fa8eebd2068b 100644 Binary files a/src/assets/covex_logo.png and b/src/assets/covex_logo.png differ diff --git a/src/assets/covex_logo_small.png b/src/assets/covex_logo_small.png index d380da83d80039adc43e5d19b9ec06220b93e932..16bac8bbd786aabfaeeb69c05dd4d62b71ee3842 100644 Binary files a/src/assets/covex_logo_small.png and b/src/assets/covex_logo_small.png differ diff --git a/src/styles.scss b/src/styles.scss index 4ff262d2e2c44ec2f8ce2d8f50644825a27816a0..34a3572101b1c3c344ae95dbd90befdfc155473f 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -31,12 +31,9 @@ nav.navbar { } img.menu-icon.is-hoverable.navbar-item.logo { - height: 45px; + height: 40px; width: 125px; - padding-top: 5px; - padding-bottom: 10px; - padding-left: 0px; - padding-right: 0px; + padding: 0; } .landing {