Hello,
I’m trying to use Panel to build a Pipeline that effectively guides the user through generating a particular object. While I could just directly render the object’s param via Panel and get a bunch of widgets, in this case, I feel like it would be nicer to do it step by step.
For example, I have:
class ProjectBase(param.Parameterized):
project_name = param.String(
allow_None=False,
doc="""The name of the project. This should probably closely correlate to the
name of the paper you intent to publish afterwards, or a keyword which
you easily understand.""",
instantiate=False, per_instance=False,
)
project_base = param.String(
default="/dev/null",
doc="""This describes where the project is located on the machine, and
should point to a directory which you want to use, either as a
pathlib.Path object, or as a string which can be converted to a
Path.""",
instantiate=False, per_instance=False,
)
models = param.ListSelector(
default=["AWIESM-2.1"],
objects=["AWIESM-2.1", "AWIESM-2.2", "PISM-1.2"],
doc="""A list of models you intend to use. This can either be a list of
strings specifiying model names, or a list of Model objects. Strings of
this list will be automatically converted into Model objects for you. """,
instantiate=False, per_instance=False,
)
experiments = param.List(doc="Which experiments are in this project")
using_internal_model_codes = param.Boolean(
default=True,
doc="Does this project include models from inside the project folder?",
instantiate=False, per_instance=False,
)
using_internal_pool = param.Boolean(
default=True,
doc="Does this project use pool files in the project folder?",
instantiate=False, per_instance=False,
)
using_internal_bc_dir = param.Boolean(
default=True,
doc="Does this project use boundary condition sets from inside the project folder?",
instantiate=False, per_instance=False,
)
hpc_system = param.Selector(
objects=["mistral.dkrz.de", "ollie.awi.de", socket.getfqdn()],
doc="""This describes where the project is located on the machine, and
should point to a directory which you want to use, either as a
pathlib.Path object, or as a string which can be converted to a
Path.""",
instantiate=False, per_instance=False,
)
description = param.String(
doc="""A long form description of what this project is about. If unset,
defaults to an empty string, but you really should describe what you
are trying to do with your science.""",
instantiate=False, per_instance=False,
)
Next, I build a few classes to set up various parts;
class ProjectWebUIConfigureMetadata(ProjectBase):
ready = param.Boolean(default=False, precedence=-1)
def __init__(self, **params):
self._project_name_widget = pn.widgets.TextInput(
name="Project Name", value="Sample"
)
self._project_desc_widget = pn.widgets.TextAreaInput(
name="Description", height=400
)
super().__init__(**params)
self._layout = pn.Row(self._project_name_widget, self._project_desc_widget)
self._sync_widgets()
@param.depends("project_name", "description", watch=True)
def _sync_widgets(self):
self._project_name_widget.value = self.project_name
self._project_desc_widget.value = self.description
@param.depends(
"_project_name_widget.value", "_project_desc_widget.value", watch=True
)
def _sync_params(self):
self.project_name = self._project_name_widget.value
self.description = self._project_desc_widget.value
@param.output
def output(self):
return (self.project_name, self.description)
def panel(self):
return self._layout
and
class ProjectWebUILocations(ProjectBase):
ready = param.Boolean(default=False, precedence=-1)
def __init__(self, **params):
self._project_base_widget = pn.widgets.TextInput(
name="Project Base Directory", value="/a/path/to/your/base"
)
self._model_codes_widget = pn.widgets.Toggle(
name="Model Codes: In Project", value=True
)
self._pool_widget = pn.widgets.Toggle(name="Pool: In Project", value=True)
self._bc_widget = pn.widgets.Toggle(
name="Boundary Conditions: In Project", value=True
)
self._hpc_widget = pn.widgets.Select(
name="HPC System",
options=self.param.hpc_system.objects,
value=self.hpc_system,
)
super().__init__(**params)
self._layout = pn.Row(
self._project_base_widget,
pn.Column(self._model_codes_widget, self._pool_widget, self._bc_widget),
self._hpc_widget,
)
self._sync_widgets()
@param.depends(
"project_base",
"using_internal_model_codes",
"using_internal_pool",
"using_internal_bc_dir",
"hpc_system",
watch=True,
)
def _sync_widgets(self):
self._project_base_widget.value = self.project_base
self._model_codes_widget.value = self.using_internal_model_codes
self._model_codes_widget.name = (
"Model Codes: In Project"
if self.using_internal_model_codes
else "Model Codes: From Filesystem"
)
self._pool_widget.value = self.using_internal_pool
self._pool_widget.name = (
"Pool: In Project" if self.using_internal_pool else "Pool: From Filesystem"
)
self._bc_widget.value = self.using_internal_bc_dir
self._bc_widget.name = (
"Boundary Conditions: In Project"
if self.using_internal_bc_dir
else "Boundary Conditions: From Filesystem"
)
self._hpc_widget.value = self.hpc_system
@param.depends(
"_project_base_widget.value",
"_model_codes_widget.value",
"_pool_widget.value",
"_bc_widget.value",
"_hpc_widget.value",
watch=True,
)
def _sync_params(self):
self.project_base = self._project_base_widget.value
self.using_internal_model_codes = self._model_codes_widget.value
self.using_internal_pool = self._pool_widget.value
self.using_internal_bc_dir = self._bc_widget.value
self.hpc_system = self._hpc_widget.value
@param.output
def output(self):
return (
self.project_base,
self.using_internal_model_codes,
self.using_internal_pool,
self.using_internal_bc_dir,
self.hpc_system,
)
def panel(self):
return self._layout
How do I modify the output
method to just send along all the parameters to the next part of the pipeline? Is that possible?
Thanks for the help!
Paul