mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-19 02:48:30 +08:00
crossfilter
This commit is contained in:
@@ -42,8 +42,23 @@ class HistogramBrush extends React.Component {
|
||||
componentDidUpdate() {
|
||||
|
||||
}
|
||||
onBrush(e) {
|
||||
console.log('brushed', e)
|
||||
onBrush(selection, x) {
|
||||
return () => {
|
||||
if (d3.event.selection) {
|
||||
this.props.dispatch({
|
||||
type: "continuous metadata histogram brush",
|
||||
selection: this.props.metadataField,
|
||||
range: [x(d3.event.selection[0]), x(d3.event.selection[1])]
|
||||
});
|
||||
} else {
|
||||
this.props.dispatch({
|
||||
type: "continuous metadata histogram brush",
|
||||
selection: this.props.metadataField,
|
||||
range: null
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
drawHistogram(svgRef) {
|
||||
|
||||
@@ -77,13 +92,12 @@ class HistogramBrush extends React.Component {
|
||||
.attr("height", function(d) { return y(0) - y(d.length / allValuesForContinuousFieldAsArray.length); });
|
||||
|
||||
if (!this.state.brush && !this.state.axis) {
|
||||
console.log('whee')
|
||||
const brush = d3.select(svgRef)
|
||||
.append('g')
|
||||
.attr('class', 'brush')
|
||||
.call(
|
||||
d3.brushX()
|
||||
.on('end', this.onBrush)
|
||||
.on('end', this.onBrush(this.props.metadataField, x.invert).bind(this))
|
||||
)
|
||||
|
||||
const xAxis = d3.select(svgRef)
|
||||
|
||||
@@ -26,6 +26,7 @@ const updateCellSelectionMiddleware = (store) => {
|
||||
/* this is a hardcoded map of the things we need to keep an eye on and update global cell selection in response to */
|
||||
const filterJustChanged =
|
||||
action.type === "continuous selection using parallel coords brushing" ||
|
||||
action.type === "continuous metadata histogram brush" ||
|
||||
action.type === "graph brush selection change" ||
|
||||
action.type === "graph brush deselect" ||
|
||||
action.type === "categorical metadata filter deselect" ||
|
||||
@@ -114,6 +115,49 @@ const updateCellSelectionMiddleware = (store) => {
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
Continuous histograms ___---^^^^--[------__]__---___
|
||||
|
||||
Create newContinuousUserDefinedRanges
|
||||
Filter based on them
|
||||
*/
|
||||
|
||||
let newContinuousUserDefinedRanges = s.controls.continuousUserDefinedRanges;
|
||||
|
||||
|
||||
/* check if this is the action and take care of that metadata field */
|
||||
if (action.type === "continuous metadata histogram brush") {
|
||||
/*
|
||||
was this a deselect? if so it will be null
|
||||
was it a select? set the new range [20, 50]
|
||||
we overload this because it is less if statements thru the whole system
|
||||
but it's invisible here, thus comment.
|
||||
*/
|
||||
newContinuousUserDefinedRanges[action.selection] = action.range;
|
||||
}
|
||||
|
||||
let activeContinuousHistogramFilters = [];
|
||||
|
||||
_.each(newContinuousUserDefinedRanges, (value, key, i) => {
|
||||
if (value !== null) {
|
||||
activeContinuousHistogramFilters.push(key)
|
||||
}
|
||||
})
|
||||
|
||||
/* see if there are others from previous... */
|
||||
if (activeContinuousHistogramFilters.length > 0) {
|
||||
_.each(activeContinuousHistogramFilters, (key) => {
|
||||
_.each(newSelection, (cell, i) => {
|
||||
if (
|
||||
+cell[key] < newContinuousUserDefinedRanges[key][0] ||
|
||||
+cell[key] > newContinuousUserDefinedRanges[key][1]
|
||||
) {
|
||||
newSelection[i]["__selected__"] = false;
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
1. figure out if the users have unchecked boxes
|
||||
2. put them in an array
|
||||
@@ -183,18 +227,19 @@ const updateCellSelectionMiddleware = (store) => {
|
||||
if (inactiveCategories.length > 0) {
|
||||
_.each(inactiveCategories, (d) => {
|
||||
_.each(newSelection, (cell, i) => {
|
||||
if (""+cell[d.category] === ""+d.option) { /* nums and strings to strings */
|
||||
if (""+cell[d.category] === ""+d.option) { /* nums and strings to strings -__- */
|
||||
newSelection[i]["__selected__"] = false;
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
let modifiedAction = Object.assign({}, action, {
|
||||
newSelection,
|
||||
newCategoricalAsBooleansMap,
|
||||
newContinuousUserDefinedRanges,
|
||||
}) /* append the result of all the filters to the action the user just triggered */
|
||||
|
||||
return next(modifiedAction);
|
||||
|
||||
13
src/reducers/controls.js
vendored
13
src/reducers/controls.js
vendored
@@ -42,6 +42,7 @@ const Controls = (state = {
|
||||
we mutate this map in the actions below
|
||||
*/
|
||||
const categoricalAsBooleansMap = {};
|
||||
const continuousUserDefinedRanges = {};
|
||||
_.each(action.data.data.ranges, (value, key) => {
|
||||
if (
|
||||
key !== "CellName" &&
|
||||
@@ -52,13 +53,20 @@ const Controls = (state = {
|
||||
optionsAsBooleans[_key] = true;
|
||||
})
|
||||
categoricalAsBooleansMap[key] = optionsAsBooleans;
|
||||
} else if (
|
||||
key !== "CellName" &&
|
||||
value.range
|
||||
) {
|
||||
continuousUserDefinedRanges[key] = null;
|
||||
}
|
||||
})
|
||||
|
||||
return Object.assign({}, state, {
|
||||
allCellsOnClient: action.data.data,
|
||||
currentCellSelection,
|
||||
graphMap,
|
||||
categoricalAsBooleansMap,
|
||||
continuousUserDefinedRanges,
|
||||
graphBrushSelection: null, /* if we are getting new cells from the server, the layout (probably? definitely?) just changed, so this is now irrelevant, and we WILL need to call a function to reset state of this kind when cells success happens */
|
||||
});
|
||||
/* * * * * * * * * * * * * * * * * *
|
||||
@@ -84,6 +92,11 @@ const Controls = (state = {
|
||||
graphBrushSelection: null,
|
||||
currentCellSelection: action.newSelection /* this comes from middleware */
|
||||
})
|
||||
case "continuous metadata histogram brush":
|
||||
return Object.assign({}, state, {
|
||||
newContinuousUserDefinedRanges: action.newContinuousUserDefinedRanges, /* this has already been applied in middleware but store it for next time */
|
||||
currentCellSelection: action.newSelection /* this comes from middleware */
|
||||
})
|
||||
case "change opacity deselected cells in 2d graph background":
|
||||
return Object.assign({}, state, {
|
||||
opacityForDeselectedCells: action.data,
|
||||
|
||||
Reference in New Issue
Block a user