diff --git a/package.json b/package.json
index 4f702ea1..84c1888f 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"bakana": "~0.6.2",
+ "bakana-remotes": "~0.1.1",
"d3": "^7.1.1",
"epiviz.gl": "^1.0.2",
"epiviz.scatter.gl": "^0.0.5",
diff --git a/src/App.js b/src/App.js
index 15e72f1d..ef3e11c5 100644
--- a/src/App.js
+++ b/src/App.js
@@ -158,7 +158,7 @@ const App = () => {
setGeneColSel, setLoadParams,
setInitLoadState, inputFiles, annotationCols, setAnnotationCols,
annotationObj, setAnnotationObj, preInputFiles,
- setPreInputFilesStatus, geneColSel } = useContext(AppContext);
+ setPreInputFilesStatus, geneColSel, setEhubDatasets } = useContext(AppContext);
// initializes various things on the worker side
useEffect(() => {
@@ -469,6 +469,11 @@ const App = () => {
setKanaIDBRecs(resp);
}
setIndexedDBState(false);
+ } else if (payload.type === "ExperimentHub_store") {
+ const { resp } = payload;
+ if (resp !== undefined && Array.isArray(resp)) {
+ setEhubDatasets(resp);
+ }
} else if (payload.type === "inputs_DATA") {
var info = [];
if ("RNA" in payload.resp.num_genes) {
@@ -488,7 +493,6 @@ const App = () => {
let pmods = Object.keys(payload.resp.genes);
setModality(pmods);
-
} else if (payload.type === "quality_control_DATA") {
const { resp } = payload;
diff --git a/src/components/Analysis/index.js b/src/components/Analysis/index.js
index e3d9dd26..e0efab4d 100644
--- a/src/components/Analysis/index.js
+++ b/src/components/Analysis/index.js
@@ -25,7 +25,8 @@ const AnalysisDialog = ({
tabSelected, setTabSelected,
loadParams,
setLoadParamsFor, loadParamsFor, setDatasetName,
- setPreInputFiles, preInputFilesStatus, setPreInputFilesStatus } = useContext(AppContext);
+ setPreInputFiles, preInputFilesStatus, setPreInputFilesStatus,
+ ehubDatasets } = useContext(AppContext);
const [inputText, setInputText] = useState([]);
@@ -46,7 +47,8 @@ const AnalysisDialog = ({
genes: "Choose feature/gene file",
annotations: "Choose barcode/annotation file",
file: "Choose file...",
- rds: "Choose file..."
+ rds: "Choose file...",
+ id: "Choose id..."
});
let [stmpInputFiles, ssetTmpInputFiles] = useState({
@@ -227,11 +229,21 @@ const AnalysisDialog = ({
) {
all_valid = false;
}
+
+ if (
+ x?.id && !(
+ ehubDatasets.indexOf(inputText[ix]?.id) !== -1
+ )
+ ) {
+ all_valid = false;
+ }
if (x.format === "MatrixMarket") {
if (!x.mtx) all_valid = false;
} else if (x.format === "SummarizedExperiment") {
if (!x.rds) all_valid = false;
+ } else if (x.format === "ExperimentHub") {
+ if (!x.id) all_valid = false;
} else {
if (!x.h5) all_valid = false;
}
@@ -344,6 +356,16 @@ const AnalysisDialog = ({
}
if (!x.rds && (sinputText?.file !== "Choose file...")) all_valid = false;
+ } else if (
+ x.format === "ExperimentHub") {
+ if (x?.id && !(
+ ehubDatasets.indexOf(sinputText?.id) !== -1
+ )
+ ) {
+ all_valid = false;
+ }
+
+ if (!x.id && (sinputText?.id !== "Choose id...")) all_valid = false;
}
// setTmpInputValid(all_valid);
@@ -1197,12 +1219,41 @@ const AnalysisDialog = ({
onInputChange={(msg) => {
if (msg.target.files) {
ssetInputText({ ...sinputText, "rds": msg.target.files[0].name });
- ssetTmpInputFiles({ ...stmpInputFiles, "rds": msg.target.files[0] })
+ ssetTmpInputFiles({ ...stmpInputFiles, "rds": msg.target.files[0] });
}
}} />
} />
+ *.mtx
or *.mtx.gz
*.tsv
or *.tsv.gz
*.h5
or *.hdf5
or *.h5ad
*.rds
*.rds
or
+ A Dataset saved to ExperimentHub
.
+ We support any SummarizedExperiment subclass containing a dense or sparse count matrix
+ (identified as any assay with name starting with "counts", or if none exist, just the first assay).
+ For a SingleCellExperiment, any alternative experiment with name starting with "hto", "adt" or "antibody" is assumed to represent CITE-seq data.
+
Batch correction: you can now import more than one file to integrate and analyze datasets. If you only import a single dataset, specify the annotation column that contains the batch information.
diff --git a/src/context/AppContext.js b/src/context/AppContext.js index 19c37d35..79bf6f8a 100644 --- a/src/context/AppContext.js +++ b/src/context/AppContext.js @@ -15,6 +15,9 @@ const AppContextProvider = ({ children }) => { // Pre flight Input Status const [preInputFilesStatus, setPreInputFilesStatus] = useState(null); + // Ehub datasets + const [ehubDatasets, setEhubDatasets] = useState(null); + // default params const [params, setParams] = useState({ qc: { @@ -129,7 +132,8 @@ const AppContextProvider = ({ children }) => { annotationCols, setAnnotationCols, annotationObj, setAnnotationObj, preInputFiles, setPreInputFiles, - preInputFilesStatus, setPreInputFilesStatus + preInputFilesStatus, setPreInputFilesStatus, + ehubDatasets, setEhubDatasets }} > {children} diff --git a/src/workers/scran.worker.js b/src/workers/scran.worker.js index 4d35b255..f371e916 100644 --- a/src/workers/scran.worker.js +++ b/src/workers/scran.worker.js @@ -4,12 +4,19 @@ import * as downloads from "./DownloadsDBHandler.js"; import * as hashwasm from "hash-wasm"; import * as translate from "./translate.js"; import { extractBuffers, postAttempt, postSuccess, postError } from "./helpers.js"; +import * as remotes from "bakana-remotes"; +import * as ehub from "bakana-remotes/ExperimentHub"; /***************************************/ let superstate = null; +const proxy = "https://cors-proxy.aaron-lun.workers.dev"; +// TODO: consolidate all bakana-related download functions into a single getter/setter. bakana.setCellLabellingDownload(downloads.get); +remotes.setDownloadFun(url => downloads.get(proxy + "/" + encodeURIComponent(url))); + +bakana.availableReaders["ExperimentHub"] = ehub; bakana.setVisualizationAnimate((type, x, y, iter) => { postMessage({ @@ -149,6 +156,20 @@ onmessage = function (msg) { }); }); + try { + let ehub_ids = ehub.availableDatasets(); + postMessage({ + type: "ExperimentHub_store", + resp: ehub_ids, + msg: "Success: ExperimentHub initialized" + }); + } catch { + postMessage({ + type: "ExperimentHub_ERROR", + msg: "Error: Cannot access datasets in ExperimentHub" + }); + } + loaded = Promise.all([ back_init,