Source code for ewoksndreg.math.crop

from typing import List
from typing import Optional
from typing import Tuple

import numpy

CropLimitsType = Optional[List[Tuple[int, int]]]


[docs] def array_crop_limits( array: numpy.ndarray, ) -> CropLimitsType: """Calculate array index limits for each dimension to strip invalid value blocks at the edges. :param array: :returns: A 2-tuple for each array dimension `[(lo0, hi0), (lo1, hi1), ...]` or `None` when the cropped sub-array is empty. """ valid = numpy.isfinite(array) if not valid.any(): return None idx_valid = numpy.where(valid) for idx in idx_valid: if idx.size == 0: return None return [(int(idx.min()), int(idx.max())) for idx in idx_valid]
[docs] def merge_crop_limits( all_limits: List[CropLimitsType], intersection: bool ) -> CropLimitsType: """Merge several array limits either by taking the intersection or the envelop. :param all_limits: several results of `array_crop_limits` :returns: A 2-tuple for each array dimension `[(lo0, hi0), (lo1, hi1), ...]` or `None` when the merged limits box is empty. """ if None in all_limits: if intersection: return None else: all_limits = [limits for limits in all_limits if limits is not None] if not all_limits: return None all_lows = [[limit[0] for limit in limits] for limits in all_limits] all_highs = [[limit[1] for limit in limits] for limits in all_limits] if intersection: overall_low = numpy.max(all_lows, axis=0) overall_high = numpy.min(all_highs, axis=0) else: overall_low = numpy.min(all_lows, axis=0) overall_high = numpy.max(all_highs, axis=0) if (overall_low >= overall_high).any(): return None return list(zip(overall_low.tolist(), overall_high.tolist()))