Commit acdc46b8 authored by Lukas Pravda's avatar Lukas Pravda
Browse files

change the way highlight of selected nodes is made

parent 5cea7d9e
Pipeline #99202 passed with stages
in 1 minute and 14 seconds
......@@ -27,6 +27,7 @@ class Visualization {
private visualsMapper: VisualsMapper;
private interactionsData: any;
private selectedResidueHash: string;
private nodeDragged: boolean;
private rProvider: ResidueProvider;
......@@ -42,6 +43,7 @@ class Visualization {
this.rProvider = ResidueProvider.getInstance(this.environment);
this.fullScreen = false;
this.bindingSites = new Array<Model.BindingSite>();
this.nodeDragged = false;
if (uiParameters === undefined) uiParameters = new Config.UIParameters();
......@@ -71,7 +73,7 @@ class Visualization {
this.addMarkers();
}
// #region even handlers
// #region event handlers
private getZoomHandler() {
return d3.zoom()
.scaleExtent([1 / 10, 10])
......@@ -87,7 +89,7 @@ class Visualization {
this.nodes?.each((node: Model.InteractionNode, index: number, group: any) => {
this.nodeDim(node, index, group);
if (node.id === hash) {
this.selectedResidueHash = hash;
this.nodeHighlight(node, index, group);
......@@ -97,7 +99,6 @@ class Visualization {
}
private nodeMouseLeaveEventHandler() {
if (this.fullScreen) return;
......@@ -109,22 +110,34 @@ class Visualization {
});
}
private linkMouseClickEventHandler(x: Model.Link) {
this.fireExternalLinkEvent(x, Config.interactionClickEvent);
private linkMouseOverEventHandler(x: Model.Link, i: number, g: any) {
if (!this.nodeDragged) {
this.linkHighlight(x, i, g);
this.fireExternalLinkEvent(x, Config.interactionMouseoverEvent);
}
}
private linkMouseOverEventHandler(x: Model.Link, index: number, group: any) {
let parent = d3.select(group[index]).node().parentNode;
d3.select(parent).classed('pdb-lig-env-svg-bond-highlighted', true);
private linkMouseOutEventHandler(x: Model.Link, i: number, g: any) {
if (!this.nodeDragged) {
this.linkDim(x, i, g);
this.fireExternalNullEvent(Config.interactionMouseoutEvent);
}
}
this.fireExternalLinkEvent(x, Config.interactionMouseoverEvent);
//https://stackoverflow.com/questions/40722344/understanding-d3-with-an-example-mouseover-mouseup-with-multiple-arguments
private nodeMouseoverEventHandler(x: Model.InteractionNode, i: number, g: any) {
if (!this.nodeDragged) {
this.nodeHighlight(x, i, g);
this.fireExternalNodeEvent(x, Config.interactionMouseoverEvent);
}
}
private linkMouseOutEventHandler(index: number, group: any) {
let parent = d3.select(group[index]).node().parentNode;
d3.select(parent).classed('pdb-lig-env-svg-bond-highlighted', false);
private nodeMouseoutEventHandler(x: Model.InteractionNode, i: number, g: any) {
if (!this.nodeDragged) {
this.nodeDim(x, i, g);
this.fireExternalLinkLeaveEvent();
this.fireExternalNullEvent(Config.interactionMouseoutEvent);
}
}
private dragHandler = d3.drag()
......@@ -136,10 +149,14 @@ class Visualization {
x.fy = x.y;
})
.on('drag', (x: Model.InteractionNode) => {
this.nodeDragged = true;
x.fx = d3.event.x;
x.fy = d3.event.y;
})
.on('end', (x: Model.InteractionNode) => {
this.nodeDragged = false;
if (!d3.event.active) this.simulation.alphaTarget(0);
x.fx = d3.event.x;
x.fy = d3.event.y;
......@@ -377,18 +394,18 @@ class Visualization {
* @memberof Visualization
*/
public reinitialize() {
if (this.bindingSites.length > 1 && this.depiction !== undefined) {
this.presentBindingSite = this.bindingSites[0];
this.bindingSites.pop();
this.depictionRoot.selectAll('*').remove();
this.depiction = undefined;
this.nullNodesPositions();
this.setupScene().then(() => this.centerScene());
}
else if (this.depiction === undefined) {
else if (this.depiction === undefined) {
this.nullNodesPositions();
this.setupScene().then(() => this.centerScene());
}
......@@ -397,7 +414,7 @@ class Visualization {
this.setupLigandScene().then(() => this.centerScene());
}
this.hideLigandLabel();
this.fireExternalNullEvent(Config.interactionHideLabelEvent);
}
......@@ -486,7 +503,7 @@ class Visualization {
return 'blank.svg';
}
private nullNodesPositions() {
private nullNodesPositions() {
this.presentBindingSite.interactionNodes.forEach((x: Model.InteractionNode) => {
if (!x.static) {
x.fx = null;
......@@ -498,22 +515,6 @@ class Visualization {
// #region fire events
//https://stackoverflow.com/questions/40722344/understanding-d3-with-an-example-mouseover-mouseup-with-multiple-arguments
private fireExternalNodeMouseEnterEvent(x: Model.InteractionNode, i: number, g: any) {
this.nodeHighlight(x, i, g);
this.fireExternalNodeEvent(x, Config.interactionMouseoverEvent);
}
private fireExternalNodeMouseLeaveEvent(x: Model.InteractionNode, i: number, g: any) {
this.nodeDim(x, i, g);
const e = new CustomEvent(Config.interactionMouseoutEvent, {
bubbles: true,
detail: {}
});
this.parent.dispatchEvent(e);
}
private fireExternalLinkEvent(link: Model.Link, eventName: string) {
let atomsSource = [];
let atomsTarget = [];
......@@ -568,8 +569,8 @@ class Visualization {
this.parent.dispatchEvent(e);
}
private fireExternalLinkLeaveEvent() {
const e = new CustomEvent(Config.interactionMouseoutEvent, {
private fireExternalNullEvent(eventName: string) {
const e = new CustomEvent(eventName, {
bubbles: true,
detail: {}
});
......@@ -595,16 +596,15 @@ class Visualization {
this.links
.append('line')
.classed('pdb-lig-env-svg-shadow-bond', (x: Model.Link) => x.getLinkClass() !== 'hydrophobic')
.on('click', (x: Model.Link) => this.linkMouseClickEventHandler(x))
.on('mouseenter', (x: Model.Link, index: number, group: any) => this.linkMouseOverEventHandler(x, index, group))
.on('mouseleave', (_, index: number, group: any) => this.linkMouseOutEventHandler(index, group));
.on('mouseleave', (x: Model.Link, index: number, group: any) => this.linkMouseOutEventHandler(x, index, group));
this.links
.append('line')
.attr('class', (e: Model.Link) => `pdb-lig-env-svg-bond pdb-lig-env-svg-bond-${e.getLinkClass()}`)
.attr('marker-mid', (e: Model.Link) => e.hasClash() ? 'url(#clash)' : '')
.on('mouseenter', (x: Model.Link, y: any, z: any) => this.linkMouseOverEventHandler(x, y, z))
.on('mouseleave', (_, index: number, group: any) => this.linkMouseOutEventHandler(index, group));
.on('mouseleave', (x: Model.Link, index: number, group: any) => this.linkMouseOutEventHandler(x, index, group));
}
......@@ -616,7 +616,7 @@ class Visualization {
.style('dominant-baseline', 'central')
.each(function (e: Model.InteractionNode) {
let labels = [e.residue.chemCompId, `${e.residue.chainId} ${e.residue.authorResidueNumber}`];
for (var i = 0; i < labels.length; i++) {
for (let i = 0; i < labels.length; i++) {
d3.select(this)
.append('tspan')
.attr('dy', (i * 20) - 4)
......@@ -643,7 +643,7 @@ class Visualization {
if (!n.residue.isLigand) return;
this.nodeDim(n, i, g);
this.fireExternalNodeMouseLeaveEvent(n, i, g);
this.nodeMouseoutEventHandler(n, i, g);
this.showLigandLabel(n);
this.initLigandInteractions(this.pdbId, n.residue.authorResidueNumber, n.residue.chainId);
......@@ -714,10 +714,9 @@ class Visualization {
this.nodes.filter((x: Model.InteractionNode) => !x.residue.isLigand)
.on('click', (x: Model.InteractionNode) => this.fireExternalNodeEvent(x, Config.interactionClickEvent))
.attr('class', (x: Model.InteractionNode) => `pdb-lig-env-svg-node pdb-lig-env-svg-${x.residue.getResidueType()}-res`)
.on('mouseenter', (x: Model.InteractionNode, i: number, g: any) => this.fireExternalNodeMouseEnterEvent(x, i, g))
.on('mouseleave', (x: Model.InteractionNode, i: number, g: any) => this.fireExternalNodeMouseLeaveEvent(x, i, g));
.on('mouseenter', (x: Model.InteractionNode, i: number, g: any) => this.nodeMouseoverEventHandler(x, i, g))
.on('mouseleave', (x: Model.InteractionNode, i: number, g: any) => this.nodeMouseoutEventHandler(x, i, g));
this.nodes.filter((x: Model.InteractionNode) => !x.residue.isLigand && this.visualsMapper.glycanMapping.has(x.residue.chemCompId))
.html((e: Model.InteractionNode) => this.visualsMapper.getGlycanImage(e.residue.chemCompId));
......@@ -761,7 +760,7 @@ class Visualization {
this.setupLinks();
// setup nodes; wait for resources to be ready
this.presentBindingSite.interactionNodes.forEach(x => ResidueProvider.getInstance(this.environment).downloadAnnotation(x.residue));
this.presentBindingSite.interactionNodes.forEach(x => this.rProvider.downloadAnnotation(x.residue));
await Promise.all(this.rProvider.downloadPromises);
await Promise.all([this.visualsMapper.graphicsPromise, this.visualsMapper.mappingPromise]);
......@@ -771,8 +770,8 @@ class Visualization {
.enter().append('g')
.attr('class', (e: Model.InteractionNode) => `pdb-lig-env-svg-node pdb-lig-env-svg-${e.residue.getResidueType()}-res`)
.on('click', (x: Model.InteractionNode, i: number, g: any) => this.selectLigand(x, i, g))
.on('mouseover', (x: Model.InteractionNode, i: number, g: any) => this.fireExternalNodeMouseEnterEvent(x, i, g))
.on('mouseout', (x: Model.InteractionNode, i: number, g: any) => this.fireExternalNodeMouseLeaveEvent(x, i, g));
.on('mouseover', (x: Model.InteractionNode, i: number, g: any) => this.nodeMouseoverEventHandler(x, i, g))
.on('mouseout', (x: Model.InteractionNode, i: number, g: any) => this.nodeMouseoutEventHandler(x, i, g));
this.nodes.filter((n: Model.InteractionNode) =>
......@@ -827,8 +826,25 @@ class Visualization {
x.scale = 1.5;
if (x.residue.isLigand) d3.select(g[i]).style('cursor', 'pointer');
d3.select(g[i])
//.transition()
.attr('transform', () => `translate(${x.x},${x.y}) scale(${x.scale})`);
let otherNodes = [x];
this.links.filter((l: Model.Link) => l.containsNode(x)).each((lnk: Model.Link) => {
let otherNode = lnk.getOtherNode(x);
otherNodes.push(otherNode);
});
this.nodes
.filter((node: Model.InteractionNode) => !otherNodes.includes(node))
.attr('opacity', 0.4);
this.links
.filter((l: Model.Link) => !l.containsNode(x))
//.transition()
.attr('opacity', 0.4);
}
......@@ -836,12 +852,57 @@ class Visualization {
x.scale = 1.0;
if (x.residue.isLigand) d3.select(g[i]).style('cursor', 'default');
d3.select(g[i])
//.transition()
.attr('transform', `translate(${x.x},${x.y}) scale(${x.scale})`);
this.links.attr('opacity', 1);
this.nodes.attr('opacity', 1);
// g.forEach((_, index) => {
// if (i != index) {
// d3.select(g[index])//.transition()
// .attr('opacity', 1);
// }
// });
// this.links
// .filter((l: Model.Link) => !l.containsNode(x))
// //.transition()
// .attr('opacity', 1);
}
private linkHighlight(x: Model.Link, i: number, g: any) {
let parent = d3.select(g[i]).node().parentNode;
d3.select(parent).classed('pdb-lig-env-svg-bond-highlighted', true);
this.links
.filter((l: Model.Link) => l !== x)
//.transition()
.attr('opacity', 0.4);
this.nodes
.filter((l: Model.InteractionNode) => !(l === x.source || l === x.target))
//.transition()
.attr('opacity', 0.4);
}
private linkDim(x: Model.Link, i: number, g: any) {
let parent = d3.select(g[i]).node().parentNode;
d3.select(parent).classed('pdb-lig-env-svg-bond-highlighted', false);
this.links
.filter((l: Model.Link) => l !== x)
//.transition()
.attr('opacity', 1);
this.nodes
.filter((l: Model.InteractionNode) => !(l === x.source || l === x.target))
//.transition()
.attr('opacity', 1);
}
private showLigandLabel(x: Model.InteractionNode) {
const e = new CustomEvent(Config.interactionShowLabelEvent, {
bubbles: true,
......@@ -853,34 +914,18 @@ class Visualization {
this.parent.dispatchEvent(e);
}
private hideLigandLabel() {
const e = new CustomEvent(Config.interactionHideLabelEvent, {
bubbles: true,
detail: {}
});
this.parent.dispatchEvent(e);
}
private addMarkers() {
// let mapping = new Map<string, string>([
// // ["arrow-electrostatic", "#3F26BF"],
// // ["arrow-vdw", "#9B7653"],
// // ["arrow-metal", "#008080"],
// // ["arrow-aromatic", "#AD4379"],
let defs = this.svg.append('defs')
// proper background for depiction tspans
// gracefully coppied from: https://stackoverflow.com/questions/15500894/background-color-of-text-in-svg
// gracefully copied from: https://stackoverflow.com/questions/15500894/background-color-of-text-in-svg
let filter = defs.append('filter')
.attr('x', 0)
.attr('y', 0)
.attr('width', 1)
.attr('height', 1)
.attr('id', 'solid-background')
filter.append('feFlood').attr('flood-color', 'white')
filter.append('feComposite').attr('in', 'SourceGraphic')
......@@ -897,21 +942,6 @@ class Visualization {
.append('path')
.attr('d', 'M22.245,4.015c0.313,0.313,0.313,0.826,0,1.139l-6.276,6.27c-0.313,0.312-0.313,0.826,0,1.14l6.273,6.272 c0.313,0.313,0.313,0.826,0,1.14l-2.285,2.277c-0.314,0.312-0.828,0.312-1.142,0l-6.271-6.271c-0.313-0.313-0.828-0.313-1.141,0 l-6.276,6.267c-0.313,0.313-0.828,0.313-1.141,0l-2.282-2.28c-0.313-0.313-0.313-0.826,0-1.14l6.278-6.269 c0.313-0.312,0.313-0.826,0-1.14L1.709,5.147c-0.314-0.313-0.314-0.827,0-1.14l2.284-2.278C4.308,1.417,4.821,1.417,5.135,1.73 L11.405,8c0.314,0.314,0.828,0.314,1.141,0.001l6.276-6.267c0.312-0.312,0.826-0.312,1.141,0L22.245,4.015z')
.attr('style', 'stroke:#FF5050;stroke-width:3px;');
// mapping.forEach((x, y) =>
// d3.select('defs').append('marker')
// .attr('id', y)
// .attr("markerWidth", 15)
// .attr("markerHeight", 15)
// .attr("refX", 7)
// .attr("refY", 3)
// .attr("orient", "auto")
// .attr('markerUnits', 'strokeWidth')
// .attr('viewBox', '0 0 20 20')
// .append('path')
// .attr('d', 'M0,0 L0,6 L9,3 z')
// .attr('fill', x)
// );
}
private parseEnvironment(env: string): Model.Environment {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment