Need help linking a pn.widget.Select and a pn.widget.MultiSelect (or for the later to watch the change in the former)

Hello,
I am new in Panel and am trying to learn by working on a project and reading the user guide. I am stuck at linking events and creating a watch functions and hope to be able to get some help.

I have successfully created a file upload widget that allows me to upload an excel sheet that is read by pandas as a dataframe.
I then make some groupby and selection and create a list that I feed as options to the pn.widget.Select

I then filter the dataframe with the value that is selected above and feed the elements of another column of the dataframe that pass the filter, to the pn.widget.MultiSelect

I now need to establish the link such that the MultiSelect options get updated based on the selection on the Select and don’t know how to.

here are the stuff I have. after loading the uploaded file to a dataframe called “tops”:

tops.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 630 entries, 0 to 629*
Data columns (total 6 columns):
 #   Column   Non-Null Count  Dtype  

0   Well     630 non-null    object 
1   Surface  630 non-null    object 
2   X        630 non-null    float64
3   Y        630 non-null    float64
4   Z        630 non-null    float64
5   MD       630 non-null    float64
dtypes: float64(4), object(2)
----
wells=tops['Well'].unique() #to get unique well values
numoftops=tops.groupby('Well').Surface.count().sort_values(ascending=False)[:10] #to find the wells with most numbers of Surfaces
----
mosttops = [w for w in wells if w in numoftops] #list of wells to be displayed in Select
----
well_select=pn.widgets.Select(name='Select Reference well (will be used as Top order and name Ref', options=mosttops)
----
top_select=pn.widgets.MultiSelect(name='Tops (use ctrl key for multi select)', 
              
 value=list(tops[tops.Well==well_select.value].sort_values(by='Z',ascending=False)'Surface']),
               
options=list(tops[tops.Well==well_select.value].sort_values(by='Z',ascending=False)['Surface']),
                                  
size=(int(len(list(tops[tops.Well==well_select.value].sort_values(by='Z',ascending=False)['Surface']))*0.70)))**

Would love to hear where your pain-points are in learning this. If you don’t want to jump down the rabbit whole of writing a Parameterized class then the easiest way is simply to set up watchers using the .param.watch API:

well_select=pn.widgets.Select(name='Select Reference well (will be used as Top order and name Ref', options=mosttops)
top_select=pn.widgets.MultiSelect(name='Tops (use ctrl key for multi select)')

def update_top_select(event=None):
    options = list(tops[tops.Well==well_select.value].sort_values(by='Z',ascending=False)['Surface'])
    top_select.param.update(options=options, value=options, size=int(len(options)*0.7))

well_select.param.watch(update_top_select, 'value')
update_top_select()

Thank you very much for taking the time to help me with this. This is indeed an elegant solution and something I can understand with my level of skills. I was trying to imitate the example on link and watch in the Panel documentation page but could not really put two and two together as how to make the connection work.

one last question: what would the (event=None) do in the function definition. In which case would you specify an event for a call back function?

I have a bunch more of these that I need to generate for this app requiring plotly charts to send call pack and generate dataframe filters. Distance calculator functions with sliders as input widgets that can then create a filter that would act upon the chart and a pandas.dataframe.describe table that would come blow it.
I hope I can accomplish these but what you showed. Thanks very much again