mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-01 22:58:11 +08:00
Add margins to histogram SVGs (#1085)
* Add a left margin to histogram SVGs Fixes https://github.com/chanzuckerberg/cellxgene/issues/1042 1. Added "margins" to the SVG as in https://bl.ocks.org/mbostock/3019563 2. Tailored the brushable area to be just where the data is and locked puppeteerUtils to use that in e2e testing. * Dial in margins to avoid y-axis clipping
This commit is contained in:
@@ -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"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -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"]);
|
||||
});
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user