Skip to content

Commit

Permalink
Integrate with ExperimentHub datasets (#147)
Browse files Browse the repository at this point in the history
* add bakana-remotes for reading ExpHub files
* UI changes for ExpHub dataset selection

Co-authored-by: LTLA <[email protected]>
  • Loading branch information
jkanche and LTLA authored Oct 25, 2022
1 parent e7d7565 commit 0eb1c83
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 8 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 6 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand Down Expand Up @@ -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) {
Expand All @@ -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;

Expand Down
72 changes: 67 additions & 5 deletions src/components/Analysis/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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([]);

Expand All @@ -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({
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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] });
}
}} />
</Label>
</div>
} />
<Tab id="ExperimentHub" title="Experiment Hub" panel={
<div className="row"
>
<Label className="row-input">
<Text className="text-100">
<span>
Choose an ExperimentHub dataset id:
</span>
</Text>
{Array.isArray(ehubDatasets) ?
<HTMLSelect
onChange={(e) => {
if (e.target.value && e.target.value !== "none") {
ssetInputText({ ...sinputText, "id": e.target.value });
ssetTmpInputFiles({ ...stmpInputFiles, "id": e.target.value });
}
}}
defaultValue={"none"}
>
<option value="none">None</option>
{
ehubDatasets.map((x, i) => <option key={i} value={x}>{x}</option>)
}
</HTMLSelect>
: "No ExperimentHub datasets available"
}
</Label>
</div>
} />
</Tabs>
</div>
</div>
Expand Down Expand Up @@ -1529,6 +1580,8 @@ const AnalysisDialog = ({
}
} else if (row["format"] === "SummarizedExperiment") {
tname += ` file: ${row.rds.name} `;
} else if (row["format"] === "ExperimentHub") {
tname += ` file: ${row.id} `;
} else {
tname += ` file: ${row.h5.name} `;
}
Expand Down Expand Up @@ -1652,7 +1705,8 @@ const AnalysisDialog = ({
mtx: "Choose Matrix Market file",
genes: "Choose feature/gene file",
annotations: "Choose barcode/annotation file",
file: "Choose file..."
file: "Choose file...",
id: "Choose id..."
});

ssetTmpInputFiles({
Expand Down Expand Up @@ -1988,7 +2042,8 @@ const AnalysisDialog = ({
<li>Matrix Market - <code>*.mtx</code> or <code>*.mtx.gz</code></li>
<li>features or genes, <code>*.tsv</code> or <code>*.tsv.gz</code></li>
<li>HDF5 (10X or H5AD) - <code>*.h5</code> or <code>*.hdf5</code> or <code>*.h5ad</code></li>
<li>RDS - <code>*.rds</code></li>
<li>RDS - <code>*.rds</code> or </li>
<li>ExperimentHub ID</li>
</ul>

Note: Names of dataset must be unique!
Expand Down Expand Up @@ -2024,6 +2079,13 @@ const AnalysisDialog = ({
For a SingleCellExperiment, any alternative experiment with name starting with "hto", "adt" or "antibody" is assumed to represent CITE-seq data.
</p>

<p>
<strong>A Dataset saved to <code>ExperimentHub</code>. </strong>
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.
</p>

<p><strong>Batch correction:</strong> 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.</p>
</Callout>
Expand Down
6 changes: 5 additions & 1 deletion src/context/AppContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -129,7 +132,8 @@ const AppContextProvider = ({ children }) => {
annotationCols, setAnnotationCols,
annotationObj, setAnnotationObj,
preInputFiles, setPreInputFiles,
preInputFilesStatus, setPreInputFilesStatus
preInputFilesStatus, setPreInputFilesStatus,
ehubDatasets, setEhubDatasets
}}
>
{children}
Expand Down
21 changes: 21 additions & 0 deletions src/workers/scran.worker.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 0eb1c83

Please sign in to comment.