Beispiel #1
0
def ipy_axes_gui(obj, **kwargs):
    wdict = {}
    nav_widgets = []
    sig_widgets = []
    i = 0
    for axis in obj.navigation_axes:
        wd = _get_axis_widgets(axis, display=False)
        nav_widgets.append(wd["widget"])
        wdict["axis{}".format(i)] = wd["wdict"]
        i += 1
    for j, axis in enumerate(obj.signal_axes):
        wd = _get_axis_widgets(axis, display=False)
        sig_widgets.append(wd["widget"])
        wdict["axis{}".format(i + j)] = wd["wdict"]
    nav_accordion = ipywidgets.Accordion(nav_widgets)
    sig_accordion = ipywidgets.Accordion(sig_widgets)
    nav_titles = [f"Axis {i}" for i in range(obj.navigation_dimension)]
    set_title_container(nav_accordion, nav_titles)
    sig_titles = [f"Axis {j+obj.navigation_dimension+1}" for j in
                  range(obj.signal_dimension)]
    set_title_container(sig_accordion, sig_titles)

    tabs = ipywidgets.HBox([nav_accordion, sig_accordion])
    return {
        "widget": tabs,
        "wdict": wdict,
    }
def interactive_range_ipy(obj, **kwargs):
    # Define widgets
    wdict = {}
    axis = obj.axis
    left = ipywidgets.FloatText(disabled=True)
    right = ipywidgets.FloatText(disabled=True)
    units = ipywidgets.Label()
    help_text = ipywidgets.HTML(
        "Click on the signal figure and drag to the right to select a signal "
        "range. Press `Apply` to perform the operation or `Close` to cancel.",
    )
    help = ipywidgets.Accordion(children=[help_text], selected_index=None)
    set_title_container(help, ["Help"])
    close = ipywidgets.Button(
        description="Close",
        tooltip="Close widget and remove span selector from the signal figure."
    )
    apply = ipywidgets.Button(
        description="Apply",
        tooltip="Perform the operation using the selected range.")
    wdict["left"] = left
    wdict["right"] = right
    wdict["units"] = units
    wdict["help_text"] = help_text
    wdict["close_button"] = close
    wdict["apply_button"] = apply

    # Connect
    link((obj, "ss_left_value"), (left, "value"))
    link((obj, "ss_right_value"), (right, "value"))
    link((axis, "units"), (units, "value"))

    def on_apply_clicked(b):
        if obj.ss_left_value != obj.ss_right_value:
            obj.span_selector_switch(False)
            for method, cls in obj.on_close:
                method(cls, obj.ss_left_value, obj.ss_right_value)
            obj.span_selector_switch(True)

    apply.on_click(on_apply_clicked)

    box = ipywidgets.VBox([
        ipywidgets.HBox([left, units,
                         ipywidgets.Label("-"), right, units]), help,
        ipywidgets.HBox((apply, close))
    ])

    def on_close_clicked(b):
        obj.span_selector_switch(False)
        box.close()

    close.on_click(on_close_clicked)
    return {
        "widget": box,
        "wdict": wdict,
    }
def fit_component_ipy(obj, **kwargs):
    wdict = {}
    only_current = Checkbox()
    iterpath = enum2dropdown(obj.traits()["iterpath"])

    def disable_iterpath(change):
        iterpath.disabled = change.new

    only_current.observe(disable_iterpath, "value")

    wdict["only_current"] = only_current
    wdict["iterpath"] = iterpath
    help_text = HTML(
        "Click on the signal figure and drag to the right to select a"
        "range. Press `Fit` to fit the component in that range. If only "
        "current is unchecked the fit is performed in the whole dataset.",
        layout=ipywidgets.Layout(width="auto"))
    wdict["help_text"] = help_text

    help = Accordion(children=[help_text], selected_index=None)
    set_title_container(help, ["Help"])

    link((obj, "only_current"), (only_current, "value"))
    link((obj, "iterpath"), (iterpath, "value"))
    fit = Button(description="Fit", tooltip="Fit in the selected signal range")
    close = Button(
        description="Close",
        tooltip="Close widget and remove span selector from the signal figure."
    )
    wdict["close_button"] = close
    wdict["fit_button"] = fit

    def on_fit_clicked(b):
        obj._fit_fired()

    fit.on_click(on_fit_clicked)
    box = VBox([
        labelme("Only current", only_current),
        labelme("Iterpath", wdict["iterpath"]), help,
        HBox((fit, close))
    ])

    def on_close_clicked(b):
        obj.span_selector_switch(False)
        box.close()

    close.on_click(on_close_clicked)
    return {
        "widget": box,
        "wdict": wdict,
    }
def get_model_widget(obj, **kwargs):
    """Creates interactive notebook widgets for all components and
    parameters, if available.

    """
    children = []
    wdict = {}
    for component in obj:
        idict = component.gui(display=False,
                              toolkit="ipywidgets")["ipywidgets"]
        children.append(idict["widget"])
        wdict["component_{}".format(component.name)] = idict["wdict"]
    accordion = Accordion(children=children)
    set_title_container(accordion, [comp.name for comp in obj])
    return {"widget": accordion, "wdict": wdict}
def get_parameter_widget(obj, **kwargs):
    """Creates interactive notebook widgets for the parameter, if
    available.

    """
    if obj._number_of_elements == 1:
        return _get_value_widget(obj)
    else:
        wdict = {}
        par_widgets = []
        for i in range(obj._number_of_elements):
            thiswd = _get_value_widget(obj=obj, index=i)
            par_widgets.append(thiswd["widget"])
            wdict["element{}".format(i)] = thiswd["wdict"]
        update = Button(
            description="Update",
            tooltip="Unlike most other widgets, the multivalue parameter "
            "widgets do not update automatically when the value of the "
            "changes by other means. Use this button to update the values"
            "manually")

        def on_update_clicked(b):
            for value, container in zip(obj.value, par_widgets):

                minwidget = container.children[0]
                vwidget = container.children[1]
                maxwidget = container.children[2]
                if value < vwidget.min:
                    minwidget.value = value
                elif value > vwidget.max:
                    maxwidget.value = value
                vwidget.value = value

        update.on_click(on_update_clicked)
        wdict["update_button"] = update
        container = Accordion([VBox([update] + par_widgets)])
        set_title_container(container, [obj.name])

    return {
        "widget": container,
        "wdict": wdict,
    }
Beispiel #6
0
def show_preferences_widget(obj, **kwargs):
    ipytabs = {}
    wdict = {}
    for tab in obj.editable_traits():
        tabdict = {}
        wdict["tab_{}".format(tab)] = tabdict
        ipytab = []
        tabtraits = getattr(obj, tab).traits()
        for trait_name in getattr(obj, tab).editable_traits():
            trait = tabtraits[trait_name]
            widget = TRAITS2IPYWIDGETS[type(trait.trait_type)](trait,
                                                               get_label(
                                                                   trait,
                                                                   trait_name))
            ipytab.append(widget)
            tabdict[trait_name] = widget.children[1]
            link((getattr(obj, tab), trait_name),
                 (widget.children[1], "value"))
        ipytabs[tab] = ipywidgets.VBox(ipytab)
    # This defines the order of the tab in the widget
    titles = ["General", "GUIs", "Plot", "EELS", "EDS"]
    ipytabs_ = ipywidgets.Tab(children=[ipytabs[title] for title in titles])
    set_title_container(ipytabs_, titles)
    save_button = ipywidgets.Button(description="Save",
                                    tooltip="Make changes permanent")
    wdict["save_button"] = save_button

    def on_button_clicked(b):
        obj.save()

    save_button.on_click(on_button_clicked)

    container = ipywidgets.VBox([ipytabs_, save_button])
    return {
        "widget": container,
        "wdict": wdict,
    }
Beispiel #7
0
def get_ipy_navigation_sliders(obj, in_accordion=False,
                               random_position_button=False,
                               **kwargs):
    continuous_update = ipywidgets.Checkbox(True,
                                            description="Continuous update")
    wdict = {}
    wdict["continuous_update"] = continuous_update
    widgets = []
    for i, axis in enumerate(obj):
        axis_dict = {}
        wdict["axis{}".format(i)] = axis_dict
        iwidget = ipywidgets.IntSlider(
            min=0,
            max=axis.size - 1,
            readout=True,
            description="index"
        )
        link((continuous_update, "value"),
             (iwidget, "continuous_update"))
        link((axis, "index"), (iwidget, "value"))
        if hasattr(axis, "scale"):
            vwidget = ipywidgets.BoundedFloatText(
                min=axis.low_value,
                max=axis.high_value,
                step=axis.scale,
                description="value"
                # readout_format=".lf"
            )
        else:
            vwidget = ipywidgets.BoundedFloatText(
                min=0,
                max=axis.size - 1,
                #step=1,
                disabled=True,
                description="value"
            )
        link((continuous_update, "value"),
             (vwidget, "continuous_update"))
        link((axis, "value"), (vwidget, "value"))
        link((axis, "high_value"), (vwidget, "max"))
        link((axis, "low_value"), (vwidget, "min"))
        if hasattr(axis, "scale"):
            link((axis, "scale"), (vwidget, "step"))
        name = ipywidgets.Label(str(axis),
                                layout=ipywidgets.Layout(width="15%"))
        units = ipywidgets.Label(layout=ipywidgets.Layout(width="5%"))
        link((axis, "name"), (name, "value"))
        link((axis, "units"), (units, "value"))
        bothw = ipywidgets.HBox([name, iwidget, vwidget, units])
        # labeled_widget = labelme(str(axis), bothw)
        widgets.append(bothw)
        axis_dict["value"] = vwidget
        axis_dict["index"] = iwidget
        axis_dict["units"] = units

    if random_position_button:
        random_nav_position = ipywidgets.Button(
            description="Set random navigation position.",
            tooltip="Set random navigation position, useful to check the "
                     "method parameters.",
            layout=ipywidgets.Layout(width="auto"))

        def _random_navigation_position_fired(b):
            am = obj[0].axes_manager
            index = np.random.randint(0, am._max_index)
            am.indices = np.unravel_index(index,
                tuple(am._navigation_shape_in_array))[::-1]
        random_nav_position.on_click(_random_navigation_position_fired)

        wdict["random_nav_position_button"] = random_nav_position
        widgets.append(random_nav_position)

    widgets.append(continuous_update)
    box = ipywidgets.VBox(widgets)
    if in_accordion:
        box = ipywidgets.Accordion((box,))
        set_title_container(box, ["Navigation sliders"])
    return {"widget": box, "wdict": wdict}
def find_peaks2D_ipy(obj, **kwargs):
    wdict = {}
    # Define widgets
    # For "local max" method
    local_max_distance = ipywidgets.IntSlider(min=1, max=20, value=3)
    local_max_threshold = ipywidgets.FloatSlider(min=0, max=20, value=10)
    # For "max" method
    max_alpha = ipywidgets.FloatSlider(min=0, max=6, value=3)
    max_distance = ipywidgets.IntSlider(min=1, max=20, value=10)
    # For "minmax" method
    minmax_distance = ipywidgets.FloatSlider(min=0, max=6, value=3)
    minmax_threshold = ipywidgets.FloatSlider(min=0, max=20, value=10)
    # For "Zaefferer" method
    zaefferer_grad_threshold = ipywidgets.FloatSlider(min=0,
                                                      max=0.2,
                                                      value=0.1,
                                                      step=0.2 * 1E-1)
    zaefferer_window_size = ipywidgets.IntSlider(min=2, max=80, value=40)
    zaefferer_distance_cutoff = ipywidgets.FloatSlider(min=0,
                                                       max=100,
                                                       value=50)
    # For "stat" method
    stat_alpha = ipywidgets.FloatSlider(min=0, max=2, value=1)
    stat_window_radius = ipywidgets.IntSlider(min=5, max=20, value=10)
    stat_convergence_ratio = ipywidgets.FloatSlider(min=0, max=0.1, value=0.05)
    # For "Laplacian of Gaussians" method
    log_min_sigma = ipywidgets.FloatSlider(min=0, max=2, value=1)
    log_max_sigma = ipywidgets.FloatSlider(min=0, max=100, value=50)
    log_num_sigma = ipywidgets.FloatSlider(min=0, max=20, value=10)
    log_threshold = ipywidgets.FloatSlider(min=0, max=0.4, value=0.2)
    log_overlap = ipywidgets.FloatSlider(min=0, max=1, value=0.5)
    log_log_scale = ipywidgets.Checkbox()
    # For "Difference of Gaussians" method
    dog_min_sigma = ipywidgets.FloatSlider(min=0, max=2, value=1)
    dog_max_sigma = ipywidgets.FloatSlider(min=0, max=100, value=50)
    dog_sigma_ratio = ipywidgets.FloatSlider(min=0, max=3.2, value=1.6)
    dog_threshold = ipywidgets.FloatSlider(min=0, max=0.4, value=0.2)
    dog_overlap = ipywidgets.FloatSlider(min=0, max=1, value=0.5)
    # For "Cross correlation" method
    xc_distance = ipywidgets.FloatSlider(min=0, max=10., value=5.)
    xc_threshold = ipywidgets.FloatSlider(min=0, max=2., value=0.5)

    wdict["local_max_distance"] = local_max_distance
    wdict["local_max_threshold"] = local_max_threshold
    wdict["max_alpha"] = max_alpha
    wdict["max_distance"] = max_distance
    wdict["minmax_distance"] = minmax_distance
    wdict["minmax_threshold"] = minmax_threshold
    wdict["zaefferer_grad_threshold"] = zaefferer_grad_threshold
    wdict["zaefferer_window_size"] = zaefferer_window_size
    wdict["zaefferer_distance_cutoff"] = zaefferer_distance_cutoff
    wdict["stat_alpha"] = stat_alpha
    wdict["stat_window_radius"] = stat_window_radius
    wdict["stat_convergence_ratio"] = stat_convergence_ratio
    wdict["log_min_sigma"] = log_min_sigma
    wdict["log_max_sigma"] = log_max_sigma
    wdict["log_num_sigma"] = log_num_sigma
    wdict["log_threshold"] = log_threshold
    wdict["log_overlap"] = log_overlap
    wdict["log_log_scale"] = log_log_scale
    wdict["dog_min_sigma"] = dog_min_sigma
    wdict["dog_max_sigma"] = dog_max_sigma
    wdict["dog_sigma_ratio"] = dog_sigma_ratio
    wdict["dog_threshold"] = dog_threshold
    wdict["dog_overlap"] = dog_overlap
    wdict["xc_distance"] = xc_distance
    wdict["xc_threshold"] = xc_threshold

    # Connect
    link((obj, "local_max_distance"), (local_max_distance, "value"))
    link((obj, "local_max_threshold"), (local_max_threshold, "value"))
    link((obj, "max_alpha"), (max_alpha, "value"))
    link((obj, "max_distance"), (max_distance, "value"))
    link((obj, "minmax_distance"), (minmax_distance, "value"))
    link((obj, "minmax_threshold"), (minmax_threshold, "value"))
    link((obj, "zaefferer_grad_threshold"),
         (zaefferer_grad_threshold, "value"))
    link((obj, "zaefferer_window_size"), (zaefferer_window_size, "value"))
    link((obj, "zaefferer_distance_cutoff"),
         (zaefferer_distance_cutoff, "value"))
    link((obj, "stat_alpha"), (stat_alpha, "value"))
    link((obj, "stat_window_radius"), (stat_window_radius, "value"))
    link((obj, "stat_convergence_ratio"), (stat_convergence_ratio, "value"))
    link((obj, "log_min_sigma"), (log_min_sigma, "value"))
    link((obj, "log_max_sigma"), (log_max_sigma, "value"))
    link((obj, "log_num_sigma"), (log_num_sigma, "value"))
    link((obj, "log_threshold"), (log_threshold, "value"))
    link((obj, "log_overlap"), (log_overlap, "value"))
    link((obj, "log_log_scale"), (log_log_scale, "value"))
    link((obj, "dog_min_sigma"), (dog_min_sigma, "value"))
    link((obj, "dog_max_sigma"), (dog_max_sigma, "value"))
    link((obj, "dog_sigma_ratio"), (dog_sigma_ratio, "value"))
    link((obj, "dog_threshold"), (dog_threshold, "value"))
    link((obj, "dog_overlap"), (dog_overlap, "value"))
    link((obj, "xc_distance"), (xc_distance, "value"))
    link((obj, "xc_threshold"), (xc_threshold, "value"))

    close = ipywidgets.Button(description="Close",
                              tooltip="Close widget and close figure.")
    compute = ipywidgets.Button(
        description="Compute over navigation axes.",
        tooltip="Find the peaks by iterating over the navigation axes.")

    box_local_max = ipywidgets.VBox([
        labelme("Distance", local_max_distance),
        labelme("Threshold", local_max_threshold),
    ])
    box_max = ipywidgets.VBox([  #max_alpha, max_distance
        labelme("Alpha", max_alpha),
        labelme("Distance", max_distance),
    ])
    box_minmax = ipywidgets.VBox([
        labelme("Distance", minmax_distance),
        labelme("Threshold", minmax_threshold),
    ])
    box_zaefferer = ipywidgets.VBox([
        labelme("Gradient threshold", zaefferer_grad_threshold),
        labelme("Window size", zaefferer_window_size),
        labelme("Distance cutoff", zaefferer_distance_cutoff),
    ])
    box_stat = ipywidgets.VBox([
        labelme("Alpha", stat_alpha),
        labelme("Radius", stat_window_radius),
        labelme("Convergence ratio", stat_convergence_ratio),
    ])
    box_log = ipywidgets.VBox([
        labelme("Min sigma", log_min_sigma),
        labelme("Max sigma", log_max_sigma),
        labelme("Num sigma", log_num_sigma),
        labelme("Threshold", log_threshold),
        labelme("Overlap", log_overlap),
        labelme("Log scale", log_log_scale),
    ])
    box_dog = ipywidgets.VBox([
        labelme("Min sigma", dog_min_sigma),
        labelme("Max sigma", dog_max_sigma),
        labelme("Sigma ratio", dog_sigma_ratio),
        labelme("Threshold", dog_threshold),
        labelme("Overlap", dog_overlap),
    ])
    box_xc = ipywidgets.VBox([
        labelme("Distance", xc_distance),
        labelme("Threshold", xc_threshold),
    ])

    box_dict = {
        "Local Max": box_local_max,
        "Max": box_max,
        "Minmax": box_minmax,
        "Zaefferer": box_zaefferer,
        "Stat": box_stat,
        "Laplacian of Gaussians": box_log,
        "Difference of Gaussians": box_dog,
        "Template matching": box_xc
    }

    method = enum2dropdown(obj.traits()["method"])

    def update_method_parameters(change):
        # Remove all parameters vbox widgets
        for item, value in box_dict.items():
            value.layout.display = "none"
        if change.new == "Local max":
            box_local_max.layout.display = ""
        elif change.new == "Max":
            box_max.layout.display = ""
        elif change.new == "Minmax":
            box_minmax.layout.display = ""
        elif change.new == "Zaefferer":
            box_zaefferer.layout.display = ""
        elif change.new == "Stat":
            box_stat.layout.display = ""
        elif change.new == "Laplacian of Gaussians":
            box_log.layout.display = ""
        elif change.new == "Difference of Gaussians":
            box_dog.layout.display = ""
        elif change.new == "Template matching":
            box_xc.layout.display = ""

    method.observe(update_method_parameters, "value")
    link((obj, "method"), (method, "value"))

    # Trigger the function that controls the visibility  as
    # setting the default value doesn't trigger it.
    class Dummy:
        new = method.value

    update_method_parameters(change=Dummy())

    widgets_list = []

    if obj.show_navigation_sliders:
        nav_widget = get_ipy_navigation_sliders(
            obj.signal.axes_manager.navigation_axes,
            in_accordion=True,
            random_position_button=True)
        widgets_list.append(nav_widget['widget'])
        wdict.update(nav_widget['wdict'])

    l = [labelme("Method", method)]
    l.extend([value for item, value in box_dict.items()])
    method_parameters = ipywidgets.Accordion((ipywidgets.VBox(l), ))
    set_title_container(method_parameters, ["Method parameters"])

    widgets_list.extend([method_parameters, ipywidgets.HBox([compute, close])])
    box = ipywidgets.VBox(widgets_list)

    def on_compute_clicked(b):
        obj.compute_navigation()
        obj.signal._plot.close()
        obj.close()
        box.close()

    compute.on_click(on_compute_clicked)

    def on_close_clicked(b):
        obj.signal._plot.close()
        obj.close()
        box.close()

    close.on_click(on_close_clicked)
    return {
        "widget": box,
        "wdict": wdict,
    }
def spikes_removal_ipy(obj, **kwargs):
    wdict = {}
    threshold = ipywidgets.FloatText()
    add_noise = ipywidgets.Checkbox()
    default_spike_width = ipywidgets.IntText()
    interpolator_kind = enum2dropdown(obj.traits()["interpolator_kind"])
    spline_order = ipywidgets.IntSlider(min=1, max=10)
    progress_bar = ipywidgets.IntProgress(max=len(obj.coordinates) - 1)
    help_text = ipywidgets.HTML(
        value=SPIKES_REMOVAL_INSTRUCTIONS.replace('\n', '<br/>'))
    help = ipywidgets.Accordion(children=[help_text], selected_index=None)
    set_title_container(help, ["Help"])

    show_diff = ipywidgets.Button(
        description="Show derivative histogram",
        tooltip="This figure is useful to estimate the threshold.",
        layout=ipywidgets.Layout(width="auto"))
    close = ipywidgets.Button(
        description="Close",
        tooltip="Close widget and remove span selector from the signal figure."
    )
    next = ipywidgets.Button(description="Find next",
                             tooltip="Find next spike")
    previous = ipywidgets.Button(description="Find previous",
                                 tooltip="Find previous spike")
    remove = ipywidgets.Button(description="Remove spike",
                               tooltip="Remove spike and find next one.")
    wdict["threshold"] = threshold
    wdict["add_noise"] = add_noise
    wdict["default_spike_width"] = default_spike_width
    wdict["interpolator_kind"] = interpolator_kind
    wdict["spline_order"] = spline_order
    wdict["progress_bar"] = progress_bar
    wdict["show_diff_button"] = show_diff
    wdict["close_button"] = close
    wdict["next_button"] = next
    wdict["previous_button"] = previous
    wdict["remove_button"] = remove

    def on_show_diff_clicked(b):
        obj._show_derivative_histogram_fired()

    show_diff.on_click(on_show_diff_clicked)

    def on_next_clicked(b):
        obj.find()

    next.on_click(on_next_clicked)

    def on_previous_clicked(b):
        obj.find(back=True)

    previous.on_click(on_previous_clicked)

    def on_remove_clicked(b):
        obj.apply()

    remove.on_click(on_remove_clicked)
    labeled_spline_order = labelme("Spline order", spline_order)

    def enable_interpolator_kind(change):
        if change.new == "Spline":
            for child in labeled_spline_order.children:
                child.layout.display = ""
        else:
            for child in labeled_spline_order.children:
                child.layout.display = "none"

    interpolator_kind.observe(enable_interpolator_kind, "value")
    link((obj, "interpolator_kind"), (interpolator_kind, "value"))
    link((obj, "threshold"), (threshold, "value"))
    link((obj, "add_noise"), (add_noise, "value"))
    link((obj, "default_spike_width"), (default_spike_width, "value"))
    link((obj, "spline_order"), (spline_order, "value"))
    link((obj, "index"), (progress_bar, "value"))

    # Trigger the function that controls the visibility  as
    # setting the default value doesn't trigger it.

    class Dummy:
        new = interpolator_kind.value

    enable_interpolator_kind(change=Dummy())
    advanced = ipywidgets.Accordion((ipywidgets.VBox([
        labelme("Add noise", add_noise),
        labelme("Interpolator kind", interpolator_kind),
        labelme("Default spike width", default_spike_width),
        labelme("Spline order", spline_order),
    ]), ))

    set_title_container(advanced, ["Advanced settings"])

    box = ipywidgets.VBox([
        ipywidgets.VBox([
            show_diff,
            labelme("Threshold", threshold),
            labelme("Progress", progress_bar),
        ]), advanced, help,
        ipywidgets.HBox([previous, next, remove, close])
    ])

    def on_close_clicked(b):
        obj.span_selector_switch(False)
        box.close()

    close.on_click(on_close_clicked)
    return {
        "widget": box,
        "wdict": wdict,
    }
def calibrate2d_ipy(obj, **kwargs):
    # Define widgets
    wdict = {}
    length = ipywidgets.FloatText(disabled=True, description="Current length")
    scale = ipywidgets.FloatText(disabled=True, description="Scale")
    new_length = ipywidgets.FloatText(disabled=False, description="New length")
    units = ipywidgets.Text(description="Units")
    unitsl = ipywidgets.Label(layout=ipywidgets.Layout(width="10%"))
    help_text = ipywidgets.HTML(
        "Click on the signal figure and drag line to some feature with a "
        "known size. Set the new length, then press `Apply` to update both "
        "the x- and y-dimensions in the signal, or press `Close` to cancel. "
        "The units can also be set with `Units`")
    wdict["help_text"] = help_text
    help = ipywidgets.Accordion(children=[help_text], selected_index=None)
    set_title_container(help, ["Help"])
    close = ipywidgets.Button(
        description="Close",
        tooltip="Close widget and remove line from the signal figure.",
    )
    apply = ipywidgets.Button(
        description="Apply",
        tooltip="Set the x- and y-scaling with the `scale` value.")

    # Connect
    link((obj, "length"), (length, "value"))
    link((obj, "new_length"), (new_length, "value"))
    link((obj, "units"), (units, "value"))
    link((obj, "units"), (unitsl, "value"))
    link((obj, "scale"), (scale, "value"))

    def on_apply_clicked(b):
        obj.apply()
        obj.on = False
        box.close()

    apply.on_click(on_apply_clicked)

    box = ipywidgets.VBox([
        ipywidgets.HBox([new_length, unitsl]),
        length,
        scale,
        units,
        help,
        ipywidgets.HBox((apply, close)),
    ])

    def on_close_clicked(b):
        obj.on = False
        box.close()

    close.on_click(on_close_clicked)

    wdict["length"] = length
    wdict["scale"] = scale
    wdict["new_length"] = new_length
    wdict["units"] = units
    wdict["close_button"] = close
    wdict["apply_button"] = apply

    return {
        "widget": box,
        "wdict": wdict,
    }
def remove_background_ipy(obj, **kwargs):
    wdict = {}
    left = ipywidgets.FloatText(disabled=True, description="Left")
    right = ipywidgets.FloatText(disabled=True, description="Right")
    red_chisq = ipywidgets.FloatText(disabled=True, description="red-χ²")
    link((obj, "ss_left_value"), (left, "value"))
    link((obj, "ss_right_value"), (right, "value"))
    link((obj, "red_chisq"), (red_chisq, "value"))
    fast = ipywidgets.Checkbox(description="Fast")
    zero_fill = ipywidgets.Checkbox(description="Zero Fill")
    help_text = ipywidgets.HTML(
        "Click on the signal figure and drag to the right to select a "
        "range. Press `Apply` to remove the background in the whole dataset. "
        "If \"Fast\" is checked, the background parameters are estimated "
        "using a fast (analytical) method that can compromise accuracy. "
        "When unchecked, non-linear least squares is employed instead. "
        "If \"Zero Fill\" is checked, all the channels prior to the fitting "
        "region will be set to zero. "
        "Otherwise the background subtraction will be performed in the "
        "pre-fitting region as well.", )
    wdict["help_text"] = help_text
    help = ipywidgets.Accordion(children=[help_text], selected_index=None)
    set_title_container(help, ["Help"])
    close = ipywidgets.Button(
        description="Close",
        tooltip="Close widget and remove span selector from the signal figure."
    )
    apply = ipywidgets.Button(
        description="Apply",
        tooltip="Remove the background in the whole dataset.")

    polynomial_order = ipywidgets.IntText(description="Polynomial order")
    background_type = enum2dropdown(obj.traits()["background_type"])
    background_type.description = "Background type"

    def enable_poly_order(change):
        if change.new == "Polynomial":
            polynomial_order.layout.display = ""
        else:
            polynomial_order.layout.display = "none"

    background_type.observe(enable_poly_order, "value")
    link((obj, "background_type"), (background_type, "value"))

    # Trigger the function that controls the visibility of poly order as
    # setting the default value doesn't trigger it.

    class Dummy:
        new = background_type.value

    enable_poly_order(change=Dummy())
    link((obj, "polynomial_order"), (polynomial_order, "value"))
    link((obj, "fast"), (fast, "value"))
    link((obj, "zero_fill"), (zero_fill, "value"))
    wdict["left"] = left
    wdict["right"] = right
    wdict["red_chisq"] = red_chisq
    wdict["fast"] = fast
    wdict["zero_fill"] = zero_fill
    wdict["polynomial_order"] = polynomial_order
    wdict["background_type"] = background_type
    wdict["apply_button"] = apply
    box = ipywidgets.VBox([
        left,
        right,
        red_chisq,
        background_type,
        polynomial_order,
        fast,
        zero_fill,
        help,
        ipywidgets.HBox((apply, close)),
    ])

    def on_apply_clicked(b):
        obj.apply()
        obj.span_selector_switch(False)
        box.close()

    apply.on_click(on_apply_clicked)

    def on_close_clicked(b):
        obj.span_selector_switch(False)
        box.close()

    close.on_click(on_close_clicked)
    return {
        "widget": box,
        "wdict": wdict,
    }
def image_constast_editor_ipy(obj, **kwargs):
    wdict = {}
    left = ipywidgets.FloatText(disabled=True, description="Vmin")
    right = ipywidgets.FloatText(disabled=True, description="Vmax")
    bins = ipywidgets.IntText(description="Bins")
    norm = ipywidgets.Dropdown(options=("Linear", "Power", "Log", "Symlog"),
                               description="Norm",
                               value=obj.norm)
    percentile = ipywidgets.FloatRangeSlider(
        value=[0.0, 100.0],
        min=0.0,
        max=100.0,
        step=0.1,
        description="Vmin/vmax percentile",
        readout_format='.1f')
    gamma = ipywidgets.FloatSlider(1.0, min=0.1, max=3.0, description="Gamma")
    linthresh = ipywidgets.FloatSlider(0.01,
                                       min=0.001,
                                       max=1.0,
                                       step=0.001,
                                       description="Linear threshold")
    linscale = ipywidgets.FloatSlider(0.1,
                                      min=0.001,
                                      max=10.0,
                                      step=0.001,
                                      description="Linear scale")
    auto = ipywidgets.Checkbox(True, description="Auto")
    help_text = ipywidgets.HTML(IMAGE_CONTRAST_EDITOR_HELP_IPYWIDGETS)
    wdict["help_text"] = help_text
    help = ipywidgets.Accordion(children=[help_text], selected_index=None)
    set_title_container(help, ["Help"])
    close = ipywidgets.Button(description="Close", tooltip="Close widget.")
    apply = ipywidgets.Button(
        description="Apply",
        tooltip="Use the selected range to re-calculate the histogram.")
    reset = ipywidgets.Button(
        description="Reset",
        tooltip="Reset the settings to their initial values.")
    wdict["left"] = left
    wdict["right"] = right
    wdict["bins"] = bins
    wdict["norm"] = norm
    wdict["percentile"] = percentile
    wdict["gamma"] = gamma
    wdict["linthresh"] = linthresh
    wdict["linscale"] = linscale
    wdict["auto"] = auto
    wdict["close_button"] = close
    wdict["apply_button"] = apply
    wdict["reset_button"] = reset

    def transform_vmin(value):
        return (value, percentile.upper)

    def transform_vmin_inv(value):
        return value[0]

    def transform_vmax(value):
        return (percentile.lower, value)

    def transform_vmax_inv(value):
        return value[1]

    # Connect
    link((obj, "ss_left_value"), (left, "value"))
    link((obj, "ss_right_value"), (right, "value"))
    link((obj, "bins"), (bins, "value"))
    link((obj, "norm"), (norm, "value"))
    link((obj, "vmin_percentile"), (percentile, "value"),
         (transform_vmin, transform_vmin_inv))
    link((obj, "vmax_percentile"), (percentile, "value"),
         (transform_vmax, transform_vmax_inv))
    link((obj, "gamma"), (gamma, "value"))
    link((obj, "linthresh"), (linthresh, "value"))
    link((obj, "linscale"), (linscale, "value"))
    link((obj, "auto"), (auto, "value"))

    def display_parameters(change):
        # Necessary for the initialisation
        v = change if isinstance(change, str) else change.new
        if v == "Symlog":
            linthresh.layout.display = ""
            linscale.layout.display = ""
        else:
            linthresh.layout.display = "none"
            linscale.layout.display = "none"
        if v == "Power":
            gamma.layout.display = ""
        else:
            gamma.layout.display = "none"

    display_parameters(obj.norm)
    norm.observe(display_parameters, "value")

    def disable_parameters(change):
        # Necessary for the initialisation
        v = change if isinstance(change, bool) else change.new
        percentile.disabled = not v

    disable_parameters(obj.auto)
    auto.observe(disable_parameters, "value")

    def on_apply_clicked(b):
        obj.apply()

    apply.on_click(on_apply_clicked)

    def on_reset_clicked(b):
        obj.reset()

    reset.on_click(on_reset_clicked)

    box = ipywidgets.VBox([
        left,
        right,
        auto,
        percentile,
        bins,
        norm,
        gamma,
        linthresh,
        linscale,
        help,
        ipywidgets.HBox((apply, reset, close)),
    ])

    def on_close_clicked(b):
        obj.close()
        box.close()

    close.on_click(on_close_clicked)
    return {
        "widget": box,
        "wdict": wdict,
    }
def print_edges_table_ipy(obj, **kwargs):
    # Define widgets
    wdict = {}
    axis = obj.axis
    style_d = {'description_width': 'initial'}
    layout_d = {'width': '50%'}
    left = ipywidgets.FloatText(disabled=True, layout={'width': '25%'})
    right = ipywidgets.FloatText(disabled=True, layout={'width': '25%'})
    units = ipywidgets.Label(style=style_d)
    major = ipywidgets.Checkbox(value=False,
                                description='Only major edge',
                                indent=False,
                                layout=layout_d)
    complmt = ipywidgets.Checkbox(value=False,
                                  description='Complementary edge',
                                  indent=False,
                                  layout=layout_d)
    order = ipywidgets.Dropdown(options=['closest', 'ascending', 'descending'],
                                value='closest',
                                description='Sort energy by: ',
                                disabled=False,
                                style=style_d)
    update = ipywidgets.Button(description='Refresh table',
                               layout={'width': 'initial'})
    gb = ipywidgets.GridBox(layout=ipywidgets.Layout(
        grid_template_columns="70px 125px 75px 250px"))
    help_text = ipywidgets.HTML(
        "Click on the signal figure and drag to the right to select a signal "
        "range. Drag the rectangle or change its border to display edges in "
        "different signal range. Select edges to show their positions "
        "on the signal.", )
    help = ipywidgets.Accordion(children=[help_text], selected_index=None)
    set_title_container(help, ["Help"])
    close = ipywidgets.Button(description="Close", tooltip="Close the widget.")
    reset = ipywidgets.Button(description="Reset",
                              tooltip="Reset the span selector.")

    header = ('<p style="padding-left: 1em; padding-right: 1em; '
              'text-align: center; vertical-align: top; '
              'font-weight:bold">{}</p>')
    entry = ('<p style="padding-left: 1em; padding-right: 1em; '
             'text-align: center; vertical-align: top">{}</p>')

    wdict["left"] = left
    wdict["right"] = right
    wdict["units"] = units
    wdict["help"] = help
    wdict["major"] = major
    wdict["update"] = update
    wdict["complmt"] = complmt
    wdict["order"] = order
    wdict["gb"] = gb
    wdict["reset"] = reset
    wdict["close"] = close

    # Connect
    link((obj, "ss_left_value"), (left, "value"))
    link((obj, "ss_right_value"), (right, "value"))
    link((axis, "units"), (units, "value"))
    link((obj, "only_major"), (major, "value"))
    link((obj, "complementary"), (complmt, "value"))
    link((obj, "order"), (order, "value"))

    def update_table(change):
        edges, energy, relevance, description = obj.update_table()

        # header
        items = [
            ipywidgets.HTML(header.format('edge')),
            ipywidgets.HTML(header.format('onset energy (eV)')),
            ipywidgets.HTML(header.format('relevance')),
            ipywidgets.HTML(header.format('description'))
        ]

        # rows
        obj.btns = []
        for k, edge in enumerate(edges):
            if edge in obj.active_edges or \
                edge in obj.active_complementary_edges:
                btn_state = True
            else:
                btn_state = False

            btn = ipywidgets.ToggleButton(
                value=btn_state,
                description=edge,
                layout=ipywidgets.Layout(width='70px'))
            btn.observe(obj.update_active_edge, names='value')
            obj.btns.append(btn)

            wenergy = ipywidgets.HTML(entry.format(str(energy[k])))
            wrelv = ipywidgets.HTML(entry.format(str(relevance[k])))
            wdes = ipywidgets.HTML(entry.format(str(description[k])))
            items.extend([btn, wenergy, wrelv, wdes])

        gb.children = items

    update.on_click(update_table)
    major.observe(update_table)

    def on_complementary_toggled(change):
        obj.update_table()
        obj.check_btn_state()

    complmt.observe(on_complementary_toggled)

    def on_order_changed(change):
        obj._get_edges_info_within_energy_axis()
        update_table(change)

    order.observe(on_order_changed)

    def on_close_clicked(b):
        obj.span_selector_switch(False)
        box.close()

    close.on_click(on_close_clicked)

    def on_reset_clicked(b):
        # ss_left_value is linked with left.value, this can prevent cyclic
        # referencing
        obj._clear_markers()
        obj.span_selector_switch(False)
        left.value = 0
        right.value = 0
        obj.span_selector_switch(True)
        update_table(b)

    reset.on_click(on_reset_clicked)

    energy_box = ipywidgets.HBox(
        [left, units, ipywidgets.Label("-"), right, units])
    check_box = ipywidgets.HBox([major, complmt])
    control_box = ipywidgets.VBox([energy_box, update, order, check_box])

    box = ipywidgets.VBox([
        ipywidgets.HBox([gb, control_box]),
        help,
        ipywidgets.HBox([reset, close]),
    ])

    return {
        "widget": box,
        "wdict": wdict,
    }
def calibrate_ipy(obj, **kwargs):
    # Define widgets
    wdict = {}
    left = ipywidgets.FloatText(disabled=True, description="Left")
    right = ipywidgets.FloatText(disabled=True, description="Right")
    offset = ipywidgets.FloatText(disabled=True, description="Offset")
    scale = ipywidgets.FloatText(disabled=True, description="Scale")
    new_left = ipywidgets.FloatText(disabled=False, description="New left")
    new_right = ipywidgets.FloatText(disabled=False, description="New right")
    units = ipywidgets.Text(description="Units")
    unitsl = ipywidgets.Label(layout=ipywidgets.Layout(width="10%"))
    help_text = ipywidgets.HTML(
        "Click on the signal figure and drag to the right to select a signal "
        "range. Set the new left and right values and press `Apply` to update "
        "the calibration of the axis with the new values or press "
        " `Close` to cancel.", )
    wdict["help_text"] = help_text
    help = ipywidgets.Accordion(children=[help_text], selected_index=None)
    set_title_container(help, ["Help"])
    close = ipywidgets.Button(
        description="Close",
        tooltip="Close widget and remove span selector from the signal figure.",
    )
    apply = ipywidgets.Button(
        description="Apply",
        tooltip=
        "Set the axis calibration with the `offset` and `scale` values above.",
    )

    # Connect
    link((obj, "ss_left_value"), (left, "value"))
    link((obj, "ss_right_value"), (right, "value"))
    link((obj, "left_value"), (new_left, "value"))
    link((obj, "right_value"), (new_right, "value"))
    link((obj, "units"), (units, "value"))
    link((obj, "units"), (unitsl, "value"))
    link((obj, "offset"), (offset, "value"))
    link((obj, "scale"), (scale, "value"))

    def on_apply_clicked(b):
        if (new_left.value, new_right.value) != (0, 0):
            # traitlets does not support undefined, therefore we need to makes
            # sure that the values are updated in the obj if they make sense
            if new_left.value == 0 and obj.left_value is t.Undefined:
                obj.left_value = 0
            elif new_right.value == 0 and obj.right_value is t.Undefined:
                obj.right_value = 0
            # This is the default value, we need to update
        obj.apply()

    apply.on_click(on_apply_clicked)

    box = ipywidgets.VBox([
        ipywidgets.HBox([new_left, unitsl]),
        ipywidgets.HBox([new_right, unitsl]),
        ipywidgets.HBox([left, unitsl]),
        ipywidgets.HBox([right, unitsl]),
        ipywidgets.HBox([offset, unitsl]),
        scale,
        units,
        help,
        ipywidgets.HBox((apply, close)),
    ])

    def on_close_clicked(b):
        obj.span_selector_switch(False)
        box.close()

    close.on_click(on_close_clicked)

    wdict["left"] = left
    wdict["right"] = right
    wdict["offset"] = offset
    wdict["scale"] = scale
    wdict["new_left"] = new_left
    wdict["new_right"] = new_right
    wdict["units"] = units
    wdict["close_button"] = close
    wdict["apply_button"] = apply

    return {
        "widget": box,
        "wdict": wdict,
    }