Skip to content
Open
Changes from all commits
Commits
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
30 changes: 27 additions & 3 deletions src/imcflibs/imagej/objects3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from de.mpicbg.scf.imgtools.image.create.image import ImageCreationUtilities
from de.mpicbg.scf.imgtools.image.create.labelmap import WatershedLabeling
from ij import IJ
from inra.ijpb.plugins import RemoveBorderLabelsPlugin
from mcib3d.geom import Objects3DPopulation
from mcib3d.image3d import ImageHandler, ImageLabeller
from mcib3d.image3d.processing import MaximaFinder
Expand Down Expand Up @@ -71,7 +72,15 @@ def imgplus_to_population3d(imp):
return Objects3DPopulation(img)


def segment_3d_image(imp, title=None, min_thresh=1, min_vol=None, max_vol=None):
def segment_3d_image(
imp,
title=None,
min_thresh=1,
min_vol=None,
max_vol=None,
remove_touching_borders=False,
remove_touching_borders_z=False,
):
"""Segment a 3D binary image to get a labelled stack.

Parameters
Expand All @@ -90,6 +99,11 @@ def segment_3d_image(imp, title=None, min_thresh=1, min_vol=None, max_vol=None):
max_vol : int, optional
Maximum volume (in voxels) above which objects get filtered.
Defaults to None.
remove_touching_borders : bool, optional
Whether to remove objects that touch the borders in X and Y. Defaults to False.
remove_touching_borders_z : bool, optional
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't have an effect if the non-z parameter is false, as far as I can see.

Either document this or automatically set the non-z to true if the z one is true inside the function. I prefer the latter approach as it seems less surprising.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked this morning and there isn't a function in the 3DImageJSuite that could filter out only objects in Z but not XY.

There is a method in MorpholibJ that I could use though, should I switch to that ?

Copy link
Member

@ehrenfeu ehrenfeu Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me clarify what I'm trying to say.

From reading the docstring, what would an innocent developer think 🤔 will happen with this call?

label_imp = segment_3d_image(binary_imp, remove_touching_borders_z=True)

I believe the expectation is that at least some filtering would be happening, which is not the case given the current code execution path.

I don't know if we need a function that purely filters objects in Z, but if the Z-filtering is requested explicitly (without the XY-filtering), it will be silently ignored. My suggestion is to implicitly enable XY-filtering if Z-filtering is requested and to explain this in the docstring.

Would you think we should rather go for the MorphoLibJ approach that allows to only filter in Z? If you foresee any use-cases for this, it's clearly the better approach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I agree.
At the moment, using only the Image3DSuite, there is no way to only filter in Z. If the user wants to do that, then it has to also filter in XY. I'm not happy about this, users might want to filter objects that aren't fully imaged in a stack and remove objects that are in slide 1 or slide max.

I'll improve this using MorpholibJ

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove this from the milestone then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have implemented it now with MorpholibJ so it can stay with the milestone no? Or maybe I misunderstood...

Copy link
Member

@ehrenfeu ehrenfeu Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I've only read your comment here - haven't checked the actual state of the code. Sorry.

If it's already done, we can keep it in the milestone, sure!

Whether to remove objects that touch the z-axis borders. Defaults to False.


Returns
-------
Expand All @@ -107,14 +121,24 @@ def segment_3d_image(imp, title=None, min_thresh=1, min_vol=None, max_vol=None):
labeler.setMinSizeCalibrated(min_vol, img)
if max_vol:
labeler.setMaxSizeCalibrated(max_vol, img)

# Generate labelled segmentation
seg = labeler.getLabels(img)
seg.setScale(cal.pixelWidth, cal.pixelDepth, cal.getUnits())

seg = RemoveBorderLabelsPlugin().remove(
seg.getImagePlus(),
remove_touching_borders,
remove_touching_borders,
remove_touching_borders,
remove_touching_borders,
remove_touching_borders_z,
remove_touching_borders_z,
)

if title:
seg.setTitle(title)

return seg.getImagePlus()
return seg


def maxima_finder_3d(imp, min_threshold=0, noise=100, rxy=1.5, rz=1.5):
Expand Down
Loading