Skip to content

Commit 4c45096

Browse files
authored
Merge pull request #383 from eweitz/interactive-pathways
Improve configurability for interactive pathways
2 parents 1023e99 + a469f9e commit 4c45096

File tree

3 files changed

+64
-18
lines changed

3 files changed

+64
-18
lines changed

examples/vanilla/gene-leads.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@ <h1>Gene Leads<small>Enrich your gene search</small></h1>
207207
}
208208
}
209209

210+
async function onWillShowAnnotTooltip(annot) {
211+
if (annot.then) {
212+
return await annot
213+
}
214+
return annot
215+
}
216+
210217
/** Ideogram has no 3rd party analytics, but lets you easily hook in your own */
211218
function reportFoundGenes() {
212219
console.log(this.relatedGenesAnalytics)
@@ -246,7 +253,8 @@ <h1>Gene Leads<small>Enrich your gene search</small></h1>
246253
onLoad: plotGeneFromUrl,
247254
onPlotFoundGenes: reportFoundGenes,
248255
onHoverLegend: reportLegendMetrics,
249-
onClickAnnot
256+
onClickAnnot,
257+
onWillShowAnnotTooltip
250258
}
251259

252260
const annotsInList = 'all';

src/js/ideogram.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ import {
7070

7171
import {
7272
drawPathway as _drawPathway,
73-
getPathwayGenes as _getPathwayGenes
73+
getPathwayGenes as _getPathwayGenes,
74+
getPathwayAnnotations
7475
} from './kit/pathway-viewer.js';
7576

7677
import {
@@ -359,23 +360,33 @@ export default class Ideogram {
359360
* @param {String} outerSelector DOM selector of container, e.g. "#my-diagram"
360361
* @param {Object} dimensions Height and width of pathway diagram
361362
* @param {Boolean} showClose Whether to show close button
362-
* @param {Function} geneNodeHoverFn Function to call upon hovering diagram node
363+
* @param {Function} geneNodeHoverFn Function to call upon hovering gene
364+
* @param {Function} pathwayNodeClickFn Function to call upon clicking pathway
365+
* @param {Boolean} showDescription Whether to display pathway description
366+
* @param {Boolean} showOntologies Whether to display ontology annotations
367+
* @param {Boolean} showDefaultTooltips Whether to display default tooltips
363368
*/
364369
static drawPathway(
365370
pwId, sourceGene, destGene,
366371
outerSelector,
367372
dimensions={height: 440, width: 900},
368373
showClose=true,
369374
geneNodeHoverFn=undefined,
370-
pathwayNodeClickFn=undefined
375+
pathwayNodeClickFn=undefined,
376+
showDescription=true,
377+
showOntologies=true,
378+
showDefaultTooltips=true
371379
) {
372380
_drawPathway(
373381
pwId, sourceGene, destGene,
374382
outerSelector,
375383
dimensions=dimensions,
376384
showClose=showClose,
377385
geneNodeHoverFn=geneNodeHoverFn,
378-
pathwayNodeClickFn=pathwayNodeClickFn
386+
pathwayNodeClickFn=pathwayNodeClickFn,
387+
showDescription=showDescription,
388+
showOntologies=showOntologies,
389+
showDefaultTooltips=showDefaultTooltips
379390
);
380391
}
381392

@@ -400,4 +411,8 @@ export default class Ideogram {
400411
static getPathwayGenes() {
401412
return _getPathwayGenes();
402413
}
414+
415+
static getPathwayOntologies(pathwayJson, selectedOntology) {
416+
return getPathwayAnnotations(pathwayJson, selectedOntology);
417+
}
403418
}

src/js/kit/pathway-viewer.js

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ function parsePwAnnotations(entitiesById, keys, ontology) {
227227
return pwAnnotations;
228228
}
229229

230-
function getPathwayAnnotations(pathwayJson) {
230+
export function getPathwayAnnotations(pathwayJson, selectedOntology) {
231231
const entitiesById = pathwayJson.entitiesById;
232232
const keys = Object.keys(entitiesById).filter(k => k.startsWith('http://identifiers.org'));
233233
const sentenceCases = {
@@ -238,12 +238,19 @@ function getPathwayAnnotations(pathwayJson) {
238238
'Disease'
239239
// 'Pathway Ontology' // maybe later
240240
];
241-
const pathwayAnnotationsList = ontologies.map(ontology => {
241+
let selectedOntologies = ontologies;
242+
if (selectedOntology) {
243+
selectedOntologies = [ontologies.find(
244+
ontology => ontology.toLowerCase() === selectedOntology.toLowerCase()
245+
)];
246+
}
247+
const pathwayAnnotationsList = selectedOntologies.map(ontology => {
242248
const pwAnnotations = parsePwAnnotations(entitiesById, keys, ontology);
243249
const links = pwAnnotations.map(pwa => {
244250
const id = pwa.xrefIdentifier.replace(':', '_');
245251
const url = `https://purl.obolibrary.org/obo/${id}`;
246-
return `<a href="${url}" target="_blank">${pwa.term}</a>`;
252+
const cls = 'class="_ideoPathwayOntologyLink"';
253+
return `<a href="${url}" target="_blank" ${cls}>${pwa.term}</a>`;
247254
}).join(', ');
248255

249256
const refinedOntology = sentenceCases[ontology] ?? ontology;
@@ -281,9 +288,10 @@ export function getPathwayGenes() {
281288
}
282289

283290

284-
function addFooter(pathwayJson, pathwayContainer) {
291+
function addFooter(pathwayJson, pathwayContainer, showOntologies) {
285292
const description = getDescription(pathwayJson);
286-
const pathwayAnnotations = getPathwayAnnotations(pathwayJson);
293+
const pathwayAnnotations =
294+
showOntologies ? getPathwayAnnotations(pathwayJson) : '';
287295
const footer =
288296
`<br/>` +
289297
`<div class="_ideoPathwayFooter">` +
@@ -302,6 +310,9 @@ export async function drawPathway(
302310
showClose=true,
303311
geneNodeHoverFn,
304312
pathwayNodeClickFn,
313+
showDescription,
314+
showOntologies,
315+
showDefaultTooltips,
305316
retryAttempt=0
306317
) {
307318
const pvjsScript = document.querySelector(`script[src="${PVJS_URL}"]`);
@@ -324,6 +335,7 @@ export async function drawPathway(
324335
pwId, sourceGene, destGene,
325336
outerSelector, dimensions, showClose,
326337
geneNodeHoverFn, pathwayNodeClickFn,
338+
showDescription,
327339
retryAttempt++
328340
);
329341
}, 250);
@@ -390,7 +402,9 @@ export async function drawPathway(
390402
const pathwayViewer = new Pvjs(pvjsContainer, pvjsProps);
391403
addHeader(pwId, pathwayJson, pathwayContainer, showClose);
392404

393-
addFooter(pathwayJson, pathwayContainer);
405+
if (showDescription) {
406+
addFooter(pathwayJson, pathwayContainer, showOntologies);
407+
}
394408

395409
// zoomToEntity(sourceEntityId);
396410

@@ -414,10 +428,15 @@ export async function drawPathway(
414428
}
415429
});
416430

417-
geneNode.setAttribute(`data-tippy-content`, tooltipContent);
431+
if (showDefaultTooltips) {
432+
geneNode.setAttribute(`data-tippy-content`, tooltipContent);
433+
}
418434
});
419-
const tippyConfig = getTippyConfig();
420-
tippy('g.GeneProduct[data-tippy-content]', tippyConfig);
435+
if (showDefaultTooltips) {
436+
const tippyConfig = getTippyConfig();
437+
tippyConfig.trigger = 'mouseenter';
438+
tippy('g.GeneProduct[data-tippy-content]', tippyConfig);
439+
}
421440

422441
// Add click handler to pathway nodes in this pathway diagram
423442
if (pathwayNodeClickFn) {
@@ -433,11 +452,15 @@ export async function drawPathway(
433452
pathwayNodeClickFn(event, pathwayId);
434453
});
435454

436-
// Indicate this new pathway can be rendered on click
437-
const tooltipContent = 'Click to show pathway';
438-
pathwayNode.setAttribute('data-tippy-content', tooltipContent);
455+
if (showDefaultTooltips) {
456+
// Indicate this new pathway can be rendered on click
457+
const tooltipContent = 'Click to show pathway';
458+
pathwayNode.setAttribute('data-tippy-content', tooltipContent);
459+
}
439460
});
440461

441-
tippy('g.Pathway[data-tippy-content]', tippyConfig);
462+
if (showDefaultTooltips) {
463+
tippy('g.Pathway[data-tippy-content]', tippyConfig);
464+
}
442465
}
443466
}

0 commit comments

Comments
 (0)