UNPKG

ideogram

Version:

Chromosome visualization for the web

132 lines (114 loc) 4.07 kB
import { fetchAndParse, getFullId, inspectWorker, cacheFetch, cacheRangeFetch, getCacheUrl } from './cache-lib'; function parseTissueKeys(rawTissuesString) { const tissueNames = []; const tissueColors = []; const tissueSamples = []; rawTissuesString.split(';').forEach(entry => { const splitEntry = entry.split(','); tissueNames.push(splitEntry[0]); tissueColors.push(splitEntry[1]); tissueSamples.push(splitEntry[2]); }); return [tissueNames, tissueColors, tissueSamples]; } /** Transform a stringified list of integers into an actual list of integers */ function processIds(ids) { const processedIds = []; const splitIds = ids.split(','); for (let i = 0; i < splitIds.length; i++) { processedIds.push(parseInt(splitIds[i], 10)); } return processedIds; } async function getTissueExpressions(gene, config) { const cache = Ideogram.tissueCache; const byteRange = cache.byteRangesByName[gene]; // Easier debuggability if (!Ideogram.cacheRangeFetch) Ideogram.cacheRangeFetch = cacheRangeFetch; if (!byteRange) return null; let cacheDir = null; if (config.cacheDir) cacheDir = config.cacheDir; const cacheType = 'tissues'; const extension = 'tsv'; const orgName = 'homo-sapiens'; const cacheUrl = getCacheUrl(orgName, cacheDir, cacheType, extension); const geneDataLine = await cacheRangeFetch(cacheUrl, byteRange); const tissueExpressions = []; const rawExpressions = geneDataLine.split('\t').slice(1); for (let i = 0; i < rawExpressions.length; i++) { const rawValues = rawExpressions[i].split(';').map( v => v === '' ? 0 : v // inflate empty string to 0-integer ); const numValues = rawValues.length; if (numValues === 15) { rawValues.splice(1, 0, 0); // Insert number 0 at position 1 } else if (numValues === 14) { // Min. and Q1 are 0 rawValues.splice(1, 0, 0); rawValues.splice(1, 0, 0); } else if (numValues === 13) { // Min., Q1, and median are 0 rawValues.splice(1, 0, 0); rawValues.splice(1, 0, 0); rawValues.splice(1, 0, 0); } const tissueId = rawValues[0]; const boxMetrics = rawValues.slice(1, 6); const min = parseFloat(boxMetrics[0]); const q1 = parseFloat(boxMetrics[1]); const median = parseFloat(boxMetrics[2]); const q3 = parseFloat(boxMetrics[3]); const max = parseFloat(boxMetrics[4]); const quantiles = rawValues.slice(6).map(v => parseInt(v)); const expression = { min, q1, median, q3, max, quantiles }; const tissue = cache.tissueNames[tissueId]; const color = cache.tissueColors[tissueId]; const samples = parseInt(cache.tissueSamples[tissueId]); tissueExpressions.push({tissue, expression, color, samples}); } return tissueExpressions; } /** Parse a tissue cache TSV file */ export function parseTissueCache(rawTsv, perfTimes, byteRangesByName) { let tissueNames; let tissueColors; let tissueSamples; let t0 = performance.now(); const lines = rawTsv.split(/\r\n|\n/); perfTimes.rawTsvSplit = Math.round(performance.now() - t0); t0 = performance.now(); for (let i = 0; i < lines.length; i++) { const line = lines[i]; if (line === '') continue; // Skip empty lines if (line[0] === '#') { if (line.slice(0, 10) === '## tissues') { const parsedTissueKeys = parseTissueKeys(line.split('tissues: ')[1]); [tissueNames, tissueColors, tissueSamples] = parsedTissueKeys; } continue; } }; const t1 = performance.now(); perfTimes.parseCacheLoop = Math.round(t1 - t0); return { getTissueExpressions, byteRangesByName, tissueNames, tissueColors, tissueSamples }; } // Uncomment when workers work outside localhost // addEventListener('message', async event => { // console.time('tissueCacheWorker'); // const [cacheUrl, perfTimes, debug] = event.data; // const result = await fetchAndParse(cacheUrl, perfTimes, parseCache); // postMessage(result); // if (debug) inspectWorker('paralog', result[0]); // });