File size: 3,972 Bytes
9999841 62fa030 9999841 da6eba7 c2f8440 9999841 da6eba7 9999841 da6eba7 9999841 da6eba7 9999841 da6eba7 9999841 da6eba7 9999841 e1895d5 9999841 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
"""The FeatureInput enables a user to select from a list of features and set their values"""
import panel as pn
import param
class FeatureInput(pn.widgets.CompositeWidget):
"""The FeatureInput enables a user to select from a list of features and set their values
## Example
```python
features = {
"A": 1.0,
"B": 2.0,
"C": 3.0,
"D": 4.0,
}
selected_features = ["A", "C"]
widget = FeatureInput(features=features, selected_features=selected_features)
```
"""
value = param.Dict(
doc="The names of the features selected and their set values", allow_None=False
)
features = param.Dict(
doc="The names of the available features and their default values",
allow_None=False,
)
selected_features = param.ListSelector(
doc="The list of selected features", allow_None=False
)
_selected_widgets = param.ClassSelector(
class_=pn.Column, doc="The widgets used to edit the selected features"
)
_composite_type = pn.Column
def __init__(self, **params):
params["value"] = params.get("value", {})
params["features"] = params.get("features", {})
params["selected_features"] = params.get("selected_features", [])
params["_selected_widgets"] = self.param._selected_widgets.class_()
super().__init__(**params)
selected_features_widget = pn.widgets.MultiChoice.from_param(
self.param.selected_features, sizing_mode="stretch_width"
)
self._composite[:] = [selected_features_widget, self._selected_widgets]
@param.depends("features", watch=True, on_init=True)
def _reset_selected_features(self):
selected_features = []
for feature in self.selected_features.copy():
if feature in self.features.copy():
selected_features.append(feature)
self.param.selected_features.objects = list(self.features)
self.selected_features = selected_features
@param.depends("selected_features", watch=True, on_init=True)
def _handle_selected_features_change(self):
org_value = self.value
self._update_selected_widgets(org_value)
self._update_value()
def _update_value(self, *args): # pylint: disable=unused-argument
new_value = {}
for widget in self._selected_widgets:
new_value[widget.name] = widget.value
self.value = new_value
def _update_selected_widgets(self, org_value):
new_widgets = {}
for feature in self.selected_features:
value = org_value.get(feature, self.features[feature])
widget = self._new_widget(feature, value)
new_widgets[feature] = widget
self._selected_widgets[:] = list(new_widgets.values())
def _new_widget(self, feature, value):
widget = pn.widgets.FloatInput(
name=feature, value=value, sizing_mode="stretch_width"
)
pn.bind(self._update_value, widget, watch=True)
return widget
def create_app():
features = {
"Blade Length (m)": 73.5,
"Cut-in Wind Speed (m/s)": 3.5,
"Cut-out Wind Speed (m/s)": 25,
"Grid Connection Capacity (MW)": 5,
"Hub Height (m)": 100,
"Rated Wind Speed (m/s)": 12,
"Rotor Diameter (m)": 150,
"Turbine Efficiency (%)": 45,
"Water Depth (m)": 30,
"Wind Speed (m/s)": 10,
}
selected_features = ["Wind Speed (m/s)", "Rotor Diameter (m)"]
widget = FeatureInput(
features=features,
selected_features=selected_features,
width=500,
)
return pn.FlexBox(
pn.Column(
"## Widget",
widget,
),
pn.Column(
"## Value",
pn.pane.JSON(widget.param.value, width=500, height=200),
),
)
if pn.state.served:
pn.extension(design="material")
create_app().servable()
|