From 81bf7c6e41be7dba74284c6b6b36f6bd07891d51 Mon Sep 17 00:00:00 2001 From: Joshua Gould Date: Thu, 18 Jul 2024 08:21:56 -0400 Subject: [PATCH] fix KeyError: "None of [Index(['0_x', '1_x', '0_y', '1_y'], dtype='object')] are in the [columns]" Added test --- dask_image/ndmeasure/_utils/_find_objects.py | 15 ++++++++-- .../test_ndmeasure/test_find_objects.py | 28 ++++++++++++------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/dask_image/ndmeasure/_utils/_find_objects.py b/dask_image/ndmeasure/_utils/_find_objects.py index e9a24ab9..46d60c22 100644 --- a/dask_image/ndmeasure/_utils/_find_objects.py +++ b/dask_image/ndmeasure/_utils/_find_objects.py @@ -1,7 +1,7 @@ +import dask.dataframe as dd import numpy as np import pandas as pd from dask.delayed import Delayed -import dask.dataframe as dd def _array_chunk_location(block_id, chunks): @@ -28,7 +28,8 @@ def _find_bounding_boxes(x, array_location): result = {} for val in unique_vals: positions = np.where(x == val) - slices = tuple(slice(np.min(pos) + array_location[i], np.max(pos) + 1 + array_location[i]) for i, pos in enumerate(positions)) + slices = tuple(slice(np.min(pos) + array_location[i], np.max(pos) + 1 + array_location[i]) for i, pos in + enumerate(positions)) result[val] = slices column_names = [i for i in range(x.ndim)] # column names are: 0, 1, ... nD return pd.DataFrame.from_dict(result, orient='index', columns=column_names) @@ -70,6 +71,14 @@ def _find_objects(ndim, df1, df2): df1 = dd.from_delayed(df1, meta=meta) if isinstance(df2, Delayed): df2 = dd.from_delayed(df2, meta=meta) - ddf = dd.merge(df1, df2, how="outer", left_index=True, right_index=True) + + if len(df1) > 0 and len(df2) > 0: + ddf = dd.merge(df1, df2, how="outer", left_index=True, right_index=True) + elif len(df1) > 0: + ddf = df1 + elif len(df2) > 0: + ddf = df2 + else: + ddf = pd.DataFrame() result = ddf.apply(_merge_bounding_boxes, ndim=ndim, axis=1, meta=meta) return result diff --git a/tests/test_dask_image/test_ndmeasure/test_find_objects.py b/tests/test_dask_image/test_ndmeasure/test_find_objects.py index f4f84fe7..30a4f28d 100644 --- a/tests/test_dask_image/test_ndmeasure/test_find_objects.py +++ b/tests/test_dask_image/test_ndmeasure/test_find_objects.py @@ -1,4 +1,3 @@ -from dask_image.ndmeasure._utils import _labeled_comprehension_delayed import dask.array as da import dask.dataframe as dd import numpy as np @@ -22,9 +21,9 @@ def label_image(): """ label_image = np.zeros((5, 10)).astype(int) - label_image[1:3,0:2] = 111 - label_image[3,3:-2] = 222 - label_image[0:2,-3:] = 333 + label_image[1:3, 0:2] = 111 + label_image[3, 3:-2] = 222 + label_image[0:2, -3:] = 333 label_image = da.from_array(label_image, chunks=(5, 5)) return label_image @@ -43,8 +42,8 @@ def label_image_with_empty_chunk(): [ 0, 0, 0, 0, 0, 0]]) """ label_image = np.zeros((6, 6)).astype(int) - label_image[1:3,0:2] = 111 - label_image[4,3:] = 222 + label_image[1:3, 0:2] = 111 + label_image[4, 3:] = 222 label_image = da.from_array(label_image, chunks=(3, 3)) return label_image @@ -55,6 +54,15 @@ def test_find_objects_err(label_image): dask_image.ndmeasure.find_objects(label_image) +def test_empty_chunk(): + test_labels = da.zeros((10, 10), dtype='int', chunks=(3, 3)) + test_labels[0, 0] = 1 + computed_result = dask_image.ndmeasure.find_objects(test_labels).compute() + expected = pd.DataFrame.from_dict({0: {1: slice(0, 1)}, + 1: {1: slice(0, 1)}, }) + assert computed_result.equals(expected) + + def test_find_objects(label_image): result = dask_image.ndmeasure.find_objects(label_image) assert isinstance(result, dd.DataFrame) @@ -62,7 +70,7 @@ def test_find_objects(label_image): assert isinstance(computed_result, pd.DataFrame) expected = pd.DataFrame.from_dict( {0: {111: slice(1, 3), 222: slice(3, 4), 333: slice(0, 2)}, - 1: {111: slice(0, 2), 222: slice(3, 8), 333: slice(7, 10)}} + 1: {111: slice(0, 2), 222: slice(3, 8), 333: slice(7, 10)}} ) assert computed_result.equals(expected) @@ -75,8 +83,8 @@ def test_3d_find_objects(label_image): assert isinstance(computed_result, pd.DataFrame) expected = pd.DataFrame.from_dict( {0: {111: slice(1, 3), 222: slice(3, 4), 333: slice(0, 2)}, - 1: {111: slice(0, 2), 222: slice(3, 8), 333: slice(7, 10)}, - 2: {111: slice(0, 2), 222: slice(0, 2), 333: slice(0, 2)}} + 1: {111: slice(0, 2), 222: slice(3, 8), 333: slice(7, 10)}, + 2: {111: slice(0, 2), 222: slice(0, 2), 333: slice(0, 2)}} ) assert computed_result.equals(expected) @@ -88,6 +96,6 @@ def test_find_objects_with_empty_chunks(label_image_with_empty_chunk): assert isinstance(computed_result, pd.DataFrame) expected = pd.DataFrame.from_dict( {0: {111: slice(1, 3, None), 222: slice(4, 5, None)}, - 1: {111: slice(0, 2, None), 222: slice(3, 6, None)}} + 1: {111: slice(0, 2, None), 222: slice(3, 6, None)}} ) assert computed_result.equals(expected)