Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transposing ArrayProxies #1136

Open
effigies opened this issue Sep 7, 2022 · 0 comments
Open

Transposing ArrayProxies #1136

effigies opened this issue Sep 7, 2022 · 0 comments

Comments

@effigies
Copy link
Member

effigies commented Sep 7, 2022

For an ArrayProxy with contiguous data, it is possible to do something like:

class ArrayProxy:
    @property
    def T(self):
        ret = copy(self)
        ret.order = 'C' if self.order == 'F' else 'F'
        ret.shape = self.shape[::-1]
        return ret

This would permit gross manipulation of arrays without loading them into memory, and in particular would make it very cheap to flip a CIFTI-2 where the BrainModelAxis is dimension 1 to dimension 0 (typical for Connectome WB tools, but weird when you expect spatial axes first). However, it could not be implemented in all ArrayProxys.

We have already done something similar with reshape:

def reshape_dataobj(obj, shape):
""" Use `obj` reshape method if possible, else numpy reshape function
"""
return (obj.reshape(shape) if hasattr(obj, 'reshape')
else np.reshape(obj, shape))

I wonder if it's time to start thinking about a consistent interface:

class BaseArrayProxy(np.ArrayLike):
    # Subclasses implement JIT loading, scaling, casting
    def __array__(self, dtype=None) -> np.ndarray: ...
    def __getitem__(self) -> np.ndarray: ...

    # Generic properties like shape, dtype, ndim

    @property
    def T(self) -> np.ArrayLike:
        return np.transpose(self)

    def reshape(self, shape) -> np.ArrayLike:
        return np.reshape(self, shape)

class ContiguousArrayProxy(BaseArrayProxy):
    # Implements optimizations
    # Requires order parameter
    @property
    def T(self): ...

    def reshape(self, shape): ...

class ArrayProxy(ContiguousArrayProxy):
    # Implement current ArrayProxy: (offset, shape, dtype, slope, inter)

I think, for instance, that AFNIArrayProxy might better fit as a subclass of ContiguousArrayProxy, since it can have different scale-factors per time point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant