Use of tab deactivates trigger

This is my stylized code:

import panel as pn
import param

pn.extension()

class ParkLab(param.Parameterized):

StartTime1_s = param.Number(0.000, step=0.001, precedence=0)
UpdateGraphsTrigger = param.Integer(default=0)

@pn.depends(ParkLab.param.UpdateGraphsTrigger)
def updateGraphs(i):

print(‘updateGraphs:’, i)
#tabs = pn.Tabs((‘Beginning’, pn.pane.Markdown(‘Test’)),(‘StartTime1_s’, ParkLab.param.StartTime1_s))
tabs = pn.pane.Markdown(‘Test’)
return tabs

caption = pn.pane.Markdown(‘Portal’, width=450)
Cp = pn.Column(caption, ParkLab.param.UpdateGraphsTrigger, updateGraphs)
Cp

Please note the one commented out #tabs and the ‘tabs’ without comment.

Desired behavior: when I modify UpdateGraphsTrigger by clicking on the box for example on the up arrow, updateGraphs is run and this is shown e.g., because it prints

When just the Markdown(‘Test’) is returned by updateGraphs, this is what happens.

But if you uncomment the pn.Tabs statement and comment the one with pn.pane, then updateGraphs is not called when I modify UpdateGraphsTrigger.

How can this be? How can I fix this?

Thanks for the questions, please use triple backticks (i.e. ```) around your code in future.

It’s really not clear to me what you’re trying to achieve here, however if you’re going to be writing classes you should probably go all the way and use methods too:

import panel as pn
import param

pn.extension()

class ParkLab(param.Parameterized):

    StartTime1_s = param.Number(0.000, step=0.001, precedence=0)
    UpdateGraphsTrigger = param.Integer(default=0)

    @pn.depends('UpdateGraphsTrigger')
    def updateGraphs(self):
        return pn.Tabs(('Beginning', pn.pane.Markdown('Test')),
                       ('StartTime1_s', self.param.StartTime1_s))

lab = ParkLab()
caption = pn.pane.Markdown('Portal', width=450)
pn.Column(caption, lab.param.UpdateGraphsTrigger, lab.updateGraphs)

That being said even this is a really weird pattern. If you find yourself returning entire layouts from some function or method you’re usually doing something wrong. So really I’d like more of a description of what you’re trying to achieve here so I can provide some more detailed advice on how to structure your code.

Thank you. My reply is late as I was pulled into something else.

I am not so sure your code works, but I must say I am confused. This is what I have tried:

  1. Everything in the class as per your suggestion.
import panel as pn
import param

pn.extension()

class ParkLab(param.Parameterized):
    StartTime1_s = param.Number(0.000, step=0.001, precedence=0)
    UpdateGraphsTrigger = param.Integer(default=0)  
    
   
    @pn.depends('UpdateGraphsTrigger')
    def updateGraphs(self):
        print('updateGraphs:', self.UpdateGraphsTrigger)
        #return pn.Tabs(('Beginning', pn.pane.Markdown('Test ' + str(self.UpdateGraphsTrigger))),
        #               ('StartTime1_s', ParkLab.param.StartTime1_s))
        return pn.pane.Markdown('Test ' + str(self.UpdateGraphsTrigger)) 

lab = ParkLab()
caption = pn.pane.Markdown('Portal', width=450)
pn.Column(caption, ParkLab.param.UpdateGraphsTrigger, lab.updateGraphs)

The print statement is only executed once and the Markdown that generates 'Test ’ + str(self.UpdateGraphsTrigger) never changes (text on screen always stays at ‘Test 0’, even when the UpdateGraphsTrigger has been modified and shows a different number in its own control). Does the text ‘Test 0’ change when you run the code and manually modify the UpdateGraphsTrigger (even when no tabs are used)? Or is there something I do wrong?

  1. Back to my old code with the trigger outside of the class
import panel as pn
import param

pn.extension()

class ParkLab(param.Parameterized):
    StartTime1_s = param.Number(0.000, step=0.001, precedence=0)
    UpdateGraphsTrigger = param.Integer(default=0)

@pn.depends(ParkLab.param.UpdateGraphsTrigger)
def updateGraphs(i):
    print('updateGraphs:', i)
    #tabs = pn.Tabs(('Beginning', pn.pane.Markdown('Test '+ str(i) )),('StartTime1_s', ParkLab.param.StartTime1_s))
    tabs = pn.pane.Markdown('Test ' + str(i))
    return tabs

caption = pn.pane.Markdown('Portal', width=450)
pn.Column(caption, ParkLab.param.UpdateGraphsTrigger, updateGraphs)

Now, irrespective of whether I use tabs or not, the ‘Test 0’ changes when I change the UpdateGraphsTrigger. But when I don’t use tabs, the print statement is executed repeatedly but when I use tabs, it only prints once.

Yes, putting everything in the class is better. This was a holdover from something that previously did not work when I put it inside the class and I just had not wanted to put in the time to figure out why not. As you can see from the new example in this reply, there are still differences when you put a function as a method to a class vs when you put it separately (as far as I can tell).

As to the design pattern: advice is more than welcome. I actually have a more involved user interface. See attached picture.

The goal is to visualize 2 sets of time series of data which is held in csv files. I used to do this with VBA in excel but the code had become unreadable and slow because of the large volume of data to be handled.

These csv files are organized in a directory tree. Users can select subdirectories using a combination of the location field and the file field. In addition, for each such subdirectory, the time axis of the graphs must be shifted (to synchronize with video) and the amount of the shift can be indicated in Timing Offset. Finally, for both locations, up to 7 additional graphs can be displayed and the user can select which ones with the last row of UI elements (which is used for both location/file patterns selected). These 7 are grouped in 2 groups (PD and ACC).

The buttons on the right are to save the configuration (mainly the timing offset but also which graphs have been selected) and to update the parameters Timing Offset and selected graphs (per your suggestion in another question I asked on this forum).

So, when a user updates a parameter such as the Timing Offset (or any of the others), the graphs need to be re-drawn.

Currently, I use all params to return updated holoviews graphs to panel, similar to the stylized code I submitted. I have a class that holds the data from the csv files and then the visualization class.

What would be a better design pattern to do so?

Any ideas re. how to do this better would be appreciated.