def test_sparse_boxes_WITH_OFFSET(): block_mask = np.zeros((5, 6, 7), dtype=bool) # since mask offset is 20, this spans 3 bricks (physical: 20-70, logical: 0-90) block_mask[0, 0, 0:5] = True # spans a single brick (physical: 30-60, logical: 30-60) block_mask[0, 1, 1:4] = True block_mask_resolution = 10 # MASK STARTS AT OFFSET mask_box_start = np.array([0, 10, 20]) mask_box_stop = mask_box_start + 10 * np.array(block_mask.shape) block_mask_box = (mask_box_start, mask_box_stop) brick_grid = Grid((10, 10, 30), (0, 0, 0)) sparse_block_mask = SparseBlockMask(block_mask, block_mask_box, block_mask_resolution) logical_boxes = sparse_block_mask.sparse_boxes(brick_grid, return_logical_boxes=True) assert (logical_boxes == [[[0, 10, 0], [10, 20, 30]], [[0, 10, 30], [10, 20, 60]], [[0, 10, 60], [10, 20, 90]], [[0, 20, 30], [10, 30, 60]]]).all() physical_boxes = sparse_block_mask.sparse_boxes(brick_grid, return_logical_boxes=False) assert (physical_boxes == [[[0, 10, 20], [10, 20, 30]], [[0, 10, 30], [10, 20, 60]], [[0, 10, 60], [10, 20, 70]], [[0, 20, 30], [10, 30, 60]]]).all()
def test_sparse_boxes_NO_OFFSET(): block_mask = np.zeros((5, 6, 7), dtype=bool) block_mask[0, 0, 0:5] = True block_mask[0, 1, 1:4] = True block_mask_resolution = 10 # MASK STARTS AT ORIGIN (NO OFFSET) mask_box_start = np.array([0, 0, 0]) mask_box_stop = mask_box_start + 10 * np.array(block_mask.shape) block_mask_box = (mask_box_start, mask_box_stop) brick_grid = Grid((10, 10, 30)) sparse_block_mask = SparseBlockMask(block_mask, block_mask_box, block_mask_resolution) logical_boxes = sparse_block_mask.sparse_boxes(brick_grid, return_logical_boxes=True) assert (logical_boxes == [[[0, 0, 0], [10, 10, 30]], [[0, 0, 30], [10, 10, 60]], [[0, 10, 0], [10, 20, 30]], [[0, 10, 30], [10, 20, 60]]]).all() physical_boxes = sparse_block_mask.sparse_boxes(brick_grid, return_logical_boxes=False) assert (physical_boxes == [[[0, 0, 0], [10, 10, 30]], [[0, 0, 30], [10, 10, 50]], [[0, 10, 10], [10, 20, 30]], [[0, 10, 30], [10, 20, 40]]]).all()
def init_boxes(self, volume_service, roi): if not roi["name"]: boxes = boxes_from_grid(volume_service.bounding_box_zyx, volume_service.preferred_message_shape, clipped=True) return np.array([*boxes]) base_service = volume_service.base_service if not roi["server"] or not roi["uuid"]: assert isinstance(base_service, DvidVolumeService), \ "Since you aren't using a DVID input source, you must specify the ROI server and uuid." roi["server"] = (roi["server"] or volume_service.server) roi["uuid"] = (roi["uuid"] or volume_service.uuid) if roi["scale"] is not None: scale = roi["scale"] elif isinstance(volume_service, ScaledVolumeService): scale = volume_service.scale_delta assert scale <= 5, \ "The 'roi' option doesn't support volumes downscaled beyond level 5" else: scale = 0 brick_shape = volume_service.preferred_message_shape assert not (brick_shape % 2**(5-scale)).any(), \ "If using an ROI, select a brick shape that is divisible by 32" seg_box = volume_service.bounding_box_zyx seg_box = round_box(seg_box, 2**(5 - scale)) seg_box_s0 = seg_box * 2**scale seg_box_s5 = seg_box // 2**(5 - scale) with Timer( f"Fetching mask for ROI '{roi['name']}' ({seg_box_s0[:, ::-1].tolist()})", logger): roi_mask_s5, _ = fetch_roi(roi["server"], roi["uuid"], roi["name"], format='mask', mask_box=seg_box_s5) # SBM 'full-res' corresponds to the input service voxels, not necessarily scale-0. sbm = SparseBlockMask(roi_mask_s5, seg_box, 2**(5 - scale)) boxes = sbm.sparse_boxes(brick_shape) # Clip boxes to the true (not rounded) bounding box boxes[:, 0] = np.maximum(boxes[:, 0], volume_service.bounding_box_zyx[0]) boxes[:, 1] = np.minimum(boxes[:, 1], volume_service.bounding_box_zyx[1]) return boxes
def init_boxes(self, volume_service, roi): if not roi: boxes = boxes_from_grid(volume_service.bounding_box_zyx, volume_service.preferred_message_shape, clipped=True) return np.array([*boxes]) base_service = volume_service.base_service assert isinstance(base_service, DvidVolumeService), \ "Can't specify an ROI unless you're using a dvid input" assert isinstance(volume_service, (ScaledVolumeService, DvidVolumeService)), \ "The 'roi' option doesn't support adapters other than 'rescale-level'" scale = 0 if isinstance(volume_service, ScaledVolumeService): scale = volume_service.scale_delta assert scale <= 5, \ "The 'roi' option doesn't support volumes downscaled beyond level 5" server, uuid, _seg_instance = base_service.instance_triple brick_shape = volume_service.preferred_message_shape assert not (brick_shape % 2**(5-scale)).any(), \ "If using an ROI, select a brick shape that is divisible by 32" seg_box = volume_service.bounding_box_zyx seg_box = round_box(seg_box, 2**(5 - scale)) seg_box_s0 = seg_box * 2**scale seg_box_s5 = seg_box // 2**(5 - scale) with Timer( f"Fetching mask for ROI '{roi}' ({seg_box_s0[:, ::-1].tolist()})", logger): roi_mask_s5, _ = fetch_roi(server, uuid, roi, format='mask', mask_box=seg_box_s5) # SBM 'full-res' corresponds to the input service voxels, not necessarily scale-0. sbm = SparseBlockMask(roi_mask_s5, seg_box, 2**(5 - scale)) boxes = sbm.sparse_boxes(brick_shape) # Clip boxes to the true (not rounded) bounding box boxes[:, 0] = np.maximum(boxes[:, 0], volume_service.bounding_box_zyx[0]) boxes[:, 1] = np.minimum(boxes[:, 1], volume_service.bounding_box_zyx[1]) return boxes
def init_boxes(self, volume_service, roi, chunk_shape_s0): """ Return a set of bounding boxes to tile the given ROI. Scale 0 of the volume service should correspond to full-res data, which is 32x higher-res than ROI resolution. """ if not roi["name"]: boxes = boxes_from_grid(volume_service.bounding_box_zyx, chunk_shape_s0, clipped=True) return np.array([*boxes]) base_service = volume_service.base_service if not roi["server"] or not roi["uuid"]: assert isinstance(base_service, DvidVolumeService), \ "Since you aren't using a DVID input source, you must specify the ROI server and uuid." roi["server"] = (roi["server"] or volume_service.server) roi["uuid"] = (roi["uuid"] or volume_service.uuid) assert not (chunk_shape_s0 % 2**5).any(), \ "If using an ROI, select a chunk shape that is divisible by 32" seg_box_s0 = volume_service.bounding_box_zyx seg_box_s0 = round_box(seg_box_s0, 2**5) seg_box_s5 = seg_box_s0 // 2**5 with Timer( f"Fetching mask for ROI '{roi['name']}' ({seg_box_s0[:, ::-1].tolist()})", logger): roi_mask_s5, _ = fetch_roi(roi["server"], roi["uuid"], roi["name"], format='mask', mask_box=seg_box_s5) # SBM 'full-res' corresponds to the input service voxels, not necessarily scale-0. sbm = SparseBlockMask(roi_mask_s5, seg_box_s0, 2**5) boxes = sbm.sparse_boxes(chunk_shape_s0) # Clip boxes to the true (not rounded) bounding box boxes[:, 0] = np.maximum(boxes[:, 0], volume_service.bounding_box_zyx[0]) boxes[:, 1] = np.minimum(boxes[:, 1], volume_service.bounding_box_zyx[1]) return boxes
def init_boxes(self, volume_service, roi): if not roi["name"]: boxes = boxes_from_grid(volume_service.bounding_box_zyx, volume_service.preferred_message_shape, clipped=True) return np.array([*boxes]) server, uuid, roi_name = roi["server"], roi["uuid"], roi["name"] roi_scale = roi["relative-scale"] brick_shape = volume_service.preferred_message_shape assert not (brick_shape % 2**roi_scale).any(), \ "If using an ROI, select a brick shape that is divisible by 32" seg_box = volume_service.bounding_box_zyx seg_box = round_box(seg_box, 2**roi_scale) seg_box_s5 = seg_box // 2**roi_scale with Timer( f"Fetching mask for ROI '{roi_name}' ({seg_box[:, ::-1].tolist()})", logger): roi_mask_s5, _ = fetch_roi(server, uuid, roi_name, format='mask', mask_box=seg_box_s5) # SBM 'full-res' corresponds to the input service voxels, not necessarily scale-0. sbm = SparseBlockMask(roi_mask_s5, seg_box, 2**roi_scale) boxes = sbm.sparse_boxes(brick_shape) # Clip boxes to the true (not rounded) bounding box boxes[:, 0] = np.maximum(boxes[:, 0], volume_service.bounding_box_zyx[0]) boxes[:, 1] = np.minimum(boxes[:, 1], volume_service.bounding_box_zyx[1]) return boxes