Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Add a "tracker" attribute to AnnData objects to keep track of transformations to it's data
import scanpy.api as sc
import numpy as np
def add_tracker(field_name="tracker"):
from inspect import getcallargs
from functools import wraps
def tracker(f):
def wrapper(*args, **kwds):
adata = args[0]
if field_name not in adata.uns:
adata.uns[field_name] = np.array([], dtype="<U32")
adata.uns[field_name] = np.append(adata.uns[field_name], [f.__name__])
return f(*args, **kwds)
return wrapper
pp_functions = filter(
lambda x: list(getcallargs(getattr(sc.pp, x), None, None).keys())[0] in ["adata", "data"],
lambda x: not x.startswith("__"), sc.pp.__dict__.keys()))
for function in pp_functions:
setattr(sc.pp, function, tracker(getattr(sc.pp, function)))
a = sc.AnnData(np.random.randint(0, 100, size=(20, 5)))
assert "tracker" not in a.uns
assert "tracker" in a.uns
assert a.uns['tracker'] == np.array(["normalize_per_cell"])
assert all(a.uns['tracker'] == np.array(["normalize_per_cell", "log1p"]))
sc.write("example_anndata.h5ad", a)
a ="example_anndata.h5ad")
assert "tracker" in a.uns
assert all(a.uns['tracker'] == np.array(["normalize_per_cell", "log1p"]))

This comment has been minimized.

Copy link
Owner Author

@afrendeiro afrendeiro commented Feb 10, 2019

I'd prefer to have a ,more simple and discrete class attribute e.g. "_tracker" of type list to track, but since saving as h5ad is not true object serialization, adding it to uns seemed like the other obvious way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment