From 2462d4afb183904decd539aa7c1c66463278ca8c Mon Sep 17 00:00:00 2001 From: Colin Megill Date: Wed, 21 Jul 2021 12:01:20 -0700 Subject: [PATCH] color scale, button --- .../components/categorical/category/index.js | 29 ++++++++++------- client/src/components/dotplot/column.js | 32 +++++++++++++++---- client/src/components/dotplot/dot.js | 6 ++-- client/src/components/menubar/index.js | 2 +- 4 files changed, 48 insertions(+), 21 deletions(-) diff --git a/client/src/components/categorical/category/index.js b/client/src/components/categorical/category/index.js index a87499bc..1facf4c5 100644 --- a/client/src/components/categorical/category/index.js +++ b/client/src/components/categorical/category/index.js @@ -36,6 +36,7 @@ const LABEL_WIDTH_ANNO = LABEL_WIDTH - ANNO_BUTTON_WIDTH; const { metadataField } = ownProps; const isUserAnno = schema?.annotations?.obsByName[metadataField]?.writable; const categoricalSelection = state.categoricalSelection?.[metadataField]; + const isDotplotRows = metadataField === state.dotplot.row; return { colors: state.colors, categoricalSelection, @@ -45,7 +46,8 @@ const LABEL_WIDTH_ANNO = LABEL_WIDTH - ANNO_BUTTON_WIDTH; crossfilter: state.obsCrossfilter, isUserAnno, genesets: state.genesets.genesets, - dotplot: state.layoutChoice.dotplot, + layoutChoiceIsDotplot: state.layoutChoice.dotplot, + isDotplotRows, }; }) class Category extends React.PureComponent { @@ -84,9 +86,9 @@ class Category extends React.PureComponent { } handleColorChange = () => { - const { dispatch, metadataField, dotplot } = this.props; + const { dispatch, metadataField, layoutChoiceIsDotplot } = this.props; - if (dotplot) { + if (layoutChoiceIsDotplot) { dispatch({ type: "set dotplot row", data: metadataField, @@ -229,7 +231,8 @@ class Category extends React.PureComponent { colors, annoMatrix, isUserAnno, - dotplot, + layoutChoiceIsDotplot, + isDotplotRows, } = this.props; const checkboxID = `category-select-${metadataField}`; @@ -288,7 +291,8 @@ class Category extends React.PureComponent { onCategoryToggleAllClick={handleCategoryToggleAllClick} onCategoryMenuClick={this.handleCategoryClick} onCategoryMenuKeyPress={this.handleCategoryKeyPress} - dotplot={dotplot} + layoutChoiceIsDotplot={layoutChoiceIsDotplot} + isDotplotRows={isDotplotRows} /> ); }} @@ -383,7 +387,8 @@ const CategoryHeader = React.memo( onCategoryMenuClick, onCategoryMenuKeyPress, onCategoryToggleAllClick, - dotplot, + layoutChoiceIsDotplot, + isDotplotRows, }) => { /* Render category name and controls (eg, color-by button). @@ -482,10 +487,10 @@ const CategoryHeader = React.memo( data-testclass="colorby" data-testid={`colorby-${metadataField}`} onClick={onColorChangeClick} - active={isColorAccessor} - intent={isColorAccessor ? "primary" : "none"} + active={isColorAccessor || isDotplotRows} + intent={isColorAccessor || isDotplotRows ? "primary" : "none"} disabled={isTruncated} - icon={dotplot ? "layout-grid" : "tint"} + icon={layoutChoiceIsDotplot ? "layout-grid" : "tint"} /> @@ -512,7 +517,8 @@ const CategoryRender = React.memo( onCategoryMenuClick, onCategoryMenuKeyPress, onCategoryToggleAllClick, - dotplot, + layoutChoiceIsDotplot, + isDotplotRows, }) => { /* Render the core of the category, including checkboxes, controls, etc. @@ -557,7 +563,8 @@ const CategoryRender = React.memo( onCategoryToggleAllClick={onCategoryToggleAllClick} onCategoryMenuClick={onCategoryMenuClick} onCategoryMenuKeyPress={onCategoryMenuKeyPress} - dotplot={dotplot} + layoutChoiceIsDotplot={layoutChoiceIsDotplot} + isDotplotRows={isDotplotRows} />
diff --git a/client/src/components/dotplot/column.js b/client/src/components/dotplot/column.js index f18977e4..9d71b664 100644 --- a/client/src/components/dotplot/column.js +++ b/client/src/components/dotplot/column.js @@ -1,7 +1,7 @@ import React from "react"; import { connect, shallowEqual } from "react-redux"; -// import * as d3 from "d3"; +import * as d3 from "d3"; import memoize from "memoize-one"; @@ -140,18 +140,34 @@ class Column extends React.Component { const col = colorData.icol(0); const range = col.summarize(); - console.log(_geneSymbol, metadataField, categoryData); - const histogramMap = col.histogram( 100, [range.min, range.max], groupBy ); - // const dotColorScale = d3 - // .scaleLinear() - // .domain([range.min, range.max]) - // .range([0, 1]); + const categories = + annoMatrix?.schema?.annotations?.obsByName[metadataField] + ?.categories; + const cellCategories = groupBy.asArray(); + const geneExpressions = col.asArray(); + let mean; + const meanGeneExpressions = {}; + for (const c of categories) { + const arr = []; + for (let i = 0; i < geneExpressions.length; i += 1) { + if (cellCategories[i] === c) { + arr.push(geneExpressions[i]); + } + } + mean = arr.reduce((a, b) => a + b) / arr.length; + meanGeneExpressions[c] = mean; + } + + const columnColorScale = d3 + .scaleLinear() + .domain(d3.extent(Object.values(meanGeneExpressions))) + .range([0, 1]); return categorySummary.categoryValues.map( (val, _categoryValueIndex) => { @@ -165,6 +181,8 @@ class Column extends React.Component { _geneIndex={_geneIndex} colorData={colorData} rowColumnSize={rowColumnSize} + columnColorScale={columnColorScale} + meanGeneExpression={meanGeneExpressions[val]} /> ); } diff --git a/client/src/components/dotplot/dot.js b/client/src/components/dotplot/dot.js index ec12ebd3..e43855bd 100644 --- a/client/src/components/dotplot/dot.js +++ b/client/src/components/dotplot/dot.js @@ -10,7 +10,8 @@ const Dot = (props) => { _geneSymbol, _geneIndex, rowColumnSize, - // dotColorScale, + columnColorScale, + meanGeneExpression, } = props; const bins = histogramMap.has(categoryValue) @@ -34,6 +35,7 @@ const Dot = (props) => { /* TODO(colinmegill) #632 scale between correct dimensions */ const paddingEquivalentToRowColumnIndexOffset = 8; + /* domain is some fraction of the cells expressing, percent as decimal */ const dotscale = d3 .scaleLinear() .domain([0, 1]) @@ -62,7 +64,7 @@ const Dot = (props) => { cx="11" cy="-3.5" style={{ - fill: interpolateCool(Math.random()), + fill: interpolateCool(columnColorScale(meanGeneExpression)), fillOpacity: 1, stroke: "none", }} diff --git a/client/src/components/menubar/index.js b/client/src/components/menubar/index.js index 350327d0..1f902497 100644 --- a/client/src/components/menubar/index.js +++ b/client/src/components/menubar/index.js @@ -276,7 +276,7 @@ class MenuBar extends React.PureComponent { icon="layout-grid" onClick={this.handleDotplotToggle} active={dotplotEnabled} - intent={dotplotEnabled ? "primary" : "none"} + intent={dotplotEnabled ? "success" : "none"} />