Skip to content

Commit

Permalink
Add reversed norm order for ALRA in Denoising Task (#835)
Browse files Browse the repository at this point in the history
* add reverse order/regular order

Try to match the magic code format for decorators and implementation of reverse norm

* Update __init__.py

* pre-commit

* Update alra.py

* Update alra.py

* pre-commit

* Fix method names

* Update alra.py

* function names should be lowercase

* Update alra.R

* X is unused

* Fix bug

* Revert 5fa2c64 [formerly 77302de]

* pre-commit

* Actually pass sqrt in sqrt norm methods

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Scott Gigante <[email protected]>
Former-commit-id: 86375dd
  • Loading branch information
3 people authored Feb 21, 2023
1 parent 1caa044 commit 4f21b1b
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 57 deletions.
2 changes: 2 additions & 0 deletions openproblems/tasks/denoising/methods/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from .alra import alra_log
from .alra import alra_log_reversenorm
from .alra import alra_sqrt
from .alra import alra_sqrt_reversenorm
from .baseline import no_denoising
from .baseline import perfect_denoising
from .dca import dca
Expand Down
113 changes: 56 additions & 57 deletions openproblems/tasks/denoising/methods/alra.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,61 @@
from ....tools.conversion import r_function
from ....tools.decorators import method

import functools
import logging

_alra = r_function("alra.R")
_r_alra = r_function("alra.R")

log = logging.getLogger("openproblems")


@method(
method_name="ALRA (sqrt norm, reversed normalization)",
method_name = ("ALRA (sqrt norm, reversed normalization)",)
_alra_method = functools.partial(
method,
paper_name="Zero-preserving imputation of scRNA-seq data using "
"low-rank approximation",
paper_reference="linderman2018zero",
paper_year=2018,
code_url="https://github.com/KlugerLab/ALRA",
image="openproblems-r-extras",
)
def alra_sqrt(adata, test=False):


def _alra(adata, normtype="log", reverse_norm_order=False, test=False):
import numpy as np
import rpy2.rinterface_lib.embedded
import scprep

# libsize and sqrt norm
adata.obsm["train_norm"] = scprep.utils.matrix_transform(
adata.obsm["train"], np.sqrt
)
adata.obsm["train_norm"], libsize = scprep.normalize.library_size_normalize(
adata.obsm["train_norm"], rescale=1, return_library_size=True
)
adata.obsm["train_norm"] = adata.obsm["train_norm"].tocsr()
if normtype == "sqrt":
norm_fn = np.sqrt
denorm_fn = np.square
elif normtype == "log":
norm_fn = np.log1p
denorm_fn = np.expm1
else:
raise NotImplementedError

X = adata.obsm["train"].copy()
if reverse_norm_order:
# inexplicably, this sometimes performs better
X = scprep.utils.matrix_transform(X, norm_fn)
X, libsize = scprep.normalize.library_size_normalize(
X, rescale=1, return_library_size=True
)
else:
X, libsize = scprep.normalize.library_size_normalize(
X, rescale=1, return_library_size=True
)
X = scprep.utils.matrix_transform(X, norm_fn)

adata.obsm["train_norm"] = X.tocsr()
# run alra
# _alra takes sparse array, returns dense array
# _r_alra takes sparse array, returns dense array
Y = None
attempts = 0
while Y is None:
try:
Y = _alra(adata)
Y = _r_alra(adata)
except rpy2.rinterface_lib.embedded.RRuntimeError: # pragma: no cover
if attempts < 10:
attempts += 1
Expand All @@ -46,57 +65,37 @@ def alra_sqrt(adata, test=False):

# transform back into original space
# functions are reversed!
Y = scprep.utils.matrix_transform(Y, np.square)
Y = scprep.utils.matrix_transform(Y, denorm_fn)
Y = scprep.utils.matrix_vector_elementwise_multiply(Y, libsize, axis=0)
adata.obsm["denoised"] = Y

adata.uns["method_code_version"] = "1.0.0"
return adata


@method(
method_name="ALRA (log norm)",
paper_name="Zero-preserving imputation of scRNA-seq data using "
"low-rank approximation",
paper_reference="linderman2018zero",
paper_year=2018,
code_url="https://github.com/KlugerLab/ALRA",
image="openproblems-r-extras",
@_alra_method(
method_name="ALRA (sqrt norm, reversed normalization)",
)
def alra_log(adata, test=False):
import numpy as np
import rpy2.rinterface_lib.embedded
import scprep
def alra_sqrt_reversenorm(adata, test=False):
return _alra(adata, normtype="sqrt", reverse_norm_order=True, test=False)

# libsize and log norm
# lib norm
adata.obsm["train_norm"], libsize = scprep.normalize.library_size_normalize(
adata.obsm["train"], rescale=1, return_library_size=True
)
# log
adata.obsm["train_norm"] = scprep.utils.matrix_transform(
adata.obsm["train_norm"], np.log1p
)
# to csr
adata.obsm["train_norm"] = adata.obsm["train_norm"].tocsr()
# run alra
# _alra takes sparse array, returns dense array
Y = None
attempts = 0
while Y is None:
try:
Y = _alra(adata)
except rpy2.rinterface_lib.embedded.RRuntimeError: # pragma: no cover
if attempts < 10:
attempts += 1
log.warning(f"alra.R failed (attempt {attempts})")
else:
raise

# transform back into original space
Y = scprep.utils.matrix_transform(Y, np.expm1)
Y = scprep.utils.matrix_vector_elementwise_multiply(Y, libsize, axis=0)
adata.obsm["denoised"] = Y
@_alra_method(
method_name="ALRA (log norm, reversed normalization)",
)
def alra_log_reversenorm(adata, test=False):
return _alra(adata, normtype="log", reverse_norm_order=True, test=False)

adata.uns["method_code_version"] = "1.0.0"
return adata

@_alra_method(
method_name="ALRA (sqrt norm)",
)
def alra_sqrt(adata, test=False):
return _alra(adata, normtype="sqrt", reverse_norm_order=False, test=False)


@_alra_method(
method_name="ALRA (log norm)",
)
def alra_log(adata, test=False):
return _alra(adata, normtype="log", reverse_norm_order=False, test=False)

0 comments on commit 4f21b1b

Please sign in to comment.