Mpl_interactions: set initial/default values of sliders

@ianhi Thanks a lot for such great package for a non-gui user to quickly make simple code working for my projects.

I would like to set the default or initial values to set the sliders before its values have been changed manually. For example. how do I set the tau to have an initial value of 5 and also the slider is set to 5.

Thanks a lot for the help!

tau = np.linspace(0.5, 10, 100)

def f1(tau):
return np.sin( tau)

fig, ax = plt.subplots()
controls = iplt.plot(x, f1, tau=tau)

I figured that the crude way to do it would be np.insert the initial value to the beginning of the array, tau. Any better way would be appreciated.

Also, if I need to return two sets of values from function f1, then I have problem. For example:
def f1(tau):
ret_2 = “some number calc in f1”
return np.sin( tau), ret_2

fig, ax = plt.subplots()
controls = iplt.plot(x, f1()[0], tau=tau)

then tau will be sent into f1 as an array instead a single number.

And I realized that iplt.plot(x, f1+f2,…) will also failed since only one function name is expected there. Did I miss something?

hi @dukeja, glad to hear it’s useful to you!

Unfortunately you’ve hit on one of the rough spots in the library, as there isn’t a super great way to do what you want at the moment. You see more detailed thoughts on this here: Easier method to programmatically change the current param value · Issue #183 · ianhi/mpl-interactions · GitHub

There are some other hacky workarounds where you can directly access the underlying widget, but they differ depending on if you’re using matplotlib or ipywidgets sliders.

For returning two values can you explain a bit more what you want to do? Are you trying to return both the x and y values, or the function just returns two separate things?

For the former option you can accomplish that using the parametric=True argument example here: Visualizing the Lotka-Volterra Model — mpl-interactions

@ianhi Thanks a lot for the reply.

For my 2nd question, I would like to get an 2D array (image) and some parameter(s) (such as a normalization scaling facto only known after the execution of f1) out. Currently I have to duplicate the definition of f1 and one returns image and the other for additional return value.

In your reply, that example is easier since they are two same-size array. But my situation needs an 2D array and one or a few scalars.

Thanks!

Puck

Can you give a concrete minimal example (i.e. no data need just generating fake images) that I can mess around with?

I think what you want is possible but will be easier to explain with an example

While I was working on an example for you, I realized my problem can be solved simply by making those parameters global.

An simple example is shown below, the idea was to send the variable “factor” along with the 2D array.

Example -----------------------------------

import numpy as np
import matplotlib.pyplot as plt
import mpl_interactions.ipyplot as ipl

import mpl_interactions.ipyplot as iplt

def Gauss_2D(x, y, A, x0, y0, std):
    g2d= A * np.exp( -0.5*((x-x0)/std)**2 -.5*((y-y0)/std)**2)
    return g2d

# p1: baseline
dx = 100
x = np.linspace(-(dx+1)//2, (dx+1)//2, dx)
y = np.linspace(-(dx+1)//2, (dx+1)//2, dx)
xx, yy = np.meshgrid(x, y)

p1 = np.zeros_like(xx, dtype = np.uint8)
p2 = np.zeros_like(xx, dtype = np.uint8)
factor =1.

# Interactive
def chg_mix(s1, s2):
    global factor
    p1 = Gauss_2D(xx,yy, 300, 0, 0, 50)
    p2 = Gauss_2D(xx,yy, 50, s1, s2, 10)

    combo = np.zeros_like(p1, dtype = float)
    combo = p1 + p2
    print(f'combo max before scaling: {combo.max():.1f}')
    factor =  255./ combo.max() 
    combo *= factor
    print(f'scaling factor: {factor:.2f}, combo max after scaling: {combo.max():.1f}')

    #return (combo, factor)
    return combo.astype(dtype=np.uint8)

def pp(s1, s2):
    global factor
    p3 = (Gauss_2D(xx,yy, 300, 0, 0, 50)+Gauss_2D(xx,yy, 50, s1, s2, 10))*factor
    print(f'p3 max: {p3.max()}')
    return p3[dx//2, :]
    
# Plotting Final results
s1=np.arange(0.,50.)
s2=np.arange(0.,50.)

plt.figure(figsize=(10,5))
ax1=plt.subplot(121)
ctrl = iplt.imshow(chg_mix, ax=ax1,
        s1=s1,
        s2=s2,
        )        
ax2=plt.subplot(122)
iplt.plot(pp, controls = ctrl, ax=ax2)

plt.show()
plt.tight_layout()