Files
cellxgene/client/src/actions/index.js
T

233 lines
6.5 KiB
JavaScript

// jshint esversion: 6
import * as globals from "../globals";
import store from "../reducers";
import URI from "urijs";
import _ from "lodash";
const requestCells = (query = "") => {
return dispatch => {
dispatch({ type: "request cells started" });
return fetch(`${globals.API.prefix}${globals.API.version}cells${query}`, {
method: "get",
headers: new Headers({
"Content-Type": "application/json"
})
})
.then(res => res.json())
.then(
data => dispatch({ type: "request cells success", data }),
error => dispatch({ type: "request cells error", error })
);
};
};
/* SELECT */
const regraph = () => {
return (dispatch, getState) => {
dispatch({ type: "regraph started" });
const state = getState();
const selectedMetadata = {};
_.each(state.controls.categoricalAsBooleansMap, (options, field) => {
let atLeastOneOptionDeselected = false;
_.each(options, (isActive, option) => {
if (!isActive) {
atLeastOneOptionDeselected = true;
}
});
if (atLeastOneOptionDeselected) {
_.each(options, (isActive, option) => {
if (isActive) {
if (selectedMetadata[field]) {
selectedMetadata[field].push(option);
} else if (!selectedMetadata[field]) {
selectedMetadata[field] = [option];
}
}
});
}
});
let uri = new URI();
uri.setSearch(selectedMetadata);
console.log(uri.search(), selectedMetadata);
dispatch(requestCells(uri.search())).then(res => {
if (res.error) {
dispatch({ type: "regraph error" });
} else {
dispatch({ type: "regraph success" });
}
});
};
};
const resetGraph = () => {
return (dispatch, getState) => {
dispatch({ type: "reset graph" });
};
};
const initialize = () => {
return (dispatch, getState) => {
dispatch({ type: "initialize started" });
fetch(`${globals.API.prefix}${globals.API.version}initialize`, {
method: "get",
headers: new Headers({
"Content-Type": "application/json"
})
})
.then(res => res.json())
.then(
data => dispatch({ type: "initialize success", data }),
error => dispatch({ type: "initialize error", error })
);
};
};
// This code defends against the case where /expression returns a cellname
// never seen before (ie, not returned by /cells). This should not happen
// (see https://github.com/chanzuckerberg/cellxgene-rest-api/issues/34) but
// occasionally does.
//
function cleanupExpressionResponse(data) {
const s = store.getState();
const metadata = s.controls.allCellsMetadataMap;
let errorFound = false;
data.data.cells = _.filter(data.data.cells, cell => {
if (!errorFound && !metadata[cell.cellname]) {
errorFound = true;
console.error(
"Warning: /expression REST API returned unexpected cell names -- discarding surprises."
);
}
return metadata[cell.cellname];
});
return data;
}
const requestGeneExpressionCounts = () => {
return (dispatch, getState) => {
dispatch({ type: "get expression started" });
fetch(`${globals.API.prefix}${globals.API.version}expression`, {
method: "get",
headers: new Headers({
accept: "application/json"
})
})
.then(res => res.json())
.then(data => cleanupExpressionResponse(data))
.then(
data => dispatch({ type: "get expression success", data }),
error => dispatch({ type: "get expression error", error })
);
};
};
const requestSingleGeneExpressionCountsForColoringPOST = gene => {
return (dispatch, getState) => {
dispatch({ type: "get single gene expression for coloring started" });
fetch(`${globals.API.prefix}${globals.API.version}expression`, {
method: "POST",
body: JSON.stringify({
genelist: [gene]
}),
headers: new Headers({
accept: "application/json",
"Content-Type": "application/json"
})
})
.then(res => res.json())
.then(data => cleanupExpressionResponse(data))
.then(
data =>
dispatch({
type: "color by expression",
gene: gene,
data
}),
error =>
dispatch({
type: "get single gene expression for coloring error",
error
})
);
};
};
const requestGeneExpressionCountsPOST = genes => {
return (dispatch, getState) => {
dispatch({ type: "get expression started" });
fetch(`${globals.API.prefix}${globals.API.version}expression`, {
method: "POST",
body: JSON.stringify({
genelist: genes
}),
headers: new Headers({
accept: "application/json",
"Content-Type": "application/json"
})
})
.then(res => res.json())
.then(data => cleanupExpressionResponse(data))
.then(
data => dispatch({ type: "get expression success", data }),
error => dispatch({ type: "get expression error", error })
);
};
};
const requestDifferentialExpression = (celllist1, celllist2, num_genes = 7) => {
return (dispatch, getState) => {
dispatch({ type: "request differential expression started" });
fetch(`${globals.API.prefix}${globals.API.version}diffexpression`, {
method: "POST",
body: JSON.stringify({
celllist1,
celllist2,
num_genes
}),
headers: new Headers({
accept: "application/json",
"Content-Type": "application/json"
})
})
.then(res => res.json())
.then(
data => {
/* kick off a secondary action to get all expression counts for all cells now that we know what the top expressed are */
dispatch(
requestGeneExpressionCountsPOST(
_.union(
data.data.celllist1.topgenes,
data.data.celllist2.topgenes
) // ["GPM6B", "FEZ1", "TSPAN31", "PCSK1N", "TUBA1A", "GPM6A", "CLU", "FCER1G", "TYROBP", "C1QB", "CD74", "CYBA", "GPX1", "TMSB4X"]
)
);
/* then send the success case action through */
return dispatch({
type: "request differential expression success",
data
});
},
error =>
dispatch({ type: "request differential expression error", error })
);
};
};
export default {
initialize,
requestCells,
regraph,
resetGraph,
requestGeneExpressionCounts,
requestGeneExpressionCountsPOST,
requestSingleGeneExpressionCountsForColoringPOST,
requestDifferentialExpression
};