-
Notifications
You must be signed in to change notification settings - Fork 3
Additional options for rolling ball background subtraction #143
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
Open
lguerard
wants to merge
11
commits into
imcf:devel
Choose a base branch
from
lguerard:rollingball_options
base: devel
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
3ca94fa
feat: Enhance rolling ball background subtraction with additional opt…
lguerard 6659e11
fix: Correct spelling of 'Subtract Background' in rolling ball backgr…
lguerard cd48fac
refactor: Extract rolling ball options into a separate function for c…
lguerard 7741f5e
Merge branch 'devel' into pr/143
ehrenfeu edaa79e
Update docstring
ehrenfeu 373a05c
Add test for the rolling_ball_options function
ehrenfeu 4a4a10b
Add pure helpers for processing options
c76580d
Test processing option strings
9fe0a64
Add processing helper coverage
27f4165
Enhance docstrings for filter and threshold options functions
56d003b
Fix parameter name for disable smoothing in rolling ball functions an…
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,66 @@ | |
| from ..log import LOG as log | ||
|
|
||
|
|
||
| def filter_options(filter_method, filter_radius, do_3d=False): | ||
| """Build the ImageJ filter command and options strings. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| filter_method : str | ||
| Name of the filter method to use | ||
| filter_radius : int | ||
| Radius of the filter to use | ||
| do_3d : bool, optional | ||
| If set to True, will do a 3D filtering, by default False | ||
|
|
||
| Returns | ||
| ------- | ||
| tuple[str, str] | ||
| The filter name and options strings | ||
| """ | ||
|
|
||
| if do_3d: | ||
| filter_name = filter_method + " 3D..." | ||
| else: | ||
| filter_name = filter_method + "..." | ||
|
|
||
| if filter_method == "Gaussian Blur": | ||
| options = "sigma=" + str(filter_radius) + " stack" | ||
| else: | ||
| options = "radius=" + str(filter_radius) + " stack" | ||
|
|
||
| return filter_name, options | ||
|
|
||
|
|
||
| def threshold_options(threshold_method, do_3d=True): | ||
| """Build the ImageJ threshold option strings. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| threshold_method : str | ||
| Name of the threshold method to use | ||
| do_3d : bool, optional | ||
| If set to True, the automatic threshold will be done on a 3D stack, | ||
| by default True | ||
|
|
||
| Returns | ||
| ------- | ||
| tuple[str, str] | ||
| The auto threshold options and the convert to binary options strings | ||
|
|
||
| """ | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Docstring is missing parameters description (simply copy the relevant parts from the Actually the ruff linter should complain about this but we need to wait until ruff-pr-21076 has been merged (cf. #148) ... ⏳ |
||
| auto_threshold_options = ( | ||
| threshold_method + " " + "dark" + " " + "stack" if do_3d else "" | ||
| ) | ||
|
|
||
| convert_to_binary_options = ( | ||
| "method=" + threshold_method + " " + "background=Dark" + " " + "black" | ||
| ) | ||
|
|
||
| return auto_threshold_options, convert_to_binary_options | ||
|
|
||
|
|
||
| def apply_filter(imp, filter_method, filter_radius, do_3d=False): | ||
| """Make a specific filter followed by a threshold method of choice. | ||
|
|
||
|
|
@@ -47,16 +107,7 @@ def apply_filter(imp, filter_method, filter_radius, do_3d=False): | |
| "filter_method must be one of: Median, Mean, Gaussian Blur, Minimum, Maximum" | ||
| ) | ||
|
|
||
| if do_3d: | ||
| filter = filter_method + " 3D..." | ||
| else: | ||
| filter = filter_method + "..." | ||
|
|
||
| options = ( | ||
| "sigma=" | ||
| if filter_method == "Gaussian Blur" | ||
| else "radius=" + str(filter_radius) + " stack" | ||
| ) | ||
| filter, options = filter_options(filter_method, filter_radius, do_3d=do_3d) | ||
|
|
||
| log.debug("Filter: <%s> with options <%s>" % (filter, options)) | ||
|
|
||
|
|
@@ -66,7 +117,14 @@ def apply_filter(imp, filter_method, filter_radius, do_3d=False): | |
| return imageplus | ||
|
|
||
|
|
||
| def apply_rollingball_bg_subtraction(imp, rolling_ball_radius, do_3d=False): | ||
| def apply_rollingball_bg_subtraction( | ||
| imp, | ||
| rolling_ball_radius, | ||
| light_background=False, | ||
| sliding=False, | ||
| disable_smoothing=False, | ||
| do_3d=False, | ||
| ): | ||
| """Perform background subtraction using a rolling ball method. | ||
|
|
||
| Parameters | ||
|
|
@@ -75,6 +133,12 @@ def apply_rollingball_bg_subtraction(imp, rolling_ball_radius, do_3d=False): | |
| Input ImagePlus to filter and threshold | ||
| rolling_ball_radius : int | ||
| Radius of the rolling ball filter to use | ||
| light_background : bool, optional | ||
| If set to True, will treat the background as light, by default False | ||
| sliding : bool, optional | ||
| If set to True, will do a sliding window approach, by default False | ||
| disable_smoothing : bool, optional | ||
| If set to True, will disable the smoothing, by default False | ||
| do_3d : bool, optional | ||
| If set to True, will do a 3D filtering, by default False | ||
|
|
||
|
|
@@ -85,16 +149,62 @@ def apply_rollingball_bg_subtraction(imp, rolling_ball_radius, do_3d=False): | |
| """ | ||
| log.info("Applying rolling ball with radius %d" % rolling_ball_radius) | ||
|
|
||
| options = "rolling=" + str(rolling_ball_radius) + " stack" if do_3d else "" | ||
| options = rolling_ball_options( | ||
| rolling_ball_radius, | ||
| light_background=light_background, | ||
| sliding=sliding, | ||
| disable_smoothing=disable_smoothing, | ||
| do_3d=do_3d, | ||
| ) | ||
|
|
||
| log.debug("Background subtraction options: %s" % options) | ||
|
|
||
| imageplus = imp.duplicate() | ||
| IJ.run(imageplus, "Substract Background...", options) | ||
| IJ.run(imageplus, "Subtract Background...", options) | ||
|
|
||
| return imageplus | ||
|
|
||
|
|
||
| def rolling_ball_options( | ||
| rolling_ball_radius, | ||
| light_background=False, | ||
| sliding=False, | ||
| disable_smoothing=False, | ||
| do_3d=False, | ||
| ): | ||
| """Generate the options for the "Subtract Background..." macro command. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| rolling_ball_radius : int | ||
| Radius of the rolling ball filter to use | ||
| light_background : bool, optional | ||
| If set to True, will treat the background as light, by default False | ||
| sliding : bool, optional | ||
| If set to True, will do a sliding window approach, by default False | ||
| disable_smoothing : bool, optional | ||
| If set to True, will disable the smoothing, by default False | ||
| do_3d : bool, optional | ||
| If set to True, will do a 3D filtering, by default False | ||
|
|
||
| Returns | ||
| ------- | ||
| str | ||
| The options string for the "Subtract Background..." macro command | ||
|
|
||
| """ | ||
| parts = ["rolling=" + str(rolling_ball_radius)] | ||
| if light_background: | ||
| parts.append("light") | ||
| if sliding: | ||
| parts.append("sliding") | ||
| if disable_smoothing: | ||
| parts.append("disable") | ||
| if do_3d: | ||
| parts.append("stack") | ||
| return " ".join(parts) | ||
|
|
||
|
|
||
| def apply_threshold(imp, threshold_method, do_3d=True): | ||
| """Apply a threshold method to the input ImagePlus. | ||
|
|
||
|
|
@@ -105,7 +215,8 @@ def apply_threshold(imp, threshold_method, do_3d=True): | |
| threshold_method : str | ||
| Name of the threshold method to use | ||
| do_3d : bool, optional | ||
| If set to True, the automatic threshold will be done on a 3D stack, by default True | ||
| If set to True, the automatic threshold will be done on a 3D stack, | ||
| by default True | ||
|
|
||
| Returns | ||
| ------- | ||
|
|
@@ -117,18 +228,14 @@ def apply_threshold(imp, threshold_method, do_3d=True): | |
|
|
||
| imageplus = imp.duplicate() | ||
|
|
||
| auto_threshold_options = ( | ||
| threshold_method + " " + "dark" + " " + "stack" if do_3d else "" | ||
| auto_threshold_options, convert_to_binary_options = threshold_options( | ||
| threshold_method, do_3d=do_3d | ||
| ) | ||
|
|
||
| log.debug("Auto threshold options: %s" % auto_threshold_options) | ||
|
|
||
| IJ.setAutoThreshold(imageplus, auto_threshold_options) | ||
|
|
||
| convert_to_binary_options = ( | ||
| "method=" + threshold_method + " " + "background=Dark" + " " + "black" | ||
| ) | ||
|
|
||
| log.debug("Convert to binary options: %s" % convert_to_binary_options) | ||
|
|
||
| IJ.run(imageplus, "Convert to Mask", convert_to_binary_options) | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| """Tests for the imcflibs.imagej.processing module.""" | ||
|
|
||
| from imcflibs.imagej.processing import ( | ||
| filter_options, | ||
| rolling_ball_options, | ||
| threshold_options, | ||
| ) | ||
|
|
||
|
|
||
| def test_rolling_ball_options(): | ||
| """Test the rolling_ball_options function.""" | ||
|
|
||
| options = rolling_ball_options(42.23) | ||
| assert options == "rolling=42.23" | ||
|
|
||
|
|
||
| def test_rolling_ball_options_with_flags(): | ||
| """Test `rolling_ball_options()` string concatenation with all flags.""" | ||
|
|
||
| options = rolling_ball_options( | ||
| 12, | ||
| light_background=True, | ||
| sliding=True, | ||
| disable_smoothing=True, | ||
| do_3d=True, | ||
| ) | ||
| assert options == "rolling=12 light sliding disable stack" | ||
|
|
||
|
|
||
| def test_filter_options(): | ||
| """Test `filter_options()` string concatenation.""" | ||
|
|
||
| command, options = filter_options("Mean", 5, do_3d=True) | ||
| assert command == "Mean 3D..." | ||
| assert options == "radius=5 stack" | ||
|
|
||
|
|
||
| def test_filter_options_gaussian_blur(): | ||
| """Test `filter_options()` with the Gaussian Blur branch.""" | ||
|
|
||
| command, options = filter_options("Gaussian Blur", 5) | ||
| assert command == "Gaussian Blur..." | ||
| assert options == "sigma=5 stack" | ||
|
|
||
|
|
||
| def test_threshold_options(): | ||
| """Test `threshold_options()` string concatenation.""" | ||
|
|
||
| auto_threshold, convert_to_binary = threshold_options("Otsu", do_3d=True) | ||
| assert auto_threshold == "Otsu dark stack" | ||
| assert convert_to_binary == "method=Otsu background=Dark black" | ||
|
|
||
|
|
||
| def test_threshold_options_without_stack(): | ||
| """Test `threshold_options()` when 3D stacking is disabled.""" | ||
|
|
||
| auto_threshold, convert_to_binary = threshold_options("Otsu", do_3d=False) | ||
| assert auto_threshold == "" | ||
| assert convert_to_binary == "method=Otsu background=Dark black" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Docstring is missing parameters description (simply copy the relevant parts from the
apply_filter()function).Actually the ruff linter should complain about this but we need to wait until ruff-pr-21076 has been merged (cf. #148) ... ⏳