I'm looking to have a main image upon which I draw either spirals, ellipses etc with variables that change the shape on the imposed drawing. The main image also needs to have a contrast variable.
My code currently looks like this;
###############################################BASIC FIGURE PLOT####################################
plt.figure(figsize=(24,24))
@interact
def spiral(Spiral=False,n=2000,x1=50,y1=50,z1=50,k1=300):
if Spiral == False:
x = 0;
y = 0;
plt.scatter(x,y,s = 3, c = 'black');
else:
angle = np.linspace(x1,y1*1*np.pi, n)
radius = np.linspace(z1,k1,n)
x = radius * np.cos(angle) + 150
y = radius * np.sin(angle) + 150
plt.scatter(x,y,s = 3, c = 'black');
@interact
def contrast(vuc=(0.2,1,0.01),vlc=(0.1,1,0.01)):
vu = np.quantile(qphi, vuc);
vl = np.quantile(qphi, vlc);
print("upper =",vu, " lower=",vl);
plt.imshow(qphi, origin='lower',vmin=vl,vmax=vu);
plt.show()
This produces two plots; visible here One plot which creates a spiral I can edit freely and one plot that is the main image with variable contrast.
Any advise on how to combine the two plots would be much appreciated; Thank you!
There are several ways to approach controlling a matplotlib plot using ipywidgets. Below I've created the output I think you're looking for using each of the options. The methods are listed in what feels like the natural order of discovery, however, I would recommend trying them in this order:
4, 2, 1, 3
Approach 1 - inline backend
If you use
%matplotlib inline
then matplotlib figures will not be interactive and you will need to recreate the entire plot every timeApproach 2 - interactive backend + cla
You can use one of the interactive maptlotlib backends to avoid having to completely regenerate the figure every time you change. To do this the first approach is to simply clear the axes everytime the sliders change using the
cla
method.This will work with either
%matplotlib notebook
or%matplotlib ipympl
. The former will only work in jupyter notebook and the latter will work in both jupyter notebook and juptyerlab. (Installation info for ipympl here: https://github.com/matplotlib/ipympl#installation)Approach 3 - interactive backend + set_data
Totally clearing the axes can be inefficient when you are plotting larger datasets or have some parts of the plot that you want to persist from one interaction to the next. So you can instead use the
set_data
andset_offsets
methods to update what you have already drawn.Approach 4 - mpl_interactions
Using
set_offsets
and equivalentset_data
will be the most performant solution, but can also be tricky to figure out how to get it work and even trickier to remember. To make it easier I've creted a library (mpl-interactions) that automates the boilerplate of approach 3.In addition to being easy and performant this has the advantage that you aren't responsible for updating the plots, only for returning the correct values. Which then has the ancillary benefit that now functions like
spiral
can be used in other parts of your code as they just return values rather than handle plotting.The other advantage is that mpl-interactions can also create matplotlib widgets so this is the only approach that will also work outside of a notebook.