{"action":"created","issue":{"url":"https://api.github.com/repos/matplotlib/matplotlib/issues/7631","repository_url":"https://api.github.com/repos/matplotlib/matplotlib","labels_url":"https://api.github.com/repos/matplotlib/matplotlib/issues/7631/labels{/name}","comments_url":"https://api.github.com/repos/matplotlib/matplotlib/issues/7631/comments","events_url":"https://api.github.com/repos/matplotlib/matplotlib/issues/7631/events","html_url":"https://github.com/matplotlib/matplotlib/pull/7631","id":195953510,"number":7631,"title":"ENH: Added FuncNorm","user":{"login":"alvarosg","id":12649253,"avatar_url":"https://avatars.githubusercontent.com/u/12649253?v=3","gravatar_id":"","url":"https://api.github.com/users/alvarosg","html_url":"https://github.com/alvarosg","followers_url":"https://api.github.com/users/alvarosg/followers","following_url":"https://api.github.com/users/alvarosg/following{/other_user}","gists_url":"https://api.github.com/users/alvarosg/gists{/gist_id}","starred_url":"https://api.github.com/users/alvarosg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alvarosg/subscriptions","organizations_url":"https://api.github.com/users/alvarosg/orgs","repos_url":"https://api.github.com/users/alvarosg/repos","events_url":"https://api.github.com/users/alvarosg/events{/privacy}","received_events_url":"https://api.github.com/users/alvarosg/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":{"login":"efiring","id":85125,"avatar_url":"https://avatars.githubusercontent.com/u/85125?v=3","gravatar_id":"","url":"https://api.github.com/users/efiring","html_url":"https://github.com/efiring","followers_url":"https://api.github.com/users/efiring/followers","following_url":"https://api.github.com/users/efiring/following{/other_user}","gists_url":"https://api.github.com/users/efiring/gists{/gist_id}","starred_url":"https://api.github.com/users/efiring/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/efiring/subscriptions","organizations_url":"https://api.github.com/users/efiring/orgs","repos_url":"https://api.github.com/users/efiring/repos","events_url":"https://api.github.com/users/efiring/events{/privacy}","received_events_url":"https://api.github.com/users/efiring/received_events","type":"User","site_admin":false},"assignees":[{"login":"efiring","id":85125,"avatar_url":"https://avatars.githubusercontent.com/u/85125?v=3","gravatar_id":"","url":"https://api.github.com/users/efiring","html_url":"https://github.com/efiring","followers_url":"https://api.github.com/users/efiring/followers","following_url":"https://api.github.com/users/efiring/following{/other_user}","gists_url":"https://api.github.com/users/efiring/gists{/gist_id}","starred_url":"https://api.github.com/users/efiring/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/efiring/subscriptions","organizations_url":"https://api.github.com/users/efiring/orgs","repos_url":"https://api.github.com/users/efiring/repos","events_url":"https://api.github.com/users/efiring/events{/privacy}","received_events_url":"https://api.github.com/users/efiring/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/matplotlib/matplotlib/milestones/12","html_url":"https://github.com/matplotlib/matplotlib/milestone/12","labels_url":"https://api.github.com/repos/matplotlib/matplotlib/milestones/12/labels","id":534144,"number":12,"title":"2.1 (next point release)","description":"Next feature release.\r\n\r\nBig ticket items:\r\n\r\n - MEP 22/27\r\n - traitlets","creator":{"login":"tacaswell","id":199813,"avatar_url":"https://avatars.githubusercontent.com/u/199813?v=3","gravatar_id":"","url":"https://api.github.com/users/tacaswell","html_url":"https://github.com/tacaswell","followers_url":"https://api.github.com/users/tacaswell/followers","following_url":"https://api.github.com/users/tacaswell/following{/other_user}","gists_url":"https://api.github.com/users/tacaswell/gists{/gist_id}","starred_url":"https://api.github.com/users/tacaswell/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tacaswell/subscriptions","organizations_url":"https://api.github.com/users/tacaswell/orgs","repos_url":"https://api.github.com/users/tacaswell/repos","events_url":"https://api.github.com/users/tacaswell/events{/privacy}","received_events_url":"https://api.github.com/users/tacaswell/received_events","type":"User","site_admin":false},"open_issues":584,"closed_issues":673,"state":"open","created_at":"2014-01-13T03:21:09Z","updated_at":"2017-02-05T03:09:06Z","due_on":null,"closed_at":null},"comments":6,"created_at":"2016-12-16T00:35:48Z","updated_at":"2017-02-05T14:56:48Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/matplotlib/matplotlib/pulls/7631","html_url":"https://github.com/matplotlib/matplotlib/pull/7631","diff_url":"https://github.com/matplotlib/matplotlib/pull/7631.diff","patch_url":"https://github.com/matplotlib/matplotlib/pull/7631.patch"},"body":"This PR is part of a [larger PR](https://github.com/matplotlib/matplotlib/pull/7294) originally proposed to include FuncNorm and PiecewiseNorm. It was decided to split it into several PRs for easier review starting from the simpler classes.\r\n\r\nIn this case the functionality added is `FuncNorm`, a normalization class (inheriting from `Normalize`), that allows using any arbitrary function as a normalization, by specifying a callable (and a callable of the inverse function), or a string compatible with the brand new `_StringFuncParser`.\r\n\r\nExamples of usage for log normalization:\r\n```python\r\n    norm_log = colors.FuncNorm(f='log10', vmin=0.01)\r\n```\r\nthe same can be achieved with\r\n```python\r\n    norm_log = colors.FuncNorm(f=np.log10,\r\n                               finv=lambda x: 10.**(x), vmin=0.01)\r\n```\r\n\r\nFor root normalization:\r\n```python\r\n    norm_sqrt = colors.FuncNorm(f='sqrt', vmin=0.0)\r\n```\r\nthe same can be achieved with\r\n```python\r\n    norm_sqrt = colors.FuncNorm(f='root{2}', vmin=0.)\r\n```\r\nor with\r\n```python\r\n    norm_sqrt = colors.FuncNorm(f=lambda x: x**0.5,\r\n                                finv=lambda x: x**2, vmin=0.0)\r\n```\r\n\r\nTests have been added, as well as an example producing this output this output:\r\n\r\n![funcnorm](https://cloud.githubusercontent.com/assets/12649253/21963626/eb4f26d2-db35-11e6-9dd7-a6e943be05cd.png)\r\n\r\nPossible caveat:\r\n\r\nMost of the behaviour provided by this class does not change the existing interfaces for normalizations, as most public methods of the new class are just overridden methods from `Normalize`.\r\n\r\n<del>The only exception to this is the ticks methods, returning an educated guess on where to add tick values, which would be a new public method in the class. \r\n\r\n<del>On the other hand I think it works quite well (even for very non-linear normalizations) and it is important to give the user a good guess at where to put the ticks, so it is not required to manually enter values (or come up with his own automated algorithm). This way the only thing the user needs to specify is a number of ticks, which may also be easily set to a default value. We should think whether we want to include this or no, or maybe do it in a different way.\r\n\r\n<del>The way it is done now is by an explicit call to `norm.ticks()`:\r\n\r\n<del>```python\r\n<del>fig.colorbar(cax, format='%.3g', ticks=cax.norm.ticks(5), ax=ax2)\r\n<del>```\r\n\r\nA FuncLocator class has now been implemented, so ticks are set automatically to the suggested positions without explicit user input, in exactly the same way it was done for other normalizations like `LogNorm`.\r\n\r\n\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/matplotlib/matplotlib/issues/comments/277524909","html_url":"https://github.com/matplotlib/matplotlib/pull/7631#issuecomment-277524909","issue_url":"https://api.github.com/repos/matplotlib/matplotlib/issues/7631","id":277524909,"user":{"login":"alvarosg","id":12649253,"avatar_url":"https://avatars.githubusercontent.com/u/12649253?v=3","gravatar_id":"","url":"https://api.github.com/users/alvarosg","html_url":"https://github.com/alvarosg","followers_url":"https://api.github.com/users/alvarosg/followers","following_url":"https://api.github.com/users/alvarosg/following{/other_user}","gists_url":"https://api.github.com/users/alvarosg/gists{/gist_id}","starred_url":"https://api.github.com/users/alvarosg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alvarosg/subscriptions","organizations_url":"https://api.github.com/users/alvarosg/orgs","repos_url":"https://api.github.com/users/alvarosg/repos","events_url":"https://api.github.com/users/alvarosg/events{/privacy}","received_events_url":"https://api.github.com/users/alvarosg/received_events","type":"User","site_admin":false},"created_at":"2017-02-05T14:56:48Z","updated_at":"2017-02-05T14:56:48Z","body":"@efiring Did you get a chance to look at the changes I implemented about a couple of weeks ago?"}}
{"actor":{"display_login":"alvarosg"}}