sensotwin.temperature_selection.ui

  1import ipywidgets as widgets
  2from . import configuration
  3from . import style
  4from .. import global_style
  5from .. import store_connection
  6import matplotlib.pyplot as plt
  7import numpy as np
  8
  9class TemperatureSelectionUIElements:
 10    """Contains all UI functionality of material curing process configuration UI (Step 1).
 11
 12    In order to use, show the top level widget 'self.dashboard' in one cell of a notebook
 13    and the apply css styling calling 'self.apply_styling()' an another cell
 14    """
 15    def __init__(self):
 16        """Initialize UI objects and associated UI functionality."""
 17        self.dashboard = widgets.Tab().add_class("global_tab_container")
 18        self.dashboard.children = [
 19            self.init_data_source_box(),
 20            self.init_graph_input_box()]
 21        tab_titles = ['Input', 'Simulation']
 22        for i in range(len(tab_titles)):
 23            self.dashboard.set_title(i, tab_titles[i])
 24
 25    def init_data_source_box(self) -> widgets.Box:
 26        """Initialize first tab of dashboard, choosing data source."""
 27        local_database_label = widgets.Label(value="Use local owlready2 database:").add_class("global_headline")
 28        use_local_data_button = widgets.Button(
 29            description='Use local database',
 30            disabled=False,
 31            tooltip='Use local database',
 32            icon='play',
 33        ).add_class("global_load_data_button").add_class("global_basic_button")
 34        use_local_data_button.on_click(self.load_local_data)
 35        
 36        remote_database_label = widgets.Label(value="Use remote Apache Jena Fuseki database:").add_class("global_headline")
 37        self.remote_database_input = widgets.Text(
 38            value=None,
 39            placeholder="insert SPARQL url here",
 40            description="SPARQL Endpoint:",
 41            disabled=False   
 42        ).add_class("global_url_input").add_class("global_basic_input")
 43        use_remote_data_button = widgets.Button(
 44            description='Use remote database',
 45            disabled=False,
 46            tooltip='Use remote database',
 47            icon='play',
 48        ).add_class("global_load_data_button").add_class("global_basic_button")
 49        use_remote_data_button.on_click(self.load_remote_data)
 50        
 51        remote_data_box = widgets.VBox([
 52            remote_database_label,
 53            self.remote_database_input,
 54            use_remote_data_button
 55        ])
 56        local_data_box = widgets.VBox([
 57            local_database_label,
 58            use_local_data_button
 59        ])
 60        data_source_box = widgets.VBox([
 61            local_data_box,
 62            remote_data_box
 63        ]).add_class("global_data_tab_container")
 64
 65        return data_source_box
 66
 67    def init_graph_input_box(self) -> widgets.Box:
 68        """Initialize second tab of dashboard, configuring material curing behaviour."""
 69        with plt.ioff():
 70            fig, self.ax = plt.subplots()
 71        fig.canvas.toolbar_visible = False
 72        fig.canvas.header_visible = False
 73        fig.canvas.footer_visible = False
 74        fig.canvas.resizable = False
 75        fig.set_facecolor((0.0, 0.0, 0.0, 0.0))
 76        self.ax.set_facecolor((0.0, 0.0, 0.0, 0.0))
 77
 78        choose_timeline_label = widgets.Label(value="Choose temperature curve:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
 79        def on_selection_change(change):
 80            new_data_set = self.graph_data[change['new']]
 81            self.update_plot(new_data_set.get_time_data(),new_data_set.get_temperature_data())
 82        self.curve_selection = widgets.Dropdown(
 83            options=['No data loaded'],
 84            value='No data loaded',
 85            description='Name:',
 86            disabled=False
 87        ).add_class("temp_sel_basic_input").add_class("global_basic_input")
 88        self.curve_selection.observe(on_selection_change, names="value")
 89
 90        fibre_volume_content_label = widgets.Label(value="Choose FVC:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
 91        self.fibre_volume_content_input = widgets.Dropdown(
 92            options=['No data loaded'],
 93            value='No data loaded',
 94            description='Fibre Volume Content (%):',
 95            disabled=False
 96        ).add_class("temp_sel_basic_input").add_class("global_basic_input")
 97
 98        fvc_creation_label = widgets.Label(value="Create new fibre volume content:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
 99        self.creation_fvc_input = widgets.FloatText(
100            value=0,
101            disabled=False,
102            description="Create new FVC entry (%)"
103        ).add_class("temp_sel_basic_input").add_class("global_basic_input")
104        save_fvc_button = widgets.Button(
105            description='Save FVC',
106            disabled=False,
107            tooltip='Save FVC',
108            icon='save',
109        ).add_class("temp_sel_curve_creation_button").add_class("global_basic_button")
110        save_fvc_button.on_click(self.save_new_fibre_volume_content)
111
112        creation_label = widgets.Label(value="Create new temperature curve:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
113        self.creation_time_input = widgets.Text(
114            value="",
115            placeholder="comma seperated values",
116            description="Time values (h):",
117            disabled=False   
118        ).add_class("temp_sel_timeline_input").add_class("global_basic_input")
119        self.creation_temperature_input = widgets.Text(
120            value="",
121            placeholder="comma seperated values",
122            description="Temperature values (°C):",
123            disabled=False   
124        ).add_class("temp_sel_timeline_input").add_class("global_basic_input")
125        self.creation_name_input = widgets.Text(
126            value="",
127            placeholder="enter name",
128            description="Name:",
129            disabled=False   
130        ).add_class("temp_sel_timeline_input").add_class("global_basic_input")
131        plot_curve_button = widgets.Button(
132            description='Plot Curve',
133            disabled=False,
134            tooltip='Plot Curve',
135            icon='play'
136        ).add_class("temp_sel_curve_creation_button").add_class("global_basic_button")
137        plot_curve_button.on_click(self.preview_new_timeline)
138        save_curve_button = widgets.Button(
139            description='Save Curve',
140            disabled=False,
141            tooltip='Save Curve',
142            icon='save',
143        ).add_class("temp_sel_curve_creation_button").add_class("global_basic_button")
144        save_curve_button.on_click(self.save_new_timeline)
145
146        input_set_selection_label = widgets.Label(value="Select Input Set:").add_class("global_headline")
147        self.input_set_selection = widgets.Select(
148            options=['No data loaded'],
149            value='No data loaded',
150            rows=10,
151            description='Input sets:',
152            disabled=False
153        ).add_class("global_input_set_selection").add_class("global_basic_input")
154        display_input_set_button = widgets.Button(
155            description='Load Input Set',
156            disabled=False,
157            tooltip='Load Input Set',
158            icon='play',
159        ).add_class("global_basic_button")
160        display_input_set_button.on_click(self.display_input_set)
161        input_set_box = widgets.VBox([
162            input_set_selection_label,
163            self.input_set_selection,
164            display_input_set_button
165        ])
166
167        save_input_set_button = widgets.Button(
168            description='Save selected temperature graph and fibre volume content as new input set',
169            disabled=False,
170            tooltip='Save selected temperature graph and fibre volume content as new input set',
171            icon='save',
172        ).add_class("global_save_input_set_button").add_class("global_basic_button")
173        save_input_set_button.on_click(self.save_new_input_set)
174        curve_creation_button_box = widgets.HBox([
175            plot_curve_button,
176            save_curve_button
177        ]).add_class("temp_sel_curve_creation_button_container")
178        fvc_creation_button_box = widgets.HBox([
179            save_fvc_button
180        ]).add_class("temp_sel_curve_creation_button_container")
181        temperature_selection_box = widgets.VBox([
182            choose_timeline_label,
183            self.curve_selection,
184            creation_label,
185            self.creation_time_input, 
186            self.creation_temperature_input,
187            self.creation_name_input,
188            curve_creation_button_box
189        ]).add_class("temp_sel_curve_selection_container")
190        fvc_selection_box = widgets.VBox([
191            fibre_volume_content_label,
192            self.fibre_volume_content_input,
193            fvc_creation_label,
194            self.creation_fvc_input,
195            fvc_creation_button_box
196        ]).add_class("temp_sel_curve_creation_container")
197        data_input_box = widgets.VBox([
198            temperature_selection_box,
199            fvc_selection_box
200        ]).add_class("temp_sel_data_input_container")
201        matplot_box = widgets.VBox([
202            fig.canvas
203        ]).add_class("temp_sel_matplot_box")
204        
205        graph_input_box = widgets.VBox([
206            widgets.HBox([
207                input_set_box,
208                matplot_box,
209                data_input_box
210            ]).add_class("temp_sel_graph_tab_container"),
211            save_input_set_button
212        ])
213        
214        return graph_input_box
215
216    def update_plot(self, time_data: list, temperature_data: list):
217        """Update central plot with new data.
218
219        Args:
220            time_data: list of floats (hour)
221            temperature_data: list of floats (°C)
222        """
223        self.ax.clear()
224        self.ax.plot(np.array(time_data), np.array(temperature_data), label='_Temp?')
225        self.ax.set_xlabel('Time (h)')
226        self.ax.set_ylabel('Temperature (°C)')
227
228    def load_local_data(self, ui_element=None):
229        """Use locally stored data for UI.
230
231        Args:
232            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
233        """
234        self.conn = store_connection.LocalStoreConnection("sensotwin_world")
235        self.load_temperature_data()
236        self.load_fvc_data()
237        self.load_input_set_data()
238
239    def load_remote_data(self, ui_element=None):
240        """Use remotely stored data for UI.
241
242        Args:
243            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
244        """
245        self.conn = store_connection.FusekiConnection(self.remote_database_input.value)
246        self.load_temperature_data()
247        self.load_fvc_data()
248        self.load_input_set_data()
249
250    def load_input_set_data(self):
251        """Load data from previously set input source and populate UI."""
252        self.input_set_data = configuration.MaterialHardeningInputDataSet.get_all_entries_from_store(self.conn)
253        if self.input_set_data:
254            options = []
255            for key, input_set in self.input_set_data.items():
256                temperature_graph = self.graph_data[input_set.get_temperature_graph_id()]
257                fibre_volume_content = self.fvc_data[input_set.get_fibre_volume_content_id()]
258                label = input_set.generate_input_set_display_label()
259                options.append((label, key))
260            self.input_set_selection.options = options
261            self.input_set_selection.value = list(self.input_set_data.keys())[0]
262
263    def display_input_set(self, ui_element=None):
264        """Display data for currently selected input set in UI.
265
266        Args:
267            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
268        """
269        selected_set = self.input_set_data[self.input_set_selection.value]
270        temperature_graph = self.graph_data[selected_set.get_temperature_graph_id()]
271        fibre_volume_content = self.fvc_data[selected_set.get_fibre_volume_content_id()]
272        self.load_temperature_data(pre_select=temperature_graph.get_id())
273        self.load_fvc_data(pre_select=fibre_volume_content.get_id())
274
275    def load_temperature_data(self, pre_select=None):
276        """Refresh list for available temperature graphs.
277
278        Args:
279            pre_select: optional int id of a temperature set to be pre-selected after refresh
280        """
281        self.graph_data = configuration.TemperatureGraph.get_all_entries_from_store(self.conn)
282        if self.graph_data:
283            if pre_select:
284                initial_dict_key = pre_select
285            else:
286                initial_dict_key = list(self.graph_data.keys())[0]
287            time_data = self.graph_data[initial_dict_key].get_time_data()
288            temperature_data = self.graph_data[initial_dict_key].get_temperature_data()
289            self.curve_selection.options = [(value.get_name(), key) for key, value in self.graph_data.items()]
290            self.curve_selection.value = initial_dict_key
291            self.update_plot(time_data, temperature_data)
292
293    def load_fvc_data(self, pre_select=None):
294        """Refresh list for available fibre volume content values.
295
296        Args:
297            pre_select: optional int id of a fibre volume content to be pre-selected after refresh
298        """
299        self.fvc_data = configuration.FibreVolumeContent.get_all_entries_from_store(self.conn)
300        if self.fvc_data:
301            if pre_select:
302                initial_dict_key = pre_select
303            else:
304                initial_dict_key = list(self.fvc_data.keys())[0]
305            self.fibre_volume_content_input.options = [(value.get_value(), key) for key, value in self.fvc_data.items()]
306            self.fibre_volume_content_input.value = initial_dict_key
307
308    def preview_new_timeline(self, ui_element=None):
309        """Display new timeline currently defined in input fields without saving to store.
310
311        Args:
312            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
313        """
314        self.update_plot(self.get_creation_time_values(), self.get_creation_temperature_values())
315
316    def get_creation_time_values(self) -> list:
317        """Parse current input of time value input."""
318        time_string = self.creation_time_input.value
319        time_values = list(map(float, time_string.split(",")))
320        return time_values
321
322    def get_creation_temperature_values(self) -> list:
323        """Parse current input of temperature value input."""
324        temperature_string = self.creation_temperature_input.value
325        temperature_values = list(map(int, temperature_string.split(",")))
326        return temperature_values
327
328    def save_new_fibre_volume_content(self, ui_element=None):
329        """Save currently defined value of fibre volume content to store as new entry.
330
331        Args:
332            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
333        """
334        new_id = max(self.fvc_data.keys()) + 1 if self.fvc_data else 1
335        new_fvc = configuration.FibreVolumeContent(
336            uniq_id = new_id,
337            value = self.creation_fvc_input.value,
338            conn = self.conn)
339        new_fvc.save_entry_to_store()
340        self.load_fvc_data(pre_select=new_id)
341    
342    def save_new_timeline(self, ui_element=None):
343        """Save currently defined values of temperature graph to store as new entry.
344
345        Args:
346            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
347        """
348        new_id = max(self.graph_data.keys()) + 1 if self.graph_data else 1
349        new_graph = configuration.TemperatureGraph(
350            uniq_id = new_id,
351            name = self.creation_name_input.value,
352            time_data = self.get_creation_time_values(),
353            temperature_data = self.get_creation_temperature_values(),
354            conn = self.conn)
355        new_graph.save_entry_to_store()
356        self.load_temperature_data(pre_select=new_id)
357
358    def save_new_input_set(self, ui_element=None):
359        """Save currently defined selections of temperature graph and fibre volume content to store as new entry.
360
361        Args:
362            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
363        """
364        new_id = max(self.input_set_data.keys()) + 1 if self.input_set_data else 1
365        new_set = configuration.MaterialHardeningInputDataSet(
366            uniq_id = new_id,
367            temperature_graph = self.graph_data[self.curve_selection.value],
368            fibre_volume_content = self.fvc_data[self.fibre_volume_content_input.value],
369            conn = self.conn)
370        self.graph_data[self.curve_selection.value].save_entry_to_store()
371        self.fvc_data[self.fibre_volume_content_input.value].save_entry_to_store()
372        new_set.save_entry_to_store()
373        self.load_input_set_data()
374
375    def apply_styling(self):
376        """Apply CSS hack to notebook for better styling than native Jupyter Widget styles."""
377        css = """
378            <style>
379            {}
380            {}
381            </style>
382        """.format(global_style.global_css, style.local_css)
383        return widgets.HTML(css)
class TemperatureSelectionUIElements:
 10class TemperatureSelectionUIElements:
 11    """Contains all UI functionality of material curing process configuration UI (Step 1).
 12
 13    In order to use, show the top level widget 'self.dashboard' in one cell of a notebook
 14    and the apply css styling calling 'self.apply_styling()' an another cell
 15    """
 16    def __init__(self):
 17        """Initialize UI objects and associated UI functionality."""
 18        self.dashboard = widgets.Tab().add_class("global_tab_container")
 19        self.dashboard.children = [
 20            self.init_data_source_box(),
 21            self.init_graph_input_box()]
 22        tab_titles = ['Input', 'Simulation']
 23        for i in range(len(tab_titles)):
 24            self.dashboard.set_title(i, tab_titles[i])
 25
 26    def init_data_source_box(self) -> widgets.Box:
 27        """Initialize first tab of dashboard, choosing data source."""
 28        local_database_label = widgets.Label(value="Use local owlready2 database:").add_class("global_headline")
 29        use_local_data_button = widgets.Button(
 30            description='Use local database',
 31            disabled=False,
 32            tooltip='Use local database',
 33            icon='play',
 34        ).add_class("global_load_data_button").add_class("global_basic_button")
 35        use_local_data_button.on_click(self.load_local_data)
 36        
 37        remote_database_label = widgets.Label(value="Use remote Apache Jena Fuseki database:").add_class("global_headline")
 38        self.remote_database_input = widgets.Text(
 39            value=None,
 40            placeholder="insert SPARQL url here",
 41            description="SPARQL Endpoint:",
 42            disabled=False   
 43        ).add_class("global_url_input").add_class("global_basic_input")
 44        use_remote_data_button = widgets.Button(
 45            description='Use remote database',
 46            disabled=False,
 47            tooltip='Use remote database',
 48            icon='play',
 49        ).add_class("global_load_data_button").add_class("global_basic_button")
 50        use_remote_data_button.on_click(self.load_remote_data)
 51        
 52        remote_data_box = widgets.VBox([
 53            remote_database_label,
 54            self.remote_database_input,
 55            use_remote_data_button
 56        ])
 57        local_data_box = widgets.VBox([
 58            local_database_label,
 59            use_local_data_button
 60        ])
 61        data_source_box = widgets.VBox([
 62            local_data_box,
 63            remote_data_box
 64        ]).add_class("global_data_tab_container")
 65
 66        return data_source_box
 67
 68    def init_graph_input_box(self) -> widgets.Box:
 69        """Initialize second tab of dashboard, configuring material curing behaviour."""
 70        with plt.ioff():
 71            fig, self.ax = plt.subplots()
 72        fig.canvas.toolbar_visible = False
 73        fig.canvas.header_visible = False
 74        fig.canvas.footer_visible = False
 75        fig.canvas.resizable = False
 76        fig.set_facecolor((0.0, 0.0, 0.0, 0.0))
 77        self.ax.set_facecolor((0.0, 0.0, 0.0, 0.0))
 78
 79        choose_timeline_label = widgets.Label(value="Choose temperature curve:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
 80        def on_selection_change(change):
 81            new_data_set = self.graph_data[change['new']]
 82            self.update_plot(new_data_set.get_time_data(),new_data_set.get_temperature_data())
 83        self.curve_selection = widgets.Dropdown(
 84            options=['No data loaded'],
 85            value='No data loaded',
 86            description='Name:',
 87            disabled=False
 88        ).add_class("temp_sel_basic_input").add_class("global_basic_input")
 89        self.curve_selection.observe(on_selection_change, names="value")
 90
 91        fibre_volume_content_label = widgets.Label(value="Choose FVC:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
 92        self.fibre_volume_content_input = widgets.Dropdown(
 93            options=['No data loaded'],
 94            value='No data loaded',
 95            description='Fibre Volume Content (%):',
 96            disabled=False
 97        ).add_class("temp_sel_basic_input").add_class("global_basic_input")
 98
 99        fvc_creation_label = widgets.Label(value="Create new fibre volume content:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
100        self.creation_fvc_input = widgets.FloatText(
101            value=0,
102            disabled=False,
103            description="Create new FVC entry (%)"
104        ).add_class("temp_sel_basic_input").add_class("global_basic_input")
105        save_fvc_button = widgets.Button(
106            description='Save FVC',
107            disabled=False,
108            tooltip='Save FVC',
109            icon='save',
110        ).add_class("temp_sel_curve_creation_button").add_class("global_basic_button")
111        save_fvc_button.on_click(self.save_new_fibre_volume_content)
112
113        creation_label = widgets.Label(value="Create new temperature curve:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
114        self.creation_time_input = widgets.Text(
115            value="",
116            placeholder="comma seperated values",
117            description="Time values (h):",
118            disabled=False   
119        ).add_class("temp_sel_timeline_input").add_class("global_basic_input")
120        self.creation_temperature_input = widgets.Text(
121            value="",
122            placeholder="comma seperated values",
123            description="Temperature values (°C):",
124            disabled=False   
125        ).add_class("temp_sel_timeline_input").add_class("global_basic_input")
126        self.creation_name_input = widgets.Text(
127            value="",
128            placeholder="enter name",
129            description="Name:",
130            disabled=False   
131        ).add_class("temp_sel_timeline_input").add_class("global_basic_input")
132        plot_curve_button = widgets.Button(
133            description='Plot Curve',
134            disabled=False,
135            tooltip='Plot Curve',
136            icon='play'
137        ).add_class("temp_sel_curve_creation_button").add_class("global_basic_button")
138        plot_curve_button.on_click(self.preview_new_timeline)
139        save_curve_button = widgets.Button(
140            description='Save Curve',
141            disabled=False,
142            tooltip='Save Curve',
143            icon='save',
144        ).add_class("temp_sel_curve_creation_button").add_class("global_basic_button")
145        save_curve_button.on_click(self.save_new_timeline)
146
147        input_set_selection_label = widgets.Label(value="Select Input Set:").add_class("global_headline")
148        self.input_set_selection = widgets.Select(
149            options=['No data loaded'],
150            value='No data loaded',
151            rows=10,
152            description='Input sets:',
153            disabled=False
154        ).add_class("global_input_set_selection").add_class("global_basic_input")
155        display_input_set_button = widgets.Button(
156            description='Load Input Set',
157            disabled=False,
158            tooltip='Load Input Set',
159            icon='play',
160        ).add_class("global_basic_button")
161        display_input_set_button.on_click(self.display_input_set)
162        input_set_box = widgets.VBox([
163            input_set_selection_label,
164            self.input_set_selection,
165            display_input_set_button
166        ])
167
168        save_input_set_button = widgets.Button(
169            description='Save selected temperature graph and fibre volume content as new input set',
170            disabled=False,
171            tooltip='Save selected temperature graph and fibre volume content as new input set',
172            icon='save',
173        ).add_class("global_save_input_set_button").add_class("global_basic_button")
174        save_input_set_button.on_click(self.save_new_input_set)
175        curve_creation_button_box = widgets.HBox([
176            plot_curve_button,
177            save_curve_button
178        ]).add_class("temp_sel_curve_creation_button_container")
179        fvc_creation_button_box = widgets.HBox([
180            save_fvc_button
181        ]).add_class("temp_sel_curve_creation_button_container")
182        temperature_selection_box = widgets.VBox([
183            choose_timeline_label,
184            self.curve_selection,
185            creation_label,
186            self.creation_time_input, 
187            self.creation_temperature_input,
188            self.creation_name_input,
189            curve_creation_button_box
190        ]).add_class("temp_sel_curve_selection_container")
191        fvc_selection_box = widgets.VBox([
192            fibre_volume_content_label,
193            self.fibre_volume_content_input,
194            fvc_creation_label,
195            self.creation_fvc_input,
196            fvc_creation_button_box
197        ]).add_class("temp_sel_curve_creation_container")
198        data_input_box = widgets.VBox([
199            temperature_selection_box,
200            fvc_selection_box
201        ]).add_class("temp_sel_data_input_container")
202        matplot_box = widgets.VBox([
203            fig.canvas
204        ]).add_class("temp_sel_matplot_box")
205        
206        graph_input_box = widgets.VBox([
207            widgets.HBox([
208                input_set_box,
209                matplot_box,
210                data_input_box
211            ]).add_class("temp_sel_graph_tab_container"),
212            save_input_set_button
213        ])
214        
215        return graph_input_box
216
217    def update_plot(self, time_data: list, temperature_data: list):
218        """Update central plot with new data.
219
220        Args:
221            time_data: list of floats (hour)
222            temperature_data: list of floats (°C)
223        """
224        self.ax.clear()
225        self.ax.plot(np.array(time_data), np.array(temperature_data), label='_Temp?')
226        self.ax.set_xlabel('Time (h)')
227        self.ax.set_ylabel('Temperature (°C)')
228
229    def load_local_data(self, ui_element=None):
230        """Use locally stored data for UI.
231
232        Args:
233            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
234        """
235        self.conn = store_connection.LocalStoreConnection("sensotwin_world")
236        self.load_temperature_data()
237        self.load_fvc_data()
238        self.load_input_set_data()
239
240    def load_remote_data(self, ui_element=None):
241        """Use remotely stored data for UI.
242
243        Args:
244            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
245        """
246        self.conn = store_connection.FusekiConnection(self.remote_database_input.value)
247        self.load_temperature_data()
248        self.load_fvc_data()
249        self.load_input_set_data()
250
251    def load_input_set_data(self):
252        """Load data from previously set input source and populate UI."""
253        self.input_set_data = configuration.MaterialHardeningInputDataSet.get_all_entries_from_store(self.conn)
254        if self.input_set_data:
255            options = []
256            for key, input_set in self.input_set_data.items():
257                temperature_graph = self.graph_data[input_set.get_temperature_graph_id()]
258                fibre_volume_content = self.fvc_data[input_set.get_fibre_volume_content_id()]
259                label = input_set.generate_input_set_display_label()
260                options.append((label, key))
261            self.input_set_selection.options = options
262            self.input_set_selection.value = list(self.input_set_data.keys())[0]
263
264    def display_input_set(self, ui_element=None):
265        """Display data for currently selected input set in UI.
266
267        Args:
268            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
269        """
270        selected_set = self.input_set_data[self.input_set_selection.value]
271        temperature_graph = self.graph_data[selected_set.get_temperature_graph_id()]
272        fibre_volume_content = self.fvc_data[selected_set.get_fibre_volume_content_id()]
273        self.load_temperature_data(pre_select=temperature_graph.get_id())
274        self.load_fvc_data(pre_select=fibre_volume_content.get_id())
275
276    def load_temperature_data(self, pre_select=None):
277        """Refresh list for available temperature graphs.
278
279        Args:
280            pre_select: optional int id of a temperature set to be pre-selected after refresh
281        """
282        self.graph_data = configuration.TemperatureGraph.get_all_entries_from_store(self.conn)
283        if self.graph_data:
284            if pre_select:
285                initial_dict_key = pre_select
286            else:
287                initial_dict_key = list(self.graph_data.keys())[0]
288            time_data = self.graph_data[initial_dict_key].get_time_data()
289            temperature_data = self.graph_data[initial_dict_key].get_temperature_data()
290            self.curve_selection.options = [(value.get_name(), key) for key, value in self.graph_data.items()]
291            self.curve_selection.value = initial_dict_key
292            self.update_plot(time_data, temperature_data)
293
294    def load_fvc_data(self, pre_select=None):
295        """Refresh list for available fibre volume content values.
296
297        Args:
298            pre_select: optional int id of a fibre volume content to be pre-selected after refresh
299        """
300        self.fvc_data = configuration.FibreVolumeContent.get_all_entries_from_store(self.conn)
301        if self.fvc_data:
302            if pre_select:
303                initial_dict_key = pre_select
304            else:
305                initial_dict_key = list(self.fvc_data.keys())[0]
306            self.fibre_volume_content_input.options = [(value.get_value(), key) for key, value in self.fvc_data.items()]
307            self.fibre_volume_content_input.value = initial_dict_key
308
309    def preview_new_timeline(self, ui_element=None):
310        """Display new timeline currently defined in input fields without saving to store.
311
312        Args:
313            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
314        """
315        self.update_plot(self.get_creation_time_values(), self.get_creation_temperature_values())
316
317    def get_creation_time_values(self) -> list:
318        """Parse current input of time value input."""
319        time_string = self.creation_time_input.value
320        time_values = list(map(float, time_string.split(",")))
321        return time_values
322
323    def get_creation_temperature_values(self) -> list:
324        """Parse current input of temperature value input."""
325        temperature_string = self.creation_temperature_input.value
326        temperature_values = list(map(int, temperature_string.split(",")))
327        return temperature_values
328
329    def save_new_fibre_volume_content(self, ui_element=None):
330        """Save currently defined value of fibre volume content to store as new entry.
331
332        Args:
333            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
334        """
335        new_id = max(self.fvc_data.keys()) + 1 if self.fvc_data else 1
336        new_fvc = configuration.FibreVolumeContent(
337            uniq_id = new_id,
338            value = self.creation_fvc_input.value,
339            conn = self.conn)
340        new_fvc.save_entry_to_store()
341        self.load_fvc_data(pre_select=new_id)
342    
343    def save_new_timeline(self, ui_element=None):
344        """Save currently defined values of temperature graph to store as new entry.
345
346        Args:
347            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
348        """
349        new_id = max(self.graph_data.keys()) + 1 if self.graph_data else 1
350        new_graph = configuration.TemperatureGraph(
351            uniq_id = new_id,
352            name = self.creation_name_input.value,
353            time_data = self.get_creation_time_values(),
354            temperature_data = self.get_creation_temperature_values(),
355            conn = self.conn)
356        new_graph.save_entry_to_store()
357        self.load_temperature_data(pre_select=new_id)
358
359    def save_new_input_set(self, ui_element=None):
360        """Save currently defined selections of temperature graph and fibre volume content to store as new entry.
361
362        Args:
363            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
364        """
365        new_id = max(self.input_set_data.keys()) + 1 if self.input_set_data else 1
366        new_set = configuration.MaterialHardeningInputDataSet(
367            uniq_id = new_id,
368            temperature_graph = self.graph_data[self.curve_selection.value],
369            fibre_volume_content = self.fvc_data[self.fibre_volume_content_input.value],
370            conn = self.conn)
371        self.graph_data[self.curve_selection.value].save_entry_to_store()
372        self.fvc_data[self.fibre_volume_content_input.value].save_entry_to_store()
373        new_set.save_entry_to_store()
374        self.load_input_set_data()
375
376    def apply_styling(self):
377        """Apply CSS hack to notebook for better styling than native Jupyter Widget styles."""
378        css = """
379            <style>
380            {}
381            {}
382            </style>
383        """.format(global_style.global_css, style.local_css)
384        return widgets.HTML(css)

Contains all UI functionality of material curing process configuration UI (Step 1).

In order to use, show the top level widget 'self.dashboard' in one cell of a notebook and the apply css styling calling 'self.apply_styling()' an another cell

TemperatureSelectionUIElements()
16    def __init__(self):
17        """Initialize UI objects and associated UI functionality."""
18        self.dashboard = widgets.Tab().add_class("global_tab_container")
19        self.dashboard.children = [
20            self.init_data_source_box(),
21            self.init_graph_input_box()]
22        tab_titles = ['Input', 'Simulation']
23        for i in range(len(tab_titles)):
24            self.dashboard.set_title(i, tab_titles[i])

Initialize UI objects and associated UI functionality.

dashboard
def init_data_source_box(self) -> ipywidgets.widgets.widget_box.Box:
26    def init_data_source_box(self) -> widgets.Box:
27        """Initialize first tab of dashboard, choosing data source."""
28        local_database_label = widgets.Label(value="Use local owlready2 database:").add_class("global_headline")
29        use_local_data_button = widgets.Button(
30            description='Use local database',
31            disabled=False,
32            tooltip='Use local database',
33            icon='play',
34        ).add_class("global_load_data_button").add_class("global_basic_button")
35        use_local_data_button.on_click(self.load_local_data)
36        
37        remote_database_label = widgets.Label(value="Use remote Apache Jena Fuseki database:").add_class("global_headline")
38        self.remote_database_input = widgets.Text(
39            value=None,
40            placeholder="insert SPARQL url here",
41            description="SPARQL Endpoint:",
42            disabled=False   
43        ).add_class("global_url_input").add_class("global_basic_input")
44        use_remote_data_button = widgets.Button(
45            description='Use remote database',
46            disabled=False,
47            tooltip='Use remote database',
48            icon='play',
49        ).add_class("global_load_data_button").add_class("global_basic_button")
50        use_remote_data_button.on_click(self.load_remote_data)
51        
52        remote_data_box = widgets.VBox([
53            remote_database_label,
54            self.remote_database_input,
55            use_remote_data_button
56        ])
57        local_data_box = widgets.VBox([
58            local_database_label,
59            use_local_data_button
60        ])
61        data_source_box = widgets.VBox([
62            local_data_box,
63            remote_data_box
64        ]).add_class("global_data_tab_container")
65
66        return data_source_box

Initialize first tab of dashboard, choosing data source.

def init_graph_input_box(self) -> ipywidgets.widgets.widget_box.Box:
 68    def init_graph_input_box(self) -> widgets.Box:
 69        """Initialize second tab of dashboard, configuring material curing behaviour."""
 70        with plt.ioff():
 71            fig, self.ax = plt.subplots()
 72        fig.canvas.toolbar_visible = False
 73        fig.canvas.header_visible = False
 74        fig.canvas.footer_visible = False
 75        fig.canvas.resizable = False
 76        fig.set_facecolor((0.0, 0.0, 0.0, 0.0))
 77        self.ax.set_facecolor((0.0, 0.0, 0.0, 0.0))
 78
 79        choose_timeline_label = widgets.Label(value="Choose temperature curve:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
 80        def on_selection_change(change):
 81            new_data_set = self.graph_data[change['new']]
 82            self.update_plot(new_data_set.get_time_data(),new_data_set.get_temperature_data())
 83        self.curve_selection = widgets.Dropdown(
 84            options=['No data loaded'],
 85            value='No data loaded',
 86            description='Name:',
 87            disabled=False
 88        ).add_class("temp_sel_basic_input").add_class("global_basic_input")
 89        self.curve_selection.observe(on_selection_change, names="value")
 90
 91        fibre_volume_content_label = widgets.Label(value="Choose FVC:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
 92        self.fibre_volume_content_input = widgets.Dropdown(
 93            options=['No data loaded'],
 94            value='No data loaded',
 95            description='Fibre Volume Content (%):',
 96            disabled=False
 97        ).add_class("temp_sel_basic_input").add_class("global_basic_input")
 98
 99        fvc_creation_label = widgets.Label(value="Create new fibre volume content:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
100        self.creation_fvc_input = widgets.FloatText(
101            value=0,
102            disabled=False,
103            description="Create new FVC entry (%)"
104        ).add_class("temp_sel_basic_input").add_class("global_basic_input")
105        save_fvc_button = widgets.Button(
106            description='Save FVC',
107            disabled=False,
108            tooltip='Save FVC',
109            icon='save',
110        ).add_class("temp_sel_curve_creation_button").add_class("global_basic_button")
111        save_fvc_button.on_click(self.save_new_fibre_volume_content)
112
113        creation_label = widgets.Label(value="Create new temperature curve:").add_class("temp_sel_timeline_input_headline").add_class("global_headline")
114        self.creation_time_input = widgets.Text(
115            value="",
116            placeholder="comma seperated values",
117            description="Time values (h):",
118            disabled=False   
119        ).add_class("temp_sel_timeline_input").add_class("global_basic_input")
120        self.creation_temperature_input = widgets.Text(
121            value="",
122            placeholder="comma seperated values",
123            description="Temperature values (°C):",
124            disabled=False   
125        ).add_class("temp_sel_timeline_input").add_class("global_basic_input")
126        self.creation_name_input = widgets.Text(
127            value="",
128            placeholder="enter name",
129            description="Name:",
130            disabled=False   
131        ).add_class("temp_sel_timeline_input").add_class("global_basic_input")
132        plot_curve_button = widgets.Button(
133            description='Plot Curve',
134            disabled=False,
135            tooltip='Plot Curve',
136            icon='play'
137        ).add_class("temp_sel_curve_creation_button").add_class("global_basic_button")
138        plot_curve_button.on_click(self.preview_new_timeline)
139        save_curve_button = widgets.Button(
140            description='Save Curve',
141            disabled=False,
142            tooltip='Save Curve',
143            icon='save',
144        ).add_class("temp_sel_curve_creation_button").add_class("global_basic_button")
145        save_curve_button.on_click(self.save_new_timeline)
146
147        input_set_selection_label = widgets.Label(value="Select Input Set:").add_class("global_headline")
148        self.input_set_selection = widgets.Select(
149            options=['No data loaded'],
150            value='No data loaded',
151            rows=10,
152            description='Input sets:',
153            disabled=False
154        ).add_class("global_input_set_selection").add_class("global_basic_input")
155        display_input_set_button = widgets.Button(
156            description='Load Input Set',
157            disabled=False,
158            tooltip='Load Input Set',
159            icon='play',
160        ).add_class("global_basic_button")
161        display_input_set_button.on_click(self.display_input_set)
162        input_set_box = widgets.VBox([
163            input_set_selection_label,
164            self.input_set_selection,
165            display_input_set_button
166        ])
167
168        save_input_set_button = widgets.Button(
169            description='Save selected temperature graph and fibre volume content as new input set',
170            disabled=False,
171            tooltip='Save selected temperature graph and fibre volume content as new input set',
172            icon='save',
173        ).add_class("global_save_input_set_button").add_class("global_basic_button")
174        save_input_set_button.on_click(self.save_new_input_set)
175        curve_creation_button_box = widgets.HBox([
176            plot_curve_button,
177            save_curve_button
178        ]).add_class("temp_sel_curve_creation_button_container")
179        fvc_creation_button_box = widgets.HBox([
180            save_fvc_button
181        ]).add_class("temp_sel_curve_creation_button_container")
182        temperature_selection_box = widgets.VBox([
183            choose_timeline_label,
184            self.curve_selection,
185            creation_label,
186            self.creation_time_input, 
187            self.creation_temperature_input,
188            self.creation_name_input,
189            curve_creation_button_box
190        ]).add_class("temp_sel_curve_selection_container")
191        fvc_selection_box = widgets.VBox([
192            fibre_volume_content_label,
193            self.fibre_volume_content_input,
194            fvc_creation_label,
195            self.creation_fvc_input,
196            fvc_creation_button_box
197        ]).add_class("temp_sel_curve_creation_container")
198        data_input_box = widgets.VBox([
199            temperature_selection_box,
200            fvc_selection_box
201        ]).add_class("temp_sel_data_input_container")
202        matplot_box = widgets.VBox([
203            fig.canvas
204        ]).add_class("temp_sel_matplot_box")
205        
206        graph_input_box = widgets.VBox([
207            widgets.HBox([
208                input_set_box,
209                matplot_box,
210                data_input_box
211            ]).add_class("temp_sel_graph_tab_container"),
212            save_input_set_button
213        ])
214        
215        return graph_input_box

Initialize second tab of dashboard, configuring material curing behaviour.

def update_plot(self, time_data: list, temperature_data: list):
217    def update_plot(self, time_data: list, temperature_data: list):
218        """Update central plot with new data.
219
220        Args:
221            time_data: list of floats (hour)
222            temperature_data: list of floats (°C)
223        """
224        self.ax.clear()
225        self.ax.plot(np.array(time_data), np.array(temperature_data), label='_Temp?')
226        self.ax.set_xlabel('Time (h)')
227        self.ax.set_ylabel('Temperature (°C)')

Update central plot with new data.

Args: time_data: list of floats (hour) temperature_data: list of floats (°C)

def load_local_data(self, ui_element=None):
229    def load_local_data(self, ui_element=None):
230        """Use locally stored data for UI.
231
232        Args:
233            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
234        """
235        self.conn = store_connection.LocalStoreConnection("sensotwin_world")
236        self.load_temperature_data()
237        self.load_fvc_data()
238        self.load_input_set_data()

Use locally stored data for UI.

Args: ui_element: Override for ipywidgets to not pass the UI element that triggered the event

def load_remote_data(self, ui_element=None):
240    def load_remote_data(self, ui_element=None):
241        """Use remotely stored data for UI.
242
243        Args:
244            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
245        """
246        self.conn = store_connection.FusekiConnection(self.remote_database_input.value)
247        self.load_temperature_data()
248        self.load_fvc_data()
249        self.load_input_set_data()

Use remotely stored data for UI.

Args: ui_element: Override for ipywidgets to not pass the UI element that triggered the event

def load_input_set_data(self):
251    def load_input_set_data(self):
252        """Load data from previously set input source and populate UI."""
253        self.input_set_data = configuration.MaterialHardeningInputDataSet.get_all_entries_from_store(self.conn)
254        if self.input_set_data:
255            options = []
256            for key, input_set in self.input_set_data.items():
257                temperature_graph = self.graph_data[input_set.get_temperature_graph_id()]
258                fibre_volume_content = self.fvc_data[input_set.get_fibre_volume_content_id()]
259                label = input_set.generate_input_set_display_label()
260                options.append((label, key))
261            self.input_set_selection.options = options
262            self.input_set_selection.value = list(self.input_set_data.keys())[0]

Load data from previously set input source and populate UI.

def display_input_set(self, ui_element=None):
264    def display_input_set(self, ui_element=None):
265        """Display data for currently selected input set in UI.
266
267        Args:
268            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
269        """
270        selected_set = self.input_set_data[self.input_set_selection.value]
271        temperature_graph = self.graph_data[selected_set.get_temperature_graph_id()]
272        fibre_volume_content = self.fvc_data[selected_set.get_fibre_volume_content_id()]
273        self.load_temperature_data(pre_select=temperature_graph.get_id())
274        self.load_fvc_data(pre_select=fibre_volume_content.get_id())

Display data for currently selected input set in UI.

Args: ui_element: Override for ipywidgets to not pass the UI element that triggered the event

def load_temperature_data(self, pre_select=None):
276    def load_temperature_data(self, pre_select=None):
277        """Refresh list for available temperature graphs.
278
279        Args:
280            pre_select: optional int id of a temperature set to be pre-selected after refresh
281        """
282        self.graph_data = configuration.TemperatureGraph.get_all_entries_from_store(self.conn)
283        if self.graph_data:
284            if pre_select:
285                initial_dict_key = pre_select
286            else:
287                initial_dict_key = list(self.graph_data.keys())[0]
288            time_data = self.graph_data[initial_dict_key].get_time_data()
289            temperature_data = self.graph_data[initial_dict_key].get_temperature_data()
290            self.curve_selection.options = [(value.get_name(), key) for key, value in self.graph_data.items()]
291            self.curve_selection.value = initial_dict_key
292            self.update_plot(time_data, temperature_data)

Refresh list for available temperature graphs.

Args: pre_select: optional int id of a temperature set to be pre-selected after refresh

def load_fvc_data(self, pre_select=None):
294    def load_fvc_data(self, pre_select=None):
295        """Refresh list for available fibre volume content values.
296
297        Args:
298            pre_select: optional int id of a fibre volume content to be pre-selected after refresh
299        """
300        self.fvc_data = configuration.FibreVolumeContent.get_all_entries_from_store(self.conn)
301        if self.fvc_data:
302            if pre_select:
303                initial_dict_key = pre_select
304            else:
305                initial_dict_key = list(self.fvc_data.keys())[0]
306            self.fibre_volume_content_input.options = [(value.get_value(), key) for key, value in self.fvc_data.items()]
307            self.fibre_volume_content_input.value = initial_dict_key

Refresh list for available fibre volume content values.

Args: pre_select: optional int id of a fibre volume content to be pre-selected after refresh

def preview_new_timeline(self, ui_element=None):
309    def preview_new_timeline(self, ui_element=None):
310        """Display new timeline currently defined in input fields without saving to store.
311
312        Args:
313            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
314        """
315        self.update_plot(self.get_creation_time_values(), self.get_creation_temperature_values())

Display new timeline currently defined in input fields without saving to store.

Args: ui_element: Override for ipywidgets to not pass the UI element that triggered the event

def get_creation_time_values(self) -> list:
317    def get_creation_time_values(self) -> list:
318        """Parse current input of time value input."""
319        time_string = self.creation_time_input.value
320        time_values = list(map(float, time_string.split(",")))
321        return time_values

Parse current input of time value input.

def get_creation_temperature_values(self) -> list:
323    def get_creation_temperature_values(self) -> list:
324        """Parse current input of temperature value input."""
325        temperature_string = self.creation_temperature_input.value
326        temperature_values = list(map(int, temperature_string.split(",")))
327        return temperature_values

Parse current input of temperature value input.

def save_new_fibre_volume_content(self, ui_element=None):
329    def save_new_fibre_volume_content(self, ui_element=None):
330        """Save currently defined value of fibre volume content to store as new entry.
331
332        Args:
333            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
334        """
335        new_id = max(self.fvc_data.keys()) + 1 if self.fvc_data else 1
336        new_fvc = configuration.FibreVolumeContent(
337            uniq_id = new_id,
338            value = self.creation_fvc_input.value,
339            conn = self.conn)
340        new_fvc.save_entry_to_store()
341        self.load_fvc_data(pre_select=new_id)

Save currently defined value of fibre volume content to store as new entry.

Args: ui_element: Override for ipywidgets to not pass the UI element that triggered the event

def save_new_timeline(self, ui_element=None):
343    def save_new_timeline(self, ui_element=None):
344        """Save currently defined values of temperature graph to store as new entry.
345
346        Args:
347            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
348        """
349        new_id = max(self.graph_data.keys()) + 1 if self.graph_data else 1
350        new_graph = configuration.TemperatureGraph(
351            uniq_id = new_id,
352            name = self.creation_name_input.value,
353            time_data = self.get_creation_time_values(),
354            temperature_data = self.get_creation_temperature_values(),
355            conn = self.conn)
356        new_graph.save_entry_to_store()
357        self.load_temperature_data(pre_select=new_id)

Save currently defined values of temperature graph to store as new entry.

Args: ui_element: Override for ipywidgets to not pass the UI element that triggered the event

def save_new_input_set(self, ui_element=None):
359    def save_new_input_set(self, ui_element=None):
360        """Save currently defined selections of temperature graph and fibre volume content to store as new entry.
361
362        Args:
363            ui_element: Override for ipywidgets to not pass the UI element that triggered the event
364        """
365        new_id = max(self.input_set_data.keys()) + 1 if self.input_set_data else 1
366        new_set = configuration.MaterialHardeningInputDataSet(
367            uniq_id = new_id,
368            temperature_graph = self.graph_data[self.curve_selection.value],
369            fibre_volume_content = self.fvc_data[self.fibre_volume_content_input.value],
370            conn = self.conn)
371        self.graph_data[self.curve_selection.value].save_entry_to_store()
372        self.fvc_data[self.fibre_volume_content_input.value].save_entry_to_store()
373        new_set.save_entry_to_store()
374        self.load_input_set_data()

Save currently defined selections of temperature graph and fibre volume content to store as new entry.

Args: ui_element: Override for ipywidgets to not pass the UI element that triggered the event

def apply_styling(self):
376    def apply_styling(self):
377        """Apply CSS hack to notebook for better styling than native Jupyter Widget styles."""
378        css = """
379            <style>
380            {}
381            {}
382            </style>
383        """.format(global_style.global_css, style.local_css)
384        return widgets.HTML(css)

Apply CSS hack to notebook for better styling than native Jupyter Widget styles.