mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-09 14:20:56 +08:00
namespacing
This commit is contained in:
@@ -83,17 +83,28 @@ class HistogramBrush extends React.Component {
|
|||||||
|
|
||||||
onBrush(selection, x) {
|
onBrush(selection, x) {
|
||||||
return () => {
|
return () => {
|
||||||
const { dispatch, field } = this.props;
|
const { dispatch, field, isObs, isUserDefined, isDiffExp } = this.props;
|
||||||
|
|
||||||
if (d3.event.selection) {
|
if (d3.event.selection) {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "continuous metadata histogram brush",
|
type: "continuous metadata histogram brush",
|
||||||
selection: field,
|
selection: field,
|
||||||
|
continuousNamespace: {
|
||||||
|
isObs,
|
||||||
|
isUserDefined,
|
||||||
|
isDiffExp
|
||||||
|
},
|
||||||
range: [x(d3.event.selection[0]), x(d3.event.selection[1])]
|
range: [x(d3.event.selection[0]), x(d3.event.selection[1])]
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "continuous metadata histogram brush",
|
type: "continuous metadata histogram brush",
|
||||||
selection: field,
|
selection: field,
|
||||||
|
continuousNamespace: {
|
||||||
|
isObs,
|
||||||
|
isUserDefined,
|
||||||
|
isDiffExp
|
||||||
|
},
|
||||||
range: null
|
range: null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class Continuous extends React.Component {
|
|||||||
<HistogramBrush
|
<HistogramBrush
|
||||||
key={key}
|
key={key}
|
||||||
field={key}
|
field={key}
|
||||||
|
isObs
|
||||||
fieldValues={obsAnnotations}
|
fieldValues={obsAnnotations}
|
||||||
ranges={value.range}
|
ranges={value.range}
|
||||||
handleColorAction={this.handleColorAction(key).bind(this)}
|
handleColorAction={this.handleColorAction(key).bind(this)}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import React from "react";
|
|||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import * as d3 from "d3";
|
import * as d3 from "d3";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import HistogramBrush from "../brushableHistogram";
|
|
||||||
import CirclePlus from "react-icons/lib/fa/plus-circle";
|
import CirclePlus from "react-icons/lib/fa/plus-circle";
|
||||||
|
import HistogramBrush from "../brushableHistogram";
|
||||||
import * as globals from "../../globals";
|
import * as globals from "../../globals";
|
||||||
// import ReactAutocomplete from "react-autocomplete"; /* http://emilebres.github.io/react-virtualized-checkbox/ */
|
// import ReactAutocomplete from "react-autocomplete"; /* http://emilebres.github.io/react-virtualized-checkbox/ */
|
||||||
import actions from "../../actions/";
|
import actions from "../../actions";
|
||||||
|
|
||||||
@connect(state => {
|
@connect(state => {
|
||||||
const metadata = _.get(state.controls.world, "obsAnnotations", null);
|
const metadata = _.get(state.controls.world, "obsAnnotations", null);
|
||||||
@@ -22,7 +22,6 @@ import actions from "../../actions/";
|
|||||||
initializeRanges,
|
initializeRanges,
|
||||||
userDefinedGenes: state.controls.userDefinedGenes,
|
userDefinedGenes: state.controls.userDefinedGenes,
|
||||||
world: state.controls.world,
|
world: state.controls.world,
|
||||||
dimensionMap: state.controls.dimensionMap,
|
|
||||||
colorAccessor: state.controls.colorAccessor,
|
colorAccessor: state.controls.colorAccessor,
|
||||||
allGeneNames: state.controls.allGeneNames,
|
allGeneNames: state.controls.allGeneNames,
|
||||||
differential: state.differential
|
differential: state.differential
|
||||||
@@ -32,40 +31,42 @@ class GeneExpression extends React.Component {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
svg: null,
|
|
||||||
ctx: null,
|
|
||||||
axes: null,
|
|
||||||
dimensions: null,
|
|
||||||
gene: ""
|
gene: ""
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
keyPress(e) {
|
keyPress(e) {
|
||||||
if (e.keyCode == 13) {
|
if (e.keyCode === 13) {
|
||||||
this.handleClick();
|
this.handleClick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick() {
|
handleClick() {
|
||||||
const { world, dispatch, userDefinedGenes } = this.props;
|
const { world, dispatch, userDefinedGenes } = this.props;
|
||||||
|
const { gene } = this.state;
|
||||||
|
|
||||||
if (userDefinedGenes.indexOf(this.state.gene) !== -1) {
|
if (userDefinedGenes.indexOf(gene) !== -1) {
|
||||||
console.log("That gene already exists");
|
console.log("That gene already exists");
|
||||||
} else if (userDefinedGenes.length > 15) {
|
} else if (userDefinedGenes.length > 15) {
|
||||||
console.log(
|
console.log(
|
||||||
"That's too many genes, you can have at most 15 user defined genes"
|
"That's too many genes, you can have at most 15 user defined genes"
|
||||||
);
|
);
|
||||||
} else if (!_.find(world.varAnnotations, { name: this.state.gene })) {
|
} else if (!_.find(world.varAnnotations, { name: gene })) {
|
||||||
console.log("That doesn't appear to be a valid gene name.");
|
console.log("That doesn't appear to be a valid gene name.");
|
||||||
} else {
|
} else {
|
||||||
dispatch(actions.requestGeneExpressionCountsPOST([this.state.gene]));
|
dispatch(actions.requestGeneExpressionCountsPOST([gene]));
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "user defined gene",
|
type: "user defined gene",
|
||||||
data: this.state.gene
|
data: gene
|
||||||
});
|
});
|
||||||
this.setState({ gene: "" });
|
this.setState({ gene: "" });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { world, userDefinedGenes } = this.props;
|
const { world, userDefinedGenes } = this.props;
|
||||||
|
const { gene } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
@@ -74,9 +75,10 @@ class GeneExpression extends React.Component {
|
|||||||
this.setState({ gene: e.target.value });
|
this.setState({ gene: e.target.value });
|
||||||
}}
|
}}
|
||||||
type="text"
|
type="text"
|
||||||
value={this.state.gene}
|
value={gene}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
style={{
|
style={{
|
||||||
border: "none",
|
border: "none",
|
||||||
background: "none",
|
background: "none",
|
||||||
@@ -101,7 +103,7 @@ class GeneExpression extends React.Component {
|
|||||||
<p>User defined genes</p>
|
<p>User defined genes</p>
|
||||||
) : null}
|
) : null}
|
||||||
{world && userDefinedGenes.length > 0
|
{world && userDefinedGenes.length > 0
|
||||||
? _.map(userDefinedGenes, (geneName, index) => {
|
? _.map(userDefinedGenes, geneName => {
|
||||||
if (!world.varDataCache[geneName]) {
|
if (!world.varDataCache[geneName]) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Vendored
+66
-33
@@ -5,6 +5,13 @@ import { World, kvCache } from "../util/stateManager";
|
|||||||
import parseRGB from "../util/parseRGB";
|
import parseRGB from "../util/parseRGB";
|
||||||
import Crossfilter from "../util/typedCrossfilter";
|
import Crossfilter from "../util/typedCrossfilter";
|
||||||
import * as globals from "../globals";
|
import * as globals from "../globals";
|
||||||
|
import {
|
||||||
|
layoutDimensionName,
|
||||||
|
obsAnnoDimensionName,
|
||||||
|
userDefinedDimensionName,
|
||||||
|
diffexpDimensionName,
|
||||||
|
makeContinuousDimensionName
|
||||||
|
} from "../util/nameCreators";
|
||||||
|
|
||||||
function createCategoricalAsBooleansMap(world) {
|
function createCategoricalAsBooleansMap(world) {
|
||||||
const res = {};
|
const res = {};
|
||||||
@@ -79,8 +86,14 @@ const Controls = (
|
|||||||
const crossfilter = Crossfilter(world.obsAnnotations);
|
const crossfilter = Crossfilter(world.obsAnnotations);
|
||||||
const dimensionMap = World.createObsDimensionMap(crossfilter, world);
|
const dimensionMap = World.createObsDimensionMap(crossfilter, world);
|
||||||
|
|
||||||
let worldVarDataCache = world.varDataCache;
|
const worldVarDataCache = world.varDataCache;
|
||||||
|
|
||||||
|
// dimensionMap = {
|
||||||
|
// layout_X: dim-for-X,
|
||||||
|
// obsAnno_name: dim for an annotation,
|
||||||
|
// varData_userDefined_genename: dim for user defined expression,
|
||||||
|
// varData_diffexp_genename: dim for diff-exp added gene expression
|
||||||
|
// }
|
||||||
/* var dimensions */
|
/* var dimensions */
|
||||||
if (userDefinedGenes.length > 0) {
|
if (userDefinedGenes.length > 0) {
|
||||||
/*
|
/*
|
||||||
@@ -88,8 +101,10 @@ const Controls = (
|
|||||||
in controls rather than an array, should be abstracted into
|
in controls rather than an array, should be abstracted into
|
||||||
util ie., createDimensionsFromBothListsOfGenes(userGenes, diffExp)
|
util ie., createDimensionsFromBothListsOfGenes(userGenes, diffExp)
|
||||||
*/
|
*/
|
||||||
_.forEach(userDefinedGenes, (gene, index) => {
|
_.forEach(userDefinedGenes, gene => {
|
||||||
dimensionMap[gene] = World.createVarDimension(
|
dimensionMap[
|
||||||
|
userDefinedDimensionName(gene)
|
||||||
|
] = World.createVarDimension(
|
||||||
/* "__var__" + */
|
/* "__var__" + */
|
||||||
world,
|
world,
|
||||||
worldVarDataCache,
|
worldVarDataCache,
|
||||||
@@ -100,8 +115,8 @@ const Controls = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (diffexpGenes.length > 0) {
|
if (diffexpGenes.length > 0) {
|
||||||
_.forEach(diffexpGenes, (gene, index) => {
|
_.forEach(diffexpGenes, gene => {
|
||||||
dimensionMap[gene] = World.createVarDimension(
|
dimensionMap[diffexpDimensionName(gene)] = World.createVarDimension(
|
||||||
/* "__var__" + */
|
/* "__var__" + */
|
||||||
world,
|
world,
|
||||||
worldVarDataCache,
|
worldVarDataCache,
|
||||||
@@ -140,7 +155,7 @@ const Controls = (
|
|||||||
const crossfilter = Crossfilter(world.obsAnnotations);
|
const crossfilter = Crossfilter(world.obsAnnotations);
|
||||||
const dimensionMap = World.createObsDimensionMap(crossfilter, world);
|
const dimensionMap = World.createObsDimensionMap(crossfilter, world);
|
||||||
|
|
||||||
let worldVarDataCache = world.varDataCache;
|
const worldVarDataCache = world.varDataCache;
|
||||||
/* var dimensions */
|
/* var dimensions */
|
||||||
|
|
||||||
if (userDefinedGenes.length > 0) {
|
if (userDefinedGenes.length > 0) {
|
||||||
@@ -149,8 +164,10 @@ const Controls = (
|
|||||||
in controls rather than an array, should be abstracted into
|
in controls rather than an array, should be abstracted into
|
||||||
util ie., createDimensionsFromBothListsOfGenes(userGenes, diffExp)
|
util ie., createDimensionsFromBothListsOfGenes(userGenes, diffExp)
|
||||||
*/
|
*/
|
||||||
_.forEach(userDefinedGenes, (gene, index) => {
|
_.forEach(userDefinedGenes, gene => {
|
||||||
dimensionMap[gene] = World.createVarDimension(
|
dimensionMap[
|
||||||
|
userDefinedDimensionName(gene)
|
||||||
|
] = World.createVarDimension(
|
||||||
/* "__var__" + */
|
/* "__var__" + */
|
||||||
world,
|
world,
|
||||||
worldVarDataCache,
|
worldVarDataCache,
|
||||||
@@ -161,8 +178,8 @@ const Controls = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (diffexpGenes.length > 0) {
|
if (diffexpGenes.length > 0) {
|
||||||
_.forEach(diffexpGenes, (gene, index) => {
|
_.forEach(diffexpGenes, gene => {
|
||||||
dimensionMap[gene] = World.createVarDimension(
|
dimensionMap[diffexpDimensionName(gene)] = World.createVarDimension(
|
||||||
/* "__var__" + */
|
/* "__var__" + */
|
||||||
world,
|
world,
|
||||||
worldVarDataCache,
|
worldVarDataCache,
|
||||||
@@ -186,6 +203,7 @@ const Controls = (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
case "expression load success": {
|
case "expression load success": {
|
||||||
|
console.log("expression load success", action);
|
||||||
const { world, universe, crossfilter, dimensionMap } = state;
|
const { world, universe, crossfilter, dimensionMap } = state;
|
||||||
let universeVarDataCache = universe.varDataCache;
|
let universeVarDataCache = universe.varDataCache;
|
||||||
let worldVarDataCache = world.varDataCache;
|
let worldVarDataCache = world.varDataCache;
|
||||||
@@ -223,33 +241,34 @@ const Controls = (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
case "request differential expression success": {
|
case "request differential expression success": {
|
||||||
|
console.log("request diff success", action);
|
||||||
const { world } = state;
|
const { world } = state;
|
||||||
const _diffexpGenes = [];
|
const _diffexpGenes = [];
|
||||||
|
|
||||||
action.data.forEach(d => {
|
action.data.forEach(d => {
|
||||||
_diffexpGenes.push(world.varAnnotations[d[0]].name);
|
_diffexpGenes.push(world.varAnnotations[d[0]].name);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
diffexpGenes: _diffexpGenes
|
diffexpGenes: _diffexpGenes
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case "clear differential expression":
|
case "clear differential expression": {
|
||||||
const { world, universe, crossfilter, dimensionMap } = state;
|
const { world, universe, crossfilter, dimensionMap } = state;
|
||||||
const _dimensionMap = dimensionMap;
|
const _dimensionMap = dimensionMap;
|
||||||
let universeVarDataCache = universe.varDataCache;
|
const universeVarDataCache = universe.varDataCache;
|
||||||
let worldVarDataCache = world.varDataCache;
|
const worldVarDataCache = world.varDataCache;
|
||||||
|
|
||||||
_.forEach(action.diffExp, values => {
|
_.forEach(action.diffExp, values => {
|
||||||
const name = world.varAnnotations[values[0]].name;
|
const { name } = world.varAnnotations[values[0]].name;
|
||||||
// clean up crossfilter dimensions
|
// clean up crossfilter dimensions
|
||||||
const filterID = dimensionMap[name];
|
const filterID = dimensionMap[diffexpDimensionName(name)];
|
||||||
const dimension = crossfilter.filters.find(d => {
|
const dimension = crossfilter.filters.find(d => d.id === filterID);
|
||||||
return (d.id = filterID);
|
|
||||||
});
|
|
||||||
dimension.dim.dispose();
|
dimension.dim.dispose();
|
||||||
|
|
||||||
// clean up dimensionsMap
|
// clean up dimensionsMap
|
||||||
delete _dimensionMap[name];
|
delete _dimensionMap[diffexpDimensionName(name)];
|
||||||
// clean up the varDataCaches
|
// clean up the varDataCaches
|
||||||
delete universeVarDataCache[name];
|
delete universeVarDataCache[name];
|
||||||
delete worldVarDataCache[name];
|
delete worldVarDataCache[name];
|
||||||
@@ -267,8 +286,12 @@ const Controls = (
|
|||||||
varDataCache: worldVarDataCache
|
varDataCache: worldVarDataCache
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
case "user defined gene": {
|
case "user defined gene": {
|
||||||
/* this could also live in expression success with a conditional, but that handles diffexp also */
|
/*
|
||||||
|
this could also live in expression success with a conditional,
|
||||||
|
but that handles diffexp also
|
||||||
|
*/
|
||||||
const newUserDefinedGenes = state.userDefinedGenes.slice();
|
const newUserDefinedGenes = state.userDefinedGenes.slice();
|
||||||
newUserDefinedGenes.push(action.data);
|
newUserDefinedGenes.push(action.data);
|
||||||
return {
|
return {
|
||||||
@@ -278,9 +301,10 @@ const Controls = (
|
|||||||
}
|
}
|
||||||
case "clear user defined gene": {
|
case "clear user defined gene": {
|
||||||
const { userDefinedGenes } = state;
|
const { userDefinedGenes } = state;
|
||||||
const newUserDefinedGenes = _.filter(userDefinedGenes, d => {
|
const newUserDefinedGenes = _.filter(
|
||||||
return d !== action.data;
|
userDefinedGenes,
|
||||||
});
|
d => d !== action.data
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
userDefinedGenes: newUserDefinedGenes
|
userDefinedGenes: newUserDefinedGenes
|
||||||
@@ -310,11 +334,11 @@ const Controls = (
|
|||||||
User Events
|
User Events
|
||||||
*******************************/
|
*******************************/
|
||||||
case "graph brush selection change": {
|
case "graph brush selection change": {
|
||||||
state.dimensionMap.x.filterRange([
|
state.dimensionMap[layoutDimensionName("X")].filterRange([
|
||||||
action.brushCoords.northwest[0],
|
action.brushCoords.northwest[0],
|
||||||
action.brushCoords.southeast[0]
|
action.brushCoords.southeast[0]
|
||||||
]);
|
]);
|
||||||
state.dimensionMap.y.filterRange([
|
state.dimensionMap[layoutDimensionName("Y")].filterRange([
|
||||||
action.brushCoords.southeast[1],
|
action.brushCoords.southeast[1],
|
||||||
action.brushCoords.northwest[1]
|
action.brushCoords.northwest[1]
|
||||||
]);
|
]);
|
||||||
@@ -324,20 +348,25 @@ const Controls = (
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
case "graph brush deselect": {
|
case "graph brush deselect": {
|
||||||
state.dimensionMap.x.filterAll();
|
state.dimensionMap[layoutDimensionName("X")].filterAll();
|
||||||
state.dimensionMap.y.filterAll();
|
state.dimensionMap[layoutDimensionName("Y")].filterAll();
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
graphBrushSelection: null
|
graphBrushSelection: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case "continuous metadata histogram brush": {
|
case "continuous metadata histogram brush": {
|
||||||
|
const name = makeContinuousDimensionName(
|
||||||
|
action.continuousNamespace,
|
||||||
|
action.selection
|
||||||
|
);
|
||||||
|
|
||||||
// action.selection: metadata name being selected
|
// action.selection: metadata name being selected
|
||||||
// action.range: filter range, or null if deselected
|
// action.range: filter range, or null if deselected
|
||||||
if (!action.range) {
|
if (!action.range) {
|
||||||
state.dimensionMap[action.selection].filterAll();
|
state.dimensionMap[name].filterAll();
|
||||||
} else {
|
} else {
|
||||||
state.dimensionMap[action.selection].filterRange(action.range);
|
state.dimensionMap[name].filterRange(action.range);
|
||||||
}
|
}
|
||||||
return { ...state };
|
return { ...state };
|
||||||
}
|
}
|
||||||
@@ -359,7 +388,7 @@ const Controls = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
// update the filter for the one category that changed state
|
// update the filter for the one category that changed state
|
||||||
state.dimensionMap[action.metadataField].filterEnum(
|
state.dimensionMap[obsAnnoDimensionName(action.metadataField)].filterEnum(
|
||||||
_.filter(
|
_.filter(
|
||||||
_.map(
|
_.map(
|
||||||
newCategoricalAsBooleansMap[action.metadataField],
|
newCategoricalAsBooleansMap[action.metadataField],
|
||||||
@@ -381,7 +410,7 @@ const Controls = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
// update the filter for the one category that changed state
|
// update the filter for the one category that changed state
|
||||||
state.dimensionMap[action.metadataField].filterEnum(
|
state.dimensionMap[obsAnnoDimensionName(action.metadataField)].filterEnum(
|
||||||
_.filter(
|
_.filter(
|
||||||
_.map(
|
_.map(
|
||||||
newCategoricalAsBooleansMap[action.metadataField],
|
newCategoricalAsBooleansMap[action.metadataField],
|
||||||
@@ -404,7 +433,9 @@ const Controls = (
|
|||||||
c[k] = false;
|
c[k] = false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
state.dimensionMap[action.metadataField].filterNone();
|
state.dimensionMap[
|
||||||
|
obsAnnoDimensionName(action.metadataField)
|
||||||
|
].filterNone();
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
categoricalAsBooleansMap: newCategoricalAsBooleansMap
|
categoricalAsBooleansMap: newCategoricalAsBooleansMap
|
||||||
@@ -420,7 +451,9 @@ const Controls = (
|
|||||||
c[k] = true;
|
c[k] = true;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
state.dimensionMap[action.metadataField].filterAll();
|
state.dimensionMap[
|
||||||
|
obsAnnoDimensionName(action.metadataField)
|
||||||
|
].filterAll();
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
categoricalAsBooleansMap: newCategoricalAsBooleansMap
|
categoricalAsBooleansMap: newCategoricalAsBooleansMap
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
// jshint esversion: 6
|
// jshint esversion: 6
|
||||||
import _ from "lodash";
|
|
||||||
|
|
||||||
const Differential = (
|
const Differential = (
|
||||||
state = {
|
state = {
|
||||||
@@ -47,7 +46,7 @@ const Differential = (
|
|||||||
diffExp: null,
|
diffExp: null,
|
||||||
celllist1: null,
|
celllist1: null,
|
||||||
celllist2: null
|
celllist2: null
|
||||||
}
|
};
|
||||||
case "reset World to eq Universe":
|
case "reset World to eq Universe":
|
||||||
case "set World to current selection":
|
case "set World to current selection":
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
The original motivation for this file is name collision. It's possible
|
||||||
|
to have two of the same gene, user defined and diffexpressed, on the client
|
||||||
|
simultaneously, looking at the same data in the cache but with two
|
||||||
|
dimensions and two crossfilters. It's also possible that someone could
|
||||||
|
have a obsAnnotation named X, but we are using that for layout. So
|
||||||
|
we namespace, and abstract to avoid proliferating strings throughout the
|
||||||
|
codebase.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const makeDimensionName = (namespace, key) => `${namespace}_${key}`;
|
||||||
|
|
||||||
|
export const layoutDimensionName = key => makeDimensionName("layout", key);
|
||||||
|
export const obsAnnoDimensionName = key => makeDimensionName("obsAnno", key);
|
||||||
|
export const diffexpDimensionName = key =>
|
||||||
|
makeDimensionName("varData_diffexp", key);
|
||||||
|
export const userDefinedDimensionName = key =>
|
||||||
|
makeDimensionName("varData_userDefined", key);
|
||||||
|
|
||||||
|
/*
|
||||||
|
continuousNamespace = {
|
||||||
|
isObs: true,
|
||||||
|
isDiffExp: false,
|
||||||
|
isUserDefined: false
|
||||||
|
}
|
||||||
|
|
||||||
|
ie., makeContinuousDimensionName(continuousNamespace = {isObs: true}, "total_reads")
|
||||||
|
see: histogram brush, as it doesn't know what type of continuous it was with only field
|
||||||
|
*/
|
||||||
|
export const makeContinuousDimensionName = (continuousNamespace, key) => {
|
||||||
|
let name;
|
||||||
|
if (continuousNamespace.isObs) {
|
||||||
|
name = obsAnnoDimensionName(key);
|
||||||
|
} else if (continuousNamespace.isDiffExp) {
|
||||||
|
name = diffexpDimensionName(key);
|
||||||
|
} else if (continuousNamespace.isUserDefined) {
|
||||||
|
name = userDefinedDimensionName(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
};
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import * as kvCache from "./keyvalcache";
|
import * as kvCache from "./keyvalcache";
|
||||||
|
import { layoutDimensionName, obsAnnoDimensionName } from "../nameCreators";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
World is a subset of universe. Most code should use world, and should
|
World is a subset of universe. Most code should use world, and should
|
||||||
@@ -296,13 +297,14 @@ export function createVarDimension(
|
|||||||
crossfilter,
|
crossfilter,
|
||||||
geneName
|
geneName
|
||||||
) {
|
) {
|
||||||
const { varDataCache, worldObsIndex } = world;
|
const { worldObsIndex } = world;
|
||||||
const varData = _worldVarDataCache[geneName];
|
const varData = _worldVarDataCache[geneName];
|
||||||
const worldIndex = worldObsIndex ? idx => worldObsIndex[idx] : idx => idx;
|
const worldIndex = worldObsIndex ? idx => worldObsIndex[idx] : idx => idx;
|
||||||
|
|
||||||
return crossfilter.dimension(r => {
|
return crossfilter.dimension(
|
||||||
return varData[worldIndex(r.__index__)];
|
r => varData[worldIndex(r.__index__)],
|
||||||
}, Float32Array);
|
Float32Array
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createObsDimensionMap(crossfilter, world) {
|
export function createObsDimensionMap(crossfilter, world) {
|
||||||
@@ -317,7 +319,10 @@ export function createObsDimensionMap(crossfilter, world) {
|
|||||||
(result, anno) => {
|
(result, anno) => {
|
||||||
const dimType = deduceDimensionType(anno, anno.name);
|
const dimType = deduceDimensionType(anno, anno.name);
|
||||||
if (dimType) {
|
if (dimType) {
|
||||||
result[anno.name] = crossfilter.dimension(r => r[anno.name], dimType);
|
result[obsAnnoDimensionName(anno.name)] = crossfilter.dimension(
|
||||||
|
r => r[anno.name],
|
||||||
|
dimType
|
||||||
|
);
|
||||||
} // else ignore the annotation
|
} // else ignore the annotation
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
@@ -327,11 +332,11 @@ export function createObsDimensionMap(crossfilter, world) {
|
|||||||
Add crossfilter dimensions allowing filtering on layout
|
Add crossfilter dimensions allowing filtering on layout
|
||||||
*/
|
*/
|
||||||
const worldIndex = worldObsIndex ? idx => worldObsIndex[idx] : idx => idx;
|
const worldIndex = worldObsIndex ? idx => worldObsIndex[idx] : idx => idx;
|
||||||
dimensionMap.x = crossfilter.dimension(
|
dimensionMap[layoutDimensionName("X")] = crossfilter.dimension(
|
||||||
r => obsLayout.X[worldIndex(r.__index__)],
|
r => obsLayout.X[worldIndex(r.__index__)],
|
||||||
Float32Array
|
Float32Array
|
||||||
);
|
);
|
||||||
dimensionMap.y = crossfilter.dimension(
|
dimensionMap[layoutDimensionName("Y")] = crossfilter.dimension(
|
||||||
r => obsLayout.Y[worldIndex(r.__index__)],
|
r => obsLayout.Y[worldIndex(r.__index__)],
|
||||||
Float32Array
|
Float32Array
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user