def test_copysegmentation_dvid_to_zarr(setup_dvid_to_zarr): template_dir, config, volume, dvid_address, repo_uuid, output_file = setup_dvid_to_zarr # Modify the config from above to compute pyramid scales, # and choose a bounding box that is aligned with the bricks even at scale 2 # (just for easier testing). box_zyx = [[0, 0, 0], [256, 256, 256]] config["input"]["geometry"]["bounding-box"] = box_zyx config["copysegmentation"]["pyramid-depth"] = 2 yaml = YAML() yaml.default_flow_style = False with open(f"{template_dir}/workflow.yaml", 'w') as f: yaml.dump(config, f) execution_dir, _workflow = launch_flow(template_dir, 1) box_zyx = np.array(box_zyx) scale_0_vol = volume[box_to_slicing(*box_zyx)] scale_1_vol = downsample_labels(scale_0_vol, 2, True) scale_2_vol = downsample_labels(scale_1_vol, 2, True) store = zarr.NestedDirectoryStore(f"{execution_dir}/{output_file}") f = zarr.open(store, 'r') output_0_vol = f['s0'][box_to_slicing(*(box_zyx // 1))] output_1_vol = f['s1'][box_to_slicing(*(box_zyx // 2))] output_2_vol = f['s2'][box_to_slicing(*(box_zyx // 4))] assert (output_0_vol == scale_0_vol).all(), \ "Scale 0: Written vol does not match expected" assert (output_1_vol == scale_1_vol).all(), \ "Scale 1: Written vol does not match expected" assert (output_2_vol == scale_2_vol).all(), \ "Scale 2: Written vol does not match expected"
def test_copygrayscale_from_hdf5_to_dvid_multiscale(setup_hdf5_grayscale_input, disable_auto_retry): _template_dir, config, _volume, dvid_address, repo_uuid, output_grayscale_name = setup_hdf5_grayscale_input # Modify the config from above to compute pyramid scales, # and choose a bounding box that is aligned with the bricks even at scale 2 # (just for easier testing). config["input"]["geometry"]["bounding-box"] = [[0, 0, 0], [128, 256, 128]] config["copygrayscale"]["min-pyramid-scale"] = 1 config["copygrayscale"]["max-pyramid-scale"] = 2 config["copygrayscale"][ "downsample-method"] = "label" # This test is easier to write if we use this downsampling method box_zyx, scale_0_vol = _run_to_dvid(setup_hdf5_grayscale_input, check_scale_0=False) scale_1_vol = downsample_labels(scale_0_vol, 2, True) scale_2_vol = downsample_labels(scale_1_vol, 2, True) # Check the other scales -- be careful to extract exactly one brick. output_vol = fetch_raw(dvid_address, repo_uuid, output_grayscale_name + '_1', box_zyx // 2) assert (output_vol == scale_1_vol).all(), \ "Scale 1: Written vol does not match expected" # Check the other scales -- be careful to extract exactly one brick. output_vol = fetch_raw(dvid_address, repo_uuid, output_grayscale_name + '_2', box_zyx // 4) assert (output_vol == scale_2_vol).all(), \ "Scale 2: Written vol does not match expected"
def downsample(volume, factor, method): assert method in DOWNSAMPLE_METHODS assert (np.array(volume.shape) % factor == 0).all(), \ "Volume dimensions must be a multiple of the downsample factor." if method == 'subsample': sl = slice(None, None, factor) return volume[(sl, ) * volume.ndim].copy('C') if method == 'block-mean': return block_downsample(volume, factor) if method in ('zoom', 'grayscale'): # synonyms # vigra is 2.7x faster than scipy, but it complains for small images: # # Precondition violation! # resizeImage(): Each output axis must have length > 1.) # # Furthermore, it seems to be somewhat unstable even for small # images that satisfy the above condition. # Therefore, use vigra for non-tiny images, # and use scipy for the tiny stuff. newshape = np.array(volume.shape) // factor if (newshape >= 10).all(): return vigra_sampling_resize(volume, newshape) else: return scipy.ndimage.zoom(volume, 1 / factor) if method == 'mode': return downsample_labels(volume, factor, False) if method in ('labels', 'label'): # synonyms return downsample_labels(volume, factor, True) if method == 'labels-numba': reduced_output, _reduced_box = downsample_labels_3d_suppress_zero( volume, factor) return reduced_output raise AssertionError("Shouldn't get here.")
def downsample_brick(brick): assert (brick.physical_box % factor == 0).all() assert (brick.logical_box % factor == 0).all() if method == 'grayscale': downsampled_volume = scipy.ndimage.interpolation.zoom(brick.volume, 1/factor, mode='reflect') elif method == 'label': # Old: Python downsampling # downsample_3Dlabels(brick.volume) # Newer: Numba downsampling #downsampled_volume, _ = downsample_labels_3d_suppress_zero(brick.volume, (2,2,2), brick.physical_box) # Even Newer: C++ downsampling (note: only works on aligned data.) # For consistency with DVID's on-demand downsampling, we suppress 0 pixels. downsampled_volume = downsample_labels(brick.volume, factor, suppress_zero=True) else: assert False downsampled_logical_box = brick.logical_box // factor downsampled_physical_box = brick.physical_box // factor return Brick(downsampled_logical_box, downsampled_physical_box, downsampled_volume)
def test_copysegmentation_from_hdf5_to_dvid_multiscale( setup_hdf5_segmentation_input, disable_auto_retry): template_dir, config, volume, dvid_address, repo_uuid, _ = setup_hdf5_segmentation_input # Modify the config from above to compute pyramid scales, # and choose a bounding box that is aligned with the bricks even at scale 2 # (just for easier testing). box_zyx = [[0, 0, 0], [256, 256, 256]] config["input"]["geometry"]["bounding-box"] = box_zyx config["copysegmentation"]["pyramid-depth"] = 2 # Change the segmentation name so it doesn't conflict with earlier tests output_segmentation_name = 'segmentation-output-from-hdf5-multiscale' config["output"]["dvid"]["segmentation-name"] = output_segmentation_name yaml = YAML() yaml.default_flow_style = False with open(f"{template_dir}/workflow.yaml", 'w') as f: yaml.dump(config, f) _execution_dir, _workflow = launch_flow(template_dir, 1) box_zyx = np.array(box_zyx) scale_0_vol = volume[box_to_slicing(*box_zyx)] scale_1_vol = downsample_labels(scale_0_vol, 2, True) scale_2_vol = downsample_labels(scale_1_vol, 2, True) output_0_vol = fetch_labelmap_voxels(dvid_address, repo_uuid, output_segmentation_name, box_zyx // 1, scale=0) output_1_vol = fetch_labelmap_voxels(dvid_address, repo_uuid, output_segmentation_name, box_zyx // 2, scale=1) output_2_vol = fetch_labelmap_voxels(dvid_address, repo_uuid, output_segmentation_name, box_zyx // 4, scale=2) # np.save('/tmp/expected-0.npy', scale_0_vol) # np.save('/tmp/expected-1.npy', scale_1_vol) # np.save('/tmp/expected-2.npy', scale_2_vol) # # np.save('/tmp/output-0.npy', output_0_vol) # np.save('/tmp/output-1.npy', output_1_vol) # np.save('/tmp/output-2.npy', output_2_vol) # # np.save('/tmp/diff-0.npy', (output_0_vol != scale_0_vol)) # np.save('/tmp/diff-1.npy', (output_1_vol != scale_1_vol)) # np.save('/tmp/diff-2.npy', (output_2_vol != scale_2_vol)) assert (output_0_vol == scale_0_vol).all(), \ "Scale 0: Written vol does not match expected" assert (output_1_vol == scale_1_vol).all(), \ "Scale 1: Written vol does not match expected" assert (output_2_vol == scale_2_vol).all(), \ "Scale 2: Written vol does not match expected"