def __init__(self, app, allow_move=False): self.app = app launcher = load_widget(app.name) launcher.layout = ipw.Layout(width="900px") update_info = UpdateAvailableInfoWidget() ipw.dlink((app, 'updates_available'), (update_info, 'updates_available')) update_info.layout.margin = "0px 0px 0px 800px" if allow_move: app_widget_move_buttons = create_app_widget_move_buttons(app.name) body = ipw.HBox([launcher, app_widget_move_buttons]) else: body = launcher footer = ipw.HTML( "<a href=./single_app.ipynb?app={}><button>Manage App</button></a>" .format(app.name), layout={'width': 'initial'}) if app.url: footer.value += ' <a href="{}"><button>URL</button></a>'.format( app.url) footer.layout.margin = "0px 0px 0px 700px" super().__init__(children=[update_info, body, footer])
def __init__(self, options: Sequence[str], *args, **kwargs): """Create a dropdown button. Parameters ---------- options : Sequence[str] The options to display in the widget. """ super().__init__(*args, **kwargs) self.options = options self.dropdown = widgets.Dropdown( options=[str(option) for option in self.options], description="Label:", ) widgets.dlink((self, "options"), (self.dropdown, "options")) self.dropdown.observe(self._change_selection) self.button = widgets.Button( description="Submit.", tooltip="Submit label.", button_style="success", ) self.button.on_click(self._handle_click) self.hints: DefaultDict[str, widgets.Output] = defaultdict(widgets.Output) self.children = [ widgets.HBox([self.dropdown, self.button]), self.hints[self.dropdown.value], ]
def __init__(self, **kwargs): self.work_chains_prompt = ipw.HTML( "<b>Select workflow or start new:</b> ") self.work_chains_selector = ipw.Dropdown( options=[("New workflow...", self._NO_PROCESS)], layout=ipw.Layout(min_width="300px", flex="1 1 auto"), ) ipw.dlink( (self.work_chains_selector, "value"), (self, "value"), transform=lambda pk: None if pk is self._NO_PROCESS else pk, ) self.refresh_work_chains_button = ipw.Button(description="Refresh") self.refresh_work_chains_button.on_click(self.refresh_work_chains) self._refresh_lock = Lock() self._refresh_thread = None self._stop_refresh_thread = Event() self._update_auto_refresh_thread_state() super().__init__( children=[ self.work_chains_prompt, self.work_chains_selector, self.refresh_work_chains_button, ], **kwargs, )
def __init__(self, manager, description=None, **kwargs): self.manager = manager if description is None: description = ipw.Label( 'Select a structure from one of the following sources and then ' 'click "Confirm" to go to the next step.') self.description = description self.structure_name_text = ipw.Text( placeholder='[No structure selected]', description='Selected:', disabled=True, layout=ipw.Layout(width='auto', flex="1 1 auto"), ) self.confirm_button = ipw.Button( description='Confirm', tooltip="Confirm the currently selected structure and go to the next step.", button_style='success', icon='check-circle', disabled=True, layout=ipw.Layout(width='auto'), ) self.confirm_button.on_click(self.confirm) # Create directional link from the (read-only) 'structure_node' traitlet of the # structure manager to our 'structure' traitlet: ipw.dlink((manager, 'structure_node'), (self, 'structure')) super().__init__( children=[self.description, self.manager, self.structure_name_text, self.confirm_button], **kwargs)
def __init__(self, **kwargs): super(VizHeatmapBqplot, self).__init__(**kwargs) self.fig.padding_y = 0 self.fig.fig_margin = {'bottom': 80, 'left': 60, 'right': 10, 'top': 60} grid = self.state.grid if self.state.grid_sliced is not None: grid = self.state.grid_sliced if self.normalize: grid = grid/grid.sum() self.color_scale = bqplot.ColorScale(scheme='Blues') self.color_axis = bqplot.ColorAxis(scale=self.color_scale, label='counts', scheme='Blues') self.fig.axes = self.fig.axes + [self.color_axis] self.scales = {'row': self.y_scale, 'column': self.x_scale, 'color': self.color_scale} # self.scales = {'row': bqplot.OrdinalScale(), 'column': bqplot.OrdinalScale(), 'color': self.color_scale} self.heatmap = bqplot.GridHeatMap(color=grid.T[:,::], scales=self.scales) self.update_heatmap() self.fig.marks = self.fig.marks + [self.heatmap] self.state.observe(self.update_heatmap, 'grid') widgets.dlink((self.state, 'x_expression'), (self.x_axis, 'label')) widgets.dlink((self.state, 'y_expression'), (self.y_axis, 'label')) @self.output.capture() # @vaex.jupyter.debounced(DEBOUNCE_SLICE) def on_bar_hover(bar, event): # print(event) #set_transparancy(event['data']['sub_index'], event['data']['index']) #print(event['data']['index']) self.state.y_slice = event['data']['row'] self.state.x_slice = event['data']['column'] self.set_transparancy() #print(viz_state.grid.sum()) self.heatmap.on_hover(on_bar_hover)
def bind(self, widget, trait): """ Binding a widget input 'v_model' trait to a trait of the model. The binding will be unidirectionnal for the sake of some custom widget that does not support it. This wrapper avoid to import the ipywidgets lib everywhere and reduce the number of parameters Some existence check are also performed and will throw an error if the trait doesn't exist Params: widget (v.widget): any input widget with a v_model trait trait (str): the name of a trait of the current model Return: self """ # check trait existence getattr(self, trait) # bind them dlink((widget, 'v_model'),(self, trait)) # maybe I would add the possiblity to add an alert to display stuff to the user with the same options as in alert.bind return self
def __init__(self, **kwargs): self.message_area = ipw.Output() self.workchain_settings = WorkChainSettings() self.kpoints_settings = KpointSettings() self.pseudo_family_selector = PseudoFamilySelector() self.codes_selector = CodeSettings() self.resources_config = ResourceSelectionWidget() self.set_trait("builder_parameters", self._default_builder_parameters()) self._setup_builder_parameters_update() self.codes_selector.pw.observe(self._update_state, "selected_code") self.codes_selector.pw.observe(self._set_num_mpi_tasks_to_default, "selected_code") self.tab = ipw.Tab( children=[ self.workchain_settings, ], layout=ipw.Layout(min_height="250px"), ) self.tab.set_title(0, "Workflow") self.submit_button = ipw.Button( description="Submit", tooltip="Submit the calculation with the selected parameters.", icon="play", button_style="success", layout=ipw.Layout(width="auto", flex="1 1 auto"), disabled=True, ) self.submit_button.on_click(self._on_submit_button_clicked) self.expert_mode_control = ipw.ToggleButton( description="Expert mode", tooltip="Activate Expert mode for access to advanced settings.", value=True, ) ipw.link((self, "expert_mode"), (self.expert_mode_control, "value")) self._update_builder_parameters() self.builder_parameters_view = ipw.HTML(layout=ipw.Layout( width="auto")) ipw.dlink( (self, "builder_parameters"), (self.builder_parameters_view, "value"), transform=lambda p: '<pre style="line-height: 100%">' + pformat( p, indent=2, width=200) + "</pre>", ) super().__init__(children=[ self.message_area, self.tab, ipw.HBox([self.submit_button, self.expert_mode_control]), ])
def display( self, function, target_boundaries, boundaries, kw_names=None): ''' Display the explainer for a given function. Parameters ---------- function : Function to interact with. boundaries : Dictionary containing a tuple of 2 elements for parameters of the function, with the boundaries of the slider generated for each parameter. target_boundaries : A tuple of 2 values with the boundaries for the result returned by the function. kw_names : If the function uses keyworded variable-length argument list, you must pass its names in kw_names. ''' fspec = inspect.getfullargspec(function) arguments = fspec.args kw_name = fspec.varkw if len(arguments) == 0 and kw_name is not None: arguments = kw_names # Generate widgets. caption = widgets.Label( value=self.title_text, layout=widgets.Layout( display='flex', flex_flow='column', align_items='center')) widget_dic = {} for a in arguments: bound_min, bound_max = boundaries.get( a, (sys.float_info.min, sys.float_info.max)) new_widget = _generate_widget( boundaries=(bound_min, bound_max), description=a, width=self.width, step=self.step, ) widget_dic[a] = new_widget bound_min, bound_max = target_boundaries result_widget = _generate_widget( boundaries=(bound_min, bound_max), description='<b>Result</b>', width=self.width, step=self.step, ) # Connect widgets to target result. for wid in widget_dic.values(): #target_values = self.boundaries.copy() widgets.dlink( (wid, 'value'), (result_widget, 'value'), transform=lambda v: function(**{x: widget_dic[x].value for x in arguments}), ) wid_list = [w for w in widget_dic.values()] wid_list.append(result_widget) display(caption, *wid_list)
def _default_Pipe(self): from .flow import BrowserTextSizer, DefaultFlow progress_bar = self.get_tool(PipelineProgressBar) pipeline = DefaultFlow(on_progress=progress_bar.update) for pipe in pipeline.pipes: if isinstance(pipe, BrowserTextSizer): W.dlink((self, "style"), (pipe, "style")) return pipeline
def _link_widget_to_model( self, name: str, widget: widgets.Widget, model: traitlets.HasTraits) -> Iterator[traitlets.link]: """Link a single widget to a model. Respect read-only relationships, and delegate linking to widget if it implements the necessary interface. :param name: name of model field :param widget: widget instance :param model: model instance :return: """ # Allow widget to handle linking if hasattr(widget, "link_to_model"): yield from widget.link_to_model(model, self, name) return # Infer read-only state from initial widget disabled state is_read_only = getattr(widget, "disabled", False) link_factory = widgets.dlink if is_read_only else widgets.link # Allow widget to be disabled when container is disabled if hasattr(widget, "disabled") and not is_read_only: yield widgets.dlink((self, "disabled"), (widget, "disabled")) yield link_factory((model, name), (widget, "value"))
def __init__(self, **kwargs): self.sections = ( ("Structure details", StructureSummary()), ("Sites", StructureSites()), ) super().__init__( children=tuple(_[1] for _ in self.sections), layout=ipw.Layout(width="auto", height="345px"), **kwargs, ) for index, title in enumerate([_[0] for _ in self.sections]): self.set_title(index, title) for widget in self.children: ipw.dlink((self, "entity"), (widget, "structure"))
def gui_select_files_widget(name, key): text_wc_low = widgets.Text(placeholder="*{}*".format(key), layout={'border': '1px solid black', "width":"100px"}) out_files_low = widgets.Output(layout={'border': '1px solid black', "width":"800px", "min_height": "40px"}) @out_files_low.capture(clear_output=True, wait=True) def text_wc_low_changed(change): if not change.new: return fl = get_file_list(text_in_dir.value, change.new) if len(fl) == 0: print("no files match...") else: for f in fl: print(f.name) params[key] = change.new text_wc_low.observe(text_wc_low_changed, 'value') label_in_dir = widgets.Label() mylink = widgets.dlink((text_in_dir, 'value'), (label_in_dir, 'value')) file_select_widget = widgets.VBox([widgets.Label(name), widgets.HBox([label_in_dir, widgets.Label("/"), text_wc_low]), out_files_low]) text_wc_low.value = params[key] return file_select_widget
def __init__(self, **kwargs): self._control = None super().__init__(**kwargs) self.output = widgets.Output() self.plot = self.create_plot() self.children = (self.progress_widget, self.plot.widget, self.output) widgets.dlink((self, 'tool'), (self.plot, 'tool')) # first dlink our model to the plot widgets.dlink((self.model.x, 'expression'), (self.plot, 'x_label'), transform=str) self.plot.y_label = "count" # set before we observe changes if self.model.x.min is not None: self.plot.x_min = self.model.x.min if self.model.x.max is not None: self.plot.x_max = self.model.x.max # then we sync the limits of the plot with a debouce to the model traitlets.dlink((self.plot, 'x_min'), (self.model.x, 'min')) traitlets.dlink((self.plot, 'x_max'), (self.model.x, 'max')) self.model.observe(self.update_data, ['grid', 'grid_sliced']) self.observe(self.update_data, ['normalize', 'dimension_groups']) @self.output.capture() @vaex.jupyter.debounced(DEBOUNCE_HOVER_SLICED) def unhighlight(): self.plot.highlight(None) self.model.x_slice = None @self.output.capture() # @vaex.jupyter.debounced(DEBOUNCE_SLICE) def on_bar_hover(bar, event): self.model.x_slice = event['data']['index'] self.plot.highlight(self.model.x_slice) unhighlight() self.plot.mark.on_hover(on_bar_hover) if self.model.grid is not None: self.update_data()
def follow(self, detach=False): """Initiate following the process with or without blocking.""" if self.process is None: self.output.value = """<font color="red"> ProcessFollowerWidget: process is set to 'None', nothing to follow. </font>""" return self.output.value = "" if self._monitor is None: self._monitor = ProcessMonitor( process=self.process, callbacks=[self.update], on_sealed=self._run_after_completed, timeout=self.update_interval, ) ipw.dlink((self, "process"), (self._monitor, "process")) if not detach: self._monitor.join()
def __init__(self): # define a title title = sw.Html(tag="h4", children=[cm.widget.alert.surface.label]) # define the slider with the value vizualizer slider = sw.Slider(v_model=0, min=0, max=100, thumb_label=True, class_="mt-5") number = sw.TextField(suffix="ha", readonly=True, xs2=True) # create the widget super().__init__(children=[title, slider]) # add links dlink((slider, "v_model"), (self, "v_model")) dlink((slider, "v_model"), (number, "v_model"))
def __init__(self, parameter, downloadable=True, **kwargs): import pandas as pd # Here we are defining properties of 'df' class (specified while exporting pandas table into html). # Since the exported object is nothing more than HTML table, all 'standard' HTML table settings # can be applied to it as well. # For more information on how to controle the table appearance please visit: # https://css-tricks.com/complete-guide-table-element/ self.widget = ipw.HTML() ipw.dlink((self, "value"), (self.widget, "value")) self.value += """ <style> .df { border: none; } .df tbody tr:nth-child(odd) { background-color: #e5e7e9; } .df tbody tr:nth-child(odd):hover { background-color: #f5b7b1; } .df tbody tr:nth-child(even):hover { background-color: #f5b7b1; } .df tbody td { min-width: 300px; text-align: center; border: none } .df th { text-align: center; border: none; border-bottom: 1px solid black;} </style> """ pd.set_option("max_colwidth", 40) dataf = pd.DataFrame( [(key, value) for key, value in sorted(parameter.get_dict().items())], columns=["Key", "Value"], ) self.value += dataf.to_html( classes="df", index=False) # specify that exported table belongs to 'df' class # this is used to setup table's appearance using CSS if downloadable: payload = base64.b64encode( dataf.to_csv(index=False).encode()).decode() fname = f"{parameter.pk}.csv" to_add = """Download table in csv format: <a download="{filename}" href="data:text/csv;base64,{payload}" target="_blank">{title}</a>""" self.value += to_add.format(filename=fname, payload=payload, title=fname) super().__init__([self.widget], **kwargs)
def __init__(self, **kwargs): self.install_button = ipw.Button( description='Install pseudos', button_style='warning', icon='cloud-download', tooltip='Download and install the SSSP pseudo potential families.', disabled=True, layout=ipw.Layout(width='140px'), ) self.install_button.on_click(lambda _: self.download()) self.spinner = Spinner() ipw.dlink((self, 'busy'), (self.spinner, 'enabled')) kwargs.setdefault('layout', ipw.Layout(width='180px')) super().__init__(children=[self.install_button, self.spinner], **kwargs) self._refresh_installed()
def __init__(self, **kwargs): self.work_chains_selector = ipw.Dropdown( description="WorkChain", options=[('New calculation...', self._NO_PROCESS)], layout=ipw.Layout(width='auto', flex="1 1 auto"), ) ipw.dlink((self.work_chains_selector, 'value'), (self, 'value'), transform=lambda pk: None if pk is self._NO_PROCESS else pk) self.refresh_work_chains_button = ipw.Button(description='Refresh') self.refresh_work_chains_button.on_click(self.refresh_work_chains) self._refresh_lock = Lock() self._refresh_thread = None self._stop_refresh_thread = Event() self._update_auto_refresh_thread_state() super().__init__(children=[ self.work_chains_selector, self.refresh_work_chains_button ], **kwargs)
def __init__(self, **kwargs): self.process_tree = ProcessNodesTreeWidget() ipw.dlink((self, "process"), (self.process_tree, "process")) self.node_view = NodeViewWidget(layout={ "width": "auto", "height": "auto" }) ipw.dlink( (self.process_tree, "selected_nodes"), (self.node_view, "node"), transform=lambda nodes: nodes[0] if nodes else None, ) self.process_status = ipw.VBox( children=[self.process_tree, self.node_view]) # Setup process monitor self.process_monitor = ProcessMonitor( timeout=0.2, callbacks=[ self.process_tree.update, self._update_state, ], ) ipw.dlink((self, "process"), (self.process_monitor, "process")) super().__init__([self.process_status], **kwargs)
def __init__(self, embedded: bool = False, database_limit: int = None, **kwargs): database_limit = database_limit if database_limit and database_limit > 0 else 10 layout = ipw.Layout(width="100%", height="auto") self.chooser = ProviderImplementationChooser( child_db_limit=database_limit, **kwargs) self.summary = ProviderImplementationSummary( **kwargs) if not embedded else None if embedded: super().__init__(n_rows=1, n_columns=1, layout=layout, **kwargs) self[:, :] = self.chooser else: super().__init__(n_rows=1, n_columns=31, layout=layout, **kwargs) self[:, :10] = self.chooser self[:, 11:] = self.summary ipw.dlink((self.chooser, "provider"), (self.summary, "provider")) ipw.dlink( (self.chooser, "database"), (self.summary, "database"), transform=(lambda db: db[1] if db and db is not None else None), ) ipw.dlink((self.chooser, "database"), (self, "database"))
def __init__(self, **kwargs): self._control = None super(VizHistogramBqplot, self).__init__(**kwargs) # using dlink allows us to change the label if len(self.axes) > 0: widgets.dlink((self.state, 'x_expression'), (self.x_axis, 'label')) self.y_axis.label = 'counts' else: widgets.dlink((self.state, 'x_expression'), (self.fig, 'title')) self.fig.marks = self.fig.marks + self.marks self.state.observe(self.update_data, ['grid', 'grid_sliced']) self.observe(self.update_data, ['normalize']) @self.output.capture() # @vaex.jupyter.debounced(DEBOUNCE_SLICE) def on_hover(bar, event): #set_transparancy(event['data']['sub_index'], event['data']['index']) # print(event['data']['index']) self.state.x_slice = event['data']['index'] self.set_transparancy(self.state.x_slice) #print(viz_state.grid.sum()) self.mark.on_hover(on_hover) self.reset_opacities()
def __init__( self, embedded: bool = True, title: str = None, **kwargs, ) -> None: providers_header = ipw.HTML("<h4>Select a provider</h4>") providers = OptimadeQueryProviderWidget( embedded=embedded, width_ratio=kwargs.pop("width_ratio", None), width_space=kwargs.pop("width_space", None), database_limit=kwargs.pop("database_limit", None), disable_providers=kwargs.pop("disable_providers", self._disable_providers), skip_databases=kwargs.pop("skip_databases", self._skip_databases), provider_database_groupings=kwargs.pop( "provider_database_groupings", self._database_grouping), ) filters = OptimadeQueryFilterWidget( embedded=embedded, button_style=kwargs.pop("button_style", None), result_limit=kwargs.pop("results_limit", None), subparts_order=kwargs.pop("subparts_order", None), ) ipw.dlink((providers, "database"), (filters, "database")) filters.observe(self._update_structure, names="structure") self.title = title or "OPTIMADE" layout = kwargs.pop("layout", {"width": "auto", "height": "auto"}) super().__init__( children=(providers_header, providers, filters), layout=layout, **kwargs, )
def __init__(self, **kwargs): self._set_kpoints_distance_automatically = ipw.Checkbox( description="Use default k-points distance.", indent=False, value=True, ) self._kpoints_distance = ipw.FloatText( value=self.kpoints_distance_default, step=0.05, description="K-points distance:", disabled=False, style={"description_width": "initial"}, ) ipw.dlink( (self._set_kpoints_distance_automatically, "value"), (self._kpoints_distance, "disabled"), ) self._kpoints_distance.observe(self.set_kpoints_distance_trait, "value") self._set_kpoints_distance_automatically.observe( self.set_kpoints_distance_trait, "value") self.set_kpoints_distance_trait() super().__init__( children=[ self.kpoints_distance_description, ipw.HBox([ self._set_kpoints_distance_automatically, self._kpoints_distance ]), ], layout=ipw.Layout(justify_content="space-between"), **kwargs, )
def __init__( self, embedded: bool = True, title: str = None, **kwargs, ) -> None: providers = OptimadeQueryProviderWidget(embedded=embedded) filters = OptimadeQueryFilterWidget(embedded=embedded) ipw.dlink((providers, 'database'), (filters, 'database')) filters.observe(self._update_structure, names='structure') self.title = title if title is not None else 'OPTIMADE' layout = kwargs.pop('layout') if 'layout' in kwargs else { 'width': 'auto', 'height': 'auto' } super().__init__( children=(providers, filters), layout=layout, **kwargs, )
def schedule_dlink(self, target, update_interval, transport, js=False): if js and transport: # use Tone.js Draw for better synchronization # of sound and visuals draw = True else: draw = False self.schedule_repeat(update_interval, transport, draw=draw) if js: link = ipywidgets.jsdlink((self, self.observed_trait), target) else: link = ipywidgets.dlink((self, self.observed_trait), target) return ToneDirectionalLink(self, link)
def __init__( self, embedded: bool = False, database_limit: int = None, width_ratio: Union[Tuple[int, int], List[int]] = None, width_space: int = None, **kwargs, ): # At the moment, the pagination does not work properly as each database is not tested for # validity immediately, only when each "page" is loaded. This can result in the pagination # failing. Instead the default is set to 100 in an attempt to never actually do paging. database_limit = ( database_limit if database_limit and database_limit > 0 else 100 ) layout = ipw.Layout(width="100%", height="auto") self.chooser = ProviderImplementationChooser( child_db_limit=database_limit, **kwargs ) self.summary = ProviderImplementationSummary(**kwargs) if not embedded else None if embedded: super().__init__(n_rows=1, n_columns=1, layout=layout, **kwargs) self[:, :] = self.chooser else: if width_ratio is not None and isinstance(width_ratio, (tuple, list)): if len(width_ratio) != 2 or sum(width_ratio) <= 0: width_ratio = (10, 21) warnings.warn( "width_ratio is not a list or tuple of length 2. " f"Will use defaults {width_ratio}.", OptimadeClientWarning, ) else: width_ratio = (10, 21) width_space = width_space if width_space is not None else 1 super().__init__( n_rows=1, n_columns=sum(width_ratio), layout=layout, **kwargs ) self[:, : width_ratio[0]] = self.chooser self[:, width_ratio[0] + width_space :] = self.summary ipw.dlink((self.chooser, "provider"), (self.summary, "provider")) ipw.dlink( (self.chooser, "database"), (self.summary, "database"), transform=(lambda db: db[1] if db and db is not None else None), ) ipw.dlink((self.chooser, "database"), (self, "database"))
def __init__(self, output, presenter, map=None, zoom=12, **kwargs): super().__init__(**kwargs) self.output = output self.presenter = presenter self.map = map self._zoom = zoom self.last_image_layer = None center = self.x_min + (self.x_max - self.x_min) / 2, self.y_min + ( self.y_max - self.y_min) / 2 center = center[1], center[0] self.map = ll.Map(center=center, zoom=self._zoom) widgets.dlink((self.map, 'west'), (self, 'x_min')) widgets.dlink((self.map, 'east'), (self, 'x_max')) widgets.dlink((self.map, 'north'), (self, 'y_min')) widgets.dlink((self.map, 'south'), (self, 'y_max')) self.widget = self.map
def __init__(self, **kwargs): self.progress_bar = ProgressBarWidget() self.log_output = ProcessOutputFollower( layout=ipw.Layout(min_height='150px', max_height='400px')) self.process_id_text = ipw.Text( value='', description='Process:', layout=ipw.Layout(width='auto', flex="1 1 auto"), disabled=True, ) ipw.dlink((self, 'process'), (self.process_id_text, 'value'), transform=lambda proc: str(proc)) ipw.dlink((self, 'process'), (self.log_output, 'process')) ipw.dlink((self, 'process'), (self.progress_bar, 'process')) super().__init__(children=[ self.progress_bar, self.process_id_text, self.log_output, ], **kwargs)
def kwarg_to_ipywidget(key, val, update, slider_format_string, play_button=None): """ Parameters ---------- key : str val : str or number or tuple, or set or array-like The value to be interpreted and possibly transformed into an ipywidget update : callable The function to be called when the value of the generated widget changes. Must accept a dictionary *change* and an array-like *values* slider_format_string : str The format string to use for slider labels play_button : bool or None or str, default: None If true and the output widget is a slider then added a play button widget on the left. Also accepts 'left' or 'right' to specify the play button position. Returns ------- init_val The initial value of the widget. control The generated widget. This may be the raw widget or a higher level container widget (e.g. HBox) depending on what widget was generated. If a fixed value is returned then control will be *None* """ init_val = 0 control = None if isinstance(val, set): if len(val) == 1: val = val.pop() if isinstance(val, tuple): # want the categories to be ordered pass else: # fixed parameter return val, None else: val = list(val) # categorical if len(val) <= 3: selector = widgets.RadioButtons(options=val) else: selector = widgets.Select(options=val) selector.observe(partial(update, values=val), names="index") return val[0], selector elif isinstance(val, widgets.Widget) or isinstance(val, widgets.fixed): if not hasattr(val, "value"): raise TypeError( "widgets passed as parameters must have the `value` trait." "But the widget passed for {key} does not have a `.value` attribute" ) if isinstance(val, widgets.fixed): return val, None elif (isinstance(val, widgets.Select) or isinstance(val, widgets.SelectionSlider) or isinstance(val, widgets.RadioButtons)): # all the selection widget inherit a private _Selection :( # it looks unlikely to change but still would be nice to just check # if its a subclass val.observe(partial(update, values=val.options), names="index") else: # set values to None and hope for the best val.observe(partial(update, values=None), names="value") return val.value, val # val.observe(partial(update, key=key, label=None), names=["value"]) else: if isinstance(val, tuple) and val[0] in ["r", "range", "rang", "rage"]: # also check for some reasonably easy mispellings if isinstance(val[1], (np.ndarray, list)): vals = val[1] else: vals = np.linspace(*val[1:]) label = widgets.Label(value=str(vals[0])) slider = widgets.IntRangeSlider(value=(0, vals.size - 1), min=0, max=vals.size - 1, readout=False, description=key) widgets.dlink( (slider, "value"), (label, "value"), transform=lambda x: slider_format_string.format(vals[x[0]]) + " - " + slider_format_string.format(vals[x[1]]), ) slider.observe(partial(update, values=vals), names="value") controls = widgets.HBox([slider, label]) return vals[[0, -1]], controls if isinstance(val, tuple) and len(val) in [2, 3]: # treat as an argument to linspace # idk if it's acceptable to overwrite kwargs like this # but I think at this point kwargs is just a dict like any other val = np.linspace(*val) val = np.atleast_1d(val) if val.ndim > 1: raise ValueError( f"{key} is {val.ndim}D but can only be 1D or a scalar") if len(val) == 1: # don't need to create a slider return val, None else: # params[key] = val[0] label = widgets.Label(value=slider_format_string.format(val[0])) slider = widgets.IntSlider(min=0, max=val.size - 1, readout=False, description=key) widgets.dlink( (slider, "value"), (label, "value"), transform=lambda x: slider_format_string.format(val[x]), ) slider.observe(partial(update, values=val), names="value") if play_button is not None and play_button is not False: play = widgets.Play(min=0, max=val.size - 1, step=1) widgets.jslink((play, "value"), (slider, "value")) if isinstance(play_button, str) and play_button.lower() == "right": control = widgets.HBox([slider, label, play]) else: control = widgets.HBox([play, slider, label]) else: control = widgets.HBox([slider, label]) return val[0], control
def table_app(df): def save_filtered_data(_): filtered_df = filter_df(df, order_by=order_by.value, ascending=ascending.value, required=filter_selector.value, search_column=search_column.value, search_term=search_term.value) filtered_df.to_csv(save_fn.value) save_status.value = '\t sucessfully saved {} rows as {}.'.format( len(filtered_df), save_fn.value) def plot_filtered(df, required, search_column, search_term, plot_column): filtered_df = filter_df(df, order_by=order_by.value, required=required, search_column=search_column, search_term=search_term) plot_column_dist(df=filtered_df, column=plot_column) nb_items = widgets.Dropdown(options=[10, 20, 50], description='items per page', layout=Layout(width='20%')) order_by = widgets.Dropdown(options=sorted(df.keys()), description='order by') ascending = widgets.ToggleButton(value=True, description='ascending') sorting = widgets.HBox([order_by, ascending, nb_items], layout=Layout(height='50px')) filter_selector = widgets.SelectMultiple(options=sorted(df.keys())) filter_tip = widgets.VBox([ widgets.HTML('Select multiple by dragging or ctrl + click'), widgets.HTML('Deselect with ctrl + click') ]) filtering = widgets.HBox([filter_selector, filter_tip]) save_button = widgets.Button(description='save') save_fn = widgets.Text('filtered_data.csv') save_button.on_click(save_filtered_data) save_status = widgets.Label() saving = widgets.HBox([save_fn, save_button, save_status]) search_term = widgets.Text('', tooltip='Search') search_column = widgets.Dropdown(options=df.keys()) plot_column = widgets.Dropdown(options=df.keys()) column_dist = interactive_output( plot_filtered, dict(df=fixed(df), search_column=search_column, required=filter_selector, search_term=search_term, plot_column=plot_column)) column_plot_box = widgets.VBox( [widgets.Label('Plot Columns'), plot_column, column_dist]) search_box = widgets.VBox( [widgets.Label('Search Columns'), search_column, search_term]) searching = widgets.TwoByTwoLayout(top_left=search_box, top_right=column_plot_box) widgets.dlink((search_column, 'value'), (plot_column, 'value')) accordion = widgets.Tab(children=[sorting, filtering, searching, saving]) accordion.set_title(0, 'Sorting') accordion.set_title(1, 'Required Values') accordion.set_title(2, 'Searching') accordion.set_title(3, 'Save filtered Data') interactive_table = interactive_output( show_filtered_df, dict(df=fixed(df), order_by=order_by, nb_items=nb_items, required=filter_selector, ascending=ascending, search_column=search_column, search_term=search_term)) display(widgets.VBox([accordion, interactive_table]))