Skip to content

Commit f3f600c

Browse files
committed
Allow individual toggling of kinase-substrate relationship links
1 parent 6dfa43d commit f3f600c

File tree

2 files changed

+216
-52
lines changed

2 files changed

+216
-52
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "Webcomponent biowc-pathwaygraph following open-wc recommendations",
44
"license": "Apache-2.0",
55
"author": "biowc-pathwaygraph",
6-
"version": "0.1.1",
6+
"version": "0.1.2",
77
"main": "dist/src/index.js",
88
"module": "dist/src/index.js",
99
"exports": {

src/BiowcPathwaygraph.ts

Lines changed: 215 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
import {
1313
CommandBase,
1414
ContextMenu,
15+
EnabledOptions,
1516
ExecuteOptions,
1617
} from '@api-client/context-menu';
1718
import { ContextMenuCommand, Point } from '@api-client/context-menu/src/types';
@@ -293,7 +294,7 @@ export class BiowcPathwaygraph extends LitElement {
293294

294295
allPtmNodeLabelsVisible: boolean = false;
295296

296-
kinaseSubstrateLinksVisible: boolean = false;
297+
allKinaseSubstrateLinksVisible: boolean = false;
297298

298299
perturbedNodesVisible: boolean = false;
299300

@@ -309,6 +310,10 @@ export class BiowcPathwaygraph extends LitElement {
309310
...['rect.node-rect.pathway', 'rect.node-rect.compound'],
310311
];
311312

313+
static ptmNodes: string[] = [
314+
...this.regulation_strings.map(s1 => `rect.node-rect.ptm${s1}`),
315+
];
316+
312317
static nodeTypes: { id: string; label: string }[] = [
313318
{ id: 'gene_protein', label: 'Gene/Protein' },
314319
{ id: 'compound', label: 'Metabolite/Compound' },
@@ -600,6 +605,7 @@ export class BiowcPathwaygraph extends LitElement {
600605
['show-down', true],
601606
['show-not', true],
602607
['peptide-label-visibility-map', {}],
608+
['kinase-substrate-relationship-visibility-map', {}],
603609
]);
604610

605611
this._initEditModeForms();
@@ -1637,7 +1643,12 @@ export class BiowcPathwaygraph extends LitElement {
16371643
})
16381644
.style('visibility', d => {
16391645
if (d.types.includes('kinaseSubstrateLink')) {
1640-
return this.kinaseSubstrateLinksVisible ? 'visible' : 'hidden';
1646+
const visibilityMapKey = `${d.sourceId},${d.targetId}`;
1647+
return this.contextMenuStore?.get(
1648+
'kinase-substrate-relationship-visibility-map'
1649+
)[visibilityMapKey]
1650+
? 'visible'
1651+
: 'hidden';
16411652
}
16421653
if (d.types.includes('ptmlink')) {
16431654
return 'hidden';
@@ -2269,7 +2280,7 @@ export class BiowcPathwaygraph extends LitElement {
22692280

22702281
private _computeIsPerturbed(node: PathwayGraphNodeD3) {
22712282
// @ts-ignore
2272-
if (node.geneNames) {
2283+
if (node.geneNames && node.type !== 'ptm') {
22732284
const geneProteinNode = node as GeneProteinNodeD3;
22742285
if (
22752286
geneProteinNode.geneNames.filter(geneName =>
@@ -3702,6 +3713,44 @@ font-family: "Roboto Light", "Helvetica Neue", "Verdana", sans-serif'><strong st
37023713
);
37033714
}
37043715

3716+
private _updatePeptideNodeLabels() {
3717+
this.d3Nodes!.forEach(node => {
3718+
if (node.type === 'ptm') {
3719+
const ptmNode = <PTMNodeD3>node;
3720+
// TODO: If available, use Site identifier before sequence
3721+
const ptmNodeLabel =
3722+
// @ts-ignore
3723+
ptmNode.details?.Site?.text ||
3724+
ptmNode.details!['Modified Sequence'] ||
3725+
ptmNode.details!.Sequence ||
3726+
'test';
3727+
// eslint-disable-next-line no-param-reassign
3728+
ptmNode.currentDisplayedLabel = this.contextMenuStore?.get(
3729+
'peptide-label-visibility-map'
3730+
)[ptmNode.geneProteinNode?.nodeId!]
3731+
? String(ptmNodeLabel)
3732+
: '';
3733+
}
3734+
});
3735+
this._refreshGraph(true);
3736+
}
3737+
3738+
private _toggleHighlightPerturbedNodes() {
3739+
this.perturbedNodesVisible = !this.perturbedNodesVisible;
3740+
3741+
// Add or remove the show-highlight class for all circle-up and circle-down nodes
3742+
if (this.perturbedNodesVisible) {
3743+
this._getMainDiv().style('--upregulated-perturbed-color', '#c20000');
3744+
this._getMainDiv().style('--downregulated-perturbed-color', '#0043c2');
3745+
this._getMainDiv().style('--perturbed-stroke-width', '4');
3746+
} else {
3747+
this._getMainDiv().style('--upregulated-perturbed-color', '#000000');
3748+
this._getMainDiv().style('--downregulated-perturbed-color', '#000000');
3749+
this._getMainDiv().style('--perturbed-stroke-width', '1.5');
3750+
}
3751+
this._refreshGraph(true);
3752+
}
3753+
37053754
private static _getCoordinatesFromTranslate(
37063755
elem: Selection<SVGElement, unknown, any, undefined>,
37073756
withScale: Boolean
@@ -3902,49 +3951,6 @@ font-family: "Roboto Light", "Helvetica Neue", "Verdana", sans-serif'><strong st
39023951
a.click();
39033952
}
39043953

3905-
public updatePeptideNodeLabels() {
3906-
this.d3Nodes!.forEach(node => {
3907-
if (node.type === 'ptm') {
3908-
const ptmNode = <PTMNodeD3>node;
3909-
// TODO: If available, use Site identifier before sequence
3910-
const ptmNodeLabel =
3911-
// @ts-ignore
3912-
ptmNode.details?.Site?.text ||
3913-
ptmNode.details!['Modified Sequence'] ||
3914-
ptmNode.details!.Sequence ||
3915-
'test';
3916-
// eslint-disable-next-line no-param-reassign
3917-
ptmNode.currentDisplayedLabel = this.contextMenuStore?.get(
3918-
'peptide-label-visibility-map'
3919-
)[ptmNode.geneProteinNode?.nodeId!]
3920-
? String(ptmNodeLabel)
3921-
: '';
3922-
}
3923-
});
3924-
this._refreshGraph(true);
3925-
}
3926-
3927-
public toggleKinaseSubstrateLinks() {
3928-
this.kinaseSubstrateLinksVisible = !this.kinaseSubstrateLinksVisible;
3929-
this._refreshGraph(true);
3930-
}
3931-
3932-
public toggleHighlightPerturbedNodes() {
3933-
this.perturbedNodesVisible = !this.perturbedNodesVisible;
3934-
3935-
// Add or remove the show-highlight class for all circle-up and circle-down nodes
3936-
if (this.perturbedNodesVisible) {
3937-
this._getMainDiv().style('--upregulated-perturbed-color', '#c20000');
3938-
this._getMainDiv().style('--downregulated-perturbed-color', '#0043c2');
3939-
this._getMainDiv().style('--perturbed-stroke-width', '4');
3940-
} else {
3941-
this._getMainDiv().style('--upregulated-perturbed-color', '#000000');
3942-
this._getMainDiv().style('--downregulated-perturbed-color', '#000000');
3943-
this._getMainDiv().style('--perturbed-stroke-width', '1.5');
3944-
}
3945-
this._refreshGraph(true);
3946-
}
3947-
39483954
public exportSkeleton(name: string, title: string) {
39493955
return JSON.stringify(
39503956
{
@@ -4102,22 +4108,41 @@ font-family: "Roboto Light", "Helvetica Neue", "Verdana", sans-serif'><strong st
41024108
peptideNodeVisibilityMap
41034109
);
41044110

4105-
this.updatePeptideNodeLabels();
4111+
this._updatePeptideNodeLabels();
41064112
},
41074113
type: 'radio',
41084114
checked: () => this.allPtmNodeLabelsVisible,
41094115
},
41104116
{
41114117
target: 'svg',
41124118
label: 'Show Kinase-Substrate Relationships',
4113-
execute: () => this.toggleKinaseSubstrateLinks(),
4119+
execute: () => {
4120+
this.allKinaseSubstrateLinksVisible =
4121+
!this.allKinaseSubstrateLinksVisible;
4122+
const kinaseSubstrateRelationshipVisibilityMap =
4123+
this.contextMenuStore?.get(
4124+
'kinase-substrate-relationship-visibility-map'
4125+
);
4126+
this.d3Links!.forEach(link => {
4127+
if (link.types.includes('kinaseSubstrateLink')) {
4128+
const visibilityMapKey = `${link.sourceId},${link.targetId}`;
4129+
kinaseSubstrateRelationshipVisibilityMap[visibilityMapKey] =
4130+
this.allKinaseSubstrateLinksVisible;
4131+
}
4132+
});
4133+
this.contextMenuStore?.set(
4134+
'kinase-substrate-relationship-visibility-map',
4135+
kinaseSubstrateRelationshipVisibilityMap
4136+
);
4137+
this._refreshGraph(true);
4138+
},
41144139
type: 'radio',
4115-
checked: () => this.kinaseSubstrateLinksVisible,
4140+
checked: () => this.allKinaseSubstrateLinksVisible,
41164141
},
41174142
{
41184143
target: 'svg',
41194144
label: 'Highlight Differentially Active Kinases',
4120-
execute: () => this.toggleHighlightPerturbedNodes(),
4145+
execute: () => this._toggleHighlightPerturbedNodes(),
41214146
type: 'radio',
41224147
checked: () => this.perturbedNodesVisible,
41234148
},
@@ -4197,8 +4222,78 @@ font-family: "Roboto Light", "Helvetica Neue", "Verdana", sans-serif'><strong st
41974222
],
41984223
},
41994224
];
4225+
42004226
this.contextMenuCommands.push(
42014227
...(<ContextMenuCommand[]>[
4228+
// Context Menu for PTM Nodes
4229+
{
4230+
target: BiowcPathwaygraph.ptmNodes,
4231+
label: 'Show Kinase-Substrate Relationships for Node',
4232+
enabled: (ctx: EnabledOptions) =>
4233+
this.d3Links!.filter(
4234+
link =>
4235+
link.types.includes('kinaseSubstrateLink') &&
4236+
// @ts-ignore
4237+
link.targetId === ctx.target.__data__.nodeId
4238+
).length > 0,
4239+
execute: (ctx: ExecuteOptions) => {
4240+
const kinaseSubstrateRelationshipVisibilityMap =
4241+
this.contextMenuStore?.get(
4242+
'kinase-substrate-relationship-visibility-map'
4243+
);
4244+
const kslinksOfNode = this.d3Links!.filter(
4245+
link =>
4246+
link.types.includes('kinaseSubstrateLink') &&
4247+
// @ts-ignore
4248+
link.targetId === ctx.target.__data__.nodeId
4249+
);
4250+
// If there is any link that is not visible, the menu will be unchecked and clicking will make all visible
4251+
// If all are visible, the menu will be checked and clicking will make all invisible
4252+
const hasSubstrateAnyNotVisibleLink =
4253+
kslinksOfNode.filter(link => {
4254+
const visibilityMapKey = `${link.sourceId},${link.targetId}`;
4255+
return !kinaseSubstrateRelationshipVisibilityMap[
4256+
visibilityMapKey
4257+
];
4258+
}).length > 0;
4259+
kslinksOfNode.forEach(link => {
4260+
const visibilityMapKey = `${link.sourceId},${link.targetId}`;
4261+
kinaseSubstrateRelationshipVisibilityMap[visibilityMapKey] =
4262+
hasSubstrateAnyNotVisibleLink;
4263+
});
4264+
this.contextMenuStore?.set(
4265+
'kinase-substrate-relationship-visibility-map',
4266+
kinaseSubstrateRelationshipVisibilityMap
4267+
);
4268+
this._refreshGraph(true);
4269+
},
4270+
type: 'radio',
4271+
checked: ctx => {
4272+
const kslinksOfNode = this.d3Links!.filter(
4273+
link =>
4274+
link.types.includes('kinaseSubstrateLink') &&
4275+
// @ts-ignore
4276+
link.targetId === ctx.target.__data__.nodeId
4277+
);
4278+
// If the node has zero kslinks, this is disabled and cannot be checked
4279+
if (kslinksOfNode.length === 0) {
4280+
return false;
4281+
}
4282+
// Else check if any of its ks links is not visible, then it is unchecked. If all are visible it is checked
4283+
const kinaseSubstrateRelationshipVisibilityMap =
4284+
this.contextMenuStore?.get(
4285+
'kinase-substrate-relationship-visibility-map'
4286+
);
4287+
return (
4288+
kslinksOfNode.filter(link => {
4289+
const visibilityMapKey = `${link.sourceId},${link.targetId}`;
4290+
return !kinaseSubstrateRelationshipVisibilityMap[
4291+
visibilityMapKey
4292+
];
4293+
}).length === 0
4294+
);
4295+
},
4296+
},
42024297
// Context Menu for Gene/Protein Nodes
42034298
{
42044299
target: BiowcPathwaygraph.geneProteinPathwayCompoundsNodes,
@@ -4211,7 +4306,7 @@ font-family: "Roboto Light", "Helvetica Neue", "Verdana", sans-serif'><strong st
42114306
peptideNodeVisibilityMap[ctx.target.__data__.nodeId] =
42124307
// @ts-ignore
42134308
!peptideNodeVisibilityMap[ctx.target.__data__.nodeId];
4214-
this.updatePeptideNodeLabels();
4309+
this._updatePeptideNodeLabels();
42154310
},
42164311
type: 'radio',
42174312
checked: ctx =>
@@ -4220,6 +4315,75 @@ font-family: "Roboto Light", "Helvetica Neue", "Verdana", sans-serif'><strong st
42204315
ctx.target.__data__.nodeId
42214316
],
42224317
},
4318+
{
4319+
target: BiowcPathwaygraph.geneProteinPathwayCompoundsNodes,
4320+
label: 'Show Kinase-Substrate Relationships for Node',
4321+
enabled: (ctx: EnabledOptions) =>
4322+
this.d3Links!.filter(
4323+
link =>
4324+
link.types.includes('kinaseSubstrateLink') &&
4325+
// @ts-ignore
4326+
link.sourceId === ctx.target.__data__.nodeId
4327+
).length > 0,
4328+
execute: (ctx: ExecuteOptions) => {
4329+
const kinaseSubstrateRelationshipVisibilityMap =
4330+
this.contextMenuStore?.get(
4331+
'kinase-substrate-relationship-visibility-map'
4332+
);
4333+
const kslinksOfNode = this.d3Links!.filter(
4334+
link =>
4335+
link.types.includes('kinaseSubstrateLink') &&
4336+
// @ts-ignore
4337+
link.sourceId === ctx.target.__data__.nodeId
4338+
);
4339+
// If there is any link that is not visible, the menu will be unchecked and clicking will make all visible
4340+
// If all are visible, the menu will be checked and clicking will make all invisible
4341+
const hasKinaseAnyNotVisibleLink =
4342+
kslinksOfNode.filter(link => {
4343+
const visibilityMapKey = `${link.sourceId},${link.targetId}`;
4344+
return !kinaseSubstrateRelationshipVisibilityMap[
4345+
visibilityMapKey
4346+
];
4347+
}).length > 0;
4348+
4349+
kslinksOfNode.forEach(link => {
4350+
const visibilityMapKey = `${link.sourceId},${link.targetId}`;
4351+
kinaseSubstrateRelationshipVisibilityMap[visibilityMapKey] =
4352+
hasKinaseAnyNotVisibleLink;
4353+
});
4354+
this.contextMenuStore?.set(
4355+
'kinase-substrate-relationship-visibility-map',
4356+
kinaseSubstrateRelationshipVisibilityMap
4357+
);
4358+
this._refreshGraph(true);
4359+
},
4360+
type: 'radio',
4361+
checked: ctx => {
4362+
const kslinksOfNode = this.d3Links!.filter(
4363+
link =>
4364+
link.types.includes('kinaseSubstrateLink') &&
4365+
// @ts-ignore
4366+
link.sourceId === ctx.target.__data__.nodeId
4367+
);
4368+
// If the node has zero kslinks, this is disabled and cannot be checked
4369+
if (kslinksOfNode.length === 0) {
4370+
return false;
4371+
}
4372+
// Else check if any of its ks links is not visible, then it is unchecked. If all are visible it is checked
4373+
const kinaseSubstrateRelationshipVisibilityMap =
4374+
this.contextMenuStore?.get(
4375+
'kinase-substrate-relationship-visibility-map'
4376+
);
4377+
return (
4378+
kslinksOfNode.filter(link => {
4379+
const visibilityMapKey = `${link.sourceId},${link.targetId}`;
4380+
return !kinaseSubstrateRelationshipVisibilityMap[
4381+
visibilityMapKey
4382+
];
4383+
}).length === 0
4384+
);
4385+
},
4386+
},
42234387
{
42244388
target: BiowcPathwaygraph.geneProteinPathwayCompoundsNodes.concat([
42254389
'path.group-path',

0 commit comments

Comments
 (0)