Improve doc + gridify

Add an `ignore_groups` option to gridify to organize automatically the
plots in different subgroups.
This commit is contained in:
Lucas Verney 2016-03-03 18:09:47 +01:00
parent 2ef75513ed
commit 4a0b27d4a1
3 changed files with 1678 additions and 38 deletions

File diff suppressed because one or more lines are too long

View File

@ -16,54 +16,66 @@ design in the API, or required feature!
<dd>Matplotlib plots are quite ugly by default, colors are not really <dd>Matplotlib plots are quite ugly by default, colors are not really
suited for optimal black and white print, or ease reading for colorblind suited for optimal black and white print, or ease reading for colorblind
people. This module imports and makes use of people. This module imports and makes use of
[Seaborn](https://github.com/mwaskom/seaborn) for saner default params.</dd> [Seaborn](https://github.com/mwaskom/seaborn) for saner default
params.</dd>
<dt>Support `with` statement</dt> <dt>Support <code>with</code> statement</dt>
<dd>Ever got tired of having to start any figure with a call to <dd>Ever got tired of having to start any figure with a call to
`matplotlib.pyplot.subplots()`? This module abstracts it using `with` <code>matplotlib.pyplot.subplots()</code>? This module abstracts it using
statement. New figures are defined by a `with` statement, and are `show`n <code>with</code> statement. New figures are defined by a
automatically (or `save`d) upon leaving the `with` context. <code>with</code> statement, and are <code>show</code>n automatically (or
<code>save</code>d) upon leaving the <code>with</code> context.
<dt>Plot functions</dt> <dt>Plot functions</dt>
<dd>Ever got annoyed by the fact that `matplotlib` can only plot point <dd>Ever got annoyed by the fact that <code>matplotlib</code> can only
series and not evaluate a function _à la_ Mathematica? This module let plot point series and not evaluate a function <em>à la</em> Mathematica?
you do things like `plot(sin, (-10, 10))` to plot a sine function between This module let you do things like <code>plot(sin, (-10, 10))</code> to
-10 and 10, using adaptive sampling. plot a sine function between -10 and 10, using adaptive sampling.
<dt>Order of call of methods is no longer important</dt> <dt>Order of call of methods is no longer important</dt>
<dd>When calling a method from `matplotlib`, it is directly applied to the <dd>When calling a method from <code>matplotlib</code>, it is directly
figure, and not deferred to the final render call. Then, if calling applied to the figure, and not deferred to the final render call. Then, if
`matplotlib.pyplot.legend()` **before** having actually `plot`ted calling <code>matplotlib.pyplot.legend()</code> **before** having actually
anything, it will fail. This is not the case with this module, as it <code>plot</code>ted anything, it will fail. This is not the case with
abstracts on top of `matplotlib` and do the actual render only when the this module, as it abstracts on top of <code>matplotlib</code> and do the
figure is to be `show`n. Even after having called the `show` method, you actual render only when the figure is to be <code>show</code>n. Even after
can still change everything in your figure!</dd> having called the <code>show</code> method, you can still change
everything in your figure!</dd>
<dt>Does not interfere with `matplotlib`</dt> <dt>Does not interfere with <code>matplotlib</code></dt>
<dd>You can still use the default `matplotlib` if you want, as <dd>You can still use the default <code>matplotlib</code> if you want, as
`matplotlib` state and parameters are not directly affected by this <code>matplotlib</code> state and parameters are not directly affected by
module, contrary to what `seaborn` do when you import it for this module, contrary to what <code>seaborn</code> do when you import it
instance.</dd> for instance.</dd>
<dt>Useful aliases</dt> <dt>Useful aliases</dt>
<dd>You think `loc="top left"` is easier to remember than `loc="upper <dd>You think <code>loc="top left"</code> is easier to remember than
left"` in a `matplotlib.pyplot.legend()` call? No worry, this module <code>loc="upper left"</code> in a <code>matplotlib.pyplot.legend()</code>
aliases it for you! (same for "bottom" with respect to "lower")</dd> call? No worry, this module aliases it for you! (same for "bottom" with
respect to "lower")</dd>
<dt>Automatic legend</dt> <dt>Automatic legend</dt>
<dd>If any of your plots contains a `label` keyword, a legend will be <dd>If any of your plots contains a <code>label</code> keyword, a legend
added automatically on your graph (you can still explicitly tell it not to will be added automatically on your graph (you can still explicitly tell
add a legend by setting the `legend` attribute to `False`).</dd> it not to add a legend by setting the <code>legend</code> attribute to
<code>False</code>).</dd>
<dt>Use `LaTeX` rendering in `matplotlib`, if available.</dt> <dt>Use <code>LaTeX</code> rendering in <code>matplotlib</code>, if
<dd>If `replot` finds `LaTeX` installed on your machine, it will overload available.</dt>
`matplotlib` settings to use `LaTeX` rendering.</dd> <dd>If <code>replot</code> finds <code>LaTeX</code> installed on your
machine, it will overload <code>matplotlib</code> settings to use
<code>LaTeX</code> rendering.</dd>
<dt>Handle subplots more easily</dt> <dt>Handle subplots more easily</dt>
<dd>**TODO**</dd> <dd>Have you ever struggled with <code>matplotlib</em> to define a subplot
grid and arrange your plot? <code>replot</code> lets you describe your
grid visually using ascii art!</dd>
<dt>"Gridify"</dt> <dt>"Gridify"</dt>
<dd>**TODO**</dd> <dd>You have some plots that you would like to arrange into a grid, to
compare them easily, but you do not want to waste time setting up a grid
and placing your plots at the correct place? <code>gridify</code> method
just does it for you!</dd>
</dl> </dl>

View File

@ -155,7 +155,7 @@ class Figure():
"Invalid grid provided. You did not use rectangular areas " + "Invalid grid provided. You did not use rectangular areas " +
"for each group.") "for each group.")
def gridify(self, height=None, width=None): def gridify(self, height=None, width=None, ignore_groups=False):
""" """
Apply an automatic grid on the figure, trying to fit best to the \ Apply an automatic grid on the figure, trying to fit best to the \
number of plots. number of plots.
@ -169,7 +169,22 @@ class Figure():
:param height: An optional ``height`` for the grid. :param height: An optional ``height`` for the grid.
:param width: An optional ``height`` for the grid. :param width: An optional ``height`` for the grid.
:param ignore_groups: By default, ``gridify`` will use groups to \
organize plots in different subplots. If you want to put \
every plot in a different subplot, without dealing with \
groups, you can set this to ``True``.
""" """
if ignore_groups:
# If we want to ignore groups, we will start by creating a new
# group for every existing plot
existing_plots = []
for group_ in self.plots:
existing_plots.extend(self.plots[group_])
self.plots = collections.defaultdict(list,
{chr(i): [existing_plots[i]]
for i in
range(len(existing_plots))})
# Find the optimal layout # Find the optimal layout
nb_groups = len(self.plots) nb_groups = len(self.plots)
if height is None and width is not None: if height is None and width is not None: