[Python] Sharing parameters of composed holoview/param Parameterized classes

Discussão em 'Python' iniciado por Stack, Março 3, 2025.

  1. Stack

    Stack Membro Participativo

    I am still quite new to the holoviz/param library. The documentation has a lot of contents and already proved helpful. I tried to solve a problem and I am not so sure if what I did is good or bad practice.

    The problem

    I wish to define a complex model with nested objects. In our example, we have one lower-level object Geometry and one high-level object Figure with a nested geometry. The goal is to have two Figures instance with the following constraints:

    • Figure.resolution should be independant across all instances
    • Figure.alpha should be shared across all instance
    • Geometry.shape should be independant across all instances
    • Geometry.color should be shared across all instance

    The following figure illustrate what should be the result in panel (note: summary is a reflection of the Figure's instance state)

    [​IMG]

    The current solution

    To solve the problem, I relied on the feature allowing parameters to be shared as reference. In the case of the alpha parameter, I directly referenced the class parameters so it is effectively shared across all instances. For the color parameter, I had to instanciate the first Figure, give its parameter to the second Figure, and then hide the referred parameter from panel.

    from enum import Enum, auto
    import os
    import param as pm
    import panel as pn
    pn.extension()

    class Colors(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

    class Shapes(Enum):
    CIRCLE = auto()
    SQUARE = auto()

    class Geometry(pm.Parameterized):
    color = pm.Selector(objects=list(Colors), allow_refs=True, precedence=-1)
    shape = pm.Selector(objects=list(Shapes))

    class Figure(pm.Parameterized):
    geometry = pm.Parameter(Geometry(), precedence=-1)
    resolution = pm.Selector(objects=[10, 20, 30])
    alpha = pm.Number(default=0, step=0.1, allow_refs=True)
    summary = pm.String()

    @pm.depends('geometry.color', 'geometry.shape', 'resolution', 'alpha', watch=True)
    def update(self):
    self.summary = f'{self.geometry.shape.name}_{self.geometry.color.name}_{self.name}_{self.alpha}_{self.resolution}.png'

    reference = Geometry()
    refered = Geometry(color=reference.param.color)

    fig_left = Figure(name='Left Object', geometry=reference, alpha=Figure.param.alpha)
    fig_right = Figure(name='Right Object', geometry=refered, alpha=Figure.param.alpha)

    pn.Row(
    pn.Param(fig_left, expand=True, expand_button=False, parameters=['resolution', 'geometry', 'summary'], expand_layout=pn.Column),
    pn.Column(
    pn.Param(Figure, parameters=['alpha'], name='Shared alpha'),
    pn.Param(reference, parameters=['color'], name='Shared color', display_threshold=-1)),
    pn.Param(fig_right, expand=True, expand_button=False, parameters=['resolution', 'geometry', 'summary'], expand_layout=pn.Column)
    )


    The question

    I feel that my approach is quite inefficient and complex for what I am trying to do. I am pretty sure I misunderstood some of the concepts brought by the param library.

    Do you see a more efficient way to solve the problem ?

    Continue reading...

Compartilhe esta Página