<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Widgets Tools
Herein, we present MenpoWidgets's basic widget tools that implement lower level widget functionalities, such as colour selection, zoom options, axes options, etc. These are the main ingredients in order to synthesize higher-level widget classes, such as the ones presented in Widgets Components.ipynb. All the widgets of this category live in menpowidgets.tools. 
Below we present the functionalities of each one of them separately. Specifically we split this notebook in the following subsections
Step1:  Let us also define a generic print function that will be the callback trigger when the selected_values trait of all the widgets changes.
The function must have a single argument, which will be a dict with the following keys
Step2:  <a name="sec
Step3:  <a name="sec
Step4:  Note that you need to press Enter in order to pass a new value into the textbox. Also, try typing a wrong command, such as 
python
'10, 20,,', '10, a, None'
to see the corresponding error messages.
The styling of the widget can be changed using the style() method.
Step5:  The state of the widget can be updated with the set_widget_state() method. Note that since allow_callback=False, nothing gets printed after running the command, even though selected_values is updated.
Step6:  Similar to the list widget, MenpoWidgets has a widget for defining a command for slicing a list (or numpy.array). Commands can have any vald Python syntax, such as
python
'
Step7:  Note that by defining a single int number, then an ipywidget.IntSlider appears that allows to select the index. Similarly, by inserting any slicing command with a constant step, then an ipywidgets.IntRangeSlider appears. The sliders are disabled when inserting a slicing command with non-constant step. The placement of the sliders with respect to the textbox is controlled by the orientation argument.
Additionally, similar to the ListWidget, the widget is smart enough to detect any syntactic errors and print a relevant message.
The styling of the widget can be changed as
Step8:  To update the widget's state, you need to pass in a new dict of options, as
Step9:  <a name="sec
Step10:  The Apply to all button sets the currently selected colour to all the labels.
The colours can also be updated with the set_colours() function as
Step11:  In case there is only one label, defined either with a list of length 1 or by setting labels=None, then the drop-down menu to select object does not appear. For example, let's update the state of the widget
Step12:  <a name="sec
Step13:  As with all widgets, the state can be updated as
Step14:  An index selection widget where the selection can be performed with -/+ (previous/next) buttons can be created as
Step15:  Note that since text_editable is True, you can actually edit the index directly from the textbox. Additionally, by setting loop_enabled=True means that by pressing '+' when the textbox is at the last index, it takes you to the minimum index.
Let's update the styling of the widget
Step16:  Let's also update its state with a new set of options
Step17:  <a name="sec
Step18:  and its state can be updated as
Step19:  The second one defines two zoom values that are intended to control the height and width of a figure.
Step20:  Note that the sliders can be linkedd in order to preserve the aspect ratio of the figure. The state can be updated as
Step21:  <a name="sec
Step22:  The widget can be updated with a new dict of options as
Step23:  <a name="sec
Step24:  The Render lines tick box also controls the visibility of the rest of the options. So by updating the state with render_lines=False, the options disappear.
Step25:  <a name="sec
Step26:  <a name="sec
Step27:  Of course the state of the widget can be updated as
Step28:  <a name="sec
Step29:  Note that the percentage mode is accompanied by a ListWidget that expects a single float, whereas the range mode invokes a ListWidget that expects two float numbers. The state of the widget can be changed as
Step30:  On the other hand, AxesTicksWidget has two functionalities per axis
Step31:  The state can be updated as
Step32:  The AxesOptionsWidget involves the AxesLimitsWidget and AxesTicksWidget widgets and also allows the selection of font-related options. As always, the initial options are provided in a dict
Step33:  The state of the widget can be updated as
Step34:  <a name="sec
Step35:  <a name="sec
Step36:  <a name="sec
<ASSISTANT_TASK:>
Python Code:
from menpowidgets.tools import (LogoWidget, ListWidget, SlicingCommandWidget, ColourSelectionWidget, 
                                IndexButtonsWidget, IndexSliderWidget, ZoomOneScaleWidget, ZoomTwoScalesWidget, 
                                ImageOptionsWidget, LineOptionsWidget, MarkerOptionsWidget, NumberingOptionsWidget, 
                                AxesLimitsWidget, AxesTicksWidget, AxesOptionsWidget, LegendOptionsWidget, 
                                GridOptionsWidget, HOGOptionsWidget, DSIFTOptionsWidget, DaisyOptionsWidget, 
                                LBPOptionsWidget, IGOOptionsWidget)
from menpowidgets.style import map_styles_to_hex_colours
Explanation: Widgets Tools
Herein, we present MenpoWidgets's basic widget tools that implement lower level widget functionalities, such as colour selection, zoom options, axes options, etc. These are the main ingredients in order to synthesize higher-level widget classes, such as the ones presented in Widgets Components.ipynb. All the widgets of this category live in menpowidgets.tools. 
Below we present the functionalities of each one of them separately. Specifically we split this notebook in the following subsections:
Basics
Menpo Logo
List Definition and Slicing
Colour Selection
Index Selection
Zoom
Image Options
Line Options
Marker Options
Numbering Options
Axes Options
Legend Options
Grid Options
HOG, DSIFT, Daisy, LBP, IGO Options
<a name="sec:basics"></a>1. Basics
As explained in the Introduction.ipynb notebook, all the widgets presented here are subclasses of menpo.abstract.MenpoWidget, thus they follow the same rules, which are:
They expect as input the initial options, as well as the rendering callback function.
They implement add_render_function(), remove_render_function(), replace_render_function() and call_render_function().
They implement set_widget_state(), which updates the widget state with a new set of options.
They implement style() which takes a set of options that change the style of the widget, such as font-related options, border-related options, etc.
Before presenting each widget separately, let's first import the things that are required.
End of explanation
from menpo.visualize import print_dynamic
def render_function(change):
    print(change['new'])
Explanation: Let us also define a generic print function that will be the callback trigger when the selected_values trait of all the widgets changes.
The function must have a single argument, which will be a dict with the following keys:
* 'name': The name of the trait that is monitored and triggers the callback. In the case of a MenpoWidget subclass, this is always 'selected_values'.
* 'type': The type of event that happens on the trait. In the case of a MenpoWidget subclass, this is always 'change'.
* 'new': The currently selected value attached to selected_values.
* 'old': The previous value of selected_values.
* 'owner': Pointer to the widget object.
Consequently, the selected values of a widget object (e.g. wid) can be retrieved in any of the following 3 equivalent ways:
1. wid.selected_values
2. change['new']
3. change['owner'].selected_values
For this notebook, we choose the second way which is independent of the widget object.
End of explanation
wid = LogoWidget(scale=0.6, style='info')
wid
Explanation: <a name="sec:logo"></a>2. Menpo Logo
This is a simple widget that can be used for embedding an image into an ipywidgets widget are using the ipywidgets.Image class.
End of explanation
list_cmd = [0, 1, 2]
    
wid = ListWidget(list_cmd, mode='int', description='List:', render_function=render_function, example_visible=True)
wid
Explanation: <a name="sec:list"></a>3. List Definition and Slicing
MenpoWidgets has a widget for defining a list of numbers. The widget is smart enough to accept any valid python command, such as 
python
'range(10)', '[1, 2, 3]', '10'
and complain about syntactic mistakes. It can be defined to expect either int or float numbers and has an optional example as guide.
End of explanation
wid.style(box_style='danger', font_size=15)
Explanation: Note that you need to press Enter in order to pass a new value into the textbox. Also, try typing a wrong command, such as 
python
'10, 20,,', '10, a, None'
to see the corresponding error messages.
The styling of the widget can be changed using the style() method.
End of explanation
wid.set_widget_state([20, 16], allow_callback=False)
Explanation: The state of the widget can be updated with the set_widget_state() method. Note that since allow_callback=False, nothing gets printed after running the command, even though selected_values is updated.
End of explanation
# Initial options
slice_cmd = {'command': ':3', 
             'length': 10}
# Create widget
wid = SlicingCommandWidget(slice_cmd, description='Command:', render_function=render_function, 
                           example_visible=True, orientation='horizontal')
# Display widget
wid
Explanation: Similar to the list widget, MenpoWidgets has a widget for defining a command for slicing a list (or numpy.array). Commands can have any vald Python syntax, such as
python
':3:', '::2', '1:2:10', '-1::', '0, 3, 7', 'range(5)'
The widget gets as argument a dict with the initial slicing command as well as the length of the list.
End of explanation
wid.style(border_visible=True, border_style='dashed', font_weight='bold')
Explanation: Note that by defining a single int number, then an ipywidget.IntSlider appears that allows to select the index. Similarly, by inserting any slicing command with a constant step, then an ipywidgets.IntRangeSlider appears. The sliders are disabled when inserting a slicing command with non-constant step. The placement of the sliders with respect to the textbox is controlled by the orientation argument.
Additionally, similar to the ListWidget, the widget is smart enough to detect any syntactic errors and print a relevant message.
The styling of the widget can be changed as
End of explanation
wid.set_widget_state({'command': ':40', 'length': 40}, allow_callback=True)
Explanation: To update the widget's state, you need to pass in a new dict of options, as
End of explanation
wid = ColourSelectionWidget([[255, 38, 31], 'blue', 'green'], labels=['a', 'b', 'c'], 
                            render_function=render_function)
# Set styling
wid.style(box_style='warning', apply_to_all_style='info', label_colour='black', 
          label_background_colour=map_styles_to_hex_colours('info', background=True), font_weight='bold')
# Display widget
wid
Explanation: <a name="sec:colour"></a>4. Colour Selection
MenpoWidgets is using the standard Java colour picker defined in ipywidgets.ColorPicker. However, ColourSelectionWidget has the additional functionality to select colours for a set of objects. Thus the widget constructor gets a list of colours (either the colour name str or the RGB values), as well as the labels list that has the names of the objects.
End of explanation
wid.set_colours(['red', 'orange', 'pink'], allow_callback=True)
Explanation: The Apply to all button sets the currently selected colour to all the labels.
The colours can also be updated with the set_colours() function as
End of explanation
wid.set_widget_state(['red'], None)
Explanation: In case there is only one label, defined either with a list of length 1 or by setting labels=None, then the drop-down menu to select object does not appear. For example, let's update the state of the widget:
End of explanation
# Initial options
index = {'min': 0, 
         'max': 100, 
         'step': 1, 
         'index': 10}
# Crete widget
wid = IndexSliderWidget(index, description='Index: ', render_function=render_function, continuous_update=False)
# Set styling
wid.style(box_style='danger', slider_handle_colour=map_styles_to_hex_colours('danger'), 
          slider_bar_colour=map_styles_to_hex_colours('danger'))
# Display widget
wid
Explanation: <a name="sec:index"></a>5. Index Selection
The following two widgets give the ability to select a single integer number from a specified range. Thus, they can be seen as index selectors. The user must pass in a dict that defines the minimum, maximum and step of the allowed range, as well as the initially selected index. Then the selected_values trait always keeps track of the selected index, thus it has int type.
An index selection widget, where the selector is an ipywidgets.IntSlider can be created as
End of explanation
wid.set_widget_state({'min': 10, 'max': 500, 'step': 2, 'index': 50}, allow_callback=True)
Explanation: As with all widgets, the state can be updated as:
End of explanation
index = {'min': 0, 'max': 100, 'step': 1, 'index': 10}
wid = IndexButtonsWidget(index, render_function=render_function, loop_enabled=False, text_editable=True)
wid
Explanation: An index selection widget where the selection can be performed with -/+ (previous/next) buttons can be created as:
End of explanation
wid.style(box_style='danger', plus_style='success', minus_style='danger', text_colour='blue', 
          text_background_colour=map_styles_to_hex_colours('info', background=True))
Explanation: Note that since text_editable is True, you can actually edit the index directly from the textbox. Additionally, by setting loop_enabled=True means that by pressing '+' when the textbox is at the last index, it takes you to the minimum index.
Let's update the styling of the widget:
End of explanation
wid.set_widget_state({'min': 20, 'max': 500, 'step': 2, 'index': 50}, loop_enabled=True, text_editable=True, 
                     allow_callback=True)
Explanation: Let's also update its state with a new set of options:
End of explanation
# Initial options
zoom_options = {'min': 0.1, 
                'max': 4., 
                'step': 0.05, 
                'zoom': 1.}
# Create widget
wid = ZoomOneScaleWidget(zoom_options, render_function=render_function)
# Set styling
wid.style(box_style='danger')
wid.zoom_slider.background_color = map_styles_to_hex_colours('info')
wid.zoom_slider.slider_color = map_styles_to_hex_colours('danger')
# Display widget
wid
Explanation: <a name="sec:zoom"></a>6. Zoom
There are two widgets for zooming into a figure. Both are using ipywidgets.FloatSLider and get as input a dict with the minimum and maximum values, the step of the slider(s) and the initial zoom value.
The first one defines a single zoom float, as
End of explanation
wid.set_widget_state({'zoom': 0.5, 'min': 0., 'max': 4., 'step': 0.2}, allow_callback=True)
Explanation: and its state can be updated as:
End of explanation
# Initial options
zoom_options = {'min': 0.1, 
                'max': 4., 
                'step': 0.1, 
                'zoom': [1., 1.], 
                'lock_aspect_ratio': False}
# Create widget
wid = ZoomTwoScalesWidget(zoom_options, render_function=render_function, continuous_update=True)
# Set styling
wid.style(box_style='danger')
# Display widget
wid
Explanation: The second one defines two zoom values that are intended to control the height and width of a figure.
End of explanation
zoom_options = {'min': 0.5, 'max': 10., 'step': 0.3, 'zoom': [2., 3.]}
wid.set_widget_state(zoom_options, allow_callback=True)
Explanation: Note that the sliders can be linkedd in order to preserve the aspect ratio of the figure. The state can be updated as:
End of explanation
# Initial options
image_options = {'alpha': 1., 
                 'interpolation': 'bilinear', 
                 'cmap_name': None}
# Create widget
wid = ImageOptionsWidget(image_options, render_function=render_function)
# Set styling
wid.style(box_style='success', padding=10, border_visible=True, border_radius=45)
# Display widget
wid
Explanation: <a name="sec:image"></a>7. Image Options
This is a widget for selecting options related to rendering an image. It defines the colourmap, the alpha value for transparency as well as the interpolation. Specifically:
End of explanation
wid.set_widget_state({'alpha': 0.8, 'interpolation': 'none', 'cmap_name': 'gray'}, allow_callback=True)
Explanation: The widget can be updated with a new dict of options as:
End of explanation
# Initial options
line_options = {'render_lines': True, 
                'line_width': 1, 
                'line_colour': ['blue', 'red'], 
                'line_style': '-'}
# Create widget
wid = LineOptionsWidget(line_options, render_function=render_function, 
                        labels=['menpo', 'widgets'])
# Set styling
wid.style(box_style='danger', padding=6)
# Display widget
wid
Explanation: <a name="sec:line"></a>8. Line Options
The following widget allows the selection of options for rendering line objects. The initial options are passed in as a dict and control the width, style and colour of the lines. Note that a different colour can be defined for different objects using the labels argument.
End of explanation
wid.set_widget_state({'render_lines': False, 'line_width': 5, 'line_colour': ['purple'], 'line_style': '--'}, 
                     allow_callback=True, labels=None)
Explanation: The Render lines tick box also controls the visibility of the rest of the options. So by updating the state with render_lines=False, the options disappear.
End of explanation
# Initial options
marker_options = {'render_markers': True, 
                  'marker_size': 20, 
                  'marker_face_colour': ['red', 'green'], 
                  'marker_edge_colour': ['black', 'blue'], 
                  'marker_style': 'o', 
                  'marker_edge_width': 1}
# Create widget
wid = MarkerOptionsWidget(marker_options, render_function=render_function, 
                          labels=['a', 'b'])
# Set styling
wid.style(box_style='info', padding=6)
# Display widget
wid
wid.set_widget_state({'render_markers': True, 'marker_size': 20, 'marker_face_colour': ['red'], 
                     'marker_edge_colour': ['black'], 'marker_style': 'o', 'marker_edge_width': 1}, 
                     labels=None, allow_callback=True)
Explanation: <a name="sec:marker"></a>9. Marker Options
Similar to the LineOptionsWidget, this widget allows to selecting options for rendering markers. The options define the edge width, face colour, edge colour, style and size of the markers.
End of explanation
# Initial options
numbers_options = {'render_numbering': True, 
                   'numbers_font_name': 'serif', 
                   'numbers_font_size': 10, 
                   'numbers_font_style': 'normal', 
                   'numbers_font_weight': 'normal', 
                   'numbers_font_colour': ['black'], 
                   'numbers_horizontal_align': 'center', 
                   'numbers_vertical_align': 'bottom'}
# Create widget
wid = NumberingOptionsWidget(numbers_options, render_function=render_function)
# Set styling
wid.style(box_style='success', border_visible=True, border_colour='black', border_style='solid', border_width=1, 
          border_radius=0, padding=10, margin=10)
# Display widget
wid
Explanation: <a name="sec:numbering"></a>10. Numbering Options
The NumberingOptionsWidget is used in case you want to render some numbers next to the plotted points.
End of explanation
wid.set_widget_state({'render_numbering': True, 'numbers_font_name': 'serif', 'numbers_font_size': 10, 
                      'numbers_font_style': 'normal', 'numbers_font_weight': 'normal', 
                      'numbers_font_colour': ['green'], 'numbers_horizontal_align': 'center', 
                      'numbers_vertical_align': 'bottom'}, allow_callback=True)
Explanation: Of course the state of the widget can be updated as:
End of explanation
# Create widget
wid = AxesLimitsWidget(axes_x_limits=[0, 10], axes_y_limits=0.1, render_function=render_function)
# Set styling
wid.style(box_style='danger')
# Display widget
wid
Explanation: <a name="sec:axes"></a>11. Axes Options
Before presenting the AxesOptionsWidget, let's first see two widgets that are ued as its basic components for selecting the axes limits as well as the axes ticks.
AxesLimitsWidget has 3 basic functions per axis:
* auto: Allows matplotlib to automatically set the limits.
* percentage: It expects a float that defines the percentage of padding to allow around the rendered object's region.
* range: It expects two numbers that define the minimum and maximum values of the limits.
End of explanation
wid.set_widget_state([-200, 200], None, allow_callback=True)
Explanation: Note that the percentage mode is accompanied by a ListWidget that expects a single float, whereas the range mode invokes a ListWidget that expects two float numbers. The state of the widget can be changed as:
End of explanation
# Initial options
axes_ticks = {'x': [], 
              'y': [10., 20., 30.]}
# Create widget
wid = AxesTicksWidget(axes_ticks, render_function=render_function)
# St styling
wid.style(box_style='danger')
# Display widget
wid
Explanation: On the other hand, AxesTicksWidget has two functionalities per axis:
* auto: Allows matplotlib to automatically set the ticks.
* list: Enables a ListWidget to select the ticks.
End of explanation
wid.set_widget_state({'x': list(range(5)), 'y': None}, allow_callback=True)
Explanation: The state can be updated as:
End of explanation
# Initial options
axes_options = {'render_axes': True, 
                'axes_font_name': 'serif', 
                'axes_font_size': 10, 
                'axes_font_style': 'normal', 
                'axes_font_weight': 'normal', 
                'axes_x_limits': None, 
                'axes_y_limits': None, 
                'axes_x_ticks': [0, 100], 
                'axes_y_ticks': None}
# Create widget
wid = AxesOptionsWidget(axes_options, render_function=render_function)
# Set styling
wid.style(box_style='warning', padding=6, border_visible=True, border_colour=map_styles_to_hex_colours('warning'))
# Display widget
wid
Explanation: The AxesOptionsWidget involves the AxesLimitsWidget and AxesTicksWidget widgets and also allows the selection of font-related options. As always, the initial options are provided in a dict:
End of explanation
axes_options = {'render_axes': True, 'axes_font_name': 'serif', 
                'axes_font_size': 10, 'axes_font_style': 'normal', 'axes_font_weight': 'normal', 
                'axes_x_limits': [0., 0.05], 'axes_y_limits': 0.1, 'axes_x_ticks': [0, 100], 'axes_y_ticks': None}
wid.set_widget_state(axes_options, allow_callback=True)
Explanation: The state of the widget can be updated as:
End of explanation
# Initial options
legend_options = {'render_legend': True,
                  'legend_title': '',
                  'legend_font_name': 'serif',
                  'legend_font_style': 'normal',
                  'legend_font_size': 10,
                  'legend_font_weight': 'normal',
                  'legend_marker_scale': 1.,
                  'legend_location': 2,
                  'legend_bbox_to_anchor': (1.05, 1.),
                  'legend_border_axes_pad': 1.,
                  'legend_n_columns': 1,
                  'legend_horizontal_spacing': 1.,
                  'legend_vertical_spacing': 1.,
                  'legend_border': True,
                  'legend_border_padding': 0.5,
                  'legend_shadow': False,
                  'legend_rounded_corners': True}
# Create widget
wid = LegendOptionsWidget(legend_options, render_function=render_function)
# Set styling
wid.style(border_visible=True, font_size=15)
# Display widget
wid
legend_options = {'render_legend': True, 'legend_title': 'asd', 'legend_font_name': 'sans-serif', 
                  'legend_font_style': 'normal', 'legend_font_size': 60, 'legend_font_weight': 'normal',
                  'legend_marker_scale': 2., 'legend_location': 7, 'legend_bbox_to_anchor': (1.05, 1.),
                  'legend_border_axes_pad': 1., 'legend_n_columns': 2, 'legend_horizontal_spacing': 3.,
                  'legend_vertical_spacing': 7., 'legend_border': False,
                  'legend_border_padding': 0.5, 'legend_shadow': True, 'legend_rounded_corners': True}
wid.set_widget_state(legend_options, allow_callback=True)
Explanation: <a name="sec:legend"></a>12. Legend Options
LegendOptionsWidget allows to control the (many) options of renderinf the legend of a figure.
End of explanation
# Initial options
grid_options = {'render_grid': True, 
                'grid_line_width': 1, 
                'grid_line_style': '-'}
# Create widget
wid = GridOptionsWidget(grid_options, render_function=render_function)
# Set styling
wid.style(box_style='warning')
# Display widget
wid
wid.set_widget_state({'render_grid': True, 'grid_line_width': 10, 'grid_line_style': ':'})
Explanation: <a name="sec:grid"></a>13. Grid Options
The following simple widget controls the rendering of the grid lines of a plot, their style and width.
End of explanation
# Initial options
hog_options = {'mode': 'dense',
               'algorithm': 'dalaltriggs',
               'num_bins': 9,
               'cell_size': 8,
               'block_size': 2,
               'signed_gradient': True,
               'l2_norm_clip': 0.2,
               'window_height': 1,
               'window_width': 1,
               'window_unit': 'blocks',
               'window_step_vertical': 1,
               'window_step_horizontal': 1,
               'window_step_unit': 'pixels',
               'padding': True}
# Create widget
wid = HOGOptionsWidget(hog_options, render_function=render_function)
# Set styling
wid.style('info')
# Display widget
wid
# Initial options
dsift_options = {'window_step_horizontal': 1,
                 'window_step_vertical': 1,
                 'num_bins_horizontal': 2,
                 'num_bins_vertical': 2,
                 'num_or_bins': 9,
                 'cell_size_horizontal': 6,
                 'cell_size_vertical': 6,
                 'fast': True}
# Create widget
wid = DSIFTOptionsWidget(dsift_options, render_function=render_function)
# Set styling
wid.style('success')
# Display widget
wid
# Initial options
daisy_options = {'step': 1,
                 'radius': 15,
                 'rings': 2,
                 'histograms': 2,
                 'orientations': 8,
                 'normalization': 'l1',
                 'sigmas': None,
                 'ring_radii': None}
   
# Create widget
wid = DaisyOptionsWidget(daisy_options, render_function=render_function)
# Set styling
wid.style('danger')
# Display widget
wid
# Initial options
lbp_options = {'radius': list(range(1, 5)),
               'samples': [8] * 4,
               'mapping_type': 'u2',
               'window_step_vertical': 1,
               'window_step_horizontal': 1,
               'window_step_unit': 'pixels',
               'padding': True}
    
# Create widget
wid = LBPOptionsWidget(lbp_options, render_function=render_function)
# Set styling
wid.style(box_style='warning')
# Display widget
wid
wid = IGOOptionsWidget({'double_angles': True}, render_function=render_function)
wid
Explanation: <a name="sec:features"></a>14. HOG, DSIFT, Daisy, LBP, IGO Options
The following widgets allow to select options regarding HOG, DSIFT, Daisy, LBP and IGO features.
End of explanation
<END_TASK>