Skip to content

Commit

Permalink
Metabolic pathways visualisation (#731): pathway tree search
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitriiKrasnov committed Feb 1, 2022
1 parent 5c9f93d commit 5728069
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export default {
tag: '@',
onElementClick: '&',
storageName: '@',
elementsOptions: '<'
searchParams: '<'
},
controller: ngbCytoscapePathwayController
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ const sbgnStylesheet = require('cytoscape-sbgn-stylesheet');
const $ = require('jquery');

const SCALE = 0.3;
const searchedColor = '#00cc00';
let defaultNodeStyle = {};

export default class ngbCytoscapePathwayController {
constructor($element, $scope, $compile, $window, $timeout, dispatcher, cytoscapeSettings) {
Expand Down Expand Up @@ -57,6 +59,28 @@ export default class ngbCytoscapePathwayController {
(changes.elements.previousValue.id !== changes.elements.currentValue.id)) {
this.reloadCytoscape(true);
}
if (!!changes.searchParams &&
!!changes.searchParams.previousValue &&
!!changes.searchParams.currentValue) {
if (changes.searchParams.currentValue.search
&& changes.searchParams.previousValue.search !== changes.searchParams.currentValue.search) {
this.searchNode(
changes.searchParams.currentValue.search,
node => {
node.style({
'color': searchedColor,
'border-color': searchedColor
});
},
node => {
node.style({
'color': defaultNodeStyle.color,
'border-color': defaultNodeStyle['border-color']
});
}
);
}
}
}

reloadCytoscape(active) {
Expand All @@ -67,6 +91,10 @@ export default class ngbCytoscapePathwayController {
}
this.$timeout(() => {
const sbgnStyle = sbgnStylesheet(Cytoscape);
defaultNodeStyle = {
...this.settings.style.node,
...this.getNodeStyle(sbgnStyle)
};
const savedState = JSON.parse(localStorage.getItem(this.storageName) || '{}');
const savedLayout = savedState.layout ? savedState.layout[this.elements.id] : undefined;
let elements;
Expand Down Expand Up @@ -210,4 +238,50 @@ export default class ngbCytoscapePathwayController {
});
return nodes;
}

searchNode(term, onSatisfy, onDeny) {
if (!this.viewer) {
return;
}
const roots = this.viewer.nodes().roots();
this.viewer.nodes().dfs({
root: roots,
visit: node => {
if (this.deepSearch(node.data(), term)) {
onSatisfy(node);
} else {
onDeny(node);
}
}
});
}

deepSearch(obj, term) {
let result = false;
for (const key in obj) {
if (!obj.hasOwnProperty(key) || !obj[key]) continue;
if (obj[key] instanceof Object || obj[key] instanceof Array) {
result = this.deepSearch(obj[key], term);
} else {
result = obj[key].toString().toLocaleLowerCase()
.includes(term.toLocaleLowerCase());
}
if (result) {
return true;
}
}
return false;
}

getNodeStyle(style) {
const result = {};
Object.keys(style).forEach(key => {
if (style[key].selector === 'node') {
Object.keys(style[key].properties).forEach(propKey => {
result[style[key].properties[propKey].name] = style[key].properties[propKey].value;
});
}
});
return result;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
export default {
viewer: {},
style: {},
style: {
node: {
'text-opacity': 1,
'text-valign': 'center',
'text-halign': 'center',
'shape': 'rectangle',
'color': '#000',
'border-width': 1
}
},
defaultLayout: {
name: 'dagre',
rankDir: 'TB'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import baseController from '../../../shared/baseController';

export default class ngbInternalPathwaysResultController extends baseController {
selectedTree = null;
selectedTreeName = null;
treeSearchParams = {
search: null
};
treeSearch = null;
loading = true;
treeError = false;

Expand Down Expand Up @@ -61,6 +64,12 @@ export default class ngbInternalPathwaysResultController extends baseController
this.$timeout(() => this.$scope.$apply());
}

searchInTree() {
this.treeSearchParams = {
search: this.treeSearch
};
}

activePanelChanged(o) {
const isActive = o === this.appLayout.Panels.pathways.panel;
this.dispatcher.emit('cytoscape:panel:active', isActive);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
.tree-container {
position: relative;

.element-description-container {
.pathway-search-panel {
width: 50%;
max-width: 300px;
position: absolute;
Expand All @@ -51,70 +51,32 @@
padding: 10px;
box-shadow: 2px 2px 8px 2px #aaa;

.close {
cursor: pointer;
position: absolute;
top: 5px;
right: 5px;
fill: #777;
}

.close:hover {
fill: #333333;
}

.element-description-body {
.pathway-search-panel-body {
display: table;
padding-right: 16px;

.element-description-row {
.pathway-search-panel-row {
display: flex;
flex-wrap: wrap;
align-items: baseline;
border-spacing: 5px;
word-break: break-all;
padding: 5px 0;

.element-description-title {
margin-right: 5px;
}

.element-description-navigation {
font-weight: bold;
color: #2c4f9e;
text-decoration: underline;
cursor: pointer;
}

.sequenced {
font-size: smaller;
font-style: italic;
white-space: nowrap;
}
}

.element-description-attributes {
display: flex;
flex-direction: column;
align-items: flex-start;

.element-description-attribute {
margin: 2px 0;
padding: 2px 4px;
background: #f9f9f9;
border: 1px solid #e9e9e9;
border-radius: 3px;
font-size: smaller;
text-transform: uppercase;
}
.pathway-tree-search-input {
font-size: 14px;
margin: 5px 0 10px 6px;
}

.element-description-row:not(:last-child) {
border-bottom: 1px solid #eee;
.pathway-tree-search-input .md-errors-spacer {
min-height: 0;
}

.element-description-empty {
color: #999;
.pathway-tree-search-button {
line-height: 32px;
min-height: 32px;
height: 32px;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,25 @@
<span class="blast-search-result-title">{{$ctrl.selectedTree.name}}</span>
</div>
<div class="u-height__full tree-container" flex layout="column">
<div class="pathway-search-panel">
<div class="md-content">
<div class="pathway-search-panel-body" layout="column">
<div class="pathway-search-panel-row">
<form layout="row" ng-submit="$ctrl.searchInTree()">
<md-input-container class="pathway-tree-search-input" flex>
<input id="pathwayTreeSearchKeyword" name="pathway_tree_search_keyword"
ng-model="$ctrl.treeSearch" type="text">
</md-input-container>
<md-button aria-label="search node"
class="md-raised pathway-tree-search-button"
ng-click="$ctrl.searchInTree()">
<ng-md-icon icon="search"></ng-md-icon>
</md-button>
</form>
</div>
</div>
</div>
</div>
<md-content flex layout="column">
<div class="md-padding ngb-pathway-cytoscape-container">
<div class="internal-pathway-container-error" ng-if="$ctrl.treeError">
Expand All @@ -26,6 +45,7 @@
ng-if="!$ctrl.treeError"
storage-name="{{$ctrl.ngbInternalPathwaysResultService.localStorageKey}}"
tag="ngb-internal-pathway-node"
search-params="$ctrl.treeSearchParams"
></ngb-cytoscape-pathway>
</div>
</md-content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ export default class ngbInternalPathwaysTableService extends ClientPaginationSer
pageSize: this.pageSize,
pageNum: this.currentPage
},
sortInfos: this.orderBy
sortInfos: this.orderBy,
term: currentSearch
};
const data = await this.genomeDataService.getInternalPathwaysLoad(filter);
if (data.error) {
Expand Down

0 comments on commit 5728069

Please sign in to comment.