diff --git a/client/__tests__/e2e/data.js b/client/__tests__/e2e/data.js index da29f59e..204cb566 100644 --- a/client/__tests__/e2e/data.js +++ b/client/__tests__/e2e/data.js @@ -41,7 +41,7 @@ export const datasets = { { metadata: "n_genes", "coordinates-as-percent": { x1: 0.25, y1: 0.5, x2: 0.55, y2: 0.5 }, - count: "1537" + count: "1552" } ] }, diff --git a/client/__tests__/e2e/e2e.test.js b/client/__tests__/e2e/e2e.test.js index 783e8f31..a53c4ab0 100644 --- a/client/__tests__/e2e/e2e.test.js +++ b/client/__tests__/e2e/e2e.test.js @@ -126,12 +126,12 @@ describe("cell selection", () => { test("selects cells via continuous", async () => { for (const cellset of data.cellsets.continuous) { - const histId = `histogram-${cellset.metadata}-plot-brush`; + const histBrushableAreaId = `histogram-${cellset.metadata}-plot-brushable-area`; const coords = await cxgActions.calcDragCoordinates( - histId, + histBrushableAreaId, cellset["coordinates-as-percent"] ); - await cxgActions.drag(histId, coords.start, coords.end); + await cxgActions.drag(histBrushableAreaId, coords.start, coords.end); const cellCount = await cxgActions.cellSet(1); expect(cellCount).toBe(cellset.count); } @@ -280,12 +280,12 @@ describe("scatter plot", () => { describe("clipping", () => { test("clip continuous", async () => { await cxgActions.clip(data.clip.min, data.clip.max); - const histId = `histogram-${data.clip.metadata}-plot-brush`; + const histBrushableAreaId = `histogram-${data.clip.metadata}-plot-brushable-area`; const coords = await cxgActions.calcDragCoordinates( - histId, + histBrushableAreaId, data.clip["coordinates-as-percent"] ); - await cxgActions.drag(histId, coords.start, coords.end); + await cxgActions.drag(histBrushableAreaId, coords.start, coords.end); const cellCount = await cxgActions.cellSet(1); expect(cellCount).toBe(data.clip.count); }); @@ -295,12 +295,12 @@ describe("clipping", () => { await page.keyboard.press("Enter"); await page.waitForSelector(`[data-testid='histogram-${data.clip.gene}']`); await cxgActions.clip(data.clip.min, data.clip.max); - const histId = `histogram-${data.clip.gene}-plot-brush`; + const histBrushableAreaId = `histogram-${data.clip.gene}-plot-brushable-area`; const coords = await cxgActions.calcDragCoordinates( - histId, + histBrushableAreaId, data.clip["coordinates-as-percent"] ); - await cxgActions.drag(histId, coords.start, coords.end); + await cxgActions.drag(histBrushableAreaId, coords.start, coords.end); const cellCount = await cxgActions.cellSet(1); expect(cellCount).toBe(data.clip["gene-cell-count"]); }); diff --git a/client/src/components/brushableHistogram/index.js b/client/src/components/brushableHistogram/index.js index 8f5755d1..fc7732fc 100644 --- a/client/src/components/brushableHistogram/index.js +++ b/client/src/components/brushableHistogram/index.js @@ -2,6 +2,7 @@ https://bl.ocks.org/mbostock/4341954 https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172 https://bl.ocks.org/SpaceActuary/2f004899ea1b2bd78d6f1dbb2febf771 +https://bl.ocks.org/mbostock/3019563 */ // jshint esversion: 6 import React from "react"; @@ -55,7 +56,7 @@ class HistogramBrush extends React.PureComponent { histogramCache.x = d3 .scaleLinear() .domain([domainMin, domainMax]) - .range([0, this.width - this.marginRight]); + .range([this.marginLeft, this.marginLeft + this.width]); histogramCache.bins = d3 .histogram() @@ -68,7 +69,7 @@ class HistogramBrush extends React.PureComponent { histogramCache.y = d3 .scaleLinear() .domain([0, yMax]) - .range([this.height - this.marginBottom, 0]); + .range([this.marginTop + this.height, this.marginTop]); return histogramCache; }); @@ -76,10 +77,13 @@ class HistogramBrush extends React.PureComponent { constructor(props) { super(props); - this.width = 340; - this.height = 100; - this.marginBottom = 20; // space for X axis & labels + this.marginLeft = 3; // Space for 0 tick label on X axis this.marginRight = 40; // space for Y axis & labels + this.marginBottom = 25; // space for X axis & labels + this.marginTop = 3; + + this.width = 340 - this.marginLeft - this.marginRight; + this.height = 135 - this.marginTop - this.marginBottom; } componentDidMount() { @@ -315,8 +319,16 @@ class HistogramBrush extends React.PureComponent { /* Remove everything */ svg.selectAll("*").remove(); + /* Set margins within the SVG */ + const container = svg + .attr("width", this.width + this.marginLeft + this.marginRight) + .attr("height", this.height + this.marginTop + this.marginBottom) + .append("g") + .attr("class", "histogram-container") + .attr("transform", `translate(${this.marginLeft},${this.marginTop})`); + /* BINS */ - svg + container .insert("g", "*") .attr("fill", "#bbb") .selectAll("rect") @@ -328,10 +340,14 @@ class HistogramBrush extends React.PureComponent { .attr("width", d => Math.abs(x(d.x1) - x(d.x0) - 1)) .attr("height", d => y(0) - y(d.length)); - /* BRUSH */ + // BRUSH + // Note the brushable area is bounded by the data on three sides, but goes down to cover the x-axis const brushX = d3 .brushX() - .extent([[0, 0], [this.width - this.marginRight, this.height]]) + .extent([ + [x.range()[0], y.range()[1]], + [x.range()[1], this.marginTop + this.height + this.marginBottom] + ]) /* emit start so that the Undoable history can save an undo point upon drag start, and ignore the subsequent intermediate drag events. @@ -339,18 +355,18 @@ class HistogramBrush extends React.PureComponent { .on("start", this.onBrush(field, x.invert, "start").bind(this)) .on("brush", this.onBrush(field, x.invert, "brush").bind(this)) .on("end", this.onBrushEnd(field, x.invert).bind(this)); - const brushXselection = d3 - .select(svgRef) - .append("g") + + const brushXselection = container + .insert("g") .attr("class", "brush") - .attr("data-testid", `${svgRef.dataset.testid}-brush`) + .attr("data-testid", `${svgRef.dataset.testid}-brushable-area`) .call(brushX); /* X AXIS */ - svg - .append("g") + container + .insert("g") .attr("class", "axis axis--x") - .attr("transform", `translate(0,${this.height - this.marginBottom})`) + .attr("transform", `translate(0,${this.marginTop + this.height})`) .call( d3 .axisBottom(x) @@ -359,10 +375,10 @@ class HistogramBrush extends React.PureComponent { ); /* Y AXIS */ - svg - .append("g") + container + .insert("g") .attr("class", "axis axis--y") - .attr("transform", `translate(${this.width - this.marginRight},0)`) + .attr("transform", `translate(${this.marginLeft + this.width},0)`) .call( d3 .axisRight(y)