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

[WIP]Add de-aliaser function for plots #1073

Merged
merged 22 commits into from
Mar 2, 2020

Conversation

percygautam
Copy link
Contributor

@percygautam percygautam commented Feb 17, 2020

Description

Fixes #1041 . Added function to dealiase the plot kwargs passed to plots by user. Working example can be found in cookbook.

Checklist

  • Follows official PR format
  • New features are properly documented (with an example if appropriate)?
  • Code style correct (follows pylint and black guidelines)
  • Changes are listed in changelog

Copy link
Member

@OriolAbril OriolAbril left a comment

Choose a reason for hiding this comment

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

I would take advantage of the fact that alias_mapping argument in cbook.normalize_kwargs can be a subclass of Artist objects.

Therefore, cbook.normalize_kwargs(plot_kwargs, mpl.lines.Line2D) should do the trick and we can avoid maintaining the alias dicts. Regarding one or several functions, maybe we can wrap normalize_kwargs for several common objects Line2D (for plot), PathCollection (for scatter) and so on.

@percygautam
Copy link
Contributor Author

Okay, I'd do the changes. We can use a single function for dealiasing.

@percygautam
Copy link
Contributor Author

I would take advantage of the fact that alias_mapping argument in cbook.normalize_kwargs can be a subclass of Artist objects.

@OriolAbril This functionality is only present in unreleased latest version 3.2.0 and not in version used by arviz 3.1.2.
https://github.com/matplotlib/matplotlib/blob/3b2a89825e5e5a98b8b9478c8f103cc22b9b706f/lib/matplotlib/cbook/__init__.py#L1768-L1772

As a workaround I'd do something like this:

def dealiser(args): 
    return cbook.normalize_kwargs(args, getattr(mpl.collections.PathCollection,"_alias_map", {}))

We can use this workaround until arviz shifts to new version of matplotlib.

@OriolAbril
Copy link
Member

The workaround sounds good, in this case it is probably better to define a handful of dealiasers (or a dealiaser with some kind argument) to allow dealiasing for both plot and scatter and also hexbin of hist if they were to return a different artist than plot and scatter

@percygautam
Copy link
Contributor Author

I have applied dealiser to all the cases I can find. Please check if I missed something.
Also, what should we do in the case of compareplot?(we are defining arviz specific kwargs)

Copy link
Member

@OriolAbril OriolAbril left a comment

Choose a reason for hiding this comment

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

Two comments only. I would name the function as something more explicit like matplotlib_kwarg_dealiaser or normalize_matplotlib_kwargs. Also, we have to make sure that after dealiasing, only the default prop name is used (e.g. no lw nor ms...)

@percygautam
Copy link
Contributor Author

I have checked the files and confirmed that only default prop names are used.
Also, for case we set default by using alias, then kwargs dict will contain both alias prop(set by arviz) and dealiased prop (set by user), for such case full names are given precedence.( ref: https://github.com/matplotlib/matplotlib/blob/3b2a89825e5e5a98b8b9478c8f103cc22b9b706f/lib/matplotlib/cbook/__init__.py#L1722). So, only user-defined property will be used in plots.

Anyway, currently it won't cause any error and we can correct that alias aren't used in future .

Copy link
Member

@OriolAbril OriolAbril left a comment

Choose a reason for hiding this comment

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

How do you feel about adding a couple of tests for matplotlib_kwarg_dealiaser?

arviz/plots/essplot.py Outdated Show resolved Hide resolved
arviz/plots/mcseplot.py Outdated Show resolved Hide resolved
arviz/plots/mcseplot.py Outdated Show resolved Hide resolved
arviz/plots/pairplot.py Outdated Show resolved Hide resolved
@percygautam
Copy link
Contributor Author

Should I add more test cases or are these enough?

Copy link
Member

@OriolAbril OriolAbril left a comment

Choose a reason for hiding this comment

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

I think this test is enough. We are basically relying on matplotlib.

@percygautam
Copy link
Contributor Author

The dealiasing function is not working for python 3.5. Any workaround?

@OriolAbril
Copy link
Member

The dealiasing function is not working for python 3.5. Any workaround?

matplotlib 3.1 droped support for python 3.5, so CI uses 3.0.3 which probably has different alias. Checking the keys and for which kinds it fails should allow to remove the combination from tests

@OriolAbril
Copy link
Member

OriolAbril commented Feb 24, 2020

@percygautam I just had an idea. Currently most plots do something similar to:

if kwargs is None:
    kwargs = {}
else:
    kwargs = matplotlib_kwarg_dealiaser(kwargs)

We could simplify this by making matplotlb_kwarg_dealiaser also accept None in which case it would return {} straight away and not call matplotlib's kwarg normalizer. All test suite was reorganized, so a rebase/merge from master is needed.

Note: Also, to avoid merge issues with #1079 that does a considerable rewrite of plot_pair, it'd be better to not modify pairplot.py.

@percygautam
Copy link
Contributor Author

I've done the changes and left pairplot as before.

Copy link
Member

@OriolAbril OriolAbril left a comment

Choose a reason for hiding this comment

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

It looks like you have removed some blank lines in plot_pair docstring and now it the lint complains.

I have one question about matplotlib/bokeh interaction. What happens if there are keys in the kwargs dict that do not correspond to any alias nor accepted argument? is there any warning/error? Bokeh will have different names, so the dealiaser should not modify items that are not alias. Also, could you add a test to check for example that a dict like {"line_color": "black"} goes through the dealiaser unchanged?

If the desired behaviour from above were not to happen (I don't really know how to check bokeh kwarg names though, sorry), we should also pass backend to the dealiaser so that None -> {}, backend="bokeh" -> unchanged_input and when none of the two conditions above are met, call matplotlib's normalize kwargs

@percygautam
Copy link
Contributor Author

percygautam commented Feb 29, 2020

Sorry for the delay.
@OriolAbril There are two cases for kwargs, whether it is for matplotlib or it's for bokeh. If an alias(say 'lw') or full name( say 'linewidth') is passed to the normalized function, we'll get the dealiased name or same full name. Say a kwarg is passed that is not the param of matplotlib, it the normalized function will return it the same.
The error handling for wrong params is done at the backend.
I have modified test to show the desired change. (not valid param get passed on as it is)

CHANGELOG.md Outdated
Comment on lines 19 to 24
* **Experimental Feature**: Added `arviz.wrappers` module to allow ArviZ to
refit the models if necessary
* **Experimental Feature**: Added `reloo` function to ArviZ
* Added new helper function `matplotlib_kwarg_dealiaser` (#1073)
refit the models if necessary (#771)
* **Experimental Feature**: Added `reloo` function to ArviZ (#771)
Copy link
Member

Choose a reason for hiding this comment

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

There have been some issues with merging

kwargs.setdefault("linestyle", kwargs.pop("ls", "none"))
kwargs.setdefault("linewidth", kwargs.pop("lw", _linewidth))
kwargs.setdefault("markersize", kwargs.pop("ms", _markersize))
kwargs.setdefault("linestyle", "none")
Copy link
Member

Choose a reason for hiding this comment

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

kwargs should be dealiased before setting the defaults.

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 must have missed this one.

.. plot::
:context: close-figs

Copy link
Member

@OriolAbril OriolAbril Mar 2, 2020

Choose a reason for hiding this comment

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

I think these black blank lines are important for docs to render properly, could you check all inline example images are shown?

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, there was some problem with blank lines. I checked all examples are working fine now.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks!

@OriolAbril
Copy link
Member

I'll merge if tests pass

@OriolAbril OriolAbril merged commit 0cac8ed into arviz-devs:master Mar 2, 2020
@percygautam percygautam deleted the de-aliaser branch March 2, 2020 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

matplotlib kwarg de-aliasing helper function
2 participants