-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTranspose.py
More file actions
163 lines (128 loc) · 4.71 KB
/
Transpose.py
File metadata and controls
163 lines (128 loc) · 4.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
from typing import Callable, Optional, Tuple, Sequence, Any
from numpy import dtype, transpose
import numpy
import copy
from .DelayedOp import DelayedOp
from .SparseNdarray import SparseNdarray
from .extract_dense_array import extract_dense_array
from .extract_sparse_array import extract_sparse_array
from .create_dask_array import create_dask_array
from .chunk_grid import chunk_grid
from .is_sparse import is_sparse
from .is_masked import is_masked
__author__ = "ltla"
__copyright__ = "ltla"
__license__ = "MIT"
class Transpose(DelayedOp):
"""Delayed transposition, based on Bioconductor's ``DelayedArray::DelayedAperm`` class.
This will create a matrix transpose in the 2-dimensional case; for a high-dimensional array, it will permute the
dimensions.
This class is intended for developers to construct new :py:class:`~delayedarray.DelayedArray.DelayedArray`
instances. In general, end users should not be interacting with ``Transpose`` objects directly.
"""
def __init__(self, seed, perm: Optional[Tuple[int, ...]]):
"""
Args:
seed:
Any object that satisfies the seed contract,
see :py:class:`~delayedarray.DelayedArray.DelayedArray` for details.
perm:
Tuple of length equal to the dimensionality of ``seed``,
containing the permutation of dimensions. If None, the
dimension ordering is assumed to be reversed.
"""
curshape = seed.shape
ndim = len(curshape)
if perm is not None:
if len(perm) != ndim:
raise ValueError(
"Dimensionality of 'seed' and 'perm' should be the same."
)
else:
perm = (*range(ndim - 1, -1, -1),)
final_shape = []
for x in perm:
final_shape.append(curshape[x])
self._seed = seed
self._perm = perm
self._shape = (*final_shape,)
@property
def shape(self) -> Tuple[int, ...]:
"""
Returns:
Tuple of integers specifying the extent of each dimension of the
transposed object.
"""
return self._shape
@property
def dtype(self) -> dtype:
"""
Returns:
NumPy type for the transposed contents, same as ``seed``.
"""
return self._seed.dtype
@property
def seed(self):
"""
Returns:
The seed object.
"""
return self._seed
@property
def perm(self) -> Tuple[int, ...]:
"""
Returns:
Permutation of dimensions in the transposition.
"""
return self._perm
def _simplify_transpose(x: Transpose) -> Any:
seed = x.seed
if not type(seed) is Transpose:
# Don't use isinstance, we don't want to collapse for Transpose
# subclasses that might be doing god knows what.
return x
new_perm = []
noop = True
for i, p in enumerate(x.perm):
new_p = seed.perm[p]
if new_p != i:
noop = False
new_perm.append(new_p)
if noop:
return seed.seed
new_x = copy.copy(x)
new_x._seed = seed.seed
new_x._perm = (*new_perm,)
return new_x
def _extract_array(x: Transpose, subset: Tuple[Sequence[int], ...], f: Callable):
permsub = [None] * len(subset)
for i, j in enumerate(x._perm):
permsub[j] = subset[i]
target = f(x._seed, (*permsub,))
return transpose(target, axes=x._perm)
@extract_dense_array.register
def extract_dense_array_Transpose(x: Transpose, subset: Tuple[Sequence[int], ...]) -> numpy.ndarray:
"""See :py:meth:`~delayedarray.extract_dense_array.extract_dense_array`."""
return _extract_array(x, subset, extract_dense_array)
@extract_sparse_array.register
def extract_sparse_array_Transpose(x: Transpose, subset: Tuple[Sequence[int], ...]) -> SparseNdarray:
"""See :py:meth:`~delayedarray.extract_sparse_array.extract_sparse_array`."""
return _extract_array(x, subset, extract_sparse_array)
@create_dask_array.register
def create_dask_array_Transpose(x: Transpose):
"""See :py:meth:`~delayedarray.create_dask_array.create_dask_array`."""
target = create_dask_array(x._seed)
return transpose(target, axes=x._perm)
@chunk_grid.register
def chunk_grid_Transpose(x: Transpose):
"""See :py:meth:`~delayedarray.chunk_grid.chunk_grid`."""
chunks = chunk_grid(x._seed)
return chunks.transpose(x._perm)
@is_sparse.register
def is_sparse_Transpose(x: Transpose):
"""See :py:meth:`~delayedarray.is_sparse.is_sparse`."""
return is_sparse(x._seed)
@is_masked.register
def is_masked_Transpose(x: Transpose):
"""See :py:meth:`~delayedarray.is_masked.is_masked`."""
return is_masked(x._seed)