I am building a webapp with interactive plots based on Jupyter and Voila.
Inside the notebook I use ipywidgets for handling the interactivity and %matplotlib widget
backend so I can update my plots without redrawing the whole figure (does not work in %matplotlib inline
and %matplotlib notebook
does not render in Voila).
My problem is that I am not able to set figure size such that it matches the size of its canvas or container which neatly resize automatically on window resize.
This is a small working example of my situation:
%matplotlib widget
from IPython.display import display
import matplotlib.pyplot as plt
import ipywidgets as widgets
import numpy as np
# Output widget that will contain the figure
out = widgets.Output(layout = {
'border': '1px solid black',
# 'width': '100%' # Not needed and does not help
})
# Initializing the figure within out
with out:
fig, ax = plt.subplots(1, constrained_layout=True)
fig.set_size_inches(7,5) # Is not automatic and stays the same on window resize
fig.canvas.layout.border = '1px solid red'
# fig.canvas.layout.width = '100%' # Not needed and does not help
# Func for updating the data in ax within out
def update_ax(slider):
with out:
plt.cla() # Clearing the ax
ax.plot(np.arange(10), np.random.random(10)* slider)
slider = widgets.FloatSlider(10)
display(slider)
iplot = widgets.interactive(update_ax, slider=slider)
iplot.update()
display(out)
I want the figure (blue rectangle) to span 100% width of the canvas (red rectangle) and I want it resized automatically as the canvas width changes with the change of output container (black rectangle) which changes with the change of window width. E.g. when I manually resize the window.
I think it must be possible, since the corner (in green circle) does the resizing, but just based on manual user input, not on window width change. Nice solution would be something like this 'fig.set_size_relative('100%', 'auto')', but this obviously is not implemented.
Any help is very appreciated, I have already killed way more time with this than it is healthy :)