UNPKG

ideogram

Version:

Chromosome visualization for the web

315 lines (275 loc) 10.5 kB
<!DOCTYPE html> <html> <head> <title>Paralogs | Ideogram</title> <style> body {font: 14px Arial; line-height: 19.6px; padding: 0 15px;} a, a:visited {text-decoration: none;} a:hover {text-decoration: underline;} a, a:hover, a:visited, a:active {color: #0366d6;} select, optgroup, option { float: left; font-size: 14px; } #ideogram-container {z-index: -1} #search-container { height: 26px; float: left; position: relative; top: -4px; margin-left: 10px; } #search-genes { padding-left: 3px; width: 200px; height: 20px; font-size: 14px; border-radius: 3px; border: 1px solid #888; } #search-button { height: 21px; width: 23px; font-size: 24px; background: #58F; color: #FFF; display: inline-block; position: relative; top: 3px; left: -25px; border-radius: 3px; text-align: center; padding-top: 3px; cursor: pointer; } #ideogram .annot path { cursor: pointer; } #ideogram .chromosome { cursor: default; } </style> <script type="text/javascript" src="../../dist/js/ideogram.min.js"></script> <link rel="icon" type="image/x-icon" href="img/ideogram_favicon.ico"> </head> <body> <h1>Paralogs | Ideogram</h1> <a href="../">Overview</a> | <a href="multiple-primates">Previous</a> | <a href="mouse">Next</a> | <a href="https://github.com/eweitz/ideogram/blob/gh-pages/paralogs.html" target="_blank">Source</a> <p> Find evolutionarily similar genes across the genome. See also <a href="orthologs">Orthologs</a>. </p> <div> <select> <optgroup label="Model organisms"> <option value="homo-sapiens" selected>Human (Homo sapiens)</option> <option value="mus-musculus">Mouse (Mus musculus)</option> <option value="rattus-norvegicus">Rat (Rattus norvegicus)</option> <!-- <option value="drosophila-melanogaster">Fly (Drosophila melanogaster)</option> --> <!-- <option value="caenorhabditis-elegans">Worm (Caenorhabditis elegans)</option> --> <option value="danio-rerio">Zebrafish (Danio rerio)</option> <!-- <option value="arabidopsis-thaliana">Thale cress (Arabidopsis thaliana)</option> --> <!-- <option value="saccharomyces-cerevisiae">Yeast (Saccharomyces cerevisiae)</option> --> </optgroup> <optgroup label="Vertebrates"> <option value="pan-troglodytes">Chimpanzee (Pan troglodytes)</option> <option value="macaca-mulatta">Macaque (Macaca mulatta)</option> <option value="macaca-fascicularis">Crab-eating macaque (Macaca fascicularis)</option> <option value="felis-catus">Cat (Felis catus)</option> <option value="canis-lupus-familiaris">Dog (Canis lupus familiaris)</option> <option value="equus-caballus">Horse (Horse)</option> <option value="bos-taurus">Cow (Bos taurus)</option> <option value="sus-scrofa">Pig (Sus scrofa)</option> <!-- <option value="petromyzon-marinus">Lamprey (Petromyzon marinus)</option> --> </optgroup> <!-- <optgroup label="Plants"> <option value="zea-mays">Maize (Zea mays)</option> <option value="oryza-sativa">Rice (Oryza sativa)</option> <option value="solanum-lycopersicum">Tomato (Solanum lycopersicum)</option> <option value="musa-acuminata">Banana (Musa acuminata)</option> <option value="vitis-vinifera">Grape (Vitis vinifera)</option> <option value="micromonas-commoda">Green algae (Micromonas commoda)</option> </optgroup> <optgroup label="Insects"> <option value="anopheles-gambiae">Mosquito (Anopheles gambiae)</option> </optgroup> <optgroup label="Protozoa"> <option value="plasmodium falciparum">Malaria parasite (Plasmodium falciparum)</option> <option value="leishmania donovani">Leishmania parasite (Leishmania donovani)</option> </optgroup> --> </select> </div> <div style="float: left; width: 350px;"> <label for="search-genes" id="search-container"> <input id="search-genes" autocomplete="off" placeholder="Search genes (e.g. RAD51)"/> <span id="search-button">&#x2315;</span> </label> </div> <br/><br/><br/> <div id="ideogram-container"></div> <script type="text/javascript"> function parseUrlParams() { var rawParams = document.location.search; var urlParams = {}; var param, key, value; if (rawParams !== '') { rawParams = rawParams.split('?')[1].split('&'); rawParams.forEach(rawParam => { param = rawParam.split('='); key = param[0]; value = param[1]; urlParams[key] = value; }); } return urlParams; } function handleOrganism() { document.querySelector('#search-genes').value = ''; var selectedOrg = document.querySelector('option:checked').text; selectedOrg = selectedOrg.split('(')[1].split(')')[0].toLowerCase(); config.organism = selectedOrg; var banded = !['homo sapiens', 'mus musculus'].includes(selectedOrg); config.showFullyBanded = banded; ideogram = new Ideogram(config); } async function fetchEnsembl(path, body=null, method='GET') { let init = { method: method, headers: {'Content-Type': 'application/json'} } if (body !== null) init.body = JSON.stringify(body); const response = await fetch(`https://rest.ensembl.org${path}`, init); const json = await response.json(); return json; } /** * Fetch paralogs of searched gene */ async function fetchParalogPositions(annot, annots) { const taxid = ideogram.config.taxid; const orgUnderscored = ideogram.config.organism.replace(/[ -]/g, '_'); const params = `&format=condensed&type=paralogues&target_taxon=${taxid}`; let path = `/homology/id/${annot.id}?${params}` const ensemblHomologs = await fetchEnsembl(path); const homologs = ensemblHomologs.data[0].homologies; // Fetch positions of paralogs homologIds = homologs.map(homolog => homolog.id) path = '/lookup/id/' + orgUnderscored; let body = { 'ids': homologIds, 'species': orgUnderscored, 'object_type': 'gene' } const ensemblHomologGenes = await fetchEnsembl(path, body, 'POST'); Object.entries(ensemblHomologGenes).map((idGene, i) => { let gene = idGene[1] annot = { name: gene.display_name, chr: gene.seq_region_name, start: gene.start, stop: gene.end, id: gene.id, shape: 'triangle', color: 'pink', height: 3 }; // Add to start of array, so searched gene gets top z-index annots.unshift(annot); annotDescriptions[annot.name] = gene.description; }) return annots; } annotDescriptions = {} async function searchGenes(geneSymbols) { // Refine style document.querySelectorAll('.chromosome').forEach(chromosome => { chromosome.style.cursor = ''; }) const lastChr = [...document.querySelectorAll('.chromosome-set')].slice(-1)[0] const left = lastChr.getBoundingClientRect().x; const topPx = ideogram.config.chrHeight + 40; const style = `float: left; position: relative; top: -${topPx}px; left: ${left}px;`; // Fetch positon of searched gene const orgUnderscored = ideogram.config.organism.replace(/[ -]/g, '_'); let path = '/lookup/symbol/' + orgUnderscored; let body = {'symbols': geneSymbols} const ensemblGenes = await fetchEnsembl(path, body, 'POST'); let annots = [] geneSymbols.forEach(async geneSymbol => { let gene = ensemblGenes[geneSymbol] let annot = { name: gene.display_name, id: gene.id, chr: gene.seq_region_name, start: gene.start, stop: gene.end, shape: 'triangle', color: 'red' }; annots.push(annot); annotDescriptions[annot.name] = gene.description; annots = await fetchParalogPositions(annot, annots) // More notable genes tend to have shorter names. // This helps ensure such genes appear atop overlapping annotations. annots.sort((a, b) => { return b.name.length - a.name.length }) ideogram.drawAnnots(annots); document.querySelector('#_ideogramLegend').style = style; }); ideogram.drawAnnots(annots); document.querySelector('#_ideogramLegend').style = 'display: none;'; } // Process text input for the "Search" field. function handleSearch(event) { // Ignore non-"Enter" keyups if (event.type === 'keyup' && event.keyCode !== 13) return; var searchInput = event.target.value.trim(); // Handles "BRCA1,BRCA2", "BRCA1 BRCA2", and "BRCA1, BRCA2" let geneSymbols = searchInput.split(/[, ]/).filter(d => d !== '') searchGenes(geneSymbols); } function onClickAnnot(annot) { searchGenes([annot.name]); } var urlParams = parseUrlParams(); var organism = 'org' in urlParams ? urlParams.org : 'homo-sapiens'; document.querySelector('#search-button').addEventListener('click', handleSearch); document.querySelector('#search-genes').addEventListener('keyup', handleSearch); document.querySelector('select').addEventListener('change', handleOrganism); const shape = 'triangle'; var legend = [{ name: 'Click paralog to search', rows: [ {name: 'Paralog', color: 'pink', shape: shape}, {name: 'Searched gene', color: 'red', shape: shape} ] }]; function decorateGene(annot) { var org = ideogram.getScientificName(ideogram.config.taxid); var term = `(${annot.name}[gene])+AND+(${org}[orgn])`; var url = `https://ncbi.nlm.nih.gov/gene/?term=${term}`; var description = annotDescriptions[annot.name].split(' [')[0]; annot.displayName = `<a target="_blank" href="${url}">${annot.name}</a> <br/> ${description}`; return annot } config = { organism: organism, chrWidth: 8, chrHeight: 90, chrLabelSize: 10, annotationHeight: 5, showFullyBanded: false, rotatable: false, legend: legend, onClickAnnot: onClickAnnot, onWillShowAnnotTooltip: decorateGene } var ideogram = new Ideogram(config); </script> </body> </html>