UNPKG

ideogram

Version:

Chromosome visualization with D3.js

1,233 lines (1,005 loc) • 35.6 kB
// Most of these tests use Mocha's async support. // Helpful: // - http://martinfowler.com/articles/asyncJS.html // - https://mochajs.org/#asynchronous-code // innerHTML doesn't work for SVG in PhantomJS. This is a workaround. function getSvgText(selector) { var svgText = new XMLSerializer() .serializeToString( document.querySelector(selector) ) .split('>')[1] .split('</')[0]; return svgText; } describe("Ideogram", function() { var config = {}; d3 = Ideogram.d3; beforeEach(function() { delete window.chrBands; d3.selectAll("svg").remove(); config = { organism: "human", chrWidth: 10, chrHeight: 150, chrMargin: 10, showChromosomeLabels: true, orientation: "vertical", dataDir: '/dist/data/bands/native/' }; }); function takeScreenshot() { if (window.callPhantom) { var date = new Date() var filename = "screenshots/" + date.getTime() console.log("Taking screenshot " + filename) callPhantom({'screenshot': filename}) } } afterEach(function () { if (this.currentTest.state == 'failed') { takeScreenshot() } }) it("should have a non-body container when specified", function() { config.container = ".small-ideogram"; var ideogram = new Ideogram(config); assert.equal(ideogram.config.container, ".small-ideogram"); }); it("should write 'svg' element to DOM", function(done) { function callback() { var svg = document.getElementsByTagName("svg").length; assert.equal(svg, 1); done(); } config.onLoad = callback; var ideogram = new Ideogram(config); // var svg = document.getElementsByTagName("svg").length; // assert.equal(svg, 1); }); it("should have 24 chromosomes for a human ideogram instance", function(done) { // Tests use case from ../examples/human.html function callback() { var numChromosomes = Object.keys(ideogram.chromosomes["9606"]).length; assert.equal(numChromosomes, 24); done(); } config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should have 21 chromosomes for a mouse ideogram instance", function(done) { // Tests use case from ../examples/mouse.html function callback() { var numChromosomes = Object.keys(ideogram.chromosomes["10090"]).length; assert.equal(numChromosomes, 21); done(); } // Clears default setting from beforeEach (test artifact) delete config.organism; config.taxid = 10090; config.orientation = "horizontal"; config.chromosomes = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "X", "Y"]; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should have 4 syntenic regions for basic homology example", function(done) { // Tests use case from ../examples/homology_basic.html function callback() { var chrs = ideogram.chromosomes, chr1 = chrs["9606"]["1"], chr2 = chrs["9606"]["2"], r1Band, r2Band, r3Band, r4Band, r5Band, r6Band, range1, range2, range3, range4, range5, range6, syntenicRegions = []; r1Band = chr1.bands[2]; range1 = { chr: chr1, start: r1Band.bp.start, stop: r1Band.bp.stop }; r2Band = chr2.bands[2]; range2 = { chr: chr2, start: r2Band.bp.start, stop: r2Band.bp.stop }; // 1p11, chromosome 1 centromeric p band r3Band = chr1.bands[22]; range3 = { chr: chr1, start: r3Band.bp.start, stop: r3Band.bp.stop }; // 2p11.1, chromosome 2 centromeric p band r4Band = chr2.bands[13]; range4 = { chr: chr2, start: r4Band.bp.start, stop: r4Band.bp.stop }; // 1q12 r5Band = chr1.bands[24] range5 = { chr: chr1, start: r5Band.bp.start, stop: r5Band.bp.stop }; // 2q22 r6Band = chr2.bands[24]; range6 = { chr: chr2, start: r6Band.bp.start, stop: r6Band.bp.stop }; // 1q24 r7Band = chr1.bands[29] range7 = { chr: chr1, start: r7Band.bp.start, stop: r7Band.bp.stop }; // 2q31 - 2q33 range8 = { chr: chr2, start: chr2.bands[29].bp.start, stop: chr2.bands[33].bp.stop }; syntenicRegions.push( {"r1": range1, "r2": range2}, {"r1": range3, "r2": range4}, {"r1": range5, "r2": range6}, {"r1": range7, "r2": range8} ); ideogram.drawSynteny(syntenicRegions); var numChromosomes = Object.keys(ideogram.chromosomes["9606"]).length; assert.equal(numChromosomes, 2); var numSyntenicRegions = document.getElementsByClassName("syntenicRegion").length; assert.equal(numSyntenicRegions, 4); done(); } config.chromosomes = ["1", "2"]; config.showBandLabels = true; config.orientation = "vertical"; config.perspective = "comparative"; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should have 25 syntenic regions for advanced example", function(done) { // Tests use case from ../examples/homology_advanced.html function callback() { var chrs = ideogram.chromosomes, chr1 = chrs["10090"]["1"], chr2 = chrs["10090"]["2"], r1Band = chr1["bands"][7], r2Band = chr2["bands"][17], range1, range2, range3, range4, range5, range6, syntenicRegions = []; range1 = { chr: chr1, start: r1Band.bp.start, stop: r1Band.bp.stop }; for (var i = 1; i < 20; i++) { range2 = { chr: chr2, start: 6000000 * i, stop: 6500000 * i }; syntenicRegions.push({"r1": range1, "r2": range2, "color": "#F55"}); } var range3 = { chr: chr1, start: 125000000, stop: 126000000 }; range4 = { chr: chr2, start: 1500000 * i, stop: 3600000 * i }; syntenicRegions.push({"r1": range3, "r2": range4, "opacity": 0.7}); var range5 = { chr: chr2, start: r2Band.bp.start, stop: r2Band.bp.stop }; for (var i = 1; i < 6; i++) { range6 = { chr: chr1, start: 120000000 + (12000000 * i), stop: 120000000 + (8000000 * i) }; color = "#AAF"; if (i == 5) { color = "#DDD"; } syntenicRegions.push({"r1": range5, "r2": range6, "color": color}); } ideogram.drawSynteny(syntenicRegions); var numChromosomes = Object.keys(ideogram.chromosomes["10090"]).length; assert.equal(numChromosomes, 2); var numSyntenicRegions = document.getElementsByClassName("syntenicRegion").length; assert.equal(numSyntenicRegions, 25); var srID = '#chr1-10090_54516053_55989459___chr2-10090_114000000_123500000'; var otherSrID = '#chr1-10090_54516053_55989459___chr2-10090_108000000_117000000'; var sr = d3.select(srID); var otherSr = d3.select(otherSrID); sr.dispatch('mouseover'); var otherSrIsTranslucent = /ghost/.test(otherSr.nodes()[0].classList.value); assert.equal(otherSrIsTranslucent, true); sr.dispatch('mouseout'); sr.dispatch('click'); var otherSrIsHidden = /hidden/.test(otherSr.nodes()[0].classList.value); assert.equal(otherSrIsHidden, true); done(); } config = { taxid: 10090, chromosomes: ["1", "2"], chrWidth: 10, chrHeight: 500, chrMargin: 200, showChromosomeLabels: true, showBandLabels: true, orientation: "vertical", perspective: "comparative", dataDir: '/dist/data/bands/native/', onLoad: callback }; var ideogram = new Ideogram(config); }); it("should have 1 syntenic region between a human and a mouse chromosome", function(done) { // Tests use case from ../examples/homology_interspecies.html function callback() { // See HomoloGene entry for MTOR at // http://www.ncbi.nlm.nih.gov/homologene/3637 // Placements for H. sapiens and M. musculus used below. // Placements from latest annotation release in // Human: http://www.ncbi.nlm.nih.gov/gene/2475#genomic-context // Mouse: http://www.ncbi.nlm.nih.gov/gene/56717#genomic-context var chrs = ideogram.chromosomes, chr1 = chrs["9606"]["1"], chr4 = chrs["10090"]["4"], syntenicRegions = []; range1 = { chr: chr1, start: 11106531, stop: 11262557, orientation: "reverse" }; range2 = { chr: chr4, start: 148448582, stop: 148557685 }; syntenicRegions.push({"r1": range1, "r2": range2}); ideogram.drawSynteny(syntenicRegions); var numHumanChromosomes = Object.keys(ideogram.chromosomes["9606"]).length; assert.equal(numHumanChromosomes, 1, "numHumanChromosomes"); var numMouseChromosomes = Object.keys(ideogram.chromosomes["10090"]).length; assert.equal(numMouseChromosomes, 1, "numMouseChromosomes"); var numSyntenicRegions = document.getElementsByClassName("syntenicRegion").length; //console.log(d3.selectAll(".syntenicRegion")); console.log(document.getElementsByClassName("syntenicRegion")[0][0]); assert.equal(numSyntenicRegions, 1, "numSyntenicRegions"); done(); } config.organism = ["human", "mouse"]; config.chromosomes = { "human": ["1"], "mouse": ["4"] }; config.orientation = "vertical"; config.perspective = "comparative"; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should have 1000 annotations in basic annotations example", function(done) { // Tests use case from ../examples/annotations_basic.html function callback() { var numAnnots = document.getElementsByClassName("annot").length; assert.equal(numAnnots, 1000); done(); } config.annotationsPath = "../dist/data/annotations/1000_virtual_snvs.json"; config.onDrawAnnots = callback; var ideogram = new Ideogram(config); }); it("should have 1000 annotations in overlaid annotations example", function(done) { // Tests use case from old ../examples/annotations_overlaid.html function callback() { var numAnnots = document.getElementsByClassName("annot").length; assert.equal(numAnnots, 1000); done(); } config = { organism: "human", chrWidth: 10, chrHeight: 500, chrMargin: 5, showChromosomeLabels: true, annotationsPath: "../dist/data/annotations/1000_virtual_snvs.json", annotationsLayout: "overlay", orientation: "horizontal", dataDir: '/dist/data/bands/native/', onDrawAnnots: callback }; ideogram = new Ideogram(config); }); it("should have 10 spanning overlaid annotations in proper chromosomes", function(done) { // Tests: // * https://github.com/eweitz/ideogram/issues/65 // * https://github.com/eweitz/ideogram/issues/66 function callback() { // Correct number? var numAnnots = document.querySelectorAll(".annot").length; assert.equal(numAnnots, 10); // Correct order? var numChr20Annots = document.querySelectorAll('#chr20-9606 .annot').length; assert.equal(numChr20Annots, 1); // Spanning, not point? var chr1Annot = document.querySelectorAll('#chr1-9606 .annot')[0]; var chr1AnnotWidth = chr1Annot.getBBox().width; assert.isAbove(chr1AnnotWidth, 3); done(); } config = { organism: "human", annotationsPath: "../dist/data/annotations/10_virtual_cnvs.json", annotationsLayout: "overlay", orientation: "horizontal", dataDir: '/dist/data/bands/native/', onDrawAnnots: callback }; ideogram = new Ideogram(config); }); it("should have 1000 annotations and 5 tracks in tracks annotations example", function(done) { // Tests use case from ../examples/annotations_tracks.html // TODO: Add class to annots indicating track function callback() { var numAnnots = document.getElementsByClassName("annot").length; assert.equal(numAnnots, 1000); done(); } var annotationTracks = [ {"id": "pathogenicTrack", "displayName": "Pathogenic", "color": "#F00"}, {"id": "likelyPathogenicTrack", "displayName": "Likely pathogenic", "color": "#DB9"}, {"id": "uncertainSignificanceTrack", "displayName": "Uncertain significance", "color": "#CCC"}, {"id": "likelyBenignTrack", "displayName": "Likely benign", "color": "#BD9"}, {"id": "benignTrack", "displayName": "Benign", "color": "#8D4"} ] var config = { taxid: 9606, chrWidth: 8, chrHeight: 500, chrMargin: 10, showChromosomeLabels: true, annotationsPath: "../dist/data/annotations/1000_virtual_snvs.json", annotationTracks: annotationTracks, annotationHeight: 2.5, orientation: "vertical", dataDir: '/dist/data/bands/native/', onDrawAnnots: callback }; ideogram = new Ideogram(config); }); it("should have 2015 annotations in histogram annotations example", function(done) { // Tests use case from ../examples/annotations_histogram.html // TODO: Add class to annots indicating track function callback() { var numAnnots = document.getElementsByClassName("annot").length; assert.equal(numAnnots, 2015); done(); } var config = { organism: "human", chrWidth: 10, chrHeight: 500, chrMargin: 10, showChromosomeLabels: true, annotationsPath: "../dist/data/annotations/all_human_genes.json", annotationsLayout: "histogram", barWidth: 3, orientation: "vertical", dataDir: '/dist/data/bands/native/', onDrawAnnots: callback }; ideogram = new Ideogram(config); }); it("should have 114 annotations for BED file at remote URL", function(done) { // Tests use case from ../examples/annotations_file_url.html function callback() { var numAnnots = document.getElementsByClassName("annot").length; assert.equal(numAnnots, 114); done(); } var config = { organism: 'human', assembly: 'GRCh37', annotationsPath: 'https://raw.githubusercontent.com/NCBI-Hackathons/Scan2CNV/master/files/201113910010_R08C02.PennCnvOut.bed', dataDir: '/dist/data/bands/native/', onDrawAnnots: callback }; ideogram = new Ideogram(config); }); it("should have 10 annotations for native annots at remote URL", function(done) { // Tests use case from ../examples/annotations_file_url.html function callback() { var numAnnots = document.getElementsByClassName("annot").length; assert.equal(numAnnots, 10); done(); } var config = { organism: 'human', chrHeight: 300, chrMargin: 2, annotationsPath: 'https://unpkg.com/ideogram@0.9.0/dist/data/annotations/10_virtual_cnvs.json', annotationsLayout: 'overlay', orientation: 'horizontal', dataDir: '/dist/data/bands/native/', onDrawAnnots: callback }; ideogram = new Ideogram(config); }); it("should have histogram bars roughly flush with chromosome ends", function(done) { // Tests use case from ../examples/annotations_histogram.html // TODO: Add class to annots indicating track function getTerEnd(arm) { // Helper function to get the x coordinate of the outermost // edge of the p or q arm of chromosome 1 var armIndex = (arm === 'p') ? 1 : 2, ter = d3.selectAll('.chromosome-border path:nth-child(' + armIndex + ')'), terBox = ter.nodes()[0].getBBox(), terX = terBox.x, terWidth = terBox.width, terEnd, inst = ter.attr('d').split(' '), // Path instructions in description ('d') terCurve = parseInt(inst[4].replace('Q', '').split(',')[0]), terCurveX = parseInt(inst[0].replace('M', '').split(',')[0]), terStroke = parseFloat(ter.style("stroke-width").slice(0, -2)); if (arm === 'p') { terEnd = terCurve; } else { terEnd = terCurve + terCurveX - terStroke; } terEnd = terEnd.toFixed(2); return terEnd; } function onIdeogramLoadAnnots() { var pterEnd = getTerEnd("p"), firstAnnotEnd = d3.selectAll("#chr1-9606 .annot").nodes()[0].getBBox().x, qterEnd = getTerEnd("q"), tmp = d3.selectAll("#chr1-9606 .annot").nodes(), tmp = tmp[tmp.length - 1].getBBox(), bump = ideogram.bump, lastAnnotEnd = tmp.x + tmp.width; // console.log("pterEnd - firstAnnotEnd: " + (pterEnd - firstAnnotEnd)); // console.log("qterEnd - lastAnnotEnd: " + (qterEnd - lastAnnotEnd)); assert.isBelow(pterEnd - firstAnnotEnd - bump, 3); assert.isAbove(qterEnd - lastAnnotEnd - bump, -20); done(); } var config = { organism: "human", chrWidth: 10, chrHeight: 500, chrMargin: 10, showChromosomeLabels: true, annotationsPath: "../dist/data/annotations/all_human_genes.json", annotationsLayout: "histogram", barWidth: 3, orientation: "vertical", dataDir: '/dist/data/bands/native/', onDrawAnnots: onIdeogramLoadAnnots }; ideogram = new Ideogram(config); }); it("should have 12 chromosomes per row in small layout example", function(done) { // Tests use case from ../examples/layout_small.html function callback() { t1 = d3.select("#chr12-9606-chromosome-set").attr("transform"); t2 = d3.select("#chr13-9606-chromosome-set").attr("transform"); lastChrRow1Y = parseInt(t1.split('translate(')[1].split(',')[0], 10); firstChrRow2Y = parseInt(t2.split('translate(')[1].split(',')[0], 10); assert.isTrue(firstChrRow2Y > lastChrRow1Y + config.chrHeight); done(); } document.getElementsByTagName("body")[0].innerHTML += '<div class="small-ideogram"></div>'; var config = { container: ".small-ideogram", organism: "human", resolution: 550, chrWidth: 10, chrHeight: 150, chrMargin: 10, rows: 2, showChromosomeLabels: true, orientation: "vertical", dataDir: '/dist/data/bands/native/' }; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should use GRCh37 when specified in 'assembly' parameter", function(done) { // Tests use case from ../examples/human.html function callback() { var bands = ideogram.chromosomes["9606"]["1"]["bands"] var chr1Length = bands[bands.length - 1].bp.stop; assert.equal(chr1Length, 249250621); done(); } config.assembly = "GRCh37"; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should use GCF_000001405.12 when specified in 'assembly' parameter", function(done) { // Tests use case from ../examples/human.html with NCBI36 / hg18 function callback() { var bands = ideogram.chromosomes["9606"]["1"]["bands"] var chr1Length = bands[bands.length - 1].bp.stop; assert.equal(chr1Length, 247249719); done(); } config.assembly = "GCF_000001405.12"; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should support RefSeq accessions in 'assembly' parameter", function(done) { // Tests use case for non-default assemblies. // GCF_000306695.2 is commonly called CHM1_1.1 // https://www.ncbi.nlm.nih.gov/assembly/GCF_000306695.2/ function callback() { var chr1Length = ideogram.chromosomes["9606"]["1"].length // For reference, see length section of LOCUS field in GenBank record at // https://www.ncbi.nlm.nih.gov/nuccore/CM001609.2 assert.equal(chr1Length, 250522664); done(); } config.assembly = "GCF_000306695.2"; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should support GenBank accessions in 'assembly' parameter", function(done) { // Tests use case for non-default assemblies. // GCA_000002125.2 is commonly called HuRef // https://www.ncbi.nlm.nih.gov/assembly/GCA_000002125.2 function callback() { var chr1Length = ideogram.chromosomes["9606"]["1"].length // For reference, see length section of LOCUS field in GenBank record at // https://www.ncbi.nlm.nih.gov/nuccore/CM001609.2 assert.equal(chr1Length, 219475005); done(); } config.assembly = "GCA_000002125.2"; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should handle arrayed objects in 'annotations' parameter", function(done) { // Tests use case from ../examples/human.html function callback() { var numAnnots = d3.selectAll(".annot").nodes().length; assert.equal(numAnnots, 1); done(); } config.annotations = [{ "name": "BRCA1", "chr": "17", "start": 43044294, "stop": 43125482 }]; config.onDrawAnnots = callback; var ideogram = new Ideogram(config); }); it("should create a brush when specified", function(done) { // Tests use case from ../examples/brush.html function callback() { assert.equal(ideogram.selectedRegion.from, 7637454); assert.equal(ideogram.selectedRegion.to, 12390477); assert.equal(ideogram.selectedRegion.extent, 4753023); assert.equal(d3.selectAll('.selection').nodes().length, 1); done(); } var config = { organism: 'human', chromosome: '19', brush: true, chrHeight: 900, orientation: 'horizontal', onBrushMove: callback, // placeholder onLoad: callback, dataDir: '/dist/data/bands/native/' }; var ideogram = new Ideogram(config); }); // TODO: Re-enable when there is a decent package that enables // PhantomJS-like screenshots from automated tests // cf.: // if (window.callPhantom) { // callPhantom({'screenshot': filename}) // // it("should align chr. label with thick horizontal chromosome", function(done) { // // Tests use case from ../examples/annotations_basic.html // // function callback() { // var band, bandMiddle, // chrLabel, chrLabelMiddle; // // band = d3.selectAll(".chromosome .band").nodes()[0].getBoundingClientRect(); // chrLabel = d3.selectAll(".chromosome-set-label").nodes()[0].getBoundingClientRect(); // // bandMiddle = band.top + band.height/2; // chrLabelMiddle = chrLabel.top + chrLabel.height/2; // // labelsDiff = Math.abs(bandMiddle - chrLabelMiddle); // // assert.isAtMost(labelsDiff, 1); // done(); // } // // config = { // organism: "human", // chrHeight: 600, // chrWidth: 20, // orientation: "horizontal", // chromosomes: ["17"], // annotations: [{ // "name": "BRCA1", // "chr": "17", // "start": 43044294, // "stop": 43125482 // }], // annotationHeight: 6 // }; // config.onDrawAnnots = callback; // var ideogram = new Ideogram(config); // }); it("should align chr. label with vertical chromosome", function(done) { // Tests use case from ../examples/human.html function callback() { var band, bandMiddle, chrLabel, chrLabelMiddle; band = d3.selectAll(".chromosome .band").nodes()[0].getBoundingClientRect(); chrLabel = d3.selectAll(".chromosome-set-label").nodes()[0].getBoundingClientRect(); bandMiddle = band.left + band.width/2; chrLabelMiddle = chrLabel.left + chrLabel.width/2; labelsDiff = Math.abs(bandMiddle - chrLabelMiddle); assert.isAtMost(labelsDiff, 1); done(); } var annotationTracks = [ {"id": "pathogenicTrack", "displayName": "Pathogenic", "color": "#F00"}, {"id": "likelyPathogenicTrack", "displayName": "Likely pathogenic", "color": "#DB9"}, {"id": "uncertainSignificanceTrack", "displayName": "Uncertain significance", "color": "#CCC"}, {"id": "likelyBenignTrack", "displayName": "Likely benign", "color": "#BD9"}, {"id": "benignTrack", "displayName": "Benign", "color": "#8D4"} ] var config = { organism: "human", chrWidth: 20, chrHeight: 500, annotationsPath: "../dist/data/annotations/1000_virtual_snvs.json", annotationTracks: annotationTracks, annotationHeight: 2.5, dataDir: '/dist/data/bands/native/' }; config.onDrawAnnots = callback; var ideogram = new Ideogram(config); }); it("should show three human genomes in one page", function(done) { // Tests use case from ../examples/multiple_trio.html var config, containerIDs, id, i, container, ideogramsLoaded = 0; function callback() { var numChromosomes; ideogramsLoaded += 1; if (ideogramsLoaded === 3) { numChromosomes = document.querySelectorAll('.chromosome').length; assert.equal(numChromosomes, 24*3); done(); } } config = { organism: "human", chrHeight: 125, resolution: 400, orientation: "vertical", dataDir: '/dist/data/bands/native/', onLoad: callback }; containerIDs = ["mother", "father", "proband"]; for (i = 0; i < containerIDs.length; i++) { id = containerIDs[i]; container = '<div id="' + id + '"></div>'; document.querySelector("body").innerHTML += container; config.container = "#" + id; new Ideogram(config); } }); it("should show three unbanded primated genomes in one page", function(done) { // Tests use case from ../examples/multiple_primates.html var config, containerIDs, id, i, container, ideogramsLoaded = 0; function callback() { var numChromosomes; ideogramsLoaded += 1; if (ideogramsLoaded === 3) { numChromosomes = document.querySelectorAll('.chromosome').length; assert.equal(numChromosomes, 24+25+21); done(); } } config = { chrHeight: 250, chrMargin: 2, orientation: "horizontal", showFullyBanded: false, dataDir: '/dist/data/bands/native/', onLoad: callback }; containerIDs = ["homo-sapiens", "pan-troglodytes", "macaca-fascicularis"]; for (i = 0; i < containerIDs.length; i++) { id = containerIDs[i]; container = '<div id="' + id + '"></div>'; document.querySelector("body").innerHTML += container; config.container = "#" + id; config.organism = id; new Ideogram(config); } }); it("should show XX chromosomes for a diploid human female", function(done) { // Tests use case from ../examples/ploidy_basic.html function callback() { var selector = '#chrX-9606-chromosome-set .chromosome-set-label tspan'; var chrSetLabel = getSvgText(selector); assert.equal(chrSetLabel, 'XX'); done(); } var config = { organism: "human", sex: "female", chrHeight: 300, chrWidth: 8, ploidy: 2, dataDir: '/dist/data/bands/native/', onLoad: callback }; var ideogram = new Ideogram(config); }); it("should show XY chromosomes for a diploid human male", function(done) { // Tests use case from ../examples/ploidy_basic.html function callback() { var selector = '#chrX-9606-chromosome-set .chromosome-set-label tspan'; var chrSetLabel = getSvgText(selector); assert.equal(chrSetLabel, 'XY'); done(); } var config = { organism: "human", sex: "male", chrHeight: 300, chrWidth: 8, ploidy: 2, dataDir: '/dist/data/bands/native/', onLoad: callback }; var ideogram = new Ideogram(config); }); it("should omit Y chromosome in haploid human female", function(done) { function callback() { var hasChrY = d3.selectAll('#chrY-9606').nodes().length >= 1; assert.isFalse(hasChrY); done(); } var config = { organism: "human", sex: "female", dataDir: '/dist/data/bands/native/' }; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should support using NCBI Taxonomy ID in 'organism' option", function(done) { function callback() { var numChromosomes = Object.keys(ideogram.chromosomes[9606]).length; assert.equal(numChromosomes, 24); done(); } var config = { organism: 9606, dataDir: '/dist/data/bands/native/' }; config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should handle toggling single- and multi-chromosome view, in horizontal orientation", function(done) { function callback() { d3.select('#chr1-9606').dispatch('click'); var shownChrs = d3.selectAll('.chromosome').nodes().filter(function(d) { return d.style.display !== 'none'; }); var shownChrID = shownChrs[0].id; assert.equal(shownChrs.length, 1); assert.equal(shownChrID, 'chr1-9606'); d3.select('#chr1-9606').dispatch('click'); setTimeout(function() { var shownChrs = d3.selectAll('.chromosome').nodes().filter(function(d) { return d.style.display !== 'none'; }); assert.equal(shownChrs.length, 24); done(); }, 500); } config.onLoad = callback; var ideogram = new Ideogram(config); }); it("should handle toggling single- and multi-chromosome view, in horizontal orientation", function(done) { function callback() { d3.select('#chr1-9606').dispatch('click'); var shownChrs = d3.selectAll('.chromosome').nodes().filter(function(d) { return d.style.display !== 'none'; }); var shownChrID = shownChrs[0].id; assert.equal(shownChrs.length, 1); assert.equal(shownChrID, 'chr1-9606'); d3.select('#chr1-9606').dispatch('click'); setTimeout(function() { var shownChrs = d3.selectAll('.chromosome').nodes().filter(function(d) { return d.style.display !== 'none'; }); assert.equal(shownChrs.length, 24); done(); }, 500); } config.onLoad = callback; config.orientation = 'horizontal'; var ideogram = new Ideogram(config); }); it("should depict chromosomal rearrangements", function(done) { // Covers case in ../examples/ploidy_rearrangements.html function callback() { // TODO: There shouldn't be multiple elements with the same id var lastCopyChr1 = d3.selectAll('#chr1-4641').nodes().slice(-1)[0]; lastCopyChr1Fill = d3.select(lastCopyChr1).select('.p-band').nodes()[0].style.fill; assert.equal(lastCopyChr1Fill, 'transparent'); done() } function initIdeo() { if (typeof bandTimeout !== 'undefined') { window.clearTimeout(bandTimeout); } var config = { organism: "banana", orientation: "horizontal", ploidy: 3, ancestors: { "A": "#dea673", "B": "#7396be" }, ploidyDesc: [ {'AABB': ['11', '11', '11', '02']}, {'AAB': ['01', '11', '11']}, 'BAB', {'AABB': ['11', '11', '11', '20']}, 'AAB', 'BBB', {'AAB': ['01', '11', '11']}, 'AAB', 'AAB', 'AAB', 'AAB' ] }; config.onLoad = callback; var ideogram = new Ideogram(config); } d3.select('body') .append('script') .attr('src', '/dist/data/bands/native/banana.js'); // Check for banana.js content every 50 ms. // If/when that content exists, initialize ideogram. (function checkBandData() { window.bandTimeout = setTimeout(function () { if (typeof(window.chrBands) === 'undefined') { checkBandData(); } else { initIdeo(); } }, 50); })(); }); it("should depict chromosomal rangesets", function(done) { // Covers case in ../examples/ploidy_recombination.html function callback() { // TODO: There shouldn't be multiple elements with the same id var numRangeSets = d3.selectAll('.range-set rect').nodes().length; assert.equal(numRangeSets, 6); done(); } function initIdeo() { var config = { organism: "banana", orientation: "horizontal", ploidy: 3, chrMargin: 10, ancestors: { "A": "#dea673", "B": "#7396be" }, ploidyDesc: [ 'AAB', 'AAB', 'BAB', 'AAB', 'AAB', 'BBB', 'AAB', 'AAB', 'AAB', 'AAB', 'AAB' ], rangeSet: [{ chr: 1, ploidy: [0, 1, 0], start: 17120000, stop: 25120000, color: [0, '#7396be', 0,] }, { chr: 2, ploidy: [0, 1, 1], start: 12120000, stop: 15120000, color: [0, '#7396be', '#dea673'] }] }; config.onLoad = callback; config.debug = true; var ideogram = new Ideogram(config); } d3.select('body') .append('script') .attr('src', '/dist/data/bands/native/banana.js'); // Check for banana.js content every 50 ms. // If/when that content exists, initialize ideogram. (function checkBandData() { window.bandTimeout = setTimeout(function () { if (typeof(window.chrBands) === 'undefined') { checkBandData(); } else { initIdeo(); } }, 50); })(); }); // it("should align chr. label with band-labeled vertical chromosome", function(done) { // // Tests use case from ../examples/human.html // // function callback() { // // var band, bandMiddle, // chrLabel, chrLabelMiddle; // // band = d3.select(".chromosome .band").nodes()[0].getBoundingClientRect(); // chrLabel = d3.select(".chromosome .chrLabel").nodes()[0].getBoundingClientRect(); // // bandMiddle = band.left + band.width/2; // chrLabelMiddle = chrLabel.left + chrLabel.width/2; // // labelsDiff = Math.abs(bandMiddle - chrLabelMiddle); // // assert.isAtMost(labelsDiff, 1); // done(); // } // // var config = { // organism: "human", // showBandLabels: true, // chrHeight: 500 // }; // config.onLoad = callback; // var ideogram = new Ideogram(config); // }); });