Skip to content

Commit

Permalink
Use true ASCII attributes in dataframes
Browse files Browse the repository at this point in the history
  • Loading branch information
johnkerl committed Oct 4, 2022
1 parent ae2bde1 commit a8dbbb2
Show file tree
Hide file tree
Showing 5 changed files with 14 additions and 49 deletions.
8 changes: 4 additions & 4 deletions apis/python/src/tiledbsoma/soma_dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pyarrow as pa
import tiledb

from . import util, util_arrow, util_pandas, util_tiledb
from . import util, util_arrow, util_tiledb
from .logging import log_io
from .soma_collection import SOMACollectionBase
from .tiledb_array import TileDBArray
Expand Down Expand Up @@ -226,7 +226,7 @@ def read(
# Also: don't materialize these on read
# TODO: get the arrow syntax for drop
# df.drop(ROWID, axis=1)
yield util_arrow.ascii_to_unicode_pyarrow_readback(table)
yield table

def read_all(
self,
Expand Down Expand Up @@ -363,7 +363,7 @@ def read_as_pandas(
# This is the 'decode on read' part of our logic; in dim_select we have the 'encode on
# write' part.
# Context: https://github.com/single-cell-data/TileDB-SOMA/issues/99.
df = util_pandas.ascii_to_unicode_pandas_readback(df)
df = df

if id_column_name is not None:
df.reset_index(inplace=True)
Expand Down Expand Up @@ -477,7 +477,7 @@ def write_from_pandas(
dfc = dataframe[column_name]
if len(dfc) > 0 and type(dfc[0]) == str:
# Force ASCII storage if string, in order to make obs/var columns queryable.
column_types[column_name] = np.dtype("S")
column_types[column_name] = "ascii"

tiledb.from_pandas(
uri=self.uri,
Expand Down
6 changes: 1 addition & 5 deletions apis/python/src/tiledbsoma/soma_indexed_dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,7 @@ def read(
iterator = query.df[ids]

for table in iterator:
# XXX COMMENT MORE
# This is the 'decode on read' part of our logic; in dim_select we have the
# 'encode on write' part.
# Context: # https://github.com/single-cell-data/TileDB-SOMA/issues/99.
yield util_arrow.ascii_to_unicode_pyarrow_readback(table)
yield table

def read_all(
self,
Expand Down
34 changes: 8 additions & 26 deletions apis/python/src/tiledbsoma/util_arrow.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,7 @@
#
# IMPORTANT: ALL non-primitive types supported by TileDB must be in this table.
#
pa.string(): np.dtype(
"S"
), # XXX TODO: temporary work-around until UTF8 support is native. GH #338.
pa.string(): "ascii", # XXX TODO: temporary work-around until UTF8 support is native. GH #338.
pa.binary(): np.dtype("S"),
pa.timestamp("s"): "datetime64[s]",
pa.timestamp("ms"): "datetime64[ms]",
Expand All @@ -39,7 +37,7 @@
}


def tiledb_type_from_arrow_type(t: pa.DataType) -> Union[type, np.dtype]:
def tiledb_type_from_arrow_type(t: pa.DataType) -> Union[type, np.dtype, str]:
"""
Given an Arrow type, return the corresponding TileDB type as a Numpy dtype.
Building block for Arrow-to-TileDB schema translation.
Expand All @@ -61,7 +59,10 @@ def tiledb_type_from_arrow_type(t: pa.DataType) -> Union[type, np.dtype]:
arrow_type = ARROW_TO_TDB[t]
if isinstance(arrow_type, Exception):
raise arrow_type
return np.dtype(arrow_type)
if arrow_type == "ascii":
return arrow_type
else:
return np.dtype(arrow_type)

if not pa.types.is_primitive(t):
raise TypeError(f"Type {str(t)} - unsupported type")
Expand All @@ -83,11 +84,11 @@ def tiledb_type_from_arrow_type(t: pa.DataType) -> Union[type, np.dtype]:
raise TypeError("Unsupported Arrow type") from exc


def get_arrow_type_from_tiledb_dtype(tiledb_dtype: np.dtype) -> pa.DataType:
def get_arrow_type_from_tiledb_dtype(tiledb_dtype: Union[str, np.dtype]) -> pa.DataType:
"""
TODO: COMMENT
"""
if tiledb_dtype.name == "bytes":
if tiledb_dtype == "ascii" or tiledb_dtype.name == "bytes":
# XXX TODO: temporary work-around until UTF8 support is native. GH #338.
return pa.string()
else:
Expand Down Expand Up @@ -119,22 +120,3 @@ def get_arrow_schema_from_tiledb_uri(
arrow_schema_dict[name] = get_arrow_type_from_tiledb_dtype(attr.dtype)

return pa.schema(arrow_schema_dict)


def ascii_to_unicode_pyarrow_readback(table: pa.Table) -> pa.Table:
"""
Implements the 'decode on read' part of our ASCII/Unicode logic
"""
# TODO: COMMENT/LINK HEAVILY
names = [ofield.name for ofield in table.schema]
new_fields = []
for name in names:
old_field = table[name]
if len(old_field) > 0 and isinstance(old_field[0], pa.LargeBinaryScalar):
nfield = pa.array(
[element.as_py().decode("utf-8") for element in old_field]
)
new_fields.append(nfield)
else:
new_fields.append(old_field)
return pa.Table.from_arrays(new_fields, names=names)
13 changes: 0 additions & 13 deletions apis/python/src/tiledbsoma/util_pandas.py

This file was deleted.

2 changes: 1 addition & 1 deletion apis/python/tests/test_type_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def test_supported_types_supported(arrow_type):
pytest.xfail("Awaiting UTF-8 support - see issue #338")

tdb_dtype = tiledb_type_from_arrow_type(arrow_type)
assert isinstance(tdb_dtype, np.dtype)
assert isinstance(tdb_dtype, np.dtype) or tdb_dtype == "ascii"
rt_arrow_type = get_arrow_type_from_tiledb_dtype(tdb_dtype)
assert isinstance(rt_arrow_type, pa.DataType)
assert arrow_type == rt_arrow_type
Expand Down

0 comments on commit a8dbbb2

Please sign in to comment.