adding and removing user defined genes

This commit is contained in:
Colin Megill
2018-10-15 11:20:52 -07:00
parent 5b2c07f105
commit 8d07b400be
5 changed files with 114 additions and 40 deletions
@@ -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}
+18 -8
View File
@@ -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[
+27 -19
View File
@@ -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
/> />
); );
} }
+23 -3
View File
@@ -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 {