Source code for dance.transforms.base
import hashlib
import warnings
from abc import ABC, abstractmethod
from anndata import AnnData
from dance import logger
from dance.data.base import Data
from dance.typing import LogLevel, Optional, Tuple
[docs]class BaseTransform(ABC):
"""BaseTransform abstract object.
Parameters
----------
log_level
Logging level.
out
Name of the obsm channel or layer where the transformed features will be saved. Use the current
transformation name if it is not set.
"""
_DISPLAY_ATTRS: Tuple[str] = ()
def __init__(self, out: Optional[str] = None, log_level: LogLevel = "WARNING"):
self.out = out or self.name
self.logger = logger.getChild(self.name)
self.logger.setLevel(log_level)
self.log_level = log_level
@property
def name(self) -> str:
return self.__class__.__name__
[docs] def hexdigest(self) -> str:
"""Return MD5 hash using the representation of the transform object."""
return hashlib.md5(repr(self).encode()).hexdigest()
def __repr__(self) -> str:
display_attrs_str_list = [f"{i}={getattr(self, i)!r}" for i in self._DISPLAY_ATTRS]
display_attrs_str = ", ".join(display_attrs_str_list)
return f"{self.name}({display_attrs_str})"
@abstractmethod
def __call__(self, data: Data) -> Data:
raise NotImplementedError
class AnnDataAdaptor:
"""Adaptor for transforming AnnData instead of dance data object.
Example
-------
Modify an :class:`AnnData` object inplace
>>> AnnDataAdaptor(FilterGenes(mode="sum"))(adata)
"""
def __init__(self, transform, **data_init_kwargs):
warnings.warn(
"This is a temporary patch to enable transforming AnnData, and "
"might have potential incompatibility issues. Use cautiously.",
UserWarning,
stacklevel=2,
)
self.transform = transform
self.data_init_kwargs = data_init_kwargs
def __call__(self, adata: AnnData) -> AnnData:
data = Data(adata, **self.data_init_kwargs)
self.transform(data)
return data.data