-
Notifications
You must be signed in to change notification settings - Fork 26
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
Generalized masking #1092
Generalized masking #1092
Conversation
Check out this pull request on See visual diffs & provide feedback on Jupyter Notebooks. Powered by ReviewNB |
I still need to write the notebook tests, but would love any preliminary input on the masking functionalities you have helped write or seen lab members use. @alex-l-kong @srivarra |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems EzSeg already has some of this functionality in one form or another. We could figure out how to use it here, or we could make changes in ezseg
to account for this workflow. Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srivarra pretty much covered it.
Updated to use the already built ezseg functions. Decided to forego the notebook tests, since it's just a utility notebook with only top-level function calls that are already tested. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few comments about what should be visible or not, but otherwise looks great.
src/ark/utils/masking_utils.py
Outdated
return cell_mask | ||
|
||
|
||
def generate_cell_masks(seg_dir, mask_dir, cell_table, cell_types, cluster_col, mask_name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add a few defaults here:
cell_types
: default to None, in which case include all cell types increate_cell_masks
cluster_col
: should be ark.settings.cell_type. In that way you may not have to explicitly specify it in the notebook.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cluster_col
default is a great idea! For cell_types
, it wouldn't really make sense to mask all cell types in the image (it would just be a blurred version of the segmentation masks), so forcing the user to specify a list is robably the way to go.
@@ -0,0 +1,155 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally I prefer leaving sigma
, min_mask_size
, and max_hole_size
as hidden default arguments inside generate_signal_masks
. If you expect the user will change these, then I'd specify them as customizable variables in the cell above.
Reply via ReviewNB
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The defaults set here are currently based only on what Noah used for the TONIC data, so I don't want users to think the masks generated with these are the only output possible. I'll add them to the description and set them in the cell above.
@@ -0,0 +1,155 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Piggybacking off of a comment from ark.utils.masking_utils.py
, I'd prefer leaving cluster_col
as a hidden default argument in generate_cell_masks
.
Reply via ReviewNB
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the spatial scripts, this cell masking would often be used for a more broad cell type grouping specified by the user previously, so rarely would we use the 'cell_meta_cluster' column. It's just set here as a example!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good, just a couple of clarifications.
@@ -154,7 +154,9 @@ def _create_object_mask( | |||
misc_utils.verify_in_list(object_shape_type=[object_shape_type], object_shape_options=["blob", "projection"]) | |||
|
|||
# Copy the input image, and get its shape | |||
img2mask: np.ndarray = input_image.copy().to_numpy() | |||
img2mask: np.ndarray = input_image.copy() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In what instance would this not be a numpy array? If it's an xarray, all normal numpy ops and functions which make use of numpy ops will work, so we wouldn't need to convert it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where I'm implementing it in masking_utils, img2mask
is already an np.array, so I get an AttributeError: 'numpy.ndarray' object has no attribute 'to_numpy'.
"composite_directory": composite_directory, | ||
"composite_name": composite_name, | ||
} | ||
log_creator(variables_to_log, log_dir, f"{composite_name}_composite_log.txt") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we not want to return the composite images here as well? For example what if the user passes in a path for log_dir
but there isn't a path for the composite_directory
. It wouldn't return the dictionary nor save any of the composite files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ezseg functions only save the composites, they don't return them so I would have to change the ezseg notebook to handle a return (not a big deal, but unnecessary when it's not even used). Since the only case we would need the composites returned is for the internal function call inside generate_signal_masks(), I didn't think it was needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
If you haven't already, please read through our contributing guidelines before opening your PR
What is the purpose of this PR?
Closes #1091.
How did you implement your changes
Add two user functions,
generate_signal_masks()
andgenerate_cell_masks()
for either signal based masking or cell based masking.Remaining issues