mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-29 07:08:11 +08:00
add support for corpora default_embedding field (#1696)
* fix mispelling * re-implement re-embedding * always load base embedding to fetch counts * format * lint * fix tests * lint * fix accept handling * test log * more debug * more * more * more * more * remove logging * logging * jsonify * remove debugging logs * lint * clean up errors a bit * fix issue found in PR review * add support for corpora default_embedding * fix botched merge * PR review * PR review
This commit is contained in:
@@ -58,7 +58,7 @@ const doInitialDataLoad = () =>
|
|||||||
dispatch({ type: "initial data load start" });
|
dispatch({ type: "initial data load start" });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const [, schema] = await Promise.all([
|
const [config, schema] = await Promise.all([
|
||||||
configFetch(dispatch),
|
configFetch(dispatch),
|
||||||
schemaFetch(dispatch),
|
schemaFetch(dispatch),
|
||||||
userColorsFetchAndLoad(dispatch),
|
userColorsFetchAndLoad(dispatch),
|
||||||
@@ -75,6 +75,15 @@ const doInitialDataLoad = () =>
|
|||||||
obsCrossfilter,
|
obsCrossfilter,
|
||||||
});
|
});
|
||||||
dispatch({ type: "initial data load complete" });
|
dispatch({ type: "initial data load complete" });
|
||||||
|
|
||||||
|
const defaultEmbedding = config?.parameters?.["default_embedding"];
|
||||||
|
const layoutSchema = schema?.schema?.layout?.obs ?? [];
|
||||||
|
if (
|
||||||
|
defaultEmbedding &&
|
||||||
|
layoutSchema.some((s) => s.name === defaultEmbedding)
|
||||||
|
) {
|
||||||
|
dispatch(embActions.layoutChoiceAction(defaultEmbedding));
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch({ type: "initial data load error", error });
|
dispatch({ type: "initial data load error", error });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,11 +242,17 @@ class AppConfig(object):
|
|||||||
"about_legal_privacy": dataset_config.app__about_legal_privacy,
|
"about_legal_privacy": dataset_config.app__about_legal_privacy,
|
||||||
}
|
}
|
||||||
|
|
||||||
# dataset_props
|
# corpora dataset_props
|
||||||
# TODO/Note: putting info from the dataset into the /config is not ideal.
|
# TODO/Note: putting info from the dataset into the /config is not ideal.
|
||||||
# However, it is definitely not part of /schema, and we do not have a top-level
|
# However, it is definitely not part of /schema, and we do not have a top-level
|
||||||
# route for data properties. Consider creating one at some point.
|
# route for data properties. Consider creating one at some point.
|
||||||
corpora_props = data_adaptor.get_corpora_props()
|
corpora_props = data_adaptor.get_corpora_props()
|
||||||
|
if corpora_props and "default_embedding" in corpora_props:
|
||||||
|
default_embedding = corpora_props["default_embedding"]
|
||||||
|
if isinstance(default_embedding, str) and default_embedding.startswith("X_"):
|
||||||
|
default_embedding = default_embedding[2:] # drop X_ prefix
|
||||||
|
if default_embedding in data_adaptor.get_embedding_names():
|
||||||
|
parameters["default_embedding"] = default_embedding
|
||||||
|
|
||||||
data_adaptor.update_parameters(parameters)
|
data_adaptor.update_parameters(parameters)
|
||||||
if annotation:
|
if annotation:
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
import unittest
|
import unittest
|
||||||
import anndata
|
import anndata
|
||||||
import json
|
import json
|
||||||
|
import tempfile
|
||||||
|
import shutil
|
||||||
|
from http import HTTPStatus
|
||||||
|
import requests
|
||||||
|
|
||||||
from server.common.corpora import (
|
from server.common.corpora import (
|
||||||
corpora_get_versions_from_anndata,
|
corpora_get_versions_from_anndata,
|
||||||
corpora_is_version_supported,
|
corpora_is_version_supported,
|
||||||
corpora_get_props_from_anndata,
|
corpora_get_props_from_anndata,
|
||||||
)
|
)
|
||||||
from server.test import PROJECT_ROOT
|
from server.test import PROJECT_ROOT, start_test_server, stop_test_server
|
||||||
|
|
||||||
|
VERSION = "v0.2"
|
||||||
|
|
||||||
|
|
||||||
class CorporaAPITest(unittest.TestCase):
|
class CorporaAPITest(unittest.TestCase):
|
||||||
@@ -71,3 +77,70 @@ class CorporaAPITest(unittest.TestCase):
|
|||||||
|
|
||||||
def _get_h5ad(self):
|
def _get_h5ad(self):
|
||||||
return anndata.read_h5ad(f"{PROJECT_ROOT}/example-dataset/pbmc3k.h5ad")
|
return anndata.read_h5ad(f"{PROJECT_ROOT}/example-dataset/pbmc3k.h5ad")
|
||||||
|
|
||||||
|
|
||||||
|
class CorporaRESTAPITest(unittest.TestCase):
|
||||||
|
""" Confirm endpoints reflect Corpora-specific features """
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setCorporaFields(cls, path):
|
||||||
|
adata = anndata.read_h5ad(path)
|
||||||
|
corpora_props = {
|
||||||
|
"version": {
|
||||||
|
"corpora_schema_version": "1.0.0",
|
||||||
|
"corpora_encoding_version": "0.1.0"
|
||||||
|
},
|
||||||
|
"title": "PBMC3K",
|
||||||
|
"contributors": json.dumps([
|
||||||
|
{"name": "name"}
|
||||||
|
]),
|
||||||
|
"layer_descriptions": {
|
||||||
|
"X": "raw counts"
|
||||||
|
},
|
||||||
|
"organism": "human",
|
||||||
|
"organism_ontology_term_id": "unknown",
|
||||||
|
"project_name": "test project",
|
||||||
|
"project_description": "test description",
|
||||||
|
"project_links": json.dumps([
|
||||||
|
{"link_name": "test link", "link_type": "SUMMARY", "link_url": "https://a.u.r.l/"}
|
||||||
|
]),
|
||||||
|
"default_embedding": "X_tsne"
|
||||||
|
}
|
||||||
|
adata.uns.update(corpora_props)
|
||||||
|
adata.write(path)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.tmp_dir = tempfile.TemporaryDirectory()
|
||||||
|
src = f"{PROJECT_ROOT}/example-dataset/pbmc3k.h5ad"
|
||||||
|
dst = f"{cls.tmp_dir.name}/pbmc3k.h5ad"
|
||||||
|
shutil.copyfile(src, dst)
|
||||||
|
cls.setCorporaFields(dst)
|
||||||
|
cls.ps, cls.server = start_test_server([dst])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
stop_test_server(cls.ps)
|
||||||
|
cls.tmp_dir.cleanup()
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.session = requests.Session()
|
||||||
|
self.url_base = f"{self.server}/api/{VERSION}/"
|
||||||
|
|
||||||
|
def test_config(self):
|
||||||
|
endpoint = "config"
|
||||||
|
url = f"{self.url_base}{endpoint}"
|
||||||
|
result = self.session.get(url)
|
||||||
|
self.assertEqual(result.status_code, HTTPStatus.OK)
|
||||||
|
self.assertEqual(result.headers["Content-Type"], "application/json")
|
||||||
|
|
||||||
|
result_data = result.json()
|
||||||
|
self.assertIsInstance(result_data["config"]["corpora_props"], dict)
|
||||||
|
self.assertIsInstance(result_data["config"]["parameters"], dict)
|
||||||
|
|
||||||
|
corpora_props = result_data["config"]["corpora_props"]
|
||||||
|
parameters = result_data["config"]["parameters"]
|
||||||
|
|
||||||
|
self.assertEqual(corpora_props["version"]["corpora_schema_version"], "1.0.0")
|
||||||
|
self.assertEqual(corpora_props["organism"], "human")
|
||||||
|
self.assertEqual(parameters["default_embedding"], "tsne")
|
||||||
|
|||||||
Reference in New Issue
Block a user