This commit is contained in:
Colin Megill
2021-07-23 13:29:27 -07:00
parent e7200ce6c3
commit 9c2323b7bc
3 changed files with 98 additions and 71 deletions
+65 -69
View File
@@ -1,6 +1,8 @@
import React from "react"; import React from "react";
import { connect, shallowEqual } from "react-redux"; import { connect, shallowEqual } from "react-redux";
// import * as d3 from "d3";
import memoize from "memoize-one"; import memoize from "memoize-one";
import Async from "react-async"; import Async from "react-async";
@@ -10,10 +12,7 @@ import Dot from "./dot";
import { createCategorySummaryFromDfCol } from "../../util/stateManager/controlsHelpers"; import { createCategorySummaryFromDfCol } from "../../util/stateManager/controlsHelpers";
import { import { createColorQuery } from "../../util/stateManager/colorHelpers";
createColorTable,
createColorQuery,
} from "../../util/stateManager/colorHelpers";
@connect((state) => ({ @connect((state) => ({
annoMatrix: state.annoMatrix, annoMatrix: state.annoMatrix,
@@ -56,23 +55,23 @@ class Column extends React.Component {
async fetchData(annoMatrix, metadataField, colors, _geneSymbol) { async fetchData(annoMatrix, metadataField, colors, _geneSymbol) {
/* /*
fetch our data and the color-by data if appropriate, and then build a summary fetch our data and the color-by data if appropriate, and then build a summary
of our category and a color table for the color-by annotation. of our category and a color table for the color-by annotation.
*/ */
const { schema } = annoMatrix; const { schema } = annoMatrix;
const { colorMode } = colors; const { colorMode } = colors;
const { genesets, differential } = this.props; const { genesets, differential } = this.props;
let colorDataPromise = Promise.resolve(null); let colorDataPromise = Promise.resolve(null);
if (_geneSymbol) {
const query = createColorQuery( const query = createColorQuery(
colorMode, colorMode,
_geneSymbol, _geneSymbol,
schema, schema,
genesets, genesets,
differential.diffExp differential.diffExp
); );
if (query) colorDataPromise = annoMatrix.fetch(...query); if (query) colorDataPromise = annoMatrix.fetch(...query);
}
const [categoryData, colorData] = await Promise.all([ const [categoryData, colorData] = await Promise.all([
annoMatrix.fetch("obs", metadataField), annoMatrix.fetch("obs", metadataField),
colorDataPromise, colorDataPromise,
@@ -90,45 +89,6 @@ class Column extends React.Component {
return [categoryData, categorySummary, colorData]; return [categoryData, categorySummary, colorData];
} }
updateColorTable(colors, colorDf) {
const { annoMatrix } = this.props;
const { schema } = annoMatrix;
/* update color table state */
if (!colors || !colorDf) {
return createColorTable(
null, // default mode
null,
null,
schema,
null
);
}
const { colorAccessor, userColors, colorMode } = colors;
return createColorTable(
colorMode,
colorAccessor /* TODO(colinmegill) #632 dotplot wiring */,
colorDf,
schema,
userColors
);
}
createColorByQuery(colors) {
const { annoMatrix, genesets, differential } = this.props;
const { schema } = annoMatrix;
const { colorMode, colorAccessor } = colors;
return createColorQuery(
colorMode,
colorAccessor /* TODO(colinmegill) #632 dotplot wiring */,
schema,
genesets,
differential.diffExp
);
}
render() { render() {
const { const {
annoMatrix, annoMatrix,
@@ -170,13 +130,7 @@ class Column extends React.Component {
</Async.Rejected> </Async.Rejected>
<Async.Fulfilled persist> <Async.Fulfilled persist>
{(asyncProps) => { {(asyncProps) => {
const { const { categoryData, categorySummary, colorData } = asyncProps;
categoryData,
width,
height,
categorySummary,
colorData,
} = asyncProps;
if (!_geneSymbol || !colorData) return null; if (!_geneSymbol || !colorData) return null;
@@ -186,27 +140,30 @@ class Column extends React.Component {
const col = colorData.icol(0); const col = colorData.icol(0);
const range = col.summarize(); const range = col.summarize();
console.log(_geneSymbol, metadataField, categoryData);
const histogramMap = col.histogram( const histogramMap = col.histogram(
100, 100,
[range.min, range.max], [range.min, range.max],
groupBy groupBy
); );
// const dotColorScale = d3
// .scaleLinear()
// .domain([range.min, range.max])
// .range([0, 1]);
return categorySummary.categoryValues.map( return categorySummary.categoryValues.map(
(val, _categoryValueIndex) => { (val, _categoryValueIndex) => {
return ( return (
<Dot <Dot
key={val} key={val}
metadataField={metadataField}
categoryData={categoryData}
_geneSymbol={_geneSymbol}
colorData={colorData}
categoryValue={val} categoryValue={val}
width={width}
height={height}
_categoryValueIndex={_categoryValueIndex} _categoryValueIndex={_categoryValueIndex}
histogramMap={histogramMap} histogramMap={histogramMap}
_geneSymbol={_geneSymbol}
_geneIndex={_geneIndex} _geneIndex={_geneIndex}
colorData={colorData}
rowColumnSize={rowColumnSize} rowColumnSize={rowColumnSize}
/> />
); );
@@ -221,3 +178,42 @@ class Column extends React.Component {
} }
export default Column; export default Column;
// updateColorTable(colors, colorDf) {
// const { annoMatrix } = this.props;
// const { schema } = annoMatrix;
// /* update color table state */
// if (!colors || !colorDf) {
// return createColorTable(
// null, // default mode
// null,
// null,
// schema,
// null
// );
// }
// const { colorAccessor, userColors, colorMode } = colors;
// return createColorTable(
// colorMode,
// colorAccessor /* TODO(colinmegill) #632 dotplot wiring */,
// colorDf,
// schema,
// userColors
// );
// }
// createColorByQuery(colors) {
// const { annoMatrix, genesets, differential } = this.props;
// const { schema } = annoMatrix;
// const { colorMode, colorAccessor } = colors;
// return createColorQuery(
// colorMode,
// colorAccessor /* TODO(colinmegill) #632 dotplot wiring */,
// schema,
// genesets,
// differential.diffExp
// );
// }
+11 -2
View File
@@ -1,4 +1,5 @@
import React from "react"; import React from "react";
import { interpolateCool } from "d3-scale-chromatic";
import * as d3 from "d3"; import * as d3 from "d3";
const Dot = (props) => { const Dot = (props) => {
@@ -9,6 +10,7 @@ const Dot = (props) => {
_geneSymbol, _geneSymbol,
_geneIndex, _geneIndex,
rowColumnSize, rowColumnSize,
// dotColorScale,
} = props; } = props;
const bins = histogramMap.has(categoryValue) const bins = histogramMap.has(categoryValue)
@@ -18,7 +20,14 @@ const Dot = (props) => {
const totalCells = bins.reduce( const totalCells = bins.reduce(
(acc, current) => acc + current (acc, current) => acc + current
); /* SUM REMAINING ELEMENTS */ ); /* SUM REMAINING ELEMENTS */
/*
TODO(colinmegill) #632 this is a heuristic —
we need to figure out what non expressing means
and use it, rather than shifting off the first bin
for prototyping
*/
bins.shift(); /* MUTATES, REMOVES FIRST ELEMENT */ bins.shift(); /* MUTATES, REMOVES FIRST ELEMENT */
const expressing = bins.reduce( const expressing = bins.reduce(
(acc, current) => acc + current (acc, current) => acc + current
); /* SUM REMAINING ELEMENTS */ ); /* SUM REMAINING ELEMENTS */
@@ -53,8 +62,8 @@ const Dot = (props) => {
cx="11" cx="11"
cy="-3.5" cy="-3.5"
style={{ style={{
fill: "steelblue", fill: interpolateCool(Math.random()),
fillOpacity: 0.5, fillOpacity: 1,
stroke: "none", stroke: "none",
}} }}
/> />
@@ -55,6 +55,28 @@ export function createColorQuery(colorMode, colorByAccessor, schema, genesets) {
}, },
]; ];
} }
case "color by dotplot columns": {
/*
Color by COLUMNS is a mode at the UI level,
as we are going to be keeping track of many color scales —
one per column in the dotplot. The query is for
one gene at a time.
*/
const varIndex = schema?.annotations?.var?.index;
if (!varIndex) return null;
return [
"X",
{
where: {
field: "var",
column: varIndex,
value: colorByAccessor,
},
},
];
}
default: { default: {
return null; return null;
} }