[docs]classCombine(DelayedOp):"""Delayed combine operation, based on Bioconductor's ``DelayedArray::DelayedAbind`` class. This will combine multiple arrays along a specified dimension, provided the extents of all other dimensions are the same. This class is intended for developers to construct new :py:class:`~delayedarray.DelayedArray.DelayedArray` instances. In general, end users should not be interacting with ``Combine`` objects directly. """
[docs]def__init__(self,seeds:list,along:int):""" Args: seeds: List of objects that satisfy the seed contract, see :py:class:`~delayedarray.DelayedArray.DelayedArray` for details. along: Dimension along which the seeds are to be combined. """self._seeds=seedsiflen(seeds)==0:raiseValueError("expected at least one object in 'seeds'")shape=list(seeds[0].shape)ndim=len(shape)foriinrange(1,len(seeds)):curshape=seeds[i].shapefordinrange(ndim):ifd==along:shape[d]+=curshape[d]elifshape[d]!=curshape[d]:raiseValueError("expected seeds to have the same extent for non-'along' dimensions")self._shape=(*shape,)self._along=along# Guessing the dtype.to_combine=[]foriinrange(len(seeds)):to_combine.append(numpy.ndarray((0,),dtype=seeds[i].dtype))self._dtype=_concatenate_unmasked_ndarrays(to_combine,axis=0).dtypeself._is_masked=any(is_masked(y)foryinself._seeds)
@propertydefshape(self)->Tuple[int,...]:""" Returns: Tuple of integers specifying the extent of each dimension of the object after seeds were combined along the specified dimension. """returnself._shape@propertydefdtype(self)->numpy.dtype:""" Returns: NumPy type for the combined data. This may or may not be the same as those in ``seeds``, depending on casting rules. """returnself._dtype@propertydefseeds(self)->list:""" Returns: List of seed objects to be combined. """returnself._seeds@propertydefalong(self)->int:""" Returns: Dimension along which the seeds are combined. """returnself._along
def_extract_subarrays(x:Combine,subset:Tuple[Sequence[int],...],f:Callable):# Figuring out which slices belong to who.chosen=subset[x._along]limit=0fragmented=[]position=0forsinx._seeds:start=limitlimit+=s.shape[x._along]current=[]whileposition<len(chosen)andchosen[position]<limit:current.append(chosen[position]-start)position+=1fragmented.append(current)# Extracting the desired slice from each seed.extracted=[]flexargs=list(subset)fori,sinenumerate(x._seeds):iflen(fragmented[i]):flexargs[x._along]=fragmented[i]extracted.append(f(s,(*flexargs,)))returnextracted