mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-08 14:48:12 +08:00
adding and removing user defined genes
This commit is contained in:
@@ -184,8 +184,21 @@ class HistogramBrush extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeHistogram() {
|
||||||
|
const { dispatch, field, colorAccessor } = this.props;
|
||||||
|
dispatch({
|
||||||
|
type: "clear user defined gene",
|
||||||
|
data: field
|
||||||
|
});
|
||||||
|
if (field === colorAccessor) {
|
||||||
|
dispatch({
|
||||||
|
type: "reset colorscale"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { field, ranges, colorAccessor } = this.props;
|
const { field, ranges, colorAccessor, isUserDefined } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -195,7 +208,22 @@ class HistogramBrush extends React.Component {
|
|||||||
}}
|
}}
|
||||||
id={`histogram_${field}`}
|
id={`histogram_${field}`}
|
||||||
>
|
>
|
||||||
<p style={{ fontSize: globals.tiniestFontSize }}> {field} </p>
|
<div>
|
||||||
|
<span style={{ fontSize: globals.tiniestFontSize }}> {field} </span>
|
||||||
|
{isUserDefined ? (
|
||||||
|
<span
|
||||||
|
onClick={this.removeHistogram.bind(this)}
|
||||||
|
style={{
|
||||||
|
fontSize: globals.tiniestFontSize,
|
||||||
|
color: globals.blue,
|
||||||
|
cursor: "pointer",
|
||||||
|
marginLeft: 7
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
remove
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
<svg
|
<svg
|
||||||
width={this.width}
|
width={this.width}
|
||||||
height={this.height}
|
height={this.height}
|
||||||
|
|||||||
@@ -13,16 +13,17 @@ import HistogramBrush from "../brushableHistogram/";
|
|||||||
metadata: _.get(state.controls.world, "obsAnnotations", null),
|
metadata: _.get(state.controls.world, "obsAnnotations", null),
|
||||||
colorAccessor: state.controls.colorAccessor,
|
colorAccessor: state.controls.colorAccessor,
|
||||||
colorScale: state.controls.colorScale,
|
colorScale: state.controls.colorScale,
|
||||||
selectionUpdate: _.get(state.controls, "crossfilter.updateTime", null)
|
selectionUpdate: _.get(state.controls, "crossfilter.updateTime", null),
|
||||||
|
schema: _.get(state.controls.world, "schema", null)
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
class Continuous extends React.Component {
|
class Continuous extends React.Component {
|
||||||
handleBrushAction(selection) {
|
constructor(props) {
|
||||||
const { dispatch } = this.props;
|
super(props);
|
||||||
dispatch({
|
this.hasContinuous = false;
|
||||||
type: "continuous selection using parallel coords brushing",
|
this.continuousChecked = false;
|
||||||
data: selection
|
|
||||||
});
|
this.state = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleColorAction(key) {
|
handleColorAction(key) {
|
||||||
@@ -36,11 +37,20 @@ class Continuous extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { ranges, obsAnnotations } = this.props;
|
const { ranges, obsAnnotations, schema } = this.props;
|
||||||
|
if (schema && !this.continuousChecked) {
|
||||||
|
this.hasContinuous = _.some(schema.annotations.obs, d => {
|
||||||
|
return d.type === "int32" || d.type === "float32";
|
||||||
|
});
|
||||||
|
this.continuousChecked = true; /* only do this once */
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
{this.hasContinuous ? <p> Continuous metadata </p> : null}
|
||||||
{_.map(ranges, (value, key) => {
|
{_.map(ranges, (value, key) => {
|
||||||
const isColorField = key.includes("color") || key.includes("Color");
|
const isColorField = key.includes("color") || key.includes("Color");
|
||||||
if (value.range && key !== "name" && !isColorField) {
|
if (value.range && key !== "name" && !isColorField) {
|
||||||
|
|||||||
@@ -9,17 +9,23 @@ import actions from "../../actions";
|
|||||||
@connect()
|
@connect()
|
||||||
class CellSetButton extends React.Component {
|
class CellSetButton extends React.Component {
|
||||||
set() {
|
set() {
|
||||||
|
const { differential } = this.props;
|
||||||
|
|
||||||
const set = _.map(this.props.crossfilter.allFiltered(), "name");
|
const set = _.map(this.props.crossfilter.allFiltered(), "name");
|
||||||
|
|
||||||
this.props.dispatch({
|
if (!differential.diffExp) {
|
||||||
type:
|
/* diffexp needs to be cleared before we store a new set */
|
||||||
"store current cell selection as differential set " +
|
this.props.dispatch({
|
||||||
this.props.eitherCellSetOneOrTwo,
|
type:
|
||||||
data: set
|
"store current cell selection as differential set " +
|
||||||
});
|
this.props.eitherCellSetOneOrTwo,
|
||||||
|
data: set
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { differential } = this.props;
|
||||||
return (
|
return (
|
||||||
<span style={{ marginRight: 10 }}>
|
<span style={{ marginRight: 10 }}>
|
||||||
<button
|
<button
|
||||||
@@ -28,7 +34,9 @@ class CellSetButton extends React.Component {
|
|||||||
borderRadius: 2,
|
borderRadius: 2,
|
||||||
padding: "0px 10px",
|
padding: "0px 10px",
|
||||||
height: 30,
|
height: 30,
|
||||||
backgroundColor: globals.brightBlue,
|
backgroundColor: !differential.diffExp
|
||||||
|
? globals.brightBlue
|
||||||
|
: globals.lightGrey,
|
||||||
border: "none",
|
border: "none",
|
||||||
cursor: "pointer"
|
cursor: "pointer"
|
||||||
}}
|
}}
|
||||||
@@ -47,7 +55,7 @@ class CellSetButton extends React.Component {
|
|||||||
top: 0
|
top: 0
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{this.props.differential[
|
{differential[
|
||||||
"celllist" + this.props.eitherCellSetOneOrTwo
|
"celllist" + this.props.eitherCellSetOneOrTwo
|
||||||
]
|
]
|
||||||
? this.props.differential[
|
? this.props.differential[
|
||||||
|
|||||||
@@ -36,19 +36,43 @@ class GeneExpression extends React.Component {
|
|||||||
ctx: null,
|
ctx: null,
|
||||||
axes: null,
|
axes: null,
|
||||||
dimensions: null,
|
dimensions: null,
|
||||||
gene: null
|
gene: ""
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
keyPress(e) {
|
||||||
|
if (e.keyCode == 13) {
|
||||||
|
this.handleClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
handleClick() {
|
||||||
|
const { world, dispatch, userDefinedGenes } = this.props;
|
||||||
|
|
||||||
|
if (userDefinedGenes.indexOf(this.state.gene) !== -1) {
|
||||||
|
console.log("That gene already exists");
|
||||||
|
} else if (userDefinedGenes.length > 15) {
|
||||||
|
console.log(
|
||||||
|
"That's too many genes, you can have at most 15 user defined genes"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
dispatch(actions.requestGeneExpressionCountsPOST([this.state.gene]));
|
||||||
|
dispatch({
|
||||||
|
type: "user defined gene",
|
||||||
|
data: this.state.gene
|
||||||
|
});
|
||||||
|
this.setState({ gene: "" });
|
||||||
|
}
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
const { world, userDefinedGenes } = this.props;
|
const { world, userDefinedGenes } = this.props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
|
onKeyDown={this.keyPress.bind(this)}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
this.setState({ gene: e.target.value });
|
this.setState({ gene: e.target.value });
|
||||||
}}
|
}}
|
||||||
type="text"
|
type="text"
|
||||||
|
value={this.state.gene}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
style={{
|
style={{
|
||||||
@@ -59,23 +83,7 @@ class GeneExpression extends React.Component {
|
|||||||
marginTop: 20,
|
marginTop: 20,
|
||||||
padding: 0
|
padding: 0
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={this.handleClick.bind(this)}
|
||||||
if (userDefinedGenes.indexOf(this.state.gene) !== -1) {
|
|
||||||
console.log("That gene already exists");
|
|
||||||
} else if (userDefinedGenes.length > 15) {
|
|
||||||
console.log(
|
|
||||||
"That's too many genes, you can have at most 15 user defined genes"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.props.dispatch(
|
|
||||||
actions.requestGeneExpressionCountsPOST([this.state.gene])
|
|
||||||
);
|
|
||||||
this.props.dispatch({
|
|
||||||
type: "user defined gene",
|
|
||||||
data: this.state.gene
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<CirclePlus
|
<CirclePlus
|
||||||
style={{
|
style={{
|
||||||
@@ -101,7 +109,7 @@ class GeneExpression extends React.Component {
|
|||||||
key={geneName}
|
key={geneName}
|
||||||
field={geneName}
|
field={geneName}
|
||||||
ranges={d3.extent(values)}
|
ranges={d3.extent(values)}
|
||||||
isUserSelected
|
isUserDefined
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+23
-3
@@ -185,15 +185,35 @@ const Controls = (
|
|||||||
varDataCache: worldVarDataCache
|
varDataCache: worldVarDataCache
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
case "user defined gene":
|
case "user defined gene": {
|
||||||
const newUserDefinedGenes = state.userDefinedGenes.slice();
|
const newUserDefinedGenes = state.userDefinedGenes.slice();
|
||||||
newUserDefinedGenes.push(action.data);
|
newUserDefinedGenes.push(action.data);
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
userDefinedGenes: newUserDefinedGenes
|
userDefinedGenes: newUserDefinedGenes
|
||||||
};
|
};
|
||||||
case "clear user defined gene":
|
}
|
||||||
|
case "clear user defined gene": {
|
||||||
|
const { userDefinedGenes } = state;
|
||||||
|
const newUserDefinedGenes = _.filter(userDefinedGenes, d => {
|
||||||
|
return d !== action.data;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
userDefinedGenes: newUserDefinedGenes
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case "reset colorscale": {
|
||||||
|
const { world } = state;
|
||||||
|
const colorName = new Array(world.nObs).fill(globals.defaultCellColor);
|
||||||
|
const colorRGB = _.map(colorName, c => parseRGB(c));
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
colorName,
|
||||||
|
colorRGB,
|
||||||
|
colorAccessor: null
|
||||||
|
};
|
||||||
|
}
|
||||||
case "expression load error":
|
case "expression load error":
|
||||||
case "initial data load error": {
|
case "initial data load error": {
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user