Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement older monocot pipeline #54

Merged
merged 50 commits into from
Mar 11, 2024
Merged
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
3e841ec
Fix docstring and `get_network_distribution_ratio` arguments
eberrigan Aug 17, 2023
92dae9e
Add `join_pts` and `get_count` functions
eberrigan Aug 20, 2023
9325a1b
Refactor `get_network_distribution`
eberrigan Aug 21, 2023
1621efa
Generalize functions for concatenating and joining points
eberrigan Aug 21, 2023
cb0f13b
Refactor scanline function
eberrigan Aug 21, 2023
e23af0f
Make `OlderMonocotPipeline`
eberrigan Aug 21, 2023
4bc568f
Refactor tests and fix arguments
eberrigan Aug 21, 2023
ff1fb10
Refactor `get_network_length` to take arbitrary number of lengths
eberrigan Aug 23, 2023
57b8fed
Refactor `get_all_pts_array` to simplify
eberrigan Aug 23, 2023
25391b4
Refactor `Series` class to take a arbitrary number of labels
eberrigan Aug 23, 2023
dfabf07
Add 10 DO rice fixture
eberrigan Aug 23, 2023
890df7f
Test refactored functions
eberrigan Aug 23, 2023
4843f08
Add 10 DO rice fixture
eberrigan Aug 23, 2023
0c42ecb
Add test for `OlderMonocot_pipeline`
eberrigan Aug 27, 2023
f33f0e0
Modify `get_grav_index` to take float and array inputs
eberrigan Aug 31, 2023
797561b
Fix docstring in `Series` class
eberrigan Aug 31, 2023
aa59e2b
Test `OlderMonocotPipeline` and `get_grav_index`
eberrigan Aug 31, 2023
bd2621b
Lint
eberrigan Aug 31, 2023
045a7b4
Add folder of 10 do rice test data and test with `find_all_series`
eberrigan Sep 1, 2023
2364b89
Refactor series class and related functions to include crown labels
eberrigan Feb 20, 2024
a92be32
Refactor tests and fixtures
eberrigan Feb 20, 2024
1fceb01
Get rid of uncessary monocots flag
eberrigan Feb 21, 2024
1ab5a39
Refactor tips and bases
eberrigan Feb 21, 2024
11df884
Refactor tips and bases tests
eberrigan Feb 21, 2024
606af51
Merge main with `older_monocot_pipeline` branch
eberrigan Feb 21, 2024
3d1109f
Add standalone get root angle function
eberrigan Feb 27, 2024
57cfbd1
Fix typing
eberrigan Feb 27, 2024
c063a9f
Add checks to convex hull function
eberrigan Feb 27, 2024
29cdb7a
Get rid of obsolete function
eberrigan Feb 27, 2024
113ee3e
Fix network distribution
eberrigan Feb 27, 2024
534d9e6
Add points related functions
eberrigan Feb 27, 2024
b372567
Rename test data
eberrigan Feb 27, 2024
93cfe87
Test new angle functions
eberrigan Feb 27, 2024
7464680
Test new convex hull functions
eberrigan Feb 27, 2024
dd06872
Test new points functions
eberrigan Feb 27, 2024
2279ac0
Rename test data
eberrigan Feb 27, 2024
655d9cc
Fix tests
eberrigan Feb 27, 2024
ef271da
Match shapes
eberrigan Feb 27, 2024
a9054e3
Update trait pipelines
eberrigan Feb 28, 2024
d175680
Test trait pipelines
eberrigan Mar 1, 2024
5efb4fb
Test trait pipelines
eberrigan Mar 1, 2024
2416fd8
Update version
eberrigan Mar 1, 2024
9838314
Resolve conflicts
eberrigan Mar 1, 2024
0c4b4df
Resolve conflicts
eberrigan Mar 1, 2024
1e692b5
resolve
eberrigan Mar 1, 2024
10eb050
Merge branch 'main' into elizabeth/older_monocot_pipeline
eberrigan Mar 1, 2024
264dcca
Fix tips and bases and tests
eberrigan Mar 2, 2024
e38b289
Remove notebooks
eberrigan Mar 2, 2024
880817d
Reformat
eberrigan Mar 2, 2024
83b6ddd
Lint
eberrigan Mar 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 83 additions & 59 deletions sleap_roots/points.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,13 @@ def join_pts(pts0: np.ndarray, *args: Optional[np.ndarray]) -> List[np.ndarray]:
Returns:
A list of arrays, each having shape `(nodes, 2)`.
"""

# Initialize an empty list to store the points
all_pts = []
# Loop over the input arrays
for pts in [pts0] + list(args):
if pts is None:
continue # Skip None values

if pts0 is None:
raise ValueError("pts0 must not be None.")

# First, process pts0 since it's mandatory.
# If it has shape `(nodes, 2)`, expand dimensions to `(1, nodes, 2)`
if pts0.ndim == 2 and pts0.shape[-1] == 2:
pts0 = pts0[np.newaxis, :, :]

# Validate the shape of pts0
if pts0.ndim != 3 or pts0.shape[-1] != 2:
raise ValueError(
"pts0 should have a shape of `(instances, nodes, 2)` or `(nodes, 2)`."
)

# Add the points from pts0 to the list
all_pts.extend(list(pts0))

# Loop through all the additional arrays of points
for pts in [arg for arg in args if arg is not None]:
# If an array has shape `(nodes, 2)`, expand dimensions to `(1, nodes, 2)`
if pts.ndim == 2 and pts.shape[-1] == 2:
pts = pts[np.newaxis, :, :]
Expand All @@ -69,50 +53,90 @@ def join_pts(pts0: np.ndarray, *args: Optional[np.ndarray]) -> List[np.ndarray]:
return all_pts


def get_all_pts_array(
primary_max_length_pts: np.ndarray, lateral_pts: np.ndarray, monocots: bool = False
) -> np.ndarray:
def get_all_pts_array(pts0: np.ndarray, *args: Optional[np.ndarray]) -> np.ndarray:
"""Get all landmark points within a given frame as a flat array of coordinates.

Args:
primary_max_length_pts: Points of the primary root with maximum length of shape
`(nodes, 2)`.
lateral_pts: Lateral root points of shape `(instances, nodes, 2)`.
monocots: If False (default), returns a combined array of primary and lateral
root points. If True, returns only lateral root points.
pts0: The first array of points. Should have shape `(instances, nodes, 2)`
or `(nodes, 2)`.
*args: Additional optional arrays of points. Each should have shape
`(instances, nodes, 2)` or `(nodes, 2)`.

Returns:
A 2D array of shape (n_points, 2), containing the coordinates of all extracted
points.
"""
# Check if the input arrays have the right number of dimensions
if primary_max_length_pts.ndim != 2 or lateral_pts.ndim != 3:
raise ValueError(
"Input arrays should have the correct number of dimensions:"
"primary_max_length_pts should be 2-dimensional and lateral_pts should be"
"3-dimensional."
)

# Check if the last dimension of the input arrays has size 2
# (representing x and y coordinates)
if primary_max_length_pts.shape[-1] != 2 or lateral_pts.shape[-1] != 2:
raise ValueError(
"The last dimension of the input arrays should have size 2, representing x"
"and y coordinates."
)

# Flatten the arrays to 2D
primary_max_length_pts = primary_max_length_pts.reshape(-1, 2)
lateral_pts = lateral_pts.reshape(-1, 2)

# Combine points
if monocots:
pts_all_array = lateral_pts
else:
# Check if the data types of the arrays are compatible
if primary_max_length_pts.dtype != lateral_pts.dtype:
raise ValueError("Input arrays should have the same data type.")

pts_all_array = np.concatenate((primary_max_length_pts, lateral_pts), axis=0)

return pts_all_array
# Initialize an empty list to store the points
concatenated_pts = []

# Loop over the input arrays
for pts in [pts0] + list(args):
if pts is None:
continue

# Check if the array has the right number of dimensions
if pts.ndim not in [2, 3]:
raise ValueError("Each input array should be 2D or 3D.")

# Check if the last dimension of the array has size 2
# (representing x and y coordinates)
if pts.shape[-1] != 2:
raise ValueError(
"The last dimension should have size 2, representing x and y coordinates."
)

# Flatten the array to 2D and append to list
flat_pts = pts.reshape(-1, 2)
concatenated_pts.append(flat_pts)

# Concatenate all points into a single array
return np.concatenate(concatenated_pts, axis=0)


# def get_all_pts_array(
# primary_max_length_pts: np.ndarray, lateral_pts: np.ndarray, monocots: bool = False
# ) -> np.ndarray:
# """Get all landmark points within a given frame as a flat array of coordinates.

# Args:
# primary_max_length_pts: Points of the primary root with maximum length of shape
# `(nodes, 2)`.
# lateral_pts: Lateral root points of shape `(instances, nodes, 2)`.
# monocots: If False (default), returns a combined array of primary and lateral
# root points. If True, returns only lateral root points.

# Returns:
# A 2D array of shape (n_points, 2), containing the coordinates of all extracted
# points.
# """
# # Check if the input arrays have the right number of dimensions
# if primary_max_length_pts.ndim != 2 or lateral_pts.ndim != 3:
# raise ValueError(
# "Input arrays should have the correct number of dimensions:"
# "primary_max_length_pts should be 2-dimensional and lateral_pts should be"
# "3-dimensional."
# )

# # Check if the last dimension of the input arrays has size 2
# # (representing x and y coordinates)
# if primary_max_length_pts.shape[-1] != 2 or lateral_pts.shape[-1] != 2:
# raise ValueError(
# "The last dimension of the input arrays should have size 2, representing x"
# "and y coordinates."
# )

# # Flatten the arrays to 2D
# primary_max_length_pts = primary_max_length_pts.reshape(-1, 2)
# lateral_pts = lateral_pts.reshape(-1, 2)

# # Combine points
# if monocots:
# pts_all_array = lateral_pts
# else:
# # Check if the data types of the arrays are compatible
# if primary_max_length_pts.dtype != lateral_pts.dtype:
# raise ValueError("Input arrays should have the same data type.")

# pts_all_array = np.concatenate((primary_max_length_pts, lateral_pts), axis=0)

# return pts_all_array
eberrigan marked this conversation as resolved.
Show resolved Hide resolved