diff --git a/daf/__init__.py b/daf/__init__.py index 963c9ea..cddf111 100644 --- a/daf/__init__.py +++ b/daf/__init__.py @@ -51,6 +51,7 @@ # pylint: disable=wildcard-import,unused-wildcard-import from .julia_import import * # isort: skip +from .generic import * # isort: skip from .storage_types import * # isort: skip from .operations import * # isort: skip from .queries import * # isort: skip @@ -60,3 +61,4 @@ from .copies import * # isort: skip from .adapters import * # isort: skip from .concat import * # isort: skip +from .anndata_format import * # isort: skip diff --git a/daf/anndata_format.py b/daf/anndata_format.py new file mode 100644 index 0000000..a075b80 --- /dev/null +++ b/daf/anndata_format.py @@ -0,0 +1,56 @@ +""" +Import/export ``Daf`` data from/to ``AnnData``. See the Julia +`documentation `__ for details. +""" + +__all__ = ["h5ad_as_daf", "daf_as_h5ad"] + +from typing import Optional + +from .data import DafReader +from .formats import MemoryDaf +from .generic import JL_ABNORMAL_HANDLER +from .generic import AbnormalHandler +from .julia_import import jl + + +def h5ad_as_daf( + h5ad: str, + *, + name: Optional[str] = None, + obs_is: Optional[str] = None, + var_is: Optional[str] = None, + X_is: Optional[str] = None, + unsupported_handler: AbnormalHandler = "WarnHandler", +) -> MemoryDaf: + """ + View ``AnnData`` as a ``Daf`` data set, specifically using a ``MemoryDaf``. See the Julia + `documentation `__ for details. + + Note that you only pass an ``h5ad`` path, since the Julia ``AnnData`` object comes from the ``Muon.jl`` package and + is not compatible with the Python ``anndata`` object. + """ + return MemoryDaf( + jl.Daf.anndata_as_daf( + h5ad, + name=name, + obs_is=obs_is, + var_is=var_is, + X_is=X_is, + unsupported_handler=JL_ABNORMAL_HANDLER[unsupported_handler], + ) + ) + + +def daf_as_h5ad( + daf: DafReader, *, obs_is: Optional[str] = None, var_is: Optional[str] = None, X_is: Optional[str] = None, h5ad: str +) -> None: + """ + View the ``Daf`` data set as ``AnnData``. See the Julia + `documentation `__ + for details. + + Note this just creates the ``h5ad`` file. We do not return the ``AnnData`` object, because it is a Julia + (``Muon.jl``) ``AnnData`` object, which is **not** a Python ``anndata`` ``AnnData`` object. + """ + jl.daf_as_anndata(daf, obs_is=obs_is, var_is=var_is, X_is=X_is, h5ad=h5ad) diff --git a/daf/formats.py b/daf/formats.py index 2728c15..800053d 100644 --- a/daf/formats.py +++ b/daf/formats.py @@ -20,8 +20,10 @@ class MemoryDaf(DafWriter): `documentation `__ for details. """ - def __init__(self, *, name: str = "memory") -> None: - super().__init__(jl.Daf.MemoryDaf(name=name)) + def __init__(self, jl_obj: Optional[jl.MemoryDaf] = None, *, name: str = "memory") -> None: + if jl_obj is None: + jl_obj = jl.Daf.MemoryDaf(name=name) + super().__init__(jl_obj) class FilesDaf(DafWriter): diff --git a/daf/generic.py b/daf/generic.py new file mode 100644 index 0000000..e08d966 --- /dev/null +++ b/daf/generic.py @@ -0,0 +1,21 @@ +""" +Types that arguably should belong in a more general-purpose package. See the Julia +`documentation `__ for details. +""" + +from typing import Literal + +from .julia_import import jl + +__all__ = ["AbnormalHandler"] + + +#: The action to take when encountering an "abnormal" (but recoverable) operation. See the Julia +#: `documentation `__ for details. +AbnormalHandler = Literal["IgnoreHandler"] | Literal["WarnHandler"] | Literal["ErrorHandler"] + +JL_ABNORMAL_HANDLER = { + "IgnoreHandler": jl.Daf.Generic.IgnoreHandler, + "WarnHandler": jl.Daf.Generic.WarnHandler, + "ErrorHandler": jl.Daf.Generic.ErrorHandler, +} diff --git a/daf/julia_import.py b/daf/julia_import.py index d515e50..174a486 100644 --- a/daf/julia_import.py +++ b/daf/julia_import.py @@ -85,9 +85,10 @@ jl.seval("import DataFrames") jl.seval("import HDF5") jl.seval("import LinearAlgebra") +jl.seval("import Muon") jl.seval("import NamedArrays") -jl.seval("import SparseArrays") jl.seval("import PythonCall") +jl.seval("import SparseArrays") class UndefInitializer: diff --git a/docs/API.rst b/docs/API.rst index fef483d..2b7f3d7 100644 --- a/docs/API.rst +++ b/docs/API.rst @@ -7,6 +7,7 @@ API julia_import data + storage_types queries operations formats @@ -14,4 +15,5 @@ API copies adapters concat - storage_types + anndata_format + generic diff --git a/docs/anndata_format.rst b/docs/anndata_format.rst new file mode 100644 index 0000000..b5e4b47 --- /dev/null +++ b/docs/anndata_format.rst @@ -0,0 +1,5 @@ +anndata_format +============== + +.. automodule:: daf.anndata_format + :Members: diff --git a/docs/v0.1.0/html/API.html b/docs/v0.1.0/html/API.html index 8fa2230..c8c7840 100644 --- a/docs/v0.1.0/html/API.html +++ b/docs/v0.1.0/html/API.html @@ -125,6 +125,11 @@ +
  • +storage_types + +
  • +
  • queries @@ -161,7 +166,7 @@
  • -storage_types +anndata_format
  • @@ -898,6 +903,33 @@

    API +
  • +storage_types + + + +
  • +
  • queries @@ -1565,23 +1597,23 @@

    API

  • -storage_types +anndata_format
    • - + -StorageNumber +h5ad_as_daf()
    • - + -StorageScalar +daf_as_h5ad() diff --git a/docs/v0.1.0/html/_modules/daf/anndata_format.html b/docs/v0.1.0/html/_modules/daf/anndata_format.html new file mode 100644 index 0000000..ad6bf5c --- /dev/null +++ b/docs/v0.1.0/html/_modules/daf/anndata_format.html @@ -0,0 +1,171 @@ + + + + + + daf.anndata_format — Daf 0.1.0 documentation + + + + + + + + + + + + + + + + + +
      + + +
      + +
      +
      +
      + +
      +
      +
      +
      + +

      Source code for daf.anndata_format

      +"""
      +Import/export ``Daf`` data from/to ``AnnData``. See the Julia
      +`documentation <https://tanaylab.github.io/Daf.jl/v0.1.0/anndata_format.html>`__ for details.
      +"""
      +
      +__all__ = ["h5ad_as_daf", "daf_as_h5ad"]
      +
      +from typing import Optional
      +
      +from .data import DafReader
      +from .formats import MemoryDaf
      +from .generic import JL_ABNORMAL_HANDLER
      +from .generic import AbnormalHandler
      +from .julia_import import jl
      +
      +
      +
      +[docs] +def h5ad_as_daf( + h5ad: str, + *, + name: Optional[str] = None, + obs_is: Optional[str] = None, + var_is: Optional[str] = None, + X_is: Optional[str] = None, + unsupported_handler: AbnormalHandler = "WarnHandler", +) -> MemoryDaf: + """ + View ``AnnData`` as a ``Daf`` data set, specifically using a ``MemoryDaf``. See the Julia + `documentation <https://tanaylab.github.io/Daf.jl/v0.1.0/anndata_format.html#anndata_as_daf>`__ for details. + + Note that you only pass an ``h5ad`` path, since the Julia ``AnnData`` object comes from the ``Muon.jl`` package and + is not compatible with the Python ``anndata`` object. + """ + return MemoryDaf( + jl.Daf.anndata_as_daf( + h5ad, + name=name, + obs_is=obs_is, + var_is=var_is, + X_is=X_is, + unsupported_handler=JL_ABNORMAL_HANDLER[unsupported_handler], + ) + )
      + + + +
      +[docs] +def daf_as_h5ad( + daf: DafReader, *, obs_is: Optional[str] = None, var_is: Optional[str] = None, X_is: Optional[str] = None, h5ad: str +) -> None: + """ + View the ``Daf`` data set as ``AnnData``. See the Julia + `documentation <https://tanaylab.github.io/Daf.jl/v0.1.0/anndata_format.html#Daf.AnnDataFormat.daf_as_anndata>`__ + for details. + + Note this just creates the ``h5ad`` file. We do not return the ``AnnData`` object, because it is a Julia + (``Muon.jl``) ``AnnData`` object, which is **not** a Python ``anndata`` ``AnnData`` object. + """ + jl.daf_as_anndata(daf, obs_is=obs_is, var_is=var_is, X_is=X_is, h5ad=h5ad)
      + +
      + +
      +
      +
      + +
      + +
      +

      © Copyright 2023-2024 Weizmann Institute of Science.

      +
      + + Built with Sphinx using a + theme + provided by Read the Docs. + + +
      +
      +
      +
      +
      + + + + \ No newline at end of file diff --git a/docs/v0.1.0/html/_modules/daf/formats.html b/docs/v0.1.0/html/_modules/daf/formats.html index 3fe7e52..6584461 100644 --- a/docs/v0.1.0/html/_modules/daf/formats.html +++ b/docs/v0.1.0/html/_modules/daf/formats.html @@ -101,8 +101,10 @@

      Source code for daf.formats

           `documentation <https://tanaylab.github.io/Daf.jl/v0.1.0/memory_format.html>`__ for details.
           """
       
      -    def __init__(self, *, name: str = "memory") -> None:
      -        super().__init__(jl.Daf.MemoryDaf(name=name))
      + def __init__(self, jl_obj: Optional[jl.MemoryDaf] = None, *, name: str = "memory") -> None: + if jl_obj is None: + jl_obj = jl.Daf.MemoryDaf(name=name) + super().__init__(jl_obj) diff --git a/docs/v0.1.0/html/_modules/daf/julia_import.html b/docs/v0.1.0/html/_modules/daf/julia_import.html index 41b6a2b..45e6261 100644 --- a/docs/v0.1.0/html/_modules/daf/julia_import.html +++ b/docs/v0.1.0/html/_modules/daf/julia_import.html @@ -164,9 +164,10 @@

      Source code for daf.julia_import

       jl.seval("import DataFrames")
       jl.seval("import HDF5")
       jl.seval("import LinearAlgebra")
      +jl.seval("import Muon")
       jl.seval("import NamedArrays")
      -jl.seval("import SparseArrays")
       jl.seval("import PythonCall")
      +jl.seval("import SparseArrays")
       
       
       
      diff --git a/docs/v0.1.0/html/_modules/index.html b/docs/v0.1.0/html/_modules/index.html index 32c37b8..a9084da 100644 --- a/docs/v0.1.0/html/_modules/index.html +++ b/docs/v0.1.0/html/_modules/index.html @@ -77,6 +77,7 @@

      All modules for which code is available

      • daf.adapters
      • +
      • daf.anndata_format
      • daf.concat
      • daf.copies
      • daf.data
      • diff --git a/docs/v0.1.0/html/_sources/API.rst.txt b/docs/v0.1.0/html/_sources/API.rst.txt index fef483d..2b7f3d7 100644 --- a/docs/v0.1.0/html/_sources/API.rst.txt +++ b/docs/v0.1.0/html/_sources/API.rst.txt @@ -7,6 +7,7 @@ API julia_import data + storage_types queries operations formats @@ -14,4 +15,5 @@ API copies adapters concat - storage_types + anndata_format + generic diff --git a/docs/v0.1.0/html/_sources/anndata_format.rst.txt b/docs/v0.1.0/html/_sources/anndata_format.rst.txt new file mode 100644 index 0000000..b5e4b47 --- /dev/null +++ b/docs/v0.1.0/html/_sources/anndata_format.rst.txt @@ -0,0 +1,5 @@ +anndata_format +============== + +.. automodule:: daf.anndata_format + :Members: diff --git a/docs/v0.1.0/html/adapters.html b/docs/v0.1.0/html/adapters.html index 999769e..bfd019b 100644 --- a/docs/v0.1.0/html/adapters.html +++ b/docs/v0.1.0/html/adapters.html @@ -125,6 +125,11 @@ +
      • +storage_types + +
      • +
      • queries @@ -174,7 +179,7 @@
      • -storage_types +anndata_format
      • diff --git a/docs/v0.1.0/html/anndata_format.html b/docs/v0.1.0/html/anndata_format.html new file mode 100644 index 0000000..9e855ad --- /dev/null +++ b/docs/v0.1.0/html/anndata_format.html @@ -0,0 +1,917 @@ + + + + + + + + + + + + + +anndata_format — Daf 0.1.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + + +
        + + + +
        + +
        + +
        + + + +
        + +
        + +
        + +
        + + +
        + + + +

        anndata_format +¶ + +

        + +

        Import/export + +Daf + + data from/to + +AnnData + +. See the Julia + +documentation + for details. +

        + +
        + +
        + + +daf.anndata_format. + + + +h5ad_as_daf + + +( + + + +h5ad + + + +: + + + + + +str + + +, + + +* + + +, + + +name + + + +: + + + + + +str + + + + +| + + + + +None + + + + + += + + + + + +None + + +, + + +obs_is + + + +: + + + + + +str + + + + +| + + + + +None + + + + + += + + + + + +None + + +, + + +var_is + + + +: + + + + + +str + + + + +| + + + + +None + + + + + += + + + + + +None + + +, + + +X_is + + + +: + + + + + +str + + + + +| + + + + +None + + + + + += + + + + + +None + + +, + + +unsupported_handler + + + +: + + + + + +Literal + + +[ + + + +'IgnoreHandler' + + + +] + + + + + +| + + + + +Literal + + +[ + + + +'WarnHandler' + + + +] + + + + + +| + + + + +Literal + + +[ + + + +'ErrorHandler' + + + +] + + + + + + += + + + + + +'WarnHandler' + + + +) + + +→ + + + +MemoryDaf + + + + + + +[source] + + + +¶ + +
        + +
        +

        View + +AnnData + + as a + +Daf + + data set, specifically using a + +MemoryDaf + +. See the Julia + +documentation + for details. +

        + +

        Note that you only pass an + +h5ad + + path, since the Julia + +AnnData + + object comes from the + +Muon.jl + + package and +is not compatible with the Python + +anndata + + object. +

        + +
        +
        + + +
        + +
        + + +daf.anndata_format. + + + +daf_as_h5ad + + +( + + + +daf + + + +: + + + + + + +DafReader + + + +, + + +* + + +, + + +obs_is + + + +: + + + + + +str + + + + +| + + + + +None + + + + + += + + + + + +None + + +, + + +var_is + + + +: + + + + + +str + + + + +| + + + + +None + + + + + += + + + + + +None + + +, + + +X_is + + + +: + + + + + +str + + + + +| + + + + +None + + + + + += + + + + + +None + + +, + + +h5ad + + + +: + + + + + +str + + + +) + + +→ + + +None + + + + + +[source] + + + +¶ + +
        + +
        +

        View the + +Daf + + data set as + +AnnData + +. See the Julia + +documentation + +for details. +

        + +

        Note this just creates the + +h5ad + + file. We do not return the + +AnnData + + object, because it is a Julia +( + +Muon.jl + +) + +AnnData + + object, which is +not + a Python + +anndata + + + +AnnData + + object. +

        + +
        +
        + + +
        + + + +
        + +
        + + + +
        + +
        + +
        + +
        + + + + + + + \ No newline at end of file diff --git a/docs/v0.1.0/html/concat.html b/docs/v0.1.0/html/concat.html index 8911dd2..38ad9bb 100644 --- a/docs/v0.1.0/html/concat.html +++ b/docs/v0.1.0/html/concat.html @@ -50,7 +50,7 @@ - + @@ -125,6 +125,11 @@ +
      • +storage_types + +
      • +
      • queries @@ -174,7 +179,7 @@
      • -storage_types +anndata_format
      • @@ -1144,7 +1149,7 @@

        concat Previous - diff --git a/docs/v0.1.0/html/copies.html b/docs/v0.1.0/html/copies.html index 8f356c1..d5843e2 100644 --- a/docs/v0.1.0/html/copies.html +++ b/docs/v0.1.0/html/copies.html @@ -125,6 +125,11 @@ +
      • +storage_types + +
      • +
      • queries @@ -219,7 +224,7 @@
      • -storage_types +anndata_format
      • diff --git a/docs/v0.1.0/html/data.html b/docs/v0.1.0/html/data.html index 63f5019..e5c9722 100644 --- a/docs/v0.1.0/html/data.html +++ b/docs/v0.1.0/html/data.html @@ -50,7 +50,7 @@ - + @@ -501,6 +501,11 @@ +
      • +storage_types + +
      • +
      • queries @@ -537,7 +542,7 @@
      • -storage_types +anndata_format
      • @@ -8219,7 +8224,7 @@

        data Previous - diff --git a/docs/v0.1.0/html/formats.html b/docs/v0.1.0/html/formats.html index a99c10f..26af5fb 100644 --- a/docs/v0.1.0/html/formats.html +++ b/docs/v0.1.0/html/formats.html @@ -125,6 +125,11 @@ +
      • +storage_types + +
      • +
      • queries @@ -210,7 +215,7 @@
      • -storage_types +anndata_format
      • @@ -316,35 +321,37 @@

        formats ( - -* + +jl_obj: + +Julia: + +MemoryDaf + +| + +None + += + +None , -name - - - -: - +* - +, + +name: + str - - - - - + = - - - - - + 'memory' diff --git a/docs/v0.1.0/html/genindex.html b/docs/v0.1.0/html/genindex.html index 0af9130..9e6c3de 100644 --- a/docs/v0.1.0/html/genindex.html +++ b/docs/v0.1.0/html/genindex.html @@ -505,6 +505,21 @@

        D

    • +
    • + daf.anndata_format + + + +
    • +
    • daf.concat @@ -579,6 +594,12 @@

      D

  • + + + + + +
    • daf.operations @@ -594,12 +615,6 @@

      D

    - - - - - -
    • daf.queries @@ -646,6 +661,12 @@

      D

    +
  • +daf_as_h5ad() (in module daf.anndata_format) + + +
  • +
  • DafReader (class in daf.data) @@ -896,6 +917,12 @@

    H
      +
    • +h5ad_as_daf() (in module daf.anndata_format) + + +
    • +
    • H5df (class in daf.formats) @@ -1152,6 +1179,12 @@

      M

    • +
    • +daf.anndata_format + + +
    • +
    • daf.concat diff --git a/docs/v0.1.0/html/julia_import.html b/docs/v0.1.0/html/julia_import.html index 245c4ff..46b73aa 100644 --- a/docs/v0.1.0/html/julia_import.html +++ b/docs/v0.1.0/html/julia_import.html @@ -165,6 +165,11 @@
    • +
    • +storage_types + +
    • +
    • queries @@ -201,7 +206,7 @@
    • -storage_types +anndata_format
    • diff --git a/docs/v0.1.0/html/objects.inv b/docs/v0.1.0/html/objects.inv index 51ad101..29cdae7 100644 Binary files a/docs/v0.1.0/html/objects.inv and b/docs/v0.1.0/html/objects.inv differ diff --git a/docs/v0.1.0/html/operations.html b/docs/v0.1.0/html/operations.html index 403538a..403d300 100644 --- a/docs/v0.1.0/html/operations.html +++ b/docs/v0.1.0/html/operations.html @@ -125,6 +125,11 @@ +
    • +storage_types + +
    • +
    • queries @@ -354,7 +359,7 @@
    • -storage_types +anndata_format
    • diff --git a/docs/v0.1.0/html/py-modindex.html b/docs/v0.1.0/html/py-modindex.html index 3901033..e59f20d 100644 --- a/docs/v0.1.0/html/py-modindex.html +++ b/docs/v0.1.0/html/py-modindex.html @@ -250,6 +250,25 @@

      Python Module Index     + +daf.anndata_format + + + + + + + + + + + + + + + +    + daf.concat diff --git a/docs/v0.1.0/html/queries.html b/docs/v0.1.0/html/queries.html index 799a733..086e6a0 100644 --- a/docs/v0.1.0/html/queries.html +++ b/docs/v0.1.0/html/queries.html @@ -52,7 +52,7 @@ - + @@ -125,6 +125,11 @@ +
    • +storage_types + +
    • +
    • queries @@ -399,7 +404,7 @@
    • -storage_types +anndata_format
    • @@ -3642,7 +3647,7 @@

      queries

    - @@ -473,10 +480,15 @@

    storage_types
    diff --git a/docs/v0.1.0/html/views.html b/docs/v0.1.0/html/views.html index 7becff7..44fd935 100644 --- a/docs/v0.1.0/html/views.html +++ b/docs/v0.1.0/html/views.html @@ -125,6 +125,11 @@

  • +
  • +storage_types + +
  • +
  • queries @@ -228,7 +233,7 @@
  • -storage_types +anndata_format
  • diff --git a/juliapkg.json b/juliapkg.json index 4ffbcec..7e95f9a 100644 --- a/juliapkg.json +++ b/juliapkg.json @@ -9,6 +9,9 @@ "HDF5": { "uuid": "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" }, + "Muon": { + "uuid": "446846d7-b4ce-489d-bf74-72da18fe3629" + }, "NamedArrays": { "uuid": "86f7a689-2022-50b4-a561-43c23ac3c673" } diff --git a/tests/test_anndata_format.py b/tests/test_anndata_format.py new file mode 100644 index 0000000..a88be3c --- /dev/null +++ b/tests/test_anndata_format.py @@ -0,0 +1,63 @@ +""" +Test ``Daf`` conversion to and from ``AnnData``. +""" + +# pylint: disable=wildcard-import,unused-wildcard-import,missing-function-docstring +# flake8: noqa: F403,F405 + +from tempfile import TemporaryDirectory +from textwrap import dedent + +import numpy as np + +from daf import * + + +def test_h5ad() -> None: # pylint: disable=too-many-statements + origin = MemoryDaf(name="memory!") + origin.set_scalar("version", 1) + origin.add_axis("cell", ["A", "B"]) + origin.add_axis("gene", ["X", "Y", "Z"]) + origin.set_matrix("gene", "cell", "UMIs", np.array([[0, 1, 2], [3, 4, 5]]).transpose(), relayout=False) + + assert ( + origin.description() + == dedent( + """ + name: memory! + type: MemoryDaf + scalars: + version: 1 (Int64) + axes: + cell: 2 entries + gene: 3 entries + matrices: + gene,cell: + UMIs: 3 x 2 x Int64 in Columns (PyArray{Int64, 2, true, true, Int64} - Dense) + """ + )[1:] + ) + + with TemporaryDirectory() as tmpdir: + daf_as_h5ad(origin, obs_is="cell", var_is="gene", X_is="UMIs", h5ad=f"{tmpdir}/test.h5ad") + back = h5ad_as_daf(f"{tmpdir}/test.h5ad", obs_is="cell", var_is="gene", X_is="UMIs") + assert ( + back.description() + == dedent( + """ + name: anndata + type: MemoryDaf + scalars: + X_is: "UMIs" + obs_is: "cell" + var_is: "gene" + version: 1 (Int64) + axes: + cell: 2 entries + gene: 3 entries + matrices: + gene,cell: + UMIs: 3 x 2 x Int64 in Columns (Dense) + """ + )[1:] + )