diff --git a/server/common/app_config.py b/server/common/app_config.py index 7e8a3635..3731f9b4 100644 --- a/server/common/app_config.py +++ b/server/common/app_config.py @@ -782,12 +782,14 @@ class DatasetConfig(BaseConfig): self.check_attr("embeddings__names", list) self.check_attr("embeddings__enable_reembedding", bool) - if self.app_config.server_config.single_dataset__datapath: + server_config = self.app_config.server_config + if server_config.single_dataset__datapath: if self.embeddings__enable_reembedding: - matrix_data_loader = MatrixDataLoader(self.single_dataset__datapath, app_config=self.app_config) - if matrix_data_loader.matrix_data_type() != MatrixDataType.H5AD: + matrix_data_loader = MatrixDataLoader( + server_config.single_dataset__datapath, app_config=self.app_config) + if matrix_data_loader.matrix_data_type != MatrixDataType.H5AD: raise ConfigurationError("'enable-reembedding is only supported with H5AD files.") - if self.adaptor__anndata_adaptor__backed: + if server_config.adaptor__anndata_adaptor__backed: raise ConfigurationError("enable-reembedding is not supported when run in --backed mode.") def handle_diffexp(self, context): diff --git a/server/common/rest.py b/server/common/rest.py index a1e1a9ae..0a0c2b50 100644 --- a/server/common/rest.py +++ b/server/common/rest.py @@ -301,7 +301,7 @@ def layout_obs_get(request, data_adaptor): def layout_obs_put(request, data_adaptor): - if not data_adaptor.dataset_config.embedding__enable_reembedding: + if not data_adaptor.dataset_config.embeddings__enable_reembedding: return abort(HTTPStatus.NOT_IMPLEMENTED) preferred_mimetype = request.accept_mimetypes.best_match(["application/octet-stream"]) diff --git a/server/requirements-dev.txt b/server/requirements-dev.txt index 291ff9c1..88def55a 100644 --- a/server/requirements-dev.txt +++ b/server/requirements-dev.txt @@ -4,4 +4,5 @@ parameterized>=0.7.0 pytest>=3.6.3 twine>=1.12.1 codecov>=2.0.15 +scanpy>=1.4.6 -r requirements.txt diff --git a/server/test/test_api.py b/server/test/test_api.py index 4db3aea5..dad7ea5e 100644 --- a/server/test/test_api.py +++ b/server/test/test_api.py @@ -66,6 +66,32 @@ class EndPoints(object): self.assertIsNone(df["row_idx"]) self.assertEqual(len(df["columns"]), df["n_cols"]) + def test_put_layout_fbs(self): + # first check that re-embedding is turned on + result = self.session.get(f"{self.URL_BASE}config") + config_data = result.json() + re_embed = config_data["config"]["parameters"]["enable-reembedding"] + if not re_embed: + return + # attempt to reembed with umap over 100 cells. + endpoint = "layout/obs" + url = f"{self.URL_BASE}{endpoint}" + header = {"Accept": "application/octet-stream"} + data = {} + data["filter"] = {} + data["filter"]["obs"] = {} + data["filter"]["obs"]["index"] = list(range(100)) + data["method"] = "umap" + result = self.session.put(url, headers=header, json=data) + + self.assertEqual(result.status_code, HTTPStatus.OK) + df = decode_fbs.decode_matrix_FBS(result.content) + self.assertEqual(df["n_rows"], 100) + self.assertEqual(df["n_cols"], 2) + cols = list(df["col_idx"]) + self.assertTrue(cols[0].startswith("reembed:umap_") and cols[0].endswith("_0")) + self.assertTrue(cols[1].startswith("reembed:umap_") and cols[1].endswith("_1")) + def test_bad_filter(self): endpoint = "data/var" url = f"{self.URL_BASE}{endpoint}" @@ -376,6 +402,7 @@ class EndPointsAnndata(unittest.TestCase, EndPoints): f"{PROJECT_ROOT}/example-dataset/pbmc3k.h5ad", "--disable-annotations", "--verbose", + "--experimental-enable-reembedding", "--port", str(cls.PORT), ],