-
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
base: devel
Are you sure you want to change the base?
Changes from 9 commits
3ca94fa
6659e11
cd48fac
7741f5e
edaa79e
373a05c
4a4a10b
c76580d
9fe0a64
27f4165
56d003b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,37 @@ | |
| from ..log import LOG as log | ||
|
|
||
|
|
||
| def filter_options(filter_method, filter_radius, do_3d=False): | ||
| """Build the ImageJ filter command and options strings.""" | ||
|
|
||
| if do_3d: | ||
| filter_name = filter_method + " 3D..." | ||
| else: | ||
| filter_name = filter_method + "..." | ||
|
|
||
| options = ( | ||
| "sigma=" | ||
| if filter_method == "Gaussian Blur" | ||
| else "radius=" + str(filter_radius) + " stack" | ||
| ) | ||
|
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. This is much harder to read compared to this (which is 3 lines vs. 5 lines): options = "sigma"
if filter_method != "Gaussian Blur":
options = "radius=" + str(filter_radius) + " stack" |
||
|
|
||
| return filter_name, options | ||
|
|
||
|
|
||
| def threshold_options(threshold_method, do_3d=True): | ||
| """Build the ImageJ threshold option 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 +78,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 +88,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=False, | ||
| do_3d=False, | ||
| ): | ||
| """Perform background subtraction using a rolling ball method. | ||
|
|
||
| Parameters | ||
|
|
@@ -75,6 +104,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 : 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 +120,42 @@ 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=disable, | ||
| 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=False, | ||
| do_3d=False, | ||
| ): | ||
| """Generate the options 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: | ||
| 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. | ||
|
|
||
|
|
@@ -117,18 +178,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) | ||
|
|
||
| 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=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=" | ||
|
|
||
|
|
||
| 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" |
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) ... ⏳