Skip to content

Commit a337a4c

Browse files
committed
MAINT, TST: PR #33 revisions
* revert changes associated with removal of fastparquet * add test case for contour filtering to enforce bbox_area calculation
1 parent 3df935a commit a337a4c

3 files changed

Lines changed: 24 additions & 7 deletions

File tree

neat_ml/bubblesam/bubblesam.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,13 @@ def bubblesam_detection(
274274
# save filtered dataframe as parquet file
275275
# convert ``contour`` column to list to save as parquet
276276
save_filtered_df = filtered_df.copy()
277-
save_filtered_df["contour"] = save_filtered_df["contour"].apply(list)
277+
save_filtered_df["bbox"] = save_filtered_df["bbox"].apply(list)
278+
save_filtered_df["contour"] = save_filtered_df["contour"].apply(
279+
lambda x: [arr.tolist() if isinstance(arr, np.ndarray) else arr for arr in x]
280+
)
278281
save_filtered_df.to_parquet(
279282
output_dir / f'{image_basename}_masks_filtered.parquet.gzip',
283+
engine="fastparquet",
280284
compression="gzip",
281285
)
282286

neat_ml/tests/test_bubblesam.py

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ def test_bubblesam_detection_generates_pngs(
156156
)
157157
saved_df = pd.read_parquet(
158158
out_dir / "circles_masks_filtered.parquet.gzip",
159+
engine="fastparquet",
159160
)
160161
saved_df["bbox"] = saved_df["bbox"].apply(tuple)
161162
saved_df['contour'] = saved_df['contour'].apply(
@@ -318,24 +319,35 @@ def test_run_bubblesam_model_cfg_error():
318319
with pytest.raises(ValueError, match="Must provide model configuration"):
319320
run_bubblesam(pd.DataFrame(), Path("output"), detection_cfg={})
320321

321-
def test_bubblesam_contours():
322+
@pytest.mark.parametrize("seg_params, exp_bbox",
323+
[
324+
# a test case where the segmentation contains two disjoint areas
325+
([[50, 60], [40, 45]], (50, 50, 60, 60)),
326+
# a test case where the segmentation contains a region that touches
327+
# the image boundary at the bottom right corner
328+
([[90, 100]], (90, 90, 100, 100)),
329+
]
330+
)
331+
def test_bubblesam_contours(seg_params, exp_bbox):
322332
"""
323333
test that running `analyze_and_filter_masks` generates a dataframe with
324334
only a single contour per detection and without background areas
325335
"""
326336
# create two segmentation maps, one that takes up the whole image (background)
327-
# and one that has two segmented areas (one smaller than the other)
337+
# and one containing the segmentation map generated using the test case parameters
328338
seg = np.ones((100, 100)).astype(bool)
329339
seg2 = np.zeros((100, 100)).astype(bool)
330-
seg2[50:60, 50:60] = True
331-
seg2[40:45, 40:45] = True
340+
for seg_param in seg_params:
341+
start = seg_param[0]
342+
end = seg_param[1]
343+
seg2[start:end, start:end] = True
332344
input_df = pd.DataFrame({"segmentation": [seg, seg2]})
333345
# call `analyze_and_filter_masks` to return filtered dataframe
334346
# (the circularity of a perfect square is ~0.8, so lower the
335347
# circularity threshold so that the background only gets filtered
336348
# out by the bounding box area)
337349
df = analyze_and_filter_masks(input_df, 25, 0.7, device="cpu")
338350
# assert that there is only a single dataframe row after filtration
339-
# corresponding to the larger of the two segmented areas from `seg2`
340-
assert df.bbox.item() == (50, 50, 60, 60)
351+
# corresponding to the appropriate segmentation map to keep from `seg2`
352+
assert df.bbox.item() == exp_bbox
341353
assert df.contour.item().shape == (36, 2)

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ dependencies = [
2424
'pyyaml',
2525
'pooch',
2626
'pyarrow',
27+
'fastparquet',
2728
'torch',
2829
'torchvision',
2930
'huggingface_hub',

0 commit comments

Comments
 (0)