cap_anndata 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, R. Mukhin, A. Isaev, Cell-Annotation Platform
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,70 @@
1
+ Metadata-Version: 2.4
2
+ Name: cap_anndata
3
+ Version: 0.5.1
4
+ Summary: Partial read/write of AnnData (h5ad) files for low-memory operations with large datasets.
5
+ Home-page: https://github.com/cellannotation/cap-anndata
6
+ Author: R. Mukhin, A. Isaev
7
+ Author-email: roman@ebookapplications.com
8
+ Project-URL: Bug Tracker, https://github.com/cellannotation/cap-anndata/issues
9
+ Project-URL: Changelog, https://github.com/cellannotation/cap-anndata/blob/main/CHANGELOG.md
10
+ Project-URL: Documentation, https://github.com/cellannotation/cap-anndata/blob/main/HOWTO.md
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: License :: OSI Approved :: BSD License
13
+ Classifier: Operating System :: OS Independent
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: numpy>=1.23.5
18
+ Requires-Dist: pandas>=2.2.0
19
+ Requires-Dist: anndata>=0.10.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
22
+ Requires-Dist: setuptools~=69.1.1; extra == "dev"
23
+ Dynamic: author
24
+ Dynamic: author-email
25
+ Dynamic: classifier
26
+ Dynamic: description
27
+ Dynamic: description-content-type
28
+ Dynamic: home-page
29
+ Dynamic: license-file
30
+ Dynamic: project-url
31
+ Dynamic: provides-extra
32
+ Dynamic: requires-dist
33
+ Dynamic: requires-python
34
+ Dynamic: summary
35
+
36
+ # CAP-AnnData: Partial I/O for AnnData (.h5ad) Files
37
+
38
+ [![PyPI version](https://img.shields.io/pypi/v/cap-anndata)](https://pypi.org/project/cap-anndata/) [![Build Status](https://github.com/cellannotation/cap-anndata/actions/workflows/python-app.yml/badge.svg)](https://github.com/cellannotation/cap-anndata/actions)
39
+
40
+ ## Overview
41
+ CAP-AnnData offering functionalities for selective reading and writing of [AnnData](https://pypi.org/project/anndata/)
42
+ file fields without the need for loading entire dataset (or even entire field) into memory.
43
+ For example, it allows to read and modify the single `obs` column taking nothing into memory except the column itself.
44
+ Package eager to replicate the original AnnData API as much as possible,
45
+ while providing additional features for efficient data manipulation for heavy datasets.
46
+
47
+ ## Installation
48
+ Install CAP-AnnData via pip:
49
+
50
+ ```commandline
51
+ pip install -U cap-anndata
52
+ ```
53
+
54
+ ## Basic Example
55
+
56
+ The example below displayes how to read a single `obs` column, create new obs column and propagate it to the `.h5ad` file.
57
+ ```python
58
+ from cap_anndata import read_h5ad
59
+
60
+ file_path = "your_data.h5ad"
61
+ with read_h5ad(file_path=file_path, edit=True) as cap_adata:
62
+ print(cap_adata.obs_keys()) # ['a', 'b', 'c']
63
+ print(cap_adata.obs) # Empty DataFrame
64
+ cap_adata.read_obs(columns=['a'])
65
+ print(cap_adata.obs.columns) # ['a']
66
+ cap_adata.obs['new_col'] = cap_adata.obs['a']
67
+ cap_adata.overwrite(fields=['obs'])
68
+ ```
69
+
70
+ More example can be found in the [How-TO](https://github.com/cellannotation/cap-anndata/blob/main/HOWTO.md) file.
@@ -0,0 +1,35 @@
1
+ # CAP-AnnData: Partial I/O for AnnData (.h5ad) Files
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/cap-anndata)](https://pypi.org/project/cap-anndata/) [![Build Status](https://github.com/cellannotation/cap-anndata/actions/workflows/python-app.yml/badge.svg)](https://github.com/cellannotation/cap-anndata/actions)
4
+
5
+ ## Overview
6
+ CAP-AnnData offering functionalities for selective reading and writing of [AnnData](https://pypi.org/project/anndata/)
7
+ file fields without the need for loading entire dataset (or even entire field) into memory.
8
+ For example, it allows to read and modify the single `obs` column taking nothing into memory except the column itself.
9
+ Package eager to replicate the original AnnData API as much as possible,
10
+ while providing additional features for efficient data manipulation for heavy datasets.
11
+
12
+ ## Installation
13
+ Install CAP-AnnData via pip:
14
+
15
+ ```commandline
16
+ pip install -U cap-anndata
17
+ ```
18
+
19
+ ## Basic Example
20
+
21
+ The example below displayes how to read a single `obs` column, create new obs column and propagate it to the `.h5ad` file.
22
+ ```python
23
+ from cap_anndata import read_h5ad
24
+
25
+ file_path = "your_data.h5ad"
26
+ with read_h5ad(file_path=file_path, edit=True) as cap_adata:
27
+ print(cap_adata.obs_keys()) # ['a', 'b', 'c']
28
+ print(cap_adata.obs) # Empty DataFrame
29
+ cap_adata.read_obs(columns=['a'])
30
+ print(cap_adata.obs.columns) # ['a']
31
+ cap_adata.obs['new_col'] = cap_adata.obs['a']
32
+ cap_adata.overwrite(fields=['obs'])
33
+ ```
34
+
35
+ More example can be found in the [How-TO](https://github.com/cellannotation/cap-anndata/blob/main/HOWTO.md) file.
@@ -0,0 +1,10 @@
1
+ from .backed_df import CapAnnDataDF
2
+ from .backed_dict import CapAnnDataDict
3
+ from .cap_anndata import CapAnnData
4
+ from .reader import (
5
+ read_directly,
6
+ read_h5ad,
7
+ )
8
+
9
+
10
+ __all__ = ["CapAnnData"]
@@ -0,0 +1,85 @@
1
+ import pandas as pd
2
+ import numpy as np
3
+ from typing import List, Any, Union
4
+
5
+ from pandas.core.generic import bool_t
6
+
7
+ try:
8
+ from typing import Self # Python 3.11+
9
+ except ImportError:
10
+ from typing_extensions import Self # Python 3.10
11
+
12
+
13
+ class CapAnnDataDF(pd.DataFrame):
14
+ """
15
+ The class to expand the pandas DataFrame behaviour to support partial
16
+ reading and writing of AnnData obs and var (raw.var) fields.
17
+ The main feature of the class is handling <column-order> attribute
18
+ which must be a copy of h5py.Group attribute
19
+ """
20
+
21
+ _metadata = ["column_order"]
22
+
23
+ def column_order_array(self) -> np.array:
24
+ order = self.column_order
25
+ if order is not None and isinstance(order, List):
26
+ # Convert it to numpy array of str elements
27
+ return np.array(order, dtype=object)
28
+ else:
29
+ return order
30
+
31
+ def rename_column(self, old_name: str, new_name: str) -> None:
32
+ i = np.where(self.column_order_array() == old_name)[0]
33
+ tmp_array = self.column_order_array().copy()
34
+ tmp_array[i] = new_name
35
+ self.column_order = tmp_array.copy()
36
+ self.rename(columns={old_name: new_name}, inplace=True)
37
+
38
+ def remove_column(self, col_name: str) -> None:
39
+ i = np.where(self.column_order_array() == col_name)[0]
40
+ self.column_order = np.delete(self.column_order_array(), i)
41
+ self.drop(columns=[col_name], inplace=True)
42
+
43
+ def __setitem__(self, key, value) -> None:
44
+ if key not in self.column_order_array():
45
+ self.column_order = np.append(self.column_order_array(), key)
46
+ return super().__setitem__(key, value)
47
+
48
+ @classmethod
49
+ def from_df(cls, df: pd.DataFrame, column_order: Union[np.array, List[str], None] = None) -> Self:
50
+ if column_order is None:
51
+ column_order = df.columns.to_numpy()
52
+ elif isinstance(column_order, List):
53
+ column_order = np.array(column_order)
54
+ new_inst = cls(df)
55
+ new_inst.column_order = column_order
56
+ return new_inst
57
+
58
+ def join(self, other: Any, **kwargs) -> Self:
59
+ result = super().join(other=other, **kwargs)
60
+ if isinstance(other, CapAnnDataDF):
61
+ new_columns = [
62
+ col for col in other.column_order_array() if col not in self.column_order_array()
63
+ ]
64
+ else:
65
+ new_columns = [col for col in other.columns if col not in self.column_order_array()]
66
+ column_order = np.append(self.column_order_array(), new_columns)
67
+ df = self.from_df(result, column_order=column_order)
68
+ return df
69
+
70
+ def merge(self, right, **kwargs) -> Self:
71
+ result = super().merge(right=right, **kwargs)
72
+ if isinstance(right, CapAnnDataDF):
73
+ new_columns = [
74
+ col for col in right.column_order_array() if col not in self.column_order_array()
75
+ ]
76
+ else:
77
+ new_columns = [col for col in right.columns if col not in self.column_order_array()]
78
+ column_order = np.append(self.column_order_array(), new_columns)
79
+ df = self.from_df(result, column_order=column_order)
80
+ return df
81
+
82
+ def copy(self, deep: Union[bool_t, None] = True) -> Self:
83
+ column_order = self.column_order_array()
84
+ df = self.from_df(super().copy(deep=deep), column_order=column_order)
85
+ return df
@@ -0,0 +1,34 @@
1
+ from typing import Set, Any
2
+
3
+
4
+ class CapAnnDataDict(dict):
5
+ __keys_to_remove: Set[str] = None
6
+
7
+ def __delitem__(self, __key: Any) -> None:
8
+ self.keys_to_remove.add(__key)
9
+ return super().__delitem__(__key)
10
+
11
+ def __setitem__(self, __key: Any, __value: Any) -> None:
12
+ if __value is not None:
13
+ if __key in self.keys_to_remove:
14
+ self.keys_to_remove.remove(__key)
15
+ else:
16
+ self.keys_to_remove.add(__key)
17
+ return super().__setitem__(__key, __value)
18
+
19
+ @property
20
+ def keys_to_remove(self) -> Set[str]:
21
+ if self.__keys_to_remove is None:
22
+ self.__keys_to_remove = set()
23
+ return self.__keys_to_remove
24
+
25
+ def pop(self, __key: Any, __default: Any = None) -> Any:
26
+ if __key in self:
27
+ self.keys_to_remove.add(__key)
28
+ return super().pop(__key, __default)
29
+
30
+ def popitem(self) -> Any:
31
+ item = super().popitem()
32
+ key = item[0]
33
+ self.keys_to_remove.add(key)
34
+ return item