mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-24 08:58: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() {
|
||||
const { field, ranges, colorAccessor } = this.props;
|
||||
const { field, ranges, colorAccessor, isUserDefined } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -195,7 +208,22 @@ class HistogramBrush extends React.Component {
|
||||
}}
|
||||
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
|
||||
width={this.width}
|
||||
height={this.height}
|
||||
|
||||
@@ -13,16 +13,17 @@ import HistogramBrush from "../brushableHistogram/";
|
||||
metadata: _.get(state.controls.world, "obsAnnotations", null),
|
||||
colorAccessor: state.controls.colorAccessor,
|
||||
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 {
|
||||
handleBrushAction(selection) {
|
||||
const { dispatch } = this.props;
|
||||
dispatch({
|
||||
type: "continuous selection using parallel coords brushing",
|
||||
data: selection
|
||||
});
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.hasContinuous = false;
|
||||
this.continuousChecked = false;
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
handleColorAction(key) {
|
||||
@@ -36,11 +37,20 @@ class Continuous extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate() {}
|
||||
|
||||
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 (
|
||||
<div>
|
||||
{this.hasContinuous ? <p> Continuous metadata </p> : null}
|
||||
{_.map(ranges, (value, key) => {
|
||||
const isColorField = key.includes("color") || key.includes("Color");
|
||||
if (value.range && key !== "name" && !isColorField) {
|
||||
|
||||
@@ -9,17 +9,23 @@ import actions from "../../actions";
|
||||
@connect()
|
||||
class CellSetButton extends React.Component {
|
||||
set() {
|
||||
const { differential } = this.props;
|
||||
|
||||
const set = _.map(this.props.crossfilter.allFiltered(), "name");
|
||||
|
||||
this.props.dispatch({
|
||||
type:
|
||||
"store current cell selection as differential set " +
|
||||
this.props.eitherCellSetOneOrTwo,
|
||||
data: set
|
||||
});
|
||||
if (!differential.diffExp) {
|
||||
/* diffexp needs to be cleared before we store a new set */
|
||||
this.props.dispatch({
|
||||
type:
|
||||
"store current cell selection as differential set " +
|
||||
this.props.eitherCellSetOneOrTwo,
|
||||
data: set
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { differential } = this.props;
|
||||
return (
|
||||
<span style={{ marginRight: 10 }}>
|
||||
<button
|
||||
@@ -28,7 +34,9 @@ class CellSetButton extends React.Component {
|
||||
borderRadius: 2,
|
||||
padding: "0px 10px",
|
||||
height: 30,
|
||||
backgroundColor: globals.brightBlue,
|
||||
backgroundColor: !differential.diffExp
|
||||
? globals.brightBlue
|
||||
: globals.lightGrey,
|
||||
border: "none",
|
||||
cursor: "pointer"
|
||||
}}
|
||||
@@ -47,7 +55,7 @@ class CellSetButton extends React.Component {
|
||||
top: 0
|
||||
}}
|
||||
>
|
||||
{this.props.differential[
|
||||
{differential[
|
||||
"celllist" + this.props.eitherCellSetOneOrTwo
|
||||
]
|
||||
? this.props.differential[
|
||||
|
||||
@@ -36,19 +36,43 @@ class GeneExpression extends React.Component {
|
||||
ctx: null,
|
||||
axes: 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() {
|
||||
const { world, userDefinedGenes } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<input
|
||||
onKeyDown={this.keyPress.bind(this)}
|
||||
onChange={e => {
|
||||
this.setState({ gene: e.target.value });
|
||||
}}
|
||||
type="text"
|
||||
value={this.state.gene}
|
||||
/>
|
||||
<button
|
||||
style={{
|
||||
@@ -59,23 +83,7 @@ class GeneExpression extends React.Component {
|
||||
marginTop: 20,
|
||||
padding: 0
|
||||
}}
|
||||
onClick={() => {
|
||||
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
|
||||
});
|
||||
}
|
||||
}}
|
||||
onClick={this.handleClick.bind(this)}
|
||||
>
|
||||
<CirclePlus
|
||||
style={{
|
||||
@@ -101,7 +109,7 @@ class GeneExpression extends React.Component {
|
||||
key={geneName}
|
||||
field={geneName}
|
||||
ranges={d3.extent(values)}
|
||||
isUserSelected
|
||||
isUserDefined
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Vendored
+23
-3
@@ -185,15 +185,35 @@ const Controls = (
|
||||
varDataCache: worldVarDataCache
|
||||
}
|
||||
};
|
||||
case "user defined gene":
|
||||
case "user defined gene": {
|
||||
const newUserDefinedGenes = state.userDefinedGenes.slice();
|
||||
newUserDefinedGenes.push(action.data);
|
||||
return {
|
||||
...state,
|
||||
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 "initial data load error": {
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user