mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-07 08:08:11 +08:00
clean up type inferencing (#2332)
* unit tests for 64 bit conversion * clean up type handling * type inference tests * more type inference fixes * use schema to determine user intent for data typing * stop using deprecated API * fbs type encoding test * add missing test * add more tests * correctly infer X type for CXG adaptor * lint * fix typo * ts migration * cleanup from PR review * lint * PR review changes
This commit is contained in:
@@ -10,7 +10,7 @@ from flask import current_app
|
||||
from backend.czi_hosted.common.annotations.annotations import Annotations
|
||||
from backend.common.errors import AnnotationCategoryNameError
|
||||
from backend.czi_hosted.common.utils.sanitization_utils import sanitize_values_in_list
|
||||
from backend.common.utils.type_conversion_utils import get_dtypes_and_schemas_of_dataframe, get_dtype_of_array
|
||||
from backend.common.utils.type_conversion_utils import get_dtypes_and_schemas_of_dataframe, get_encoding_dtype_of_array
|
||||
from backend.czi_hosted.db.cellxgene_orm import Annotation
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ class AnnotationsHostedTileDB(Annotations):
|
||||
# convert to tiledb datatypes
|
||||
|
||||
for col in df:
|
||||
df[col] = df[col].astype(get_dtype_of_array(df[col]))
|
||||
df[col] = df[col].astype(get_encoding_dtype_of_array(df[col]))
|
||||
tiledb.from_pandas(uri, df, sparse=True)
|
||||
else:
|
||||
uri = ""
|
||||
|
||||
@@ -3,7 +3,7 @@ import json
|
||||
import numpy as np
|
||||
import tiledb
|
||||
|
||||
from backend.common.utils.type_conversion_utils import get_dtype_of_array, get_dtype_and_schema_of_array
|
||||
from backend.common.utils.type_conversion_utils import get_encoding_dtype_of_array, get_dtype_and_schema_of_array
|
||||
|
||||
|
||||
def convert_dictionary_to_cxg_group(cxg_container, metadata_dict, group_metadata_name="cxg_group_metadata"):
|
||||
@@ -47,7 +47,7 @@ def convert_dataframe_to_cxg_array(cxg_container, dataframe_name, dataframe, ind
|
||||
]
|
||||
)
|
||||
attrs = [
|
||||
tiledb.Attr(name=column, dtype=get_dtype_of_array(dataframe[column]), filters=tiledb_filter)
|
||||
tiledb.Attr(name=column, dtype=get_encoding_dtype_of_array(dataframe[column]), filters=tiledb_filter)
|
||||
for column in dataframe
|
||||
]
|
||||
domain = tiledb.Domain(
|
||||
|
||||
@@ -66,11 +66,11 @@ class AnndataAdaptor(DataAdaptor):
|
||||
|
||||
@staticmethod
|
||||
def _create_unique_column_name(df, col_name_prefix):
|
||||
""" given the columns of a dataframe, and a name prefix, return a column name which
|
||||
does not exist in the dataframe, AND which is prefixed by `prefix`
|
||||
"""given the columns of a dataframe, and a name prefix, return a column name which
|
||||
does not exist in the dataframe, AND which is prefixed by `prefix`
|
||||
|
||||
The approach is to append a numeric suffix, starting at zero and increasing by
|
||||
one, until an unused name is found (eg, prefix_0, prefix_1, ...).
|
||||
The approach is to append a numeric suffix, starting at zero and increasing by
|
||||
one, until an unused name is found (eg, prefix_0, prefix_1, ...).
|
||||
"""
|
||||
suffix = 0
|
||||
while f"{col_name_prefix}{suffix}" in df:
|
||||
@@ -124,7 +124,11 @@ class AnndataAdaptor(DataAdaptor):
|
||||
|
||||
def _create_schema(self):
|
||||
self.schema = {
|
||||
"dataframe": {"nObs": self.cell_count, "nVar": self.gene_count, "type": str(self.data.X.dtype)},
|
||||
"dataframe": {
|
||||
"nObs": self.cell_count,
|
||||
"nVar": self.gene_count,
|
||||
**get_schema_type_hint_of_array(self.data.X),
|
||||
},
|
||||
"annotations": {
|
||||
"obs": {"index": self.parameters.get("obs_names"), "columns": []},
|
||||
"var": {"index": self.parameters.get("var_names"), "columns": []},
|
||||
@@ -201,10 +205,10 @@ class AnndataAdaptor(DataAdaptor):
|
||||
self.parameters.update({"diffexp_may_be_slow": True})
|
||||
|
||||
def _is_valid_layout(self, arr):
|
||||
""" return True if this layout data is a valid array for front-end presentation:
|
||||
* ndarray, dtype float/int/uint
|
||||
* with shape (n_obs, >= 2)
|
||||
* with all values finite or NaN (no +Inf or -Inf)
|
||||
"""return True if this layout data is a valid array for front-end presentation:
|
||||
* ndarray, dtype float/int/uint
|
||||
* with shape (n_obs, >= 2)
|
||||
* with all values finite or NaN (no +Inf or -Inf)
|
||||
"""
|
||||
is_valid = type(arr) == np.ndarray and arr.dtype.kind in "fiu"
|
||||
is_valid = is_valid and arr.shape[0] == self.data.n_obs and arr.shape[1] >= 2
|
||||
|
||||
@@ -210,7 +210,8 @@ class CxgAdaptor(DataAdaptor):
|
||||
if lfc_cutoff is None:
|
||||
lfc_cutoff = self.dataset_config.diffexp__lfc_cutoff
|
||||
return diffexp_cxg.diffexp_ttest(
|
||||
adaptor=self, maskA=maskA, maskB=maskB, top_n=top_n, diffexp_lfc_cutoff=lfc_cutoff)
|
||||
adaptor=self, maskA=maskA, maskB=maskB, top_n=top_n, diffexp_lfc_cutoff=lfc_cutoff
|
||||
)
|
||||
|
||||
def get_colors(self):
|
||||
if self.cxg_version == "0.0":
|
||||
@@ -357,7 +358,7 @@ class CxgAdaptor(DataAdaptor):
|
||||
shape = self.get_shape()
|
||||
dtype = self.get_X_array_dtype()
|
||||
|
||||
dataframe = {"nObs": shape[0], "nVar": shape[1], "type": dtype.name}
|
||||
dataframe = {"nObs": shape[0], "nVar": shape[1], **get_schema_type_hint_from_dtype(dtype)}
|
||||
|
||||
annotations = {}
|
||||
for ax in ("obs", "var"):
|
||||
|
||||
Reference in New Issue
Block a user