vdata 0.3.1__tar.gz → 0.3.2__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.
Files changed (70) hide show
  1. {vdata-0.3.1 → vdata-0.3.2}/PKG-INFO +2 -2
  2. {vdata-0.3.1 → vdata-0.3.2}/pyproject.toml +2 -2
  3. {vdata-0.3.1 → vdata-0.3.2}/vdata/__init__.py +5 -3
  4. {vdata-0.3.1 → vdata-0.3.2}/vdata/_typing.py +1 -3
  5. {vdata-0.3.1 → vdata-0.3.2}/vdata/anndata_proxy/anndata.py +50 -25
  6. {vdata-0.3.1 → vdata-0.3.2}/vdata/anndata_proxy/containers.py +16 -11
  7. {vdata-0.3.1 → vdata-0.3.2}/vdata/array_view.py +2 -2
  8. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/__init__.py +6 -4
  9. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_indexing.py +2 -2
  10. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/time.py +4 -4
  11. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/arrays/base.py +8 -12
  12. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/arrays/layers.py +6 -3
  13. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/arrays/obs.py +1 -2
  14. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/arrays/var.py +9 -9
  15. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/arrays/view.py +5 -5
  16. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/concatenate.py +2 -3
  17. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/convert.py +11 -12
  18. vdata-0.3.2/vdata/data/name.py +1 -0
  19. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/vdata.py +61 -31
  20. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/view.py +20 -8
  21. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/write.py +25 -20
  22. {vdata-0.3.1 → vdata-0.3.2}/vdata/tdf/index.py +2 -0
  23. {vdata-0.3.1 → vdata-0.3.2}/vdata/tdf/view.py +1 -1
  24. {vdata-0.3.1 → vdata-0.3.2}/vdata/timepoint/_functions.py +0 -18
  25. {vdata-0.3.1 → vdata-0.3.2}/vdata/timepoint/array.py +17 -1
  26. {vdata-0.3.1 → vdata-0.3.2}/vdata/timepoint/timepoint.py +6 -4
  27. vdata-0.3.2/vdata/update/__init__.py +14 -0
  28. {vdata-0.3.1 → vdata-0.3.2}/vdata/update/array.py +15 -6
  29. {vdata-0.3.1 → vdata-0.3.2}/vdata/update/dict.py +15 -7
  30. {vdata-0.3.1 → vdata-0.3.2}/vdata/update/tdf.py +42 -36
  31. {vdata-0.3.1 → vdata-0.3.2}/vdata/update/update.py +35 -23
  32. {vdata-0.3.1 → vdata-0.3.2}/vdata/update/vdf.py +24 -14
  33. vdata-0.3.1/vdata/IO/logger.conf +0 -27
  34. vdata-0.3.1/vdata/update/__init__.py +0 -6
  35. {vdata-0.3.1 → vdata-0.3.2}/LICENSE +0 -0
  36. {vdata-0.3.1 → vdata-0.3.2}/README.md +0 -0
  37. {vdata-0.3.1 → vdata-0.3.2}/vdata/IO/__init__.py +0 -0
  38. {vdata-0.3.1 → vdata-0.3.2}/vdata/IO/errors.py +0 -0
  39. {vdata-0.3.1 → vdata-0.3.2}/vdata/IO/logger.py +0 -0
  40. {vdata-0.3.1 → vdata-0.3.2}/vdata/_meta.py +0 -0
  41. {vdata-0.3.1 → vdata-0.3.2}/vdata/anndata_proxy/__init__.py +0 -0
  42. {vdata-0.3.1 → vdata-0.3.2}/vdata/anndata_proxy/dataframe.py +0 -0
  43. {vdata-0.3.1 → vdata-0.3.2}/vdata/cli.py +0 -0
  44. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/__init__.py +0 -0
  45. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/anndata.py +0 -0
  46. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/data.py +0 -0
  47. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/objects/__init__.py +0 -0
  48. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/objects/layers.py +0 -0
  49. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/objects/objects.py +0 -0
  50. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/objects/obs.py +0 -0
  51. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/objects/uns.py +0 -0
  52. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/objects/var.py +0 -0
  53. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/_parse/utils.py +0 -0
  54. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/arrays/__init__.py +0 -0
  55. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/arrays/lazy.py +0 -0
  56. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/hash.py +0 -0
  57. {vdata-0.3.1 → vdata-0.3.2}/vdata/data/read.py +0 -0
  58. {vdata-0.3.1 → vdata-0.3.2}/vdata/names.py +0 -0
  59. {vdata-0.3.1 → vdata-0.3.2}/vdata/py.typed +0 -0
  60. {vdata-0.3.1 → vdata-0.3.2}/vdata/tdf/__init__.py +0 -0
  61. {vdata-0.3.1 → vdata-0.3.2}/vdata/tdf/_parse.py +0 -0
  62. {vdata-0.3.1 → vdata-0.3.2}/vdata/tdf/base.py +0 -0
  63. {vdata-0.3.1 → vdata-0.3.2}/vdata/tdf/dataframe.py +0 -0
  64. {vdata-0.3.1 → vdata-0.3.2}/vdata/tdf/indexers.py +0 -0
  65. {vdata-0.3.1 → vdata-0.3.2}/vdata/tdf/indexing.py +0 -0
  66. {vdata-0.3.1 → vdata-0.3.2}/vdata/timepoint/__init__.py +0 -0
  67. {vdata-0.3.1 → vdata-0.3.2}/vdata/timepoint/_typing.py +0 -0
  68. {vdata-0.3.1 → vdata-0.3.2}/vdata/timepoint/index.py +0 -0
  69. {vdata-0.3.1 → vdata-0.3.2}/vdata/timepoint/range.py +0 -0
  70. {vdata-0.3.1 → vdata-0.3.2}/vdata/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vdata
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: Annotated multivariate observation of timestamped data
5
5
  Author: Matteo Bouvier
6
6
  Author-email: Matteo Bouvier <matteo.bouvier@hotmail.fr>
@@ -11,7 +11,7 @@ Requires-Dist: anndata>=0.10.4
11
11
  Requires-Dist: scipy>=1.12.0
12
12
  Requires-Dist: numpy-indexed>=0.3.7
13
13
  Requires-Dist: ch5mpy>=0.5.1
14
- Requires-Dist: ezarr>=1.1.0
14
+ Requires-Dist: ezarr>=1.1.1
15
15
  Requires-Dist: h5dataframe>=0.2.3 ; extra == 'update'
16
16
  Requires-Python: >=3.12
17
17
  Provides-Extra: update
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vdata"
3
- version = "0.3.1"
3
+ version = "0.3.2"
4
4
  description = "Annotated multivariate observation of timestamped data"
5
5
  authors = [{ name = "Matteo Bouvier", email="matteo.bouvier@hotmail.fr"}]
6
6
  license = "CECILL-B"
@@ -14,7 +14,7 @@ dependencies = [
14
14
  "scipy>=1.12.0",
15
15
  "numpy-indexed>=0.3.7",
16
16
  "ch5mpy>=0.5.1",
17
- "ezarr>=1.1.0",
17
+ "ezarr>=1.1.1",
18
18
  ]
19
19
 
20
20
  [dependency-groups]
@@ -1,5 +1,7 @@
1
1
  """Annotated, temporal and multivariate observation data."""
2
2
 
3
+ from importlib.metadata import metadata
4
+
3
5
  from vdata.data import VData, VDataView, concatenate, convert_anndata_to_vdata
4
6
  from vdata.IO import (
5
7
  IncoherenceError,
@@ -9,13 +11,15 @@ from vdata.IO import (
9
11
  )
10
12
  from vdata.tdf import RepeatingIndex, TemporalDataFrame, TemporalDataFrameView
11
13
  from vdata.timepoint import TimePoint
12
- from vdata.update import CURRENT_VERSION, update_vdata
13
14
 
14
15
  read = VData.read
15
16
  read_from_csv = VData.read_from_csv
16
17
  read_from_anndata = VData.read_from_anndata
17
18
  read_from_pickle = VData.read_from_pickle
18
19
 
20
+ __version__ = metadata("vdata").get("version")
21
+
22
+
19
23
  __all__ = [
20
24
  "VData",
21
25
  "TemporalDataFrame",
@@ -29,6 +33,4 @@ __all__ = [
29
33
  "VLockError",
30
34
  "TimePoint",
31
35
  "RepeatingIndex",
32
- "CURRENT_VERSION",
33
- "update_vdata",
34
36
  ]
@@ -1,8 +1,7 @@
1
- from collections.abc import Collection, MutableMapping
1
+ from collections.abc import Collection
2
2
  from types import EllipsisType
3
3
  from typing import SupportsIndex, TypedDict
4
4
 
5
- import ezarr as ez
6
5
  import numpy as np
7
6
  import numpy.typing as npt
8
7
  import zarr
@@ -23,7 +22,6 @@ type NDArrayLike_IFS = npt.NDArray[np_IFS] | zarr.Array
23
22
  type AnyNDArrayLike_IFS = npt.NDArray[np_IFS] | NDArrayView[np_IFS] | zarr.Array
24
23
 
25
24
  type Collection_IFS = Collection[IFS]
26
- type DictLike[T: ez.SupportsEZReadWrite] = MutableMapping[str, T] | ez.EZDict[T]
27
25
 
28
26
  type Slicer = IFS | tp.TimePoint | Collection[IFS | tp.TimePoint] | range | slice | EllipsisType
29
27
  type MultiSlicer = Collection[IFS | tp.TimePoint] | range | slice | EllipsisType
@@ -1,15 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Sequence
4
- from pathlib import Path
5
- from typing import TYPE_CHECKING, Any, Literal, override
3
+ from collections.abc import MutableMapping, Sequence
4
+ from os import PathLike
5
+ from typing import TYPE_CHECKING, Any, Literal, final, override
6
6
 
7
7
  import numpy.typing as npt
8
8
  import pandas as pd
9
9
  from anndata import AnnData
10
+ from ezarr.dataframe import EZDataFrame
10
11
  from scipy import sparse
11
12
 
12
- from vdata._typing import AnyNDArrayLike, DictLike
13
+ from vdata._typing import AnyNDArrayLike
13
14
  from vdata.anndata_proxy.containers import ArrayStack2DProxy, EZDataFrameContainerProxy, TemporalDataFrameContainerProxy
14
15
  from vdata.anndata_proxy.dataframe import DataFrameProxy_TDF
15
16
 
@@ -19,25 +20,26 @@ if TYPE_CHECKING:
19
20
 
20
21
  def skip_time_axis(slicer: Any) -> tuple[Any, ...]:
21
22
  if isinstance(slicer, tuple):
22
- return (slice(None),) + slicer
23
+ return (slice(None),) + slicer # pyright: ignore[reportUnknownVariableType]
23
24
 
24
25
  return (slice(None), slicer)
25
26
 
26
27
 
27
- class AnnDataProxy(AnnData): # type: ignore[misc]
28
+ @final
29
+ class AnnDataProxy(AnnData):
28
30
  """
29
31
  Class faking to be an anndata.AnnData object but actually wrapping a VData.
30
32
  """
31
33
 
32
34
  __slots__: tuple[str, ...] = "_vdata", "_X", "_layers", "_obs", "_obsm", "_obsp", "_var", "_varm", "_varp", "_uns"
33
35
 
34
- def __init__(self, vdata: VData | VDataView, X: str | None = None) -> None:
36
+ def __init__(self, vdata: VData | VDataView, X: str | None = None) -> None: # pyright: ignore[reportMissingSuperCall]
35
37
  """
36
38
  Args:
37
39
  vdata: a VData object to wrap.
38
40
  X: an optional layer name to use as X.
39
41
  """
40
- self._X = None if X is None else str(X)
42
+ self._X: str | None = None if X is None else str(X) # pyright: ignore[reportConstantRedefinition]
41
43
 
42
44
  if self._X is not None and self._X not in vdata.layers:
43
45
  raise ValueError(f"Could not find layer '{self._X}' in the given VData.")
@@ -55,32 +57,40 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
55
57
  self._varp = EZDataFrameContainerProxy(vdata.varp, name="Varp", index=vdata.var.index, columns=vdata.var.index)
56
58
  self._uns = vdata.uns
57
59
 
60
+ @override
58
61
  def __repr__(self) -> str:
59
62
  return f"AnnDataProxy from {self._vdata}"
60
63
 
61
- def __sizeof__(self, show_stratified: bool | None = None, with_disk: bool = False) -> int:
64
+ @override
65
+ def __sizeof__(self, *, show_stratified: bool | None = None, with_disk: bool = False) -> int:
62
66
  del show_stratified, with_disk
63
67
  raise NotImplementedError
64
68
 
69
+ @override
65
70
  def __delitem__(self, index: Any) -> None:
66
71
  raise NotImplementedError
67
72
 
73
+ @override
68
74
  def __getitem__(self, index: Any) -> AnnDataProxy:
69
75
  """Returns a sliced view of the object."""
70
76
  return AnnDataProxy(self._vdata[skip_time_axis(index)], X=self._X)
71
77
 
78
+ @override
72
79
  def __setitem__(self, index: Any, val: int | float | npt.NDArray[Any] | sparse.spmatrix) -> None:
73
80
  raise NotImplementedError
74
81
 
75
82
  @property
76
- def _n_obs(self) -> int:
83
+ @override
84
+ def n_obs(self) -> int:
77
85
  return self._vdata.n_obs_total
78
86
 
79
87
  @property
80
- def _n_vars(self) -> int:
88
+ @override
89
+ def n_vars(self) -> int:
81
90
  return self._vdata.n_var
82
91
 
83
92
  @property
93
+ @override
84
94
  def X(self) -> AnyNDArrayLike[Any] | None:
85
95
  if self._X is None:
86
96
  return None
@@ -91,15 +101,16 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
91
101
  if isinstance(value, ArrayStack2DProxy):
92
102
  if value.layer_name is None:
93
103
  self._layers["X"] = value.stack()
94
- self._X = "X"
104
+ self._X = "X" # pyright: ignore[reportConstantRedefinition]
95
105
 
96
106
  raise NotImplementedError
97
107
 
98
108
  @X.deleter
99
109
  def X(self) -> None:
100
- self._X = None
110
+ self._X = None # pyright: ignore[reportConstantRedefinition]
101
111
 
102
112
  @property
113
+ @override
103
114
  def layers(self) -> TemporalDataFrameContainerProxy:
104
115
  return self._layers
105
116
 
@@ -113,11 +124,12 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
113
124
  raise NotImplementedError
114
125
 
115
126
  @property
116
- def raw(self) -> None:
127
+ @override
128
+ def raw(self) -> None: # pyright: ignore[reportIncompatibleMethodOverride]
117
129
  raise NotImplementedError
118
130
 
119
131
  @raw.setter
120
- def raw(self, value: AnnData) -> None:
132
+ def raw(self, value: AnnData) -> None: # pyright: ignore[reportPropertyTypeMismatch]
121
133
  raise NotImplementedError
122
134
 
123
135
  @raw.deleter
@@ -125,11 +137,12 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
125
137
  raise NotImplementedError
126
138
 
127
139
  @property
128
- def obs(self) -> DataFrameProxy_TDF:
140
+ @override
141
+ def obs(self) -> DataFrameProxy_TDF: # pyright: ignore[reportIncompatibleMethodOverride]
129
142
  return self._obs
130
143
 
131
144
  @obs.setter
132
- def obs(self, value: pd.DataFrame) -> None:
145
+ def obs(self, value: pd.DataFrame) -> None: # pyright: ignore[reportPropertyTypeMismatch]
133
146
  raise NotImplementedError
134
147
 
135
148
  @obs.deleter
@@ -137,21 +150,23 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
137
150
  raise NotImplementedError
138
151
 
139
152
  @property
153
+ @override
140
154
  def obs_names(self) -> pd.Index:
141
155
  """Names of observations (alias for `.obs.index`)."""
142
156
  return self.obs.index
143
157
 
144
158
  @obs_names.setter
145
- def obs_names(self, names: Sequence[str]) -> None:
159
+ def obs_names(self, names: Sequence[str]) -> None: # pyright: ignore[reportPropertyTypeMismatch]
146
160
  raise NotImplementedError
147
161
 
148
162
  @property
163
+ @override
149
164
  def var(self) -> EZDataFrame:
150
165
  """One-dimensional annotation of variables/ features (`pd.DataFrame`)."""
151
166
  return self._var
152
167
 
153
168
  @var.setter
154
- def var(self, value: pd.DataFrame) -> None:
169
+ def var(self, value: pd.DataFrame) -> None: # pyright: ignore[reportPropertyTypeMismatch]
155
170
  raise NotImplementedError
156
171
 
157
172
  @var.deleter
@@ -159,21 +174,23 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
159
174
  raise NotImplementedError
160
175
 
161
176
  @property
177
+ @override
162
178
  def var_names(self) -> pd.Index:
163
179
  """Names of variables (alias for `.var.index`)."""
164
180
  return self.var.index
165
181
 
166
182
  @var_names.setter
167
- def var_names(self, names: Sequence[str]) -> None:
183
+ def var_names(self, names: Sequence[str]) -> None: # pyright: ignore[reportPropertyTypeMismatch]
168
184
  raise NotImplementedError
169
185
 
170
186
  @property
171
- def uns(self) -> DictLike[Any]:
187
+ @override
188
+ def uns(self) -> MutableMapping[str, Any]:
172
189
  """Unstructured annotation (ordered dictionary)."""
173
190
  return self._uns
174
191
 
175
192
  @uns.setter
176
- def uns(self, value: DictLike[Any]) -> None:
193
+ def uns(self, value: MutableMapping[str, Any]) -> None:
177
194
  raise NotImplementedError
178
195
 
179
196
  @uns.deleter
@@ -181,6 +198,7 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
181
198
  raise NotImplementedError
182
199
 
183
200
  @property
201
+ @override
184
202
  def obsm(self) -> TemporalDataFrameContainerProxy:
185
203
  return self._obsm
186
204
 
@@ -193,6 +211,7 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
193
211
  raise NotImplementedError
194
212
 
195
213
  @property
214
+ @override
196
215
  def varm(self) -> EZDataFrameContainerProxy:
197
216
  return self._varm
198
217
 
@@ -205,6 +224,7 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
205
224
  raise NotImplementedError
206
225
 
207
226
  @property
227
+ @override
208
228
  def obsp(self) -> EZDataFrameContainerProxy:
209
229
  return self._obsp
210
230
 
@@ -217,6 +237,7 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
217
237
  raise NotImplementedError
218
238
 
219
239
  @property
240
+ @override
220
241
  def varp(self) -> EZDataFrameContainerProxy:
221
242
  return self._varp
222
243
 
@@ -265,15 +286,19 @@ class AnnDataProxy(AnnData): # type: ignore[misc]
265
286
  self._init_from_vdata(self._vdata[skip_time_axis(index)])
266
287
 
267
288
  @override
268
- def copy(self, filename: Path | None = None) -> None:
289
+ def copy(self, filename: PathLike[str] | str | None = None) -> AnnData:
269
290
  """Full copy, optionally on disk."""
291
+ AnnData.copy
270
292
  raise NotImplementedError
271
293
 
294
+ @override
272
295
  def write_h5ad(
273
296
  self,
274
- filename: Path | None = None,
297
+ filename: PathLike[str] | str | None = None,
298
+ *,
299
+ convert_strings_to_categoricals: bool = True,
275
300
  compression: Literal["gzip", "lzf"] | None = None,
276
- compression_opts: Any = None,
301
+ compression_opts: int | Any = None,
277
302
  as_dense: Sequence[str] = (),
278
303
  ) -> None:
279
304
  raise NotImplementedError
@@ -1,29 +1,33 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import operator as op
4
- from functools import partialmethod
5
- from typing import (
6
- Any,
7
- Callable,
8
- ClassVar,
4
+ from collections.abc import (
9
5
  Collection,
10
6
  ItemsView,
11
7
  KeysView,
12
8
  MutableMapping,
13
- Union,
14
9
  ValuesView,
10
+ )
11
+ from functools import partialmethod
12
+ from typing import (
13
+ Any,
14
+ Callable,
15
+ ClassVar,
15
16
  cast,
17
+ final,
16
18
  override,
17
19
  )
18
20
 
19
21
  import numpy as np
20
22
  import numpy.typing as npt
23
+ import pandas as pd
21
24
  import scipy.sparse as ss
25
+ from ezarr.dataframe import EZDataFrame
22
26
 
23
- # from h5dataframe import EZDataFrame
24
27
  import vdata
25
- from vdata._typing import IFS, AnyNDArrayLike, AnyNDArrayLike_IFS
28
+ from vdata._typing import IFS, AnyNDArrayLike
26
29
  from vdata.tdf import TemporalDataFrame, TemporalDataFrameBase
30
+ from vdata.tdf.index import RepeatingIndex
27
31
 
28
32
  type _NP_IF = np.integer | np.floating
29
33
 
@@ -77,7 +81,7 @@ class ArrayStack2DProxy:
77
81
  ) -> None:
78
82
  self._array_numeric: AnyNDArrayLike[_NP_IF] | None = array_numeric if array_numeric.size else None
79
83
  self._array_string: AnyNDArrayLike[_NP_IF] | None = array_string if array_string.size else None
80
- self.layer_name: str = layer_name
84
+ self.layer_name: str | None = layer_name
81
85
 
82
86
  @override
83
87
  def __repr__(self) -> str:
@@ -176,6 +180,7 @@ class ArrayStack2DProxy:
176
180
  )
177
181
 
178
182
 
183
+ @final
179
184
  class EZDataFrameContainerProxy:
180
185
  __slots__: tuple[str, ...] = "_h5dfs", "_index", "_columns", "_name", "_sparse_matrices"
181
186
 
@@ -183,8 +188,8 @@ class EZDataFrameContainerProxy:
183
188
  self,
184
189
  h5dfs: MutableMapping[str, EZDataFrame],
185
190
  name: str,
186
- index: AnyNDArrayLike_IFS,
187
- columns: AnyNDArrayLike_IFS | None = None,
191
+ index: RepeatingIndex | pd.Index,
192
+ columns: RepeatingIndex | pd.Index | None = None,
188
193
  ) -> None:
189
194
  self._h5dfs = h5dfs
190
195
  self._index = index
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterable, Iterator, Sequence
3
+ from collections.abc import Collection, Iterable, Iterator
4
4
  from typing import TYPE_CHECKING, Any, SupportsIndex, cast, overload, override
5
5
 
6
6
  import ch5mpy.indexing as ci
@@ -25,7 +25,7 @@ _RESERVED_ATTRIBUTES = frozenset(
25
25
  )
26
26
 
27
27
 
28
- class NDArrayView[T: np.generic | TimePoint](Sequence[T]):
28
+ class NDArrayView[T: np.generic | TimePoint](Collection[T]):
29
29
  """View on a numpy ndarray that can be subsetted infinitely without copying."""
30
30
 
31
31
  __slots__: tuple[str, ...] = "_array", "_index", "_exposed_attr"
@@ -1,11 +1,13 @@
1
1
  from vdata.data.concatenate import concatenate
2
2
  from vdata.data.convert import convert_anndata_to_vdata
3
+ from vdata.data.name import WRITE_PROTOCOL_VERSION
3
4
  from vdata.data.vdata import VData
4
5
  from vdata.data.view import VDataView
5
6
 
6
7
  __all__ = [
7
- 'VData',
8
- 'VDataView',
9
- 'concatenate',
10
- 'convert_anndata_to_vdata'
8
+ "VData",
9
+ "VDataView",
10
+ "concatenate",
11
+ "convert_anndata_to_vdata",
12
+ "WRITE_PROTOCOL_VERSION",
11
13
  ]
@@ -53,7 +53,7 @@ def slicer_to_array(
53
53
  return np.array(reference_index)[np.where(slicer.flatten())]
54
54
 
55
55
  if isinstance(slicer, tp.TimePointNArray):
56
- return slicer[np.where(np.in1d(slicer, reference_index))]
56
+ return slicer[np.where(np.isin(slicer, reference_index))]
57
57
 
58
58
  if not isCollection(slicer):
59
59
  return np.array([slicer]) if slicer in reference_index else np.array([])
@@ -63,7 +63,7 @@ def slicer_to_array(
63
63
  if slicer.dtype == bool:
64
64
  return reference_index[slicer]
65
65
 
66
- return slicer[np.where(np.in1d(slicer, reference_index))]
66
+ return slicer[np.where(np.isin(slicer, reference_index))]
67
67
 
68
68
 
69
69
  def _gets_whole_axis(slicer: PreSlicer) -> bool:
@@ -44,7 +44,7 @@ def parse_timepoints_list(
44
44
  def parse_timepoints(timepoints: pd.DataFrame | EZDataFrame | None) -> EZDataFrame:
45
45
  if timepoints is None:
46
46
  generalLogger.debug(" 'time points' DataFrame was not given.")
47
- return EZDataFrame(pd.DataFrame(columns=np.array(["value"])))
47
+ return EZDataFrame(pd.DataFrame(columns=np.array(["value"]), dtype=float))
48
48
 
49
49
  if not isinstance(timepoints, (pd.DataFrame, EZDataFrame)): # pyright: ignore[reportUnnecessaryIsInstance]
50
50
  raise TypeError(f"'time points' must be a DataFrame, got '{type(timepoints).__name__}'.") # pyright: ignore[reportUnreachable]
@@ -55,7 +55,7 @@ def parse_timepoints(timepoints: pd.DataFrame | EZDataFrame | None) -> EZDataFra
55
55
  timepoints_col = tp.as_timepointarray(timepoints["value"])
56
56
  timepoints_col.sort()
57
57
  timepoints = EZDataFrame(timepoints.drop("value", axis=1))
58
- timepoints.insert(0, "value", timepoints_col)
58
+ timepoints.insert(0, "value", timepoints_col) # pyright: ignore[reportArgumentType]
59
59
  log_timepoints(timepoints)
60
60
 
61
61
  return timepoints
@@ -81,11 +81,11 @@ def check_time_match(data: ParsingDataIn) -> None:
81
81
 
82
82
  # check that timepoints and _time_list and _time_col_name match
83
83
  if data.timepoints_list is not None and not np.all(
84
- np.in1d(data.timepoints_list, tp.as_timepointarray(data.timepoints.value))
84
+ np.isin(data.timepoints_list, tp.as_timepointarray(data.timepoints.value))
85
85
  ):
86
86
  raise ValueError("There are values in 'timepoints_list' unknown in 'timepoints'.")
87
87
 
88
88
  elif data.time_col_name is not None and not np.all(
89
- np.in1d(tp.as_timepointarray(data.obs.timepoints), tp.as_timepointarray(data.timepoints.value))
89
+ np.isin(tp.as_timepointarray(data.obs.timepoints), tp.as_timepointarray(data.timepoints.value))
90
90
  ):
91
91
  raise ValueError(f"There are values in obs['{data.time_col_name}'] unknown in 'timepoints'.")
@@ -10,21 +10,17 @@ import pandas as pd
10
10
  from ezarr.dataframe import EZDataFrame
11
11
 
12
12
  import vdata
13
- from vdata._typing import IFS, DictLike
14
-
15
- # from vdata.data.arrays.lazy import LazyLoc
13
+ from vdata._typing import IFS
14
+ from vdata.data.arrays.lazy import LazyLoc
16
15
  from vdata.IO import generalLogger
17
16
  from vdata.tdf import RepeatingIndex, TemporalDataFrame, TemporalDataFrameView
18
17
  from vdata.tdf.base import TemporalDataFrameBase
19
18
  from vdata.utils import first_in
20
19
 
21
- # D = TypeVar("D", Union[TemporalDataFrame, TemporalDataFrameView], TemporalDataFrameView, EZDataFrame, LazyLoc)
22
- # D_copy = TypeVar("D_copy", TemporalDataFrame, pd.DataFrame)
23
-
24
20
 
25
21
  # Base Containers -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
26
22
  class ArrayContainerMixin[
27
- D: TemporalDataFrameBase | EZDataFrame,
23
+ D: TemporalDataFrameBase | EZDataFrame | LazyLoc,
28
24
  D_copy: TemporalDataFrame | pd.DataFrame,
29
25
  ](MutableMapping[str, D], ABC):
30
26
  @property
@@ -119,7 +115,7 @@ class VBaseArrayContainer[
119
115
 
120
116
  __slots__: tuple[str, ...] = "_vdata", "_data"
121
117
 
122
- def __init__(self, *, data: DictLike[D], vdata: vdata.VData):
118
+ def __init__(self, *, data: MutableMapping[str, D], vdata: vdata.VData):
123
119
  """
124
120
  Args:
125
121
  vdata: the parent VData object this ArrayContainer is linked to.
@@ -129,10 +125,10 @@ class VBaseArrayContainer[
129
125
  generalLogger.debug(f"== Creating {type(self).__name__}. ==========================")
130
126
 
131
127
  self._vdata: vdata.VData = vdata
132
- self._data: DictLike[D] = self._check_init_data(data)
128
+ self._data: MutableMapping[str, D] = self._check_init_data(data)
133
129
 
134
130
  @abstractmethod
135
- def _check_init_data(self, data: DictLike[D]) -> DictLike[D]:
131
+ def _check_init_data(self, data: MutableMapping[str, D]) -> MutableMapping[str, D]:
136
132
  """
137
133
  Function for checking, at ArrayContainer creation, that the supplied data has the correct format.
138
134
 
@@ -230,7 +226,7 @@ class VBaseArrayContainer[
230
226
  pass
231
227
 
232
228
  @property
233
- def data(self) -> DictLike[D]:
229
+ def data(self) -> MutableMapping[str, D]:
234
230
  """
235
231
  Data of this ArrayContainer.
236
232
 
@@ -277,7 +273,7 @@ class VTDFArrayContainer(VBaseArrayContainer[TemporalDataFrame | TemporalDataFra
277
273
  It is based on VBaseArrayContainer and defines some functions shared by obsm and layers.
278
274
  """
279
275
 
280
- def __init__(self, *, data: dict[str, TemporalDataFrame | TemporalDataFrameView], vdata: vdata.VData):
276
+ def __init__(self, *, data: MutableMapping[str, TemporalDataFrame | TemporalDataFrameView], vdata: vdata.VData):
281
277
  """
282
278
  Args:
283
279
  parent: the parent VData object this ArrayContainer is linked to.
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from collections.abc import MutableMapping
3
4
  from typing import override
4
5
 
5
6
  import ezarr as ez
@@ -21,8 +22,8 @@ class VLayersArrayContainer(VTDFArrayContainer):
21
22
 
22
23
  @override
23
24
  def _check_init_data(
24
- self, data: dict[str, TemporalDataFrame | TemporalDataFrameView]
25
- ) -> dict[str, TemporalDataFrame | TemporalDataFrameView]:
25
+ self, data: MutableMapping[str, TemporalDataFrame | TemporalDataFrameView]
26
+ ) -> MutableMapping[str, TemporalDataFrame | TemporalDataFrameView]:
26
27
  """
27
28
  Function for checking, at VLayerArrayContainer creation, that the supplied data has the correct format :
28
29
  - the shape of the TemporalDataFrames in 'data' match the parent VData object's shape.
@@ -44,7 +45,9 @@ class VLayersArrayContainer(VTDFArrayContainer):
44
45
  generalLogger.debug(" Data was found.")
45
46
 
46
47
  _shape = (self._vdata.timepoints.shape[0], self._vdata.obs.shape[1], self._vdata.var.shape[0])
47
- _data: dict[str, TemporalDataFrame | TemporalDataFrameView] = {} if not isinstance(data, ez.EZDict) else data
48
+ _data: MutableMapping[str, TemporalDataFrame | TemporalDataFrameView] = (
49
+ {} if not isinstance(data, ez.EZDict) else data
50
+ )
48
51
 
49
52
  generalLogger.debug(f" Reference shape is {_shape}.")
50
53
 
@@ -83,8 +83,7 @@ class VObsmArrayContainer(VTDFArrayContainer):
83
83
  f"Time points of TemporalDataFrame '{TDF_index}' ({tdf.timepoints}) do not match time_point's index. ({self._vdata.timepoints.value.values})"
84
84
  )
85
85
 
86
- if tdf.data is None or ch.H5Mode.has_write_intent(tdf.data.mode):
87
- tdf.lock_indices()
86
+ tdf.lock_indices()
88
87
 
89
88
  if isinstance(data, dict):
90
89
  _data[str(TDF_index)] = tdf
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Collection
3
+ from collections.abc import Collection, MutableMapping
4
4
  from typing import cast, override
5
5
 
6
6
  import ezarr as ez
@@ -8,7 +8,7 @@ import numpy.typing as npt
8
8
  import pandas as pd
9
9
  from ezarr.dataframe import EZDataFrame
10
10
 
11
- from vdata._typing import IFS, DictLike, np_IFS
11
+ from vdata._typing import IFS, np_IFS
12
12
  from vdata.data.arrays.base import VBaseArrayContainer
13
13
  from vdata.data.arrays.lazy import LazyLoc
14
14
  from vdata.data.arrays.view import VBaseArrayContainerView
@@ -21,7 +21,7 @@ from vdata.IO import (
21
21
  from vdata.utils import first_in
22
22
 
23
23
 
24
- class VVarmArrayContainer(VBaseArrayContainer[pd.DataFrame | EZDataFrame]):
24
+ class VVarmArrayContainer(VBaseArrayContainer[EZDataFrame, pd.DataFrame]):
25
25
  """
26
26
  Class for varm.
27
27
  This object contains any number of DataFrames, with shape (n_var, any).
@@ -30,7 +30,7 @@ class VVarmArrayContainer(VBaseArrayContainer[pd.DataFrame | EZDataFrame]):
30
30
  """
31
31
 
32
32
  @override
33
- def _check_init_data(self, data: DictLike[EZDataFrame]) -> DictLike[EZDataFrame]:
33
+ def _check_init_data(self, data: MutableMapping[str, EZDataFrame]) -> MutableMapping[str, EZDataFrame]:
34
34
  """
35
35
  Function for checking, at VVarmArrayContainer creation, that the supplied data has the correct format :
36
36
  - the index of the DataFrames in 'data' match the index of the parent VData's var DataFrame.
@@ -42,7 +42,7 @@ class VVarmArrayContainer(VBaseArrayContainer[pd.DataFrame | EZDataFrame]):
42
42
  generalLogger.debug(" Data was found.")
43
43
 
44
44
  _index = self._vdata.var.index
45
- _data: DictLike[EZDataFrame] = {} if not isinstance(data, ez.EZDict) else data
45
+ _data: MutableMapping[str, EZDataFrame] = {} if not isinstance(data, ez.EZDict) else data
46
46
 
47
47
  for DF_index, DF in data.items():
48
48
  if not _index.equals(DF.index):
@@ -97,7 +97,7 @@ class VVarmArrayContainer(VBaseArrayContainer[pd.DataFrame | EZDataFrame]):
97
97
  arr.index = pd.Index(values)
98
98
 
99
99
 
100
- class VVarmArrayContainerView(VBaseArrayContainerView[LazyLoc, pd.DataFrame | EZDataFrame]):
100
+ class VVarmArrayContainerView(VBaseArrayContainerView[LazyLoc | EZDataFrame, pd.DataFrame]):
101
101
  # region magic methods
102
102
  def __init__(self, array_container: VVarmArrayContainer, var_slicer: npt.NDArray[np_IFS]):
103
103
  super().__init__(
@@ -164,7 +164,7 @@ class VVarmArrayContainerView(VBaseArrayContainerView[LazyLoc, pd.DataFrame | EZ
164
164
  arr.index = pd.Index(values)
165
165
 
166
166
 
167
- class VVarpArrayContainer(VBaseArrayContainer[pd.DataFrame]): # EZDataFrame,
167
+ class VVarpArrayContainer(VBaseArrayContainer[EZDataFrame, pd.DataFrame]):
168
168
  """
169
169
  Class for varp.
170
170
  This object contains any number of DataFrames, with shape (n_var, n_var).
@@ -173,7 +173,7 @@ class VVarpArrayContainer(VBaseArrayContainer[pd.DataFrame]): # EZDataFrame,
173
173
  """
174
174
 
175
175
  @override
176
- def _check_init_data(self, data: DictLike[EZDataFrame]) -> DictLike[EZDataFrame]:
176
+ def _check_init_data(self, data: MutableMapping[str, EZDataFrame]) -> MutableMapping[str, EZDataFrame]:
177
177
  """
178
178
  Function for checking, at ArrayContainer creation, that the supplied data has the correct format :
179
179
  - the index and column names of the DataFrames in 'data' match the index of the parent VData's var
@@ -186,7 +186,7 @@ class VVarpArrayContainer(VBaseArrayContainer[pd.DataFrame]): # EZDataFrame,
186
186
  generalLogger.debug(" Data was found.")
187
187
 
188
188
  _index = self._vdata.var.index
189
- _data: DictLike[EZDataFrame] = {} if not isinstance(data, ez.EZDict) else data
189
+ _data: MutableMapping[str, EZDataFrame] = {} if not isinstance(data, ez.EZDict) else data
190
190
 
191
191
  for DF_index, DF in data.items():
192
192
  if not _index.equals(DF.index):