1

1)This is the code snippet that I am trying to run.The main idea is that, I want the ipywidgets to be interactive, while the data is constantly being fetched from the data source. And the data is being updated at certain interval using the while loop.The objective is to plot the principal components interactively by changing the number of principal components(PC) to be considered, using the @interact function. Also it runs perfectly fine without while loop, that is, when we are not considering the auto-update for the dataset, with the while loop. But when I include the while loop, it doesn't handle the interactive-ness of the widgets(that is, the interaction of the number of PC). My feeling is that "while True" loop does not let the interaction of ipywidget to happen, due to some execution issue.

2) Also I looked into threading but i am unsure of how to use the fucntion which is in functools(select_data), be called using threading.Thread.

Any sort of help would be appreciated. Thanks

def data_import_date(start_date,end_date):
    end_date1=end_date.strftime('%Y-%m-%dT%H:%M:%S')
    start_date=pd.Timestamp(start_date)
    end_date=pd.Timestamp(end_date1)

    button=widgets.Button(description='Pull Data')
    button.on_click(functools.partial(select_data,rs_=[start_date,end_date]))

    vbox=widgets.VBox([button])
    display(vbox,out)


def select_data(b,rs_):
#     clear_output()
    start_date=rs_[0]
    end_date1=rs_[1]
    print("Data pulling started")

    with out:
        clear_output()
        seeq_login() 
        [item1,item2]=query_seeq_for_data()
        i=0
        while True:
            end_date=end_date1.strftime('%Y-%m-%dT%H:%M:%S')
            print("Start & End date: ",start_date,end_date)
            if i==0:
                [X_data,Y_data]=pull_data(item1,item2,start_date,end_date)
            else:
                [X_data_live,Y_data_live]=pull_data(item1,item2,start_date,end_date)
                X_data=X_data.append(X_data_live)
                Y_data=Y_data.append(Y_data_live)
            print("Data pulling completed.\nNow you're ready for your analysis")

            clear_output()
            [X_train,X_test,Y_train,Y_test]=train_test(X_data,Y_data)

            [Xp_train,components,explained_variance_ratio,_,_]=apply_PCA(X_train,X_test)
            plot_PC_variance(X_data,explained_variance_ratio)
            plot_PC(X_data,components)

            time.sleep(20)
            start_date=end_date
            end_date1=end_date1+datetime.timedelta(days=1)
            i+=1



  a=interact(data_import_date,
           start_date=widgets.DatePicker(value=pd.to_datetime(start_date)),
           end_date=widgets.DatePicker(value=pd.to_datetime(end_date)))


def plot_PC(X_data,components):
    Np_comp=(1,len(X_data.columns),1)
    @interact
    def principal_components(PC1=Np_comp,PC2=Np_comp):
        fig,ax=plt.subplots(1,1,figsize=(10,10))
        plt.figure(5)
        print(PC1, PC2)

        ax.set_xlabel("Principal Component {}".format(PC1), fontsize=14)
        ax.set_ylabel("Principal Component {}".format(PC2), fontsize=14)
        ax.set_title("Principal components {0} & {1}".format(PC1,PC2), fontsize=(20))
        ax.scatter(components[:,PC1],components[:,PC2])
  • 1
    You are correct, the while loop is blocking any changes from widgets. You will need to look into async widgets implementation: https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Asynchronous.html – ac24 May 15 '20 at 09:32
  • @ac24, can you please elaborate more on the implementation aspect of this? I have gone through the documentation multiple times, but I am facing trouble to make the changes in the code. – parth prasoon May 19 '20 at 10:23

1 Answers1

1

A fairly rudimentary example that shows how you can run a loop whilst polling for widget changes, but it's not really my area of expertise.

Drag the slider whilst the values are printing and you should see the printed value change to reflect current slider position.


import threading
from IPython.display import display
import ipywidgets as widgets
import time
float_val = widgets.FloatSlider()
display(float_val)

def work(progress):
    total = 10
    for i in range(total):
        time.sleep(1)
        print(float_val.value)

thread = threading.Thread(target=work, args=(progress,))

thread.start()
ac24
  • 5,325
  • 1
  • 16
  • 31
  • I understand what you tried to work around. But if you look into my code, I would be interested in using the target fucntion in threading.Thread to be select data function. But it;s already called using button.on_click? – parth prasoon May 29 '20 at 05:33