1

I am working on a Jupyter Notebook and I am using the following ipywidget to set a threshold value:

Thr = widgets.IntSlider(value=-17, min=-30, max=-13, step=1, description='Threshold: ', disabled=False, continuous_update=True, orientation='horizontal', readout=True, readout_format='d')
Thr

Next, I am masking a numpy array using that value with:

import numpy.ma as ma
test= ma.masked_less_equal(S_images[0], Thr.value)

And finally I plot the result with:

plt.figure(figsize = (15,15))
plt.imshow(test[0], cmap='gray')

The ipywidget is in a different Jupyter cell than the other code so when I change the value of Thr I have to manually run again the cell where the masking and ploting takes place.

My question is: I have always seen those interactive plots where you change a parameter (in my case the ipywidget Thr) and automatically the plot gets updated.

I see that widgets.IntSlider has a continuous_update parameter which seems to be close to what I want but still cannot get the behaviour I want.

Any idea if this is doable or possible?

_ EDIT _

Starting from the comment of ac24, I am adapting the example he proposes:

from IPython.display import display, clear_output
import ipywidgets as ipy
import matplotlib.pyplot as plt
import numpy as np

# setup figure
n = 10

out = ipy.Output()

# show random mesh
def update(idx):
    with out:
        clear_output()
        fig, ax = plt.subplots(figsize = (5,5))
        h = ax.imshow(S_images[0]) # here I put my image
        h.set_data(np.ma.masked_less_equal(S_images[0], slider.value)) # here I set the task to masked accordint to the `slider.value`
        fig.canvas.flush_events()
        fig.canvas.draw()
        plt.show()

slider = ipy.IntSlider(min = 0, max = 10, orientation = 'vertical')
widget = ipy.interactive(update, idx = slider)

layout = ipy.Layout(
#     display = 'flex',
#                    flex_flow = 'row',
#                    justify_content = 'space-between',
#                    align_items = 'center',
                   )
widgets = ipy.HBox(children=(slider, out), layout = layout)
display(widgets)

The example works very nice and is just what I was looking for. However, I have a small question regargind the layout. Originally I am working with 3 Images so I would like to have them displayed as follows, each one with its slider next to it to do the task: (the image below is not real, just made it up to represent what I would like)

enter image description here

EDIT 2

in this occasion, the question is, once I select a value in the slider, I would write to geotiff that raster. For this I am using the following code:

with rasterio.open('/Path/20190331_VV_Crop') as src:
    ras_meta = src.profile

with rasterio.open('/path/Threshold.tif', 'w', **ras_meta) as dst:
    dst.write(X)

However, I am not sure how to reference the numpy array in dst.write(X)

2
  • There is a simple example here in another question (stackoverflow.com/questions/58556700/…). It should give the basics of the interact function and how to display the chart. The continuous_update parameter provides some different functionality, experiment with it in my example and see if you can figure out how it works. Commented Oct 25, 2019 at 15:29
  • @ac24 many thanks for the comment. If you add it as an answer I will be happy to accept it. I just have a small remark on the layout. I have edited my question to add the question. Could you comment on it? Commented Oct 28, 2019 at 10:20

1 Answer 1

4

I've adapted the example I gave into a class, as you want to link a specific output and slider instance, but create multiple groups of them. Setting the layout of the output widget avoids the widget resizing all the time as you slide the slider.

from IPython.display import display, clear_output
import ipywidgets as ipy
import matplotlib.pyplot as plt
import numpy as np

# setup figure
n = 10

class SliderAndImage():

    # show random mesh
    def update(self, idx):
        with self.out:
            clear_output()
            fig, ax = plt.subplots(figsize = (5,5))
            h = ax.imshow(np.random.rand(n, n))
            h.set_data(np.random.rand(n, n))
            fig.canvas.flush_events()
            fig.canvas.draw()
            plt.show()

    def make_slider_and_image(self):

        self.out = ipy.Output(layout=ipy.Layout(width='200px', height='200px'))

        slider = ipy.IntSlider(min = 0, max = 10, orientation = 'vertical')
        widget = ipy.interactive(self.update, idx = slider)

        layout = ipy.Layout(
        #     display = 'flex',
        #                    flex_flow = 'row',
        #                    justify_content = 'space-between',
        #                    align_items = 'center',
                           )
        widgets = ipy.HBox(children=(slider, self.out), layout = layout)
        return widgets

children = []
for _ in range(3):
    widgets = SliderAndImage()
    children.append(widgets.make_slider_and_image())
display(ipy.HBox(children))

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

great example for interactive plotting. Many thanks
I have edited the question to add a small related question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.