[docs]classBinaryIsometricOp(DelayedOp):"""Binary isometric operation involving two n-dimensional seed arrays with the same dimension extents. This is based on Bioconductor's ``DelayedArray::DelayedNaryIsoOp`` class. The data type of the result is determined by NumPy casting given the ``seed`` and ``value`` data types. It is probably safest to cast at least one array to floating-point to avoid problems due to integer overflow. This class is intended for developers to construct new :py:class:`~delayedarray.DelayedArray.DelayedArray` instances. In general, end users should not be interacting with ``BinaryIsometricOp`` objects directly. """
[docs]def__init__(self,left,right,operation:ISOMETRIC_OP_WITH_ARGS):""" Args: left: Any object satisfying the seed contract, see :py:meth:`~delayedarray.DelayedArray.DelayedArray` for details. right: Any object of the same dimensions as ``left`` that satisfies the seed contract, see :py:meth:`~delayedarray.DelayedArray.DelayedArray` for details. operation: String specifying the operation. """ifleft.shape!=right.shape:raiseValueError("'left' and 'right' shapes should be the same")ldummy=numpy.zeros(1,dtype=left.dtype)rdummy=numpy.zeros(1,dtype=right.dtype)withwarnings.catch_warnings():# silence warnings from divide by zero.warnings.simplefilter("ignore")dummy=_execute(ldummy,rdummy,operation)dtype=dummy.dtypeself._left=leftself._right=rightself._op=operationself._dtype=dtypeself._sparse=is_sparse(self._left)andis_sparse(self._right)anddummy[0]==0
@propertydefshape(self)->Tuple[int,...]:""" Returns: Tuple of integers specifying the extent of each dimension of this object. As the name of the class suggests, this is the same as the shapes of the ``left`` and ``right`` objects. """returnself._left.shape@propertydefdtype(self)->numpy.dtype:""" Returns: NumPy type for the data after the operation. This may or may not be the same as the ``left`` or ``right`` objects, depending on how NumPy does the casting for the requested operation. """returnself._dtype@propertydefleft(self):""" Returns: The seed object on the left-hand-side of the operation. """returnself._left@propertydefright(self):""" Returns: The seed object on the right-hand-side of the operation. """returnself._right@propertydefoperation(self)->ISOMETRIC_OP_WITH_ARGS:""" Returns: Name of the operation. """returnself._op
[docs]@chunk_grid.registerdefchunk_grid_BinaryIsometricOp(x:BinaryIsometricOp):"""See :py:meth:`~delayedarray.chunk_grid.chunk_grid`."""lchunk=chunk_grid(x._left)rchunk=chunk_grid(x._right)# Favor the chunking for the more expensive grid, to avoid being penalized# heavily from suboptimal chunking for that array. ## Technically, we could optimize for the case where multiple dimensions# have the same boundaries, in which case we should favor full extraction# of the other dimensions and just iterate over the common dimensions.# This avoids any chunk discrepancies but seems like a pretty unlikely case# - if two arrays of the same shape disagree on the chunk boundaries of one# dimension, they'd probably disagree on the others as well.# # The other solution is to figure out some high-dimensional caching scheme# for the partially consumed chunks. Sounds like a royal pain.iflchunk.cost>rchunk.cost:returnlchunkelse:returnrchunk