Open alexander-held opened 3 years ago
As of 5ed199a, functions returning a single figure cause them to be rendered twice when called as the last line in a notebook cell. The reason is the following I believe:
matplotlib
inline backend looks for any figures that pyplot
knows about (plt.get_fignums()
), renders them to png, Base64 encodes them, puts that into the notebook (which makes the figure show up) and then closes all figures (presumably plt.close("all")
). This rendering will always happen for any figures that are still open, which is the default behavior in cabinetry
as of this commit.visualize.pulls
which produce a single figure.Functions producing multiple figures are not affected by this duplication, since the return value is a dict
and that will not render the functions it contains.
To solve duplication, there are the following options:
...
visualize.pulls(...)
fig = visualize.pulls(...)
...
fig
visualize.pulls(..., close_figure=True);
or
_ = visualize.pulls(..., close_figure=True)
The downside of this approach is that visualize.data_mc
and visualize.templates
would still not have figure closing enabled by default and thereby behave differently. The advantage is that the easiest use case of just calling the single-figure-producing functions without thinking about return values or optional arguments "just works" correctly, and the multi-figure functions also work (via a different method).
Make figure closing default for all functions, including multi-figure functions. Rendering of multi-figure functions could then be achieved via a small helper function:
from IPython.display import display
def display_helper(fig_list_dict):
for fig_dict in fig_list_dict:
display(fig_dict["figure"])
This could be called on return values of visualize.data_mc
and visualize.templates
to show all figures at once, even if they already have been closed.
_repr_html_
defined to manually handle things (see hist
example). This is similar to the suggestion from #163.A reasonable short term solution seems to be to close figures from single-figure functions by default. There are multiple ways for them to still be rendered anyway. Multi-figure functions can stay open by default, so all figures are also rendered there. In the longer term a more unified solution could be useful. Feedback from analyzers using cabinetry
in notebooks is very welcome!
Examples of editing a data/MC figure (experiment labels, axis labels, removing existing text on the figure and replacing it): https://gist.github.com/alexander-held/2ca63e4c4c3de2114bf8d903bf28bb4a
edit: now also includes an example for how to add a normalized signal (and re-do the legend)
This collects information regarding changes in the
cabinetry
visualization API, and is a follow-up to #251.250 made
matplotlib
a core dependency and refactored the plotting code.264 made functions in the
visualize
module return figures (or a list of dictionaries with figures)267 changed
visualize.data_mc
to take a model prediction object instead of a model, and added a newchannels
keyword argument271 fixed duplicate display of figures from functions returning figures (instead of lists of dicts) in notebooks (see also https://github.com/alexander-held/cabinetry/issues/265#issuecomment-907621136 below)
399 added support for custom histogram colors for data/MC plots
Outstanding items and open questions (including pieces from #381):
visualize.plot_model
andvisualize.plot_result
, and those functions should then likely return artists. Calling these functions directly comes with a loss in convenience, e.g. the correlation matrix pruning threshold. Could consider factoring out the convenience functions? Handing axes to thevisualize
-level functions is more challenging, since several of these can return multiple figures (and the exact number is not easily known forvisualize.templates
).visualize.templates
(figures still kept around even withclose_figure=True
as long as reference to them exists).to get a custom color scheme. (from #381)