Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to apply @param.depends to all (nested) Parameters of a class #910

Open
samimia-swks opened this issue Feb 11, 2024 · 1 comment

Comments

@samimia-swks
Copy link

samimia-swks commented Feb 11, 2024

I am developing a framework using param that aids engineers (who are not so savvy in Python) in defining 'constants' and associated metadata related to an engineering design. The engineer user would a simple python Parameterized class to organize these constants, and the framework goes through the class, and generates files for another tool that needs to consume these 'constants'.

The hierarchy is something like this:

# part of the framework
class Constant(param.Parametrized):
    val = param.Integer()
    metadata = param.String()
    ....

# written by engineer A
class ModuleConstants(param.Parametrized):
    constX = param.ClassSelector(default=Constant(val = 10, metadata = "xxx"), class_=param.Parameterized)
    constY = param.ClassSelector(default=Constant(val = 20), class_=param.Parameterized)

    @param.depends('constX.val', watch=True)
    def update_derived(self):
        self.constY.val = self.constX.val * 2

# written by engineer B
class TopConstants(param.Parametrized):
    const1 = param.ClassSelector(default=Constant(val = 2), class_=param.Parameterized)
    const2  = param.ClassSelector(default=Constant(val = 4), class_=param.Parameterized)
    child = param.ClassSelector(default=ModuleConstants(), class_=param.Parameterized)

    @param.depends('const1.val', watch=True)
    def update_derived(self):
        self.child.constX.val = self.const1.val + 10

t = TopConstants()
t.const1 = 100 
print(t.child.constY) # we expect (100 + 10) * 2 = 220

So there could be an unlimited number of nested Constant parameters here, and there are dependencies between the val parameter of the Constant parameters at different levels of hierarchy.

The problem we have been running into is that because we could have tens of these Constant parameters defined, it's very easy to forget for the engineers to include the list of dependencies in the @param.depends decorator. What I want is for update_derived() to be called if any of the Constant.val integers change, regardless of how many levels deep the Constant is nested. Performance is really not an issue here so I don't mind all the redundant operations this would cause. There are no circular dependencies to worry about.

I am only slightly better at python than these forgetful engineers myself, and I have been unsuccessful in working around this issue. I have tried:

  • .param.watch() (lower level API): doesn't support nested parameters?
  • Dynamic parameters and the 'pull' model: doesn't supported nested parameters
  • Programmatically decorating update_derived() with something like this in __init__() of TopConstants, where list_of_all_params is obtained by manipulation of the .param.values() dict:
def __init__(self, **kwargs):
    super().__init__(**kwargs)
    self.update_derived = param.depends(*list_of_all_params, watch=True)(self.update_derived) 

This compiles but doesn't seem to register a watcher.

  • Reactive Expressions: the documentation shows how to create an expression from two parameters, but not how to assign that back to another parameter

I am wondering if there is a solution here or if this (admittedly weird) use case is unsupported.

@samimia-swks samimia-swks changed the title Ability to watch parameters on mass Ability to apply @param.depends to all Parameters of a class Feb 11, 2024
@samimia-swks samimia-swks changed the title Ability to apply @param.depends to all Parameters of a class Ability to apply @param.depends to all (nested) Parameters of a class Feb 11, 2024
@samimia-swks
Copy link
Author

any pointers here folks?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant