diff --git a/client/__tests__/e2e/__snapshots__/e2eAnnotations.test.js.snap b/client/__tests__/e2e/__snapshots__/e2eAnnotations.test.js.snap
index 3ad14bca..f74f258b 100644
--- a/client/__tests__/e2e/__snapshots__/e2eAnnotations.test.js.snap
+++ b/client/__tests__/e2e/__snapshots__/e2eAnnotations.test.js.snap
@@ -3,7 +3,7 @@
exports[`annotations stacked bar graph renders 1`] = `
Array [
"
",
- "",
+ "",
]
`;
diff --git a/client/__tests__/e2e/data.js b/client/__tests__/e2e/data.js
index b7f8db77..9796b96b 100644
--- a/client/__tests__/e2e/data.js
+++ b/client/__tests__/e2e/data.js
@@ -27,7 +27,7 @@ export const datasets = {
lasso: [
{
"coordinates-as-percent": { x1: 0.1, y1: 0.25, x2: 0.7, y2: 0.75 },
- count: "1173",
+ count: "1131",
},
],
categorical: [
@@ -121,8 +121,8 @@ export const datasets = {
},
newCount: {
bySubsetConfig: {
- false: "599",
- true: "594",
+ false: "668",
+ true: "659",
},
},
},
diff --git a/client/src/components/app.js b/client/src/components/app.js
index fe1de5e7..4de58f1c 100644
--- a/client/src/components/app.js
+++ b/client/src/components/app.js
@@ -11,6 +11,7 @@ import Legend from "./continuousLegend";
import Graph from "./graph/graph";
import MenuBar from "./menubar";
import Autosave from "./autosave";
+import Embedding from "./embedding";
import TermsOfServicePrompt from "./termsPrompt";
import actions from "../actions";
@@ -73,6 +74,7 @@ class App extends React.Component {
{(viewportRef) => (
<>
+
diff --git a/client/src/components/embedding/index.js b/client/src/components/embedding/index.js
new file mode 100644
index 00000000..868b6ae1
--- /dev/null
+++ b/client/src/components/embedding/index.js
@@ -0,0 +1,105 @@
+import React from "react";
+import { connect } from "react-redux";
+import {
+ ButtonGroup,
+ Popover,
+ Button,
+ Radio,
+ RadioGroup,
+ Tooltip,
+ Position,
+} from "@blueprintjs/core";
+import * as globals from "../../globals";
+import actions from "../../actions";
+
+@connect((state) => {
+ return {
+ layoutChoice: state.layoutChoice,
+ schema: state.annoMatrix?.schema,
+ crossfilter: state.obsCrossfilter,
+ };
+})
+class Embedding extends React.PureComponent {
+ constructor(props) {
+ super(props);
+ this.state = {};
+ }
+
+ handleLayoutChoiceChange = (e) => {
+ const { dispatch } = this.props;
+ dispatch(actions.layoutChoiceAction(e.currentTarget.value));
+ };
+
+ render() {
+ const { layoutChoice, schema, crossfilter } = this.props;
+ return (
+
+
+
+
+ }
+ // minimal /* removes arrow */
+ position={Position.TOP_LEFT}
+ content={
+
+
Embedding Choice
+
+ There are {schema?.dataframe?.nObs} cells in the entire dataset.
+
+
+ {layoutChoice.available.map((name) => (
+
+ ))}
+
+
+ }
+ />
+
+ );
+ }
+}
+
+export default Embedding;
diff --git a/client/src/components/graph/graph.js b/client/src/components/graph/graph.js
index c91f6e0a..7ec11976 100644
--- a/client/src/components/graph/graph.js
+++ b/client/src/components/graph/graph.js
@@ -34,8 +34,10 @@ function createProjectionTF(viewportWidth, viewportHeight) {
the projection transform accounts for the screen size & other layout
*/
const fractionToUse = 0.95; // fraction of min dimension to use
- const topGutterSizePx = 32; // toolbar box height
- const heightMinusGutter = viewportHeight - topGutterSizePx;
+ const topGutterSizePx = 32; // top gutter for tools
+ const bottomGutterSizePx = 32; // bottom gutter for tools
+ const heightMinusGutter =
+ viewportHeight - topGutterSizePx - bottomGutterSizePx;
const minDim = Math.min(viewportWidth, heightMinusGutter);
const aspectScale = [
(fractionToUse * minDim) / viewportWidth,
@@ -44,7 +46,7 @@ function createProjectionTF(viewportWidth, viewportHeight) {
const m = mat3.create();
mat3.fromTranslation(m, [
0,
- -topGutterSizePx / viewportHeight / aspectScale[1],
+ (bottomGutterSizePx - topGutterSizePx) / viewportHeight / aspectScale[1],
]);
mat3.scale(m, m, aspectScale);
return m;
diff --git a/client/src/components/menubar/embedding.js b/client/src/components/menubar/embedding.js
deleted file mode 100644
index d0bfc260..00000000
--- a/client/src/components/menubar/embedding.js
+++ /dev/null
@@ -1,118 +0,0 @@
-import React from "react";
-import {
- ButtonGroup,
- Popover,
- Button,
- Radio,
- RadioGroup,
- Tooltip,
- Position,
-} from "@blueprintjs/core";
-import { connect } from "react-redux";
-import * as globals from "../../globals";
-import styles from "./menubar.css";
-import actions from "../../actions";
-
-@connect((state) => ({
- layoutChoice: state.layoutChoice,
- // disabled temporarily. TODO - issue #1606
- // reembedController: state.reembedController,
- // enableReembedding: state.config?.parameters?.["enable-reembedding"] ?? false,
- enableReembedding: false,
-}))
-class Embedding extends React.PureComponent {
- handleLayoutChoiceChange = (e) => {
- const { dispatch } = this.props;
- dispatch(actions.layoutChoiceAction(e.currentTarget.value));
- };
-
- // eslint-disable-next-line class-methods-use-this -- temporary disable
- renderReembedding() {
- return null;
- /* disabled pending rewrite. TODO - issue #1606
- const {
- enableReembedding,
- world,
- universe,
- dispatch,
- reembedController,
- } = this.props;
-
- if (!enableReembedding) return null;
-
- const loading = !!reembedController?.pendingFetch;
- const disabled = World.worldEqUniverse(world, universe);
- const tipContent = disabled
- ? "Subset cells first, then click to recompute UMAP embedding."
- : "Click to recompute UMAP embedding on the current cell subset.";
-
- return (
-
- dispatch(actions.requestReembed())}
- loading={loading}
- />
-
- );
-*/
- }
-
- render() {
- const { layoutChoice } = this.props;
-
- return (
-
-
-
-
- }
- position={Position.BOTTOM_RIGHT}
- content={
-
-
- {layoutChoice.available.map((name) => (
-
- ))}
-
-
- }
- />
- {this.renderReembedding()}
-
- );
- }
-}
-
-export default Embedding;
diff --git a/client/src/components/menubar/index.js b/client/src/components/menubar/index.js
index dbd1bdd4..bbfd00fc 100644
--- a/client/src/components/menubar/index.js
+++ b/client/src/components/menubar/index.js
@@ -6,7 +6,6 @@ import * as globals from "../../globals";
import styles from "./menubar.css";
import actions from "../../actions";
import Clip from "./clip";
-import Embedding from "./embedding";
import InformationMenu from "./infoMenu";
import Subset from "./subset";
import UndoRedoReset from "./undoRedo";
@@ -264,7 +263,6 @@ class MenuBar extends React.PureComponent {
this.handleClipPercentileMinValueChange
}
/>
-
@@ -523,9 +527,7 @@ class Scatterplot extends React.PureComponent {
}
return (
{
+ ({
+ minimized,
+ scatterplotYYaccessor,
+ scatterplotXXaccessor,
+ xScale,
+ yScale,
+ }) => {
/*
Axis for the scatterplot, rendered with SVG/D3. Props:
* scatterplotXXaccessor - name of X axis
@@ -559,7 +567,7 @@ const ScatterplotAxis = React.memo(
const svgRef = useRef(null);
useEffect(() => {
- if (!svgRef.current) return;
+ if (!svgRef.current || minimized) return;
const svg = d3.select(svgRef.current);
svg.selectAll("*").remove();
@@ -608,6 +616,9 @@ const ScatterplotAxis = React.memo(
width={width + margin.left + margin.right}
height={height + margin.top + margin.bottom}
data-testid="scatterplot-svg"
+ style={{
+ display: minimized ? "none" : null,
+ }}
>
diff --git a/client/src/globals.js b/client/src/globals.js
index a39d7846..de7d0473 100644
--- a/client/src/globals.js
+++ b/client/src/globals.js
@@ -61,7 +61,7 @@ export const maxControlsWidth = 800;
export const graphMargin = { top: 20, right: 10, bottom: 30, left: 40 };
export const graphWidth = 700;
export const graphHeight = 700;
-export const scatterplotMarginLeft = 25;
+export const scatterplotMarginLeft = 11;
export const rightSidebarWidth = 365;
export const leftSidebarWidth = 365;