Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Set norms using scale names.#20752

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
jklymak merged 1 commit intomatplotlib:mainfromanntzer:strnorms
Jul 20, 2022
Merged

Conversation

anntzer
Copy link
Contributor

@anntzeranntzer commentedJul 27, 2021
edited
Loading

PR Summary

Implements#20746.

Proof of concept implementation for#20746.
Still needs a lot of docs, but otherwise mostly works.

Remaining issues:

PR Checklist

  • Has pytest style unit tests (andpytest passes).
  • IsFlake 8 compliant (runflake8 on changed files to check).
  • New features are documented, with examples if plot related.
  • Documentation is sphinx and numpydoc compliant (the docs shouldbuild without error).
  • Conforms to Matplotlib style conventions (installflake8-docstrings and runflake8 --docstring-convention=all).
  • New features have an entry indoc/users/next_whats_new/ (follow instructions in README.rst there).
  • API changes documented indoc/api/next_api_changes/ (follow instructions in README.rst there).

colors.Normalize)()
norm_cls = type(norm)
norm_cls.__name__ = f"{scale_cls.__name__}Norm"
return norm_cls
Copy link
Member

Choose a reason for hiding this comment

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

I guess this seems overkill to me, and fragile as shown by the pickling issue? Why don't we just usescale._scale_mapping or make one, i.e.colors._norm_mapping? Do we really need the extra flexibility given by allowing dynamic creation?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

I don't really want to create a separate mapping as people can register new scales (e.g. mpl-probscale does it), but they wouldn't show up in the norm mapping if these are separate.

Copy link
Member

Choose a reason for hiding this comment

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

Back when I was a whippersnapper, we only had the linear norm and we liked it....

I'm not sure that making this super-flexible is worth the complication. The strings can be for a few common norms. How many specialized scales truly need a norm as well, and how much of a problem is it to ask users to just pass the norm instead to the string? Its not like probscale is going to be a super-useful color norm. If you wanted to add aregister_norm, fine, but making it all dynamic just seems to be asking for trouble.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

#20755 fixes that part.

@anntzer
Copy link
ContributorAuthor

This should now be ready for review. Note that the docs are currently split in a separate commit and most methods now just point to imshow() to reduce the duplication, but once we agree on a wording I can also copy paste the same doc everywhere if that's what we decide to do at the end.

@anntzeranntzerforce-pushed thestrnorms branch 2 times, most recently from9715b10 toae7c8e8CompareDecember 21, 2021 20:27
Copy link
Member

@timhoffmtimhoffm left a comment

Choose a reason for hiding this comment

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

At some later point, we may want to move the explanation of the colormapping mechanism to someExplanations section in the docs and link everything there instead of toimshow(). But linkingimshow() for a start is ok.

Copy link
Contributor

@greglucasgreglucas left a comment

Choose a reason for hiding this comment

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

👍 I like the concept of using strings to make it easier to get a norm than having to importmatplotlib.colors and create an object. I think this could lead to some mismatch/confusion about which scale/norm mappings are available, so perhaps some better string validation/error messages would be helpful when using this.

The `.Normalize` instance used to scale scalar data to the [0, 1]
range before mapping to colors using *cmap*. By default, a linear
range before mapping to colors using *cmap*.By default, a linear
Copy link
Contributor

Choose a reason for hiding this comment

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

There should only be one space after a period for most (all now?) style guides, so this shouldn't be updated. Same for the other docstrings in this PR.

if norm is None:
norm = colors.Normalize()
elif isinstance(norm, str):
# case-insensitive, consistently with scale_factory.
scale_cls = scale._scale_mapping[norm.lower()]
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering if it would be helpful to wrap this in a try-except and re-raise with a list of options available for users?

I can see users trying:imshow(..., norm="Boundary") and wondering what option would work instead.

timhoffm reacted with thumbs up emoji
@anntzer
Copy link
ContributorAuthor

Thanks, I should have addressed all the comments.

@@ -331,6 +332,35 @@ def unregister_cmap(name):
return _cmap_registry.pop(name)


@functools.lru_cache(None)
def _auto_norm_from_scale(scale_cls):
Copy link
Member

Choose a reason for hiding this comment

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

Overall I think this is a great idea. However, all the scales with strings currently have Norm classes, don't they? If so, why are you creating a new class here versus using the existing classes? It seems like it will just make things needlessly confusing.

Copy link
ContributorAuthor

@anntzeranntzerJan 21, 2022
edited
Loading

Choose a reason for hiding this comment

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

  1. Some scales (most prominently, logit) don't have a norm associated;
  2. because everything is wrapped under lru_caches,_auto_norm_from_scale(LogScale) is going to be exactly the same object asLogNorm (multiple calls tomake_norm_from_scale or_auto_norm_from_scale always return the same norm class). (I added a test for that.)

Copy link
Member

Choose a reason for hiding this comment

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

Can you document that here? Because I couldn't parse that from the code, but maybe my ignorance of how the caches get shared across submodules.

However, I'm still not understanding what happens if the user puts 'logit' in here. Are you saying a norm will still be created?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

The documentation is the third bullet point below ("The returned norm class is memoized and reused for later calls." But feel free to suggest something clearer). Yes, a norm class will be dynamically created if the user puts in "logit" (and later calls will reuse the same dynamically created norm class).
This will also work with scales provided by third-parties, e.g. mpl-probscale (which is why I did not go for just an explicit and exhaustive mapping of names to norm classes -- this would not work with third-party scales).

Copy link
Member

Choose a reason for hiding this comment

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

this would not work with third-party scale

Fair enough if we are supporting those as norms, though that sounds risky to me...

The returned norm class is memoized and reused for later calls.

Maybe just a bit more verbose "the returned norm class is the same as for make_norm_from_scale (so norm='log' will return a LogNorm instance); these are are also memoized..." (though is there a reason to not use "cached"? "memoized" is pretty jargon, but maybe my ignorance)

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Re: 3rd-parties: well, that was also one of the points of the PR (and again, think of this as "supporting putting a third-party scale on a colorbar axis").
Re: docs: sure, reworded, sorry for the jargon :)

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Edit: actually I had to fix the caching, but it should be good now.

Copy link
Contributor

Choose a reason for hiding this comment

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

I had a bit of confusion initially figuring out exactly what is being cached. The cached "thing" is the class definition. It is not the returned Norm object. So, these two calls will have different LogNormalize objects, which is consistent with how it works currently when no norm is given (a new Normalize object is created each time).

im1=ax.imshow([[0,1]],norm="log")im2=ax.imshow([[0,1]],norm="log")assertim1.normisnotim2.norm

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Good point, I further reworded the docs to clarify that.

@anntzeranntzerforce-pushed thestrnorms branch 5 times, most recently frome0de415 tod38dd06CompareJanuary 21, 2022 14:44
Copy link
Member

@jklymakjklymak left a comment

Choose a reason for hiding this comment

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

This looks ready to go to me, but we probably need to copy the documentation between the methods. Its not very nice to be asked to look at another doscstring for basic kwargs if we can help it.

Comment on lines 5324 to 5288
The normalization can also be given as a str, which should be a
scale name (as in `~.Axes.set_xscale`, i.e. one of "linear", "log",
"symlog", "logit", etc.). In that case, a normalization class is
dynamically generated from the corresponding scale, as if using
that scale for the image's colorbar.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Thenormalizationcanalsobegivenasastr,whichshouldbea
scalename (asin`~.Axes.set_xscale`,i.e.oneof"linear","log",
"symlog","logit",etc.).Inthatcase,anormalizationclassis
dynamicallygeneratedfromthecorrespondingscale,asifusing
thatscalefortheimage'scolorbar.
Ifastr,*norm*mustbeascalename (i.e."linear","log",
"symlog","logit",asper`~.Axes.set_xscale`,orcall
`~.scale.get_scale_names`).Bydefault,thisscalewillbe
alsousedforacolorbarfortheimage.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

I'm not really sure about this wording? (Why "by default"? 1) I guess youcould change that, but having a linear-scale colorbar for a lognorm seems rare; 2) more than anything, this kwarg sets the norm on the mappable; setting the colorbar scale is more a side effect of that. Also, even set_xscale doesn't mentionget_scale_names. Perhaps it should, but if it doesn't, I don't think imshow() needs to do that either.)

Copy link
Member

Choose a reason for hiding this comment

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

"one of "linear", "log", "symlog", "logit", etc." is vague, so was trying to be more precise. "...as if using the scale" was also theoretical sounding, whereas wedo use the scale for the colorbar, so why not be explicit? As for "by default" - the user can change the colorbar scale. But I don't feel strongly about my wording - feel free to iterate as you see fit.

Comment on lines 5917 to 5891
cmap, norm, vmin, vmax
Data normalization and colormapping parameters for *C*. See
`~.Axes.imshow` for a detailed description.
Copy link
Member

Choose a reason for hiding this comment

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

I guess this needs to all be copied over.

@anntzer
Copy link
ContributorAuthor

Rebased.

@anntzeranntzer marked this pull request as ready for reviewJune 23, 2022 10:13
@timhoffm
Copy link
Member

timhoffm commentedJun 23, 2022
edited
Loading

@anntzer It seems that my proposal to interpolate every parameter individually got lost:

marker : ...    ...%(param_cmap)s%(param_norm)s%(param_vmin_vmax)s    more text on vmin/vmax.alpha : float    ...

IMHO that would solve the major issues with the present interpolation

  • Naming%(cmap_norm_vmin_vmax_doc)s is quite longish and still not very clear.
  • There's one place that extends the vmin/vmax section, but it relies implicitly on vmin/vmax being the last parameter in the interpolation block.

What do you think?

@anntzer
Copy link
ContributorAuthor

Sure, done. (I named themcmap_doc,norm_doc,vmin_vmax_doc as that's more consistent with other_doc entries already present in interpd, but don't feel strongly about that either.)

if norm is None:
norm = colors.Normalize()
elif isinstance(norm, str):
try:
scale_cls = scale._scale_mapping[norm]
Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Given#20753, I made this case-sensitive from the beginning.

timhoffm reacted with thumbs up emoji
@timhoffm
Copy link
Member

timhoffm commentedJun 25, 2022
edited
Loading

Flake8:

./lib/matplotlib/contour.py:1787:1: E124 closing bracket does not match visual indentation./lib/matplotlib/tri/tricontour.py:210:1: E124 closing bracket does not match visual indentation

The other CI failures can probably be fixed by a rebase.

Comment on lines 647 to 648
before mapping to colors using *cmap*. By default, a linear scaling mapping
the lowest value to 0 and the highest to 1 is used. This parameter is
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
beforemappingtocolorsusing*cmap*.Bydefault,alinearscalingmapping
thelowestvalueto0andthehighestto1isused.Thisparameteris
beforemappingtocolorsusing*cmap*.Bydefault,alinearscalingisused,
mappingthelowestvalueto0andthehighestto1.Thisparameteris

IMHO it's a bit easier to read this way.

cmap_doc="""\
cmap : str or `~matplotlib.colors.Colormap`, default: :rc:`image.cmap`
The Colormap instance or registered colormap name used to map scalar data
to colors. This parameter is ignored for RGB(A) data.""",
Copy link
Member

Choose a reason for hiding this comment

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

I think not all functions using cmap support RGB(A) data. Now that we have entries per parameter it is possible to do move this out of the general description and do

%(cmap_doc)s        This parameter is ignored for RGB(A) data.

only when needed (or make acmap_rgba_doc if there are many cases).

Copy link
ContributorAuthor

@anntzeranntzerJun 25, 2022
edited
Loading

Choose a reason for hiding this comment

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

Actually, none of cmap, vmin/vmax, and norm apply for RGBA data, so all of them should get this comment.

Copy link
Member

Choose a reason for hiding this comment

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

Um, that's not what I meant. We have functions likescatter that allow either colormapped or RGBA data. Here, the sentence makes sense. But we also have functions likehexbin, that only operate with colormapping. Mentioning that a parameter is ignored for RGBA data when RGBA data is not supported by the function is somewhat confusing.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

Sorry I was unclear, I was meaning "all of cmap, norm, and vmin/vmax should get this comment". From a quick check, the only functions that do not take color input are hexbin and hist2d; do you agree?

Copy link
Member

Choose a reason for hiding this comment

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

From a quick search, I think the following functions support color input:

  • scatter
  • hexbin
  • imshow
  • pcolor
  • pcolormesh
  • pcolorfast
  • hist2d
  • specgram
  • contour
  • tripcolor

Feel free to update the list.

Even if it's only hexbin and hist2d, how do we handle them?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

OK, this should be handled now.

@jklymak
Copy link
Member

Moving to draft until flake8 looked at....

@jklymakjklymak marked this pull request as draftJune 30, 2022 08:59
@QuLogicQuLogic modified the milestones:v3.6.0,v3.7.0Jul 5, 2022
@anntzeranntzer marked this pull request as ready for reviewJuly 14, 2022 10:14
@anntzer
Copy link
ContributorAuthor

@jklymak Thanks for the ping, now fixed.

Copy link
Member

@jklymakjklymak left a comment

Choose a reason for hiding this comment

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

Looks good to me!

@jklymak
Copy link
Member

Did we want the three commits?

@anntzer
Copy link
ContributorAuthor

anntzer commentedJul 20, 2022
edited
Loading

This was mostly to make it easier to iterate on the individual parts separately, now squashed.

I don't know what's the status of 3.6 right now;@QuLogic can I remilestone this to 3.6?

@jklymak
Copy link
Member

I don't think there is a 3.6.x branch, and I've not heard that the release has been started, so lets merge as 3.6

@jklymakjklymak modified the milestones:v3.7.0,v3.6.0Jul 20, 2022
@jklymakjklymak merged commit3992fb0 intomatplotlib:mainJul 20, 2022
@anntzeranntzer deleted the strnorms branchJuly 20, 2022 15:19
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@timhoffmtimhoffmtimhoffm left review comments

@jklymakjklymakjklymak approved these changes

@greglucasgreglucasgreglucas approved these changes

Assignees
No one assigned
Projects
None yet
Milestone
v3.6.0
Development

Successfully merging this pull request may close these issues.

5 participants
@anntzer@jklymak@greglucas@timhoffm@QuLogic

[8]ページ先頭

©2009-2025 Movatter.jp