-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Replace square
, rectangle
, cube
with footprint_rectangular
#7566
Replace square
, rectangle
, cube
with footprint_rectangular
#7566
Conversation
I'm thinking how to best go about updating the test suite considering review experience and long-term maintenance. The test's are somewhat strewn about over at least 2 files. So my idea is to consolidate them in a new |
Have "nd extensions" been using in your "actual work"? I have mostly stayed on "2D" + broadcasting. I find "square rectangle and cube" relatable, and "footprint_rectangle" just too abstract.... |
We are planning on renaming all structuring elements to |
My personal gut feeling is that But thinking about it more, I'd actually find Meta: I think the original aim of the discussion was to make our API clearer and reduce the maintenance aspect of it. While working on this, I discovered that the "rectangular" approach can actually be covered by one ND-enabled algorithm. I feel like that one generalized version is actually simpler to maintain long-term. @hmaarrfk, what do you think? |
The new name is not specific to a number of dimensions and I think communicates the core concept of the footprint class clearly.
square
, rectangle
, cube
with footprint_rectangle
square
, rectangle
, cube
with footprint_rectangular
@lagru all green with me. |
pre-commit.ci autofix |
While it may be more performant, I'm very unsure if enabling decomposition by default is the better option. The returned decomposed format is not as straightforward to understand. I also don't like that this function may return different types. Maybe we want a second function that decomposes footprints by default. E.g. `footprint_rectangular` and additionally `decomposed_footprint_rectangular`?
with `footprint_rectangular`.
of `square`, `rectangle` and `cube`.
if decomposition == "sequence" and has_even_width: | ||
warnings.warn( | ||
"decomposition='sequence' is only supported for uneven footprints, " | ||
"falling back to decomposition='separable'", | ||
stacklevel=2, | ||
) | ||
decomposition = "sequence_fallback" |
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.
Note this new warning which is raised when a sequence-decomposition is requested for footprints that have a dimension with an uneven length. This doesn't change previous behavior but makes it more visible to users what's going on.
This LGTM. I think the name |
Hmm, I'm rather fond of "rectangular" which works for any number of dimensions, e.g. rectangular cuboid, square, hyper-cube. Along the same line of thought, I'd suggest I think we only support 2D for diamond, octagon, etc. So going with a more precise name rather than a property makes sense here in my book. What do you think? |
I think that's the problem: rectangular means rectangular something, and the name doesn't say what. We could also consider |
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 generalization makes sense to me. Nice work, @lagru!
The length of the footprint in each dimension. The length of the | ||
sequence determines the number of dimensions of the footprint. |
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 length of the footprint in each dimension. The length of the | |
sequence determines the number of dimensions of the footprint. | |
The size of the footprint in each dimension. The length of `shape` | |
determines the number of dimensions of the footprint. |
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.
No big deal, I just find it 'visually' confusing to read/see "The length ..." and then again, next sentence, "The length ..." when really they don't refer to the same thing at all.
footprints is returned. Applying this series of smaller footprints will | ||
give an identical result to a single, larger footprint, but often with |
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.
footprints is returned. Applying this series of smaller footprints will | |
give an identical result to a single, larger footprint, but often with | |
footprints is returned. Applying this sequence of smaller footprints will | |
give a result identical to applying a single, larger, equivalent footprint, but often with |
dtype : data-type, optional | ||
The data type of the footprint. | ||
decomposition : {None, 'separable', 'sequence'}, optional | ||
If None, a single array is returned. For 'sequence', a tuple of smaller |
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.
If None, a single array is returned. For 'sequence', a tuple of smaller | |
If None, a single array is returned. With 'sequence', a tuple of smaller |
Returns | ||
------- | ||
footprint : array or tuple[tuple[ndarray, int], ...] |
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.
footprint : array or tuple[tuple[ndarray, int], ...] | |
footprint : array or tuple[tuple[array, int], ...] |
or ndarray or tuple[tuple[array, int], ...]
?
Returns | ||
------- | ||
footprint : array or tuple[tuple[ndarray, int], ...] | ||
A footprint consisting only of ones, i.e. every pixel belongs to the |
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 footprint consisting only of ones, i.e. every pixel belongs to the | |
A footprint consisting only of ones, i.e., every pixel belongs to the |
A footprint consisting only of ones, i.e. every pixel belongs to the | ||
neighborhood. When `decomposition` is None, this is just an array. | ||
Otherwise, this will be a tuple whose length is equal to the number of | ||
unique structuring elements to apply (see Examples for more detail). |
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.
unique structuring elements to apply (see Examples for more detail). | |
unique footprints to apply (see Examples for more detail). |
Or the fact that we speak of 'structuring elements' and 'footprints' interchangeably should be introduced earlier/clearly.
Thanks @mkcor! Do you have a preference or thoughts with regard to --
@stefanv, I can follow that argument. It may be somewhat alleviated by the fact, that I still feel like |
@lagru oh sorry, I'm seeing this conversation only now! I just checked and the second meaning of adjective 'rectangular' is: placed or having parts placed at right angles (so the 'cuboid' case would be covered, in the broad sense). My personal preference would go to |
drive by peanut gallery comment (came here from the Scientific Python discord that solicited input here, because who doesn't love a good bike shed?):
In one interpretation, it does: rectangular footprint, where a user can assume you're using a
I really don't have a dog in this race, or a say, but I would leave the "legacy" specialized names, or at least their
This way current users of those functions can continue to use them and think about their problems in the same way, only having to adjust to the |
That's a good point I hadn't really considered as a deciding factor. Thanks for pointing it out @ivanov. 🫶 Then let's go with
We explicitly chose to use an API that works for all shapes consistently, e.g., rectangles or ellipses that can't be represented with the API that you suggest. Another nice perk is, that it's consistent with NumPy's |
@mkcor, |
I'll leave pressing the merge button to one of you, in case we have a consensus. 😉 |
Thanks all for your inputs! |
By the way, DIPlib uses "rectangular". |
Description
We have a rework of our footprint generating function on our skimage2 agenda. This WIP starts that work by combining "rectangular" footprint generators (
square
,rectangle
,cube
) into a singleskimage.morphology.footprint_rectangular
with ND support.This is also an opportunity to change to
decomposition="sequence"
as the default as suggested in the agenda. Though, I'm not sure if we really want to do this. It's arguably a more unexpected form to represent the footprint for the sake of performance. Usually, we decide that trade-off in favor of simpler behavior.I plan to do the same for "elliptical" footprint generators in a separate PR to keep reviewing reasonable.
I'm also playing around with a small wrapper class to help with the more complicated representation of decomposed footprints. I might move that into another PR depending on how this approach turns out.
Checklist
./doc/examples
for new featuresRelease note
For maintainers and optionally contributors, please refer to the instructions on how to document this PR for the release notes.