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()