diff --git a/server/data_anndata/anndata_adaptor.py b/server/data_anndata/anndata_adaptor.py index de0361ec..d71331c3 100644 --- a/server/data_anndata/anndata_adaptor.py +++ b/server/data_anndata/anndata_adaptor.py @@ -236,6 +236,14 @@ class AnndataAdaptor(DataAdaptor): warnings.warn( f"Anndata data matrix is in {self.data.X.dtype} format not float32. " f"Precision may be truncated." ) + if self.data.X.dtype < np.float32: + if self.data.isbacked: + raise DatasetAccessError(f"Data matrix in {self.data.X.dtype} format is not supported in backed mode." + " Please reload without --backed, or convert matrix to float32") + warnings.warn( + f"Anndata data matrix is in unsupported {self.data.X.dtype} format -- will be cast to float32" + ) + self.data.X = self.data.X.astype(np.float32) for ax in Axis: curr_axis = getattr(self.data, str(ax)) for ann in curr_axis: diff --git a/test/fixtures/pbmc3k_16.h5ad b/test/fixtures/pbmc3k_16.h5ad new file mode 100644 index 00000000..71aee9ee Binary files /dev/null and b/test/fixtures/pbmc3k_16.h5ad differ diff --git a/test/unit/data_anndata/test_anndata_adaptor.py b/test/unit/data_anndata/test_anndata_adaptor.py index 3d54f0d5..f8ae8a86 100644 --- a/test/unit/data_anndata/test_anndata_adaptor.py +++ b/test/unit/data_anndata/test_anndata_adaptor.py @@ -1,5 +1,4 @@ import json -import sys import time import unittest @@ -37,6 +36,7 @@ Test the anndata adaptor using the pbmc3k data set. (f"{FIXTURES_ROOT}/pbmc3k-CSC-gz.h5ad", True, "normal"), (f"{FIXTURES_ROOT}/pbmc3k-CSR-gz.h5ad", True, "normal"), (f"{FIXTURES_ROOT}/pbmc3k_64.h5ad", False, "auto"), # 64 bit conversion tests + (f"{FIXTURES_ROOT}/pbmc3k_16.h5ad", False, "auto"), # 16 bit conversion tests ], ) class AdaptorTest(unittest.TestCase): diff --git a/test/unit/data_anndata/test_anndata_adaptor_errors.py b/test/unit/data_anndata/test_anndata_adaptor_errors.py new file mode 100644 index 00000000..8c3ed609 --- /dev/null +++ b/test/unit/data_anndata/test_anndata_adaptor_errors.py @@ -0,0 +1,23 @@ +import unittest + +from parameterized import parameterized_class + +from server.common.errors import DatasetAccessError +from test import FIXTURES_ROOT +from test.unit import app_config + + +@parameterized_class( + ("data_locator", "backed", "X_approximate_distribution"), + [ + (f"{FIXTURES_ROOT}/pbmc3k_16.h5ad", True, "auto"), # 16 bit conversion tests + ], +) +class AdaptorLoadErrorTest(unittest.TestCase): + def test_float16_backed_raises_err(self): + with self.assertRaises(DatasetAccessError): + config = app_config( + self.data_locator, + backed=self.backed, + extra_dataset_config=dict(X_approximate_distribution=self.X_approximate_distribution), + )