Skip to content

Commit d7c51e4

Browse files
authored
Merge pull request #381 from eweitz/static-draw-pathways
Enable static draw for pathways
2 parents 0baaa2c + a23101a commit d7c51e4

17 files changed

Lines changed: 434 additions & 140 deletions

examples/vanilla/gene-leads.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ <h1>Gene Leads<small>Enrich your gene search</small></h1>
242242
organism: organism,
243243
container: '#ideogram-container',
244244
// fontFamily: "'Montserrat', sans-serif",
245+
showVariantInTooltip: plotGeneFromUrl,
245246
onLoad: plotGeneFromUrl,
246247
onPlotFoundGenes: reportFoundGenes,
247248
onHoverLegend: reportLegendMetrics,

karma.conf.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ module.exports = function(config) {
1616
// list of files / patterns to load in the browser
1717
files: [
1818
'src/js/index.js',
19-
// 'test/offline/**.test.js',
20-
// 'test/online/**.test.js',
19+
'test/offline/**.test.js',
20+
'test/online/**.test.js',
2121
// 'test/online/related-genes.test.js',
22-
'test/offline/gene-structure.test.js',
22+
// 'test/offline/gene-structure.test.js',
2323
// 'test/offline/tissue.test.js',
2424
{pattern: 'dist/data/**', watched: false, included: false, served: true, nocache: false}
2525
],

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
"fast-kde": "0.2.1",
5555
"fflate": "^0.7.3",
5656
"tippy.js": "6.3.7",
57-
"workbox-range-requests": "7.0.0"
57+
"workbox-range-requests": "7.0.0",
58+
"snarkdown": "^2.0.0"
5859
},
5960
"devDependencies": {
6061
"@babel/core": "^7.16.0",

src/js/annotations/annotations.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,9 +287,9 @@ export function applyRankCutoff(annots, cutoff, ideo) {
287287
export function setAnnotRanks(annots, ideo) {
288288
if (annots.length === 0) return annots;
289289
if ('initRank' in annots[0] === false) {
290-
if ('geneCache' in ideo === false) return annots;
290+
if ('geneCache' in Ideogram === false) return annots;
291291

292-
const ranks = ideo.geneCache.interestingNames;
292+
const ranks = Ideogram.geneCache.interestingNames;
293293

294294
return annots.map(annot => {
295295
if (ranks.includes(annot.name)) {

src/js/ideogram.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ import {
6868
plotRelatedGenes, getRelatedGenesByType
6969
} from './kit/related-genes';
7070

71+
import {
72+
drawPathway as _drawPathway,
73+
getPathwayGenes as _getPathwayGenes
74+
} from './kit/pathway-viewer.js';
75+
76+
import {
77+
initCaches as _initCaches
78+
} from './init/caches/cache';
79+
7180
export default class Ideogram {
7281
constructor(config) {
7382

@@ -340,4 +349,55 @@ export default class Ideogram {
340349
static initGeneLeads(config, annotsInList='all') {
341350
return _initGeneLeads(config, annotsInList);
342351
}
352+
353+
/**
354+
* Wrapper for drawing biological pathways using cached WikiPathways data
355+
*
356+
* @param {String} pwId WikiPathways ID, e.g. "WP5109"
357+
* @param {String} sourceGene Symbol of source gene, e.g. "LDLR"
358+
* @param {String} destGene Symbol of destination gene, e.g. "PCSK9"
359+
* @param {String} outerSelector DOM selector of container, e.g. "#my-diagram"
360+
* @param {Object} dimensions Height and width of pathway diagram
361+
* @param {Boolean} showClose Whether to show close button
362+
* @param {Function} geneNodeHoverFn Function to call upon hovering diagram node
363+
*/
364+
static drawPathway(
365+
pwId, sourceGene, destGene,
366+
outerSelector,
367+
dimensions={height: 440, width: 900},
368+
showClose=true,
369+
geneNodeHoverFn=undefined,
370+
pathwayNodeClickFn=undefined
371+
) {
372+
_drawPathway(
373+
pwId, sourceGene, destGene,
374+
outerSelector,
375+
dimensions=dimensions,
376+
showClose=showClose,
377+
geneNodeHoverFn=geneNodeHoverFn,
378+
pathwayNodeClickFn=pathwayNodeClickFn
379+
);
380+
}
381+
382+
/**
383+
* Wrapper for initializing cached data
384+
*
385+
* @param {Object} config Includes organism, useCache, etc.
386+
*/
387+
static initCaches(config={
388+
organism: 'homo-sapiens', useCache: true,
389+
awaitCache: true,
390+
showGeneStructureInTooltip: true
391+
}) {
392+
_initCaches(config);
393+
}
394+
395+
/**
396+
* Get list of gene names in pathway
397+
*
398+
* @param {Object} config Includes organism, useCache, etc.
399+
*/
400+
static getPathwayGenes() {
401+
return _getPathwayGenes();
402+
}
343403
}

src/js/init/caches/cache.js

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,8 @@ import {parseVariantCacheIndex} from './variant-cache-worker';
4545
* possible completely offline (i.e. a progressive web component) -- but only
4646
* once caches are populated.
4747
*/
48-
export async function initCaches(ideo) {
48+
export async function initCaches(config) {
4949

50-
const config = ideo.config;
5150
if (!config.useCache) return;
5251

5352
const organism = config.organism;
@@ -60,31 +59,35 @@ export async function initCaches(ideo) {
6059
// resolves a Promise, whereas the others return upon completing their
6160
// respective initializations.
6261
const cachePromise = Promise.all([
63-
cacheFactory('gene', organism, ideo, cacheDir),
64-
cacheFactory('paralog', organism, ideo, cacheDir),
65-
cacheFactory('interaction', organism, ideo, cacheDir),
66-
cacheFactory('synonym', organism, ideo, cacheDir),
62+
cacheFactory('gene', organism, config, cacheDir),
63+
cacheFactory('paralog', organism, config, cacheDir),
64+
cacheFactory('interaction', organism, config, cacheDir),
65+
cacheFactory('synonym', organism, config, cacheDir),
6766
]);
6867

6968
if (config.showGeneStructureInTooltip) {
70-
cacheFactory('geneStructure', organism, ideo, cacheDir);
71-
cacheFactory('protein', organism, ideo, cacheDir);
72-
cacheFactory('tissue', organism, ideo, cacheDir);
73-
cacheFactory('variant', organism, ideo, cacheDir);
69+
cacheFactory('geneStructure', organism, config, cacheDir);
70+
cacheFactory('protein', organism, config, cacheDir);
71+
cacheFactory('tissue', organism, config, cacheDir);
72+
if (config.showVariantInTooltip) {
73+
cacheFactory('variant', organism, config, cacheDir);
74+
}
7475
}
7576

7677
return cachePromise;
7778

7879
} else {
79-
cacheFactory('gene', organism, ideo, cacheDir);
80-
cacheFactory('paralog', organism, ideo, cacheDir);
81-
cacheFactory('interaction', organism, ideo, cacheDir);
80+
cacheFactory('gene', organism, config, cacheDir);
81+
cacheFactory('paralog', organism, config, cacheDir);
82+
cacheFactory('interaction', organism, config, cacheDir);
8283
if (config.showGeneStructureInTooltip) {
83-
cacheFactory('geneStructure', organism, ideo, cacheDir);
84-
cacheFactory('protein', organism, ideo, cacheDir);
85-
cacheFactory('synonym', organism, ideo, cacheDir);
86-
cacheFactory('tissue', organism, ideo, cacheDir);
87-
cacheFactory('variant', organism, ideo, cacheDir);
84+
cacheFactory('geneStructure', organism, config, cacheDir);
85+
cacheFactory('protein', organism, config, cacheDir);
86+
cacheFactory('synonym', organism, config, cacheDir);
87+
cacheFactory('tissue', organism, config, cacheDir);
88+
if (config.showVariantInTooltip) {
89+
cacheFactory('variant', organism, config, cacheDir);
90+
}
8891
}
8992
}
9093
}
@@ -140,14 +143,14 @@ const allCacheProps = {
140143
}
141144
};
142145

143-
function setGeneCache(parsedCache, ideo) {
146+
function setGeneCache(parsedCache) {
144147
const [
145148
interestingNames, nameCaseMap, namesById, fullNamesById,
146149
idsByName, lociByName, lociById
147150
//, sortedAnnots
148151
] = parsedCache;
149152

150-
ideo.geneCache = {
153+
Ideogram.geneCache = {
151154
interestingNames, // Array ordered by general or scholarly interest
152155
nameCaseMap, // Maps of lowercase gene names to proper gene names
153156
namesById,
@@ -159,46 +162,46 @@ function setGeneCache(parsedCache, ideo) {
159162
};
160163
}
161164

162-
function setParalogCache(parsedCache, ideo) {
165+
function setParalogCache(parsedCache) {
163166
const paralogsByName = parsedCache;
164167
// Array of paralog Ensembl IDs by (uppercase) gene name
165-
ideo.paralogCache = {paralogsByName};
168+
Ideogram.paralogCache = {paralogsByName};
166169
}
167170

168-
function setInteractionCache(parsedCache, ideo) {
171+
function setInteractionCache(parsedCache) {
169172
const interactionsByName = parsedCache;
170-
ideo.interactionCache = interactionsByName;
173+
Ideogram.interactionCache = interactionsByName;
171174
}
172175

173-
function setGeneStructureCache(parsedCache, ideo) {
176+
function setGeneStructureCache(parsedCache) {
174177
const featuresByGene = parsedCache;
175-
ideo.geneStructureCache = featuresByGene;
178+
Ideogram.geneStructureCache = featuresByGene;
176179
}
177180

178-
function setProteinCache(parsedCache, ideo) {
179-
ideo.proteinCache = parsedCache;
181+
function setProteinCache(parsedCache) {
182+
Ideogram.proteinCache = parsedCache;
180183
}
181184

182-
function setSynonymCache(parsedCache, ideo) {
183-
ideo.synonymCache = parsedCache;
185+
function setSynonymCache(parsedCache) {
186+
Ideogram.synonymCache = parsedCache;
184187
}
185188

186-
function setTissueCache(parsedCache, ideo) {
187-
ideo.tissueCache = parsedCache;
189+
function setTissueCache(parsedCache) {
190+
Ideogram.tissueCache = parsedCache;
188191
}
189192

190-
function setVariantCache(parsedCache, ideo) {
191-
ideo.variantCache = parsedCache;
193+
function setVariantCache(parsedCache) {
194+
Ideogram.variantCache = parsedCache;
192195
}
193196

194-
async function cacheFactory(cacheName, orgName, ideo, cacheDir=null) {
197+
async function cacheFactory(cacheName, orgName, config, cacheDir=null) {
195198

196199
const cacheProps = allCacheProps[cacheName];
197-
const debug = ideo.config.debug;
200+
const debug = config.debug;
198201

199202
/**
200-
* Fetch cached gene data, transform it usefully, and set it as ideo prop
201-
*/
203+
* Fetch cached gene data, transform it usefully, and set it as Ideogram prop
204+
*/
202205
const startTime = performance.now();
203206
let perfTimes = {};
204207

@@ -211,7 +214,6 @@ async function cacheFactory(cacheName, orgName, ideo, cacheDir=null) {
211214
// Skip initialization if cache is already populated
212215
if (Ideogram[staticProp] && Ideogram[staticProp][orgName]) {
213216
// Simplify chief use case, i.e. for single organism
214-
ideo[staticProp] = Ideogram[staticProp][orgName];
215217
return;
216218
}
217219

@@ -233,8 +235,8 @@ async function cacheFactory(cacheName, orgName, ideo, cacheDir=null) {
233235
// cacheWorker.postMessage(message);
234236
// cacheWorker.addEventListener('message', event => {
235237
// [parsedCache, perfTimes] = event.data;
236-
cacheProps.fn(parsedCache, ideo, orgName);
237-
Ideogram[staticProp][orgName] = ideo[staticProp];
238+
cacheProps.fn(parsedCache, orgName);
239+
Ideogram[staticProp][orgName] = Ideogram[staticProp];
238240

239241
if (debug) {
240242
console.timeEnd(`${cacheName}Cache total`);

src/js/init/caches/tissue-cache-worker.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,15 @@ function processIds(ids) {
2727
return processedIds;
2828
}
2929

30-
async function getTissueExpressions(gene, ideo) {
31-
const cache = ideo.tissueCache;
30+
async function getTissueExpressions(gene, config) {
31+
const cache = Ideogram.tissueCache;
3232
const byteRange = cache.byteRangesByName[gene];
3333

3434
// Easier debuggability
35-
if (!ideo.cacheRangeFetch) ideo.cacheRangeFetch = cacheRangeFetch;
35+
if (!Ideogram.cacheRangeFetch) Ideogram.cacheRangeFetch = cacheRangeFetch;
3636

3737
if (!byteRange) return null;
3838

39-
const config = ideo.config;
4039
let cacheDir = null;
4140
if (config.cacheDir) cacheDir = config.cacheDir;
4241
const cacheType = 'tissues';

src/js/init/caches/variant-cache-worker.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,11 @@ function parseVariant(line, variantCache) {
171171
async function getVariants(gene, ideo) {
172172
const variants = [];
173173

174-
const cache = ideo.variantCache;
174+
const cache = Ideogram.variantCache;
175175
const byteRange = cache.byteRangesByName[gene];
176176

177177
// Easier debuggability
178-
if (!ideo.cacheRangeFetch) ideo.cacheRangeFetch = cacheRangeFetch;
178+
if (!Ideogram.cacheRangeFetch) Ideogram.cacheRangeFetch = cacheRangeFetch;
179179

180180
if (!byteRange) return [];
181181

@@ -188,7 +188,7 @@ async function getVariants(gene, ideo) {
188188
const orgName = 'homo-sapiens';
189189
const cacheUrl = getCacheUrl(orgName, cacheDir, cacheType, extension);
190190

191-
const geneLocus = ideo.geneCache.lociByName[gene];
191+
const geneLocus = Ideogram.geneCache.lociByName[gene];
192192

193193
// Get variant data only for the requested gene
194194
const data = await cacheRangeFetch(cacheUrl, byteRange);

src/js/init/finish-init.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ function finishInit(t0) {
119119
if (config.geometry === 'collinear') collinearizeChromosomes(ideo);
120120

121121
if (ideo.config.debug) console.time('initCache: Ideogram');
122-
initCaches(ideo).then(() => {
122+
initCaches(ideo.config).then(() => {
123123
if (ideo.config.debug) console.timeEnd('initCache: Ideogram');
124124
if (ideo.onLoadCallback) ideo.onLoadCallback();
125125
});

0 commit comments

Comments
 (0)