dsa-helpers 1.0.8.dev0__tar.gz → 1.0.8.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. {dsa_helpers-1.0.8.dev0/dsa_helpers.egg-info → dsa_helpers-1.0.8.dev2}/PKG-INFO +1 -1
  2. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/gpd_utils.py +3 -0
  3. dsa_helpers-1.0.8.dev2/dsa_helpers/utils.py +150 -0
  4. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2/dsa_helpers.egg-info}/PKG-INFO +1 -1
  5. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/pyproject.toml +1 -1
  6. dsa_helpers-1.0.8.dev0/dsa_helpers/utils.py +0 -69
  7. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/.gitignore +0 -0
  8. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/.readthedocs.yaml +0 -0
  9. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/LICENSE +0 -0
  10. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/README.md +0 -0
  11. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/app.py +0 -0
  12. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/docs/requirements.txt +0 -0
  13. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/docs/source/conf.py +0 -0
  14. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/docs/source/index.rst +0 -0
  15. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/__init__.py +0 -0
  16. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/cli_utils.py +0 -0
  17. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/dash/__init__.py +0 -0
  18. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/dash/dash_paperdragon_utils.py +0 -0
  19. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/dash/header.py +0 -0
  20. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/dash/header_callbacks.py +0 -0
  21. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/girder_utils.py +0 -0
  22. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/image_utils.py +0 -0
  23. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/imread.py +0 -0
  24. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/imwrite.py +0 -0
  25. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/__init__.py +0 -0
  26. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/callbacks.py +0 -0
  27. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/datasets/SegFormerSegmentationDataset.py +0 -0
  28. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/datasets/__init__.py +0 -0
  29. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/datasets/utils.py +0 -0
  30. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/evaluate.py +0 -0
  31. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/metrics.py +0 -0
  32. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/object_detection/__init__.py +0 -0
  33. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/object_detection/get_pearce_roi_images.py +0 -0
  34. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/object_detection/tile_image.py +0 -0
  35. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/object_detection/utils.py +0 -0
  36. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/segformer_semantic_segmentation/__init__.py +0 -0
  37. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/segformer_semantic_segmentation/inference.py +0 -0
  38. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/transforms/__init__.py +0 -0
  39. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/ml/transforms/segformer_transforms.py +0 -0
  40. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/mongo_utils.py +0 -0
  41. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/tile_utils.py +0 -0
  42. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers/tiling.py +0 -0
  43. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers.egg-info/SOURCES.txt +0 -0
  44. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers.egg-info/dependency_links.txt +0 -0
  45. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers.egg-info/requires.txt +0 -0
  46. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/dsa_helpers.egg-info/top_level.txt +0 -0
  47. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/setup.cfg +0 -0
  48. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/tests/app/Dockerfile +0 -0
  49. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/tests/app/app.py +0 -0
  50. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/tests/docker-compose.yaml +0 -0
  51. {dsa_helpers-1.0.8.dev0 → dsa_helpers-1.0.8.dev2}/tests/test.ipynb +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dsa_helpers
3
- Version: 1.0.8.dev0
3
+ Version: 1.0.8.dev2
4
4
  Summary: Utility functions for working with the DSA girder client.
5
5
  Author-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
6
6
  Maintainer-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
@@ -169,4 +169,7 @@ def remove_gdf_overlaps(
169
169
  # This could have created multiple polygons, explode them.
170
170
  gdf = gdf.explode(index_parts=False).reset_index(drop=True)
171
171
 
172
+ # Remove any rows whose geometry is empty.
173
+ gdf = gdf[gdf.geometry.notna()].reset_index(drop=True)
174
+
172
175
  return gdf
@@ -0,0 +1,150 @@
1
+ """Utility functions for DSA Helpers.
2
+
3
+ This module provides various miscellaneous utility functions that are
4
+ not grouped into their own modules.
5
+ """
6
+
7
+ from shapely.geometry import Polygon
8
+ import numpy as np
9
+ import cv2 as cv
10
+
11
+
12
+ def remove_small_holes(
13
+ polygon: Polygon, hole_area_threshold: float
14
+ ) -> Polygon:
15
+ """Remove small holes from a shapely polygon.
16
+
17
+ Args:
18
+ polygon (shapely.geometry.Polygon): Polygon to remove holes
19
+ from.
20
+ hole_area_threshold (float): Minimum area of a hole to keep it.
21
+
22
+ Returns:
23
+ shapely.geometry.Polygon: Polygon with small holes removed.
24
+
25
+ """
26
+ if not polygon.interiors: # if there are no holes, return as is
27
+ return polygon
28
+
29
+ # Filter out small holes
30
+ new_holes = [
31
+ hole
32
+ for hole in polygon.interiors
33
+ if Polygon(hole).area > hole_area_threshold
34
+ ]
35
+
36
+ # Create a new polygon with only large holes
37
+ return Polygon(polygon.exterior, new_holes)
38
+
39
+
40
+ def convert_to_json_serializable(
41
+ data: int | float | str | list | dict,
42
+ ) -> int | float | str | list | dict:
43
+ """Convert a list, integer, float, or dictionary into a JSON
44
+ serializable version of the object. Uses recursion to make sure the
45
+ entire input data structure is converted to a JSON serializable
46
+ version.
47
+
48
+ Args:
49
+ data (int | float | str | list | dict): Data to convert to
50
+ JSON serializable.
51
+
52
+ Returns:
53
+ int | float | str | list | dict: JSON serializable version of
54
+ the input data.
55
+
56
+ """
57
+ if isinstance(data, np.ndarray):
58
+ return data.tolist()
59
+ elif isinstance(data, np.integer):
60
+ return int(data)
61
+ elif isinstance(data, np.floating):
62
+ return float(data)
63
+ elif isinstance(data, dict):
64
+ return {
65
+ key: convert_to_json_serializable(value)
66
+ for key, value in data.items()
67
+ }
68
+ elif isinstance(data, list):
69
+ return [convert_to_json_serializable(item) for item in data]
70
+ return data
71
+
72
+
73
+ def contours_to_polygons(binary_image: np.ndarray) -> list[Polygon]:
74
+ """Convert a binary image to a list of polygons.
75
+
76
+ Args:
77
+ binary_image (numpy.ndarray): Binary image.
78
+
79
+ Returns:
80
+ list[shapely.geometry.Polygon]: List of polygons.
81
+
82
+ """
83
+ contours, hierarchy = cv.findContours(
84
+ binary_image, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE
85
+ )
86
+ hierarchy = hierarchy[0] # shape: (n_contours, 4)
87
+
88
+ def contour_to_coords(contour):
89
+ return [(int(p[0][0]), int(p[0][1])) for p in contour]
90
+
91
+ polygons = []
92
+ used = set()
93
+
94
+ for i, (next_idx, prev_idx, child_idx, parent_idx) in enumerate(hierarchy):
95
+ if parent_idx != -1:
96
+ # Skip child contours for now (they'll be added as holes)
97
+ continue
98
+
99
+ # Outer contour
100
+ exterior = contour_to_coords(contours[i])
101
+
102
+ if len(exterior) < 4:
103
+ # Skip contours that are too small
104
+ used.add(i)
105
+ continue
106
+
107
+ holes = []
108
+
109
+ # Look for children (holes)
110
+ child = hierarchy[i][2]
111
+ while child != -1:
112
+ hole_coords = contour_to_coords(contours[child])
113
+ holes.append(hole_coords)
114
+ used.add(child)
115
+ # Check for nested children (e.g. box in a hole in a box)
116
+ grandchild = hierarchy[child][2]
117
+ if grandchild != -1:
118
+ # Treat grandchild as a new polygon later
119
+ pass
120
+ child = hierarchy[child][0] # next sibling hole
121
+
122
+ used.add(i)
123
+ polygon = Polygon(exterior, holes)
124
+
125
+ if not polygon.is_valid:
126
+ # Attempt to fix the polygon
127
+ polygon = polygon.buffer(0)
128
+
129
+ if polygon.is_valid:
130
+ polygons.append(polygon)
131
+
132
+ # Add any unused outer contours (e.g. nested objects)
133
+ for i in range(len(contours)):
134
+ if i not in used:
135
+ coords = contour_to_coords(contours[i])
136
+
137
+ if len(coords) < 4:
138
+ # Skip contours that are too small
139
+ continue
140
+
141
+ poly = Polygon(coords)
142
+
143
+ if not poly.is_valid:
144
+ # Attempt to fix the polygon
145
+ poly = poly.buffer(0)
146
+
147
+ if poly.is_valid:
148
+ polygons.append(poly)
149
+
150
+ return polygons
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dsa_helpers
3
- Version: 1.0.8.dev0
3
+ Version: 1.0.8.dev2
4
4
  Summary: Utility functions for working with the DSA girder client.
5
5
  Author-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
6
6
  Maintainer-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
@@ -35,7 +35,7 @@ classifiers = [
35
35
  "License :: OSI Approved :: MIT License",
36
36
  ]
37
37
  keywords = ["dsa", "girder", "girder_client"]
38
- version = "v1.0.8.dev0"
38
+ version = "v1.0.8.dev2"
39
39
 
40
40
  [project.urls]
41
41
  Repository = "https://github.com/Gutman-Lab/dsa-python-utils"
@@ -1,69 +0,0 @@
1
- """Utility functions for DSA Helpers.
2
-
3
- This module provides various miscellaneous utility functions that are
4
- not grouped into their own modules.
5
- """
6
-
7
- from shapely.geometry import Polygon
8
- import numpy as np
9
-
10
-
11
- def remove_small_holes(
12
- polygon: Polygon, hole_area_threshold: float
13
- ) -> Polygon:
14
- """Remove small holes from a shapely polygon.
15
-
16
- Args:
17
- polygon (shapely.geometry.Polygon): Polygon to remove holes
18
- from.
19
- hole_area_threshold (float): Minimum area of a hole to keep it.
20
-
21
- Returns:
22
- shapely.geometry.Polygon: Polygon with small holes removed.
23
-
24
- """
25
- if not polygon.interiors: # if there are no holes, return as is
26
- return polygon
27
-
28
- # Filter out small holes
29
- new_holes = [
30
- hole
31
- for hole in polygon.interiors
32
- if Polygon(hole).area > hole_area_threshold
33
- ]
34
-
35
- # Create a new polygon with only large holes
36
- return Polygon(polygon.exterior, new_holes)
37
-
38
-
39
- def convert_to_json_serializable(
40
- data: int | float | str | list | dict,
41
- ) -> int | float | str | list | dict:
42
- """Convert a list, integer, float, or dictionary into a JSON
43
- serializable version of the object. Uses recursion to make sure the
44
- entire input data structure is converted to a JSON serializable
45
- version.
46
-
47
- Args:
48
- data (int | float | str | list | dict): Data to convert to
49
- JSON serializable.
50
-
51
- Returns:
52
- int | float | str | list | dict: JSON serializable version of
53
- the input data.
54
-
55
- """
56
- if isinstance(data, np.ndarray):
57
- return data.tolist()
58
- elif isinstance(data, np.integer):
59
- return int(data)
60
- elif isinstance(data, np.floating):
61
- return float(data)
62
- elif isinstance(data, dict):
63
- return {
64
- key: convert_to_json_serializable(value)
65
- for key, value in data.items()
66
- }
67
- elif isinstance(data, list):
68
- return [convert_to_json_serializable(item) for item in data]
69
- return data