Skip to content
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

Complete deprecations targeting release 0.20 or 1.0 #6583

Merged
merged 29 commits into from Nov 30, 2022

Conversation

lagru
Copy link
Member

@lagru lagru commented Oct 16, 2022

Description

Complete deprecations that target 0.20. This PR addresses deprecations which were created for 0.19 with target 1.0. At that time a release of 0.20 wasn't planned. See also https://discuss.scientific-python.org/t/559.

Probably easiest to check the changes commit by commit (I tried to keep related changes together / rebased and squashed related changes).

  • Address whole multichannel deprecation & remove deprecate_multichannel_kwarg decorator class
  • *_iter -> *_num_iter in unsupervised_wiener
  • deprecate height and width in morphology.rectangle
  • TODO.txt -> only address deprecations to keep this focused

Checklist

  • Docstrings for all functions
  • Gallery example in ./doc/examples (new features only)
  • Benchmark in ./benchmarks, if your changes aren't covered by an
    existing benchmark
  • Unit tests
  • Clean style in the spirit of PEP8
  • Descriptive commit messages (see below)

For reviewers

  • Check that the PR title is short, concise, and will make sense 1 year
    later.
  • Check that new functions are imported in corresponding __init__.py.
  • Check that new features, API changes, and deprecations are mentioned in
    doc/release/release_dev.rst.
  • There is a bot to help automate backporting a PR to an older branch. For
    example, to backport to v0.19.x after merging, add the following in a PR
    comment: @meeseeksdev backport to v0.19.x
  • To run benchmarks on a PR, add the run-benchmark label. To rerun, the label
    can be removed and then added again. The benchmark output can be checked in
    the "Actions" tab.

in favor of footprint. Though removed_version points at 1.0, the
deprecation is finished in 0.20 which was not planned at the time of
0.19's release.
Though removed_version points at 1.0, the deprecation is finished in
0.20 which was not planned at the time of 0.19's release.
@lagru lagru added 🔧 type: Maintenance Refactoring and maintenance of internals 🔽 Deprecation Involves deprecation labels Oct 16, 2022
@lagru lagru added this to the 0.20 milestone Oct 16, 2022
@stefanv
Copy link
Member

stefanv commented Oct 17, 2022

Thanks for working through these!

def gaussian(image, sigma=1, output=None, mode='nearest', cval=0,
multichannel=None, preserve_range=False, truncate=4.0, *,
preserve_range=False, truncate=4.0, *,
channel_axis=None):
Copy link
Member Author

Choose a reason for hiding this comment

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

I'd like to point out

if image.ndim == 3 and image.shape[-1] == 3 and channel_axis is None:
msg = ("Images with dimensions (M, N, 3) are interpreted as 2D+RGB "
"by default. Use `multichannel=False` to interpret as "
"3D image with last dimension of length 3.")
warn(RuntimeWarning(msg))
channel_axis = -1

I am pretty sure that the logic makes it impossible to indicate to the function to treat an image of shape (M, N, 3) as a grayscale image as channel_axis=None is replaced with channel_axis=-1. The warning text implies, that in the absence of an explicit multichannel, the image is treated as RGB in some cases. However, with the switch to channel_axis we can no longer replicate this behavior. channel_axis=None means "no RGB" as opposed to multichannel=None which means "not set".

Pretty sure this was broken since the deprecate_multichannel_kwarg was applied as well. A that one translates multichannel=False into channel_axis=None...

My proposal is to remove this (broken) implicit RGB assumption if (M, N, 3).

Copy link
Member

Choose a reason for hiding this comment

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

Oops! The warning message is problematic too; it should have been updated ever since multichannel became deprecated, so the user isn't invited to set a deprecated kwarg...

Copy link
Member

Choose a reason for hiding this comment

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

We need another None-proxy, e.g.:

class NoChannelAxis:
		pass

def gaussian(..., channel_axis=NoChannelAxis):
	if channel_axis is NoChannelAxis:
	    ...
			
# User can do:
gaussian(..., channel_axis=None)

Copy link
Member Author

Choose a reason for hiding this comment

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

See a5421d5. Patching the __repr__ with a metaclass was actually a lot of fun, although it probably shouldn't be. 😅

I think the patch addresses the following cases:

  1. User neither passed multichannel nor channel_axis and relied on automatic detection of color channel for (M, N, 3). Since v0.19 we silently broke his workflow. This patch recovers the original behavior for one release and notifies the user.
  2. User continued using multichannel=False. Since v0.19 that was replaced with channel_axis=None. In case the shape was (M, N, 3) we broke his code otherwise he was fine. This user is notified as well because multichannel is no longer available.
  3. User read the misleading RuntimeWarning, and nevertheless started using channel_axis=None for a grayscale image. The warning continued. In case the shape was (M, N, 3) we broke his code otherwise he was fine. This patch recovers the original behavior but does not notify him.

All other cases using grayscale images shouldn't have been impacted.

Copy link
Contributor

Choose a reason for hiding this comment

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

@stefanv @lagru What is the status of this? It would be good to get this merged soon.

Copy link
Member Author

@lagru lagru Nov 17, 2022

Choose a reason for hiding this comment

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

Are you asking about the status of this specific comment thread? It's been addressed in a5421d5.

Concerning the status of this PR, I think I addressed everything I found at the time. The only remaining suggestion was to add .. versionchanged:: directives everywhere. But that should not hold up this PR in my opinion and can be done here or in another PR if someone finds the time.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for patching up this behavior @lagru, it looks great.

in favor of "out".

Though removed_version points at 1.0, the deprecation is finished in
0.20 which was not planned at the time of 0.19's release.
in favor of "max_num_iter".

Though removed_version points at 1.0, the deprecation is finished in
0.20 which was not planned at the time of 0.19's release.
in favor of "max_num_iter".

Though removed_version points at 1.0, the deprecation is finished in
0.20 which was not planned at the time of 0.19's release.
in favor of "num_iter".

Though removed_version points at 1.0, the deprecation is finished in
0.20 which was not planned at the time of 0.19's release.
in favor of "max_num_iter".

Though removed_version points at 1.0, the deprecation is finished in
0.20 which was not planned at the time of 0.19's release.
Though removed_version points at 1.0, the deprecation is finished in
0.20 which was not planned at the time of 0.19's release.
in favor of "label_image".

Though removed_version points at 1.0, the deprecation is finished in
0.20 which was not planned at the time of 0.19's release.
Though removed_version points at 1.0, the deprecation is finished in
0.20 which was not planned at the time of 0.19's release.
Though the default removed_version of deprecate_multichannel_kwarg
points at 1.0, the deprecation is finished in 0.20 which was not planned
at the time of 0.19's release.
This decorator is no longer necessary since the deprecation of
multichannel is completed with 0.20 (previously 1.0).

Make test's independent of temporary decorations of library functions
such as hog and pyramid_gaussian. Their deprecation decorator was
removed.
For filters.inverse(), the removed_version targets 0.21 and not 0.20. So
move.
I think removed_version="1.2" is actually supposed to be 1.0 (or 0.20).
These deprecations are already part of 0.19. So it should be fine to
remove them in 0.20.
TODO.txt Outdated Show resolved Hide resolved
@lagru
Copy link
Member Author

lagru commented Oct 19, 2022

@scikit-image/core this is ready for review. Please have a look. Reviewing commit by commit might be useful as I tried to keep related changes together...

The fix for the failing test is discussed in #6583 (comment).

@lagru lagru marked this pull request as ready for review October 19, 2022 11:06
from .rank import generic


@deprecate_kwarg(kwarg_mapping={'selem': 'footprint'}, removed_version="1.0",
deprecated_version="0.19")
Copy link
Member

Choose a reason for hiding this comment

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

Before the 'Returns' section, shouldn't there be something like:

    .. versionchanged:: 0.19
        Parameter ``selem`` has been replaced by ``footprint``.

? I think @jni would know...

Copy link
Member Author

@lagru lagru Oct 19, 2022

Choose a reason for hiding this comment

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

I'm pretty sure that we don't use the .. versionchanged:: directive consistently (yet). But I could go through and update each docstring if we deem it worth it to keep the notice around.

This reverts commit 56f0431.

The deprecation of `compute_hessian_eigenvalues` was introduced after
all 0.19.x releases (see git tag --contains d2689f5)! So the target
should be 0.21.
Automatic detection of the color channel based on the old deprecated
`multichannel=None` was broken in version 0.19. This commit recovers
the old behavior for 0.20 using a proxy object `ChannelAxisNotSet`.
The behavior is still deprecated though and should be removed completely
in 0.21.

Note that the warning is only raised if the automatic behavior deviates
from the behavior that will be the new default in 0.21, which is
`channel_axis=None`. This way we only notify users that were affected
by the broken behavior in 0.19 and now deprecated behavior in 0.20.
in `regionprops` (since 0.16) and `active_contour` (since 0.18).
Instead of raising a ValueError, since
f8dfea6 [1] this is addressed by
returning `False`.

[1] scikit-image#6453
# Conflicts:
#	skimage/restoration/_denoise.py
#	skimage/segmentation/tests/test_random_walker.py
Copy link
Contributor

@grlee77 grlee77 left a comment

Choose a reason for hiding this comment

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

Thank you for completing all of these @lagru. I am especially happy to see the deprecation cycle completed for both multichannel and selem!

@grlee77
Copy link
Contributor

grlee77 commented Nov 18, 2022

The one CI failure was due to an uncaught FutureWarning message. I pushed a commit that should fix it.

Copy link
Member

@stefanv stefanv left a comment

Choose a reason for hiding this comment

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

Thanks for taking care of this @lagru!

Just one request to clarify a docstring, otherwise LGTM.

return f"<{cls.__name__}>"


class ChannelAxisNotSet(metaclass=_PatchClassRepr):
Copy link
Member

Choose a reason for hiding this comment

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

Is the metaclass necessary?

Copy link
Member Author

@lagru lagru Nov 23, 2022

Choose a reason for hiding this comment

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

I'm sure there are other ways to control how this signal object is rendered in the signature (I would post the link but strangely the pipeline did not build the docs?). I initially included the __repr__ in this class itself which requires creating an instance of it in the same scope to check for identity in the function body. Compared to that, I actually found the metaclass-based approach clearer and easier to document. The class itself clearly is the signal and there is no confusion about a second symbol that also looks like a signal; it's clearly a metaclass only responsible for modifying the representation.

It's not something I feel strongly about, though. The verbose answer is mainly because I'm rationalizing my gut feeling about which approach "felt better" in retrospective. 😄

skimage/_shared/filters.py Outdated Show resolved Hide resolved
skimage/_shared/filters.py Outdated Show resolved Hide resolved
lagru and others added 2 commits November 23, 2022 15:47
Co-authored-by: Stefan van der Walt <sjvdwalt@gmail.com>
@grlee77
Copy link
Contributor

grlee77 commented Nov 29, 2022

I think this should be good to go now. Some of these deprecations (e.g. multichannel and selem) will be great to have completed. However, note that they were first introduced in 0.19, so removing them now would be quicker than our usual two-release deprecation cycle. Given that it has been a full year since 0.19.0 was released, I am in favor of it, though. Are there any objections, or should we merge this now?

@stefanv
Copy link
Member

stefanv commented Nov 29, 2022

I'm in favor of merging.

@mkcor
Copy link
Member

mkcor commented Nov 30, 2022

I'm also in favour of merging this PR.

@grlee77 grlee77 merged commit a91f4f8 into scikit-image:main Nov 30, 2022
@grlee77
Copy link
Contributor

grlee77 commented Nov 30, 2022

Merged, thanks @lagru!

@lagru lagru deleted the complete-0.20-deprecations branch December 1, 2022 09:51
@lagru lagru mentioned this pull request Dec 7, 2022
4 tasks
orientnab added a commit to orientnab/MedMNIST that referenced this pull request Mar 30, 2023
The `multichannel` field in `skimage.util.montage` has been deprecated in version 0.20.

Update function call to work with the new API.

From the relase notes for 0.20:
Remove deprecated parameter multichannel; use channel_axis instead. [...] In skimage.util, this affects montage and apply_parallel ([#6583](scikit-image/scikit-image#6583)).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔽 Deprecation Involves deprecation 🔧 type: Maintenance Refactoring and maintenance of internals
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants