From 821de8b8a128356e485a5239899ef9f9e1f32020 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Fri, 2 Apr 2021 10:40:11 -0500 Subject: [PATCH 1/7] run black on the codebase --- chaco/__init__.py | 8 +- chaco/_speedups_fallback.py | 111 +- chaco/abstract_colormap.py | 5 +- chaco/abstract_controller.py | 2 +- chaco/abstract_data_range.py | 36 +- chaco/abstract_data_source.py | 14 +- chaco/abstract_mapper.py | 17 +- chaco/abstract_overlay.py | 10 +- chaco/abstract_plot_data.py | 36 +- chaco/abstract_plot_renderer.py | 21 +- chaco/api.py | 50 +- chaco/array_data_source.py | 73 +- chaco/array_plot_data.py | 64 +- chaco/axis.py | 489 +-- chaco/axis_view.py | 69 +- chaco/barplot.py | 130 +- chaco/base.py | 79 +- chaco/base_1d_mapper.py | 25 +- chaco/base_1d_plot.py | 87 +- chaco/base_2d_plot.py | 104 +- chaco/base_candle_plot.py | 52 +- chaco/base_contour_plot.py | 33 +- chaco/base_data_range.py | 9 +- chaco/base_plot_container.py | 25 +- chaco/base_plot_frame.py | 31 +- chaco/base_xy_plot.py | 151 +- chaco/candle_plot.py | 41 +- chaco/chaco_plot_container_editor.py | 10 +- chaco/chaco_plot_editor.py | 222 +- chaco/chaco_traits.py | 4 +- chaco/chaco_version.py | 4 +- chaco/cmap_image_plot.py | 79 +- chaco/color_bar.py | 108 +- chaco/color_mapper.py | 260 +- chaco/color_spaces.py | 120 +- chaco/colormap_generators.py | 59 +- chaco/colormapped_scatterplot.py | 150 +- chaco/colormapped_selection_overlay.py | 39 +- chaco/contour/setup.py | 17 +- chaco/contour_line_plot.py | 29 +- chaco/contour_poly_plot.py | 24 +- chaco/cross_plot_frame.py | 18 +- chaco/data_frame_plot_data.py | 66 +- chaco/data_range_1d.py | 180 +- chaco/data_range_2d.py | 55 +- chaco/data_view.py | 132 +- chaco/default_colormaps.py | 3220 ++++++++++------- chaco/default_colors.py | 28 +- chaco/discrete_color_mapper.py | 22 +- chaco/downsample/lttb.py | 2 +- chaco/downsample/tests/test_lttb.py | 81 +- chaco/errorbar_plot.py | 31 +- chaco/example_support.py | 47 +- chaco/filled_line_plot.py | 48 +- chaco/function_data_source.py | 8 +- chaco/function_image_data.py | 7 +- chaco/grid.py | 190 +- chaco/grid_data_source.py | 49 +- chaco/grid_mapper.py | 39 +- chaco/horizon_plot.py | 42 +- chaco/image_data.py | 58 +- chaco/image_plot.py | 95 +- chaco/image_utils.py | 7 +- chaco/jitterplot.py | 52 +- chaco/label.py | 110 +- chaco/label_axis.py | 58 +- chaco/lasso_overlay.py | 20 +- chaco/layers/status_layer.py | 73 +- chaco/layers/svg_range_selection_overlay.py | 51 +- chaco/legend.py | 149 +- chaco/line_scatterplot_1d.py | 34 +- chaco/linear_mapper.py | 20 +- chaco/lineplot.py | 202 +- chaco/log_mapper.py | 41 +- chaco/multi_array_data_source.py | 38 +- chaco/multi_line_plot.py | 172 +- chaco/overlays/aligned_container_overlay.py | 7 +- chaco/overlays/api.py | 9 +- chaco/overlays/container_overlay.py | 3 +- chaco/overlays/coordinate_line_overlay.py | 14 +- chaco/overlays/databox.py | 30 +- chaco/overlays/simple_inspector_overlay.py | 33 +- chaco/overlays/tests/test_databox.py | 17 +- chaco/overlays/text_grid_overlay.py | 6 +- chaco/pdf_graphics_context.py | 55 +- chaco/plot.py | 752 ++-- chaco/plot_canvas.py | 19 +- chaco/plot_canvas_toolbar.py | 8 +- chaco/plot_component.py | 25 +- chaco/plot_containers.py | 167 +- chaco/plot_factory.py | 237 +- chaco/plot_graphics_context.py | 19 +- chaco/plot_label.py | 28 +- chaco/plot_template.py | 80 +- chaco/plotscrollbar.py | 67 +- chaco/plugin/chaco_plugin.py | 21 +- chaco/plugin/plot_editor.py | 33 +- chaco/plugin/workbench_session.py | 9 +- chaco/point_data_source.py | 56 +- chaco/polar_line_renderer.py | 97 +- chaco/polar_mapper.py | 20 +- chaco/polygon_plot.py | 36 +- chaco/quiverplot.py | 26 +- chaco/scales/formatters.py | 227 +- chaco/scales/safetime.py | 36 +- chaco/scales/scales.py | 164 +- chaco/scales/tests/test_formatters.py | 13 +- chaco/scales/tests/test_scales.py | 216 +- chaco/scales/tests/test_time_scale.py | 87 +- .../tests/test_time_scale_resolution.py | 134 +- chaco/scales/time_scale.py | 174 +- chaco/scales_tick_generator.py | 32 +- chaco/scatter_inspector_overlay.py | 35 +- chaco/scatter_markers.py | 42 +- chaco/scatterplot.py | 235 +- chaco/scatterplot_1d.py | 60 +- chaco/segment_plot.py | 198 +- chaco/selectable_legend.py | 25 +- chaco/serializable.py | 21 +- chaco/shell/__init__.py | 1 - chaco/shell/chaco_shell_error.py | 5 +- chaco/shell/commands.py | 163 +- chaco/shell/plot_maker.py | 176 +- chaco/shell/plot_window.py | 69 +- chaco/shell/preferences.py | 17 +- chaco/shell/scaly_plot.py | 42 +- chaco/shell/session.py | 28 +- chaco/shell/tests/test_make_data_sources.py | 4 +- chaco/shell/tests/test_tutorial_example.py | 6 +- chaco/simple_plot_frame.py | 27 +- chaco/speedups.py | 1 - chaco/svg_graphics_context.py | 12 +- chaco/tests/_tools.py | 7 +- chaco/tests/segment_plot_test_case.py | 90 +- chaco/tests/serializable_base.py | 6 +- chaco/tests/test_array_or_none.py | 3 +- chaco/tests/test_array_plot_data.py | 16 +- chaco/tests/test_arraydatasource.py | 69 +- chaco/tests/test_base_utils.py | 111 +- chaco/tests/test_border.py | 25 +- chaco/tests/test_cmap_image_plot.py | 15 +- chaco/tests/test_colormapped_scatterplot.py | 17 +- chaco/tests/test_colormapper.py | 85 +- chaco/tests/test_contour.py | 28 +- chaco/tests/test_data_frame_plot_data.py | 51 +- chaco/tests/test_data_label.py | 24 +- chaco/tests/test_data_view.py | 20 +- chaco/tests/test_datarange_1d.py | 47 +- chaco/tests/test_datarange_2d.py | 208 +- chaco/tests/test_default_colormaps.py | 10 +- chaco/tests/test_discrete_colormapper.py | 29 +- chaco/tests/test_errorbarplot.py | 9 +- chaco/tests/test_function_data_source.py | 56 +- chaco/tests/test_grid_data_source.py | 55 +- chaco/tests/test_grid_mapper.py | 40 +- chaco/tests/test_hittest.py | 33 +- chaco/tests/test_image_data.py | 30 +- chaco/tests/test_image_plot.py | 58 +- chaco/tests/test_image_utils.py | 21 +- chaco/tests/test_instantiation_order.py | 12 +- chaco/tests/test_jitterplot.py | 56 +- chaco/tests/test_line_scatterplot.py | 80 +- chaco/tests/test_linearmapper.py | 31 +- chaco/tests/test_logmapper.py | 3 +- chaco/tests/test_multi_array_data_source.py | 29 +- chaco/tests/test_plot.py | 13 +- chaco/tests/test_plot_factory.py | 9 +- chaco/tests/test_plotcontainer.py | 543 +-- chaco/tests/test_scatterplot_1d.py | 67 +- chaco/tests/test_scatterplot_renderers.py | 2 +- chaco/tests/test_serializable.py | 10 +- chaco/tests/test_speedups.py | 25 +- chaco/tests/test_text_plot_1d.py | 71 +- chaco/tests/test_ticks.py | 23 +- chaco/tests/text_plot_test_case.py | 12 +- chaco/tests_with_backend/test_2d_case.py | 38 +- .../tests_with_backend/test_highlight_tool.py | 20 +- chaco/text_box_overlay.py | 49 +- chaco/text_plot.py | 39 +- chaco/text_plot_1d.py | 55 +- chaco/ticks.py | 445 ++- chaco/toolbar_plot.py | 7 +- chaco/tools/base_zoom_tool.py | 45 +- chaco/tools/better_selecting_zoom.py | 135 +- chaco/tools/better_zoom.py | 129 +- chaco/tools/broadcaster.py | 7 +- chaco/tools/cursor_tool.py | 96 +- chaco/tools/data_label_tool.py | 50 +- chaco/tools/dataprinter.py | 8 +- chaco/tools/drag_tool.py | 9 +- chaco/tools/drag_zoom.py | 21 +- chaco/tools/draw_points_tool.py | 11 +- chaco/tools/highlight_tool.py | 23 +- chaco/tools/image_inspector_tool.py | 61 +- chaco/tools/lasso_selection.py | 142 +- chaco/tools/legend_highlighter.py | 14 +- chaco/tools/legend_tool.py | 15 +- chaco/tools/line_inspector.py | 58 +- chaco/tools/line_segment_tool.py | 107 +- chaco/tools/move_tool.py | 10 +- chaco/tools/pan_tool.py | 47 +- chaco/tools/pan_tool2.py | 24 +- chaco/tools/point_marker.py | 18 +- chaco/tools/range_selection.py | 135 +- chaco/tools/range_selection_2d.py | 85 +- chaco/tools/range_selection_overlay.py | 67 +- chaco/tools/rect_zoom.py | 2 +- chaco/tools/rectangular_selection.py | 17 +- chaco/tools/regression_lasso.py | 27 +- chaco/tools/save_tool.py | 27 +- chaco/tools/scatter_inspector.py | 31 +- chaco/tools/select_tool.py | 25 +- chaco/tools/simple_inspector.py | 24 +- chaco/tools/simple_zoom.py | 181 +- chaco/tools/tests/test_better_zoom_tool.py | 2 +- chaco/tools/tests/test_image_inspector.py | 70 +- chaco/tools/tests/test_pan_tool.py | 5 +- chaco/tools/tests/test_range_selection.py | 19 +- chaco/tools/tests/test_range_zoom.py | 27 +- .../tests/test_rectangular_selection_tool.py | 25 +- chaco/tools/tests/test_scatter_inspector.py | 7 +- chaco/tools/tool_history_mixin.py | 34 +- chaco/tools/tool_states.py | 50 +- chaco/tools/toolbars/plot_toolbar.py | 164 +- chaco/tools/toolbars/toolbar_buttons.py | 98 +- chaco/tools/tracking_pan_tool.py | 20 +- chaco/tools/tracking_zoom.py | 24 +- chaco/tools/traits_tool.py | 45 +- chaco/tooltip.py | 63 +- chaco/transform_color_mapper.py | 124 +- chaco/ui/axis_ui.py | 160 +- chaco/ui/plot_window.py | 21 +- chaco/ui/popupable_plot.py | 4 +- 233 files changed, 9887 insertions(+), 7994 deletions(-) diff --git a/chaco/__init__.py b/chaco/__init__.py index ba5b01bf4..02ebaa757 100644 --- a/chaco/__init__.py +++ b/chaco/__init__.py @@ -5,10 +5,4 @@ """ from ._version import full_version as __version__ # noqa -__requires__ = [ - 'traits', - 'traitsui', - 'pyface', - 'numpy', - 'enable' -] +__requires__ = ["traits", "traitsui", "pyface", "numpy", "enable"] diff --git a/chaco/_speedups_fallback.py b/chaco/_speedups_fallback.py index 6b4ffd578..6b0f08c8a 100644 --- a/chaco/_speedups_fallback.py +++ b/chaco/_speedups_fallback.py @@ -3,14 +3,27 @@ _speedups extension module. """ -from numpy import clip, invert, isnan, isinf, array, transpose, zeros, \ - compress, where, take, float32, ones_like +from numpy import ( + clip, + invert, + isnan, + isinf, + array, + transpose, + zeros, + compress, + where, + take, + float32, + ones_like, +) import numpy as np import operator + def array_combine(a, b, op=operator.and_, func=lambda x: x): - """ Returns op(func(a), func(b)) if a and b are both not None; + """Returns op(func(a), func(b)) if a and b are both not None; if one is None, then returns func() on the non-None array; if both are None, then returns None. """ @@ -24,10 +37,20 @@ def array_combine(a, b, op=operator.and_, func=lambda x: x): return None -def scatterplot_gather_points(index, index_low, index_high, - value, value_low, value_high, - index_mask=None, index_sel=None, index_sel_mask=None, - value_mask=None, value_sel=None, value_sel_mask=None): +def scatterplot_gather_points( + index, + index_low, + index_high, + value, + value_low, + value_high, + index_mask=None, + index_sel=None, + index_sel_mask=None, + value_mask=None, + value_sel=None, + value_sel_mask=None, +): """ Takes index and value arrays, masks, and optional selection arrays, and returns the list of points and corresponding selection mask for @@ -74,8 +97,9 @@ def scatterplot_gather_points(index, index_low, index_high, index_range_mask = (index_low < index) & (index < index_high) value_range_mask = (value_low < value) & (value < value_high) - nan_mask = array_combine(index_mask, value_mask, - func = lambda x: invert(isnan(x)) & x) + nan_mask = array_combine( + index_mask, value_mask, func=lambda x: invert(isnan(x)) & x + ) if nan_mask is not None: point_mask = nan_mask & index_range_mask & value_range_mask @@ -112,9 +136,8 @@ def scatterplot_gather_points(index, index_low, index_high, return points, selections - def apply_selection_fade(mapped_image, mask, fade_alpha, fade_background): - '''Apply a selection fade to a colormapped image. + """Apply a selection fade to a colormapped image. Parameters ---------- @@ -127,22 +150,21 @@ def apply_selection_fade(mapped_image, mask, fade_alpha, fade_background): fade_background : rgb888 tuple The fade background - ''' + """ imask = invert(mask) if fade_alpha == 0: - mapped_image[imask,0:3] = fade_background + mapped_image[imask, 0:3] = fade_background else: - ialpha = (1.0 - fade_alpha) + ialpha = 1.0 - fade_alpha background = tuple(ialpha * x for x in fade_background) - image_region = mapped_image[imask,0:3] + image_region = mapped_image[imask, 0:3] image_region *= fade_alpha image_region += background - mapped_image[imask,0:3] = image_region + mapped_image[imask, 0:3] = image_region -def map_colors(data_array, steps, low, high, red_lut, green_lut, blue_lut, - alpha_lut): - '''Map colors from color lookup tables to a data array. +def map_colors(data_array, steps, low, high, red_lut, green_lut, blue_lut, alpha_lut): + """Map colors from color lookup tables to a data array. This is used in ColorMapper.map_screen @@ -164,37 +186,38 @@ def map_colors(data_array, steps, low, high, red_lut, green_lut, blue_lut, The blue channel lookup table alpha_lut : ndarray of float32 The alpha channel lookup table - + Returns ------- rgba: ndarray of float32 The rgba values of data_array according to the lookup tables. The shape of this array is equal to data_array.shape + (4,). - ''' + """ range_diff = high - low if range_diff == 0.0 or isinf(range_diff): - # Handle null range, or infinite range (which can happen during + # Handle null range, or infinite range (which can happen during # initialization before range is connected to a data source). - norm_data = 0.5*ones_like(data_array) + norm_data = 0.5 * ones_like(data_array) else: norm_data = clip((data_array - low) / range_diff, 0.0, 1.0) - nanmask = isnan(norm_data) - norm_data = where(nanmask, 0, (norm_data * (steps-1)).astype(int)) - rgba = zeros(norm_data.shape+(4,), float32) - rgba[...,0] = where(nanmask, 0, take(red_lut, norm_data)) - rgba[...,1] = where(nanmask, 0, take(green_lut, norm_data)) - rgba[...,2] = where(nanmask, 0, take(blue_lut, norm_data)) - rgba[...,3] = where(nanmask, 0, take(alpha_lut, norm_data)) + norm_data = where(nanmask, 0, (norm_data * (steps - 1)).astype(int)) + rgba = zeros(norm_data.shape + (4,), float32) + rgba[..., 0] = where(nanmask, 0, take(red_lut, norm_data)) + rgba[..., 1] = where(nanmask, 0, take(green_lut, norm_data)) + rgba[..., 2] = where(nanmask, 0, take(blue_lut, norm_data)) + rgba[..., 3] = where(nanmask, 0, take(alpha_lut, norm_data)) return rgba -def map_colors_uint8(data_array, steps, low, high, red_lut, green_lut, blue_lut, - alpha_lut): - '''Map colors from color lookup tables to a data array. + +def map_colors_uint8( + data_array, steps, low, high, red_lut, green_lut, blue_lut, alpha_lut +): + """Map colors from color lookup tables to a data array. This is used in ColorMapper.map_screen @@ -216,31 +239,29 @@ def map_colors_uint8(data_array, steps, low, high, red_lut, green_lut, blue_lut, The blue channel lookup table alpha_lut : ndarray of uint8 The alpha channel lookup table - + Returns ------- rgba: ndarray of uint8 The rgba values of data_array according to the lookup tables. The shape of this array is equal to data_array.shape + (4,). - ''' + """ range_diff = high - low if range_diff == 0.0 or isinf(range_diff): - # Handle null range, or infinite range (which can happen during + # Handle null range, or infinite range (which can happen during # initialization before range is connected to a data source). - norm_data = 0.5*ones_like(data_array) + norm_data = 0.5 * ones_like(data_array) else: norm_data = clip((data_array - low) / range_diff, 0.0, 1.0) - nanmask = isnan(norm_data) - norm_data = where(nanmask, 0, (norm_data * (steps-1)).astype('uint8')) - rgba = zeros(norm_data.shape+(4,), dtype='uint8') - rgba[...,0] = where(nanmask, 0, take(red_lut, norm_data)) - rgba[...,1] = where(nanmask, 0, take(green_lut, norm_data)) - rgba[...,2] = where(nanmask, 0, take(blue_lut, norm_data)) - rgba[...,3] = where(nanmask, 0, take(alpha_lut, norm_data)) + norm_data = where(nanmask, 0, (norm_data * (steps - 1)).astype("uint8")) + rgba = zeros(norm_data.shape + (4,), dtype="uint8") + rgba[..., 0] = where(nanmask, 0, take(red_lut, norm_data)) + rgba[..., 1] = where(nanmask, 0, take(green_lut, norm_data)) + rgba[..., 2] = where(nanmask, 0, take(blue_lut, norm_data)) + rgba[..., 3] = where(nanmask, 0, take(alpha_lut, norm_data)) return rgba - diff --git a/chaco/abstract_colormap.py b/chaco/abstract_colormap.py index a10dd694d..f36fa0c8f 100644 --- a/chaco/abstract_colormap.py +++ b/chaco/abstract_colormap.py @@ -4,6 +4,7 @@ from .data_range_1d import DataRange1D + class AbstractColormap(HasTraits): """ Abstract class for color maps, which map from scalar values to color values. @@ -13,7 +14,7 @@ class AbstractColormap(HasTraits): range = Instance(DataRange1D) # The color depth of the colors to use. - color_depth = Enum('rgba', 'rgb') + color_depth = Enum("rgba", "rgb") # A generic "update" event that generally means that anything that relies # on this mapper for visual output should do a redraw or repaint. @@ -65,4 +66,4 @@ def map_uint8(self, val): **color_depth** setting. """ # default implementation (not efficient) - return (self.map_screen(val)*255.0).astype('uint8') + return (self.map_screen(val) * 255.0).astype("uint8") diff --git a/chaco/abstract_controller.py b/chaco/abstract_controller.py index d687c4bd2..46cf28268 100644 --- a/chaco/abstract_controller.py +++ b/chaco/abstract_controller.py @@ -18,7 +18,7 @@ def __init__(self, component, *args, **kw): super(AbstractController, self).__init__(*args, **kw) def deactivate(self, component): - """ This method is called by the component when this controller is no + """This method is called by the component when this controller is no longer the active tool. """ pass diff --git a/chaco/abstract_data_range.py b/chaco/abstract_data_range.py index 9420fb084..925c58ba3 100644 --- a/chaco/abstract_data_range.py +++ b/chaco/abstract_data_range.py @@ -10,7 +10,7 @@ class AbstractDataRange(HasTraits): - """ Abstract class for ranges that represent sub-regions of data space. + """Abstract class for ranges that represent sub-regions of data space. They support "autoscaling" by querying their associated data sources. """ @@ -33,34 +33,35 @@ class AbstractDataRange(HasTraits): high = Float(1.0) #: Setting for the lower bound of this range. - low_setting = Trait('auto', 'auto', Float) + low_setting = Trait("auto", "auto", Float) #: Setting for the upper bound of this range. - high_setting = Trait('auto', 'auto', Float) + high_setting = Trait("auto", "auto", Float) #: Event that is fired when the actual bounds values change; the value #: of the event is a tuple (low_bound, high_bound) updated = Event - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Concrete methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, *sources, **kwargs): if len(sources) > 0: - if 'sources' in kwargs: - raise RuntimeError("Datasources for data range provided as " - "both positional and keyword arguments.") + if "sources" in kwargs: + raise RuntimeError( + "Datasources for data range provided as " + "both positional and keyword arguments." + ) else: - kwargs['sources'] = list(sources) + kwargs["sources"] = list(sources) super(AbstractDataRange, self).__init__(**kwargs) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Abstract methods that subclasses must implement - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def clip_data(self, data): - """ Returns a list of data values that are within the range. + """Returns a list of data values that are within the range. Given an array of data values of the same dimensionality as the range, returns a list of data values that are inside the range. @@ -68,7 +69,7 @@ def clip_data(self, data): raise NotImplementedError def mask_data(self, data): - """ Returns a mask array, indicating whether values in the given array + """Returns a mask array, indicating whether values in the given array are inside the range. Given an array of data values of the same dimensionality as the range, @@ -79,7 +80,7 @@ def mask_data(self, data): raise NotImplementedError def bound_data(self, data): - """ Returns a tuple of indices for the start and end of the first run + """Returns a tuple of indices for the start and end of the first run of data that falls within the range. Given an array of data values of the same dimensionality as the range, @@ -93,7 +94,7 @@ def bound_data(self, data): raise NotImplementedError def set_bounds(self, *new_bounds): - """ Sets all the bounds of the range simultaneously. + """Sets all the bounds of the range simultaneously. Because each bounds change probably fires an event, this method allows tools to set all range elements in a single, atomic step. @@ -112,10 +113,9 @@ def set_bounds(self, *new_bounds): raise NotImplementedError def _refresh_bounds(self): - """ Resets the values of the bounds depending on the data sources + """Resets the values of the bounds depending on the data sources referenced by the range. This method is called only if one of the bounds settings is "auto". """ raise NotImplementedError - diff --git a/chaco/abstract_data_source.py b/chaco/abstract_data_source.py index 6813fb4cb..426872043 100644 --- a/chaco/abstract_data_source.py +++ b/chaco/abstract_data_source.py @@ -7,8 +7,9 @@ # Local relative imports from .base import DimensionTrait + class AbstractDataSource(HasTraits): - """ This abstract interface must be implemented by any class supplying data + """This abstract interface must be implemented by any class supplying data to Chaco. Chaco does not have a notion of a "data format". For the most part, a data @@ -52,9 +53,9 @@ class AbstractDataSource(HasTraits): #: the datasource is serialized? persist_data = Bool(True) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Abstract methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def get_data(self): """get_data() -> data_array @@ -113,17 +114,16 @@ def get_bounds(self): """ raise NotImplementedError - ### Persistence ########################################################### def _metadata_default(self): - return {"selections":[], "annotations":[]} + return {"selections": [], "annotations": []} def __getstate__(self): - state = super(AbstractDataSource,self).__getstate__() + state = super(AbstractDataSource, self).__getstate__() # everything but 'metadata' - for key in ['value_dimension', 'index_dimension', 'persist_data']: + for key in ["value_dimension", "index_dimension", "persist_data"]: if key in state: del state[key] diff --git a/chaco/abstract_mapper.py b/chaco/abstract_mapper.py index 9a5649ecf..d4ff84da7 100644 --- a/chaco/abstract_mapper.py +++ b/chaco/abstract_mapper.py @@ -8,7 +8,7 @@ class AbstractMapper(HasTraits): - """ Defines an abstract mapping from a region in input space to a + """Defines an abstract mapping from a region in input space to a region in output space. """ @@ -25,19 +25,19 @@ class AbstractMapper(HasTraits): domain_limits = Tuple(None, None) def map_screen(self, data_array): - """ map_screen(data_array) -> screen_array + """map_screen(data_array) -> screen_array Maps values from data space into screen space. """ def map_data(self, screen_val): - """ map_data(screen_val) -> data_val + """map_data(screen_val) -> data_val Maps values from screen space into data space. """ def map_data_array(self, screen_vals): - """ map_data_array(screen_vals) -> data_vals + """map_data_array(screen_vals) -> data_vals Maps an array of values from screen space into data space. By default, this method just loops over the points, calling map_data() @@ -46,13 +46,12 @@ def map_data_array(self, screen_vals): """ return array([self.map_data(v) for v in screen_vals]) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Persistence-related methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __getstate__(self): - state = super(AbstractMapper,self).__getstate__() - for key in ['_cache_valid']: + state = super(AbstractMapper, self).__getstate__() + for key in ["_cache_valid"]: if key in state: del state[key] diff --git a/chaco/abstract_overlay.py b/chaco/abstract_overlay.py index 49844fa1b..3d0807c8d 100644 --- a/chaco/abstract_overlay.py +++ b/chaco/abstract_overlay.py @@ -11,7 +11,7 @@ class AbstractOverlay(PlotComponent): - """ The base class for overlays and underlays of the plot area. + """The base class for overlays and underlays of the plot area. The only default additional feature of an overlay is that it implements an overlay() drawing method that overlays this component on top of @@ -36,12 +36,11 @@ def __init__(self, component=None, *args, **kw): super(AbstractOverlay, self).__init__(*args, **kw) def overlay(self, other_component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. - """ + """Draws this component overlaid on another component.""" pass def _draw(self, gc, view_bounds=None, mode="normal"): - """ Draws the component, paying attention to **draw_order**. If the + """Draws the component, paying attention to **draw_order**. If the overlay has a non-null .component, then renders as an overlay; otherwise, default to the standard PlotComponent behavior. @@ -53,8 +52,7 @@ def _draw(self, gc, view_bounds=None, mode="normal"): super(AbstractOverlay, self)._draw(gc, view_bounds, mode) def _request_redraw(self): - """ Overrides Enable Component. - """ + """Overrides Enable Component.""" if self.component is not None: self.component.request_redraw() super(AbstractOverlay, self)._request_redraw() diff --git a/chaco/abstract_plot_data.py b/chaco/abstract_plot_data.py index 0b2611085..5a64e01ca 100644 --- a/chaco/abstract_plot_data.py +++ b/chaco/abstract_plot_data.py @@ -8,20 +8,19 @@ class AbstractPlotData(HasTraits): Defines the interface for data providers to Plot. """ - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Events that consumers of this data should use - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- #: Indicates that some of the data has changed. The event object must #: be a dict with keys "added", "removed", "changed" and values that are #: lists of strings. This event is used by consumers of this data. data_changed = Event - - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Flags - these determine how downstream consumers of the PlotData objet # interact with it. (Typically "consumers" just refers to Plots.) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- #: Can consumers (Plots) write data back through this interface using #: set_data()? @@ -30,36 +29,33 @@ class AbstractPlotData(HasTraits): #: Can consumers (Plots) set selections? selectable = Bool(True) - def list_data(self): - """ Returns a list of valid names to use for get_data(). + """Returns a list of valid names to use for get_data(). These names are generally strings but can also be integers or any other hashable type. """ raise NotImplementedError - def get_data(self, name): - """ Returns the data or data source associated with *name*. + """Returns the data or data source associated with *name*. If there is no data or data source associated with the name, this method returns None. """ raise NotImplementedError - def del_data(self, name): - """ Deletes the array specified by *name*, or raises a KeyError if + """Deletes the array specified by *name*, or raises a KeyError if the named array does not exist. - + If the instance is not writable, then this must do nothing. - + """ raise NotImplementedError def set_data(self, name, new_data, generate_name=False): - """ Sets the specified array as the value for either the specified + """Sets the specified array as the value for either the specified name or a generated name. If the instance's `writable` attribute is True, then this method sets @@ -84,19 +80,18 @@ def set_data(self, name, new_data, generate_name=False): """ raise NotImplementedError - def update_data(self, *args, **kwargs): """ Update a set of data values, firing only one data_changed event. - + This function has the same signature as the dictionary update() method. - + """ raise NotImplementedError def set_selection(self, name, selection): - """ Sets the selection on the specified data. + """Sets the selection on the specified data. This method informs the class that Chaco has selected a portion of the data. @@ -111,9 +106,9 @@ def set_selection(self, name, selection): """ raise NotImplementedError - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Dictionary Interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __getitem__(self, name): return self.arrays.get(name, None) @@ -126,4 +121,3 @@ def __delitem__(self, name): def update(self, *args, **kwargs): self.update_data(*args, **kwargs) - diff --git a/chaco/abstract_plot_renderer.py b/chaco/abstract_plot_renderer.py index 2456453d7..449268c84 100644 --- a/chaco/abstract_plot_renderer.py +++ b/chaco/abstract_plot_renderer.py @@ -6,8 +6,9 @@ # Local relative imports from .plot_component import PlotComponent + class AbstractPlotRenderer(PlotComponent): - """ This is the minimal interface that all plot renderers must support. + """This is the minimal interface that all plot renderers must support. Higher-dimensionality plot renderers can implement a richer subclass of this abstract class. @@ -18,9 +19,9 @@ class AbstractPlotRenderer(PlotComponent): origin = Enum("bottom left", "top left", "bottom right", "top right") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Override default values of inherited traits PlotComponent - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Overrides the default value inherited from PlotComponent. bgcolor = "transparent" @@ -28,23 +29,23 @@ class AbstractPlotRenderer(PlotComponent): #: Overrides the default value inherited from PlotComponent. resizable = "hv" - def map_screen(self, data_array): - """ Maps an array of data points to screen space and returns an array + """Maps an array of data points to screen space and returns an array of screen space points. """ raise NotImplementedError def map_data(self, screen_pt): - """ Maps a screen space point (sx, sy) to the "index" space of the plot. + """Maps a screen space point (sx, sy) to the "index" space of the plot. Returns a floating point number, *not* an integer index. """ raise NotImplementedError - def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, \ - index_only = False): - """ Maps a screen space point to an index into the plot's index array(s). + def map_index( + self, screen_pt, threshold=0.0, outside_returns_none=True, index_only=False + ): + """Maps a screen space point to an index into the plot's index array(s). Parameters ---------- @@ -77,7 +78,7 @@ def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, \ raise NotImplementedError def _render_icon(self, gc, x, y, width, height): - """ Renders an icon for this plot. + """Renders an icon for this plot. This method is used by the legend to draw representation of this plot as an icon into the box defined by the given coordinates. diff --git a/chaco/api.py b/chaco/api.py index 9de7bab1d..7563647d0 100644 --- a/chaco/api.py +++ b/chaco/api.py @@ -3,10 +3,21 @@ # This just imports the key datamodel classes into the top-level package # namespace for convenience. -from .base import NumericalSequenceTrait, PointTrait, ImageTrait, DimensionTrait, \ - SortOrderTrait, bin_search, reverse_map_1d, right_shift, \ - left_shift, sort_points, find_runs, arg_find_runs, \ - point_line_distance +from .base import ( + NumericalSequenceTrait, + PointTrait, + ImageTrait, + DimensionTrait, + SortOrderTrait, + bin_search, + reverse_map_1d, + right_shift, + left_shift, + sort_points, + find_runs, + arg_find_runs, + point_line_distance, +) # Data model from .abstract_data_source import AbstractDataSource @@ -44,8 +55,13 @@ from .simple_plot_frame import SimplePlotFrame from .plot_component import PlotComponent from .plot_graphics_context import PlotGraphicsContext, PlotGraphicsContextMixin -from .plot_containers import OverlayPlotContainer, HPlotContainer, VPlotContainer, \ - GridPlotContainer +from .plot_containers import ( + OverlayPlotContainer, + HPlotContainer, + VPlotContainer, + GridPlotContainer, +) + GridContainer = GridPlotContainer try: @@ -92,8 +108,14 @@ from .text_plot import TextPlot # Plot factories -from .plot_factory import create_bar_plot, create_line_plot, create_scatter_plot, \ - create_polar_plot, add_default_axes, add_default_grids +from .plot_factory import ( + create_bar_plot, + create_line_plot, + create_scatter_plot, + create_polar_plot, + add_default_axes, + add_default_grids, +) from .abstract_plot_data import AbstractPlotData from .array_plot_data import ArrayPlotData @@ -104,8 +126,16 @@ # Axis from .axis import PlotAxis, MinorPlotAxis from .label_axis import LabelAxis -from .ticks import AbstractTickGenerator, DefaultTickGenerator, auto_ticks, auto_interval, \ - tick_intervals, log_auto_ticks, auto_bounds, calc_bound +from .ticks import ( + AbstractTickGenerator, + DefaultTickGenerator, + auto_ticks, + auto_interval, + tick_intervals, + log_auto_ticks, + auto_bounds, + calc_bound, +) # Grid from .grid import PlotGrid diff --git a/chaco/array_data_source.py b/chaco/array_data_source.py index 1249ffc05..960dac4c8 100644 --- a/chaco/array_data_source.py +++ b/chaco/array_data_source.py @@ -13,7 +13,7 @@ def bounded_nanargmin(arr): - """ Find the index of the minimum value, ignoring NaNs. + """Find the index of the minimum value, ignoring NaNs. If all NaNs, return 0. """ @@ -33,8 +33,9 @@ def bounded_nanargmin(arr): else: return 0 + def bounded_nanargmax(arr): - """ Find the index of the maximum value, ignoring NaNs. + """Find the index of the maximum value, ignoring NaNs. If all NaNs, return -1. """ @@ -52,34 +53,34 @@ def bounded_nanargmax(arr): else: return -1 + class ArrayDataSource(AbstractDataSource): - """ A data source representing a single, continuous array of numerical data. + """A data source representing a single, continuous array of numerical data. This class does not listen to the array for value changes; if you need that behavior, create a subclass that hooks up the appropriate listeners. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractDataSource traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The dimensionality of the indices into this data source (overrides #: AbstractDataSource). - index_dimension = Constant('scalar') + index_dimension = Constant("scalar") #: The dimensionality of the value at each index point (overrides #: AbstractDataSource). - value_dimension = Constant('scalar') + value_dimension = Constant("scalar") #: The sort order of the data. #: This is a specialized optimization for 1-D arrays, but it's an important #: one that's used everywhere. sort_order = SortOrderTrait - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The data array itself. _data = NumericalSequenceTrait @@ -100,17 +101,16 @@ class ArrayDataSource(AbstractDataSource): # typechecks numpy.int64 on 64-bit Windows systems. _max_index = Any - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, data=array([]), sort_order="none", **kw): AbstractDataSource.__init__(self, **kw) self.set_data(data, sort_order) def set_data(self, newdata, sort_order=None): - """ Sets the data, and optionally the sort order, for this data source. + """Sets the data, and optionally the sort order, for this data source. Parameters ---------- @@ -126,23 +126,21 @@ def set_data(self, newdata, sort_order=None): self.data_changed = True def set_mask(self, mask): - """ Sets the mask for this data source. - """ + """Sets the mask for this data source.""" self._cached_mask = mask self.data_changed = True def remove_mask(self): - """ Removes the mask on this data source. - """ + """Removes the mask on this data source.""" self._cached_mask = None self.data_changed = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractDataSource interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def get_data(self): - """ Returns the data for this data source, or 0.0 if it has no data. + """Returns the data for this data source, or 0.0 if it has no data. Implements AbstractDataSource. """ @@ -182,12 +180,15 @@ def get_size(self): return 0 def get_bounds(self): - """ Returns the minimum and maximum values of the data source's data. + """Returns the minimum and maximum values of the data source's data. Implements AbstractDataSource. """ - if self._cached_bounds is None or self._cached_bounds == () or \ - self._cached_bounds == 0.0: + if ( + self._cached_bounds is None + or self._cached_bounds == () + or self._cached_bounds == 0.0 + ): self._compute_bounds() return self._cached_bounds @@ -210,12 +211,12 @@ def reverse_map(self, pt, index=0, outside_returns_none=True): # index is ignored for dataseries with 1-dimensional indices minval, maxval = self._cached_bounds - if (pt < minval): + if pt < minval: if outside_returns_none: return None else: return self._min_index - elif (pt > maxval): + elif pt > maxval: if outside_returns_none: return None else: @@ -223,13 +224,12 @@ def reverse_map(self, pt, index=0, outside_returns_none=True): else: return reverse_map_1d(self._data, pt, self.sort_order) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _compute_bounds(self, data=None): - """ Computes the minimum and maximum values of self._data. + """Computes the minimum and maximum values of self._data. If a data array is passed in, then that is used instead of self._data. This behavior is useful for subclasses. @@ -241,7 +241,7 @@ def _compute_bounds(self, data=None): # Several sources weren't setting the _data attribute, so we # go through the interface. This seems like the correct thing # to do anyway... right? - #data = self._data + # data = self._data data = self.get_data() data_len = 0 @@ -281,12 +281,11 @@ def _compute_bounds(self, data=None): # label-ish data sources. self._cached_bounds = (0.0, 0.0) - self._cached_bounds = (data[self._min_index], - data[self._max_index]) + self._cached_bounds = (data[self._min_index], data[self._max_index]) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _metadata_changed(self, event): self.metadata_changed = True @@ -294,9 +293,9 @@ def _metadata_changed(self, event): def _metadata_items_changed(self, event): self.metadata_changed = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Persistence-related methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __getstate__(self): state = self.__dict__.copy() diff --git a/chaco/array_plot_data.py b/chaco/array_plot_data.py index e44289da6..1483849c9 100644 --- a/chaco/array_plot_data.py +++ b/chaco/array_plot_data.py @@ -11,16 +11,16 @@ class ArrayPlotData(AbstractPlotData): - """ A PlotData implementation class that handles a list of Numpy arrays + """A PlotData implementation class that handles a list of Numpy arrays (or a 2-D Numpy array). By default, it doesn't allow its input data to be modified by downstream Chaco components or interactors. """ - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Public traits - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- #: Map of names to arrays. Although there is no restriction on the array #: dimensions, each array must correspond to a single plot item; that @@ -33,7 +33,7 @@ class ArrayPlotData(AbstractPlotData): writable = True def __init__(self, *data, **kw): - """ ArrayPlotData can be constructed by passing in arrays. + """ArrayPlotData can be constructed by passing in arrays. Keyword arguments can be used to give certain arrays specific names; unnamed arrays are given a generic name of the format 'seriesN', where @@ -64,27 +64,23 @@ def __init__(self, *data, **kw): data = dict(zip(self._generate_names(len(data)), data)) self._update_data(data) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractPlotData Interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def list_data(self): - """ Returns a list of the names of the arrays managed by this instance. - """ + """Returns a list of the names of the arrays managed by this instance.""" return list(self.arrays.keys()) - def get_data(self, name): - """ Returns the array associated with *name*. + """Returns the array associated with *name*. Implements AbstractDataSource. """ return self.arrays.get(name, None) - def del_data(self, name): - """ Deletes the array specified by *name*, or raises a KeyError if + """Deletes the array specified by *name*, or raises a KeyError if the named array does not exist. """ if not self.writable: @@ -92,13 +88,12 @@ def del_data(self, name): if name in self.arrays: del self.arrays[name] - self.data_changed = {'removed': [name]} + self.data_changed = {"removed": [name]} else: raise KeyError("Data series '%s' does not exist." % name) - def set_data(self, name, new_data, generate_name=False): - """ Sets the specified array as the value for either the specified + """Sets the specified array as the value for either the specified name or a generated name. If the instance's `writable` attribute is True, then this method sets @@ -132,13 +127,12 @@ def set_data(self, name, new_data, generate_name=False): if generate_name: names = self._generate_names(1) name = names[0] - + self.update_data({name: new_data}) return name - def update_data(self, *args, **kwargs): - """ Updates any number of arrays before triggering a `data_changed` + """Updates any number of arrays before triggering a `data_changed` event. Useful to set multiple ArrayPlotData entries at once, for example @@ -154,41 +148,39 @@ def update_data(self, *args, **kwargs): """ if not self.writable: return None - + data = dict(*args, **kwargs) event = {} for name in data: if name in self.arrays: - event.setdefault('changed', []).append(name) + event.setdefault("changed", []).append(name) else: - event.setdefault('added', []).append(name) + event.setdefault("added", []).append(name) self._update_data(data) self.data_changed = event - def set_selection(self, name, selection): - """ Overrides AbstractPlotData to do nothing and not raise an error. - """ + """Overrides AbstractPlotData to do nothing and not raise an error.""" pass - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _generate_names(self, n): - """ Generate n new names - """ + """Generate n new names""" max_index = max(self._generate_indices()) - names = ["series{0:d}".format(n) for n in range(max_index+1, max_index+n+1)] + names = [ + "series{0:d}".format(n) for n in range(max_index + 1, max_index + n + 1) + ] return names def _generate_indices(self): - """ Generator that yields all integers that match "series%d" in keys - """ - yield 0 # default minimum + """Generator that yields all integers that match "series%d" in keys""" + yield 0 # default minimum for name in self.list_data(): - if name.startswith('series'): + if name.startswith("series"): try: v = int(name[6:]) except ValueError: @@ -196,8 +188,7 @@ def _generate_indices(self): yield v def _update_data(self, data): - """ Update the array, ensuring that data is an array - """ + """Update the array, ensuring that data is an array""" # note that this call modifies data, but that's OK since the callers # all create the dictionary that they pass in for name, value in list(data.items()): @@ -207,4 +198,3 @@ def _update_data(self, data): data[name] = value self.arrays.update(data) - diff --git a/chaco/axis.py b/chaco/axis.py index e7ca1ed7c..46ba1f537 100644 --- a/chaco/axis.py +++ b/chaco/axis.py @@ -1,14 +1,39 @@ """ Defines the PlotAxis class, and associated validator and UI. """ # Major library import -from numpy import array, around, absolute, cos, dot, float64, inf, pi, \ - sqrt, sin, transpose +from numpy import ( + array, + around, + absolute, + cos, + dot, + float64, + inf, + pi, + sqrt, + sin, + transpose, +) # Enthought Library imports from enable.api import ColorTrait, LineStyle from kiva.trait_defs.kiva_font_trait import KivaFont -from traits.api import Any, Float, Int, Str, Trait, Unicode, \ - Bool, Event, List, Array, Instance, Enum, Callable, ArrayOrNone +from traits.api import ( + Any, + Float, + Int, + Str, + Trait, + Unicode, + Bool, + Event, + List, + Array, + Instance, + Enum, + Callable, + ArrayOrNone, +) # Local relative imports from .ticks import AbstractTickGenerator, DefaultTickGenerator, MinorTickGenerator @@ -19,7 +44,8 @@ def DEFAULT_TICK_FORMATTER(val): - return ("%f"%val).rstrip("0").rstrip(".") + return ("%f" % val).rstrip("0").rstrip(".") + class PlotAxis(AbstractOverlay): """ @@ -38,19 +64,19 @@ class PlotAxis(AbstractOverlay): origin = Enum("bottom left", "top left", "bottom right", "top right") #: The text of the axis title. - title = Trait('', Str, Unicode) #May want to add PlotLabel option + title = Trait("", Str, Unicode) # May want to add PlotLabel option #: The font of the title. - title_font = KivaFont('modern 12') + title_font = KivaFont("modern 12") #: The spacing between the axis line and the title - title_spacing = Trait('auto', 'auto', Float) + title_spacing = Trait("auto", "auto", Float) #: The color of the title. title_color = ColorTrait("black") #: The angle of the title, in degrees, from horizontal line - title_angle = Float(0.) + title_angle = Float(0.0) #: The thickness (in pixels) of each tick. tick_weight = Float(1.0) @@ -59,7 +85,7 @@ class PlotAxis(AbstractOverlay): tick_color = ColorTrait("black") #: The font of the tick labels. - tick_label_font = KivaFont('modern 10') + tick_label_font = KivaFont("modern 10") #: The color of the tick labels. tick_label_color = ColorTrait("black") @@ -68,13 +94,13 @@ class PlotAxis(AbstractOverlay): tick_label_rotate_angle = Float(0) #: Whether to align to corners or edges (corner is better for 45 degree rotation) - tick_label_alignment = Enum('edge', 'corner') + tick_label_alignment = Enum("edge", "corner") #: The margin around the tick labels. tick_label_margin = Int(2) #: The distance of the tick label from the axis. - tick_label_offset = Float(8.) + tick_label_offset = Float(8.0) #: Whether the tick labels appear to the inside or the outside of the plot area tick_label_position = Enum("outside", "inside") @@ -93,7 +119,7 @@ class PlotAxis(AbstractOverlay): tick_visible = Bool(True) #: The dataspace interval between ticks. - tick_interval = Trait('auto', 'auto', Float) + tick_interval = Trait("auto", "auto", Float) #: A callable that implements the AbstractTickGenerator interface. tick_generator = Instance(AbstractTickGenerator) @@ -112,7 +138,7 @@ class PlotAxis(AbstractOverlay): axis_line_weight = Float(1.0) #: The dash style of the axis line. - axis_line_style = LineStyle('solid') + axis_line_style = LineStyle("solid") #: A special version of the axis line that is more useful for geophysical #: plots. @@ -129,9 +155,9 @@ class PlotAxis(AbstractOverlay): #: Fired when the axis's range bounds change. updated = Event - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Override default values of inherited traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Background color (overrides AbstractOverlay). Axes usually let the color of #: the container show through. @@ -141,9 +167,9 @@ class PlotAxis(AbstractOverlay): #: Typically, axes are resizable in both dimensions. resizable = "hv" - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private Traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Cached position calculations @@ -163,14 +189,12 @@ class PlotAxis(AbstractOverlay): _axis_pixel_vector = Array _end_axis_point = Array - ticklabel_cache = List _cache_valid = Bool(False) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, component=None, **kwargs): # TODO: change this back to a factory in the instance trait some day @@ -182,26 +206,25 @@ def __init__(self, component=None, **kwargs): self.component = component def invalidate(self): - """ Invalidates the pre-computed layout and scaling data. - """ + """Invalidates the pre-computed layout and scaling data.""" self._reset_cache() self.invalidate_draw() def traits_view(self): - """ Returns a View instance for use with Traits UI. This method is + """Returns a View instance for use with Traits UI. This method is called automatically be the Traits framework when .edit_traits() is invoked. """ from .axis_view import AxisView - return AxisView + return AxisView - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # PlotComponent and AbstractOverlay interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _do_layout(self, *args, **kw): - """ Tells this component to do layout at a given size. + """Tells this component to do layout at a given size. Overrides Component. """ @@ -210,8 +233,8 @@ def _do_layout(self, *args, **kw): else: super(PlotAxis, self)._do_layout(*args, **kw) - def overlay(self, component, gc, view_bounds=None, mode='normal'): - """ Draws this component overlaid on another component. + def overlay(self, component, gc, view_bounds=None, mode="normal"): + """Draws this component overlaid on another component. Overrides AbstractOverlay. """ @@ -219,15 +242,15 @@ def overlay(self, component, gc, view_bounds=None, mode='normal'): return self._draw_component(gc, view_bounds, mode, component) - def _draw_overlay(self, gc, view_bounds=None, mode='normal'): - """ Draws the overlay layer of a component. + def _draw_overlay(self, gc, view_bounds=None, mode="normal"): + """Draws the overlay layer of a component. Overrides PlotComponent. """ self._draw_component(gc, view_bounds, mode) - def _draw_component(self, gc, view_bounds=None, mode='normal', component=None): - """ Draws the component. + def _draw_component(self, gc, view_bounds=None, mode="normal", component=None): + """Draws the component. This method is preserved for backwards compatibility. Overrides PlotComponent. @@ -259,13 +282,12 @@ def _draw_component(self, gc, view_bounds=None, mode='normal', component=None): self._cache_valid = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private draw routines - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _layout_as_overlay(self, size=None, force=False): - """ Lays out the axis as an overlay on another component. - """ + """Lays out the axis as an overlay on another component.""" if self.component is not None: if self.orientation in ("left", "right"): self.y = self.component.y @@ -287,8 +309,7 @@ def _layout_as_overlay(self, size=None, force=False): self.y = self.component.y2 + 1 def _draw_axis_line(self, gc, startpoint, endpoint): - """ Draws the line for the axis. - """ + """Draws the line for the axis.""" with gc: gc.set_antialias(0) gc.set_line_width(self.axis_line_weight) @@ -299,33 +320,37 @@ def _draw_axis_line(self, gc, startpoint, endpoint): gc.stroke_path() def _draw_title(self, gc, label=None, axis_offset=None): - """ Draws the title for the axis. - """ + """Draws the title for the axis.""" if label is None: - title_label = Label(text=self.title, - font=self.title_font, - color=self.title_color, - rotate_angle=self.title_angle) + title_label = Label( + text=self.title, + font=self.title_font, + color=self.title_color, + rotate_angle=self.title_angle, + ) else: title_label = label # get the _rotated_ bounding box of the label tl_bounds = array(title_label.get_bounding_box(gc), float64) - text_center_to_corner = -tl_bounds/2.0 + text_center_to_corner = -tl_bounds / 2.0 # which axis are we moving away from the axis line along? axis_index = self._major_axis.argmin() - if self.title_spacing != 'auto': + if self.title_spacing != "auto": axis_offset = self.title_spacing - if (self.title_spacing) and (axis_offset is None ): + if (self.title_spacing) and (axis_offset is None): if not self.ticklabel_cache: axis_offset = 25 else: - axis_offset = max([l._bounding_box[axis_index] for l in self.ticklabel_cache]) * 1.3 + axis_offset = ( + max([l._bounding_box[axis_index] for l in self.ticklabel_cache]) + * 1.3 + ) - offset = (self._origin_point+self._end_axis_point)/2 - axis_dist = self.tick_out + tl_bounds[axis_index]/2.0 + axis_offset + offset = (self._origin_point + self._end_axis_point) / 2 + axis_dist = self.tick_out + tl_bounds[axis_index] / 2.0 + axis_offset offset -= self._inside_vector * axis_dist offset += text_center_to_corner @@ -334,24 +359,22 @@ def _draw_title(self, gc, label=None, axis_offset=None): gc.translate_ctm(*(-offset)) def _draw_ticks(self, gc): - """ Draws the tick marks for the axis. - """ + """Draws the tick marks for the axis.""" if not self.tick_visible: return gc.set_stroke_color(self.tick_color_) gc.set_line_width(self.tick_weight) gc.set_antialias(False) gc.begin_path() - tick_in_vector = self._inside_vector*self.tick_in - tick_out_vector = self._inside_vector*self.tick_out + tick_in_vector = self._inside_vector * self.tick_in + tick_out_vector = self._inside_vector * self.tick_out for tick_pos in self._tick_positions: gc.move_to(*(tick_pos + tick_in_vector)) gc.line_to(*(tick_pos - tick_out_vector)) gc.stroke_path() def _draw_labels(self, gc): - """ Draws the tick labels for the axis. - """ + """Draws the tick labels for the axis.""" # which axis are we moving away from the axis line along? axis_index = self._major_axis.argmin() @@ -360,59 +383,59 @@ def _draw_labels(self, gc): inside_vector = -inside_vector for i in range(len(self._tick_label_positions)): - #We want a more sophisticated scheme than just 2 decimals all the time + # We want a more sophisticated scheme than just 2 decimals all the time ticklabel = self.ticklabel_cache[i] tl_bounds = self._tick_label_bounding_boxes[i] - #base_position puts the tick label at a point where the vector - #extending from the tick mark inside 8 units - #just touches the rectangular bounding box of the tick label. - #Note: This is not necessarily optimal for non - #horizontal/vertical axes. More work could be done on this. + # base_position puts the tick label at a point where the vector + # extending from the tick mark inside 8 units + # just touches the rectangular bounding box of the tick label. + # Note: This is not necessarily optimal for non + # horizontal/vertical axes. More work could be done on this. base_position = self._tick_label_positions[i].copy() - axis_dist = self.tick_label_offset + tl_bounds[axis_index]/2.0 + axis_dist = self.tick_label_offset + tl_bounds[axis_index] / 2.0 base_position -= inside_vector * axis_dist - base_position -= tl_bounds/2.0 + base_position -= tl_bounds / 2.0 - if self.tick_label_alignment == 'corner': + if self.tick_label_alignment == "corner": if self.orientation in ("top", "bottom"): - base_position[0] += tl_bounds[0]/2.0 + base_position[0] += tl_bounds[0] / 2.0 elif self.orientation == "left": - base_position[1] -= tl_bounds[1]/2.0 + base_position[1] -= tl_bounds[1] / 2.0 elif self.orientation == "right": - base_position[1] += tl_bounds[1]/2.0 + base_position[1] += tl_bounds[1] / 2.0 if self.ensure_labels_bounded: bound_idx = self._major_axis.argmax() if i == 0: - base_position[bound_idx] = max(base_position[bound_idx], - self._origin_point[bound_idx]) - elif i == len(self._tick_label_positions)-1: - base_position[bound_idx] = min(base_position[bound_idx], - self._end_axis_point[bound_idx] - \ - tl_bounds[bound_idx]) + base_position[bound_idx] = max( + base_position[bound_idx], self._origin_point[bound_idx] + ) + elif i == len(self._tick_label_positions) - 1: + base_position[bound_idx] = min( + base_position[bound_idx], + self._end_axis_point[bound_idx] - tl_bounds[bound_idx], + ) tlpos = around(base_position) gc.translate_ctm(*tlpos) ticklabel.draw(gc) gc.translate_ctm(*(-tlpos)) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods for computing positions and layout - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _reset_cache(self): - """ Clears the cached tick positions, labels, and label positions. - """ + """Clears the cached tick positions, labels, and label positions.""" self._tick_positions = [] self._tick_label_list = [] self._tick_label_positions = [] def _compute_tick_positions(self, gc, overlay_component=None): - """ Calculates the positions for the tick marks. - """ - if (self.mapper is None): + """Calculates the positions for the tick marks.""" + if self.mapper is None: self._reset_cache() self._cache_valid = True return @@ -422,7 +445,7 @@ def _compute_tick_positions(self, gc, overlay_component=None): screenhigh = self.mapper.high_pos screenlow = self.mapper.low_pos if overlay_component is not None: - origin = getattr(overlay_component, 'origin', 'bottom left') + origin = getattr(overlay_component, "origin", "bottom left") else: origin = self.origin if self.orientation in ("top", "bottom"): @@ -438,49 +461,72 @@ def _compute_tick_positions(self, gc, overlay_component=None): if flip_from_gc: screenlow, screenhigh = screenhigh, screenlow - if (datalow == datahigh) or (screenlow == screenhigh) or \ - (datalow in [inf, -inf]) or (datahigh in [inf, -inf]): + if ( + (datalow == datahigh) + or (screenlow == screenhigh) + or (datalow in [inf, -inf]) + or (datahigh in [inf, -inf]) + ): self._reset_cache() self._cache_valid = True return if datalow > datahigh: - raise RuntimeError("DataRange low is greater than high; unable to compute axis ticks.") + raise RuntimeError( + "DataRange low is greater than high; unable to compute axis ticks." + ) if not self.tick_generator: return if hasattr(self.tick_generator, "get_ticks_and_labels"): # generate ticks and labels simultaneously - tmp = self.tick_generator.get_ticks_and_labels(datalow, datahigh, - screenlow, screenhigh) + tmp = self.tick_generator.get_ticks_and_labels( + datalow, datahigh, screenlow, screenhigh + ) if len(tmp) == 0: tick_list = [] labels = [] else: tick_list, labels = tmp # compute the labels here - self.ticklabel_cache = [Label(text=lab, - font=self.tick_label_font, - color=self.tick_label_color) \ - for lab in labels] - self._tick_label_bounding_boxes = [array(ticklabel.get_bounding_box(gc), float64) \ - for ticklabel in self.ticklabel_cache] + self.ticklabel_cache = [ + Label(text=lab, font=self.tick_label_font, color=self.tick_label_color) + for lab in labels + ] + self._tick_label_bounding_boxes = [ + array(ticklabel.get_bounding_box(gc), float64) + for ticklabel in self.ticklabel_cache + ] else: - scale = 'log' if isinstance(self.mapper, LogMapper) else 'linear' + scale = "log" if isinstance(self.mapper, LogMapper) else "linear" if self.small_haxis_style: tick_list = array([datalow, datahigh]) else: - tick_list = array(self.tick_generator.get_ticks(datalow, datahigh, - datalow, datahigh, - self.tick_interval, - use_endpoints=False, - scale=scale), float64) - - mapped_tick_positions = (array(self.mapper.map_screen(tick_list))-screenlow) / \ - (screenhigh-screenlow) - self._tick_positions = around(array([self._axis_vector*tickpos + self._origin_point \ - for tickpos in mapped_tick_positions])) + tick_list = array( + self.tick_generator.get_ticks( + datalow, + datahigh, + datalow, + datahigh, + self.tick_interval, + use_endpoints=False, + scale=scale, + ), + float64, + ) + + mapped_tick_positions = ( + array(self.mapper.map_screen(tick_list)) - screenlow + ) / (screenhigh - screenlow) + self._tick_positions = around( + array( + [ + self._axis_vector * tickpos + self._origin_point + for tickpos in mapped_tick_positions + ] + ) + ) self._tick_label_list = tick_list self._tick_label_positions = self._tick_positions @@ -494,73 +540,82 @@ def _compute_labels(self, gc): return formatter = self.tick_label_formatter + def build_label(val): tickstring = formatter(val) if formatter is not None else str(val) - return Label(text=tickstring, - font=self.tick_label_font, - color=self.tick_label_color, - rotate_angle=self.tick_label_rotate_angle, - margin=self.tick_label_margin) + return Label( + text=tickstring, + font=self.tick_label_font, + color=self.tick_label_color, + rotate_angle=self.tick_label_rotate_angle, + margin=self.tick_label_margin, + ) self.ticklabel_cache = [build_label(val) for val in self._tick_label_list] - self._tick_label_bounding_boxes = [array(ticklabel.get_bounding_box(gc), float) - for ticklabel in self.ticklabel_cache] + self._tick_label_bounding_boxes = [ + array(ticklabel.get_bounding_box(gc), float) + for ticklabel in self.ticklabel_cache + ] def _calculate_geometry(self): origin = self.origin screenhigh = self.mapper.high_pos screenlow = self.mapper.low_pos - if self.orientation in ('top', 'bottom'): + if self.orientation in ("top", "bottom"): self._major_axis_size = self.bounds[0] self._minor_axis_size = self.bounds[1] - self._major_axis = array([1., 0.]) - self._title_orientation = array([0.,1.]) - if self.orientation == 'top': + self._major_axis = array([1.0, 0.0]) + self._title_orientation = array([0.0, 1.0]) + if self.orientation == "top": self._origin_point = array(self.position) - self._inside_vector = array([0.,-1.]) - else: #self.oriention == 'bottom' - self._origin_point = array(self.position) + array([0., self.bounds[1]]) - self._inside_vector = array([0., 1.]) + self._inside_vector = array([0.0, -1.0]) + else: # self.oriention == 'bottom' + self._origin_point = array(self.position) + array([0.0, self.bounds[1]]) + self._inside_vector = array([0.0, 1.0]) if "right" in origin: screenlow, screenhigh = screenhigh, screenlow - elif self.orientation in ('left', 'right'): + elif self.orientation in ("left", "right"): self._major_axis_size = self.bounds[1] self._minor_axis_size = self.bounds[0] - self._major_axis = array([0., 1.]) - self._title_orientation = array([-1., 0]) - if self.orientation == 'left': - self._origin_point = array(self.position) + array([self.bounds[0], 0.]) - self._inside_vector = array([1., 0.]) - else: #self.orientation == 'right' + self._major_axis = array([0.0, 1.0]) + self._title_orientation = array([-1.0, 0]) + if self.orientation == "left": + self._origin_point = array(self.position) + array([self.bounds[0], 0.0]) + self._inside_vector = array([1.0, 0.0]) + else: # self.orientation == 'right' self._origin_point = array(self.position) - self._inside_vector = array([-1., 0.]) + self._inside_vector = array([-1.0, 0.0]) if "top" in origin: screenlow, screenhigh = screenhigh, screenlow if self.ensure_ticks_bounded: - self._origin_point -= self._inside_vector*self.tick_in + self._origin_point -= self._inside_vector * self.tick_in - self._end_axis_point = abs(screenhigh-screenlow)*self._major_axis + self._origin_point + self._end_axis_point = ( + abs(screenhigh - screenlow) * self._major_axis + self._origin_point + ) self._axis_vector = self._end_axis_point - self._origin_point # This is the vector that represents one unit of data space in terms of screen space. - self._axis_pixel_vector = self._axis_vector/sqrt(dot(self._axis_vector,self._axis_vector)) + self._axis_pixel_vector = self._axis_vector / sqrt( + dot(self._axis_vector, self._axis_vector) + ) def _calculate_geometry_overlay(self, overlay_component=None): if overlay_component is None: overlay_component = self - component_origin = getattr(overlay_component, "origin", 'bottom left') + component_origin = getattr(overlay_component, "origin", "bottom left") screenhigh = self.mapper.high_pos screenlow = self.mapper.low_pos - if self.orientation in ('top', 'bottom'): + if self.orientation in ("top", "bottom"): self._major_axis_size = overlay_component.bounds[0] self._minor_axis_size = overlay_component.bounds[1] - self._major_axis = array([1., 0.]) - self._title_orientation = array([0.,1.]) - if self.orientation == 'top': + self._major_axis = array([1.0, 0.0]) + self._title_orientation = array([0.0, 1.0]) + if self.orientation == "top": self._origin_point = array([overlay_component.x, overlay_component.y2]) self._inside_vector = array([0.0, -1.0]) else: @@ -569,12 +624,12 @@ def _calculate_geometry_overlay(self, overlay_component=None): if "right" in component_origin: screenlow, screenhigh = screenhigh, screenlow - elif self.orientation in ('left', 'right'): + elif self.orientation in ("left", "right"): self._major_axis_size = overlay_component.bounds[1] self._minor_axis_size = overlay_component.bounds[0] - self._major_axis = array([0., 1.]) - self._title_orientation = array([-1., 0]) - if self.orientation == 'left': + self._major_axis = array([0.0, 1.0]) + self._title_orientation = array([-1.0, 0]) + if self.orientation == "left": self._origin_point = array([overlay_component.x, overlay_component.y]) self._inside_vector = array([1.0, 0.0]) else: @@ -584,16 +639,20 @@ def _calculate_geometry_overlay(self, overlay_component=None): screenlow, screenhigh = screenhigh, screenlow if self.ensure_ticks_bounded: - self._origin_point -= self._inside_vector*self.tick_in + self._origin_point -= self._inside_vector * self.tick_in - self._end_axis_point = abs(screenhigh-screenlow)*self._major_axis + self._origin_point + self._end_axis_point = ( + abs(screenhigh - screenlow) * self._major_axis + self._origin_point + ) self._axis_vector = self._end_axis_point - self._origin_point # This is the vector that represents one unit of data space in terms of screen space. - self._axis_pixel_vector = self._axis_vector/sqrt(dot(self._axis_vector,self._axis_vector)) + self._axis_pixel_vector = self._axis_vector / sqrt( + dot(self._axis_vector, self._axis_vector) + ) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _bounds_changed(self, old, new): super(PlotAxis, self)._bounds_changed(old, new) @@ -660,8 +719,10 @@ def _component_changed(self): # Try to pick the most appropriate mapper for our orientation # and what information we can glean from our component. - attrmap = { "left": ("ymapper", "y_mapper", "value_mapper"), - "bottom": ("xmapper", "x_mapper", "index_mapper"), } + attrmap = { + "left": ("ymapper", "y_mapper", "value_mapper"), + "bottom": ("xmapper", "x_mapper", "index_mapper"), + } attrmap["right"] = attrmap["left"] attrmap["top"] = attrmap["bottom"] @@ -673,13 +734,13 @@ def _component_changed(self): break # Keep our origin in sync with the component - self.origin = getattr(component, 'origin', 'bottom left') + self.origin = getattr(component, "origin", "bottom left") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The following event handlers just invalidate our previously computed # Label instances and backbuffer if any of our visual attributes change. # TODO: refactor this stuff and the caching of contained objects (e.g. Label) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _title_changed(self): self.invalidate_draw() @@ -687,38 +748,38 @@ def _title_changed(self): self.component.invalidate_draw() def _anytrait_changed(self, name, old, new): - """ For every trait that defines a visual attribute - we just call _invalidate() when a change is made. + """For every trait that defines a visual attribute + we just call _invalidate() when a change is made. """ invalidate_traits = [ - 'title_font', - 'title_spacing', - 'title_color', - 'title_angle', - 'tick_weight', - 'tick_color', - 'tick_label_font', - 'tick_label_color', - 'tick_label_rotate_angle', - 'tick_label_alignment', - 'tick_label_margin', - 'tick_label_offset', - 'tick_label_position', - 'tick_label_formatter', - 'tick_in', - 'tick_out', - 'tick_visible', - 'tick_interval', - 'tick_generator', - 'orientation', - 'origin', - 'axis_line_visible', - 'axis_line_color', - 'axis_line_weight', - 'axis_line_style', - 'small_haxis_style', - 'ensure_labels_bounded', - 'ensure_ticks_bounded', + "title_font", + "title_spacing", + "title_color", + "title_angle", + "tick_weight", + "tick_color", + "tick_label_font", + "tick_label_color", + "tick_label_rotate_angle", + "tick_label_alignment", + "tick_label_margin", + "tick_label_offset", + "tick_label_position", + "tick_label_formatter", + "tick_in", + "tick_out", + "tick_visible", + "tick_interval", + "tick_generator", + "orientation", + "origin", + "axis_line_visible", + "axis_line_color", + "axis_line_weight", + "axis_line_style", + "small_haxis_style", + "ensure_labels_bounded", + "ensure_ticks_bounded", ] if name in invalidate_traits: self._invalidate() @@ -728,39 +789,39 @@ def _anytrait_changed(self, name, old, new): # ------------------------------------------------------------------------ def _title_angle_default(self): - if self.orientation == 'left': + if self.orientation == "left": return 90.0 - if self.orientation == 'right': + if self.orientation == "right": return 270.0 # Then self.orientation in {'top', 'bottom'} return 0.0 - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Persistence-related methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __getstate__(self): dont_pickle = [ - '_tick_list', - '_tick_positions', - '_tick_label_list', - '_tick_label_positions', - '_tick_label_bounding_boxes', - '_major_axis_size', - '_minor_axis_size', - '_major_axis', - '_title_orientation', - '_title_angle', - '_origin_point', - '_inside_vector', - '_axis_vector', - '_axis_pixel_vector', - '_end_axis_point', - '_ticklabel_cache', - '_cache_valid' - ] - - state = super(PlotAxis,self).__getstate__() + "_tick_list", + "_tick_positions", + "_tick_label_list", + "_tick_label_positions", + "_tick_label_bounding_boxes", + "_major_axis_size", + "_minor_axis_size", + "_major_axis", + "_title_orientation", + "_title_angle", + "_origin_point", + "_inside_vector", + "_axis_vector", + "_axis_pixel_vector", + "_end_axis_point", + "_ticklabel_cache", + "_cache_valid", + ] + + state = super(PlotAxis, self).__getstate__() for key in dont_pickle: if key in state: del state[key] @@ -768,7 +829,7 @@ def __getstate__(self): return state def __setstate__(self, state): - super(PlotAxis,self).__setstate__(state) + super(PlotAxis, self).__setstate__(state) self._mapper_changed(None, self.mapper) self._reset_cache() self._cache_valid = False @@ -783,13 +844,13 @@ class MinorPlotAxis(PlotAxis): def __init__(self, *args, **kwargs): super(MinorPlotAxis, self).__init__(*args, **kwargs) - if 'tick_generator' not in kwargs: + if "tick_generator" not in kwargs: self.tick_generator = MinorTickGenerator() - if 'tick_label_formatter' not in kwargs: - self.tick_label_formatter = lambda x: '' - if 'tick_in' not in kwargs: - self.tick_in = 2 - if 'tick_out' not in kwargs: + if "tick_label_formatter" not in kwargs: + self.tick_label_formatter = lambda x: "" + if "tick_in" not in kwargs: + self.tick_in = 2 + if "tick_out" not in kwargs: self.tick_out = 2 - if 'axis_line_visible' not in kwargs: + if "axis_line_visible" not in kwargs: self.axis_line_visible = False diff --git a/chaco/axis_view.py b/chaco/axis_view.py index e546ee624..a5c8e3ec3 100644 --- a/chaco/axis_view.py +++ b/chaco/axis_view.py @@ -2,6 +2,7 @@ from traits.api import TraitError from traitsui.api import View, HGroup, Group, VGroup, Item, TextEditor + def float_or_auto(val): """ Validator function that returns *val* if *val* is either a number or @@ -15,34 +16,42 @@ def float_or_auto(val): return val raise TraitError("Tick interval must be a number or 'auto'.") -# Traits UI for a PlotAxis. -AxisView = View(VGroup( - Group( - Item("object.mapper.range.low", label="Low Range"), - Item("object.mapper.range.high", label="High Range"), - ), - Group( - Item("title", label="Title", editor=TextEditor()), - Item("title_font", label="Font", style="simple"), - Item("title_color", label="Color", style="custom"), - Item("tick_interval", label="Interval", editor=TextEditor(evaluate=float_or_auto)), - label="Main"), - Group( - Item("tick_color", label="Color", style="custom"), - Item("tick_weight", label="Thickness"), - Item("tick_label_color", label="Label color", style="custom"), - HGroup( - Item("tick_in", label="Tick in"), - Item("tick_out", label="Tick out"), - ), - Item("tick_visible", label="Visible"), - label="Ticks"), - Group( - Item("axis_line_color", label="Color", style="custom"), - Item("axis_line_weight", label="Thickness"), - Item("axis_line_visible", label="Visible"), - label="Line"), - ), - buttons = ["OK", "Cancel"] - ) +# Traits UI for a PlotAxis. +AxisView = View( + VGroup( + Group( + Item("object.mapper.range.low", label="Low Range"), + Item("object.mapper.range.high", label="High Range"), + ), + Group( + Item("title", label="Title", editor=TextEditor()), + Item("title_font", label="Font", style="simple"), + Item("title_color", label="Color", style="custom"), + Item( + "tick_interval", + label="Interval", + editor=TextEditor(evaluate=float_or_auto), + ), + label="Main", + ), + Group( + Item("tick_color", label="Color", style="custom"), + Item("tick_weight", label="Thickness"), + Item("tick_label_color", label="Label color", style="custom"), + HGroup( + Item("tick_in", label="Tick in"), + Item("tick_out", label="Tick out"), + ), + Item("tick_visible", label="Visible"), + label="Ticks", + ), + Group( + Item("axis_line_color", label="Color", style="custom"), + Item("axis_line_weight", label="Thickness"), + Item("axis_line_visible", label="Visible"), + label="Line", + ), + ), + buttons=["OK", "Cancel"], +) diff --git a/chaco/barplot.py b/chaco/barplot.py index c32b9fad4..df3f7d1f7 100644 --- a/chaco/barplot.py +++ b/chaco/barplot.py @@ -3,8 +3,17 @@ import logging from numpy import array, compress, column_stack, invert, isnan, transpose, zeros -from traits.api import Any, Bool, Enum, Float, Instance, Property, \ - Range, Tuple, cached_property +from traits.api import ( + Any, + Bool, + Enum, + Float, + Instance, + Property, + Range, + Tuple, + cached_property, +) from enable.api import black_color_trait from kiva.constants import FILL_STROKE @@ -20,10 +29,12 @@ # TODO: make child of BaseXYPlot + class BarPlot(AbstractPlotRenderer): """ A renderer for bar charts. """ + #: The data source to use for the index coordinate. index = Instance(ArrayDataSource) @@ -78,18 +89,17 @@ class BarPlot(AbstractPlotRenderer): #: The RGBA tuple for rendering lines. It is always a tuple of length 4. #: It has the same RGB values as :attr:`line_color`, and its alpha value #: is the alpha value of self.line_color multiplied by self.alpha. - effective_line_color = Property(Tuple, depends_on=['line_color', 'alpha']) + effective_line_color = Property(Tuple, depends_on=["line_color", "alpha"]) #: The RGBA tuple for rendering the fill. It is always a tuple of length #: 4. It has the same RGB values as :attr:`fill_color`, and its alpha #: value is the alpha value of self.fill_color multiplied by self.alpha. - effective_fill_color = Property(Tuple, depends_on=['fill_color', 'alpha']) + effective_fill_color = Property(Tuple, depends_on=["fill_color", "alpha"]) #: Overall alpha value of the image. Ranges from 0.0 for transparent to 1.0 alpha = Range(0.0, 1.0, 1.0, requires_redraw=True) - - #use_draw_order = False + # use_draw_order = False # Convenience properties that correspond to either index_mapper or # value_mapper, depending on the orientation of the plot. @@ -113,10 +123,9 @@ class BarPlot(AbstractPlotRenderer): #: Convenience property for accessing the value data range. value_range = Property - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Indicates whether or not the data cache is valid _cache_valid = Bool(False) @@ -127,15 +136,14 @@ class BarPlot(AbstractPlotRenderer): # this is an Nx3 array of (bar_center, start, end). _cached_data_pts = Any - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractPlotRenderer interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, *args, **kw): # These Traits depend on others, so we'll defer setting them until # after the HasTraits initialization has been completed. - later_list = ['index_direction', 'value_direction'] + later_list = ["index_direction", "value_direction"] postponed = {} for name in later_list: if name in kw: @@ -146,9 +154,8 @@ def __init__(self, *args, **kw): # Set any keyword Traits that were postponed. self.trait_set(**postponed) - def map_screen(self, data_array): - """ Maps an array of data points into screen space and returns it as + """Maps an array of data points into screen space and returns it as an array. Implements the AbstractPlotRenderer interface. @@ -161,12 +168,12 @@ def map_screen(self, data_array): sy = self.value_mapper.map_screen(y_ary) if self.orientation == "h": - return transpose(array((sx,sy))) + return transpose(array((sx, sy))) else: - return transpose(array((sy,sx))) + return transpose(array((sy, sx))) def map_data(self, screen_pt): - """ Maps a screen space point into the "index" space of the plot. + """Maps a screen space point into the "index" space of the plot. Implements the AbstractPlotRenderer interface. """ @@ -176,15 +183,18 @@ def map_data(self, screen_pt): screen_coord = screen_pt[1] return self.index_mapper.map_data(screen_coord) - def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, - index_only=False): - """ Maps a screen space point to an index into the plot's index array(s). + def map_index( + self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=False + ): + """Maps a screen space point to an index into the plot's index array(s). Implements the AbstractPlotRenderer interface. """ data_pt = self.map_data(screen_pt) - if ((data_pt < self.index_mapper.range.low) or \ - (data_pt > self.index_mapper.range.high)) and outside_returns_none: + if ( + (data_pt < self.index_mapper.range.low) + or (data_pt > self.index_mapper.range.high) + ) and outside_returns_none: return None index_data = self.index.get_data() value_data = self.value.get_data() @@ -200,24 +210,26 @@ def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, x = index_data[ndx] y = value_data[ndx] - result = self.map_screen(array([[x,y]])) + result = self.map_screen(array([[x, y]])) if result is None: return None sx, sy = result[0] - if index_only and ((screen_pt[0]-sx) < threshold): + if index_only and ((screen_pt[0] - sx) < threshold): return ndx - elif ((screen_pt[0]-sx)**2 + (screen_pt[1]-sy)**2 < threshold*threshold): + elif (screen_pt[0] - sx) ** 2 + ( + screen_pt[1] - sy + ) ** 2 < threshold * threshold: return ndx else: return None - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # PlotComponent interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _gather_points(self): - """ Collects data points that are within the range of the plot, and + """Collects data points that are within the range of the plot, and caches them in **_cached_data_pts**. """ index, index_mask = self.index.get_data_mask() @@ -229,7 +241,8 @@ def _gather_points(self): if len(index) == 0 or len(value) == 0 or len(index) != len(value): logger.warning( "Chaco: using empty dataset; index_len=%d, value_len=%d." - % (len(index), len(value))) + % (len(index), len(value)) + ) self._cached_data_pts = array([]) self._cache_valid = True return @@ -237,10 +250,10 @@ def _gather_points(self): # TODO: Until we code up a better handling of value-based culling that # takes into account starting_value and dataspace bar widths, just use # the index culling for now. -# value_range_mask = self.value_mapper.range.mask_data(value) -# nan_mask = invert(isnan(index_mask)) & invert(isnan(value_mask)) -# point_mask = index_mask & value_mask & nan_mask & \ -# index_range_mask & value_range_mask + # value_range_mask = self.value_mapper.range.mask_data(value) + # nan_mask = invert(isnan(index_mask)) & invert(isnan(value_mask)) + # point_mask = index_mask & value_mask & nan_mask & \ + # index_range_mask & value_range_mask index_range_mask = self.index_mapper.range.mask_data(index) nan_mask = invert(isnan(index_mask)) @@ -253,8 +266,9 @@ def _gather_points(self): if self.bar_width_type == "data": half_width = self.bar_width / 2.0 - points = column_stack((index-half_width, index+half_width, - starting_values, value)) + points = column_stack( + (index - half_width, index + half_width, starting_values, value) + ) else: points = column_stack((index, starting_values, value)) self._cached_data_pts = compress(point_mask, points, axis=0) @@ -262,8 +276,7 @@ def _gather_points(self): self._cache_valid = True def _draw_plot(self, gc, view_bounds=None, mode="normal"): - """ Draws the 'plot' layer. - """ + """Draws the 'plot' layer.""" if not self._cache_valid: self._gather_points() @@ -281,22 +294,21 @@ def _draw_plot(self, gc, view_bounds=None, mode="normal"): if self.bar_width_type == "data": # map the bar start and stop locations into screen space - lower_left_pts = self.map_screen(data[:,(0,2)]) - upper_right_pts = self.map_screen(data[:,(1,3)]) + lower_left_pts = self.map_screen(data[:, (0, 2)]) + upper_right_pts = self.map_screen(data[:, (1, 3)]) else: half_width = self.bar_width / 2.0 # map the bar centers into screen space and then compute the bar # start and end positions - lower_left_pts = self.map_screen(data[:,(0,1)]) - upper_right_pts = self.map_screen(data[:,(0,2)]) - lower_left_pts[:,0] -= half_width - upper_right_pts[:,0] += half_width + lower_left_pts = self.map_screen(data[:, (0, 1)]) + upper_right_pts = self.map_screen(data[:, (0, 2)]) + lower_left_pts[:, 0] -= half_width + upper_right_pts[:, 0] += half_width bounds = upper_right_pts - lower_left_pts gc.rects(column_stack((lower_left_pts, bounds))) gc.draw_path() - def _draw_default_axes(self, gc): if not self.origin_axis_visible: return @@ -310,28 +322,28 @@ def _draw_default_axes(self, gc): if (range.low < 0) and (range.high > 0): if range == self.index_mapper.range: dual = self.value_mapper.range - data_pts = array([[0.0,dual.low], [0.0, dual.high]]) + data_pts = array([[0.0, dual.low], [0.0, dual.high]]) else: dual = self.index_mapper.range - data_pts = array([[dual.low,0.0], [dual.high,0.0]]) - start,end = self.map_screen(data_pts) - gc.move_to(int(start[0])+0.5, int(start[1])+0.5) - gc.line_to(int(end[0])+0.5, int(end[1])+0.5) + data_pts = array([[dual.low, 0.0], [dual.high, 0.0]]) + start, end = self.map_screen(data_pts) + gc.move_to(int(start[0]) + 0.5, int(start[1]) + 0.5) + gc.line_to(int(end[0]) + 0.5, int(end[1]) + 0.5) gc.stroke_path() def _render_icon(self, gc, x, y, width, height): with gc: gc.set_fill_color(self.effective_fill_color) gc.set_stroke_color(self.effective_line_color) - gc.rect(x+width/4, y+height/4, width/2, height/2) + gc.rect(x + width / 4, y + height / 4, width / 2, height / 2) gc.draw_path(FILL_STROKE) def _post_load(self): super(BarPlot, self)._post_load() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Properties - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_index_range(self): return self.index_mapper.range @@ -369,12 +381,12 @@ def _get_y_direction(self): else: return self.index_direction - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - these are mostly copied from BaseXYPlot - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _update_mappers(self): - """ Updates the index and value mappers. Called by trait change handlers + """Updates the index and value mappers. Called by trait change handlers for various traits. """ x_mapper = self.index_mapper @@ -392,7 +404,7 @@ def _update_mappers(self): y2 = self.y2 if x_mapper is not None: - if x_dir =="normal": + if x_dir == "normal": x_mapper.low_pos = x x_mapper.high_pos = x2 else: @@ -478,9 +490,9 @@ def _bar_width_type_changed(self): self.invalidate_draw() self.request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property getters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @cached_property def _get_effective_line_color(self): diff --git a/chaco/base.py b/chaco/base.py index 1328b8f76..5c3350aa2 100644 --- a/chaco/base.py +++ b/chaco/base.py @@ -7,17 +7,31 @@ # Major library imports from numpy import ( - array, argsort, concatenate, cos, diff, dot, dtype, empty, float32, - isfinite, nonzero, pi, searchsorted, seterr, sin, int8 + array, + argsort, + concatenate, + cos, + diff, + dot, + dtype, + empty, + float32, + isfinite, + nonzero, + pi, + searchsorted, + seterr, + sin, + int8, ) # Enthought library imports from traits.api import Enum, ArrayOrNone -delta = {'ascending': 1, 'descending': -1, 'flat': 0} +delta = {"ascending": 1, "descending": -1, "flat": 0} -rgba_dtype = dtype([('r', float32), ('g', float32), ('b', float32), ('a', float32)]) -point_dtype = dtype([('x', float), ('y', float)]) +rgba_dtype = dtype([("r", float32), ("g", float32), ("b", float32), ("a", float32)]) +point_dtype = dtype([("x", float), ("y", float)]) # Dimensions @@ -42,32 +56,33 @@ SortOrderTrait = Enum("ascending", "descending", "none") -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- # Utility functions -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- + def poly_point(center, r, degrees): x = r * cos(degrees) + center[0] y = r * sin(degrees) + center[1] - return x,y + return x, y def n_gon(center, r, nsides, rot_degrees=0): - """ Generates the points of a regular polygon with specified center, + """Generates the points of a regular polygon with specified center, radius, and number of sides. By default the rightmost point of the polygon is (*r*,0) but a rotation about the center may be specified with *rot_degrees*. """ if nsides < 3: - raise ValueError('Must have at least 3 sides in a polygon') + raise ValueError("Must have at least 3 sides in a polygon") rotation = radians(rot_degrees) theta = (pi * 2) / nsides - return [poly_point(center, r, i*theta+rotation) for i in range(nsides)] + return [poly_point(center, r, i * theta + rotation) for i in range(nsides)] def bin_search(values, value, ascending): - """ Performs a binary search of a sorted array for a specified value. + """Performs a binary search of a sorted array for a specified value. Parameters ---------- @@ -93,12 +108,12 @@ def bin_search(values, value, ascending): if ascending > 0: if (value < values[0]) or (value > values[-1]): return -1 - index = searchsorted(values, value, 'right') - 1 + index = searchsorted(values, value, "right") - 1 else: if (value < values[-1]) or (value > values[0]): return -1 ascending_values = values[::-1] - index = len(values) - searchsorted(ascending_values, value, 'left') - 1 + index = len(values) - searchsorted(ascending_values, value, "left") - 1 return index @@ -132,7 +147,6 @@ def reverse_map_1d(data, pt, sort_order, floor_only=False): if ndx == -1: raise IndexError("value outside array data range") - # Now round the index to the closest matching index. Do this # by determining the width (in value space) of each cell and # figuring out which side of the midpoint pt falls into. Since @@ -143,9 +157,10 @@ def reverse_map_1d(data, pt, sort_order, floor_only=False): if ndx < last: if floor_only: return ndx - delta = 0.5 * (data[ndx+1] - data[ndx]) - if ((sort_order == "ascending") and (pt > data[ndx] + delta)) or \ - ((sort_order == "descending") and (pt < data[ndx] + delta)): + delta = 0.5 * (data[ndx + 1] - data[ndx]) + if ((sort_order == "ascending") and (pt > data[ndx] + delta)) or ( + (sort_order == "descending") and (pt < data[ndx] + delta) + ): return ndx + 1 else: return ndx @@ -155,17 +170,19 @@ def reverse_map_1d(data, pt, sort_order, floor_only=False): # if we hit the last point exactly we still really want the index # of the previous point if floor_only: - return last-1 + return last - 1 # If pt happened to match the value of data[last] exactly, # we just return it here. return last + # These are taken from Chaco 1.0's datamapper and subdivision_cells modules. # TODO: Write unit tests for these! def right_shift(ary, newval): "Returns a right-shifted version of *ary* with *newval* inserted on the left." return concatenate([[newval], ary[:-1]]) + def left_shift(ary, newval): "Returns a left-shifted version of *ary* with *newval* inserted on the right." return concatenate([ary[1:], [newval]]) @@ -184,7 +201,7 @@ def sort_points(points, index=0): return points[argsort(points[:, index]), :] -def find_runs(int_array, order='ascending'): +def find_runs(int_array, order="ascending"): """ find_runs(int_array, order=<'ascending'|'flat'|'descending'>) -> list_of_int_arrays @@ -201,10 +218,10 @@ def find_runs(int_array, order='ascending'): return [ [0,0,0], [1,1,1,1], [0,0,0,0] ] """ ranges = arg_find_runs(int_array, order) - return [int_array[i:j] for (i,j) in ranges] + return [int_array[i:j] for (i, j) in ranges] -def arg_find_runs(int_array, order='ascending'): +def arg_find_runs(int_array, order="ascending"): """ Like find_runs(), but returns a list of tuples indicating the start and end indices of runs in the input *int_array*. @@ -225,7 +242,7 @@ def arg_true_runs(bool_array): """ Find runs where array is True """ if len(bool_array) == 0: return [] - runs = arg_find_runs(bool_array.view(int8), 'flat') + runs = arg_find_runs(bool_array.view(int8), "flat") # runs have to alternate true and false if bool_array[0]: # even runs are true @@ -238,20 +255,19 @@ def arg_true_runs(bool_array): return [] - def point_line_distance(pt, p1, p2): - """ Returns the perpendicular distance between *pt* and the line segment + """Returns the perpendicular distance between *pt* and the line segment between the points *p1* and *p2*. """ v1 = array((pt[0] - p1[0], pt[1] - p1[1])) v2 = array((p2[0] - p1[0], p2[1] - p1[1])) diff = v1 - dot(v1, v2) / dot(v2, v2) * v2 - return sqrt(dot(diff,diff)) + return sqrt(dot(diff, diff)) def intersect_range(x, low, high, mask=None): - """ Discard 1D intervals outside of range, with optional mask + """Discard 1D intervals outside of range, with optional mask This is an optimized routine for detecting which points are endpoints of visible segments in a 1D polyline. An optional mask can be provided for @@ -285,7 +301,7 @@ def intersect_range(x, low, high, mask=None): mask = isfinite(x) # find relationships to range bounds - old_err = seterr(invalid='ignore') + old_err = seterr(invalid="ignore") try: not_low_x = (x >= low) & mask not_high_x = (x <= high) & mask @@ -293,12 +309,13 @@ def intersect_range(x, low, high, mask=None): seterr(**old_err) # a point is in if it is not low and not high - result = (not_low_x & not_high_x) + result = not_low_x & not_high_x if x.shape[0] >= 2: # interval intersects range if one end not low and other end not high - interval_mask = ((not_low_x[:-1] & not_high_x[1:]) | - (not_high_x[:-1] & not_low_x[1:])) + interval_mask = (not_low_x[:-1] & not_high_x[1:]) | ( + not_high_x[:-1] & not_low_x[1:] + ) # point is also in if at least one of its interval is in result[1:-1] |= interval_mask[:-1] | interval_mask[1:] diff --git a/chaco/base_1d_mapper.py b/chaco/base_1d_mapper.py index 88b639ef1..7b017a66f 100644 --- a/chaco/base_1d_mapper.py +++ b/chaco/base_1d_mapper.py @@ -9,7 +9,7 @@ class Base1DMapper(AbstractMapper): - """ Defines an abstract mapping from a 1-D region in input space to a 1-D + """Defines an abstract mapping from a 1-D region in input space to a 1-D region in output space. """ @@ -20,7 +20,7 @@ class Base1DMapper(AbstractMapper): low_pos = Float(0.0) #: The screen space position of the upper bound of the data space. - high_pos = Float(1.0) + high_pos = Float(1.0) #: Convenience property to get low and high positions in one structure. #: Must be a tuple (low_pos, high_pos). @@ -44,9 +44,9 @@ class Base1DMapper(AbstractMapper): _low_bound_initialized = Bool(False) _high_bound_initialized = Bool(False) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _low_pos_changed(self, old, new): self._cache_valid = False @@ -80,11 +80,11 @@ def _get_screen_bounds(self): return (self.low_pos, self.high_pos) def _get_sign(self): - delta_screen = (self.high_pos - self.low_pos) - delta_data = (self.range.high-self.range.low) + delta_screen = self.high_pos - self.low_pos + delta_data = self.range.high - self.range.low if delta_screen == 0 or delta_data == 0: return 0 - elif delta_screen/float(delta_data) < 0: + elif delta_screen / float(delta_data) < 0: return -1 else: return 1 @@ -94,21 +94,22 @@ def _set_screen_bounds(self, new_bounds): return if not self.stretch_data: self._adjust_range((self.low_pos, self.high_pos), new_bounds) - self.trait_setq(low_pos = new_bounds[0]) - self.trait_setq(high_pos = new_bounds[1]) + self.trait_setq(low_pos=new_bounds[0]) + self.trait_setq(high_pos=new_bounds[1]) self._cache_valid = False self._low_bound_initialized = True self._high_bound_initialized = True self.updated = True def _adjust_range(self, old_bounds, new_bounds): - initialized = self._low_bound_initialized and \ - self._high_bound_initialized + initialized = self._low_bound_initialized and self._high_bound_initialized if self.range is not None and initialized: rangelow = self.range.low rangehigh = self.range.high d_data = rangehigh - rangelow old_d_screen = old_bounds[1] - old_bounds[0] if d_data != 0 and old_d_screen != 0: - new_data_extent = d_data / old_d_screen * (new_bounds[1] - new_bounds[0]) + new_data_extent = ( + d_data / old_d_screen * (new_bounds[1] - new_bounds[0]) + ) self.range.set_bounds(rangelow, rangelow + new_data_extent) diff --git a/chaco/base_1d_plot.py b/chaco/base_1d_plot.py index 92557e5e4..cb05e113d 100644 --- a/chaco/base_1d_plot.py +++ b/chaco/base_1d_plot.py @@ -5,9 +5,7 @@ from numpy import argsort, asarray # Enthought library imports -from traits.api import ( - Any, Bool, Enum, Instance, Property, cached_property, observe -) +from traits.api import Any, Bool, Enum, Instance, Property, cached_property, observe # local imports from .abstract_plot_renderer import AbstractPlotRenderer @@ -17,7 +15,7 @@ class Base1DPlot(AbstractPlotRenderer): - """ Base class for one-dimensional plots + """Base class for one-dimensional plots This class provides a base for plots such as jitter plots, color bars, single-axis scatter plots, and geophysical horizon and tops plots. @@ -35,27 +33,27 @@ class Base1DPlot(AbstractPlotRenderer): #: Corresponds to either **index_mapper** or None, depending on #: the orientation of the plot. - x_mapper = Property(depends_on=['orientation', 'index_mapper']) + x_mapper = Property(depends_on=["orientation", "index_mapper"]) #: Corresponds to either **index_mapper** or None, depending on #: the orientation of the plot. - y_mapper = Property(depends_on=['orientation', 'index_mapper']) + y_mapper = Property(depends_on=["orientation", "index_mapper"]) #: The orientation of the index axis. - orientation = Enum('v', 'h') + orientation = Enum("v", "h") #: Should the plot go left-to-right or bottom-to-top (normal) or the reverse? - direction = Enum('normal', 'flipped') + direction = Enum("normal", "flipped") #: Faux origin for the axes and other objects to look at origin = Property( - Enum('bottom left', 'top left', 'bottom right', 'top right'), - depends_on=['orientation', 'direction'] + Enum("bottom left", "top left", "bottom right", "top right"), + depends_on=["orientation", "direction"], ) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: flag whether the data cache is valid _cache_valid = Bool(False) @@ -75,12 +73,12 @@ class Base1DPlot(AbstractPlotRenderer): #: cache holding the screen coordinates of the index values _cached_screen_pts = Any() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractPlotRenderer interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def map_screen(self, data_array): - """ Maps a 1D array of data points into screen space and returns it as + """Maps a 1D array of data points into screen space and returns it as a 1D array. Parameters @@ -109,7 +107,7 @@ def map_screen(self, data_array): return asarray(self.index_mapper.map_screen(data_array)) def map_data(self, screen_pts): - """ Maps 2D screen space points into the 1D index space of the plot. + """Maps 2D screen space points into the 1D index space of the plot. Parameters ---------- @@ -131,9 +129,10 @@ def map_data(self, screen_pts): else: return asarray(self.index_mapper.map_data(x)) - def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, - index_only=True): - """ Maps a screen space point to an index into the plot's index array. + def map_index( + self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=True + ): + """Maps a screen space point to an index into the plot's index array. Parameters ---------- @@ -166,9 +165,10 @@ def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, """ data_pt = self.map_data(screen_pt) - if ((data_pt < self.index_mapper.range.low) or \ - (data_pt > self.index_mapper.range.high)) and \ - outside_returns_none: + if ( + (data_pt < self.index_mapper.range.low) + or (data_pt > self.index_mapper.range.high) + ) and outside_returns_none: return None if self._cached_data_pts_sorted is None: @@ -196,7 +196,7 @@ def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, screen_points = self._cached_screen_pts x = screen_points[orig_ndx] - if self.orientation == 'v': + if self.orientation == "v": x0 = screen_pt[1] else: x0 = screen_pt[0] @@ -206,9 +206,9 @@ def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, else: return None - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _compute_screen_coord(self): """ Compute the screen coordinates of the index values """ @@ -240,8 +240,7 @@ def _gather_points(self): self._screen_cached_valid = False def _update_mappers(self): - """ Update the mapper when the bounds, orientation or direction change - """ + """Update the mapper when the bounds, orientation or direction change""" mapper = self.index_mapper if mapper is None: return @@ -251,24 +250,24 @@ def _update_mappers(self): y = self.y y2 = self.y2 - if self.orientation == 'h': - if self.direction == 'normal': + if self.orientation == "h": + if self.direction == "normal": mapper.screen_bounds = (x, x2) - elif self.direction == 'flipped': + elif self.direction == "flipped": mapper.screen_bounds = (x2, x) - elif self.orientation == 'v': - if self.direction == 'normal': + elif self.orientation == "v": + if self.direction == "normal": mapper.screen_bounds = (y, y2) - elif self.direction == 'flipped': + elif self.direction == "flipped": mapper.screen_bounds = (y2, y) self.invalidate_draw() self._cache_valid = False self._screen_cache_valid = False - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property setters and getters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_index_range(self): return self.index_mapper.range @@ -292,20 +291,20 @@ def _get_y_mapper(self): @cached_property def _get_origin(self): - if self.orientation == 'h': - if self.direction == 'normal': - return 'bottom left' + if self.orientation == "h": + if self.direction == "normal": + return "bottom left" else: - return 'bottom right' + return "bottom right" else: - if self.direction == 'normal': - return 'bottom left' + if self.direction == "normal": + return "bottom left" else: - return 'top left' + return "top left" - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @observe("index.data_changed") def _invalidate(self, event): diff --git a/chaco/base_2d_plot.py b/chaco/base_2d_plot.py index e12b9dab6..2cd9159f0 100644 --- a/chaco/base_2d_plot.py +++ b/chaco/base_2d_plot.py @@ -16,11 +16,11 @@ class Base2DPlot(AbstractPlotRenderer): - """ Base class for 2-D plots. - """ - #------------------------------------------------------------------------ + """Base class for 2-D plots.""" + + # ------------------------------------------------------------------------ # Data-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The data source to use for the index coordinate. index = Instance(GridDataSource) @@ -75,9 +75,9 @@ class Base2DPlot(AbstractPlotRenderer): #: is done in this class). value_data_changed = Event - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, **kwargs): # Handling the setting/initialization of these traits manually because @@ -99,12 +99,12 @@ def __init__(self, **kwargs): if self.resizable == "": self._update_mappers() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractPlotRenderer interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def map_screen(self, data_pts): - """ Maps an array of data points into screen space and returns it as + """Maps an array of data points into screen space and returns it as an array. Implements the AbstractPlotRenderer interface. @@ -115,29 +115,32 @@ def map_screen(self, data_pts): return asarray(self.index_mapper.map_screen(data_pts)) def map_data(self, screen_pts): - """ Maps a screen space point into the "index" space of the plot. + """Maps a screen space point into the "index" space of the plot. Implements the AbstractPlotRenderer interface. """ return self.index_mapper.map_data(screen_pts) - def map_index(self, screen_pt, threshold=2.0, - outside_returns_none=True, index_only=False): - """ Maps a screen space point to an index into the plot's index arrays. + def map_index( + self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=False + ): + """Maps a screen space point to an index into the plot's index arrays. Implements the AbstractPlotRenderer interface. The *index_only* parameter is ignored because the index is intrinsically 2-D. """ - if self.orientation == 'h': - x_pt,y_pt = self.map_data([screen_pt])[0] + if self.orientation == "h": + x_pt, y_pt = self.map_data([screen_pt])[0] else: - x_pt,y_pt = self.map_data([(screen_pt[1],screen_pt[0])])[0] - - if ((x_pt < self.index_mapper.range.low[0]) or - (x_pt > self.index_mapper.range.high[0]) or - (y_pt < self.index_mapper.range.low[1]) or - (y_pt > self.index_mapper.range.high[1])) and outside_returns_none: + x_pt, y_pt = self.map_data([(screen_pt[1], screen_pt[0])])[0] + + if ( + (x_pt < self.index_mapper.range.low[0]) + or (x_pt > self.index_mapper.range.high[0]) + or (y_pt < self.index_mapper.range.low[1]) + or (y_pt > self.index_mapper.range.high[1]) + ) and outside_returns_none: return None, None x_index_data, y_index_data = self.index.get_data() @@ -149,28 +152,30 @@ def map_index(self, screen_pt, threshold=2.0, x_data = x_index_data.get_data() y_data = y_index_data.get_data() try: - x_ndx = reverse_map_1d(x_data, x_pt, self.index.sort_order[0], - floor_only=True) + x_ndx = reverse_map_1d( + x_data, x_pt, self.index.sort_order[0], floor_only=True + ) except IndexError as e: if outside_returns_none: return None, None # x index if x_pt < x_data[0]: - x_ndx = 0 + x_ndx = 0 else: x_ndx = len(x_data) - 1 try: - y_ndx = reverse_map_1d(y_data, y_pt, self.index.sort_order[1], - floor_only=True) + y_ndx = reverse_map_1d( + y_data, y_pt, self.index.sort_order[1], floor_only=True + ) except IndexError as e: if outside_returns_none: return None, None # y index if y_pt < y_data[0]: - y_ndx = 0 + y_ndx = 0 else: y_ndx = len(y_data) - 1 @@ -182,35 +187,34 @@ def map_index(self, screen_pt, threshold=2.0, if isnan(x) or isnan(y): return None, None - sx, sy = self.map_screen([(x,y)])[0] - if ((screen_pt[0]-sx)**2 + (screen_pt[1]-sy)**2 < threshold**2): + sx, sy = self.map_screen([(x, y)])[0] + if (screen_pt[0] - sx) ** 2 + (screen_pt[1] - sy) ** 2 < threshold ** 2: return x_ndx, y_ndx else: return None, None - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # PlotComponent interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _draw_image(self, gc, view_bounds=None, mode="normal"): - """ Handler for drawing the 'image' layer. + """Handler for drawing the 'image' layer. Used by the PlotComponent interface. """ self._render(gc) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Abstract methods that subclasses must implement - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _render(self, gc, points): - """ Abstract method for drawing the plot. - """ + """Abstract method for drawing the plot.""" raise NotImplementedError - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Properties - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_index_range(self): return self.index_mapper.range @@ -220,30 +224,29 @@ def _set_index_range(self, val): def _get_labels(self): labels = [] - for obj in self.underlays+self.overlays: + for obj in self.underlays + self.overlays: if isinstance(obj, PlotLabel): labels.append(obj) return labels def _get_x_mapper(self): - if self.orientation == 'h': + if self.orientation == "h": return self.index_mapper._xmapper else: return self.index_mapper._ymapper def _get_y_mapper(self): - if self.orientation == 'h': + if self.orientation == "h": return self.index_mapper._ymapper else: return self.index_mapper._xmapper - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _update_index_mapper(self, event=None): - """ Updates the index mapper. + """Updates the index mapper. Called by various trait change handlers. """ @@ -268,7 +271,7 @@ def _update_index_mapper(self, event=None): y_high = y if self.index_mapper is not None: - if self.orientation == 'h': + if self.orientation == "h": self.index_mapper.screen_bounds = (x_low, x_high, y_low, y_high) else: self.index_mapper.screen_bounds = (y_low, y_high, x_low, x_high) @@ -276,7 +279,7 @@ def _update_index_mapper(self, event=None): self.invalidate_draw() def _update_index_data(self, event=None): - """ Updates the index data. + """Updates the index data. Called by various trait change handlers. """ @@ -284,17 +287,16 @@ def _update_index_data(self, event=None): self.invalidate_draw() def _update_value_data(self, event=None): - """ Updates the value data. + """Updates the value data. Called by various trait change handlers. """ self.value_data_changed = True self.invalidate_draw() - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _bounds_changed(self, old, new): super(Base2DPlot, self)._bounds_changed(old, new) diff --git a/chaco/base_candle_plot.py b/chaco/base_candle_plot.py index 2e01be8fe..f3816c646 100644 --- a/chaco/base_candle_plot.py +++ b/chaco/base_candle_plot.py @@ -10,12 +10,15 @@ # TODO: allow to set the width of the bar + def Alias(name): - return Property(lambda obj: getattr(obj, name), - lambda obj, val: setattr(obj, name, val)) + return Property( + lambda obj: getattr(obj, name), lambda obj, val: setattr(obj, name, val) + ) + class BaseCandlePlot(BaseXYPlot): - """ Represents the base class for candle- and bar-type plots that are + """Represents the base class for candle- and bar-type plots that are multi-valued at each index point, and optionally have an extent in the index dimension. @@ -24,9 +27,9 @@ class BaseCandlePlot(BaseXYPlot): clipping of data is up to individual subclasses. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Appearance traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The fill color of the marker. color = ColorTrait("black") @@ -64,27 +67,27 @@ class BaseCandlePlot(BaseXYPlot): # Whether or not to draw bars at the min and max extents of the error bar end_cap = Bool(True) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Override the base class definition of this because we store a list of # arrays and not a single array. _cached_data_pts = List() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # BaseXYPlot interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def get_screen_points(self): # Override the BaseXYPlot implementation so that this is just # a pass-through, in case anyone calls it. pass - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Protected methods (subclasses should be able to use these directly # or wrap them) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _render(self, gc, right, left, min, bar_min, center, bar_max, max): stack = column_stack @@ -112,15 +115,21 @@ def _render(self, gc, right, left, min, bar_min, center, bar_max, max): gc.set_line_width(stem_width) if min is None: - gc.line_set(stack((bar_vert_center, bar_max)), stack((bar_vert_center, max))) + gc.line_set( + stack((bar_vert_center, bar_max)), stack((bar_vert_center, max)) + ) if self.end_cap: gc.line_set(stack((left, max)), stack((right, max))) elif max is None: - gc.line_set(stack((bar_vert_center, min)), stack((bar_vert_center, bar_min))) + gc.line_set( + stack((bar_vert_center, min)), stack((bar_vert_center, bar_min)) + ) if self.end_cap: gc.line_set(stack((left, min)), stack((right, min))) else: - gc.line_set(stack((bar_vert_center, min)), stack((bar_vert_center, max))) + gc.line_set( + stack((bar_vert_center, min)), stack((bar_vert_center, max)) + ) if self.end_cap: gc.line_set(stack((left, max)), stack((right, max))) gc.line_set(stack((left, min)), stack((right, min))) @@ -157,8 +166,13 @@ def _render_icon(self, gc, x, y, width, height): bar_min = array([y + height / 3]) bar_max = array([y + height - (height / 3)]) center = array([y + (height / 2)]) - self._render(gc, array([x+width/4]), array([x+3*width/4]), min, bar_min, center, bar_max, max) - - - - + self._render( + gc, + array([x + width / 4]), + array([x + 3 * width / 4]), + min, + bar_min, + center, + bar_max, + max, + ) diff --git a/chaco/base_contour_plot.py b/chaco/base_contour_plot.py index 22d384e85..a3a96609b 100644 --- a/chaco/base_contour_plot.py +++ b/chaco/base_contour_plot.py @@ -2,8 +2,7 @@ # Enthought library imports from enable.api import ColorTrait -from traits.api import Bool, Instance, Int, List, Property, \ - Range, Str, Trait, Tuple +from traits.api import Bool, Instance, Int, List, Property, Range, Str, Trait, Tuple # Local relative imports from .base_2d_plot import Base2DPlot @@ -11,13 +10,13 @@ class BaseContourPlot(Base2DPlot): - """ The base class for contour plots. Mostly manages configuration and + """The base class for contour plots. Mostly manages configuration and change events with colormap and contour parameters. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Data-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Defines the levels to contour. # ``levels`` can be either: a list of floating point numbers that define @@ -40,9 +39,9 @@ class BaseContourPlot(Base2DPlot): # A global alpha value to apply to all the contours alpha = Trait(1.0, Range(0.0, 1.0)) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Is the cached level data valid? _level_cache_valid = Bool(False) @@ -61,7 +60,6 @@ class BaseContourPlot(Base2DPlot): # a time.) _color_map_trait = ColorTrait - def __init__(self, *args, **kwargs): super(BaseContourPlot, self).__init__(*args, **kwargs) if self.color_mapper: @@ -81,7 +79,7 @@ def _update_levels(self): self._colors_cache_valid = False def _update_colors(self, numcolors=None): - """ Update the colors cache using our color mapper and based + """Update the colors cache using our color mapper and based on our number of levels. The **mode** parameter accounts for fenceposting: - If **mode** is "poly", then the number of colors to generate is 1 less than the number of levels @@ -104,7 +102,7 @@ def _update_colors(self, numcolors=None): # If we are given a colormap, use it to map all the levels to colors elif isinstance(colors, ColorMapper): - self._colors = [] + self._colors = [] mapped_colors = self.color_mapper.map_screen(array(self._levels)) for i in range(numcolors): self._color_map_trait = tuple(mapped_colors[i]) @@ -115,8 +113,9 @@ def _update_colors(self, numcolors=None): # a color; otherwise, this is interpreted as a list of items to # be converted via self._color_map_trait. else: - if len(colors) in (3,4) and \ - (isscalar(colors[0]) and issubsctype(type(colors[0]), number)): + if len(colors) in (3, 4) and ( + isscalar(colors[0]) and issubsctype(type(colors[0]), number) + ): self._color_map_trait = colors self._colors = [self._color_map_trait_] * numcolors else: @@ -124,14 +123,14 @@ def _update_colors(self, numcolors=None): # repeat colors from the beginning of the list as needed self._colors = [] for i in range(len(self._levels)): - self._color_map_trait = colors[i%len(colors)] + self._color_map_trait = colors[i % len(colors)] self._colors.append(self._color_map_trait_) self._colors_cache_valid = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _index_data_changed_fired(self): # If the index data has changed, the reset the levels cache (which @@ -164,9 +163,9 @@ def _colors_changed(self): self._update_colors() self.invalidate_and_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait properties - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_color_mapper(self): if isinstance(self.colors, ColorMapper): diff --git a/chaco/base_data_range.py b/chaco/base_data_range.py index 242d4ba97..e94674476 100644 --- a/chaco/base_data_range.py +++ b/chaco/base_data_range.py @@ -7,14 +7,14 @@ class BaseDataRange(AbstractDataRange): - """ Ranges represent sub-regions of data space. + """Ranges represent sub-regions of data space. They support "autoscaling" by querying their associated data sources. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, *datasources, **kwtraits): super(AbstractDataRange, self).__init__(**kwtraits) @@ -32,6 +32,3 @@ def remove(self, *datasources): for datasource in datasources: if datasource in self.sources: self.sources.remove(datasource) - - - diff --git a/chaco/base_plot_container.py b/chaco/base_plot_container.py index f4ffa6806..f26f605c1 100644 --- a/chaco/base_plot_container.py +++ b/chaco/base_plot_container.py @@ -38,9 +38,9 @@ class BasePlotContainer(Container): draw_order = Instance(list, args=(DEFAULT_DRAWING_ORDER,)) draw_layer = Str("plot") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Deprecated traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Deprecated flag to indicate that a component needed to do old-style #: drawing. Unused by any recent Chaco component. @@ -50,19 +50,26 @@ class BasePlotContainer(Container): plot_components = Property def _get_plot_components(self): - warnings.warn("Use of plot_components attribute deprecated." \ - "Use components attribute instead.", DeprecationWarning) + warnings.warn( + "Use of plot_components attribute deprecated." + "Use components attribute instead.", + DeprecationWarning, + ) return self._components def _set_plot_components(self, new): - warnings.warn("Use of plot_components attribute deprecated." \ - "Use components attribute instead.", DeprecationWarning) + warnings.warn( + "Use of plot_components attribute deprecated." + "Use components attribute instead.", + DeprecationWarning, + ) self._components = new def _use_draw_order_changed(self, old, new): - """ Handler to catch the case when someone is trying to use the + """Handler to catch the case when someone is trying to use the old-style drawing mechanism, which is now unsupported. """ if new == False: - raise RuntimeError("The old-style drawing mechanism is no longer " \ - "supported in Chaco.") + raise RuntimeError( + "The old-style drawing mechanism is no longer " "supported in Chaco." + ) diff --git a/chaco/base_plot_frame.py b/chaco/base_plot_frame.py index 3ff21ae36..9e0f2b721 100644 --- a/chaco/base_plot_frame.py +++ b/chaco/base_plot_frame.py @@ -69,12 +69,12 @@ def get_slot(self, slotname): """ Returns the container in the named slot. """ return self._frame_slots.get(slotname, None) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # PlotComponent interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def draw(self, gc, view_bounds=None, mode="normal"): - """ Draws the plot frame. + """Draws the plot frame. Frames are the topmost Chaco component that knows about layout, and they are the start of the layout pipeline. When they are asked to draw, @@ -83,17 +83,17 @@ def draw(self, gc, view_bounds=None, mode="normal"): """ self.do_layout() - #if gc.window and gc.window.is_sizing: + # if gc.window and gc.window.is_sizing: if 0: with gc: gc.translate_ctm(*self.position) - #TODO: We are ignoring Container... + # TODO: We are ignoring Container... PlotComponent.draw(self, gc, view_bounds, "interactive") else: super(BasePlotFrame, self).draw(gc, view_bounds, mode) def do_layout(self, size=None, force=False): - """ Tells this frame to do layout at a given size. + """Tells this frame to do layout at a given size. Overrides PlotComponent. If this frame needs to fit components in at least one dimension, then it checks whether any of them need to do @@ -107,7 +107,7 @@ def do_layout(self, size=None, force=False): return PlotComponent.do_layout(self, size, force) def _draw(self, *args, **kw): - """ Draws the plot frame. + """Draws the plot frame. Overrides PlotComponent and Container, explicitly calling the PlotComponent version of _draw(). @@ -115,15 +115,15 @@ def _draw(self, *args, **kw): PlotComponent._draw(self, *args, **kw) def _dispatch_to_enable(self, event, suffix): - """ Calls Enable-level event handlers. + """Calls Enable-level event handlers. Overrides PlotComponent. """ Container.dispatch(self, event, suffix) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers, properties - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _bounds_changed(self, old, new): if self.container is not None: @@ -134,16 +134,17 @@ def _bounds_changed(self, old, new): def _bounds_items_changed(self, event): return self._bounds_changed(None, self.bounds) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __getattr__(self, name): if name in self.slot_names: return self._frame_slots[name] else: - raise AttributeError("'%s' object has no attribute '%s'" % \ - (self.__class__.__name__, name)) + raise AttributeError( + "'%s' object has no attribute '%s'" % (self.__class__.__name__, name) + ) def __setattr__(self, name, value): if name in self.slot_names: @@ -152,7 +153,7 @@ def __setattr__(self, name, value): super(BasePlotFrame, self).__setattr__(name, value) ### Persistence ########################################################### -# _pickles = ("_frame_slots", "_components", "fit_components", "fit_window") + # _pickles = ("_frame_slots", "_components", "fit_components", "fit_window") def post_load(self, path=None): super(BasePlotFrame, self).post_load(path) diff --git a/chaco/base_xy_plot.py b/chaco/base_xy_plot.py index 2f5fdb0df..5f9bc63c0 100644 --- a/chaco/base_xy_plot.py +++ b/chaco/base_xy_plot.py @@ -5,8 +5,7 @@ # Enthought library imports from enable.api import black_color_trait -from traits.api import Any, Array, Bool, Enum, Float, Instance, \ - Property, Range +from traits.api import Any, Array, Bool, Enum, Float, Instance, Property, Range # Local relative imports @@ -21,7 +20,7 @@ class BaseXYPlot(AbstractPlotRenderer): - """ Base class for simple X-vs-Y plots that consist of a single index + """Base class for simple X-vs-Y plots that consist of a single index data array and a single value data array. Subclasses handle the actual rendering, but this base class takes care of @@ -29,9 +28,9 @@ class BaseXYPlot(AbstractPlotRenderer): space changes, etc. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Data-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The data source to use for the index coordinate. index = Instance(ArrayDataSource) @@ -44,7 +43,6 @@ class BaseXYPlot(AbstractPlotRenderer): #: Screen mapper for value data value_mapper = Instance(AbstractMapper) - # Convenience properties that correspond to either index_mapper or # value_mapper, depending on the orientation of the plot. @@ -67,9 +65,9 @@ class BaseXYPlot(AbstractPlotRenderer): #: * 'point': Checks for adjacency to a marker or point. hittest_type = Enum("point", "line") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Appearance-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The orientation of the index axis. orientation = Enum("h", "v") @@ -77,9 +75,9 @@ class BaseXYPlot(AbstractPlotRenderer): #: Overall alpha value of the image. Ranges from 0.0 for transparent to 1.0 alpha = Range(0.0, 1.0, 1.0, requires_redraw=True) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Convenience readonly properties for common annotations - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Read-only property for horizontal grid. hgrid = Property @@ -92,10 +90,9 @@ class BaseXYPlot(AbstractPlotRenderer): #: Read-only property for labels. labels = Property - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Other public traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Does the plot use downsampling? #: This is not used right now. It needs an implementation of robust, fast @@ -119,9 +116,9 @@ class BaseXYPlot(AbstractPlotRenderer): #: Defines the origin axis visibility, for testing. origin_axis_visible = Bool(False) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Are the cache traits valid? If False, new ones need to be compute. _cache_valid = Bool(False) @@ -140,12 +137,12 @@ class BaseXYPlot(AbstractPlotRenderer): # Reference to a spatial subdivision acceleration structure. _subdivision = Any - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Abstract methods that subclasses must implement - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _render(self, gc, points): - """ Abstract method for rendering points. + """Abstract method for rendering points. Parameters ---------- @@ -157,21 +154,21 @@ def _render(self, gc, points): raise NotImplementedError def _gather_points(self): - """ Abstract method to collect data points that are within the range of + """Abstract method to collect data points that are within the range of the plot, and cache them. """ raise NotImplementedError def _downsample(self): - """ Abstract method that gives the renderer a chance to downsample in + """Abstract method that gives the renderer a chance to downsample in screen space. """ # By default, this just does a mapscreen and returns the result raise NotImplementedError - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Concrete methods below - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, **kwtraits): # Handling the setting/initialization of these traits manually because @@ -199,7 +196,7 @@ def __init__(self, **kwtraits): self._update_mappers() def hittest(self, screen_pt, threshold=7.0, return_distance=False): - """ Performs proximity testing between a given screen point and the + """Performs proximity testing between a given screen point and the plot. Parameters @@ -244,7 +241,7 @@ def hittest(self, screen_pt, threshold=7.0, return_distance=False): return None def get_closest_point(self, screen_pt, threshold=7.0): - """ Tests for proximity in screen-space. + """Tests for proximity in screen-space. This method checks only data points, not the line segments connecting them; to do the latter use get_closest_line() instead. @@ -267,12 +264,12 @@ def get_closest_point(self, screen_pt, threshold=7.0): if ndx is not None: x = self.x_mapper.map_screen(self.index.get_data()[ndx]) y = self.y_mapper.map_screen(self.value.get_data()[ndx]) - return (x, y, sqrt((x-screen_pt[0])**2 + (y-screen_pt[1])**2)) + return (x, y, sqrt((x - screen_pt[0]) ** 2 + (y - screen_pt[1]) ** 2)) else: return None def get_closest_line(self, screen_pt, threshold=7.0): - """ Tests for proximity in screen-space against lines connecting the + """Tests for proximity in screen-space against lines connecting the points in this plot's dataset. Parameters @@ -306,7 +303,7 @@ def get_closest_line(self, screen_pt, threshold=7.0): # even that we only have 1 point, just return that point. datalen = len(index_data) if datalen == 1: - dist = (x, y, sqrt((x-screen_pt[0])**2 + (y-screen_pt[1])**2)) + dist = (x, y, sqrt((x - screen_pt[0]) ** 2 + (y - screen_pt[1]) ** 2)) if (threshold == 0.0) or (dist <= threshold): return (x, y, x, y, dist) else: @@ -318,19 +315,18 @@ def get_closest_line(self, screen_pt, threshold=7.0): ndx2 = ndx - 1 x2 = self.x_mapper.map_screen(index_data[ndx2]) y2 = self.y_mapper.map_screen(value_data[ndx2]) - dist = point_line_distance(screen_pt, (x,y), (x2,y2)) + dist = point_line_distance(screen_pt, (x, y), (x2, y2)) if (threshold == 0.0) or (dist <= threshold): return (x, y, x2, y2, dist) else: return None - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractPlotRenderer interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def map_screen(self, data_array): - """ Maps an array of data points into screen space and returns it as + """Maps an array of data points into screen space and returns it as an array. Implements the AbstractPlotRenderer interface. @@ -344,12 +340,12 @@ def map_screen(self, data_array): sx = self.index_mapper.map_screen(x_ary) sy = self.value_mapper.map_screen(y_ary) if self.orientation == "h": - return transpose(array((sx,sy))) + return transpose(array((sx, sy))) else: - return transpose(array((sy,sx))) + return transpose(array((sy, sx))) def map_data(self, screen_pt, all_values=False): - """ Maps a screen space point into the "index" space of the plot. + """Maps a screen space point into the "index" space of the plot. Implements the AbstractPlotRenderer interface. @@ -357,17 +353,17 @@ def map_data(self, screen_pt, all_values=False): otherwise, it returns only the index values. """ x, y = screen_pt - if self.orientation == 'v': - x, y = y, x + if self.orientation == "v": + x, y = y, x if all_values: - return array((self.index_mapper.map_data(x), - self.value_mapper.map_data(y))) + return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) else: return self.index_mapper.map_data(x) - def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, - index_only=False): - """ Maps a screen space point to an index into the plot's index array(s). + def map_index( + self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=False + ): + """Maps a screen space point to an index into the plot's index array(s). Implements the AbstractPlotRenderer interface. @@ -392,8 +388,10 @@ def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, """ data_pt = self.map_data(screen_pt) - if ((data_pt < self.index_mapper.range.low) or - (data_pt > self.index_mapper.range.high)) and outside_returns_none: + if ( + (data_pt < self.index_mapper.range.low) + or (data_pt > self.index_mapper.range.high) + ) and outside_returns_none: return None index_data = self.index.get_data() value_data = self.value.get_data() @@ -428,12 +426,13 @@ def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, # map_screen. this makes it robust against differences in # the map_screen methods of logmapper and linearmapper # when passed a scalar - xy = array([[x,y]]) + xy = array([[x, y]]) sx, sy = self.map_screen(xy).T - if index_only and (threshold == 0.0 or screen_pt[0]-sx < threshold): + if index_only and (threshold == 0.0 or screen_pt[0] - sx < threshold): return ndx - elif ((screen_pt[0]-sx)**2 + (screen_pt[1]-sy)**2 - < threshold*threshold): + elif (screen_pt[0] - sx) ** 2 + ( + screen_pt[1] - sy + ) ** 2 < threshold * threshold: return ndx else: return None @@ -451,14 +450,12 @@ def get_screen_points(self): else: return self.map_screen(self._cached_data_pts) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # PlotComponent interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _draw_plot(self, gc, view_bounds=None, mode="normal"): - """ Draws the 'plot' layer. - """ + """Draws the 'plot' layer.""" self._draw_component(gc, view_bounds, mode) def _draw_component(self, gc, view_bounds=None, mode="normal"): @@ -481,11 +478,11 @@ def _draw_default_axes(self, gc): if (range.low < 0) and (range.high > 0): if range == self.index_mapper.range: dual = self.value_mapper.range - data_pts = array([[0.0,dual.low], [0.0, dual.high]]) + data_pts = array([[0.0, dual.low], [0.0, dual.high]]) else: dual = self.index_mapper.range - data_pts = array([[dual.low,0.0], [dual.high,0.0]]) - start,end = self.map_screen(data_pts) + data_pts = array([[dual.low, 0.0], [dual.high, 0.0]]) + start, end = self.map_screen(data_pts) start = around(start) end = around(end) gc.move_to(int(start[0]), int(start[1])) @@ -502,9 +499,9 @@ def _post_load(self): def _update_subdivision(self): pass - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Properties - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_index_range(self): return self.index_mapper.range @@ -531,28 +528,28 @@ def _get_y_mapper(self): return self.index_mapper def _get_hgrid(self): - for obj in self.underlays+self.overlays: - if isinstance(obj, PlotGrid) and obj.orientation=="horizontal": + for obj in self.underlays + self.overlays: + if isinstance(obj, PlotGrid) and obj.orientation == "horizontal": return obj else: return None def _get_vgrid(self): - for obj in self.underlays+self.overlays: - if isinstance(obj, PlotGrid) and obj.orientation=="vertical": + for obj in self.underlays + self.overlays: + if isinstance(obj, PlotGrid) and obj.orientation == "vertical": return obj else: return None def _get_x_axis(self): - for obj in self.underlays+self.overlays: + for obj in self.underlays + self.overlays: if isinstance(obj, PlotAxis) and obj.orientation in ("bottom", "top"): return obj else: return None def _get_y_axis(self): - for obj in self.underlays+self.overlays: + for obj in self.underlays + self.overlays: if isinstance(obj, PlotAxis) and obj.orientation in ("left", "right"): return obj else: @@ -560,14 +557,14 @@ def _get_y_axis(self): def _get_labels(self): labels = [] - for obj in self.underlays+self.overlays: + for obj in self.underlays + self.overlays: if isinstance(obj, PlotLabel): labels.append(obj) return labels - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _update_mappers(self): x_mapper = self.index_mapper @@ -615,8 +612,7 @@ def _orientation_changed(self): def _index_changed(self, old, new): if old is not None: old.observe(self._either_data_updated, "data_changed", remove=True) - old.observe(self._either_metadata_updated, "metadata_changed", - remove=True) + old.observe(self._either_metadata_updated, "metadata_changed", remove=True) if new is not None: new.observe(self._either_data_updated, "data_changed") new.observe(self._either_metadata_updated, "metadata_changed") @@ -635,8 +631,7 @@ def _either_metadata_updated(self, event): def _value_changed(self, old, new): if old is not None: old.observe(self._either_data_updated, "data_changed", remove=True) - old.observe(self._either_metadata_updated, "metadata_changed", - remove=True) + old.observe(self._either_metadata_updated, "metadata_changed", remove=True) if new is not None: new.observe(self._either_data_updated, "data_changed") new.observe(self._either_metadata_updated, "metadata_changed") @@ -694,14 +689,18 @@ def _use_subdivision_changed(self, old, new): if new: self._set_up_subdivision() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Persistence - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __getstate__(self): - state = super(BaseXYPlot,self).__getstate__() - for key in ['_cache_valid', '_cached_data_pts', '_screen_cache_valid', - '_cached_screen_pts']: + state = super(BaseXYPlot, self).__getstate__() + for key in [ + "_cache_valid", + "_cached_data_pts", + "_screen_cache_valid", + "_cached_screen_pts", + ]: if key in state: del state[key] diff --git a/chaco/candle_plot.py b/chaco/candle_plot.py index 588669f32..0f07e18db 100644 --- a/chaco/candle_plot.py +++ b/chaco/candle_plot.py @@ -8,8 +8,9 @@ from .abstract_data_source import AbstractDataSource from .base_candle_plot import BaseCandlePlot + def broaden(mask): - """ Takes a 1D boolean mask array and returns a copy with all the non-zero + """Takes a 1D boolean mask array and returns a copy with all the non-zero runs widened by 1. """ if len(mask) < 2: @@ -23,7 +24,7 @@ def broaden(mask): class CandlePlot(BaseCandlePlot): - """ A plot consisting of a filled bar with an optional centerline and + """A plot consisting of a filled bar with an optional centerline and stems extending to extrema. Usually used to represent some statistics on bins of data, with the centerline representing the mean, the bar extents representing +/- 1 standard dev or 10th/90th percentiles, and @@ -34,9 +35,9 @@ class CandlePlot(BaseCandlePlot): determined by the minimum space between adjacent index values. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Data-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The minimum values at each index point. If None, then no stem and no #: endcap line will be drawn below each bar. @@ -62,21 +63,23 @@ class CandlePlot(BaseCandlePlot): value = Property def map_data(self, screen_pt, all_values=True): - """ Maps a screen space point into the "index" space of the plot. + """Maps a screen space point into the "index" space of the plot. Overrides the BaseXYPlot implementation, and always returns an array of (index, value) tuples. """ x, y = screen_pt - if self.orientation == 'v': + if self.orientation == "v": x, y = y, x - return array((self.index_mapper.map_data(x), - self.value_mapper.map_data(y))) + return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) - def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, - index_only = True): + def map_index( + self, screen_pt, threshold=0.0, outside_returns_none=True, index_only=True + ): if not index_only: - raise NotImplementedError("Candle Plots only support index_only map_index()") + raise NotImplementedError( + "Candle Plots only support index_only map_index()" + ) if len(screen_pt) == 0: return None @@ -93,9 +96,11 @@ def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, # Bracket index and map those points to screen space, then # compute the distance if index > 0: - lower = index_data[index-1] + lower = index_data[index - 1] upper = index_data[index] - screen_low, screen_high = self.index_mapper.map_screen(array([lower, upper])) + screen_low, screen_high = self.index_mapper.map_screen( + array([lower, upper]) + ) # Find the closest index low_dist = abs(screen_pt[0] - screen_low) high_dist = abs(screen_pt[0] - screen_high) @@ -127,7 +132,13 @@ def _gather_points(self): data_pts = [compress(mask, index)] - for v in (self.min_values, self.bar_min, self.center_values, self.bar_max, self.max_values): + for v in ( + self.min_values, + self.bar_min, + self.center_values, + self.bar_max, + self.max_values, + ): if v is None or len(v.get_data()) == 0: data_pts.append(None) else: @@ -172,5 +183,3 @@ def _get_value(self): return self.bar_min elif self.bar_max is not None: return self.bar_max - - diff --git a/chaco/chaco_plot_container_editor.py b/chaco/chaco_plot_container_editor.py index 84a1a3937..6d153d27a 100644 --- a/chaco/chaco_plot_container_editor.py +++ b/chaco/chaco_plot_container_editor.py @@ -7,11 +7,11 @@ class PlotContainerEditor(ComponentEditor): - """ Deprecated alias for ComponentEditor. - """ + """Deprecated alias for ComponentEditor.""" def __init__(self, *args, **kwds): super(PlotContainerEditor, self).__init__(*args, **kwds) - warnings.warn("DEPRECATED: Use enable.component_editor" - ".ComponentEditor instead.", DeprecationWarning) - + warnings.warn( + "DEPRECATED: Use enable.component_editor" ".ComponentEditor instead.", + DeprecationWarning, + ) diff --git a/chaco/chaco_plot_editor.py b/chaco/chaco_plot_editor.py index 8c5922cc5..e442994b6 100644 --- a/chaco/chaco_plot_editor.py +++ b/chaco/chaco_plot_editor.py @@ -4,48 +4,54 @@ """ # Enthought library imports from traits.etsconfig.api import ETSConfig -from enable.api import black_color_trait, LineStyle, ColorTrait,\ - white_color_trait, MarkerTrait, Window +from enable.api import ( + black_color_trait, + LineStyle, + ColorTrait, + white_color_trait, + MarkerTrait, + Window, +) from enable.trait_defs.ui.api import RGBAColorEditor from kiva.trait_defs.kiva_font_trait import KivaFont -from traits.api import Enum, Str, Range, Tuple, \ - Bool, Trait, Int, Any, Property +from traits.api import Enum, Str, Range, Tuple, Bool, Trait, Int, Any, Property from traitsui.api import Item from traitsui.editor_factory import EditorFactory # Toolkit dependent imports from traitsui.toolkit import toolkit_object -Editor = toolkit_object('editor:Editor') + +Editor = toolkit_object("editor:Editor") # Local relative imports from .axis import PlotAxis from .plot_containers import OverlayPlotContainer -from .plot_factory import create_line_plot, create_scatter_plot, \ - add_default_grids, add_default_axes +from .plot_factory import ( + create_line_plot, + create_scatter_plot, + add_default_grids, + add_default_axes, +) from .plot_label import PlotLabel # Somewhat unorthodox... from .tools.api import PanTool, ZoomTool -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # Trait definitions: -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # Range of values for an axis. -AxisRange = Tuple( ( 0.0, 1.0, 0.01 ), - labels = [ 'Low', 'High', 'Step' ], - cols = 3 ) +AxisRange = Tuple((0.0, 1.0, 0.01), labels=["Low", "High", "Step"], cols=3) # Range of axis bounds. -AxisBounds = Tuple( ( 0.0, 1.0 ), - labels = [ 'Min', 'Max' ], - cols = 2 ) +AxisBounds = Tuple((0.0, 1.0), labels=["Min", "Max"], cols=2) # Range for the height and width for the plot widget. -PlotSize = Range( 50, 1000, 180 ) +PlotSize = Range(50, 1000, 180) # Range of plot line weights. -LineWeight = Range( 1, 9, 3 ) +LineWeight = Range(1, 9, 3) # The color editor to use for various color traits. color_editor = RGBAColorEditor() @@ -55,10 +61,11 @@ class ChacoPlotItem(Item): - """ A Traits UI Item for a Chaco plot, for use in Traits UI Views. + """A Traits UI Item for a Chaco plot, for use in Traits UI Views. NOTE: ComponentEditor is preferred over this class, as it is more flexible. """ + # Name of the trait that references the index data source. index = Str # Name of the trait that references the value data source. @@ -106,7 +113,7 @@ class ChacoPlotItem(Item): # Background color of the plot. bgcolor = white_color_trait # Background color of the plot (deprecated). - bg_color = Property # backwards compatibility; deprecated + bg_color = Property # backwards compatibility; deprecated # Color of the background padding. padding_bg_color = ColorTrait("sys_window") @@ -153,84 +160,91 @@ def _get_bg_color(self): return self.bgcolor -class ChacoEditorFactory ( EditorFactory ): - """ Editor factory for plot editors. - """ - #--------------------------------------------------------------------------- +class ChacoEditorFactory(EditorFactory): + """Editor factory for plot editors.""" + + # --------------------------------------------------------------------------- # Trait definitions: - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Width of the plot editor. - width = PlotSize + width = PlotSize # Height of the plot editor. - height = PlotSize + height = PlotSize # The ChacoPlotItem associated with this factory. plotitem = Any - - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # 'Editor' factory methods: - #--------------------------------------------------------------------------- - - def simple_editor ( self, ui, object, name, description, parent ): - return ChacoPlotEditor( parent, - factory = self, - ui = ui, - object = object, - name = name, - description = description ) - - def text_editor ( self, ui, object, name, description, parent ): - return ChacoPlotEditor( parent, - factory = self, - ui = ui, - object = object, - name = name, - description = description ) - - def readonly_editor ( self, ui, object, name, description, parent ): - return ChacoPlotEditor( parent, - factory = self, - ui = ui, - object = object, - name = name, - description = description ) - - -class ChacoPlotEditor ( Editor ): - """ Traits UI editor for displaying trait values in a Chaco plot. - """ - - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- + + def simple_editor(self, ui, object, name, description, parent): + return ChacoPlotEditor( + parent, + factory=self, + ui=ui, + object=object, + name=name, + description=description, + ) + + def text_editor(self, ui, object, name, description, parent): + return ChacoPlotEditor( + parent, + factory=self, + ui=ui, + object=object, + name=name, + description=description, + ) + + def readonly_editor(self, ui, object, name, description, parent): + return ChacoPlotEditor( + parent, + factory=self, + ui=ui, + object=object, + name=name, + description=description, + ) + + +class ChacoPlotEditor(Editor): + """Traits UI editor for displaying trait values in a Chaco plot.""" + + # --------------------------------------------------------------------------- # Finishes initializing the editor by creating the underlying toolkit # widget: - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- - def init ( self, parent ): - """ Finishes initializing the editor by creating the underlying toolkit - widget. + def init(self, parent): + """Finishes initializing the editor by creating the underlying toolkit + widget. """ factory = self.factory plotitem = factory.plotitem - container = OverlayPlotContainer(padding = 50, fill_padding = True, - bgcolor = plotitem.padding_bg_color, - use_backbuffer=True) + container = OverlayPlotContainer( + padding=50, + fill_padding=True, + bgcolor=plotitem.padding_bg_color, + use_backbuffer=True, + ) - if plotitem.title != '': - container.overlays.append(PlotLabel(plotitem.title, - component=container, - overlay_position="top")) + if plotitem.title != "": + container.overlays.append( + PlotLabel(plotitem.title, component=container, overlay_position="top") + ) self._container = container - window = Window(parent, component = container) + window = Window(parent, component=container) # FIXME: Toolkit specifc code here. The AbstractWindow should have a # 'set size' method as part of its API. self.control = control = window.control - if ETSConfig.toolkit == 'wx': + if ETSConfig.toolkit == "wx": control.SetSize((factory.width, factory.height)) - elif ETSConfig.toolkit == 'qt4': + elif ETSConfig.toolkit == "qt4": control.resize(factory.width, factory.height) else: raise NotImplementedError @@ -243,27 +257,26 @@ def init ( self, parent ): object = self.object if USE_DATA_UPDATE == 1: for name in (plotitem.index, plotitem.value): - object.observe( self._update_data, name) + object.observe(self._update_data, name) for name in (plotitem.x_label_trait, plotitem.y_label_trait): object.observe(lambda s: self._update_axis_grids(), name) if plotitem.type_trait not in ("", None): object.observe(self.update_editor, plotitem.type_trait) - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Disposes of the contents of an editor: - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def dispose(self): - """ Disposes of the contents of the editor. - """ + """Disposes of the contents of the editor.""" object = self.object plotitem = self.factory.plotitem if USE_DATA_UPDATE == 1: for name in (plotitem.index, plotitem.value): - object.observe( self._update_data, name, remove = True ) + object.observe(self._update_data, name, remove=True) for name in (plotitem.type_trait,): - object.observe( self.update_editor, name, remove = True ) + object.observe(self.update_editor, name, remove=True) self._destroy_plot() super(ChacoPlotEditor, self).dispose() @@ -279,16 +292,16 @@ def _destroy_plot(self): plot.index = None plot.value = None - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Updates the editor when the object trait changes externally to the editor: - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def update_editor(self, event=None): - """ Updates the editor when the object trait changes externally to the - editor. + """Updates the editor when the object trait changes externally to the + editor. """ - factory = self.factory + factory = self.factory if factory is None: return plotitem = factory.plotitem @@ -321,14 +334,19 @@ def update_editor(self, event=None): # Class-level attribute mapping different plot_type strings to methods for # creating different types of plots - plot_creator_map = { "line": self._create_line_plot, - "scatter": self._create_scatter_plot } + plot_creator_map = { + "line": self._create_line_plot, + "scatter": self._create_scatter_plot, + } if plot_type in plot_creator_map: - plot = plot_creator_map[plot_type](plotitem, (x_values, y_values), - index_bounds = index_bounds, - value_bounds = value_bounds, - orientation = plotitem.orientation) + plot = plot_creator_map[plot_type]( + plotitem, + (x_values, y_values), + index_bounds=index_bounds, + value_bounds=value_bounds, + orientation=plotitem.orientation, + ) else: raise RuntimeError("Unknown plot type '%s' in ChacoPlotEditor." % plot_type) @@ -341,8 +359,8 @@ def update_editor(self, event=None): self._container.request_redraw() def _update_data(self, event): - """ Updates the editor when the object trait changes externally to the - editor. + """Updates the editor when the object trait changes externally to the + editor. """ if self._plot is None: self.update_editor() @@ -352,10 +370,15 @@ def _update_data(self, event): self._plot.index.set_data(x_values) self._plot.value.set_data(y_values) - def _set_basic_properties(self, plot, plotitem): - for attr in ("color", "bgcolor", "border_visible", "border_width", - "border_dash", "border_color"): + for attr in ( + "color", + "bgcolor", + "border_visible", + "border_width", + "border_dash", + "border_color", + ): setattr(plot, attr, getattr(plotitem, attr)) def _create_line_plot(self, plotitem, values, **kwargs): @@ -369,8 +392,9 @@ def _create_scatter_plot(self, plotitem, values, **kwargs): return plot def _add_axis_grids(self, new_plot, plotitem): - value_axis, index_axis = add_default_axes(new_plot, - orientation=plotitem.orientation) + value_axis, index_axis = add_default_axes( + new_plot, orientation=plotitem.orientation + ) add_default_grids(new_plot) new_plot.tools.append(PanTool(new_plot)) zoom = ZoomTool(component=new_plot, tool_mode="box", always_on=False) diff --git a/chaco/chaco_traits.py b/chaco/chaco_traits.py index 33fdabbcd..618297024 100644 --- a/chaco/chaco_traits.py +++ b/chaco/chaco_traits.py @@ -4,10 +4,10 @@ # Enthought library imports from traits.api import Enum -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- # Box positioning traits: used to specify positions of boxes relative to # one another. Generally used for layout. -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- box_edge_enum = Enum("left", "right", "top", "bottom") diff --git a/chaco/chaco_version.py b/chaco/chaco_version.py index cc041903a..768b15dbd 100644 --- a/chaco/chaco_version.py +++ b/chaco/chaco_version.py @@ -1,4 +1,4 @@ -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Copyright (c) 2005, Enthought, Inc. # All rights reserved. # @@ -10,7 +10,7 @@ # # Author: Enthought, Inc. # Description: -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ """ Defines version numbering for the Chaco package. """ major = 2 diff --git a/chaco/cmap_image_plot.py b/chaco/cmap_image_plot.py index 46cd9d531..e2d5bddfe 100644 --- a/chaco/cmap_image_plot.py +++ b/chaco/cmap_image_plot.py @@ -18,15 +18,15 @@ class CMapImagePlot(ImagePlot): - """ Colormapped image plot. Takes a value data object whose elements are + """Colormapped image plot. Takes a value data object whose elements are scalars, and renders them as a colormapped image. """ # TODO: Modify ImageData to explicitly support scalar value arrays - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Data-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Maps from scalar data values in self.data.value to color tuples value_mapper = Instance(AbstractColormap) @@ -42,14 +42,14 @@ class CMapImagePlot(ImagePlot): fade_alpha = Float(0.3) #: RGB color to use to fade out unselected points. - fade_background = Tuple((0,0,0)) - + fade_background = Tuple((0, 0, 0)) + #: whether to pre-compute the full colormapped RGB(A) image cache_full_map = Bool(True) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private Traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Is the mapped image valid? _mapped_image_cache_valid = Bool(False) @@ -57,9 +57,9 @@ class CMapImagePlot(ImagePlot): # Cache of the fully mapped RGB(A) image. _cached_mapped_image = Any - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, **kwargs): super(CMapImagePlot, self).__init__(**kwargs) @@ -69,43 +69,39 @@ def __init__(self, **kwargs): self.value.observe(self._update_selections, "metadata_changed") def set_value_selection(self, val): - """ Sets a range of values in the value data source as selected. - """ + """Sets a range of values in the value data source as selected.""" if val is not None: low, high = val data = self.value.get_data() - new_mask = (data>=low) & (data<=high) + new_mask = (data >= low) & (data <= high) self.value.metadata["selection_masks"] = [new_mask] else: del self.value.metadata["selection_masks"] self._update_selections() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Base2DPlot interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _render(self, gc): - """ Ensures that the cached image is valid. + """Ensures that the cached image is valid. Called before _render() is called. Implements the Base2DPlot interface. """ if not self._mapped_image_cache_valid: - if 'selection_masks' in self.value.metadata: - self._compute_cached_image(self.value.metadata['selection_masks']) + if "selection_masks" in self.value.metadata: + self._compute_cached_image(self.value.metadata["selection_masks"]) else: self._compute_cached_image() ImagePlot._render(self, gc) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ - + # ------------------------------------------------------------------------ + def _cmap_values(self, data, selection_masks=None): - """ Maps the data to RGB(A) with optional selection masks overlayed - - """ + """Maps the data to RGB(A) with optional selection masks overlayed""" # get the RGBA values from the color map as uint8 mapped_image = self.value_mapper.map_uint8(data) if selection_masks is not None: @@ -117,26 +113,28 @@ def _cmap_values(self, data, selection_masks=None): else: mask = zeros(self._cached_mapped_image.shape[:2], dtype=bool) # Apply the selection fade, from speedups.py - apply_selection_fade(mapped_image, mask, - self.fade_alpha, self.fade_background) + apply_selection_fade( + mapped_image, mask, self.fade_alpha, self.fade_background + ) return mapped_image - + def _compute_cached_image(self, selection_masks=None): - """ Updates the cached image. - """ + """Updates the cached image.""" if self.cache_full_map: if not self._mapped_image_cache_valid: - self._cached_mapped_image = self._cmap_values(self.value.data, - selection_masks) + self._cached_mapped_image = self._cmap_values( + self.value.data, selection_masks + ) self._mapped_image_cache_valid = True mapped_value = self._cached_mapped_image ImagePlot._compute_cached_image(self, mapped_value) else: self._mapped_image_cache_valid = True - ImagePlot._compute_cached_image(self, self.value.data, mapper=lambda data: - self._cmap_values(data)) - + ImagePlot._compute_cached_image( + self, self.value.data, mapper=lambda data: self._cmap_values(data) + ) + def _update_value_mapper(self, event=None): self._mapped_image_cache_valid = False self._image_cache_valid = False @@ -147,9 +145,9 @@ def _update_selections(self, event=None): self._image_cache_valid = False self.invalidate_and_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Properties - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_value_range(self): return self.value_mapper.range @@ -163,9 +161,9 @@ def _get_color_mapper(self): def _set_color_mapper(self, val): self.value_mapper = val - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _value_mapper_changed(self, old, new): if old is not None: @@ -177,7 +175,7 @@ def _value_mapper_changed(self, old, new): if new.range is None and old.range is not None: new.range = old.range self._update_value_mapper() - + def _value_data_changed_fired(self): super(CMapImagePlot, self)._value_data_changed_fired() self._mapped_image_cache_valid = False @@ -185,7 +183,6 @@ def _value_data_changed_fired(self): def _index_data_changed_fired(self): super(CMapImagePlot, self)._index_data_changed_fired() self._mapped_image_cache_valid = False - + def _cache_full_map_changed(self): self._mapped_image_cache_valid = False - diff --git a/chaco/color_bar.py b/chaco/color_bar.py index f9e016c13..615bed5ff 100644 --- a/chaco/color_bar.py +++ b/chaco/color_bar.py @@ -4,9 +4,7 @@ from numpy import array, arange, ascontiguousarray, ones, transpose, uint8 # Enthought library imports -from traits.api import ( - Any, Bool, Enum, Instance, Property, cached_property, observe -) +from traits.api import Any, Bool, Enum, Instance, Property, cached_property, observe from traits.observation.api import parse from kiva.image import GraphicsContext @@ -20,16 +18,16 @@ class ColorBar(AbstractPlotRenderer): - """ A color bar for a color-mapped plot. - """ + """A color bar for a color-mapped plot.""" + #: Screen mapper for index data. index_mapper = Instance(AbstractMapper) #: Screen mapper for color data - color_mapper = Property #Instance(ColorMapper) + color_mapper = Property # Instance(ColorMapper) #: Screen mapper for value data (synonym for color_mapper) - value_mapper = Property(depends_on='color_mapper') + value_mapper = Property(depends_on="color_mapper") #: Optional index data source for generic tools to attach metadata to. index = Property @@ -51,29 +49,29 @@ class ColorBar(AbstractPlotRenderer): #: the orientation of the plot. y_mapper = Property - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Override default values of inherited traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The border is visible (overrides enable.Component). border_visible = True #: The orientation of the index axis. - orientation = Enum('v', 'h') + orientation = Enum("v", "h") #: Should the bar go left-to-right or bottom-to-top (normal) or the reverse? - direction = Enum('normal', 'flipped') + direction = Enum("normal", "flipped") #: Overrides the default background color trait in PlotComponent. - bgcolor = 'transparent' + bgcolor = "transparent" #: Draw layers in "draw order" use_draw_order = True #: Default width is 40 pixels (overrides enable.CoordinateBox) width = 40 #: Faux origin for the axis to look at - origin = Enum('bottom left', 'top left', 'bottom right', 'top right') + origin = Enum("bottom left", "top left", "bottom right", "top right") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private attributes - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The grid _grid = Instance(PlotGrid) @@ -88,7 +86,7 @@ class ColorBar(AbstractPlotRenderer): _index = Instance(ArrayDataSource, args=()) def __init__(self, *args, **kw): - """ In creating an instance, this method ensures that the grid and the + """In creating an instance, this method ensures that the grid and the axis are created before setting their visibility. """ grid_visible = kw.pop("grid_visible", True) @@ -96,27 +94,27 @@ def __init__(self, *args, **kw): super(ColorBar, self).__init__(*args, **kw) - if self.orientation == 'h': - if self.direction == 'normal': - self.origin = 'bottom left' + if self.orientation == "h": + if self.direction == "normal": + self.origin = "bottom left" else: - self.origin = 'bottom right' - grid_orientation = 'vertical' - axis_orientation = 'bottom' + self.origin = "bottom right" + grid_orientation = "vertical" + axis_orientation = "bottom" else: - if self.direction == 'normal': - self.origin = 'bottom left' + if self.direction == "normal": + self.origin = "bottom left" else: - self.origin = 'top left' - grid_orientation = 'horizontal' - axis_orientation = 'left' - - self._grid = PlotGrid(orientation=grid_orientation, - mapper=self.index_mapper, - component=self) - self._axis = PlotAxis(orientation=axis_orientation, - mapper=self.index_mapper, - component=self) + self.origin = "top left" + grid_orientation = "horizontal" + axis_orientation = "left" + + self._grid = PlotGrid( + orientation=grid_orientation, mapper=self.index_mapper, component=self + ) + self._axis = PlotAxis( + orientation=axis_orientation, mapper=self.index_mapper, component=self + ) self.overlays.append(self._grid) self.overlays.append(self._axis) @@ -124,12 +122,11 @@ def __init__(self, *args, **kw): self.grid_visible = grid_visible self.axis_visible = axis_visible - def _draw_plot(self, gc, view_bounds=None, mode='normal'): - """ Draws the 'plot' layer. - """ + def _draw_plot(self, gc, view_bounds=None, mode="normal"): + """Draws the 'plot' layer.""" self._update_mappers() with gc: - if self.orientation == 'h': + if self.orientation == "h": perpendicular_dim = 1 axis_dim = 0 else: @@ -140,7 +137,7 @@ def _draw_plot(self, gc, view_bounds=None, mode='normal'): low = mapper.low_pos high = mapper.high_pos - if self.direction == 'flipped': + if self.direction == "flipped": low, high = high, low scrn_points = arange(low, high + 1) @@ -155,8 +152,9 @@ def _draw_plot(self, gc, view_bounds=None, mode='normal'): # Get the colors associated with the data points. colors = self.color_mapper.map_screen(data_points) - img = self._make_color_image(colors, self.bounds[perpendicular_dim], - self.orientation, self.direction) + img = self._make_color_image( + colors, self.bounds[perpendicular_dim], self.orientation, self.direction + ) gc.draw_image(img, (self.x, self.y, self.width, self.height)) def _make_color_image(self, color_values, width, orientation, direction): @@ -165,33 +163,35 @@ def _make_color_image(self, color_values, width, orientation, direction): values (Nx3 or Nx4). The *width* parameter is the width of the colorbar, and *orientation* is the orientation of the plot. """ - bmparray = ones((width, color_values.shape[0], - color_values.shape[1]))* color_values * 255 + bmparray = ( + ones((width, color_values.shape[0], color_values.shape[1])) + * color_values + * 255 + ) if orientation == "v": - bmparray = ascontiguousarray(transpose(bmparray, axes=(1,0,2))[::-1]) + bmparray = ascontiguousarray(transpose(bmparray, axes=(1, 0, 2))[::-1]) bmparray = bmparray.astype(uint8) img = GraphicsContext(bmparray, "rgba32") return img - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait events - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _update_mappers(self): if not self.index_mapper or not self.color_mapper: return - if self.orientation == 'h' and 'left' in self.origin: + if self.orientation == "h" and "left" in self.origin: self.index_mapper.low_pos = self.x self.index_mapper.high_pos = self.x2 - elif self.orientation == 'h' and 'right' in self.origin: + elif self.orientation == "h" and "right" in self.origin: self.index_mapper.low_pos = self.x2 self.index_mapper.high_pos = self.x - elif self.orientation == 'v' and 'bottom' in self.origin: + elif self.orientation == "v" and "bottom" in self.origin: self.index_mapper.low_pos = self.y self.index_mapper.high_pos = self.y2 - elif self.orientation == 'v' and 'top' in self.origin: + elif self.orientation == "v" and "top" in self.origin: self.index_mapper.low_pos = self.y2 self.index_mapper.high_pos = self.y self.index_mapper.range = self.color_mapper.range @@ -218,7 +218,7 @@ def _updated_changed_for_index_mapper(self): def _updated_changed_for_color_mapper(self): self._update_mappers() - @observe(parse('[index_mapper,color_mapper]').match(lambda n, t: True)) + @observe(parse("[index_mapper,color_mapper]").match(lambda n, t: True)) def _either_mapper_updated(self, event=None): self.invalidate_draw() self.request_redraw() @@ -248,9 +248,9 @@ def _axis_visible_changed(self, old, new): self._axis.visible = new self.request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property setters and getters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_x_mapper(self): if self.orientation == "h": diff --git a/chaco/color_mapper.py b/chaco/color_mapper.py index b094e5fdb..08c2be7e8 100644 --- a/chaco/color_mapper.py +++ b/chaco/color_mapper.py @@ -2,13 +2,42 @@ """ # Major library imports -from numpy import arange, array, asarray, clip, divide, float32, int8, isinf, \ - isnan, ones, searchsorted, sometrue, sort, take, uint8, where, zeros, \ - linspace, ones_like +from numpy import ( + arange, + array, + asarray, + clip, + divide, + float32, + int8, + isinf, + isnan, + ones, + searchsorted, + sometrue, + sort, + take, + uint8, + where, + zeros, + linspace, + ones_like, +) # Enthought library imports -from traits.api import Any, Array, Bool, Dict, Event, Float, HasTraits, \ - Int, Property, Str, Trait +from traits.api import ( + Any, + Array, + Bool, + Dict, + Event, + Float, + HasTraits, + Int, + Property, + Str, + Trait, +) # Relative imports from .abstract_colormap import AbstractColormap @@ -22,14 +51,15 @@ class ColorMapTemplate(HasTraits): A class representing the state of a ColorMapper, for use when persisting plots. """ + #: The segment data of the color map. segment_map = Any #: The number of steps in the color map. steps = Int(256) #: Low end of the color map range. - range_low_setting = Trait('auto', 'auto', Float) + range_low_setting = Trait("auto", "auto", Float) #: High end of the color map range. - range_high_setting = Trait('auto', 'auto', Float) + range_high_setting = Trait("auto", "auto", Float) def __init__(self, colormap=None, **kwtraits): """ @@ -40,28 +70,26 @@ def __init__(self, colormap=None, **kwtraits): self.from_colormap(colormap) def from_colormap(self, colormap): - """ Populates this template from a color map. - """ + """Populates this template from a color map.""" self.segment_map = colormap._segmentdata.copy() self.steps = colormap.steps self.range_low_setting = colormap.range.low_setting self.range_high_setting = colormap.range.high_setting def to_colormap(self, range=None): - """ Returns a ColorMapper instance from this template. - """ - colormap = ColorMapper(self.segment_map, steps = self.steps) + """Returns a ColorMapper instance from this template.""" + colormap = ColorMapper(self.segment_map, steps=self.steps) if range: colormap.range = range else: - colormap.range = DataRange1D(low = self.range_low_setting, - high = self.range_high_setting) + colormap.range = DataRange1D( + low=self.range_low_setting, high=self.range_high_setting + ) return colormap - class ColorMapper(AbstractColormap): - """ Represents a simple band-of-colors style of color map. + """Represents a simple band-of-colors style of color map. The look-up transfer function is a simple linear function between defined intensities. There is no limit to the number of steps that can be @@ -97,14 +125,13 @@ class ColorMapper(AbstractColormap): # The raw segment data for creating the mapping array. _segmentdata = Dict # (Str, Tuple | List) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Static methods. - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @classmethod def from_palette_array(cls, palette, **traits): - """ Creates a ColorMapper from a palette array. + """Creates a ColorMapper from a palette array. The palette colors are linearly interpolated across the range of mapped values. @@ -121,32 +148,34 @@ def from_palette_array(cls, palette, **traits): n_colors, n_components = palette.shape if n_colors < 2: raise ValueError("Palette must contain at least two colors.") - if n_components not in (3,4): - raise ValueError("Palette must be of RGB or RGBA colors. " - "Got %s color components." % n_components) + if n_components not in (3, 4): + raise ValueError( + "Palette must be of RGB or RGBA colors. " + "Got %s color components." % n_components + ) # Compute the % offset for each of the color locations. offsets = linspace(0.0, 1.0, n_colors) # From the offsets and the color data, generate a segment map. segment_map = {} - red_values = palette[:,0] - segment_map['red'] = list(zip(offsets, red_values, red_values)) - green_values = palette[:,1] - segment_map['green'] = list(zip(offsets, green_values, green_values)) - blue_values = palette[:,2] - segment_map['blue'] = list(zip(offsets, blue_values, blue_values)) + red_values = palette[:, 0] + segment_map["red"] = list(zip(offsets, red_values, red_values)) + green_values = palette[:, 1] + segment_map["green"] = list(zip(offsets, green_values, green_values)) + blue_values = palette[:, 2] + segment_map["blue"] = list(zip(offsets, blue_values, blue_values)) if n_components == 3: alpha_values = ones(n_colors) else: - alpha_values = palette[:,3] - segment_map['alpha'] = list(zip(offsets, alpha_values, alpha_values)) + alpha_values = palette[:, 3] + segment_map["alpha"] = list(zip(offsets, alpha_values, alpha_values)) return cls(segment_map, **traits) @classmethod def from_segment_map(cls, segment_map, **traits): - """ Creates a Colormapper from a segment map. + """Creates a Colormapper from a segment map. The *segment_map* parameter is a dictionary with 'red', 'green', and 'blue' (and optionally 'alpha') entries. Each entry is a list of @@ -165,14 +194,14 @@ def from_segment_map(cls, segment_map, **traits): the transitions. """ - if 'alpha' not in segment_map: + if "alpha" not in segment_map: segment_map = segment_map.copy() - segment_map['alpha'] = [(0.0, 1.0, 1.0), (1.0, 1.0, 1.0)] + segment_map["alpha"] = [(0.0, 1.0, 1.0), (1.0, 1.0, 1.0)] return cls(segment_map, **traits) @classmethod def from_file(cls, filename, **traits): - """ Creates a ColorMapper from a file. + """Creates a ColorMapper from a file. The *filename* parameter is the name of a file whose lines each contain 4 or 5 float values between 0.0 and 1.0. The first value is an offset in @@ -181,42 +210,41 @@ def from_file(cls, filename, **traits): The first line is assumed to contain the name of the colormap. """ - colormap_file = open(filename, 'r') + colormap_file = open(filename, "r") lines = colormap_file.readlines() colormap_file.close() - rgba_arr = [[],[],[],[]] + rgba_arr = [[], [], [], []] for line in lines[1:]: strvalues = line.strip().split() values = [float32(value) for value in strvalues] if len(values) > 4: - channels = (0,1,2,3) + channels = (0, 1, 2, 3) else: - channels = (0,1,2) + channels = (0, 1, 2) for i in channels: - channeltuple = (values[0], values[i+1], values[i+1]) + channeltuple = (values[0], values[i + 1], values[i + 1]) rgba_arr[i].append(channeltuple) # Alpha is frequently unspecified. if len(rgba_arr[-1]) == 0: rgba_arr[-1] = [(0.0, 1.0, 1.0), (1.0, 1.0, 1.0)] - if 'name' not in traits: + if "name" not in traits: # Don't override the code. - traits['name'] = lines[0].strip() + traits["name"] = lines[0].strip() rgba_dict = { - 'red': rgba_arr[0], - 'green': rgba_arr[1], - 'blue': rgba_arr[2], - 'alpha': rgba_arr[3], + "red": rgba_arr[0], + "green": rgba_arr[1], + "blue": rgba_arr[2], + "alpha": rgba_arr[3], } return cls(rgba_dict, **traits) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, segmentdata, **kwtraits): - """ Creates a Colormapper from a segment map. + """Creates a Colormapper from a segment map. The *segment_map* parameter is a dictionary with 'red', 'green', and 'blue' (and optionally 'alpha') entries. Each entry is a list of @@ -238,65 +266,73 @@ def __init__(self, segmentdata, **kwtraits): super(ColorMapper, self).__init__(**kwtraits) def map_screen(self, data_array): - """ Maps an array of data values to an array of colors. - """ + """Maps an array of data values to an array of colors.""" if self._dirty: self._recalculate() - rgba = map_colors(data_array, self.steps, self.range.low, - self.range.high, self._red_lut, self._green_lut, - self._blue_lut, self._alpha_lut) + rgba = map_colors( + data_array, + self.steps, + self.range.low, + self.range.high, + self._red_lut, + self._green_lut, + self._blue_lut, + self._alpha_lut, + ) return rgba - def map_index(self, ary): - """ Maps an array of values to their corresponding color band index. - """ + """Maps an array of values to their corresponding color band index.""" if self._dirty: self._recalculate() - indices = (ary - self.range.low) / (self.range.high - self.range.low) * self.steps + indices = ( + (ary - self.range.low) / (self.range.high - self.range.low) * self.steps + ) return clip(indices.astype(int), 0, self.steps - 1) def reverse_colormap(self): - """ Reverses the color bands of this colormap. - """ + """Reverses the color bands of this colormap.""" for name in ("red", "green", "blue", "alpha"): data = asarray(self._segmentdata[name]) - data[:, (1,2)] = data[:, (2,1)] - data[:,0] = (1.0 - data[:,0]) + data[:, (1, 2)] = data[:, (2, 1)] + data[:, 0] = 1.0 - data[:, 0] self._segmentdata[name] = data[::-1] self._recalculate() def map_uint8(self, data_array): - """ Maps an array of data values to an array of colors. - """ + """Maps an array of data values to an array of colors.""" if self._dirty: self._recalculate() - rgba = map_colors_uint8(data_array, self.steps, self.range.low, - self.range.high, self._red_lut_uint8, self._green_lut_uint8, - self._blue_lut_uint8, self._alpha_lut_uint8) + rgba = map_colors_uint8( + data_array, + self.steps, + self.range.low, + self.range.high, + self._red_lut_uint8, + self._green_lut_uint8, + self._blue_lut_uint8, + self._alpha_lut_uint8, + ) return rgba - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ - + # ------------------------------------------------------------------------ def _get_color_bands(self): - """ Gets the color bands array. - """ + """Gets the color bands array.""" if self._dirty: self._recalculate() luts = [self._red_lut, self._green_lut, self._blue_lut] - if self.color_depth is 'rgba': + if self.color_depth is "rgba": luts.append(self._alpha_lut) result = list(zip(*luts)) @@ -304,25 +340,20 @@ def _get_color_bands(self): return result def _recalculate(self): - """ Recalculates the mapping arrays. - """ + """Recalculates the mapping arrays.""" - self._red_lut = self._make_mapping_array( - self.steps, self._segmentdata['red'] - ) + self._red_lut = self._make_mapping_array(self.steps, self._segmentdata["red"]) self._green_lut = self._make_mapping_array( - self.steps, self._segmentdata['green'] - ) - self._blue_lut = self._make_mapping_array( - self.steps, self._segmentdata['blue'] + self.steps, self._segmentdata["green"] ) + self._blue_lut = self._make_mapping_array(self.steps, self._segmentdata["blue"]) self._alpha_lut = self._make_mapping_array( - self.steps, self._segmentdata['alpha'] + self.steps, self._segmentdata["alpha"] ) - self._red_lut_uint8 = (self._red_lut * 255.0).astype('uint8') - self._green_lut_uint8 = (self._green_lut * 255.0).astype('uint8') - self._blue_lut_uint8 = (self._blue_lut * 255.0).astype('uint8') - self._alpha_lut_uint8 = (self._alpha_lut * 255.0).astype('uint8') + self._red_lut_uint8 = (self._red_lut * 255.0).astype("uint8") + self._green_lut_uint8 = (self._green_lut * 255.0).astype("uint8") + self._blue_lut_uint8 = (self._blue_lut * 255.0).astype("uint8") + self._alpha_lut_uint8 = (self._alpha_lut * 255.0).astype("uint8") self.updated = True self._dirty = False @@ -357,25 +388,25 @@ def _make_mapping_array(self, n, data): if len(shape) != 2 and shape[1] != 3: raise ValueError("data must be nx3 format") - x = adata[:,0] - y0 = adata[:,1] - y1 = adata[:,2] + x = adata[:, 0] + y0 = adata[:, 1] + y1 = adata[:, 2] - if x[0] != 0. or x[-1] != 1.0: + if x[0] != 0.0 or x[-1] != 1.0: raise ValueError( - "data mapping points must start with x=0. and end with x=1") - if sometrue(sort(x)-x): - raise ValueError( - "data mapping points must have x in increasing order") + "data mapping points must start with x=0. and end with x=1" + ) + if sometrue(sort(x) - x): + raise ValueError("data mapping points must have x in increasing order") # begin generation of lookup table - x = x * (n-1) + x = x * (n - 1) lut = zeros((n,), float32) xind = arange(float32(n), dtype=float32) ind = searchsorted(x, xind)[1:-1] - lut[1:-1] = ( divide(xind[1:-1] - take(x,ind-1), - take(x,ind)-take(x,ind-1) ) - *(take(y0,ind)-take(y1,ind-1)) + take(y1,ind-1)) + lut[1:-1] = divide( + xind[1:-1] - take(x, ind - 1), take(x, ind) - take(x, ind - 1) + ) * (take(y0, ind) - take(y1, ind - 1)) + take(y1, ind - 1) lut[0] = y1[0] lut[-1] = y0[-1] @@ -385,7 +416,7 @@ def _make_mapping_array(self, n, data): #### matplotlib #### def _map(self, X): - """ Maps from a scalar or an array to an RGBA value or array. + """Maps from a scalar or an array to an RGBA value or array. The *X* parameter is either a scalar or an array (of any dimension). If it is scalar, the function returns a tuple of RGBA values; otherwise @@ -399,26 +430,25 @@ def _map(self, X): """ if type(X) in [int, float]: - vtype = 'scalar' + vtype = "scalar" xa = array([X]) else: - vtype = 'array' + vtype = "array" xa = asarray(X) # assume the data is properly normalized - #xa = where(xa>1.,1.,xa) - #xa = where(xa<0.,0.,xa) - + # xa = where(xa>1.,1.,xa) + # xa = where(xa<0.,0.,xa) nanmask = isnan(xa) - xa = where(nanmask, 0, (xa * (self.steps-1)).astype(int)) - rgba = zeros(xa.shape+(4,), float) - rgba[...,0] = where(nanmask, 0, take(self._red_lut, xa)) - rgba[...,1] = where(nanmask, 0, take(self._green_lut, xa)) - rgba[...,2] = where(nanmask, 0, take(self._blue_lut, xa)) - rgba[...,3] = where(nanmask, 0, take(self._alpha_lut, xa)) - if vtype == 'scalar': - rgba = tuple(rgba[0,:]) + xa = where(nanmask, 0, (xa * (self.steps - 1)).astype(int)) + rgba = zeros(xa.shape + (4,), float) + rgba[..., 0] = where(nanmask, 0, take(self._red_lut, xa)) + rgba[..., 1] = where(nanmask, 0, take(self._green_lut, xa)) + rgba[..., 2] = where(nanmask, 0, take(self._blue_lut, xa)) + rgba[..., 3] = where(nanmask, 0, take(self._alpha_lut, xa)) + if vtype == "scalar": + rgba = tuple(rgba[0, :]) return rgba diff --git a/chaco/color_spaces.py b/chaco/color_spaces.py index ac8262a2e..053102688 100644 --- a/chaco/color_spaces.py +++ b/chaco/color_spaces.py @@ -17,8 +17,9 @@ #### Utilities ################################################################ + def convert(matrix, TTT, axis=-1): - """ Apply linear matrix transformation to an array of color triples. + """Apply linear matrix transformation to an array of color triples. Parameters ---------- @@ -35,19 +36,19 @@ def convert(matrix, TTT, axis=-1): The transformed colors. """ TTT = np.asarray(TTT) - if (axis != 0): + if axis != 0: TTT = np.swapaxes(TTT, 0, axis) oldshape = TTT.shape TTT = np.reshape(TTT, (3, -1)) OUT = np.dot(matrix, TTT) OUT.shape = oldshape - if (axis != 0): + if axis != 0: OUT = np.swapaxes(OUT, axis, 0) return OUT def makeslices(n): - """ Return a list of `n` slice objects. + """Return a list of `n` slice objects. Each slice object corresponds to [:] without arguments. """ @@ -56,7 +57,7 @@ def makeslices(n): def separate_colors(xyz, axis=-1): - """ Separate an array of color triples into three arrays, one for + """Separate an array of color triples into three arrays, one for each color axis. Parameters @@ -89,8 +90,7 @@ def separate_colors(xyz, axis=-1): def join_colors(c1, c2, c3, axis): - """ Rejoin the separated colors into a single array. - """ + """Rejoin the separated colors into a single array.""" c1 = np.asarray(c1) c2 = np.asarray(c2) c3 = np.asarray(c3) @@ -100,40 +100,45 @@ def join_colors(c1, c2, c3, axis): def triwhite(x, y): - """ Convert x,y chromaticity coordinates to XYZ tristimulus values. - """ + """Convert x,y chromaticity coordinates to XYZ tristimulus values.""" X = x / y Y = 1.0 - Z = (1-x-y)/y + Z = (1 - x - y) / y return [X, Y, Z] + #### Data ##################################################################### # From the sRGB specification. -xyz_from_rgb = np.array([[0.412453, 0.357580, 0.180423], - [0.212671, 0.715160, 0.072169], - [0.019334, 0.119193, 0.950227]]) +xyz_from_rgb = np.array( + [ + [0.412453, 0.357580, 0.180423], + [0.212671, 0.715160, 0.072169], + [0.019334, 0.119193, 0.950227], + ] +) rgb_from_xyz = inv(xyz_from_rgb) # XYZ white-point coordinates # from http://en.wikipedia.org/wiki/Standard_illuminant whitepoints = { - 'CIE A': ['Normal incandescent', triwhite(0.44757, 0.40745)], - 'CIE B': ['Direct sunlight', triwhite(0.34842, 0.35161)], - 'CIE C': ['Average sunlight', triwhite(0.31006, 0.31616)], - 'CIE E': ['Normalized reference', triwhite(1.0/3, 1.0/3)], - 'D50': ['Bright tungsten', triwhite(0.34567, 0.35850)], - 'D55': ['Cloudy daylight', triwhite(0.33242, 0.34743)], - 'D65': ['Daylight', triwhite(0.31271, 0.32902)], - 'D75': ['?', triwhite(0.29902, 0.31485)], + "CIE A": ["Normal incandescent", triwhite(0.44757, 0.40745)], + "CIE B": ["Direct sunlight", triwhite(0.34842, 0.35161)], + "CIE C": ["Average sunlight", triwhite(0.31006, 0.31616)], + "CIE E": ["Normalized reference", triwhite(1.0 / 3, 1.0 / 3)], + "D50": ["Bright tungsten", triwhite(0.34567, 0.35850)], + "D55": ["Cloudy daylight", triwhite(0.33242, 0.34743)], + "D65": ["Daylight", triwhite(0.31271, 0.32902)], + "D75": ["?", triwhite(0.29902, 0.31485)], } #### Conversion routines ###################################################### -def xyz2lab(xyz, axis=-1, wp=whitepoints['D65'][-1]): - """ Convert XYZ tristimulus values to CIE L*a*b*. + +def xyz2lab(xyz, axis=-1, wp=whitepoints["D65"][-1]): + """Convert XYZ tristimulus values to CIE L*a*b*. Parameters ---------- @@ -150,25 +155,23 @@ def xyz2lab(xyz, axis=-1, wp=whitepoints['D65'][-1]): The L*a*b* colors. """ x, y, z, axis = separate_colors(xyz, axis) - xn, yn, zn = x/wp[0], y/wp[1], z/wp[2] + xn, yn, zn = x / wp[0], y / wp[1], z / wp[2] def f(t): - eps = 216/24389. - kap = 24389/27. - return np.where(t > eps, - np.power(t, 1.0/3), - (kap*t + 16.0)/116) + eps = 216 / 24389.0 + kap = 24389 / 27.0 + return np.where(t > eps, np.power(t, 1.0 / 3), (kap * t + 16.0) / 116) fx, fy, fz = f(xn), f(yn), f(zn) - L = 116*fy - 16 - a = 500*(fx - fy) - b = 200*(fy - fz) + L = 116 * fy - 16 + a = 500 * (fx - fy) + b = 200 * (fy - fz) return join_colors(L, a, b, axis) -def lab2xyz(lab, axis=-1, wp=whitepoints['D65'][-1]): - """ Convert CIE L*a*b* colors to XYZ tristimulus values. +def lab2xyz(lab, axis=-1, wp=whitepoints["D65"][-1]): + """Convert CIE L*a*b* colors to XYZ tristimulus values. Parameters ---------- @@ -186,19 +189,18 @@ def lab2xyz(lab, axis=-1, wp=whitepoints['D65'][-1]): """ lab = np.asarray(lab) L, a, b, axis = separate_colors(lab, axis) - fy = (L+16)/116.0 - fz = fy - b / 200. - fx = a/500.0 + fy + fy = (L + 16) / 116.0 + fz = fy - b / 200.0 + fx = a / 500.0 + fy def finv(y): - eps3 = (216/24389.)**3 - kap = 24389/27. - return np.where(y > eps3, - np.power(y, 3), - (116*y - 16)/kap) + eps3 = (216 / 24389.0) ** 3 + kap = 24389 / 27.0 + return np.where(y > eps3, np.power(y, 3), (116 * y - 16) / kap) + xr, yr, zr = finv(fx), finv(fy), finv(fz) - return join_colors(xr*wp[0], yr*wp[1], zr*wp[2], axis) + return join_colors(xr * wp[0], yr * wp[1], zr * wp[2], axis) # RGB values that will be displayed on a screen are always nonlinear @@ -216,8 +218,9 @@ def finv(y): # Macintosh displays are usually gamma = 1.8 + def rgb2rgbp(rgb, gamma=None): - """ Convert linear RGB coordinates to nonlinear R'G'B' coordinates. + """Convert linear RGB coordinates to nonlinear R'G'B' coordinates. Parameters ---------- @@ -237,14 +240,14 @@ def rgb2rgbp(rgb, gamma=None): mask = rgb < eps rgbp = np.empty_like(rgb) rgbp[mask] = 12.92 * rgb[mask] - rgbp[~mask] = 1.055*rgb[~mask]**(1.0/2.4) - 0.055 + rgbp[~mask] = 1.055 * rgb[~mask] ** (1.0 / 2.4) - 0.055 return rgbp else: - return rgb**(1.0/gamma) + return rgb ** (1.0 / gamma) def rgbp2rgb(rgbp, gamma=None): - """ Convert nonlinear R'G'B' coordinates to linear RGB coordinates. + """Convert nonlinear R'G'B' coordinates to linear RGB coordinates. Parameters ---------- @@ -267,11 +270,11 @@ def rgbp2rgb(rgbp, gamma=None): rgb[~mask] = ((rgbp[~mask] + 0.055) / 1.055) ** 2.4 return rgb else: - return rgbp**gamma + return rgbp ** gamma def xyz2rgb(xyz, axis=-1): - """ Convert XYZ tristimulus values to linear RGB coordinates. + """Convert XYZ tristimulus values to linear RGB coordinates. Parameters ---------- @@ -289,7 +292,7 @@ def xyz2rgb(xyz, axis=-1): def rgb2xyz(rgb, axis=-1): - """ Convert linear RGB coordinates to XYZ tristimulus values. + """Convert linear RGB coordinates to XYZ tristimulus values. Parameters ---------- @@ -307,7 +310,7 @@ def rgb2xyz(rgb, axis=-1): def srgb2xyz(srgb, axis=-1): - """ Convert sR'G'B' colors to XYZ. + """Convert sR'G'B' colors to XYZ. Parameters ---------- @@ -325,7 +328,7 @@ def srgb2xyz(srgb, axis=-1): def xyz2srgb(xyz, axis=-1): - """ Convert XYZ colors to sR'G'B'. + """Convert XYZ colors to sR'G'B'. Parameters ---------- @@ -343,13 +346,12 @@ def xyz2srgb(xyz, axis=-1): def xyz2xyz(xyz): - """ Identity mapping. - """ + """Identity mapping.""" return xyz -def xyz2msh(xyz, axis=-1, wp=whitepoints['D65'][-1]): - """ Convert XYZ tristimulus values to Msh. +def xyz2msh(xyz, axis=-1, wp=whitepoints["D65"][-1]): + """Convert XYZ tristimulus values to Msh. Msh is a hemispherical coordinate system derived from L*a*b*. The origin remains the same. M is the distance from the origin. s is an @@ -375,15 +377,15 @@ def xyz2msh(xyz, axis=-1, wp=whitepoints['D65'][-1]): The Msh colors. """ L, a, b, axis = separate_colors(xyz2lab(xyz, axis=axis, wp=wp), axis) - M = np.sqrt(L*L + a*a + b*b) + M = np.sqrt(L * L + a * a + b * b) s = np.arccos(L / M) h = np.arctan2(b, a) return join_colors(M, s, h, axis) -def msh2xyz(msh, axis=-1, wp=whitepoints['D65'][-1]): - """ Convert Msh values to XYZ tristimulus values. +def msh2xyz(msh, axis=-1, wp=whitepoints["D65"][-1]): + """Convert Msh values to XYZ tristimulus values. Parameters ---------- diff --git a/chaco/colormap_generators.py b/chaco/colormap_generators.py index e8f5a9362..abb947af9 100644 --- a/chaco/colormap_generators.py +++ b/chaco/colormap_generators.py @@ -23,7 +23,7 @@ def adjust_hue(msh_sat, m_unsat): - """ Adjust the hue when interpolating to an unsaturated color. + """Adjust the hue when interpolating to an unsaturated color. Parameters ---------- @@ -41,7 +41,9 @@ def adjust_hue(msh_sat, m_unsat): if m_sat >= m_unsat: return h_sat else: - spin = s_sat * np.sqrt(m_unsat*m_unsat - m_sat*m_sat) / (m_sat * np.sin(s_sat)) + spin = ( + s_sat * np.sqrt(m_unsat * m_unsat - m_sat * m_sat) / (m_sat * np.sin(s_sat)) + ) if h_sat > -np.pi / 3: return h_sat + spin else: @@ -49,7 +51,7 @@ def adjust_hue(msh_sat, m_unsat): def generate_diverging_palette(srgb1, srgb2, n_colors=256): - """ Generate a diverging color palette with two endpoint colors. + """Generate a diverging color palette with two endpoint colors. Parameters ---------- @@ -80,27 +82,38 @@ def generate_diverging_palette(srgb1, srgb2, n_colors=256): if s2 > 0.05: hmid2 = adjust_hue((m2, s2, h2), mmid) - m_palette = np.hstack([ - half1 * mmid + (1 - half1) * m1, - half2 * m2 + (1 - half2) * mmid, - ]) - s_palette = np.hstack([ - (1 - half1) * s1, - half2 * s2, - ]) - h_palette = np.hstack([ - half1 * hmid1 + (1 - half1) * h1, - half2 * h2 + (1 - half2) * hmid2, - ]) + m_palette = np.hstack( + [ + half1 * mmid + (1 - half1) * m1, + half2 * m2 + (1 - half2) * mmid, + ] + ) + s_palette = np.hstack( + [ + (1 - half1) * s1, + half2 * s2, + ] + ) + h_palette = np.hstack( + [ + half1 * hmid1 + (1 - half1) * h1, + half2 * h2 + (1 - half2) * hmid2, + ] + ) msh_palette = np.column_stack([m_palette, s_palette, h_palette]) srgb_palette = xyz2srgb(msh2xyz(msh_palette)).clip(0.0, 1.0) return srgb_palette -def generate_cubehelix_palette(start=0.5, rot=-1.5, saturation=1.2, - lightness_range=(0.0, 1.0), gamma=1.0, - n_colors=256): - """ Generate a sequential color palette from black to white spiraling +def generate_cubehelix_palette( + start=0.5, + rot=-1.5, + saturation=1.2, + lightness_range=(0.0, 1.0), + gamma=1.0, + n_colors=256, +): + """Generate a sequential color palette from black to white spiraling through intermediate colors. Parameters @@ -124,11 +137,11 @@ def generate_cubehelix_palette(start=0.5, rot=-1.5, saturation=1.2, RGB color palette. """ x = np.linspace(lightness_range[0], lightness_range[1], n_colors) - theta = 2.0 * np.pi * (start / 3.0 + rot * x + 1.) + theta = 2.0 * np.pi * (start / 3.0 + rot * x + 1.0) x **= gamma amplitude = saturation * x * (1 - x) / 2.0 - red = x + amplitude * (-0.14861*np.cos(theta) + 1.78277*np.sin(theta)) - green = x + amplitude * (-0.29227*np.cos(theta) - 0.90649*np.sin(theta)) - blue = x + amplitude * (1.97294*np.cos(theta)) + red = x + amplitude * (-0.14861 * np.cos(theta) + 1.78277 * np.sin(theta)) + green = x + amplitude * (-0.29227 * np.cos(theta) - 0.90649 * np.sin(theta)) + blue = x + amplitude * (1.97294 * np.cos(theta)) srgb_palette = np.column_stack([red, green, blue]).clip(0.0, 1.0) return srgb_palette diff --git a/chaco/colormapped_scatterplot.py b/chaco/colormapped_scatterplot.py index acf7f5ae4..f8cf2d540 100644 --- a/chaco/colormapped_scatterplot.py +++ b/chaco/colormapped_scatterplot.py @@ -2,8 +2,19 @@ """ # Major library imports -from numpy import argsort, array, concatenate, nonzero, invert, take, \ - isnan, transpose, newaxis, zeros, ndarray +from numpy import ( + argsort, + array, + concatenate, + nonzero, + invert, + take, + isnan, + transpose, + newaxis, + zeros, + ndarray, +) # Enthought library imports from kiva.constants import STROKE @@ -18,13 +29,16 @@ class ColormappedScatterPlotView(ScatterPlotView): - """ Traits UI View for customizing a color-mapped scatter plot. - """ + """Traits UI View for customizing a color-mapped scatter plot.""" + def __init__(self): super(ColormappedScatterPlotView, self).__init__() vgroup = self.content - vgroup.content[0].content.append(Item("fill_alpha", label="Fill alpha", - editor=RangeEditor(low=0.0, high=1.0))) + vgroup.content[0].content.append( + Item( + "fill_alpha", label="Fill alpha", editor=RangeEditor(low=0.0, high=1.0) + ) + ) class ColormappedScatterPlot(ScatterPlot): @@ -74,9 +88,9 @@ class ColormappedScatterPlot(ScatterPlot): #: Traits UI View for customizing the plot. Overrides the ScatterPlot value. traits_view = ColormappedScatterPlotView() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # BaseXYPlot interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def map_screen(self, data_array): """ @@ -87,13 +101,13 @@ def map_screen(self, data_array): (index, value, color_value) array. The returned array is an Nx2 array of (x, y) tuples. """ - if len(data_array)>0: + if len(data_array) > 0: if data_array.shape[1] == 3: data_array = data_array[:, :2] return super(ColormappedScatterPlot, self).map_screen(data_array) def _draw_plot(self, gc, view_bounds=None, mode="normal"): - """ Draws the 'plot' layer. + """Draws the 'plot' layer. Overrides BaseXYPlot, which isn't really fully generic (it assumes that the output of map_screen() is sufficient to render the data). @@ -108,7 +122,7 @@ def _draw_plot(self, gc, view_bounds=None, mode="normal"): super(ColormappedScatterPlot, self)._draw_component(gc, view_bounds, mode) self.color = old_color else: - colors = self._cached_data_pts[:,2] + colors = self._cached_data_pts[:, 2] screen_pts = self.map_screen(self._cached_data_pts) pts = concatenate((screen_pts, colors[:, newaxis]), axis=1) self._render(gc, pts) @@ -136,8 +150,9 @@ def _gather_points(self): index_range_mask = self.index_mapper.range.mask_data(index) value_range_mask = self.value_mapper.range.mask_data(value) nan_mask = invert(isnan(index_mask)) & invert(isnan(value_mask)) - point_mask = index_mask & value_mask & nan_mask & \ - index_range_mask & value_range_mask + point_mask = ( + index_mask & value_mask & nan_mask & index_range_mask & value_range_mask + ) if self.color_data is not None: if self.color_data.is_masked(): @@ -153,14 +168,13 @@ def _gather_points(self): else: points = transpose(array((index, value))) - self._cached_data_pts = points[point_mask] self._cached_point_mask = point_mask self._cache_valid = True def _render(self, gc, points): - """ Actually draws the plot. + """Actually draws the plot. Overrides the ScatterPlot implementation. """ @@ -169,25 +183,25 @@ def _render(self, gc, points): return super(ColormappedScatterPlot, self)._render(gc, points) # If the GC doesn't have draw_*_at_points, then use bruteforce - if hasattr(gc, 'draw_marker_at_points') or hasattr(gc, 'draw_path_at_points'): + if hasattr(gc, "draw_marker_at_points") or hasattr(gc, "draw_path_at_points"): batch_capable = True else: batch_capable = False - if self.render_method == 'auto': + if self.render_method == "auto": method = self._calc_render_method(len(points)) else: method = self.render_method with gc: - if method == 'bruteforce' or (not batch_capable): + if method == "bruteforce" or (not batch_capable): self._render_bruteforce(gc, points) - elif method == 'banded': + elif method == "banded": self._render_banded(gc, points) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _compute_bands(self, points, smartmode=False): """ @@ -206,11 +220,11 @@ def _compute_bands(self, points, smartmode=False): # map the V values in the (x,y,v) self.data array - color_data = points[:,2] + color_data = points[:, 2] color_indices = self.color_mapper.map_index(color_data) - if smartmode and self.render_method == 'bruteforce': - pass + if smartmode and self.render_method == "bruteforce": + pass else: # shuffle_indices indicates how to sort the points in self.data # so that their color_indices are in order. We don't really care @@ -226,7 +240,9 @@ def _compute_bands(self, points, smartmode=False): # this by right-shifting the sorted_color_indices array, subtracting # it from the original, and looking for all the nonzero points. shifted = right_shift(sorted_color_indices, sorted_color_indices[0]) - start_indices = concatenate([[0], nonzero(sorted_color_indices - shifted)[0]]) + start_indices = concatenate( + [[0], nonzero(sorted_color_indices - shifted)[0]] + ) end_indices = left_shift(start_indices, len(sorted_color_indices)) # Store the shuffled indices in self._index_bands. We don't store the @@ -241,43 +257,43 @@ def _compute_bands(self, points, smartmode=False): self._cache_valid = True def _calc_render_method(self, numpoints): - """ Returns a string indicating the render method. - """ + """Returns a string indicating the render method.""" if numpoints > 1000 and isinstance(self.marker_size, float): - return 'banded' + return "banded" else: return "bruteforce" def _set_draw_info(self, gc, mode, color, outline_color=None, outline_weight=None): - """ Sets the stroke color, fill color, and line width on the graphics + """Sets the stroke color, fill color, and line width on the graphics context. """ color = tuple(color[:3]) + (self.fill_alpha,) if mode == STROKE: if outline_color is not None: - gc.set_stroke_color( color ) + gc.set_stroke_color(color) else: if outline_color is not None: - gc.set_stroke_color( outline_color ) - gc.set_fill_color( color ) + gc.set_stroke_color(outline_color) + gc.set_fill_color(color) if outline_weight is not None: gc.set_line_width(outline_weight) def _render_banded(self, gc, points): - """ Draws the points color-band by color-band. - """ + """Draws the points color-band by color-band.""" self._compute_bands(points) # Grab the XY values corresponding to each color band of points - xy_points = points[:,0:2] + xy_points = points[:, 0:2] marker = self.marker_ size = self.marker_size - assert isinstance(size, float), "Variable size markers not implemented for banded rendering" + assert isinstance( + size, float + ), "Variable size markers not implemented for banded rendering" # Set up the GC for drawing - gc.set_line_dash( None ) + gc.set_line_dash(None) if marker.draw_mode == STROKE: gc.set_line_width(self.line_width) @@ -285,25 +301,35 @@ def _render_banded(self, gc, points): cmap = self.color_mapper - if (hasattr(gc, 'draw_marker_at_points') and self.marker not in ('custom', 'circle', 'diamond')): + if hasattr(gc, "draw_marker_at_points") and self.marker not in ( + "custom", + "circle", + "diamond", + ): # This is the fastest method: we use one of the built-in markers. color_bands = cmap.color_bands # Initial setup of drawing parameters - self._set_draw_info(gc, marker.draw_mode, color_bands[0], - self.outline_color_, self.line_width) + self._set_draw_info( + gc, + marker.draw_mode, + color_bands[0], + self.outline_color_, + self.line_width, + ) index_bands = self._index_bands mode = marker.draw_mode for color_index in index_bands.keys(): self._set_draw_info(gc, mode, color_bands[color_index]) - gc.draw_marker_at_points(xy_points[index_bands[color_index]], size, marker.kiva_marker) + gc.draw_marker_at_points( + xy_points[index_bands[color_index]], size, marker.kiva_marker + ) - - elif hasattr( gc, 'draw_path_at_points' ): + elif hasattr(gc, "draw_path_at_points"): point_bands = {} for color_index, indices in self._index_bands.items(): point_bands[color_index] = xy_points[indices] # We have to construct the path for the marker. - if self.marker != 'custom': + if self.marker != "custom": path = gc.get_empty_path() # turn the class into an instance... we should make add_to_path a # class method at some point. @@ -315,20 +341,24 @@ def _render_banded(self, gc, points): color_bands = cmap.color_bands for color_index, xy in point_bands.items(): - self._set_draw_info(gc, mode, color_bands[color_index], - self.outline_color_, self.line_width) + self._set_draw_info( + gc, + mode, + color_bands[color_index], + self.outline_color_, + self.line_width, + ) gc.draw_path_at_points(xy, path, mode) else: raise RuntimeError("Batch drawing requested on non-batch-capable GC.") def _render_bruteforce(self, gc, points): - """ Draws the points, setting the stroke color for each one. - """ + """Draws the points, setting the stroke color for each one.""" x, y, colors = transpose(points) # Map the colors colors = self.color_mapper.map_screen(colors) - alphas = (zeros(len(colors))+self.fill_alpha)[:, newaxis] + alphas = (zeros(len(colors)) + self.fill_alpha)[:, newaxis] colors = concatenate((colors[:, :3], alphas), axis=1) with gc: @@ -343,19 +373,28 @@ def _render_bruteforce(self, gc, points): mode = marker_cls.draw_mode if marker_cls != "custom": - if (hasattr(gc, "draw_marker_at_points") and self.marker not in ('custom', 'circle', 'diamond')): - draw_func = lambda x, y, size: gc.draw_marker_at_points([[x,y]], size, marker_cls.kiva_marker) + if hasattr(gc, "draw_marker_at_points") and self.marker not in ( + "custom", + "circle", + "diamond", + ): + draw_func = lambda x, y, size: gc.draw_marker_at_points( + [[x, y]], size, marker_cls.kiva_marker + ) elif hasattr(gc, "draw_path_at_points"): # turn the class into an instance... we should make add_to_path a # class method at some point. m = marker_cls() + def draw_func(x, y, size): path = gc.get_empty_path() m.add_to_path(path, size) gc.draw_path_at_points([[x, y]], path, mode) + else: m = marker_cls() + def draw_func(x, y, size): gc.translate_ctm(x, y) gc.begin_path() @@ -377,10 +416,9 @@ def draw_func(x, y, size): gc.set_fill_color(colors[i]) gc.draw_path_at_points([[x[i], y[i]]], path, STROKE) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _color_data_changed(self, old, new): if old is not None: @@ -392,7 +430,7 @@ def _color_data_changed(self, old, new): def _color_mapper_changed(self, old, new): self._cache_valid = False - if hasattr(new, 'range') and new.range is None and old is not None: + if hasattr(new, "range") and new.range is None and old is not None: # Someone passed in a ColorMapper that has no range associated with # it. Use the range on the old ColorMapper. new.range = old.range @@ -400,7 +438,7 @@ def _color_mapper_changed(self, old, new): self.invalidate_draw() self.request_redraw() - @observe('color_mapper:updated') + @observe("color_mapper:updated") def _color_mapper_updated(self, event): self.invalidate_draw() self.request_redraw() diff --git a/chaco/colormapped_selection_overlay.py b/chaco/colormapped_selection_overlay.py index 718cb205f..173b5ac2f 100644 --- a/chaco/colormapped_selection_overlay.py +++ b/chaco/colormapped_selection_overlay.py @@ -12,6 +12,7 @@ from .abstract_overlay import AbstractOverlay from .colormapped_scatterplot import ColormappedScatterPlot + class ColormappedSelectionOverlay(AbstractOverlay): """ Overlays and changes a ColormappedScatterPlot to fade its non-selected @@ -35,7 +36,7 @@ class ColormappedSelectionOverlay(AbstractOverlay): unselected_outline_width = Float(0.0) #: The type of selection used by the data source. - selection_type = Enum('range', 'mask') + selection_type = Enum("range", "mask") _plot = Instance(ColormappedScatterPlot) @@ -50,7 +51,7 @@ def __init__(self, component=None, **kw): self.component = component def overlay(self, component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Implements AbstractOverlay. """ @@ -60,7 +61,7 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): plot = self.plot datasource = plot.color_data - if self.selection_type == 'range': + if self.selection_type == "range": selections = datasource.metadata["selections"] if selections is not None and len(selections) == 0: @@ -75,9 +76,9 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): data_pts = datasource.get_data() mask = (data_pts >= low) & (data_pts <= high) - elif self.selection_type == 'mask': + elif self.selection_type == "mask": mask = functools.reduce(logical_and, datasource.metadata["selection_masks"]) - if sum(mask)<2: + if sum(mask) < 2: return datasource.set_mask(mask) @@ -92,7 +93,6 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): plot.line_width = self.selected_outline_width plot._draw_plot(gc, view_bounds, mode) - # Restore the plot's previous color settings and data mask. plot.fill_alpha = self.fade_alpha plot.outline_color = fade_outline_color @@ -107,13 +107,10 @@ def _component_changed(self, old, new): self._old_alpha = new.fill_alpha self._old_outline_color = new.outline_color self._old_line_width = new.line_width - + self.datasource_change_handler( TraitChangeEvent( - object=new, - name="color_data", - old=None, - new=new.color_data + object=new, name="color_data", old=None, new=new.color_data ) ) @@ -126,23 +123,23 @@ def datasource_change_handler(self, event): new.observe(self.selection_change_handler, "metadata_changed") self.selection_change_handler( TraitChangeEvent( - object=new, - name="metadata_changed", - old=None, - new=new.metadata + object=new, name="metadata_changed", old=None, new=new.metadata ) ) def selection_change_handler(self, event): obj, name, old, new = (event.object, event.name, event.old, event.new) - if self.selection_type == 'range': - selection_key = 'selections' - elif self.selection_type == 'mask': - selection_key = 'selection_masks' + if self.selection_type == "range": + selection_key = "selections" + elif self.selection_type == "mask": + selection_key = "selection_masks" - if type(new) == dict and new.get(selection_key, None) is not None \ - and len(new[selection_key]) > 0: + if ( + type(new) == dict + and new.get(selection_key, None) is not None + and len(new[selection_key]) > 0 + ): if not self._visible: # We have a new selection, so replace the colors on the plot with the # faded alpha and colors diff --git a/chaco/contour/setup.py b/chaco/contour/setup.py index 5bb9e8cef..2f7d45f8b 100644 --- a/chaco/contour/setup.py +++ b/chaco/contour/setup.py @@ -1,17 +1,18 @@ #!/usr/bin/env python -def configuration(parent_package='',top_path=None): +def configuration(parent_package="", top_path=None): from numpy.distutils.misc_util import Configuration - config = Configuration('contour',parent_package,top_path) - numerix_info = config.get_info('numerix') + config = Configuration("contour", parent_package, top_path) - config.add_extension('contour',['*.c'],**numerix_info) - config.add_data_dir('tests') + numerix_info = config.get_info("numerix") + + config.add_extension("contour", ["*.c"], **numerix_info) + config.add_data_dir("tests") return config + if __name__ == "__main__": from numpy.distutils.core import setup - setup( - zip_safe = False, - configuration=configuration) + + setup(zip_safe=False, configuration=configuration) diff --git a/chaco/contour_line_plot.py b/chaco/contour_line_plot.py index 5f2a69534..92dff38da 100644 --- a/chaco/contour_line_plot.py +++ b/chaco/contour_line_plot.py @@ -15,15 +15,15 @@ class ContourLinePlot(BaseContourPlot): - """ Takes a value data object whose elements are scalars, and renders them + """Takes a value data object whose elements are scalars, and renders them as a contour plot. """ # TODO: Modify ImageData to explicitly support scalar value arrays - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Data-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The thickness(es) of the contour lines. #: It can be either a scalar value, valid for all contour lines, or a list @@ -41,9 +41,9 @@ class ContourLinePlot(BaseContourPlot): #: Line style for negative levels. negative_style = LineStyle("dash") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Are the cached contours valid? If False, new ones need to be computed. _contour_cache_valid = Bool(False) @@ -68,12 +68,12 @@ class ContourLinePlot(BaseContourPlot): # converted one at a time.) _style_map_trait = LineStyle - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _render(self, gc): - """ Actually draws the plot. + """Actually draws the plot. Implements the Base2DPlot interface. """ @@ -103,8 +103,7 @@ def _render(self, gc): if self.orientation == "h": strace = self.index_mapper.map_screen(trace) else: - strace = array( - self.index_mapper.map_screen(trace))[:, ::-1] + strace = array(self.index_mapper.map_screen(trace))[:, ::-1] gc.begin_path() gc.lines(strace) gc.stroke_path() @@ -143,8 +142,7 @@ def _update_levels(self): self._styles_cache_valid = False def _update_widths(self): - """ Updates the widths cache. - """ + """Updates the widths cache.""" # If we are given a single width, apply it to all levels if isinstance(self.widths, float): self._widths = [self.widths] * len(self._levels) @@ -159,8 +157,7 @@ def _update_widths(self): self._widths_cache_valid = True def _update_styles(self): - """ Updates the styles cache. - """ + """Updates the styles cache.""" # If the style type is "signed" then assign styles to levels based # on their sign if self.styles == "signed": @@ -186,9 +183,9 @@ def _update_styles(self): self._styles_cache_valid = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _widths_changed(self): if self._level_cache_valid: diff --git a/chaco/contour_poly_plot.py b/chaco/contour_poly_plot.py index 129e85fbb..b441bff60 100644 --- a/chaco/contour_poly_plot.py +++ b/chaco/contour_poly_plot.py @@ -2,7 +2,6 @@ """ - # Major library imports from numpy import array, isfinite, meshgrid, transpose @@ -15,14 +14,14 @@ class ContourPolyPlot(BaseContourPlot): - """ Contour image plot. Takes a value data object whose elements are + """Contour image plot. Takes a value data object whose elements are scalars, and renders them as a contour plot. """ # TODO: Modify ImageData to explicitly support scalar value arrays - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Are the cached contours valid? If False, new ones need to be computed. _poly_cache_valid = Bool(False) @@ -30,12 +29,12 @@ class ContourPolyPlot(BaseContourPlot): # Cached collection of traces. _cached_polys = Dict - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _render(self, gc): - """ Actually draws the plot. + """Actually draws the plot. Implements the Base2DPlot interface. """ @@ -53,16 +52,15 @@ def _render(self, gc): gc.set_line_width(0) gc.set_alpha(self.alpha) - for i in range(len(self._levels)-1): + for i in range(len(self._levels) - 1): gc.set_fill_color(self._colors[i]) gc.set_stroke_color(self._colors[i]) - key = (self._levels[i], self._levels[i+1]) + key = (self._levels[i], self._levels[i + 1]) for poly in self._cached_polys[key]: if self.orientation == "h": spoly = self.index_mapper.map_screen(poly) else: - spoly = array( - self.index_mapper.map_screen(poly))[:, ::-1] + spoly = array(self.index_mapper.map_screen(poly))[:, ::-1] gc.lines(spoly) gc.close_path() gc.draw_path() @@ -86,8 +84,8 @@ def _update_polys(self): c = Cntr(xg, yg, data, ~mask) self._cached_contours = {} - for i in range(len(self._levels)-1): - key = (self._levels[i], self._levels[i+1]) + for i in range(len(self._levels) - 1): + key = (self._levels[i], self._levels[i + 1]) self._cached_polys[key] = [] polys = c.trace(*key) for poly in polys: diff --git a/chaco/cross_plot_frame.py b/chaco/cross_plot_frame.py index 17677cc1a..da3533a20 100644 --- a/chaco/cross_plot_frame.py +++ b/chaco/cross_plot_frame.py @@ -8,7 +8,6 @@ ################################################################################# - # Enthought library imports from traits.api import Bool, Float @@ -18,7 +17,7 @@ class CrossPlotFrame(BasePlotFrame): - """ A simple, box-layout based plotframe. + """A simple, box-layout based plotframe. This class supports a central plot area with optional axes on the top, bottom, and sides. The legend can be placed to the bottom, left, right, or @@ -34,7 +33,7 @@ class CrossPlotFrame(BasePlotFrame): slot_names = ("center", "left", "right", "top", "bottom") #: Default width and height. Class attribute. - default_bounds = (500,500) + default_bounds = (500, 500) # The sizes of the various areas @@ -50,7 +49,6 @@ class CrossPlotFrame(BasePlotFrame): # Does the component need to do a layout call? _layout_needed = Bool(True) - def __init__(self, **kwtraits): bounds = kwtraits.pop("bounds", list(self.default_bounds)) @@ -76,12 +74,12 @@ def set_visible_slots(self, *names): else: self.get_slot(slot).visible = False - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Protected methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _draw_component(self, gc, view_bounds=None, mode="normal"): - """ Draws the component. + """Draws the component. This method is preserved for backwards compatibility with _old_draw(). Overrides PlotComponent. @@ -153,11 +151,11 @@ def _do_layout(self): ### Persistence ########################################################### - #_pickles = ("left_width", "right_width", "top_height", "bottom_height") + # _pickles = ("left_width", "right_width", "top_height", "bottom_height") def __getstate__(self): - state = super(CrossPlotFrame,self).__getstate__() - for key in ['_layout_needed']: + state = super(CrossPlotFrame, self).__getstate__() + for key in ["_layout_needed"]: if key in state: del state[key] diff --git a/chaco/data_frame_plot_data.py b/chaco/data_frame_plot_data.py index 59721720d..e31579760 100644 --- a/chaco/data_frame_plot_data.py +++ b/chaco/data_frame_plot_data.py @@ -9,7 +9,7 @@ class DataFramePlotData(AbstractPlotData): - """ A PlotData implementation class that handles a DataFrame. + """A PlotData implementation class that handles a DataFrame. By default, it doesn't allow its input data to be modified by downstream Chaco components or interactors. The index is available as data unless @@ -19,74 +19,74 @@ class DataFramePlotData(AbstractPlotData): """ - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Public traits - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # The DataFrame backing this object. - data_frame = Instance('pandas.core.frame.DataFrame') + data_frame = Instance("pandas.core.frame.DataFrame") # Consumers can write data to this object (overrides AbstractPlotData). writable = True - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Private traits - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- _has_index_column = Property(Bool) def _get__has_index_column(self): - return 'index' in self.data_frame.columns + return "index" in self.data_frame.columns - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractPlotData Interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def list_data(self): - """ Returns a list of the names of the columns of the DataFrame. The + """Returns a list of the names of the columns of the DataFrame. The name 'index' is added to this unless there is a column named 'index'. """ names = self.data_frame.columns.tolist() if not self._has_index_column: - names = ['index'] + names + names = ["index"] + names return names def get_data(self, name): - """ Returns the array associated with *name*. + """Returns the array associated with *name*. Implements AbstractDataSource. """ - if name == 'index' and not self._has_index_column: + if name == "index" and not self._has_index_column: return self.data_frame.index.values series = self.data_frame.get(name) return series if series is None else series.values def del_data(self, name): - """ Deletes the column specified by *name*, or raises a KeyError if + """Deletes the column specified by *name*, or raises a KeyError if the named column does not exist. """ if not self.writable: return None - if name == 'index' and not self._has_index_column: + if name == "index" and not self._has_index_column: raise KeyError("Cannot delete the index.") if name in self.data_frame.columns: del self.data_frame[name] - if name == 'index': + if name == "index": # It is impossible to remove the 'index' in the PlotData. # Removing a column named 'index' in the DataFrame means that # the DataFrame index is now the 'index' in the PlotData. Thus, # this results in a 'changed' event instead of a 'removed' # event. - self.data_changed = {'changed': [name]} + self.data_changed = {"changed": [name]} else: - self.data_changed = {'removed': [name]} + self.data_changed = {"removed": [name]} else: raise KeyError("Column '{}' does not exist.".format(name)) def set_data(self, name, new_data, generate_name=False): - """ Sets the specified index or column as the value for either the + """Sets the specified index or column as the value for either the specified name or a generated name. @@ -121,7 +121,7 @@ def set_data(self, name, new_data, generate_name=False): return name def update_data(self, *args, **kwargs): - """ Sets the specified column or index as the value for either the + """Sets the specified column or index as the value for either the specified name or a generated name. Implements AbstractPlotData's update_data() method. This method has @@ -134,39 +134,35 @@ def update_data(self, *args, **kwargs): data = dict(*args, **kwargs) event = {} for name in data: - if name == 'index' or name in self.data_frame.columns: - event.setdefault('changed', []).append(name) + if name == "index" or name in self.data_frame.columns: + event.setdefault("changed", []).append(name) else: - event.setdefault('added', []).append(name) + event.setdefault("added", []).append(name) self._update_data(data) self.data_changed = event def set_selection(self, name, selection): - """ Overrides AbstractPlotData to do nothing and not raise an error. - """ + """Overrides AbstractPlotData to do nothing and not raise an error.""" pass - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _generate_names(self, n): - """ Generate n new names - """ + """Generate n new names""" max_index = max(self._generate_indices()) names = [ - "series{0:d}".format(i) - for i in range(max_index + 1, max_index + n + 1) + "series{0:d}".format(i) for i in range(max_index + 1, max_index + n + 1) ] return names def _generate_indices(self): - """ Generator that yields all integers that match "series%d" in keys - """ + """Generator that yields all integers that match "series%d" in keys""" yield 0 # default minimum for name in self.list_data(): - if name.startswith('series'): + if name.startswith("series"): try: v = int(name[6:]) except ValueError: @@ -175,7 +171,7 @@ def _generate_indices(self): def _update_data(self, data): for name, value in data.items(): - if name == 'index' and not self._has_index_column: + if name == "index" and not self._has_index_column: self.data_frame.index = value else: self.data_frame[name] = value diff --git a/chaco/data_range_1d.py b/chaco/data_range_1d.py index cfd9f70b0..42bdade7b 100644 --- a/chaco/data_range_1d.py +++ b/chaco/data_range_1d.py @@ -9,8 +9,7 @@ from numpy import compress, inf, isinf, isnan, ndarray # Enthought library imports -from traits.api import Bool, CFloat, Enum, Float, Property, Trait, \ - Callable +from traits.api import Bool, CFloat, Enum, Float, Property, Trait, Callable # Local relative imports from .base import arg_find_runs @@ -19,8 +18,7 @@ class DataRange1D(BaseDataRange): - """ Represents a 1-D data range. - """ + """Represents a 1-D data range.""" #: The actual value of the lower bound of this range (overrides #: AbstractDataRange). To set it, use **low_setting**. @@ -35,14 +33,14 @@ class DataRange1D(BaseDataRange): #: of the data. #: * 'track': The lower bound tracks the upper bound by **tracking_amount**. #: * CFloat: An explicit value for the lower bound - low_setting = Property(Trait('auto', 'auto', 'track', CFloat)) + low_setting = Property(Trait("auto", "auto", "track", CFloat)) #: Property for the upper bound of this range (overrides AbstractDataRange). #: #: * 'auto': The upper bound is automatically set at or above the maximum #: of the data. #: * 'track': The upper bound tracks the lower bound by **tracking_amount**. #: * CFloat: An explicit value for the upper bound - high_setting = Property(Trait('auto', 'auto', 'track', CFloat)) + high_setting = Property(Trait("auto", "auto", "track", CFloat)) #: Do "auto" bounds imply an exact fit to the data? If False, #: they pad a little bit of margin on either side. @@ -75,51 +73,52 @@ class DataRange1D(BaseDataRange): #: resets to 'auto'. #: * 'low_track': The low bound resets to 'track', and the high bound #: resets to 'auto'. - default_state = Enum('auto', 'high_track', 'low_track') + default_state = Enum("auto", "high_track", "low_track") #: FIXME: this attribute is not used anywhere, is it safe to remove it? #: Is this range dependent upon another range? fit_to_subset = Bool(False) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The "_setting" attributes correspond to what the user has "set"; the # "_value" attributes are the actual numerical values for the given # setting. # The user-specified low setting. - _low_setting = Trait('auto', 'auto', 'track', CFloat) + _low_setting = Trait("auto", "auto", "track", CFloat) # The actual numerical value for the low setting. _low_value = CFloat(-inf) # The user-specified high setting. - _high_setting = Trait('auto', 'auto', 'track', CFloat) + _high_setting = Trait("auto", "auto", "track", CFloat) # The actual numerical value for the high setting. _high_value = CFloat(inf) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractRange interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def clip_data(self, data): - """ Returns a list of data values that are within the range. + """Returns a list of data values that are within the range. Implements AbstractDataRange. """ return compress(self.mask_data(data), data) def mask_data(self, data): - """ Returns a mask array, indicating whether values in the given array + """Returns a mask array, indicating whether values in the given array are inside the range. Implements AbstractDataRange. """ - return ((data.view(ndarray) >= self._low_value) & - (data.view(ndarray) <= self._high_value)) + return (data.view(ndarray) >= self._low_value) & ( + data.view(ndarray) <= self._high_value + ) def bound_data(self, data): - """ Returns a tuple of indices for the start and end of the first run + """Returns a tuple of indices for the start and end of the first run of *data* that falls within the range. Implements AbstractDataRange. @@ -135,11 +134,11 @@ def bound_data(self, data): return (0, 0) def set_bounds(self, low, high): - """ Sets all the bounds of the range simultaneously. + """Sets all the bounds of the range simultaneously. Implements AbstractDataRange. """ - if low == 'track': + if low == "track": # Set the high setting first result_high = self._do_set_high_setting(high, fire_event=False) result_low = self._do_set_low_setting(low, fire_event=False) @@ -153,57 +152,54 @@ def set_bounds(self, low, high): self.updated = result def scale_tracking_amount(self, multiplier): - """ Sets the **tracking_amount** to a new value, scaled by *multiplier*. - """ + """Sets the **tracking_amount** to a new value, scaled by *multiplier*.""" self.tracking_amount = self.tracking_amount * multiplier self._do_track() def set_tracking_amount(self, amount): - """ Sets the **tracking_amount** to a new value, *amount*. - """ + """Sets the **tracking_amount** to a new value, *amount*.""" self.tracking_amount = amount self._do_track() def set_default_tracking_amount(self, amount): - """ Sets the **default_tracking_amount** to a new value, *amount*. - """ + """Sets the **default_tracking_amount** to a new value, *amount*.""" self.default_tracking_amount = amount - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def reset(self): - """ Resets the bounds of this range, based on **default_state**. - """ + """Resets the bounds of this range, based on **default_state**.""" # need to maintain 'track' setting - if self.default_state == 'auto': - self._high_setting = 'auto' - self._low_setting = 'auto' - elif self.default_state == 'low_track': - self._high_setting = 'auto' - self._low_setting = 'track' - elif self.default_state == 'high_track': - self._high_setting = 'track' - self._low_setting = 'auto' + if self.default_state == "auto": + self._high_setting = "auto" + self._low_setting = "auto" + elif self.default_state == "low_track": + self._high_setting = "auto" + self._low_setting = "track" + elif self.default_state == "high_track": + self._high_setting = "track" + self._low_setting = "auto" self._refresh_bounds() self.tracking_amount = self.default_tracking_amount def refresh(self, event=None): - """ If any of the bounds is 'auto', this method refreshes the actual + """If any of the bounds is 'auto', this method refreshes the actual low and high values from the set of the view filters' data sources. """ - if ('auto' in (self._low_setting, self._high_setting)) or \ - ('track' in (self._low_setting, self._high_setting)): + if ("auto" in (self._low_setting, self._high_setting)) or ( + "track" in (self._low_setting, self._high_setting) + ): # If the user has hard-coded bounds, then refresh() doesn't do # anything. self._refresh_bounds() else: return - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods (getters and setters) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_low(self): return float(self._low_value) @@ -230,14 +226,13 @@ def _do_set_low_setting(self, val, fire_event=True): # If val is 'auto' or 'track', get the corresponding numerical # value. - if val == 'auto': + if val == "auto": if len(self.sources) > 0: - val = min([source.get_bounds()[0] - for source in self.sources]) + val = min([source.get_bounds()[0] for source in self.sources]) else: val = -inf - elif val == 'track': - if len(self.sources) > 0 or self._high_setting != 'auto': + elif val == "track": + if len(self.sources) > 0 or self._high_setting != "auto": val = self._high_value - self.tracking_amount else: val = -inf @@ -246,7 +241,7 @@ def _do_set_low_setting(self, val, fire_event=True): # value, there is nothing to do. if self._low_value != val: self._low_value = val - if self._high_setting == 'track': + if self._high_setting == "track": self._high_value = val + self.tracking_amount if fire_event: self.updated = (self._low_value, self._high_value) @@ -283,14 +278,13 @@ def _do_set_high_setting(self, val, fire_event=True): # If val is 'auto' or 'track', get the corresponding numerical # value. - if val == 'auto': + if val == "auto": if len(self.sources) > 0: - val = max([source.get_bounds()[1] - for source in self.sources]) + val = max([source.get_bounds()[1] for source in self.sources]) else: val = inf - elif val == 'track': - if len(self.sources) > 0 or self._low_setting != 'auto': + elif val == "track": + if len(self.sources) > 0 or self._low_setting != "auto": val = self._low_value + self.tracking_amount else: val = inf @@ -299,7 +293,7 @@ def _do_set_high_setting(self, val, fire_event=True): # value, there is nothing to do. if self._high_value != val: self._high_value = val - if self._low_setting == 'track': + if self._low_setting == "track": self._low_value = val - self.tracking_amount if fire_event: self.updated = (self._low_value, self._high_value) @@ -316,8 +310,9 @@ def _refresh_bounds(self): if len(self.sources) == 0: null_bounds = True else: - bounds_list = [source.get_bounds() for source in self.sources \ - if source.get_size() > 0] + bounds_list = [ + source.get_bounds() for source in self.sources if source.get_size() > 0 + ] if len(bounds_list) == 0: null_bounds = True @@ -326,11 +321,11 @@ def _refresh_bounds(self): # If we have no sources and our settings are "auto", then reset our # bounds to infinity; otherwise, set the _value to the corresponding # setting. - if (self._low_setting in ("auto", "track")): + if self._low_setting in ("auto", "track"): self._low_value = -inf else: self._low_value = self._low_setting - if (self._high_setting in ("auto", "track")): + if self._high_setting in ("auto", "track"): self._high_value = inf else: self._high_value = self._high_setting @@ -338,12 +333,17 @@ def _refresh_bounds(self): else: mins, maxes = zip(*bounds_list) - low_start, high_start = \ - calc_bounds(self._low_setting, self._high_setting, - mins, maxes, self.epsilon, - self.tight_bounds, margin=self.margin, - track_amount=self.tracking_amount, - bounds_func=self.bounds_func) + low_start, high_start = calc_bounds( + self._low_setting, + self._high_setting, + mins, + maxes, + self.epsilon, + self.tight_bounds, + margin=self.margin, + track_amount=self.tracking_amount, + bounds_func=self.bounds_func, + ) if (self._low_value != low_start) or (self._high_value != high_start): self._low_value = low_start @@ -352,12 +352,12 @@ def _refresh_bounds(self): def _do_track(self): changed = False - if self._low_setting == 'track': + if self._low_setting == "track": new_value = self._high_value - self.tracking_amount if self._low_value != new_value: self._low_value = new_value changed = True - elif self._high_setting == 'track': + elif self._high_setting == "track": new_value = self._low_value + self.tracking_amount if self._high_value != new_value: self._high_value = new_value @@ -365,9 +365,9 @@ def _do_track(self): if changed: self.updated = (self._low_value, self._high_value) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _sources_items_changed(self, event): self.refresh() @@ -383,18 +383,27 @@ def _sources_changed(self, old, new): for source in new: source.observe(self.refresh, "data_changed") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Serialization interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _post_load(self): self._sources_changed(None, self.sources) ###### method to calculate bounds for a given 1-dimensional set of data -def calc_bounds(low_set, high_set, mins, maxes, epsilon, tight_bounds, - margin=0.08, track_amount=0, bounds_func=None): - """ Calculates bounds for a given 1-D set of data. +def calc_bounds( + low_set, + high_set, + mins, + maxes, + epsilon, + tight_bounds, + margin=0.08, + track_amount=0, + bounds_func=None, +): + """Calculates bounds for a given 1-D set of data. Parameters ---------- @@ -430,35 +439,38 @@ def calc_bounds(low_set, high_set, mins, maxes, epsilon, tight_bounds, the method copes by setting *high_set* to 'auto', and proceeding. """ - if (low_set == 'track') and (high_set == 'track'): - high_set = 'auto' + if (low_set == "track") and (high_set == "track"): + high_set = "auto" - if low_set == 'auto': + if low_set == "auto": real_min = min(mins) - elif low_set == 'track': + elif low_set == "track": # real_max hasn't been set yet pass else: real_min = low_set - if high_set == 'auto': + if high_set == "auto": real_max = max(maxes) - elif high_set == 'track': + elif high_set == "track": # real_min has been set now real_max = real_min + track_amount else: real_max = high_set # Go back and set real_min if we need to - if low_set == 'track': + if low_set == "track": real_min = real_max - track_amount # If we're all NaNs, just return a 0,1 range if isnan(real_max) or isnan(real_min): return 0, 0 - if not isinf(real_min) and not isinf(real_max) and \ - (abs(real_max - real_min) <= abs(epsilon * real_min)): + if ( + not isinf(real_min) + and not isinf(real_max) + and (abs(real_max - real_min) <= abs(epsilon * real_min)) + ): # If we get here, then real_min and real_max are (for all # intents and purposes) identical, and so we just base # everything off of real_min. diff --git a/chaco/data_range_2d.py b/chaco/data_range_2d.py index 97ad908ad..36e148174 100644 --- a/chaco/data_range_2d.py +++ b/chaco/data_range_2d.py @@ -5,8 +5,7 @@ from numpy import compress, inf, transpose # Enthought library imports -from traits.api import Any, Bool, CFloat, Instance, Property, Trait, \ - Tuple, observe +from traits.api import Any, Bool, CFloat, Instance, Property, Trait, Tuple, observe # Local relative imports from .base_data_range import BaseDataRange @@ -14,7 +13,7 @@ class DataRange2D(BaseDataRange): - """ A range on (2-D) image data. + """A range on (2-D) image data. In a mathematically general sense, a 2-D range is an arbitrary region in the plane. Arbitrary regions are difficult to implement well, so this @@ -51,28 +50,28 @@ class supports only rectangular regions for now. #: dimension. That is, (high-low) >= epsilon * low. epsilon = Tuple(CFloat(1.0e-4), CFloat(1.0e-4)) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # DataRange1D for the x-dimension. _xrange = Instance(DataRange1D, args=()) # DataRange1D for the y-dimension. _yrange = Instance(DataRange1D, args=()) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractRange interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def clip_data(self, data): - """ Returns a list of data values that are within the range. + """Returns a list of data values that are within the range. Implements AbstractDataRange. """ return compress(self.mask_data(data), data, axis=0) def mask_data(self, data): - """ Returns a mask array, indicating whether values in the given array + """Returns a mask array, indicating whether values in the given array are inside the range. Implements AbstractDataRange. @@ -83,13 +82,13 @@ def mask_data(self, data): return x_mask & y_mask def bound_data(self, data): - """ Not implemented for this class. - """ - raise NotImplementedError("bound_data() has not been implemented " - "for 2d pointsets.") + """Not implemented for this class.""" + raise NotImplementedError( + "bound_data() has not been implemented " "for 2d pointsets." + ) def set_bounds(self, low, high): - """ Sets all the bounds of the range simultaneously. + """Sets all the bounds of the range simultaneously. Implements AbstractDataRange. @@ -103,43 +102,41 @@ def set_bounds(self, low, high): self._do_set_low_setting(low, fire_event=False) self._do_set_high_setting(high) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, *args, **kwargs): super(DataRange2D, self).__init__(*args, **kwargs) def reset(self): - """ Resets the bounds of this range. - """ - self.high_setting = ('auto', 'auto') - self.low_setting = ('auto', 'auto') + """Resets the bounds of this range.""" + self.high_setting = ("auto", "auto") + self.low_setting = ("auto", "auto") self.refresh() def refresh(self, event=None): - """ If any of the bounds is 'auto', this method refreshes the actual + """If any of the bounds is 'auto', this method refreshes the actual low and high values from the set of the view filters' data sources. """ - if 'auto' not in self.low_setting and \ - 'auto' not in self.high_setting: + if "auto" not in self.low_setting and "auto" not in self.high_setting: # If the user has hard-coded bounds, then refresh() doesn't do # anything. return else: self._refresh_bounds() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _refresh_bounds(self): self._xrange.refresh() self._yrange.refresh() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property getters and setters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_low(self): return (self._xrange.low, self._yrange.low) @@ -198,9 +195,9 @@ def _set_1d_range(self, dataname, oldrange, newrange): if newrange: newrange.add(source1d) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _sources_items_changed(self, event): for source in event.removed: diff --git a/chaco/data_view.py b/chaco/data_view.py index cb1b1a467..03a07a907 100644 --- a/chaco/data_view.py +++ b/chaco/data_view.py @@ -17,73 +17,74 @@ from .plot_containers import OverlayPlotContainer -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Define new traits to condense the definition of some convenience # properties in the Plot class -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- + def get_mapper(self, attr_name): - """ Getter function used by OrientedMapperProperty. - """ - if (attr_name,self.orientation) in [("x_mapper","h"), ("y_mapper","v")]: + """Getter function used by OrientedMapperProperty.""" + if (attr_name, self.orientation) in [("x_mapper", "h"), ("y_mapper", "v")]: return self.index_mapper else: return self.value_mapper + def set_mapper(self, attr_name, new): - """ Setter function used by OrientedMapperProperty. - """ - if (attr_name,self.orientation) in [("x_mapper","h"), ("y_mapper","v")]: + """Setter function used by OrientedMapperProperty.""" + if (attr_name, self.orientation) in [("x_mapper", "h"), ("y_mapper", "v")]: self.index_mapper = new else: self.value_mapper = new + # Property that represents a mapper for an orientation. OrientedMapperProperty = Property(get_mapper, set_mapper) def get_axis(self, attr_name): - """ Getter function used by AxisProperty. - """ - if (attr_name,self.orientation) in [("index_axis","h"), ("value_axis","v")]: + """Getter function used by AxisProperty.""" + if (attr_name, self.orientation) in [("index_axis", "h"), ("value_axis", "v")]: return self.x_axis else: return self.y_axis + def set_axis(self, attr_name, new): - """ Setter function used by AxisProperty. - """ - if (attr_name,self.orientation) in [("index_axis","h"), ("value_axis","v")]: + """Setter function used by AxisProperty.""" + if (attr_name, self.orientation) in [("index_axis", "h"), ("value_axis", "v")]: self.x_axis = new else: self.y_axis = new + # Property that represents an axis. AxisProperty = Property(get_axis, set_axis) def get_grid(self, attr_name): - """ Getter function used by GridProperty. - """ - if (attr_name,self.orientation) in [("index_grid","v"), ("value_grid","h")]: + """Getter function used by GridProperty.""" + if (attr_name, self.orientation) in [("index_grid", "v"), ("value_grid", "h")]: return self.y_grid else: return self.x_grid + def set_grid(self, attr_name, new): - """ Setter function used by GridProperty. - """ - if (attr_name,self.orientation) in [("index_grid","v"), ("value_grid","h")]: + """Setter function used by GridProperty.""" + if (attr_name, self.orientation) in [("index_grid", "v"), ("value_grid", "h")]: self.y_grid = new else: self.y_grid = new + # Property that represents a grid for a particular orientation. GridProperty = Property(get_grid, set_grid) class DataView(OverlayPlotContainer): - """ Represents a mapping from 2-D data space into 2-D screen space. + """Represents a mapping from 2-D data space into 2-D screen space. It can house renderers and other plot components, and otherwise behaves just like a normal PlotContainer. @@ -93,11 +94,10 @@ class DataView(OverlayPlotContainer): orientation = Enum("h", "v") #: The default location of the origin for new plots - default_origin = Enum("bottom left", "top left", - "bottom right", "top right") + default_origin = Enum("bottom left", "top left", "bottom right", "top right") #: The origin reported to axes, etc - origin = Property(depends_on='default_origin') + origin = Property(depends_on="default_origin") # Whether our map_screen and map_data should treat screen-space # coords as being in our coordinate space or in our contained @@ -134,9 +134,9 @@ class DataView(OverlayPlotContainer): #: to the Y-axis y_mapper = OrientedMapperProperty - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Axis and Grids - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The horizontal axis. Its position relative to the plot #: area can be "top", "bottom", or "float". The default position for a new @@ -186,9 +186,9 @@ class DataView(OverlayPlotContainer): #: or horizontal, depending on **orientation**. value_grid = GridProperty - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Appearance - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Background color (overrides Enable Component) bgcolor = "white" @@ -201,9 +201,9 @@ class DataView(OverlayPlotContainer): border_visible = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, **kwtraits): super(DataView, self).__init__(**kwtraits) @@ -215,7 +215,7 @@ def __init__(self, **kwtraits): self._update_mappers() def map_screen(self, data_array): - """ Maps an array of data points to screen space and returns an array + """Maps an array of data points to screen space and returns an array of screen space points. """ # data_array is Nx2 array @@ -225,24 +225,23 @@ def map_screen(self, data_array): sx = self.index_mapper.map_screen(x_ary) sy = self.value_mapper.map_screen(y_ary) if self.orientation == "h": - return transpose(array((sx,sy))) + return transpose(array((sx, sy))) else: - return transpose(array((sy,sx))) + return transpose(array((sy, sx))) def map_data(self, screen_pt): - """ Maps a screen space point into the 2D data space of this plot. + """Maps a screen space point into the 2D data space of this plot. (Note that this differs from the BaseXYPlot implementation, which by default only maps into the 1D index space.) """ # At some point it would be good to change the DataView to use # the GridMapper, and then use its map_data() method. x, y = screen_pt - return array((self.index_mapper.map_data(x), - self.value_mapper.map_data(y))) + return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _init_components(self): # Since this is called after the HasTraits constructor, we have to make @@ -268,30 +267,40 @@ def _init_components(self): # make sure the grid and bgcolor are not the same color - grid_color = 'lightgray' + grid_color = "lightgray" if color_table[self.bgcolor] == color_table[grid_color]: - grid_color = 'white' + grid_color = "white" if not self.x_grid and self.auto_grid: - self.x_grid = PlotGrid(mapper=self.x_mapper, orientation="vertical", - line_color=grid_color, line_style="dot", - component=self) + self.x_grid = PlotGrid( + mapper=self.x_mapper, + orientation="vertical", + line_color=grid_color, + line_style="dot", + component=self, + ) if not self.y_grid and self.auto_grid: - self.y_grid = PlotGrid(mapper=self.y_mapper, orientation="horizontal", - line_color=grid_color, line_style="dot", - component=self) + self.y_grid = PlotGrid( + mapper=self.y_mapper, + orientation="horizontal", + line_color=grid_color, + line_style="dot", + component=self, + ) if not self.x_axis and self.auto_axis: - self.x_axis = PlotAxis(mapper=self.x_mapper, orientation="bottom", - component=self) + self.x_axis = PlotAxis( + mapper=self.x_mapper, orientation="bottom", component=self + ) if not self.y_axis and self.auto_axis: - self.y_axis = PlotAxis(mapper=self.y_mapper, orientation="left", - component=self) + self.y_axis = PlotAxis( + mapper=self.y_mapper, orientation="left", component=self + ) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Event handlers - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- def _update_mappers(self): @@ -421,24 +430,23 @@ def _range2d_changed(self, old, new): if new is not None: new.add(datasource) for renderer in self.components: - if hasattr(renderer, 'range2d'): + if hasattr(renderer, "range2d"): renderer.range2d = new elif isinstance(renderer, Base2DPlot): renderer.index_range = new else: - if hasattr(renderer, 'index_range'): - setattr(renderer, 'index_range', self.index_range) - if hasattr(renderer, 'value_range'): - setattr(renderer, 'value_range', self.value_range) + if hasattr(renderer, "index_range"): + setattr(renderer, "index_range", self.index_range) + if hasattr(renderer, "value_range"): + setattr(renderer, "value_range", self.value_range) def _range2d_default(self): """ Default trait initializer for the range2d trait """ return DataRange2D() - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property getters and setters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_index_range(self): return self.range2d.x_range @@ -455,7 +463,7 @@ def _set_value_range(self, newrange): self.range2d.y_range = newrange def _handle_range_changed(self, name, old, new): - mapper = getattr(self, name+"_mapper") + mapper = getattr(self, name + "_mapper") if mapper.range == old: mapper.range = new if old is not None: @@ -471,5 +479,3 @@ def _handle_range_changed(self, name, old, new): def _get_origin(self): # FIXME: return self.default_origin - - diff --git a/chaco/default_colormaps.py b/chaco/default_colormaps.py index d4bdf323b..426675b9b 100644 --- a/chaco/default_colormaps.py +++ b/chaco/default_colormaps.py @@ -1,4 +1,4 @@ -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Copyright (c) 2005-2014, Enthought, Inc. # All rights reserved. # @@ -11,7 +11,7 @@ # Portions of this software are: # Copyright (c) 2002-2004 John D. Hunter # All Rights Reserved. -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ """ A collection of pre-defined colormap generator functions. @@ -26,18 +26,23 @@ # Local imports. from .color_mapper import ColorMapper from .discrete_color_mapper import DiscreteColorMapper -from .colormap_generators import generate_cubehelix_palette, \ - generate_diverging_palette +from .colormap_generators import generate_cubehelix_palette, generate_diverging_palette # The colormaps will be added to this at the end of the file. -__all__ = ['reverse', 'center', 'color_map_functions', 'color_map_dict', - 'color_map_name_dict'] +__all__ = [ + "reverse", + "center", + "color_map_functions", + "color_map_dict", + "color_map_name_dict", +] # Utility functions. + def reverse(func): - """ Modify a colormap factory to reverse the color sequence + """Modify a colormap factory to reverse the color sequence Parameters ---------- @@ -50,21 +55,23 @@ def reverse(func): A wrapper factory function that can be used in place of the original factory function. """ + def cmap(range, **traits): cm = func(range, **traits) cm.reverse_colormap() return cm # Look a little like the wrapped function. - cmap.__name__ = 'reversed_' + func.__name__ + cmap.__name__ = "reversed_" + func.__name__ if func.__doc__ is not None: - cmap.__doc__ = 'Reversed: ' + func.__doc__ + cmap.__doc__ = "Reversed: " + func.__doc__ else: - cmap.__doc__ = 'Reversed: ' + func.__name__ + cmap.__doc__ = "Reversed: " + func.__name__ return cmap + def center(func, center=0.0): - """ Modify the range of a colormap to be centered around the given value. + """Modify the range of a colormap to be centered around the given value. For example, when passed a DataRange1D(low=-0.5, high=1.0), a colormap would usually have its lowest color at -0.5 and its highest at 1.0. Some colormaps @@ -85,6 +92,7 @@ def center(func, center=0.0): A wrapper factory function that can be used in place of the original factory function. """ + def cmap(range, **traits): maxdev = max(abs(range.low - center), abs(range.high - center)) range = range.clone_traits() @@ -93,15 +101,16 @@ def cmap(range, **traits): return func(range, **traits) # Look a little like the wrapped function. - cmap.__name__ = 'centered_' + func.__name__ + cmap.__name__ = "centered_" + func.__name__ if func.__doc__ is not None: - cmap.__doc__ = 'Centered: ' + func.__doc__ + cmap.__doc__ = "Centered: " + func.__doc__ else: - cmap.__doc__ = 'Centered: ' + func.__name__ + cmap.__doc__ = "Centered: " + func.__name__ return cmap + def fix(func, range): - """ Apply the given range to a colormap rather than accept the one coming + """Apply the given range to a colormap rather than accept the one coming from the data. This is useful for colormaps intrinsically tied to a given scale, like @@ -124,6 +133,7 @@ def fix(func, range): if isinstance(range, tuple): # Adapt tuples to DataRange1D for convenience. from chaco.data_range_1d import DataRange1D + range = DataRange1D(low=range[0], high=range[1]) def cmap(dummy_range, **traits): @@ -131,11 +141,11 @@ def cmap(dummy_range, **traits): return func(range, **traits) # Look a little like the wrapped function. - cmap.__name__ = 'fixed_' + func.__name__ + cmap.__name__ = "fixed_" + func.__name__ if func.__doc__ is not None: - cmap.__doc__ = 'Fixed: ' + func.__doc__ + cmap.__doc__ = "Fixed: " + func.__doc__ else: - cmap.__doc__ = 'Fixed: ' + func.__name__ + cmap.__doc__ = "Fixed: " + func.__name__ return cmap @@ -145,9 +155,11 @@ def cmap(dummy_range, **traits): def autumn(range, **traits): """ Generator function for the 'autumn' colormap. """ - _data = {'red': ((0., 1.0, 1.0),(1.0, 1.0, 1.0)), - 'green': ((0., 0., 0.),(1.0, 1.0, 1.0)), - 'blue': ((0., 0., 0.),(1.0, 0., 0.))} + _data = { + "red": ((0.0, 1.0, 1.0), (1.0, 1.0, 1.0)), + "green": ((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)), + "blue": ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) @@ -155,9 +167,11 @@ def autumn(range, **traits): def binary(range, **traits): """ Generator function for the 'binary' colormap. """ - _data = {'red': [(0., 1.0, 1.0), (1.0, 0.0, 0.0)], - 'green': [(0., 1.0, 1.0), (1.0, 0.0, 0.0)], - 'blue': [(0., 1.0, 1.0), (1.0, 0.0, 0.0)]} + _data = { + "red": [(0.0, 1.0, 1.0), (1.0, 0.0, 0.0)], + "green": [(0.0, 1.0, 1.0), (1.0, 0.0, 0.0)], + "blue": [(0.0, 1.0, 1.0), (1.0, 0.0, 0.0)], + } return ColorMapper.from_segment_map(_data, range=range, **traits) @@ -165,154 +179,269 @@ def binary(range, **traits): def bone(range, **traits): """ Generator function for the 'bone' colormap. """ - _data = {'red': ((0., 0., 0.), (0.746032, 0.652778, 0.652778), (1.0, 1.0, 1.0)), - 'green': ((0., 0., 0.), (0.365079, 0.319444, 0.319444), (0.746032, 0.777778, 0.777778), (1.0, 1.0, 1.0)), - 'blue': ((0., 0., 0.), (0.365079, 0.444444, 0.444444), (1.0, 1.0, 1.0))} + _data = { + "red": ((0.0, 0.0, 0.0), (0.746032, 0.652778, 0.652778), (1.0, 1.0, 1.0)), + "green": ( + (0.0, 0.0, 0.0), + (0.365079, 0.319444, 0.319444), + (0.746032, 0.777778, 0.777778), + (1.0, 1.0, 1.0), + ), + "blue": ((0.0, 0.0, 0.0), (0.365079, 0.444444, 0.444444), (1.0, 1.0, 1.0)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def cool(range, **traits): """ Generator function for the 'cool' colormap. """ - _data = {'red': ((0., 0., 0.), (1.0, 1.0, 1.0)), - 'green': ((0., 1., 1.), (1.0, 0., 0.)), - 'blue': ((0., 1., 1.), (1.0, 1., 1.))} + _data = { + "red": ((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)), + "green": ((0.0, 1.0, 1.0), (1.0, 0.0, 0.0)), + "blue": ((0.0, 1.0, 1.0), (1.0, 1.0, 1.0)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def copper(range, **traits): """ Generator function for the 'copper' colormap. """ - _data = {'red': ((0., 0., 0.),(0.809524, 1.000000, 1.000000),(1.0, 1.0, 1.0)), - 'green': ((0., 0., 0.),(1.0, 0.7812, 0.7812)), - 'blue': ((0., 0., 0.),(1.0, 0.4975, 0.4975))} + _data = { + "red": ((0.0, 0.0, 0.0), (0.809524, 1.000000, 1.000000), (1.0, 1.0, 1.0)), + "green": ((0.0, 0.0, 0.0), (1.0, 0.7812, 0.7812)), + "blue": ((0.0, 0.0, 0.0), (1.0, 0.4975, 0.4975)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def flag(range, **traits): """ Generator function for the 'flag' colormap. """ - _data = {'red': ((0., 1., 1.),(0.015873, 1.000000, 1.000000), - (0.031746, 0.000000, 0.000000),(0.047619, 0.000000, 0.000000), - (0.063492, 1.000000, 1.000000),(0.079365, 1.000000, 1.000000), - (0.095238, 0.000000, 0.000000),(0.111111, 0.000000, 0.000000), - (0.126984, 1.000000, 1.000000),(0.142857, 1.000000, 1.000000), - (0.158730, 0.000000, 0.000000),(0.174603, 0.000000, 0.000000), - (0.190476, 1.000000, 1.000000),(0.206349, 1.000000, 1.000000), - (0.222222, 0.000000, 0.000000),(0.238095, 0.000000, 0.000000), - (0.253968, 1.000000, 1.000000),(0.269841, 1.000000, 1.000000), - (0.285714, 0.000000, 0.000000),(0.301587, 0.000000, 0.000000), - (0.317460, 1.000000, 1.000000),(0.333333, 1.000000, 1.000000), - (0.349206, 0.000000, 0.000000),(0.365079, 0.000000, 0.000000), - (0.380952, 1.000000, 1.000000),(0.396825, 1.000000, 1.000000), - (0.412698, 0.000000, 0.000000),(0.428571, 0.000000, 0.000000), - (0.444444, 1.000000, 1.000000),(0.460317, 1.000000, 1.000000), - (0.476190, 0.000000, 0.000000),(0.492063, 0.000000, 0.000000), - (0.507937, 1.000000, 1.000000),(0.523810, 1.000000, 1.000000), - (0.539683, 0.000000, 0.000000),(0.555556, 0.000000, 0.000000), - (0.571429, 1.000000, 1.000000),(0.587302, 1.000000, 1.000000), - (0.603175, 0.000000, 0.000000),(0.619048, 0.000000, 0.000000), - (0.634921, 1.000000, 1.000000),(0.650794, 1.000000, 1.000000), - (0.666667, 0.000000, 0.000000),(0.682540, 0.000000, 0.000000), - (0.698413, 1.000000, 1.000000),(0.714286, 1.000000, 1.000000), - (0.730159, 0.000000, 0.000000),(0.746032, 0.000000, 0.000000), - (0.761905, 1.000000, 1.000000),(0.777778, 1.000000, 1.000000), - (0.793651, 0.000000, 0.000000),(0.809524, 0.000000, 0.000000), - (0.825397, 1.000000, 1.000000),(0.841270, 1.000000, 1.000000), - (0.857143, 0.000000, 0.000000),(0.873016, 0.000000, 0.000000), - (0.888889, 1.000000, 1.000000),(0.904762, 1.000000, 1.000000), - (0.920635, 0.000000, 0.000000),(0.936508, 0.000000, 0.000000), - (0.952381, 1.000000, 1.000000),(0.968254, 1.000000, 1.000000), - (0.984127, 0.000000, 0.000000),(1.0, 0., 0.)), - 'green': ((0., 0., 0.),(0.015873, 1.000000, 1.000000), - (0.031746, 0.000000, 0.000000),(0.063492, 0.000000, 0.000000), - (0.079365, 1.000000, 1.000000),(0.095238, 0.000000, 0.000000), - (0.126984, 0.000000, 0.000000),(0.142857, 1.000000, 1.000000), - (0.158730, 0.000000, 0.000000),(0.190476, 0.000000, 0.000000), - (0.206349, 1.000000, 1.000000),(0.222222, 0.000000, 0.000000), - (0.253968, 0.000000, 0.000000),(0.269841, 1.000000, 1.000000), - (0.285714, 0.000000, 0.000000),(0.317460, 0.000000, 0.000000), - (0.333333, 1.000000, 1.000000),(0.349206, 0.000000, 0.000000), - (0.380952, 0.000000, 0.000000),(0.396825, 1.000000, 1.000000), - (0.412698, 0.000000, 0.000000),(0.444444, 0.000000, 0.000000), - (0.460317, 1.000000, 1.000000),(0.476190, 0.000000, 0.000000), - (0.507937, 0.000000, 0.000000),(0.523810, 1.000000, 1.000000), - (0.539683, 0.000000, 0.000000),(0.571429, 0.000000, 0.000000), - (0.587302, 1.000000, 1.000000),(0.603175, 0.000000, 0.000000), - (0.634921, 0.000000, 0.000000),(0.650794, 1.000000, 1.000000), - (0.666667, 0.000000, 0.000000),(0.698413, 0.000000, 0.000000), - (0.714286, 1.000000, 1.000000),(0.730159, 0.000000, 0.000000), - (0.761905, 0.000000, 0.000000),(0.777778, 1.000000, 1.000000), - (0.793651, 0.000000, 0.000000),(0.825397, 0.000000, 0.000000), - (0.841270, 1.000000, 1.000000),(0.857143, 0.000000, 0.000000), - (0.888889, 0.000000, 0.000000),(0.904762, 1.000000, 1.000000), - (0.920635, 0.000000, 0.000000),(0.952381, 0.000000, 0.000000), - (0.968254, 1.000000, 1.000000),(0.984127, 0.000000, 0.000000), - (1.0, 0., 0.)), - 'blue': ((0., 0., 0.),(0.015873, 1.000000, 1.000000), - (0.031746, 1.000000, 1.000000),(0.047619, 0.000000, 0.000000), - (0.063492, 0.000000, 0.000000),(0.079365, 1.000000, 1.000000), - (0.095238, 1.000000, 1.000000),(0.111111, 0.000000, 0.000000), - (0.126984, 0.000000, 0.000000),(0.142857, 1.000000, 1.000000), - (0.158730, 1.000000, 1.000000),(0.174603, 0.000000, 0.000000), - (0.190476, 0.000000, 0.000000),(0.206349, 1.000000, 1.000000), - (0.222222, 1.000000, 1.000000),(0.238095, 0.000000, 0.000000), - (0.253968, 0.000000, 0.000000),(0.269841, 1.000000, 1.000000), - (0.285714, 1.000000, 1.000000),(0.301587, 0.000000, 0.000000), - (0.317460, 0.000000, 0.000000),(0.333333, 1.000000, 1.000000), - (0.349206, 1.000000, 1.000000),(0.365079, 0.000000, 0.000000), - (0.380952, 0.000000, 0.000000),(0.396825, 1.000000, 1.000000), - (0.412698, 1.000000, 1.000000),(0.428571, 0.000000, 0.000000), - (0.444444, 0.000000, 0.000000),(0.460317, 1.000000, 1.000000), - (0.476190, 1.000000, 1.000000),(0.492063, 0.000000, 0.000000), - (0.507937, 0.000000, 0.000000),(0.523810, 1.000000, 1.000000), - (0.539683, 1.000000, 1.000000),(0.555556, 0.000000, 0.000000), - (0.571429, 0.000000, 0.000000),(0.587302, 1.000000, 1.000000), - (0.603175, 1.000000, 1.000000),(0.619048, 0.000000, 0.000000), - (0.634921, 0.000000, 0.000000),(0.650794, 1.000000, 1.000000), - (0.666667, 1.000000, 1.000000),(0.682540, 0.000000, 0.000000), - (0.698413, 0.000000, 0.000000),(0.714286, 1.000000, 1.000000), - (0.730159, 1.000000, 1.000000),(0.746032, 0.000000, 0.000000), - (0.761905, 0.000000, 0.000000),(0.777778, 1.000000, 1.000000), - (0.793651, 1.000000, 1.000000),(0.809524, 0.000000, 0.000000), - (0.825397, 0.000000, 0.000000),(0.841270, 1.000000, 1.000000), - (0.857143, 1.000000, 1.000000),(0.873016, 0.000000, 0.000000), - (0.888889, 0.000000, 0.000000),(0.904762, 1.000000, 1.000000), - (0.920635, 1.000000, 1.000000),(0.936508, 0.000000, 0.000000), - (0.952381, 0.000000, 0.000000),(0.968254, 1.000000, 1.000000), - (0.984127, 1.000000, 1.000000),(1.0, 0., 0.))} + _data = { + "red": ( + (0.0, 1.0, 1.0), + (0.015873, 1.000000, 1.000000), + (0.031746, 0.000000, 0.000000), + (0.047619, 0.000000, 0.000000), + (0.063492, 1.000000, 1.000000), + (0.079365, 1.000000, 1.000000), + (0.095238, 0.000000, 0.000000), + (0.111111, 0.000000, 0.000000), + (0.126984, 1.000000, 1.000000), + (0.142857, 1.000000, 1.000000), + (0.158730, 0.000000, 0.000000), + (0.174603, 0.000000, 0.000000), + (0.190476, 1.000000, 1.000000), + (0.206349, 1.000000, 1.000000), + (0.222222, 0.000000, 0.000000), + (0.238095, 0.000000, 0.000000), + (0.253968, 1.000000, 1.000000), + (0.269841, 1.000000, 1.000000), + (0.285714, 0.000000, 0.000000), + (0.301587, 0.000000, 0.000000), + (0.317460, 1.000000, 1.000000), + (0.333333, 1.000000, 1.000000), + (0.349206, 0.000000, 0.000000), + (0.365079, 0.000000, 0.000000), + (0.380952, 1.000000, 1.000000), + (0.396825, 1.000000, 1.000000), + (0.412698, 0.000000, 0.000000), + (0.428571, 0.000000, 0.000000), + (0.444444, 1.000000, 1.000000), + (0.460317, 1.000000, 1.000000), + (0.476190, 0.000000, 0.000000), + (0.492063, 0.000000, 0.000000), + (0.507937, 1.000000, 1.000000), + (0.523810, 1.000000, 1.000000), + (0.539683, 0.000000, 0.000000), + (0.555556, 0.000000, 0.000000), + (0.571429, 1.000000, 1.000000), + (0.587302, 1.000000, 1.000000), + (0.603175, 0.000000, 0.000000), + (0.619048, 0.000000, 0.000000), + (0.634921, 1.000000, 1.000000), + (0.650794, 1.000000, 1.000000), + (0.666667, 0.000000, 0.000000), + (0.682540, 0.000000, 0.000000), + (0.698413, 1.000000, 1.000000), + (0.714286, 1.000000, 1.000000), + (0.730159, 0.000000, 0.000000), + (0.746032, 0.000000, 0.000000), + (0.761905, 1.000000, 1.000000), + (0.777778, 1.000000, 1.000000), + (0.793651, 0.000000, 0.000000), + (0.809524, 0.000000, 0.000000), + (0.825397, 1.000000, 1.000000), + (0.841270, 1.000000, 1.000000), + (0.857143, 0.000000, 0.000000), + (0.873016, 0.000000, 0.000000), + (0.888889, 1.000000, 1.000000), + (0.904762, 1.000000, 1.000000), + (0.920635, 0.000000, 0.000000), + (0.936508, 0.000000, 0.000000), + (0.952381, 1.000000, 1.000000), + (0.968254, 1.000000, 1.000000), + (0.984127, 0.000000, 0.000000), + (1.0, 0.0, 0.0), + ), + "green": ( + (0.0, 0.0, 0.0), + (0.015873, 1.000000, 1.000000), + (0.031746, 0.000000, 0.000000), + (0.063492, 0.000000, 0.000000), + (0.079365, 1.000000, 1.000000), + (0.095238, 0.000000, 0.000000), + (0.126984, 0.000000, 0.000000), + (0.142857, 1.000000, 1.000000), + (0.158730, 0.000000, 0.000000), + (0.190476, 0.000000, 0.000000), + (0.206349, 1.000000, 1.000000), + (0.222222, 0.000000, 0.000000), + (0.253968, 0.000000, 0.000000), + (0.269841, 1.000000, 1.000000), + (0.285714, 0.000000, 0.000000), + (0.317460, 0.000000, 0.000000), + (0.333333, 1.000000, 1.000000), + (0.349206, 0.000000, 0.000000), + (0.380952, 0.000000, 0.000000), + (0.396825, 1.000000, 1.000000), + (0.412698, 0.000000, 0.000000), + (0.444444, 0.000000, 0.000000), + (0.460317, 1.000000, 1.000000), + (0.476190, 0.000000, 0.000000), + (0.507937, 0.000000, 0.000000), + (0.523810, 1.000000, 1.000000), + (0.539683, 0.000000, 0.000000), + (0.571429, 0.000000, 0.000000), + (0.587302, 1.000000, 1.000000), + (0.603175, 0.000000, 0.000000), + (0.634921, 0.000000, 0.000000), + (0.650794, 1.000000, 1.000000), + (0.666667, 0.000000, 0.000000), + (0.698413, 0.000000, 0.000000), + (0.714286, 1.000000, 1.000000), + (0.730159, 0.000000, 0.000000), + (0.761905, 0.000000, 0.000000), + (0.777778, 1.000000, 1.000000), + (0.793651, 0.000000, 0.000000), + (0.825397, 0.000000, 0.000000), + (0.841270, 1.000000, 1.000000), + (0.857143, 0.000000, 0.000000), + (0.888889, 0.000000, 0.000000), + (0.904762, 1.000000, 1.000000), + (0.920635, 0.000000, 0.000000), + (0.952381, 0.000000, 0.000000), + (0.968254, 1.000000, 1.000000), + (0.984127, 0.000000, 0.000000), + (1.0, 0.0, 0.0), + ), + "blue": ( + (0.0, 0.0, 0.0), + (0.015873, 1.000000, 1.000000), + (0.031746, 1.000000, 1.000000), + (0.047619, 0.000000, 0.000000), + (0.063492, 0.000000, 0.000000), + (0.079365, 1.000000, 1.000000), + (0.095238, 1.000000, 1.000000), + (0.111111, 0.000000, 0.000000), + (0.126984, 0.000000, 0.000000), + (0.142857, 1.000000, 1.000000), + (0.158730, 1.000000, 1.000000), + (0.174603, 0.000000, 0.000000), + (0.190476, 0.000000, 0.000000), + (0.206349, 1.000000, 1.000000), + (0.222222, 1.000000, 1.000000), + (0.238095, 0.000000, 0.000000), + (0.253968, 0.000000, 0.000000), + (0.269841, 1.000000, 1.000000), + (0.285714, 1.000000, 1.000000), + (0.301587, 0.000000, 0.000000), + (0.317460, 0.000000, 0.000000), + (0.333333, 1.000000, 1.000000), + (0.349206, 1.000000, 1.000000), + (0.365079, 0.000000, 0.000000), + (0.380952, 0.000000, 0.000000), + (0.396825, 1.000000, 1.000000), + (0.412698, 1.000000, 1.000000), + (0.428571, 0.000000, 0.000000), + (0.444444, 0.000000, 0.000000), + (0.460317, 1.000000, 1.000000), + (0.476190, 1.000000, 1.000000), + (0.492063, 0.000000, 0.000000), + (0.507937, 0.000000, 0.000000), + (0.523810, 1.000000, 1.000000), + (0.539683, 1.000000, 1.000000), + (0.555556, 0.000000, 0.000000), + (0.571429, 0.000000, 0.000000), + (0.587302, 1.000000, 1.000000), + (0.603175, 1.000000, 1.000000), + (0.619048, 0.000000, 0.000000), + (0.634921, 0.000000, 0.000000), + (0.650794, 1.000000, 1.000000), + (0.666667, 1.000000, 1.000000), + (0.682540, 0.000000, 0.000000), + (0.698413, 0.000000, 0.000000), + (0.714286, 1.000000, 1.000000), + (0.730159, 1.000000, 1.000000), + (0.746032, 0.000000, 0.000000), + (0.761905, 0.000000, 0.000000), + (0.777778, 1.000000, 1.000000), + (0.793651, 1.000000, 1.000000), + (0.809524, 0.000000, 0.000000), + (0.825397, 0.000000, 0.000000), + (0.841270, 1.000000, 1.000000), + (0.857143, 1.000000, 1.000000), + (0.873016, 0.000000, 0.000000), + (0.888889, 0.000000, 0.000000), + (0.904762, 1.000000, 1.000000), + (0.920635, 1.000000, 1.000000), + (0.936508, 0.000000, 0.000000), + (0.952381, 0.000000, 0.000000), + (0.968254, 1.000000, 1.000000), + (0.984127, 1.000000, 1.000000), + (1.0, 0.0, 0.0), + ), + } return ColorMapper.from_segment_map(_data, range=range, **traits) def seismic(range, **traits): """ Generator for 'seismic' colormap from matplotlib """ - _data = [(0.0, 0.0, 0.3), (0.0, 0.0, 1.0), (1.0, 1.0, 1.0), - (1.0, 0.0, 0.0), (0.5, 0.0, 0.0)] + _data = [ + (0.0, 0.0, 0.3), + (0.0, 0.0, 1.0), + (1.0, 1.0, 1.0), + (1.0, 0.0, 0.0), + (0.5, 0.0, 0.0), + ] return ColorMapper.from_palette_array(_data, range=range, **traits) def terrain(range, **traits): """ Generator for 'terrain' colormap from matplotlib """ _data = { - 'red': [ - (0., 0.2, 0.2), + "red": [ + (0.0, 0.2, 0.2), (0.15, 0.0, 0.0), (0.25, 0.0, 0.0), (0.50, 1.0, 1.0), (0.75, 0.5, 0.5), (1.0, 1.0, 1.0), ], - 'green': [ - (0., 0.2, 0.2), + "green": [ + (0.0, 0.2, 0.2), (0.15, 0.6, 0.6), (0.25, 0.8, 0.8), (0.50, 1.0, 1.0), (0.75, 0.36, 0.36), (1.0, 1.0, 1.0), ], - 'blue': [ - (0., 0.6, 0.6), + "blue": [ + (0.0, 0.6, 0.6), (0.15, 1.0, 1.0), (0.25, 0.4, 0.4), (0.50, 0.6, 0.6), @@ -326,59 +455,98 @@ def terrain(range, **traits): def gray(range, **traits): """ Generator function for the 'gray' colormap. """ - _data = {'red': ((0., 0, 0), (1., 1, 1)), - 'green': ((0., 0, 0), (1., 1, 1)), - 'blue': ((0., 0, 0), (1., 1, 1))} + _data = { + "red": ((0.0, 0, 0), (1.0, 1, 1)), + "green": ((0.0, 0, 0), (1.0, 1, 1)), + "blue": ((0.0, 0, 0), (1.0, 1, 1)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def yarg(range, **traits): """ Generator function for the 'yarg' colormap. """ - _data = {'red': ((0., 1, 1), (1., 0, 0)), - 'green': ((0., 1, 1), (1., 0, 0)), - 'blue': ((0., 1, 1), (1., 0, 0))} + _data = { + "red": ((0.0, 1, 1), (1.0, 0, 0)), + "green": ((0.0, 1, 1), (1.0, 0, 0)), + "blue": ((0.0, 1, 1), (1.0, 0, 0)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def hot(range, **traits): """ Generator function for the 'hot' colormap. """ - _data = {'red': ((0., 0.0416, 0.0416),(0.365079, 1.000000, 1.000000),(1.0, 1.0, 1.0)), - 'green': ((0., 0., 0.),(0.365079, 0.000000, 0.000000), - (0.746032, 1.000000, 1.000000),(1.0, 1.0, 1.0)), - 'blue': ((0., 0., 0.),(0.746032, 0.000000, 0.000000),(1.0, 1.0, 1.0))} + _data = { + "red": ((0.0, 0.0416, 0.0416), (0.365079, 1.000000, 1.000000), (1.0, 1.0, 1.0)), + "green": ( + (0.0, 0.0, 0.0), + (0.365079, 0.000000, 0.000000), + (0.746032, 1.000000, 1.000000), + (1.0, 1.0, 1.0), + ), + "blue": ((0.0, 0.0, 0.0), (0.746032, 0.000000, 0.000000), (1.0, 1.0, 1.0)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def hsv(range, **traits): """ Generator function for the 'hsv' colormap. """ - _data = {'red': ((0., 1., 1.),(0.158730, 1.000000, 1.000000), - (0.174603, 0.968750, 0.968750),(0.333333, 0.031250, 0.031250), - (0.349206, 0.000000, 0.000000),(0.666667, 0.000000, 0.000000), - (0.682540, 0.031250, 0.031250),(0.841270, 0.968750, 0.968750), - (0.857143, 1.000000, 1.000000),(1.0, 1.0, 1.0)), - 'green': ((0., 0., 0.),(0.158730, 0.937500, 0.937500), - (0.174603, 1.000000, 1.000000),(0.507937, 1.000000, 1.000000), - (0.666667, 0.062500, 0.062500),(0.682540, 0.000000, 0.000000), - (1.0, 0., 0.)), - 'blue': ((0., 0., 0.),(0.333333, 0.000000, 0.000000), - (0.349206, 0.062500, 0.062500),(0.507937, 1.000000, 1.000000), - (0.841270, 1.000000, 1.000000),(0.857143, 0.937500, 0.937500), - (1.0, 0.09375, 0.09375))} + _data = { + "red": ( + (0.0, 1.0, 1.0), + (0.158730, 1.000000, 1.000000), + (0.174603, 0.968750, 0.968750), + (0.333333, 0.031250, 0.031250), + (0.349206, 0.000000, 0.000000), + (0.666667, 0.000000, 0.000000), + (0.682540, 0.031250, 0.031250), + (0.841270, 0.968750, 0.968750), + (0.857143, 1.000000, 1.000000), + (1.0, 1.0, 1.0), + ), + "green": ( + (0.0, 0.0, 0.0), + (0.158730, 0.937500, 0.937500), + (0.174603, 1.000000, 1.000000), + (0.507937, 1.000000, 1.000000), + (0.666667, 0.062500, 0.062500), + (0.682540, 0.000000, 0.000000), + (1.0, 0.0, 0.0), + ), + "blue": ( + (0.0, 0.0, 0.0), + (0.333333, 0.000000, 0.000000), + (0.349206, 0.062500, 0.062500), + (0.507937, 1.000000, 1.000000), + (0.841270, 1.000000, 1.000000), + (0.857143, 0.937500, 0.937500), + (1.0, 0.09375, 0.09375), + ), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def jet(range, **traits): """ Generator function for the 'jet' colormap. """ - _data = {'red': ((0., 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89,1, 1), - (1, 0.5, 0.5)), - 'green': ((0., 0, 0), (0.125,0, 0), (0.375,1, 1), (0.64,1, 1), - (0.91,0,0), (1, 0, 0)), - 'blue': ((0., 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), (0.65,0, 0), - (1, 0, 0))} + _data = { + "red": ((0.0, 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89, 1, 1), (1, 0.5, 0.5)), + "green": ( + (0.0, 0, 0), + (0.125, 0, 0), + (0.375, 1, 1), + (0.64, 1, 1), + (0.91, 0, 0), + (1, 0, 0), + ), + "blue": ((0.0, 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), (0.65, 0, 0), (1, 0, 0)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) @@ -386,269 +554,474 @@ def jet(range, **traits): def pink(range, **traits): """ Generator function for the 'pink' colormap. """ - _data = {'red': ((0., 0.1178, 0.1178),(0.015873, 0.195857, 0.195857), - (0.031746, 0.250661, 0.250661),(0.047619, 0.295468, 0.295468), - (0.063492, 0.334324, 0.334324),(0.079365, 0.369112, 0.369112), - (0.095238, 0.400892, 0.400892),(0.111111, 0.430331, 0.430331), - (0.126984, 0.457882, 0.457882),(0.142857, 0.483867, 0.483867), - (0.158730, 0.508525, 0.508525),(0.174603, 0.532042, 0.532042), - (0.190476, 0.554563, 0.554563),(0.206349, 0.576204, 0.576204), - (0.222222, 0.597061, 0.597061),(0.238095, 0.617213, 0.617213), - (0.253968, 0.636729, 0.636729),(0.269841, 0.655663, 0.655663), - (0.285714, 0.674066, 0.674066),(0.301587, 0.691980, 0.691980), - (0.317460, 0.709441, 0.709441),(0.333333, 0.726483, 0.726483), - (0.349206, 0.743134, 0.743134),(0.365079, 0.759421, 0.759421), - (0.380952, 0.766356, 0.766356),(0.396825, 0.773229, 0.773229), - (0.412698, 0.780042, 0.780042),(0.428571, 0.786796, 0.786796), - (0.444444, 0.793492, 0.793492),(0.460317, 0.800132, 0.800132), - (0.476190, 0.806718, 0.806718),(0.492063, 0.813250, 0.813250), - (0.507937, 0.819730, 0.819730),(0.523810, 0.826160, 0.826160), - (0.539683, 0.832539, 0.832539),(0.555556, 0.838870, 0.838870), - (0.571429, 0.845154, 0.845154),(0.587302, 0.851392, 0.851392), - (0.603175, 0.857584, 0.857584),(0.619048, 0.863731, 0.863731), - (0.634921, 0.869835, 0.869835),(0.650794, 0.875897, 0.875897), - (0.666667, 0.881917, 0.881917),(0.682540, 0.887896, 0.887896), - (0.698413, 0.893835, 0.893835),(0.714286, 0.899735, 0.899735), - (0.730159, 0.905597, 0.905597),(0.746032, 0.911421, 0.911421), - (0.761905, 0.917208, 0.917208),(0.777778, 0.922958, 0.922958), - (0.793651, 0.928673, 0.928673),(0.809524, 0.934353, 0.934353), - (0.825397, 0.939999, 0.939999),(0.841270, 0.945611, 0.945611), - (0.857143, 0.951190, 0.951190),(0.873016, 0.956736, 0.956736), - (0.888889, 0.962250, 0.962250),(0.904762, 0.967733, 0.967733), - (0.920635, 0.973185, 0.973185),(0.936508, 0.978607, 0.978607), - (0.952381, 0.983999, 0.983999),(0.968254, 0.989361, 0.989361), - (0.984127, 0.994695, 0.994695),(1.0, 1.0, 1.0)), - 'green': ((0., 0., 0.),(0.015873, 0.102869, 0.102869), - (0.031746, 0.145479, 0.145479),(0.047619, 0.178174, 0.178174), - (0.063492, 0.205738, 0.205738),(0.079365, 0.230022, 0.230022), - (0.095238, 0.251976, 0.251976),(0.111111, 0.272166, 0.272166), - (0.126984, 0.290957, 0.290957),(0.142857, 0.308607, 0.308607), - (0.158730, 0.325300, 0.325300),(0.174603, 0.341178, 0.341178), - (0.190476, 0.356348, 0.356348),(0.206349, 0.370899, 0.370899), - (0.222222, 0.384900, 0.384900),(0.238095, 0.398410, 0.398410), - (0.253968, 0.411476, 0.411476),(0.269841, 0.424139, 0.424139), - (0.285714, 0.436436, 0.436436),(0.301587, 0.448395, 0.448395), - (0.317460, 0.460044, 0.460044),(0.333333, 0.471405, 0.471405), - (0.349206, 0.482498, 0.482498),(0.365079, 0.493342, 0.493342), - (0.380952, 0.517549, 0.517549),(0.396825, 0.540674, 0.540674), - (0.412698, 0.562849, 0.562849),(0.428571, 0.584183, 0.584183), - (0.444444, 0.604765, 0.604765),(0.460317, 0.624669, 0.624669), - (0.476190, 0.643958, 0.643958),(0.492063, 0.662687, 0.662687), - (0.507937, 0.680900, 0.680900),(0.523810, 0.698638, 0.698638), - (0.539683, 0.715937, 0.715937),(0.555556, 0.732828, 0.732828), - (0.571429, 0.749338, 0.749338),(0.587302, 0.765493, 0.765493), - (0.603175, 0.781313, 0.781313),(0.619048, 0.796819, 0.796819), - (0.634921, 0.812029, 0.812029),(0.650794, 0.826960, 0.826960), - (0.666667, 0.841625, 0.841625),(0.682540, 0.856040, 0.856040), - (0.698413, 0.870216, 0.870216),(0.714286, 0.884164, 0.884164), - (0.730159, 0.897896, 0.897896),(0.746032, 0.911421, 0.911421), - (0.761905, 0.917208, 0.917208),(0.777778, 0.922958, 0.922958), - (0.793651, 0.928673, 0.928673),(0.809524, 0.934353, 0.934353), - (0.825397, 0.939999, 0.939999),(0.841270, 0.945611, 0.945611), - (0.857143, 0.951190, 0.951190),(0.873016, 0.956736, 0.956736), - (0.888889, 0.962250, 0.962250),(0.904762, 0.967733, 0.967733), - (0.920635, 0.973185, 0.973185),(0.936508, 0.978607, 0.978607), - (0.952381, 0.983999, 0.983999),(0.968254, 0.989361, 0.989361), - (0.984127, 0.994695, 0.994695),(1.0, 1.0, 1.0)), - 'blue': ((0., 0., 0.),(0.015873, 0.102869, 0.102869), - (0.031746, 0.145479, 0.145479),(0.047619, 0.178174, 0.178174), - (0.063492, 0.205738, 0.205738),(0.079365, 0.230022, 0.230022), - (0.095238, 0.251976, 0.251976),(0.111111, 0.272166, 0.272166), - (0.126984, 0.290957, 0.290957),(0.142857, 0.308607, 0.308607), - (0.158730, 0.325300, 0.325300),(0.174603, 0.341178, 0.341178), - (0.190476, 0.356348, 0.356348),(0.206349, 0.370899, 0.370899), - (0.222222, 0.384900, 0.384900),(0.238095, 0.398410, 0.398410), - (0.253968, 0.411476, 0.411476),(0.269841, 0.424139, 0.424139), - (0.285714, 0.436436, 0.436436),(0.301587, 0.448395, 0.448395), - (0.317460, 0.460044, 0.460044),(0.333333, 0.471405, 0.471405), - (0.349206, 0.482498, 0.482498),(0.365079, 0.493342, 0.493342), - (0.380952, 0.503953, 0.503953),(0.396825, 0.514344, 0.514344), - (0.412698, 0.524531, 0.524531),(0.428571, 0.534522, 0.534522), - (0.444444, 0.544331, 0.544331),(0.460317, 0.553966, 0.553966), - (0.476190, 0.563436, 0.563436),(0.492063, 0.572750, 0.572750), - (0.507937, 0.581914, 0.581914),(0.523810, 0.590937, 0.590937), - (0.539683, 0.599824, 0.599824),(0.555556, 0.608581, 0.608581), - (0.571429, 0.617213, 0.617213),(0.587302, 0.625727, 0.625727), - (0.603175, 0.634126, 0.634126),(0.619048, 0.642416, 0.642416), - (0.634921, 0.650600, 0.650600),(0.650794, 0.658682, 0.658682), - (0.666667, 0.666667, 0.666667),(0.682540, 0.674556, 0.674556), - (0.698413, 0.682355, 0.682355),(0.714286, 0.690066, 0.690066), - (0.730159, 0.697691, 0.697691),(0.746032, 0.705234, 0.705234), - (0.761905, 0.727166, 0.727166),(0.777778, 0.748455, 0.748455), - (0.793651, 0.769156, 0.769156),(0.809524, 0.789314, 0.789314), - (0.825397, 0.808969, 0.808969),(0.841270, 0.828159, 0.828159), - (0.857143, 0.846913, 0.846913),(0.873016, 0.865261, 0.865261), - (0.888889, 0.883229, 0.883229),(0.904762, 0.900837, 0.900837), - (0.920635, 0.918109, 0.918109),(0.936508, 0.935061, 0.935061), - (0.952381, 0.951711, 0.951711),(0.968254, 0.968075, 0.968075), - (0.984127, 0.984167, 0.984167),(1.0, 1.0, 1.0))} + _data = { + "red": ( + (0.0, 0.1178, 0.1178), + (0.015873, 0.195857, 0.195857), + (0.031746, 0.250661, 0.250661), + (0.047619, 0.295468, 0.295468), + (0.063492, 0.334324, 0.334324), + (0.079365, 0.369112, 0.369112), + (0.095238, 0.400892, 0.400892), + (0.111111, 0.430331, 0.430331), + (0.126984, 0.457882, 0.457882), + (0.142857, 0.483867, 0.483867), + (0.158730, 0.508525, 0.508525), + (0.174603, 0.532042, 0.532042), + (0.190476, 0.554563, 0.554563), + (0.206349, 0.576204, 0.576204), + (0.222222, 0.597061, 0.597061), + (0.238095, 0.617213, 0.617213), + (0.253968, 0.636729, 0.636729), + (0.269841, 0.655663, 0.655663), + (0.285714, 0.674066, 0.674066), + (0.301587, 0.691980, 0.691980), + (0.317460, 0.709441, 0.709441), + (0.333333, 0.726483, 0.726483), + (0.349206, 0.743134, 0.743134), + (0.365079, 0.759421, 0.759421), + (0.380952, 0.766356, 0.766356), + (0.396825, 0.773229, 0.773229), + (0.412698, 0.780042, 0.780042), + (0.428571, 0.786796, 0.786796), + (0.444444, 0.793492, 0.793492), + (0.460317, 0.800132, 0.800132), + (0.476190, 0.806718, 0.806718), + (0.492063, 0.813250, 0.813250), + (0.507937, 0.819730, 0.819730), + (0.523810, 0.826160, 0.826160), + (0.539683, 0.832539, 0.832539), + (0.555556, 0.838870, 0.838870), + (0.571429, 0.845154, 0.845154), + (0.587302, 0.851392, 0.851392), + (0.603175, 0.857584, 0.857584), + (0.619048, 0.863731, 0.863731), + (0.634921, 0.869835, 0.869835), + (0.650794, 0.875897, 0.875897), + (0.666667, 0.881917, 0.881917), + (0.682540, 0.887896, 0.887896), + (0.698413, 0.893835, 0.893835), + (0.714286, 0.899735, 0.899735), + (0.730159, 0.905597, 0.905597), + (0.746032, 0.911421, 0.911421), + (0.761905, 0.917208, 0.917208), + (0.777778, 0.922958, 0.922958), + (0.793651, 0.928673, 0.928673), + (0.809524, 0.934353, 0.934353), + (0.825397, 0.939999, 0.939999), + (0.841270, 0.945611, 0.945611), + (0.857143, 0.951190, 0.951190), + (0.873016, 0.956736, 0.956736), + (0.888889, 0.962250, 0.962250), + (0.904762, 0.967733, 0.967733), + (0.920635, 0.973185, 0.973185), + (0.936508, 0.978607, 0.978607), + (0.952381, 0.983999, 0.983999), + (0.968254, 0.989361, 0.989361), + (0.984127, 0.994695, 0.994695), + (1.0, 1.0, 1.0), + ), + "green": ( + (0.0, 0.0, 0.0), + (0.015873, 0.102869, 0.102869), + (0.031746, 0.145479, 0.145479), + (0.047619, 0.178174, 0.178174), + (0.063492, 0.205738, 0.205738), + (0.079365, 0.230022, 0.230022), + (0.095238, 0.251976, 0.251976), + (0.111111, 0.272166, 0.272166), + (0.126984, 0.290957, 0.290957), + (0.142857, 0.308607, 0.308607), + (0.158730, 0.325300, 0.325300), + (0.174603, 0.341178, 0.341178), + (0.190476, 0.356348, 0.356348), + (0.206349, 0.370899, 0.370899), + (0.222222, 0.384900, 0.384900), + (0.238095, 0.398410, 0.398410), + (0.253968, 0.411476, 0.411476), + (0.269841, 0.424139, 0.424139), + (0.285714, 0.436436, 0.436436), + (0.301587, 0.448395, 0.448395), + (0.317460, 0.460044, 0.460044), + (0.333333, 0.471405, 0.471405), + (0.349206, 0.482498, 0.482498), + (0.365079, 0.493342, 0.493342), + (0.380952, 0.517549, 0.517549), + (0.396825, 0.540674, 0.540674), + (0.412698, 0.562849, 0.562849), + (0.428571, 0.584183, 0.584183), + (0.444444, 0.604765, 0.604765), + (0.460317, 0.624669, 0.624669), + (0.476190, 0.643958, 0.643958), + (0.492063, 0.662687, 0.662687), + (0.507937, 0.680900, 0.680900), + (0.523810, 0.698638, 0.698638), + (0.539683, 0.715937, 0.715937), + (0.555556, 0.732828, 0.732828), + (0.571429, 0.749338, 0.749338), + (0.587302, 0.765493, 0.765493), + (0.603175, 0.781313, 0.781313), + (0.619048, 0.796819, 0.796819), + (0.634921, 0.812029, 0.812029), + (0.650794, 0.826960, 0.826960), + (0.666667, 0.841625, 0.841625), + (0.682540, 0.856040, 0.856040), + (0.698413, 0.870216, 0.870216), + (0.714286, 0.884164, 0.884164), + (0.730159, 0.897896, 0.897896), + (0.746032, 0.911421, 0.911421), + (0.761905, 0.917208, 0.917208), + (0.777778, 0.922958, 0.922958), + (0.793651, 0.928673, 0.928673), + (0.809524, 0.934353, 0.934353), + (0.825397, 0.939999, 0.939999), + (0.841270, 0.945611, 0.945611), + (0.857143, 0.951190, 0.951190), + (0.873016, 0.956736, 0.956736), + (0.888889, 0.962250, 0.962250), + (0.904762, 0.967733, 0.967733), + (0.920635, 0.973185, 0.973185), + (0.936508, 0.978607, 0.978607), + (0.952381, 0.983999, 0.983999), + (0.968254, 0.989361, 0.989361), + (0.984127, 0.994695, 0.994695), + (1.0, 1.0, 1.0), + ), + "blue": ( + (0.0, 0.0, 0.0), + (0.015873, 0.102869, 0.102869), + (0.031746, 0.145479, 0.145479), + (0.047619, 0.178174, 0.178174), + (0.063492, 0.205738, 0.205738), + (0.079365, 0.230022, 0.230022), + (0.095238, 0.251976, 0.251976), + (0.111111, 0.272166, 0.272166), + (0.126984, 0.290957, 0.290957), + (0.142857, 0.308607, 0.308607), + (0.158730, 0.325300, 0.325300), + (0.174603, 0.341178, 0.341178), + (0.190476, 0.356348, 0.356348), + (0.206349, 0.370899, 0.370899), + (0.222222, 0.384900, 0.384900), + (0.238095, 0.398410, 0.398410), + (0.253968, 0.411476, 0.411476), + (0.269841, 0.424139, 0.424139), + (0.285714, 0.436436, 0.436436), + (0.301587, 0.448395, 0.448395), + (0.317460, 0.460044, 0.460044), + (0.333333, 0.471405, 0.471405), + (0.349206, 0.482498, 0.482498), + (0.365079, 0.493342, 0.493342), + (0.380952, 0.503953, 0.503953), + (0.396825, 0.514344, 0.514344), + (0.412698, 0.524531, 0.524531), + (0.428571, 0.534522, 0.534522), + (0.444444, 0.544331, 0.544331), + (0.460317, 0.553966, 0.553966), + (0.476190, 0.563436, 0.563436), + (0.492063, 0.572750, 0.572750), + (0.507937, 0.581914, 0.581914), + (0.523810, 0.590937, 0.590937), + (0.539683, 0.599824, 0.599824), + (0.555556, 0.608581, 0.608581), + (0.571429, 0.617213, 0.617213), + (0.587302, 0.625727, 0.625727), + (0.603175, 0.634126, 0.634126), + (0.619048, 0.642416, 0.642416), + (0.634921, 0.650600, 0.650600), + (0.650794, 0.658682, 0.658682), + (0.666667, 0.666667, 0.666667), + (0.682540, 0.674556, 0.674556), + (0.698413, 0.682355, 0.682355), + (0.714286, 0.690066, 0.690066), + (0.730159, 0.697691, 0.697691), + (0.746032, 0.705234, 0.705234), + (0.761905, 0.727166, 0.727166), + (0.777778, 0.748455, 0.748455), + (0.793651, 0.769156, 0.769156), + (0.809524, 0.789314, 0.789314), + (0.825397, 0.808969, 0.808969), + (0.841270, 0.828159, 0.828159), + (0.857143, 0.846913, 0.846913), + (0.873016, 0.865261, 0.865261), + (0.888889, 0.883229, 0.883229), + (0.904762, 0.900837, 0.900837), + (0.920635, 0.918109, 0.918109), + (0.936508, 0.935061, 0.935061), + (0.952381, 0.951711, 0.951711), + (0.968254, 0.968075, 0.968075), + (0.984127, 0.984167, 0.984167), + (1.0, 1.0, 1.0), + ), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def prism(range, **traits): """ Generator function for the 'prism' colormap. """ - _data = {'red': ((0., 1., 1.),(0.031746, 1.000000, 1.000000), - (0.047619, 0.000000, 0.000000),(0.063492, 0.000000, 0.000000), - (0.079365, 0.666667, 0.666667),(0.095238, 1.000000, 1.000000), - (0.126984, 1.000000, 1.000000),(0.142857, 0.000000, 0.000000), - (0.158730, 0.000000, 0.000000),(0.174603, 0.666667, 0.666667), - (0.190476, 1.000000, 1.000000),(0.222222, 1.000000, 1.000000), - (0.238095, 0.000000, 0.000000),(0.253968, 0.000000, 0.000000), - (0.269841, 0.666667, 0.666667),(0.285714, 1.000000, 1.000000), - (0.317460, 1.000000, 1.000000),(0.333333, 0.000000, 0.000000), - (0.349206, 0.000000, 0.000000),(0.365079, 0.666667, 0.666667), - (0.380952, 1.000000, 1.000000),(0.412698, 1.000000, 1.000000), - (0.428571, 0.000000, 0.000000),(0.444444, 0.000000, 0.000000), - (0.460317, 0.666667, 0.666667),(0.476190, 1.000000, 1.000000), - (0.507937, 1.000000, 1.000000),(0.523810, 0.000000, 0.000000), - (0.539683, 0.000000, 0.000000),(0.555556, 0.666667, 0.666667), - (0.571429, 1.000000, 1.000000),(0.603175, 1.000000, 1.000000), - (0.619048, 0.000000, 0.000000),(0.634921, 0.000000, 0.000000), - (0.650794, 0.666667, 0.666667),(0.666667, 1.000000, 1.000000), - (0.698413, 1.000000, 1.000000),(0.714286, 0.000000, 0.000000), - (0.730159, 0.000000, 0.000000),(0.746032, 0.666667, 0.666667), - (0.761905, 1.000000, 1.000000),(0.793651, 1.000000, 1.000000), - (0.809524, 0.000000, 0.000000),(0.825397, 0.000000, 0.000000), - (0.841270, 0.666667, 0.666667),(0.857143, 1.000000, 1.000000), - (0.888889, 1.000000, 1.000000),(0.904762, 0.000000, 0.000000), - (0.920635, 0.000000, 0.000000),(0.936508, 0.666667, 0.666667), - (0.952381, 1.000000, 1.000000),(0.984127, 1.000000, 1.000000), - (1.0, 0.0, 0.0)), - 'green': ((0., 0., 0.),(0.031746, 1.000000, 1.000000), - (0.047619, 1.000000, 1.000000),(0.063492, 0.000000, 0.000000), - (0.095238, 0.000000, 0.000000),(0.126984, 1.000000, 1.000000), - (0.142857, 1.000000, 1.000000),(0.158730, 0.000000, 0.000000), - (0.190476, 0.000000, 0.000000),(0.222222, 1.000000, 1.000000), - (0.238095, 1.000000, 1.000000),(0.253968, 0.000000, 0.000000), - (0.285714, 0.000000, 0.000000),(0.317460, 1.000000, 1.000000), - (0.333333, 1.000000, 1.000000),(0.349206, 0.000000, 0.000000), - (0.380952, 0.000000, 0.000000),(0.412698, 1.000000, 1.000000), - (0.428571, 1.000000, 1.000000),(0.444444, 0.000000, 0.000000), - (0.476190, 0.000000, 0.000000),(0.507937, 1.000000, 1.000000), - (0.523810, 1.000000, 1.000000),(0.539683, 0.000000, 0.000000), - (0.571429, 0.000000, 0.000000),(0.603175, 1.000000, 1.000000), - (0.619048, 1.000000, 1.000000),(0.634921, 0.000000, 0.000000), - (0.666667, 0.000000, 0.000000),(0.698413, 1.000000, 1.000000), - (0.714286, 1.000000, 1.000000),(0.730159, 0.000000, 0.000000), - (0.761905, 0.000000, 0.000000),(0.793651, 1.000000, 1.000000), - (0.809524, 1.000000, 1.000000),(0.825397, 0.000000, 0.000000), - (0.857143, 0.000000, 0.000000),(0.888889, 1.000000, 1.000000), - (0.904762, 1.000000, 1.000000),(0.920635, 0.000000, 0.000000), - (0.952381, 0.000000, 0.000000),(0.984127, 1.000000, 1.000000), - (1.0, 1.0, 1.0)), - 'blue': ((0., 0., 0.),(0.047619, 0.000000, 0.000000), - (0.063492, 1.000000, 1.000000),(0.079365, 1.000000, 1.000000), - (0.095238, 0.000000, 0.000000),(0.142857, 0.000000, 0.000000), - (0.158730, 1.000000, 1.000000),(0.174603, 1.000000, 1.000000), - (0.190476, 0.000000, 0.000000),(0.238095, 0.000000, 0.000000), - (0.253968, 1.000000, 1.000000),(0.269841, 1.000000, 1.000000), - (0.285714, 0.000000, 0.000000),(0.333333, 0.000000, 0.000000), - (0.349206, 1.000000, 1.000000),(0.365079, 1.000000, 1.000000), - (0.380952, 0.000000, 0.000000),(0.428571, 0.000000, 0.000000), - (0.444444, 1.000000, 1.000000),(0.460317, 1.000000, 1.000000), - (0.476190, 0.000000, 0.000000),(0.523810, 0.000000, 0.000000), - (0.539683, 1.000000, 1.000000),(0.555556, 1.000000, 1.000000), - (0.571429, 0.000000, 0.000000),(0.619048, 0.000000, 0.000000), - (0.634921, 1.000000, 1.000000),(0.650794, 1.000000, 1.000000), - (0.666667, 0.000000, 0.000000),(0.714286, 0.000000, 0.000000), - (0.730159, 1.000000, 1.000000),(0.746032, 1.000000, 1.000000), - (0.761905, 0.000000, 0.000000),(0.809524, 0.000000, 0.000000), - (0.825397, 1.000000, 1.000000),(0.841270, 1.000000, 1.000000), - (0.857143, 0.000000, 0.000000),(0.904762, 0.000000, 0.000000), - (0.920635, 1.000000, 1.000000),(0.936508, 1.000000, 1.000000), - (0.952381, 0.000000, 0.000000),(1.0, 0.0, 0.0))} + _data = { + "red": ( + (0.0, 1.0, 1.0), + (0.031746, 1.000000, 1.000000), + (0.047619, 0.000000, 0.000000), + (0.063492, 0.000000, 0.000000), + (0.079365, 0.666667, 0.666667), + (0.095238, 1.000000, 1.000000), + (0.126984, 1.000000, 1.000000), + (0.142857, 0.000000, 0.000000), + (0.158730, 0.000000, 0.000000), + (0.174603, 0.666667, 0.666667), + (0.190476, 1.000000, 1.000000), + (0.222222, 1.000000, 1.000000), + (0.238095, 0.000000, 0.000000), + (0.253968, 0.000000, 0.000000), + (0.269841, 0.666667, 0.666667), + (0.285714, 1.000000, 1.000000), + (0.317460, 1.000000, 1.000000), + (0.333333, 0.000000, 0.000000), + (0.349206, 0.000000, 0.000000), + (0.365079, 0.666667, 0.666667), + (0.380952, 1.000000, 1.000000), + (0.412698, 1.000000, 1.000000), + (0.428571, 0.000000, 0.000000), + (0.444444, 0.000000, 0.000000), + (0.460317, 0.666667, 0.666667), + (0.476190, 1.000000, 1.000000), + (0.507937, 1.000000, 1.000000), + (0.523810, 0.000000, 0.000000), + (0.539683, 0.000000, 0.000000), + (0.555556, 0.666667, 0.666667), + (0.571429, 1.000000, 1.000000), + (0.603175, 1.000000, 1.000000), + (0.619048, 0.000000, 0.000000), + (0.634921, 0.000000, 0.000000), + (0.650794, 0.666667, 0.666667), + (0.666667, 1.000000, 1.000000), + (0.698413, 1.000000, 1.000000), + (0.714286, 0.000000, 0.000000), + (0.730159, 0.000000, 0.000000), + (0.746032, 0.666667, 0.666667), + (0.761905, 1.000000, 1.000000), + (0.793651, 1.000000, 1.000000), + (0.809524, 0.000000, 0.000000), + (0.825397, 0.000000, 0.000000), + (0.841270, 0.666667, 0.666667), + (0.857143, 1.000000, 1.000000), + (0.888889, 1.000000, 1.000000), + (0.904762, 0.000000, 0.000000), + (0.920635, 0.000000, 0.000000), + (0.936508, 0.666667, 0.666667), + (0.952381, 1.000000, 1.000000), + (0.984127, 1.000000, 1.000000), + (1.0, 0.0, 0.0), + ), + "green": ( + (0.0, 0.0, 0.0), + (0.031746, 1.000000, 1.000000), + (0.047619, 1.000000, 1.000000), + (0.063492, 0.000000, 0.000000), + (0.095238, 0.000000, 0.000000), + (0.126984, 1.000000, 1.000000), + (0.142857, 1.000000, 1.000000), + (0.158730, 0.000000, 0.000000), + (0.190476, 0.000000, 0.000000), + (0.222222, 1.000000, 1.000000), + (0.238095, 1.000000, 1.000000), + (0.253968, 0.000000, 0.000000), + (0.285714, 0.000000, 0.000000), + (0.317460, 1.000000, 1.000000), + (0.333333, 1.000000, 1.000000), + (0.349206, 0.000000, 0.000000), + (0.380952, 0.000000, 0.000000), + (0.412698, 1.000000, 1.000000), + (0.428571, 1.000000, 1.000000), + (0.444444, 0.000000, 0.000000), + (0.476190, 0.000000, 0.000000), + (0.507937, 1.000000, 1.000000), + (0.523810, 1.000000, 1.000000), + (0.539683, 0.000000, 0.000000), + (0.571429, 0.000000, 0.000000), + (0.603175, 1.000000, 1.000000), + (0.619048, 1.000000, 1.000000), + (0.634921, 0.000000, 0.000000), + (0.666667, 0.000000, 0.000000), + (0.698413, 1.000000, 1.000000), + (0.714286, 1.000000, 1.000000), + (0.730159, 0.000000, 0.000000), + (0.761905, 0.000000, 0.000000), + (0.793651, 1.000000, 1.000000), + (0.809524, 1.000000, 1.000000), + (0.825397, 0.000000, 0.000000), + (0.857143, 0.000000, 0.000000), + (0.888889, 1.000000, 1.000000), + (0.904762, 1.000000, 1.000000), + (0.920635, 0.000000, 0.000000), + (0.952381, 0.000000, 0.000000), + (0.984127, 1.000000, 1.000000), + (1.0, 1.0, 1.0), + ), + "blue": ( + (0.0, 0.0, 0.0), + (0.047619, 0.000000, 0.000000), + (0.063492, 1.000000, 1.000000), + (0.079365, 1.000000, 1.000000), + (0.095238, 0.000000, 0.000000), + (0.142857, 0.000000, 0.000000), + (0.158730, 1.000000, 1.000000), + (0.174603, 1.000000, 1.000000), + (0.190476, 0.000000, 0.000000), + (0.238095, 0.000000, 0.000000), + (0.253968, 1.000000, 1.000000), + (0.269841, 1.000000, 1.000000), + (0.285714, 0.000000, 0.000000), + (0.333333, 0.000000, 0.000000), + (0.349206, 1.000000, 1.000000), + (0.365079, 1.000000, 1.000000), + (0.380952, 0.000000, 0.000000), + (0.428571, 0.000000, 0.000000), + (0.444444, 1.000000, 1.000000), + (0.460317, 1.000000, 1.000000), + (0.476190, 0.000000, 0.000000), + (0.523810, 0.000000, 0.000000), + (0.539683, 1.000000, 1.000000), + (0.555556, 1.000000, 1.000000), + (0.571429, 0.000000, 0.000000), + (0.619048, 0.000000, 0.000000), + (0.634921, 1.000000, 1.000000), + (0.650794, 1.000000, 1.000000), + (0.666667, 0.000000, 0.000000), + (0.714286, 0.000000, 0.000000), + (0.730159, 1.000000, 1.000000), + (0.746032, 1.000000, 1.000000), + (0.761905, 0.000000, 0.000000), + (0.809524, 0.000000, 0.000000), + (0.825397, 1.000000, 1.000000), + (0.841270, 1.000000, 1.000000), + (0.857143, 0.000000, 0.000000), + (0.904762, 0.000000, 0.000000), + (0.920635, 1.000000, 1.000000), + (0.936508, 1.000000, 1.000000), + (0.952381, 0.000000, 0.000000), + (1.0, 0.0, 0.0), + ), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def spring(range, **traits): """ Generator function for the 'spring' colormap. """ - _data = {'red': ((0., 1., 1.),(1.0, 1.0, 1.0)), - 'green': ((0., 0., 0.),(1.0, 1.0, 1.0)), - 'blue': ((0., 1., 1.),(1.0, 0.0, 0.0))} + _data = { + "red": ((0.0, 1.0, 1.0), (1.0, 1.0, 1.0)), + "green": ((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)), + "blue": ((0.0, 1.0, 1.0), (1.0, 0.0, 0.0)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def summer(range, **traits): """ Generator function for the 'summer' colormap. """ - _data = {'red': ((0., 0., 0.),(1.0, 1.0, 1.0)), - 'green': ((0., 0.5, 0.5),(1.0, 1.0, 1.0)), - 'blue': ((0., 0.4, 0.4),(1.0, 0.4, 0.4))} + _data = { + "red": ((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)), + "green": ((0.0, 0.5, 0.5), (1.0, 1.0, 1.0)), + "blue": ((0.0, 0.4, 0.4), (1.0, 0.4, 0.4)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def winter(range, **traits): """ Generator function for the 'winter' colormap. """ - _data = {'red': ((0., 0., 0.),(1.0, 0.0, 0.0)), - 'green': ((0., 0., 0.),(1.0, 1.0, 1.0)), - 'blue': ((0., 1., 1.),(1.0, 0.5, 0.5))} + _data = { + "red": ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)), + "green": ((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)), + "blue": ((0.0, 1.0, 1.0), (1.0, 0.5, 0.5)), + } return ColorMapper.from_segment_map(_data, range=range, **traits) + def cw1_004(range, **traits): """ Generator function for the Crumblingwalls cw1-004 gradient """ - colors = array([(0.7176,0.6980,0.6118), - (0.8000,0.5373,0.7059), - (0.2510,0.4588,0.4902), - (0.0588,0.3176,0.5137)]) + colors = array( + [ + (0.7176, 0.6980, 0.6118), + (0.8000, 0.5373, 0.7059), + (0.2510, 0.4588, 0.4902), + (0.0588, 0.3176, 0.5137), + ] + ) return ColorMapper.from_palette_array(colors, range=range, **traits) + def cw1_005(range, **traits): """ Generator function for the Crumblingwalls cw1-005 gradient """ - colors = array([(0.7059,0.1686,0.0980), - (0.7961,0.5176,0.2039), - (0.2863,0.3255,0.1294)]) + colors = array( + [(0.7059, 0.1686, 0.0980), (0.7961, 0.5176, 0.2039), (0.2863, 0.3255, 0.1294)] + ) return ColorMapper.from_palette_array(colors, range=range, **traits) + def cw1_006(range, **traits): """ Generator function for the Crumblingwalls cw1-006 gradient """ - colors = array([(0.4275,0.2824,0.4667), - (0.2039,0.1843,0.4667), - (0.0863,0.4078,0.2078)]) + colors = array( + [(0.4275, 0.2824, 0.4667), (0.2039, 0.1843, 0.4667), (0.0863, 0.4078, 0.2078)] + ) return ColorMapper.from_palette_array(colors, range=range, **traits) + def cw1_028(range, **traits): """ Generator function for the Crumblingwalls cw1-058 gradient """ - colors = array([(0.2275, 0.2275, 0.4784), - (0.3294, 0.5137, 0.8588), - (0.4078, 0.8471, 0.8510)]) + colors = array( + [(0.2275, 0.2275, 0.4784), (0.3294, 0.5137, 0.8588), (0.4078, 0.8471, 0.8510)] + ) return ColorMapper.from_palette_array(colors, range=range, **traits) + def gmt_drywet(range, **traits): - _data = {'red': ((0.00000,0.5255,0.5255), - (0.16670,0.9333,0.9333), - (0.33330,0.7059,0.7059), - (0.50000,0.1961,0.1961), - (0.66670,0.0471,0.0471), - (0.83330,0.1490,0.1490), - (1.00000,0.0314,0.0314)), - - 'green': ((0.00000,0.3804,0.3804), - (0.16670,0.7804,0.7804), - (0.33330,0.9333,0.9333), - (0.50000,0.9333,0.9333), - (0.66670,0.4706,0.4706), - (0.83330,0.0039,0.0039), - (1.00000,0.2000,0.2000)), - - 'blue': ((0.00000,0.1647,0.1647), - (0.16670,0.3922,0.3922), - (0.33330,0.5294,0.5294), - (0.50000,0.9216,0.9216), - (0.66670,0.9333,0.9333), - (0.83330,0.7176,0.7176), - (1.00000,0.4431,0.4431)) } + _data = { + "red": ( + (0.00000, 0.5255, 0.5255), + (0.16670, 0.9333, 0.9333), + (0.33330, 0.7059, 0.7059), + (0.50000, 0.1961, 0.1961), + (0.66670, 0.0471, 0.0471), + (0.83330, 0.1490, 0.1490), + (1.00000, 0.0314, 0.0314), + ), + "green": ( + (0.00000, 0.3804, 0.3804), + (0.16670, 0.7804, 0.7804), + (0.33330, 0.9333, 0.9333), + (0.50000, 0.9333, 0.9333), + (0.66670, 0.4706, 0.4706), + (0.83330, 0.0039, 0.0039), + (1.00000, 0.2000, 0.2000), + ), + "blue": ( + (0.00000, 0.1647, 0.1647), + (0.16670, 0.3922, 0.3922), + (0.33330, 0.5294, 0.5294), + (0.50000, 0.9216, 0.9216), + (0.66670, 0.9333, 0.9333), + (0.83330, 0.7176, 0.7176), + (1.00000, 0.4431, 0.4431), + ), + } return ColorMapper.from_segment_map(_data, range=range, **traits) @@ -658,15 +1031,17 @@ def gmt_drywet(range, **traits): # create continuous colormaps from them by linear interpolation in RGB # colorspace, in the same manner as matplotlib + def Blues(range, **traits): - """ Generator for the 'Blues' colormap from ColorBrewer. + """Generator for the 'Blues' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 0.96862745098, 0.96862745098), + red=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.870588235294, 0.870588235294), (0.25, 0.776470588235, 0.776470588235), (0.375, 0.619607843137, 0.619607843137), @@ -674,8 +1049,10 @@ def Blues(range, **traits): (0.625, 0.258823529412, 0.258823529412), (0.75, 0.129411764706, 0.129411764706), (0.875, 0.0313725490196, 0.0313725490196), - (1.0, 0.0313725490196, 0.0313725490196)], - green = [(0.0, 0.98431372549, 0.98431372549), + (1.0, 0.0313725490196, 0.0313725490196), + ], + green=[ + (0.0, 0.98431372549, 0.98431372549), (0.125, 0.921568627451, 0.921568627451), (0.25, 0.858823529412, 0.858823529412), (0.375, 0.792156862745, 0.792156862745), @@ -683,8 +1060,10 @@ def Blues(range, **traits): (0.625, 0.572549019608, 0.572549019608), (0.75, 0.443137254902, 0.443137254902), (0.875, 0.317647058824, 0.317647058824), - (1.0, 0.188235294118, 0.188235294118)], - blue = [(0.0, 1.0, 1.0), + (1.0, 0.188235294118, 0.188235294118), + ], + blue=[ + (0.0, 1.0, 1.0), (0.125, 0.96862745098, 0.96862745098), (0.25, 0.937254901961, 0.937254901961), (0.375, 0.882352941176, 0.882352941176), @@ -692,12 +1071,14 @@ def Blues(range, **traits): (0.625, 0.776470588235, 0.776470588235), (0.75, 0.709803921569, 0.709803921569), (0.875, 0.611764705882, 0.611764705882), - (1.0, 0.419607843137, 0.419607843137)], + (1.0, 0.419607843137, 0.419607843137), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def BrBG(range, **traits): - """ Generator for the 'BrBG' colormap from ColorBrewer. + """Generator for the 'BrBG' colormap from ColorBrewer. This is a diverging colormap. It is good for data which is centered around a "special" value, like 0. @@ -707,7 +1088,8 @@ def BrBG(range, **traits): colorspace. """ _data = dict( - red = [(0.0, 0.329411764706, 0.329411764706), + red=[ + (0.0, 0.329411764706, 0.329411764706), (0.1, 0.549019607843, 0.549019607843), (0.2, 0.749019607843, 0.749019607843), (0.3, 0.874509803922, 0.874509803922), @@ -717,8 +1099,10 @@ def BrBG(range, **traits): (0.7, 0.501960784314, 0.501960784314), (0.8, 0.207843137255, 0.207843137255), (0.9, 0.00392156862745, 0.00392156862745), - (1.0, 0.0, 0.0)], - green = [(0.0, 0.188235294118, 0.188235294118), + (1.0, 0.0, 0.0), + ], + green=[ + (0.0, 0.188235294118, 0.188235294118), (0.1, 0.317647058824, 0.317647058824), (0.2, 0.505882352941, 0.505882352941), (0.3, 0.760784313725, 0.760784313725), @@ -728,8 +1112,10 @@ def BrBG(range, **traits): (0.7, 0.803921568627, 0.803921568627), (0.8, 0.592156862745, 0.592156862745), (0.9, 0.4, 0.4), - (1.0, 0.235294117647, 0.235294117647)], - blue = [(0.0, 0.0196078431373, 0.0196078431373), + (1.0, 0.235294117647, 0.235294117647), + ], + blue=[ + (0.0, 0.0196078431373, 0.0196078431373), (0.1, 0.0392156862745, 0.0392156862745), (0.2, 0.176470588235, 0.176470588235), (0.3, 0.490196078431, 0.490196078431), @@ -739,19 +1125,22 @@ def BrBG(range, **traits): (0.7, 0.756862745098, 0.756862745098), (0.8, 0.560784313725, 0.560784313725), (0.9, 0.36862745098, 0.36862745098), - (1.0, 0.188235294118, 0.188235294118)], + (1.0, 0.188235294118, 0.188235294118), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def BuGn(range, **traits): - """ Generator for the 'BuGn' colormap from ColorBrewer. + """Generator for the 'BuGn' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 0.96862745098, 0.96862745098), + red=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.898039215686, 0.898039215686), (0.25, 0.8, 0.8), (0.375, 0.6, 0.6), @@ -759,8 +1148,10 @@ def BuGn(range, **traits): (0.625, 0.254901960784, 0.254901960784), (0.75, 0.137254901961, 0.137254901961), (0.875, 0.0, 0.0), - (1.0, 0.0, 0.0)], - green = [(0.0, 0.988235294118, 0.988235294118), + (1.0, 0.0, 0.0), + ], + green=[ + (0.0, 0.988235294118, 0.988235294118), (0.125, 0.960784313725, 0.960784313725), (0.25, 0.925490196078, 0.925490196078), (0.375, 0.847058823529, 0.847058823529), @@ -768,8 +1159,10 @@ def BuGn(range, **traits): (0.625, 0.682352941176, 0.682352941176), (0.75, 0.545098039216, 0.545098039216), (0.875, 0.427450980392, 0.427450980392), - (1.0, 0.266666666667, 0.266666666667)], - blue = [(0.0, 0.992156862745, 0.992156862745), + (1.0, 0.266666666667, 0.266666666667), + ], + blue=[ + (0.0, 0.992156862745, 0.992156862745), (0.125, 0.976470588235, 0.976470588235), (0.25, 0.901960784314, 0.901960784314), (0.375, 0.788235294118, 0.788235294118), @@ -777,19 +1170,22 @@ def BuGn(range, **traits): (0.625, 0.462745098039, 0.462745098039), (0.75, 0.270588235294, 0.270588235294), (0.875, 0.172549019608, 0.172549019608), - (1.0, 0.105882352941, 0.105882352941)], + (1.0, 0.105882352941, 0.105882352941), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def BuPu(range, **traits): - """ Generator for the 'BuPu' colormap from ColorBrewer. + """Generator for the 'BuPu' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 0.96862745098, 0.96862745098), + red=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.878431372549, 0.878431372549), (0.25, 0.749019607843, 0.749019607843), (0.375, 0.619607843137, 0.619607843137), @@ -797,8 +1193,10 @@ def BuPu(range, **traits): (0.625, 0.549019607843, 0.549019607843), (0.75, 0.533333333333, 0.533333333333), (0.875, 0.505882352941, 0.505882352941), - (1.0, 0.301960784314, 0.301960784314)], - green = [(0.0, 0.988235294118, 0.988235294118), + (1.0, 0.301960784314, 0.301960784314), + ], + green=[ + (0.0, 0.988235294118, 0.988235294118), (0.125, 0.925490196078, 0.925490196078), (0.25, 0.827450980392, 0.827450980392), (0.375, 0.737254901961, 0.737254901961), @@ -806,8 +1204,10 @@ def BuPu(range, **traits): (0.625, 0.419607843137, 0.419607843137), (0.75, 0.254901960784, 0.254901960784), (0.875, 0.0588235294118, 0.0588235294118), - (1.0, 0.0, 0.0)], - blue = [(0.0, 0.992156862745, 0.992156862745), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 0.992156862745, 0.992156862745), (0.125, 0.956862745098, 0.956862745098), (0.25, 0.901960784314, 0.901960784314), (0.375, 0.854901960784, 0.854901960784), @@ -815,19 +1215,22 @@ def BuPu(range, **traits): (0.625, 0.694117647059, 0.694117647059), (0.75, 0.61568627451, 0.61568627451), (0.875, 0.486274509804, 0.486274509804), - (1.0, 0.294117647059, 0.294117647059)], + (1.0, 0.294117647059, 0.294117647059), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def GnBu(range, **traits): - """ Generator for the 'GnBu' colormap from ColorBrewer. + """Generator for the 'GnBu' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 0.96862745098, 0.96862745098), + red=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.878431372549, 0.878431372549), (0.25, 0.8, 0.8), (0.375, 0.658823529412, 0.658823529412), @@ -835,8 +1238,10 @@ def GnBu(range, **traits): (0.625, 0.305882352941, 0.305882352941), (0.75, 0.16862745098, 0.16862745098), (0.875, 0.0313725490196, 0.0313725490196), - (1.0, 0.0313725490196, 0.0313725490196)], - green = [(0.0, 0.988235294118, 0.988235294118), + (1.0, 0.0313725490196, 0.0313725490196), + ], + green=[ + (0.0, 0.988235294118, 0.988235294118), (0.125, 0.952941176471, 0.952941176471), (0.25, 0.921568627451, 0.921568627451), (0.375, 0.866666666667, 0.866666666667), @@ -844,8 +1249,10 @@ def GnBu(range, **traits): (0.625, 0.701960784314, 0.701960784314), (0.75, 0.549019607843, 0.549019607843), (0.875, 0.407843137255, 0.407843137255), - (1.0, 0.250980392157, 0.250980392157)], - blue = [(0.0, 0.941176470588, 0.941176470588), + (1.0, 0.250980392157, 0.250980392157), + ], + blue=[ + (0.0, 0.941176470588, 0.941176470588), (0.125, 0.858823529412, 0.858823529412), (0.25, 0.772549019608, 0.772549019608), (0.375, 0.709803921569, 0.709803921569), @@ -853,19 +1260,22 @@ def GnBu(range, **traits): (0.625, 0.827450980392, 0.827450980392), (0.75, 0.745098039216, 0.745098039216), (0.875, 0.674509803922, 0.674509803922), - (1.0, 0.505882352941, 0.505882352941)], + (1.0, 0.505882352941, 0.505882352941), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def Greens(range, **traits): - """ Generator for the 'Greens' colormap from ColorBrewer. + """Generator for the 'Greens' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 0.96862745098, 0.96862745098), + red=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.898039215686, 0.898039215686), (0.25, 0.780392156863, 0.780392156863), (0.375, 0.63137254902, 0.63137254902), @@ -873,8 +1283,10 @@ def Greens(range, **traits): (0.625, 0.254901960784, 0.254901960784), (0.75, 0.137254901961, 0.137254901961), (0.875, 0.0, 0.0), - (1.0, 0.0, 0.0)], - green = [(0.0, 0.988235294118, 0.988235294118), + (1.0, 0.0, 0.0), + ], + green=[ + (0.0, 0.988235294118, 0.988235294118), (0.125, 0.960784313725, 0.960784313725), (0.25, 0.913725490196, 0.913725490196), (0.375, 0.850980392157, 0.850980392157), @@ -882,8 +1294,10 @@ def Greens(range, **traits): (0.625, 0.670588235294, 0.670588235294), (0.75, 0.545098039216, 0.545098039216), (0.875, 0.427450980392, 0.427450980392), - (1.0, 0.266666666667, 0.266666666667)], - blue = [(0.0, 0.960784313725, 0.960784313725), + (1.0, 0.266666666667, 0.266666666667), + ], + blue=[ + (0.0, 0.960784313725, 0.960784313725), (0.125, 0.878431372549, 0.878431372549), (0.25, 0.752941176471, 0.752941176471), (0.375, 0.607843137255, 0.607843137255), @@ -891,19 +1305,22 @@ def Greens(range, **traits): (0.625, 0.364705882353, 0.364705882353), (0.75, 0.270588235294, 0.270588235294), (0.875, 0.172549019608, 0.172549019608), - (1.0, 0.105882352941, 0.105882352941)], + (1.0, 0.105882352941, 0.105882352941), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def Greys(range, **traits): - """ Generator for the 'Greys' colormap from ColorBrewer. + """Generator for the 'Greys' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 0.941176470588, 0.941176470588), (0.25, 0.850980392157, 0.850980392157), (0.375, 0.741176470588, 0.741176470588), @@ -911,8 +1328,10 @@ def Greys(range, **traits): (0.625, 0.450980392157, 0.450980392157), (0.75, 0.321568627451, 0.321568627451), (0.875, 0.145098039216, 0.145098039216), - (1.0, 0.0, 0.0)], - green = [(0.0, 1.0, 1.0), + (1.0, 0.0, 0.0), + ], + green=[ + (0.0, 1.0, 1.0), (0.125, 0.941176470588, 0.941176470588), (0.25, 0.850980392157, 0.850980392157), (0.375, 0.741176470588, 0.741176470588), @@ -920,8 +1339,10 @@ def Greys(range, **traits): (0.625, 0.450980392157, 0.450980392157), (0.75, 0.321568627451, 0.321568627451), (0.875, 0.145098039216, 0.145098039216), - (1.0, 0.0, 0.0)], - blue = [(0.0, 1.0, 1.0), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 1.0, 1.0), (0.125, 0.941176470588, 0.941176470588), (0.25, 0.850980392157, 0.850980392157), (0.375, 0.741176470588, 0.741176470588), @@ -929,19 +1350,22 @@ def Greys(range, **traits): (0.625, 0.450980392157, 0.450980392157), (0.75, 0.321568627451, 0.321568627451), (0.875, 0.145098039216, 0.145098039216), - (1.0, 0.0, 0.0)], + (1.0, 0.0, 0.0), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def OrRd(range, **traits): - """ Generator for the 'OrRd' colormap from ColorBrewer. + """Generator for the 'OrRd' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 0.996078431373, 0.996078431373), (0.25, 0.992156862745, 0.992156862745), (0.375, 0.992156862745, 0.992156862745), @@ -949,8 +1373,10 @@ def OrRd(range, **traits): (0.625, 0.937254901961, 0.937254901961), (0.75, 0.843137254902, 0.843137254902), (0.875, 0.701960784314, 0.701960784314), - (1.0, 0.498039215686, 0.498039215686)], - green = [(0.0, 0.96862745098, 0.96862745098), + (1.0, 0.498039215686, 0.498039215686), + ], + green=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.909803921569, 0.909803921569), (0.25, 0.83137254902, 0.83137254902), (0.375, 0.733333333333, 0.733333333333), @@ -958,8 +1384,10 @@ def OrRd(range, **traits): (0.625, 0.396078431373, 0.396078431373), (0.75, 0.188235294118, 0.188235294118), (0.875, 0.0, 0.0), - (1.0, 0.0, 0.0)], - blue = [(0.0, 0.925490196078, 0.925490196078), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 0.925490196078, 0.925490196078), (0.125, 0.78431372549, 0.78431372549), (0.25, 0.619607843137, 0.619607843137), (0.375, 0.517647058824, 0.517647058824), @@ -967,19 +1395,22 @@ def OrRd(range, **traits): (0.625, 0.282352941176, 0.282352941176), (0.75, 0.121568627451, 0.121568627451), (0.875, 0.0, 0.0), - (1.0, 0.0, 0.0)], + (1.0, 0.0, 0.0), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def Oranges(range, **traits): - """ Generator for the 'Oranges' colormap from ColorBrewer. + """Generator for the 'Oranges' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 0.996078431373, 0.996078431373), (0.25, 0.992156862745, 0.992156862745), (0.375, 0.992156862745, 0.992156862745), @@ -987,8 +1418,10 @@ def Oranges(range, **traits): (0.625, 0.945098039216, 0.945098039216), (0.75, 0.850980392157, 0.850980392157), (0.875, 0.650980392157, 0.650980392157), - (1.0, 0.498039215686, 0.498039215686)], - green = [(0.0, 0.960784313725, 0.960784313725), + (1.0, 0.498039215686, 0.498039215686), + ], + green=[ + (0.0, 0.960784313725, 0.960784313725), (0.125, 0.901960784314, 0.901960784314), (0.25, 0.81568627451, 0.81568627451), (0.375, 0.682352941176, 0.682352941176), @@ -996,8 +1429,10 @@ def Oranges(range, **traits): (0.625, 0.411764705882, 0.411764705882), (0.75, 0.282352941176, 0.282352941176), (0.875, 0.211764705882, 0.211764705882), - (1.0, 0.152941176471, 0.152941176471)], - blue = [(0.0, 0.921568627451, 0.921568627451), + (1.0, 0.152941176471, 0.152941176471), + ], + blue=[ + (0.0, 0.921568627451, 0.921568627451), (0.125, 0.807843137255, 0.807843137255), (0.25, 0.635294117647, 0.635294117647), (0.375, 0.419607843137, 0.419607843137), @@ -1005,13 +1440,14 @@ def Oranges(range, **traits): (0.625, 0.0745098039216, 0.0745098039216), (0.75, 0.00392156862745, 0.00392156862745), (0.875, 0.0117647058824, 0.0117647058824), - (1.0, 0.0156862745098, 0.0156862745098)], + (1.0, 0.0156862745098, 0.0156862745098), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) def PRGn(range, **traits): - """ Generator for the 'PRGn' colormap from ColorBrewer. + """Generator for the 'PRGn' colormap from ColorBrewer. This is a diverging colormap. It is good for data which is centered around a "special" value, like 0. @@ -1021,7 +1457,8 @@ def PRGn(range, **traits): colorspace. """ _data = dict( - red = [(0.0, 0.250980392157, 0.250980392157), + red=[ + (0.0, 0.250980392157, 0.250980392157), (0.1, 0.462745098039, 0.462745098039), (0.2, 0.6, 0.6), (0.3, 0.760784313725, 0.760784313725), @@ -1031,8 +1468,10 @@ def PRGn(range, **traits): (0.7, 0.650980392157, 0.650980392157), (0.8, 0.352941176471, 0.352941176471), (0.9, 0.105882352941, 0.105882352941), - (1.0, 0.0, 0.0)], - green = [(0.0, 0.0, 0.0), + (1.0, 0.0, 0.0), + ], + green=[ + (0.0, 0.0, 0.0), (0.1, 0.164705882353, 0.164705882353), (0.2, 0.439215686275, 0.439215686275), (0.3, 0.647058823529, 0.647058823529), @@ -1042,8 +1481,10 @@ def PRGn(range, **traits): (0.7, 0.858823529412, 0.858823529412), (0.8, 0.682352941176, 0.682352941176), (0.9, 0.470588235294, 0.470588235294), - (1.0, 0.266666666667, 0.266666666667)], - blue = [(0.0, 0.294117647059, 0.294117647059), + (1.0, 0.266666666667, 0.266666666667), + ], + blue=[ + (0.0, 0.294117647059, 0.294117647059), (0.1, 0.513725490196, 0.513725490196), (0.2, 0.670588235294, 0.670588235294), (0.3, 0.811764705882, 0.811764705882), @@ -1053,12 +1494,14 @@ def PRGn(range, **traits): (0.7, 0.627450980392, 0.627450980392), (0.8, 0.380392156863, 0.380392156863), (0.9, 0.21568627451, 0.21568627451), - (1.0, 0.105882352941, 0.105882352941)], + (1.0, 0.105882352941, 0.105882352941), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def PiYG(range, **traits): - """ Generator for the 'PiYG' colormap from ColorBrewer. + """Generator for the 'PiYG' colormap from ColorBrewer. This is a diverging colormap. It is good for data which is centered around a "special" value, like 0. @@ -1068,7 +1511,8 @@ def PiYG(range, **traits): colorspace. """ _data = dict( - red = [(0.0, 0.556862745098, 0.556862745098), + red=[ + (0.0, 0.556862745098, 0.556862745098), (0.1, 0.772549019608, 0.772549019608), (0.2, 0.870588235294, 0.870588235294), (0.3, 0.945098039216, 0.945098039216), @@ -1078,8 +1522,10 @@ def PiYG(range, **traits): (0.7, 0.721568627451, 0.721568627451), (0.8, 0.498039215686, 0.498039215686), (0.9, 0.301960784314, 0.301960784314), - (1.0, 0.152941176471, 0.152941176471)], - green = [(0.0, 0.00392156862745, 0.00392156862745), + (1.0, 0.152941176471, 0.152941176471), + ], + green=[ + (0.0, 0.00392156862745, 0.00392156862745), (0.1, 0.105882352941, 0.105882352941), (0.2, 0.466666666667, 0.466666666667), (0.3, 0.713725490196, 0.713725490196), @@ -1089,8 +1535,10 @@ def PiYG(range, **traits): (0.7, 0.882352941176, 0.882352941176), (0.8, 0.737254901961, 0.737254901961), (0.9, 0.572549019608, 0.572549019608), - (1.0, 0.392156862745, 0.392156862745)], - blue = [(0.0, 0.321568627451, 0.321568627451), + (1.0, 0.392156862745, 0.392156862745), + ], + blue=[ + (0.0, 0.321568627451, 0.321568627451), (0.1, 0.490196078431, 0.490196078431), (0.2, 0.682352941176, 0.682352941176), (0.3, 0.854901960784, 0.854901960784), @@ -1100,19 +1548,22 @@ def PiYG(range, **traits): (0.7, 0.525490196078, 0.525490196078), (0.8, 0.254901960784, 0.254901960784), (0.9, 0.129411764706, 0.129411764706), - (1.0, 0.0980392156863, 0.0980392156863)], + (1.0, 0.0980392156863, 0.0980392156863), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def PuBu(range, **traits): - """ Generator for the 'PuBu' colormap from ColorBrewer. + """Generator for the 'PuBu' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 0.925490196078, 0.925490196078), (0.25, 0.81568627451, 0.81568627451), (0.375, 0.650980392157, 0.650980392157), @@ -1120,8 +1571,10 @@ def PuBu(range, **traits): (0.625, 0.211764705882, 0.211764705882), (0.75, 0.0196078431373, 0.0196078431373), (0.875, 0.0156862745098, 0.0156862745098), - (1.0, 0.0078431372549, 0.0078431372549)], - green = [(0.0, 0.96862745098, 0.96862745098), + (1.0, 0.0078431372549, 0.0078431372549), + ], + green=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.905882352941, 0.905882352941), (0.25, 0.819607843137, 0.819607843137), (0.375, 0.741176470588, 0.741176470588), @@ -1129,8 +1582,10 @@ def PuBu(range, **traits): (0.625, 0.564705882353, 0.564705882353), (0.75, 0.439215686275, 0.439215686275), (0.875, 0.352941176471, 0.352941176471), - (1.0, 0.219607843137, 0.219607843137)], - blue = [(0.0, 0.98431372549, 0.98431372549), + (1.0, 0.219607843137, 0.219607843137), + ], + blue=[ + (0.0, 0.98431372549, 0.98431372549), (0.125, 0.949019607843, 0.949019607843), (0.25, 0.901960784314, 0.901960784314), (0.375, 0.858823529412, 0.858823529412), @@ -1138,19 +1593,22 @@ def PuBu(range, **traits): (0.625, 0.752941176471, 0.752941176471), (0.75, 0.690196078431, 0.690196078431), (0.875, 0.552941176471, 0.552941176471), - (1.0, 0.345098039216, 0.345098039216)], + (1.0, 0.345098039216, 0.345098039216), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def PuBuGn(range, **traits): - """ Generator for the 'PuBuGn' colormap from ColorBrewer. + """Generator for the 'PuBuGn' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 0.925490196078, 0.925490196078), (0.25, 0.81568627451, 0.81568627451), (0.375, 0.650980392157, 0.650980392157), @@ -1158,8 +1616,10 @@ def PuBuGn(range, **traits): (0.625, 0.211764705882, 0.211764705882), (0.75, 0.0078431372549, 0.0078431372549), (0.875, 0.00392156862745, 0.00392156862745), - (1.0, 0.00392156862745, 0.00392156862745)], - green = [(0.0, 0.96862745098, 0.96862745098), + (1.0, 0.00392156862745, 0.00392156862745), + ], + green=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.886274509804, 0.886274509804), (0.25, 0.819607843137, 0.819607843137), (0.375, 0.741176470588, 0.741176470588), @@ -1167,8 +1627,10 @@ def PuBuGn(range, **traits): (0.625, 0.564705882353, 0.564705882353), (0.75, 0.505882352941, 0.505882352941), (0.875, 0.423529411765, 0.423529411765), - (1.0, 0.274509803922, 0.274509803922)], - blue = [(0.0, 0.98431372549, 0.98431372549), + (1.0, 0.274509803922, 0.274509803922), + ], + blue=[ + (0.0, 0.98431372549, 0.98431372549), (0.125, 0.941176470588, 0.941176470588), (0.25, 0.901960784314, 0.901960784314), (0.375, 0.858823529412, 0.858823529412), @@ -1176,12 +1638,14 @@ def PuBuGn(range, **traits): (0.625, 0.752941176471, 0.752941176471), (0.75, 0.541176470588, 0.541176470588), (0.875, 0.349019607843, 0.349019607843), - (1.0, 0.211764705882, 0.211764705882)], + (1.0, 0.211764705882, 0.211764705882), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def PuOr(range, **traits): - """ Generator for the 'PuOr' colormap from ColorBrewer. + """Generator for the 'PuOr' colormap from ColorBrewer. This is a diverging colormap. It is good for data which is centered around a "special" value, like 0. @@ -1191,7 +1655,8 @@ def PuOr(range, **traits): colorspace. """ _data = dict( - red = [(0.0, 0.498039215686, 0.498039215686), + red=[ + (0.0, 0.498039215686, 0.498039215686), (0.1, 0.701960784314, 0.701960784314), (0.2, 0.878431372549, 0.878431372549), (0.3, 0.992156862745, 0.992156862745), @@ -1201,8 +1666,10 @@ def PuOr(range, **traits): (0.7, 0.698039215686, 0.698039215686), (0.8, 0.501960784314, 0.501960784314), (0.9, 0.329411764706, 0.329411764706), - (1.0, 0.176470588235, 0.176470588235)], - green = [(0.0, 0.23137254902, 0.23137254902), + (1.0, 0.176470588235, 0.176470588235), + ], + green=[ + (0.0, 0.23137254902, 0.23137254902), (0.1, 0.345098039216, 0.345098039216), (0.2, 0.509803921569, 0.509803921569), (0.3, 0.721568627451, 0.721568627451), @@ -1212,8 +1679,10 @@ def PuOr(range, **traits): (0.7, 0.670588235294, 0.670588235294), (0.8, 0.450980392157, 0.450980392157), (0.9, 0.152941176471, 0.152941176471), - (1.0, 0.0, 0.0)], - blue = [(0.0, 0.0313725490196, 0.0313725490196), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 0.0313725490196, 0.0313725490196), (0.1, 0.0235294117647, 0.0235294117647), (0.2, 0.078431372549, 0.078431372549), (0.3, 0.388235294118, 0.388235294118), @@ -1223,19 +1692,22 @@ def PuOr(range, **traits): (0.7, 0.823529411765, 0.823529411765), (0.8, 0.674509803922, 0.674509803922), (0.9, 0.533333333333, 0.533333333333), - (1.0, 0.294117647059, 0.294117647059)], + (1.0, 0.294117647059, 0.294117647059), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def PuRd(range, **traits): - """ Generator for the 'PuRd' colormap from ColorBrewer. + """Generator for the 'PuRd' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 0.96862745098, 0.96862745098), + red=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.905882352941, 0.905882352941), (0.25, 0.83137254902, 0.83137254902), (0.375, 0.788235294118, 0.788235294118), @@ -1243,8 +1715,10 @@ def PuRd(range, **traits): (0.625, 0.905882352941, 0.905882352941), (0.75, 0.807843137255, 0.807843137255), (0.875, 0.596078431373, 0.596078431373), - (1.0, 0.403921568627, 0.403921568627)], - green = [(0.0, 0.956862745098, 0.956862745098), + (1.0, 0.403921568627, 0.403921568627), + ], + green=[ + (0.0, 0.956862745098, 0.956862745098), (0.125, 0.882352941176, 0.882352941176), (0.25, 0.725490196078, 0.725490196078), (0.375, 0.580392156863, 0.580392156863), @@ -1252,8 +1726,10 @@ def PuRd(range, **traits): (0.625, 0.160784313725, 0.160784313725), (0.75, 0.0705882352941, 0.0705882352941), (0.875, 0.0, 0.0), - (1.0, 0.0, 0.0)], - blue = [(0.0, 0.976470588235, 0.976470588235), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 0.976470588235, 0.976470588235), (0.125, 0.937254901961, 0.937254901961), (0.25, 0.854901960784, 0.854901960784), (0.375, 0.780392156863, 0.780392156863), @@ -1261,19 +1737,22 @@ def PuRd(range, **traits): (0.625, 0.541176470588, 0.541176470588), (0.75, 0.337254901961, 0.337254901961), (0.875, 0.262745098039, 0.262745098039), - (1.0, 0.121568627451, 0.121568627451)], + (1.0, 0.121568627451, 0.121568627451), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def Purples(range, **traits): - """ Generator for the 'Purples' colormap from ColorBrewer. + """Generator for the 'Purples' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 0.988235294118, 0.988235294118), + red=[ + (0.0, 0.988235294118, 0.988235294118), (0.125, 0.937254901961, 0.937254901961), (0.25, 0.854901960784, 0.854901960784), (0.375, 0.737254901961, 0.737254901961), @@ -1281,8 +1760,10 @@ def Purples(range, **traits): (0.625, 0.501960784314, 0.501960784314), (0.75, 0.41568627451, 0.41568627451), (0.875, 0.329411764706, 0.329411764706), - (1.0, 0.247058823529, 0.247058823529)], - green = [(0.0, 0.98431372549, 0.98431372549), + (1.0, 0.247058823529, 0.247058823529), + ], + green=[ + (0.0, 0.98431372549, 0.98431372549), (0.125, 0.929411764706, 0.929411764706), (0.25, 0.854901960784, 0.854901960784), (0.375, 0.741176470588, 0.741176470588), @@ -1290,8 +1771,10 @@ def Purples(range, **traits): (0.625, 0.490196078431, 0.490196078431), (0.75, 0.317647058824, 0.317647058824), (0.875, 0.152941176471, 0.152941176471), - (1.0, 0.0, 0.0)], - blue = [(0.0, 0.992156862745, 0.992156862745), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 0.992156862745, 0.992156862745), (0.125, 0.960784313725, 0.960784313725), (0.25, 0.921568627451, 0.921568627451), (0.375, 0.862745098039, 0.862745098039), @@ -1299,12 +1782,14 @@ def Purples(range, **traits): (0.625, 0.729411764706, 0.729411764706), (0.75, 0.639215686275, 0.639215686275), (0.875, 0.560784313725, 0.560784313725), - (1.0, 0.490196078431, 0.490196078431)], + (1.0, 0.490196078431, 0.490196078431), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def RdBu(range, **traits): - """ Generator for the 'RdBu' colormap from ColorBrewer. + """Generator for the 'RdBu' colormap from ColorBrewer. This is a diverging colormap. It is good for data which is centered around a "special" value, like 0. @@ -1314,7 +1799,8 @@ def RdBu(range, **traits): colorspace. """ _data = dict( - red = [(0.0, 0.403921568627, 0.403921568627), + red=[ + (0.0, 0.403921568627, 0.403921568627), (0.1, 0.698039215686, 0.698039215686), (0.2, 0.839215686275, 0.839215686275), (0.3, 0.956862745098, 0.956862745098), @@ -1324,8 +1810,10 @@ def RdBu(range, **traits): (0.7, 0.572549019608, 0.572549019608), (0.8, 0.262745098039, 0.262745098039), (0.9, 0.129411764706, 0.129411764706), - (1.0, 0.0196078431373, 0.0196078431373)], - green = [(0.0, 0.0, 0.0), + (1.0, 0.0196078431373, 0.0196078431373), + ], + green=[ + (0.0, 0.0, 0.0), (0.1, 0.0941176470588, 0.0941176470588), (0.2, 0.376470588235, 0.376470588235), (0.3, 0.647058823529, 0.647058823529), @@ -1335,8 +1823,10 @@ def RdBu(range, **traits): (0.7, 0.772549019608, 0.772549019608), (0.8, 0.576470588235, 0.576470588235), (0.9, 0.4, 0.4), - (1.0, 0.188235294118, 0.188235294118)], - blue = [(0.0, 0.121568627451, 0.121568627451), + (1.0, 0.188235294118, 0.188235294118), + ], + blue=[ + (0.0, 0.121568627451, 0.121568627451), (0.1, 0.16862745098, 0.16862745098), (0.2, 0.301960784314, 0.301960784314), (0.3, 0.509803921569, 0.509803921569), @@ -1346,12 +1836,14 @@ def RdBu(range, **traits): (0.7, 0.870588235294, 0.870588235294), (0.8, 0.764705882353, 0.764705882353), (0.9, 0.674509803922, 0.674509803922), - (1.0, 0.380392156863, 0.380392156863)], + (1.0, 0.380392156863, 0.380392156863), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def RdGy(range, **traits): - """ Generator for the 'RdGy' colormap from ColorBrewer. + """Generator for the 'RdGy' colormap from ColorBrewer. This is a diverging colormap. It is good for data which is centered around a "special" value, like 0. @@ -1361,7 +1853,8 @@ def RdGy(range, **traits): colorspace. """ _data = dict( - red = [(0.0, 0.403921568627, 0.403921568627), + red=[ + (0.0, 0.403921568627, 0.403921568627), (0.1, 0.698039215686, 0.698039215686), (0.2, 0.839215686275, 0.839215686275), (0.3, 0.956862745098, 0.956862745098), @@ -1371,8 +1864,10 @@ def RdGy(range, **traits): (0.7, 0.729411764706, 0.729411764706), (0.8, 0.529411764706, 0.529411764706), (0.9, 0.301960784314, 0.301960784314), - (1.0, 0.101960784314, 0.101960784314)], - green = [(0.0, 0.0, 0.0), + (1.0, 0.101960784314, 0.101960784314), + ], + green=[ + (0.0, 0.0, 0.0), (0.1, 0.0941176470588, 0.0941176470588), (0.2, 0.376470588235, 0.376470588235), (0.3, 0.647058823529, 0.647058823529), @@ -1382,8 +1877,10 @@ def RdGy(range, **traits): (0.7, 0.729411764706, 0.729411764706), (0.8, 0.529411764706, 0.529411764706), (0.9, 0.301960784314, 0.301960784314), - (1.0, 0.101960784314, 0.101960784314)], - blue = [(0.0, 0.121568627451, 0.121568627451), + (1.0, 0.101960784314, 0.101960784314), + ], + blue=[ + (0.0, 0.121568627451, 0.121568627451), (0.1, 0.16862745098, 0.16862745098), (0.2, 0.301960784314, 0.301960784314), (0.3, 0.509803921569, 0.509803921569), @@ -1393,19 +1890,22 @@ def RdGy(range, **traits): (0.7, 0.729411764706, 0.729411764706), (0.8, 0.529411764706, 0.529411764706), (0.9, 0.301960784314, 0.301960784314), - (1.0, 0.101960784314, 0.101960784314)], + (1.0, 0.101960784314, 0.101960784314), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def RdPu(range, **traits): - """ Generator for the 'RdPu' colormap from ColorBrewer. + """Generator for the 'RdPu' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 0.992156862745, 0.992156862745), (0.25, 0.988235294118, 0.988235294118), (0.375, 0.980392156863, 0.980392156863), @@ -1413,8 +1913,10 @@ def RdPu(range, **traits): (0.625, 0.866666666667, 0.866666666667), (0.75, 0.682352941176, 0.682352941176), (0.875, 0.478431372549, 0.478431372549), - (1.0, 0.286274509804, 0.286274509804)], - green = [(0.0, 0.96862745098, 0.96862745098), + (1.0, 0.286274509804, 0.286274509804), + ], + green=[ + (0.0, 0.96862745098, 0.96862745098), (0.125, 0.878431372549, 0.878431372549), (0.25, 0.772549019608, 0.772549019608), (0.375, 0.623529411765, 0.623529411765), @@ -1422,8 +1924,10 @@ def RdPu(range, **traits): (0.625, 0.203921568627, 0.203921568627), (0.75, 0.00392156862745, 0.00392156862745), (0.875, 0.00392156862745, 0.00392156862745), - (1.0, 0.0, 0.0)], - blue = [(0.0, 0.952941176471, 0.952941176471), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 0.952941176471, 0.952941176471), (0.125, 0.866666666667, 0.866666666667), (0.25, 0.752941176471, 0.752941176471), (0.375, 0.709803921569, 0.709803921569), @@ -1431,12 +1935,14 @@ def RdPu(range, **traits): (0.625, 0.592156862745, 0.592156862745), (0.75, 0.494117647059, 0.494117647059), (0.875, 0.466666666667, 0.466666666667), - (1.0, 0.41568627451, 0.41568627451)], + (1.0, 0.41568627451, 0.41568627451), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def RdYlBu(range, **traits): - """ Generator for the 'RdYlBu' colormap from ColorBrewer. + """Generator for the 'RdYlBu' colormap from ColorBrewer. This is a diverging colormap. It is good for data which is centered around a "special" value, like 0. @@ -1446,7 +1952,8 @@ def RdYlBu(range, **traits): colorspace. """ _data = dict( - red = [(0.0, 0.647058823529, 0.647058823529), + red=[ + (0.0, 0.647058823529, 0.647058823529), (0.1, 0.843137254902, 0.843137254902), (0.2, 0.956862745098, 0.956862745098), (0.3, 0.992156862745, 0.992156862745), @@ -1456,8 +1963,10 @@ def RdYlBu(range, **traits): (0.7, 0.670588235294, 0.670588235294), (0.8, 0.454901960784, 0.454901960784), (0.9, 0.270588235294, 0.270588235294), - (1.0, 0.192156862745, 0.192156862745)], - green = [(0.0, 0.0, 0.0), + (1.0, 0.192156862745, 0.192156862745), + ], + green=[ + (0.0, 0.0, 0.0), (0.1, 0.188235294118, 0.188235294118), (0.2, 0.427450980392, 0.427450980392), (0.3, 0.682352941176, 0.682352941176), @@ -1467,8 +1976,10 @@ def RdYlBu(range, **traits): (0.7, 0.850980392157, 0.850980392157), (0.8, 0.678431372549, 0.678431372549), (0.9, 0.458823529412, 0.458823529412), - (1.0, 0.211764705882, 0.211764705882)], - blue = [(0.0, 0.149019607843, 0.149019607843), + (1.0, 0.211764705882, 0.211764705882), + ], + blue=[ + (0.0, 0.149019607843, 0.149019607843), (0.1, 0.152941176471, 0.152941176471), (0.2, 0.262745098039, 0.262745098039), (0.3, 0.380392156863, 0.380392156863), @@ -1478,12 +1989,14 @@ def RdYlBu(range, **traits): (0.7, 0.913725490196, 0.913725490196), (0.8, 0.819607843137, 0.819607843137), (0.9, 0.705882352941, 0.705882352941), - (1.0, 0.58431372549, 0.58431372549)], + (1.0, 0.58431372549, 0.58431372549), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def RdYlGn(range, **traits): - """ Generator for the 'RdYlGn' colormap from ColorBrewer. + """Generator for the 'RdYlGn' colormap from ColorBrewer. This is a diverging colormap. It is good for data which is centered around a "special" value, like 0. @@ -1493,7 +2006,8 @@ def RdYlGn(range, **traits): colorspace. """ _data = dict( - red = [(0.0, 0.647058823529, 0.647058823529), + red=[ + (0.0, 0.647058823529, 0.647058823529), (0.1, 0.843137254902, 0.843137254902), (0.2, 0.956862745098, 0.956862745098), (0.3, 0.992156862745, 0.992156862745), @@ -1503,8 +2017,10 @@ def RdYlGn(range, **traits): (0.7, 0.650980392157, 0.650980392157), (0.8, 0.4, 0.4), (0.9, 0.101960784314, 0.101960784314), - (1.0, 0.0, 0.0)], - green = [(0.0, 0.0, 0.0), + (1.0, 0.0, 0.0), + ], + green=[ + (0.0, 0.0, 0.0), (0.1, 0.188235294118, 0.188235294118), (0.2, 0.427450980392, 0.427450980392), (0.3, 0.682352941176, 0.682352941176), @@ -1514,8 +2030,10 @@ def RdYlGn(range, **traits): (0.7, 0.850980392157, 0.850980392157), (0.8, 0.741176470588, 0.741176470588), (0.9, 0.596078431373, 0.596078431373), - (1.0, 0.407843137255, 0.407843137255)], - blue = [(0.0, 0.149019607843, 0.149019607843), + (1.0, 0.407843137255, 0.407843137255), + ], + blue=[ + (0.0, 0.149019607843, 0.149019607843), (0.1, 0.152941176471, 0.152941176471), (0.2, 0.262745098039, 0.262745098039), (0.3, 0.380392156863, 0.380392156863), @@ -1525,19 +2043,22 @@ def RdYlGn(range, **traits): (0.7, 0.41568627451, 0.41568627451), (0.8, 0.388235294118, 0.388235294118), (0.9, 0.313725490196, 0.313725490196), - (1.0, 0.21568627451, 0.21568627451)], + (1.0, 0.21568627451, 0.21568627451), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def Reds(range, **traits): - """ Generator for the 'Reds' colormap from ColorBrewer. + """Generator for the 'Reds' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 0.996078431373, 0.996078431373), (0.25, 0.988235294118, 0.988235294118), (0.375, 0.988235294118, 0.988235294118), @@ -1545,8 +2066,10 @@ def Reds(range, **traits): (0.625, 0.937254901961, 0.937254901961), (0.75, 0.796078431373, 0.796078431373), (0.875, 0.647058823529, 0.647058823529), - (1.0, 0.403921568627, 0.403921568627)], - green = [(0.0, 0.960784313725, 0.960784313725), + (1.0, 0.403921568627, 0.403921568627), + ], + green=[ + (0.0, 0.960784313725, 0.960784313725), (0.125, 0.878431372549, 0.878431372549), (0.25, 0.733333333333, 0.733333333333), (0.375, 0.572549019608, 0.572549019608), @@ -1554,8 +2077,10 @@ def Reds(range, **traits): (0.625, 0.23137254902, 0.23137254902), (0.75, 0.0941176470588, 0.0941176470588), (0.875, 0.0588235294118, 0.0588235294118), - (1.0, 0.0, 0.0)], - blue = [(0.0, 0.941176470588, 0.941176470588), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 0.941176470588, 0.941176470588), (0.125, 0.823529411765, 0.823529411765), (0.25, 0.63137254902, 0.63137254902), (0.375, 0.447058823529, 0.447058823529), @@ -1563,12 +2088,14 @@ def Reds(range, **traits): (0.625, 0.172549019608, 0.172549019608), (0.75, 0.113725490196, 0.113725490196), (0.875, 0.0823529411765, 0.0823529411765), - (1.0, 0.0509803921569, 0.0509803921569)], + (1.0, 0.0509803921569, 0.0509803921569), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def Spectral(range, **traits): - """ Generator for the 'Spectral' colormap from ColorBrewer. + """Generator for the 'Spectral' colormap from ColorBrewer. This is a diverging colormap. It is good for data which is centered around a "special" value, like 0. @@ -1578,7 +2105,8 @@ def Spectral(range, **traits): colorspace. """ _data = dict( - red = [(0.0, 0.619607843137, 0.619607843137), + red=[ + (0.0, 0.619607843137, 0.619607843137), (0.1, 0.835294117647, 0.835294117647), (0.2, 0.956862745098, 0.956862745098), (0.3, 0.992156862745, 0.992156862745), @@ -1588,8 +2116,10 @@ def Spectral(range, **traits): (0.7, 0.670588235294, 0.670588235294), (0.8, 0.4, 0.4), (0.9, 0.196078431373, 0.196078431373), - (1.0, 0.36862745098, 0.36862745098)], - green = [(0.0, 0.00392156862745, 0.00392156862745), + (1.0, 0.36862745098, 0.36862745098), + ], + green=[ + (0.0, 0.00392156862745, 0.00392156862745), (0.1, 0.243137254902, 0.243137254902), (0.2, 0.427450980392, 0.427450980392), (0.3, 0.682352941176, 0.682352941176), @@ -1599,8 +2129,10 @@ def Spectral(range, **traits): (0.7, 0.866666666667, 0.866666666667), (0.8, 0.760784313725, 0.760784313725), (0.9, 0.533333333333, 0.533333333333), - (1.0, 0.309803921569, 0.309803921569)], - blue = [(0.0, 0.258823529412, 0.258823529412), + (1.0, 0.309803921569, 0.309803921569), + ], + blue=[ + (0.0, 0.258823529412, 0.258823529412), (0.1, 0.309803921569, 0.309803921569), (0.2, 0.262745098039, 0.262745098039), (0.3, 0.380392156863, 0.380392156863), @@ -1610,19 +2142,22 @@ def Spectral(range, **traits): (0.7, 0.643137254902, 0.643137254902), (0.8, 0.647058823529, 0.647058823529), (0.9, 0.741176470588, 0.741176470588), - (1.0, 0.635294117647, 0.635294117647)], + (1.0, 0.635294117647, 0.635294117647), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def YlGn(range, **traits): - """ Generator for the 'YlGn' colormap from ColorBrewer. + """Generator for the 'YlGn' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 0.96862745098, 0.96862745098), (0.25, 0.850980392157, 0.850980392157), (0.375, 0.678431372549, 0.678431372549), @@ -1630,8 +2165,10 @@ def YlGn(range, **traits): (0.625, 0.254901960784, 0.254901960784), (0.75, 0.137254901961, 0.137254901961), (0.875, 0.0, 0.0), - (1.0, 0.0, 0.0)], - green = [(0.0, 1.0, 1.0), + (1.0, 0.0, 0.0), + ], + green=[ + (0.0, 1.0, 1.0), (0.125, 0.988235294118, 0.988235294118), (0.25, 0.941176470588, 0.941176470588), (0.375, 0.866666666667, 0.866666666667), @@ -1639,8 +2176,10 @@ def YlGn(range, **traits): (0.625, 0.670588235294, 0.670588235294), (0.75, 0.517647058824, 0.517647058824), (0.875, 0.407843137255, 0.407843137255), - (1.0, 0.270588235294, 0.270588235294)], - blue = [(0.0, 0.898039215686, 0.898039215686), + (1.0, 0.270588235294, 0.270588235294), + ], + blue=[ + (0.0, 0.898039215686, 0.898039215686), (0.125, 0.725490196078, 0.725490196078), (0.25, 0.639215686275, 0.639215686275), (0.375, 0.556862745098, 0.556862745098), @@ -1648,19 +2187,22 @@ def YlGn(range, **traits): (0.625, 0.364705882353, 0.364705882353), (0.75, 0.262745098039, 0.262745098039), (0.875, 0.21568627451, 0.21568627451), - (1.0, 0.160784313725, 0.160784313725)], + (1.0, 0.160784313725, 0.160784313725), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def YlGnBu(range, **traits): - """ Generator for the 'YlGnBu' colormap from ColorBrewer. + """Generator for the 'YlGnBu' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 0.929411764706, 0.929411764706), (0.25, 0.780392156863, 0.780392156863), (0.375, 0.498039215686, 0.498039215686), @@ -1668,8 +2210,10 @@ def YlGnBu(range, **traits): (0.625, 0.113725490196, 0.113725490196), (0.75, 0.133333333333, 0.133333333333), (0.875, 0.145098039216, 0.145098039216), - (1.0, 0.0313725490196, 0.0313725490196)], - green = [(0.0, 1.0, 1.0), + (1.0, 0.0313725490196, 0.0313725490196), + ], + green=[ + (0.0, 1.0, 1.0), (0.125, 0.972549019608, 0.972549019608), (0.25, 0.913725490196, 0.913725490196), (0.375, 0.803921568627, 0.803921568627), @@ -1677,8 +2221,10 @@ def YlGnBu(range, **traits): (0.625, 0.56862745098, 0.56862745098), (0.75, 0.36862745098, 0.36862745098), (0.875, 0.203921568627, 0.203921568627), - (1.0, 0.113725490196, 0.113725490196)], - blue = [(0.0, 0.850980392157, 0.850980392157), + (1.0, 0.113725490196, 0.113725490196), + ], + blue=[ + (0.0, 0.850980392157, 0.850980392157), (0.125, 0.694117647059, 0.694117647059), (0.25, 0.705882352941, 0.705882352941), (0.375, 0.733333333333, 0.733333333333), @@ -1686,19 +2232,22 @@ def YlGnBu(range, **traits): (0.625, 0.752941176471, 0.752941176471), (0.75, 0.658823529412, 0.658823529412), (0.875, 0.580392156863, 0.580392156863), - (1.0, 0.345098039216, 0.345098039216)], + (1.0, 0.345098039216, 0.345098039216), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def YlOrBr(range, **traits): - """ Generator for the 'YlOrBr' colormap from ColorBrewer. + """Generator for the 'YlOrBr' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 1.0, 1.0), (0.25, 0.996078431373, 0.996078431373), (0.375, 0.996078431373, 0.996078431373), @@ -1706,8 +2255,10 @@ def YlOrBr(range, **traits): (0.625, 0.925490196078, 0.925490196078), (0.75, 0.8, 0.8), (0.875, 0.6, 0.6), - (1.0, 0.4, 0.4)], - green = [(0.0, 1.0, 1.0), + (1.0, 0.4, 0.4), + ], + green=[ + (0.0, 1.0, 1.0), (0.125, 0.96862745098, 0.96862745098), (0.25, 0.890196078431, 0.890196078431), (0.375, 0.76862745098, 0.76862745098), @@ -1715,8 +2266,10 @@ def YlOrBr(range, **traits): (0.625, 0.439215686275, 0.439215686275), (0.75, 0.298039215686, 0.298039215686), (0.875, 0.203921568627, 0.203921568627), - (1.0, 0.145098039216, 0.145098039216)], - blue = [(0.0, 0.898039215686, 0.898039215686), + (1.0, 0.145098039216, 0.145098039216), + ], + blue=[ + (0.0, 0.898039215686, 0.898039215686), (0.125, 0.737254901961, 0.737254901961), (0.25, 0.56862745098, 0.56862745098), (0.375, 0.309803921569, 0.309803921569), @@ -1724,19 +2277,22 @@ def YlOrBr(range, **traits): (0.625, 0.078431372549, 0.078431372549), (0.75, 0.0078431372549, 0.0078431372549), (0.875, 0.0156862745098, 0.0156862745098), - (1.0, 0.0235294117647, 0.0235294117647)], + (1.0, 0.0235294117647, 0.0235294117647), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def YlOrRd(range, **traits): - """ Generator for the 'YlOrRd' colormap from ColorBrewer. + """Generator for the 'YlOrRd' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.125, 1.0, 1.0), (0.25, 0.996078431373, 0.996078431373), (0.375, 0.996078431373, 0.996078431373), @@ -1744,8 +2300,10 @@ def YlOrRd(range, **traits): (0.625, 0.988235294118, 0.988235294118), (0.75, 0.890196078431, 0.890196078431), (0.875, 0.741176470588, 0.741176470588), - (1.0, 0.501960784314, 0.501960784314)], - green = [(0.0, 1.0, 1.0), + (1.0, 0.501960784314, 0.501960784314), + ], + green=[ + (0.0, 1.0, 1.0), (0.125, 0.929411764706, 0.929411764706), (0.25, 0.850980392157, 0.850980392157), (0.375, 0.698039215686, 0.698039215686), @@ -1753,8 +2311,10 @@ def YlOrRd(range, **traits): (0.625, 0.305882352941, 0.305882352941), (0.75, 0.101960784314, 0.101960784314), (0.875, 0.0, 0.0), - (1.0, 0.0, 0.0)], - blue = [(0.0, 0.8, 0.8), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 0.8, 0.8), (0.125, 0.627450980392, 0.627450980392), (0.25, 0.462745098039, 0.462745098039), (0.375, 0.298039215686, 0.298039215686), @@ -1762,18 +2322,20 @@ def YlOrRd(range, **traits): (0.625, 0.164705882353, 0.164705882353), (0.75, 0.109803921569, 0.109803921569), (0.875, 0.149019607843, 0.149019607843), - (1.0, 0.149019607843, 0.149019607843)], + (1.0, 0.149019607843, 0.149019607843), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) # The following colormaps are from Yorick, a derivative of the GIST package. + def gist_earth(range, **traits): - """ Generator for the 'gist_earth' colormap from GIST. - """ + """Generator for the 'gist_earth' colormap from GIST.""" _data = dict( - red = [(0.0, 0.0, 0.0), + red=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0, 0.0), (0.0084033617749810219, 0.0, 0.0), (0.012605042196810246, 0.0, 0.0), @@ -2011,8 +2573,10 @@ def gist_earth(range, **traits): (0.98739492893218994, 0.98039215803146362, 0.98039215803146362), (0.99159663915634155, 0.9843137264251709, 0.9843137264251709), (0.99579828977584839, 0.98823529481887817, 0.98823529481887817), - (1.0, 0.99215686321258545, 0.99215686321258545)], - green = [(0.0, 0.0, 0.0), + (1.0, 0.99215686321258545, 0.99215686321258545), + ], + green=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0, 0.0), (0.0084033617749810219, 0.0, 0.0), (0.012605042196810246, 0.0, 0.0), @@ -2250,8 +2814,10 @@ def gist_earth(range, **traits): (0.98739492893218994, 0.94509804248809814, 0.94509804248809814), (0.99159663915634155, 0.95686274766921997, 0.95686274766921997), (0.99579828977584839, 0.97254902124404907, 0.97254902124404907), - (1.0, 0.9843137264251709, 0.9843137264251709)], - blue = [(0.0, 0.0, 0.0), + (1.0, 0.9843137264251709, 0.9843137264251709), + ], + blue=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.18039216101169586, 0.18039216101169586), (0.0084033617749810219, 0.22745098173618317, 0.22745098173618317), (0.012605042196810246, 0.27058824896812439, 0.27058824896812439), @@ -2489,15 +3055,17 @@ def gist_earth(range, **traits): (0.98739492893218994, 0.94509804248809814, 0.94509804248809814), (0.99159663915634155, 0.95686274766921997, 0.95686274766921997), (0.99579828977584839, 0.97254902124404907, 0.97254902124404907), - (1.0, 0.9843137264251709, 0.9843137264251709)], + (1.0, 0.9843137264251709, 0.9843137264251709), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def gist_gray(range, **traits): - """ Generator for the 'gist_gray' colormap from GIST. - """ + """Generator for the 'gist_gray' colormap from GIST.""" _data = dict( - red = [(0.0, 0.0, 0.0), + red=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), (0.012605042196810246, 0.011764706112444401, 0.011764706112444401), @@ -2735,8 +3303,10 @@ def gist_gray(range, **traits): (0.98739492893218994, 0.9843137264251709, 0.9843137264251709), (0.99159663915634155, 0.98823529481887817, 0.98823529481887817), (0.99579828977584839, 0.99215686321258545, 0.99215686321258545), - (1.0, 0.99607843160629272, 0.99607843160629272)], - green = [(0.0, 0.0, 0.0), + (1.0, 0.99607843160629272, 0.99607843160629272), + ], + green=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), (0.012605042196810246, 0.011764706112444401, 0.011764706112444401), @@ -2974,8 +3544,10 @@ def gist_gray(range, **traits): (0.98739492893218994, 0.9843137264251709, 0.9843137264251709), (0.99159663915634155, 0.98823529481887817, 0.98823529481887817), (0.99579828977584839, 0.99215686321258545, 0.99215686321258545), - (1.0, 0.99607843160629272, 0.99607843160629272)], - blue = [(0.0, 0.0, 0.0), + (1.0, 0.99607843160629272, 0.99607843160629272), + ], + blue=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), (0.012605042196810246, 0.011764706112444401, 0.011764706112444401), @@ -3213,15 +3785,17 @@ def gist_gray(range, **traits): (0.98739492893218994, 0.9843137264251709, 0.9843137264251709), (0.99159663915634155, 0.98823529481887817, 0.98823529481887817), (0.99579828977584839, 0.99215686321258545, 0.99215686321258545), - (1.0, 0.99607843160629272, 0.99607843160629272)], + (1.0, 0.99607843160629272, 0.99607843160629272), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def gist_heat(range, **traits): - """ Generator for the 'gist_heat' colormap from GIST. - """ + """Generator for the 'gist_heat' colormap from GIST.""" _data = dict( - red = [(0.0, 0.0, 0.0), + red=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), (0.012605042196810246, 0.015686275437474251, 0.015686275437474251), @@ -3459,8 +4033,10 @@ def gist_heat(range, **traits): (0.98739492893218994, 1.0, 1.0), (0.99159663915634155, 1.0, 1.0), (0.99579828977584839, 1.0, 1.0), - (1.0, 1.0, 1.0)], - green = [(0.0, 0.0, 0.0), + (1.0, 1.0, 1.0), + ], + green=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0, 0.0), (0.0084033617749810219, 0.0, 0.0), (0.012605042196810246, 0.0, 0.0), @@ -3698,8 +4274,10 @@ def gist_heat(range, **traits): (0.98739492893218994, 0.96078431606292725, 0.96078431606292725), (0.99159663915634155, 0.9686274528503418, 0.9686274528503418), (0.99579828977584839, 0.97647058963775635, 0.97647058963775635), - (1.0, 0.9843137264251709, 0.9843137264251709)], - blue = [(0.0, 0.0, 0.0), + (1.0, 0.9843137264251709, 0.9843137264251709), + ], + blue=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0, 0.0), (0.0084033617749810219, 0.0, 0.0), (0.012605042196810246, 0.0, 0.0), @@ -3937,15 +4515,17 @@ def gist_heat(range, **traits): (0.98739492893218994, 0.92156863212585449, 0.92156863212585449), (0.99159663915634155, 0.93725490570068359, 0.93725490570068359), (0.99579828977584839, 0.9529411792755127, 0.9529411792755127), - (1.0, 0.9686274528503418, 0.9686274528503418)], + (1.0, 0.9686274528503418, 0.9686274528503418), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def gist_ncar(range, **traits): - """ Generator for the 'gist_ncar' colormap from GIST. - """ + """Generator for the 'gist_ncar' colormap from GIST.""" _data = dict( - red = [(0.0, 0.0, 0.0), + red=[ + (0.0, 0.0, 0.0), (0.0050505050458014011, 0.0, 0.0), (0.010101010091602802, 0.0, 0.0), (0.015151515603065491, 0.0, 0.0), @@ -4143,8 +4723,10 @@ def gist_ncar(range, **traits): (0.9848484992980957, 0.9843137264251709, 0.9843137264251709), (0.98989897966384888, 0.98823529481887817, 0.98823529481887817), (0.99494951963424683, 0.99215686321258545, 0.99215686321258545), - (1.0, 0.99607843160629272, 0.99607843160629272)], - green = [(0.0, 0.0, 0.0), + (1.0, 0.99607843160629272, 0.99607843160629272), + ], + green=[ + (0.0, 0.0, 0.0), (0.0050505050458014011, 0.035294119268655777, 0.035294119268655777), (0.010101010091602802, 0.074509806931018829, 0.074509806931018829), (0.015151515603065491, 0.10980392247438431, 0.10980392247438431), @@ -4342,8 +4924,10 @@ def gist_ncar(range, **traits): (0.9848484992980957, 0.90196079015731812, 0.90196079015731812), (0.98989897966384888, 0.92549020051956177, 0.92549020051956177), (0.99494951963424683, 0.94901961088180542, 0.94901961088180542), - (1.0, 0.97254902124404907, 0.97254902124404907)], - blue = [(0.0, 0.50196081399917603, 0.50196081399917603), + (1.0, 0.97254902124404907, 0.97254902124404907), + ], + blue=[ + (0.0, 0.50196081399917603, 0.50196081399917603), (0.0050505050458014011, 0.45098039507865906, 0.45098039507865906), (0.010101010091602802, 0.40392157435417175, 0.40392157435417175), (0.015151515603065491, 0.35686275362968445, 0.35686275362968445), @@ -4541,15 +5125,17 @@ def gist_ncar(range, **traits): (0.9848484992980957, 0.9843137264251709, 0.9843137264251709), (0.98989897966384888, 0.98823529481887817, 0.98823529481887817), (0.99494951963424683, 0.99215686321258545, 0.99215686321258545), - (1.0, 0.99607843160629272, 0.99607843160629272)], + (1.0, 0.99607843160629272, 0.99607843160629272), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def gist_rainbow(range, **traits): - """ Generator for the 'gist_rainbow' colormap from GIST. - """ + """Generator for the 'gist_rainbow' colormap from GIST.""" _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.0042016808874905109, 1.0, 1.0), (0.0084033617749810219, 1.0, 1.0), (0.012605042196810246, 1.0, 1.0), @@ -4787,8 +5373,10 @@ def gist_rainbow(range, **traits): (0.98739492893218994, 1.0, 1.0), (0.99159663915634155, 1.0, 1.0), (0.99579828977584839, 1.0, 1.0), - (1.0, 1.0, 1.0)], - green = [(0.0, 0.0, 0.0), + (1.0, 1.0, 1.0), + ], + green=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0, 0.0), (0.0084033617749810219, 0.0, 0.0), (0.012605042196810246, 0.0, 0.0), @@ -5026,8 +5614,10 @@ def gist_rainbow(range, **traits): (0.98739492893218994, 0.0, 0.0), (0.99159663915634155, 0.0, 0.0), (0.99579828977584839, 0.0, 0.0), - (1.0, 0.0, 0.0)], - blue = [(0.0, 0.16470588743686676, 0.16470588743686676), + (1.0, 0.0, 0.0), + ], + blue=[ + (0.0, 0.16470588743686676, 0.16470588743686676), (0.0042016808874905109, 0.14117647707462311, 0.14117647707462311), (0.0084033617749810219, 0.12156862765550613, 0.12156862765550613), (0.012605042196810246, 0.10196078568696976, 0.10196078568696976), @@ -5265,15 +5855,17 @@ def gist_rainbow(range, **traits): (0.98739492893218994, 0.87058824300765991, 0.87058824300765991), (0.99159663915634155, 0.85098040103912354, 0.85098040103912354), (0.99579828977584839, 0.82745099067687988, 0.82745099067687988), - (1.0, 0.80784314870834351, 0.80784314870834351)], + (1.0, 0.80784314870834351, 0.80784314870834351), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def gist_stern(range, **traits): - """ Generator for the 'gist_stern' colormap from GIST. - """ + """Generator for the 'gist_stern' colormap from GIST.""" _data = dict( - red = [(0.0, 0.0, 0.0), + red=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.070588238537311554, 0.070588238537311554), (0.0084033617749810219, 0.14117647707462311, 0.14117647707462311), (0.012605042196810246, 0.21176470816135406, 0.21176470816135406), @@ -5511,8 +6103,10 @@ def gist_stern(range, **traits): (0.98739492893218994, 0.98039215803146362, 0.98039215803146362), (0.99159663915634155, 0.9843137264251709, 0.9843137264251709), (0.99579828977584839, 0.98823529481887817, 0.98823529481887817), - (1.0, 0.99215686321258545, 0.99215686321258545)], - green = [(0.0, 0.0, 0.0), + (1.0, 0.99215686321258545, 0.99215686321258545), + ], + green=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), (0.012605042196810246, 0.011764706112444401, 0.011764706112444401), @@ -5750,8 +6344,10 @@ def gist_stern(range, **traits): (0.98739492893218994, 0.98039215803146362, 0.98039215803146362), (0.99159663915634155, 0.9843137264251709, 0.9843137264251709), (0.99579828977584839, 0.98823529481887817, 0.98823529481887817), - (1.0, 0.99215686321258545, 0.99215686321258545)], - blue = [(0.0, 0.0, 0.0), + (1.0, 0.99215686321258545, 0.99215686321258545), + ], + blue=[ + (0.0, 0.0, 0.0), (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), (0.0084033617749810219, 0.011764706112444401, 0.011764706112444401), (0.012605042196810246, 0.019607843831181526, 0.019607843831181526), @@ -5989,15 +6585,17 @@ def gist_stern(range, **traits): (0.98739492893218994, 0.92156863212585449, 0.92156863212585449), (0.99159663915634155, 0.93725490570068359, 0.93725490570068359), (0.99579828977584839, 0.9529411792755127, 0.9529411792755127), - (1.0, 0.9686274528503418, 0.9686274528503418)], + (1.0, 0.9686274528503418, 0.9686274528503418), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) + def gist_yarg(range, **traits): - """ Generator for the 'gist_yarg' colormap from GIST. - """ + """Generator for the 'gist_yarg' colormap from GIST.""" _data = dict( - red = [(0.0, 1.0, 1.0), + red=[ + (0.0, 1.0, 1.0), (0.0042016808874905109, 0.99607843160629272, 0.99607843160629272), (0.0084033617749810219, 0.99215686321258545, 0.99215686321258545), (0.012605042196810246, 0.98823529481887817, 0.98823529481887817), @@ -6235,8 +6833,10 @@ def gist_yarg(range, **traits): (0.98739492893218994, 0.015686275437474251, 0.015686275437474251), (0.99159663915634155, 0.011764706112444401, 0.011764706112444401), (0.99579828977584839, 0.0078431377187371254, 0.0078431377187371254), - (1.0, 0.0039215688593685627, 0.0039215688593685627)], - green = [(0.0, 1.0, 1.0), + (1.0, 0.0039215688593685627, 0.0039215688593685627), + ], + green=[ + (0.0, 1.0, 1.0), (0.0042016808874905109, 0.99607843160629272, 0.99607843160629272), (0.0084033617749810219, 0.99215686321258545, 0.99215686321258545), (0.012605042196810246, 0.98823529481887817, 0.98823529481887817), @@ -6474,8 +7074,10 @@ def gist_yarg(range, **traits): (0.98739492893218994, 0.015686275437474251, 0.015686275437474251), (0.99159663915634155, 0.011764706112444401, 0.011764706112444401), (0.99579828977584839, 0.0078431377187371254, 0.0078431377187371254), - (1.0, 0.0039215688593685627, 0.0039215688593685627)], - blue = [(0.0, 1.0, 1.0), + (1.0, 0.0039215688593685627, 0.0039215688593685627), + ], + blue=[ + (0.0, 1.0, 1.0), (0.0042016808874905109, 0.99607843160629272, 0.99607843160629272), (0.0084033617749810219, 0.99215686321258545, 0.99215686321258545), (0.012605042196810246, 0.98823529481887817, 0.98823529481887817), @@ -6713,41 +7315,44 @@ def gist_yarg(range, **traits): (0.98739492893218994, 0.015686275437474251, 0.015686275437474251), (0.99159663915634155, 0.011764706112444401, 0.011764706112444401), (0.99579828977584839, 0.0078431377187371254, 0.0078431377187371254), - (1.0, 0.0039215688593685627, 0.0039215688593685627)], + (1.0, 0.0039215688593685627, 0.0039215688593685627), + ], ) return ColorMapper.from_segment_map(_data, range=range, **traits) def CubicYF(range, **traits): - """ Generator of the 'CubicYF' colormap from Matteo Niccoli. + """Generator of the 'CubicYF' colormap from Matteo Niccoli. Lab-based rainbow scheme with cubic-law luminance. http://mycarta.wordpress.com/color-palettes/ """ - palette = array([ - [0.5151, 0.0482, 0.6697], - [0.5199, 0.1762, 0.8083], - [0.4884, 0.2912, 0.9234], - [0.4297, 0.3855, 0.9921], - [0.3893, 0.4792, 0.9775], - [0.3337, 0.5650, 0.9056], - [0.2795, 0.6419, 0.8287], - [0.2210, 0.7123, 0.7258], - [0.2468, 0.7612, 0.6248], - [0.2833, 0.8125, 0.5069], - [0.3198, 0.8492, 0.3956], - [0.3602, 0.8896, 0.2919], - [0.4568, 0.9136, 0.3018], - [0.6033, 0.9255, 0.3295], - [0.7066, 0.9255, 0.3414], - [0.8000, 0.9255, 0.3529], - ]) + palette = array( + [ + [0.5151, 0.0482, 0.6697], + [0.5199, 0.1762, 0.8083], + [0.4884, 0.2912, 0.9234], + [0.4297, 0.3855, 0.9921], + [0.3893, 0.4792, 0.9775], + [0.3337, 0.5650, 0.9056], + [0.2795, 0.6419, 0.8287], + [0.2210, 0.7123, 0.7258], + [0.2468, 0.7612, 0.6248], + [0.2833, 0.8125, 0.5069], + [0.3198, 0.8492, 0.3956], + [0.3602, 0.8896, 0.2919], + [0.4568, 0.9136, 0.3018], + [0.6033, 0.9255, 0.3295], + [0.7066, 0.9255, 0.3414], + [0.8000, 0.9255, 0.3529], + ] + ) return ColorMapper.from_palette_array(palette, range=range, **traits) def CubicL(range, **traits): - """ Generator of the 'CubicL' colormap from Matteo Niccoli. + """Generator of the 'CubicL' colormap from Matteo Niccoli. Lab-based rainbow scheme with cubic-law luminance, like `CubicYF` but with red at the high end, a modest deviation from being @@ -6755,85 +7360,91 @@ def CubicL(range, **traits): http://mycarta.wordpress.com/color-palettes/ """ - palette = array([ - [0.4706, 0.0000, 0.5216], - [0.5137, 0.0527, 0.7096], - [0.4942, 0.2507, 0.8781], - [0.4296, 0.3858, 0.9922], - [0.3691, 0.5172, 0.9495], - [0.2963, 0.6191, 0.8515], - [0.2199, 0.7134, 0.7225], - [0.2643, 0.7836, 0.5756], - [0.3094, 0.8388, 0.4248], - [0.3623, 0.8917, 0.2858], - [0.5200, 0.9210, 0.3137], - [0.6800, 0.9255, 0.3386], - [0.8000, 0.9255, 0.3529], - [0.8706, 0.8549, 0.3608], - [0.9514, 0.7466, 0.3686], - [0.9765, 0.5887, 0.3569], - ]) + palette = array( + [ + [0.4706, 0.0000, 0.5216], + [0.5137, 0.0527, 0.7096], + [0.4942, 0.2507, 0.8781], + [0.4296, 0.3858, 0.9922], + [0.3691, 0.5172, 0.9495], + [0.2963, 0.6191, 0.8515], + [0.2199, 0.7134, 0.7225], + [0.2643, 0.7836, 0.5756], + [0.3094, 0.8388, 0.4248], + [0.3623, 0.8917, 0.2858], + [0.5200, 0.9210, 0.3137], + [0.6800, 0.9255, 0.3386], + [0.8000, 0.9255, 0.3529], + [0.8706, 0.8549, 0.3608], + [0.9514, 0.7466, 0.3686], + [0.9765, 0.5887, 0.3569], + ] + ) return ColorMapper.from_palette_array(palette, range=range, **traits) def LinearL(range, **traits): - """ Generator of the 'LinearL' colormap from Matteo Niccoli. + """Generator of the 'LinearL' colormap from Matteo Niccoli. Lab-based linear lightness rainbow. http://mycarta.wordpress.com/color-palettes/ """ - palette = array([ - [0.0143, 0.0143, 0.0143], - [0.1413, 0.0555, 0.1256], - [0.1761, 0.0911, 0.2782], - [0.1710, 0.1314, 0.4540], - [0.1074, 0.2234, 0.4984], - [0.0686, 0.3044, 0.5068], - [0.0008, 0.3927, 0.4267], - [0.0000, 0.4763, 0.3464], - [0.0000, 0.5565, 0.2469], - [0.0000, 0.6381, 0.1638], - [0.2167, 0.6966, 0.0000], - [0.3898, 0.7563, 0.0000], - [0.6912, 0.7795, 0.0000], - [0.8548, 0.8041, 0.4555], - [0.9712, 0.8429, 0.7287], - [0.9692, 0.9273, 0.8961], - ]) + palette = array( + [ + [0.0143, 0.0143, 0.0143], + [0.1413, 0.0555, 0.1256], + [0.1761, 0.0911, 0.2782], + [0.1710, 0.1314, 0.4540], + [0.1074, 0.2234, 0.4984], + [0.0686, 0.3044, 0.5068], + [0.0008, 0.3927, 0.4267], + [0.0000, 0.4763, 0.3464], + [0.0000, 0.5565, 0.2469], + [0.0000, 0.6381, 0.1638], + [0.2167, 0.6966, 0.0000], + [0.3898, 0.7563, 0.0000], + [0.6912, 0.7795, 0.0000], + [0.8548, 0.8041, 0.4555], + [0.9712, 0.8429, 0.7287], + [0.9692, 0.9273, 0.8961], + ] + ) return ColorMapper.from_palette_array(palette, range=range, **traits) def LinearLHot(range, **traits): - """ Generator of the 'LinearLHot' colormap from Matteo Niccoli. + """Generator of the 'LinearLHot' colormap from Matteo Niccoli. Linear lightness modification of the `hot` colormap. http://mycarta.wordpress.com/color-palettes/ """ - palette = array([ - [0.0225, 0.0121, 0.0121], - [0.1927, 0.0225, 0.0311], - [0.3243, 0.0106, 0.0000], - [0.4463, 0.0000, 0.0091], - [0.5706, 0.0000, 0.0737], - [0.6969, 0.0000, 0.1337], - [0.8213, 0.0000, 0.1792], - [0.8636, 0.0000, 0.0565], - [0.8821, 0.2555, 0.0000], - [0.8720, 0.4182, 0.0000], - [0.8424, 0.5552, 0.0000], - [0.8031, 0.6776, 0.0000], - [0.7659, 0.7870, 0.0000], - [0.8170, 0.8296, 0.0000], - [0.8853, 0.8896, 0.4113], - [0.9481, 0.9486, 0.7165], - ]) + palette = array( + [ + [0.0225, 0.0121, 0.0121], + [0.1927, 0.0225, 0.0311], + [0.3243, 0.0106, 0.0000], + [0.4463, 0.0000, 0.0091], + [0.5706, 0.0000, 0.0737], + [0.6969, 0.0000, 0.1337], + [0.8213, 0.0000, 0.1792], + [0.8636, 0.0000, 0.0565], + [0.8821, 0.2555, 0.0000], + [0.8720, 0.4182, 0.0000], + [0.8424, 0.5552, 0.0000], + [0.8031, 0.6776, 0.0000], + [0.7659, 0.7870, 0.0000], + [0.8170, 0.8296, 0.0000], + [0.8853, 0.8896, 0.4113], + [0.9481, 0.9486, 0.7165], + ] + ) return ColorMapper.from_palette_array(palette, range=range, **traits) def CoolWarm(range, **traits): - """ Generator of Kenneth Moreland's CoolWarm colormap. + """Generator of Kenneth Moreland's CoolWarm colormap. Blue-White-Red with smooth lightness transitions. Good for applying to 3D surfaces or otherwise have extra shading applied. @@ -6847,7 +7458,7 @@ def CoolWarm(range, **traits): def CubeHelix(range, **traits): - """ Generator of Dave Green's CubeHelix colormap. + """Generator of Dave Green's CubeHelix colormap. Sequential colormap with a linear lightness increasing from black to white deviating away from gray in a tapered helix. @@ -6857,44 +7468,47 @@ def CubeHelix(range, **traits): palette = generate_cubehelix_palette() return ColorMapper.from_palette_array(palette, range=range, **traits) + # An MIT licensed, colorblind-friendly heatmap from Wistia: # https://github.com/wistia/heatmap-palette # http://wistia.com/blog/heatmaps-for-colorblindness # def wistia(range, **traits): - """ An MIT licensed, colorblind-friendly heatmap from Wistia + """An MIT licensed, colorblind-friendly heatmap from Wistia See: https://github.com/wistia/heatmap-palette http://wistia.com/blog/heatmaps-for-colorblindness. """ _data = { - 'red': [ + "red": [ (0.0, 0.8941176470588236, 0.8941176470588236), (0.25, 1.0, 1.0), (0.5, 1.0, 1.0), (0.75, 1.0, 1.0), - (1.0, 0.9882352941176471, 0.9882352941176471) + (1.0, 0.9882352941176471, 0.9882352941176471), ], - 'green': [ + "green": [ (0.0, 1.0, 1.0), (0.25, 0.9098039215686274, 0.9098039215686274), (0.5, 0.7411764705882353, 0.7411764705882353), (0.75, 0.6274509803921569, 0.6274509803921569), - (1.0, 0.4980392156862745, 0.4980392156862745) + (1.0, 0.4980392156862745, 0.4980392156862745), ], - 'blue': [ + "blue": [ (0.0, 0.47843137254901963, 0.47843137254901963), (0.25, 0.10196078431372549, 0.10196078431372549), (0.5, 0.0, 0.0), (0.75, 0.0, 0.0), - (1.0, 0.0, 0.0) + (1.0, 0.0, 0.0), ], } return ColorMapper.from_segment_map(_data, range=range, **traits) + # New colormaps from matplotlib's 2015 update + def magma(range, **traits): """ Generator for the 'magma' colormap from matplolib """ _data = [ @@ -7153,270 +7767,274 @@ def magma(range, **traits): [0.988033, 0.970012, 0.727077], [0.987691, 0.977154, 0.734536], [0.987387, 0.984288, 0.742002], - [0.987053, 0.991438, 0.749504]] + [0.987053, 0.991438, 0.749504], + ] return ColorMapper.from_palette_array(_data, range=range, **traits) + def inferno(range, **traits): """ Generator for the 'inferno' colormap from matplolib """ _data = [ [0.001462, 0.000466, 0.013866], - [0.002267, 0.001270, 0.018570], - [0.003299, 0.002249, 0.024239], - [0.004547, 0.003392, 0.030909], - [0.006006, 0.004692, 0.038558], - [0.007676, 0.006136, 0.046836], - [0.009561, 0.007713, 0.055143], - [0.011663, 0.009417, 0.063460], - [0.013995, 0.011225, 0.071862], - [0.016561, 0.013136, 0.080282], - [0.019373, 0.015133, 0.088767], - [0.022447, 0.017199, 0.097327], - [0.025793, 0.019331, 0.105930], - [0.029432, 0.021503, 0.114621], - [0.033385, 0.023702, 0.123397], - [0.037668, 0.025921, 0.132232], - [0.042253, 0.028139, 0.141141], - [0.046915, 0.030324, 0.150164], - [0.051644, 0.032474, 0.159254], - [0.056449, 0.034569, 0.168414], - [0.061340, 0.036590, 0.177642], - [0.066331, 0.038504, 0.186962], - [0.071429, 0.040294, 0.196354], - [0.076637, 0.041905, 0.205799], - [0.081962, 0.043328, 0.215289], - [0.087411, 0.044556, 0.224813], - [0.092990, 0.045583, 0.234358], - [0.098702, 0.046402, 0.243904], - [0.104551, 0.047008, 0.253430], - [0.110536, 0.047399, 0.262912], - [0.116656, 0.047574, 0.272321], - [0.122908, 0.047536, 0.281624], - [0.129285, 0.047293, 0.290788], - [0.135778, 0.046856, 0.299776], - [0.142378, 0.046242, 0.308553], - [0.149073, 0.045468, 0.317085], - [0.155850, 0.044559, 0.325338], - [0.162689, 0.043554, 0.333277], - [0.169575, 0.042489, 0.340874], - [0.176493, 0.041402, 0.348111], - [0.183429, 0.040329, 0.354971], - [0.190367, 0.039309, 0.361447], - [0.197297, 0.038400, 0.367535], - [0.204209, 0.037632, 0.373238], - [0.211095, 0.037030, 0.378563], - [0.217949, 0.036615, 0.383522], - [0.224763, 0.036405, 0.388129], - [0.231538, 0.036405, 0.392400], - [0.238273, 0.036621, 0.396353], - [0.244967, 0.037055, 0.400007], - [0.251620, 0.037705, 0.403378], - [0.258234, 0.038571, 0.406485], - [0.264810, 0.039647, 0.409345], - [0.271347, 0.040922, 0.411976], - [0.277850, 0.042353, 0.414392], - [0.284321, 0.043933, 0.416608], - [0.290763, 0.045644, 0.418637], - [0.297178, 0.047470, 0.420491], - [0.303568, 0.049396, 0.422182], - [0.309935, 0.051407, 0.423721], - [0.316282, 0.053490, 0.425116], - [0.322610, 0.055634, 0.426377], - [0.328921, 0.057827, 0.427511], - [0.335217, 0.060060, 0.428524], - [0.341500, 0.062325, 0.429425], - [0.347771, 0.064616, 0.430217], - [0.354032, 0.066925, 0.430906], - [0.360284, 0.069247, 0.431497], - [0.366529, 0.071579, 0.431994], - [0.372768, 0.073915, 0.432400], - [0.379001, 0.076253, 0.432719], - [0.385228, 0.078591, 0.432955], - [0.391453, 0.080927, 0.433109], - [0.397674, 0.083257, 0.433183], - [0.403894, 0.085580, 0.433179], - [0.410113, 0.087896, 0.433098], - [0.416331, 0.090203, 0.432943], - [0.422549, 0.092501, 0.432714], - [0.428768, 0.094790, 0.432412], - [0.434987, 0.097069, 0.432039], - [0.441207, 0.099338, 0.431594], - [0.447428, 0.101597, 0.431080], - [0.453651, 0.103848, 0.430498], - [0.459875, 0.106089, 0.429846], - [0.466100, 0.108322, 0.429125], - [0.472328, 0.110547, 0.428334], - [0.478558, 0.112764, 0.427475], - [0.484789, 0.114974, 0.426548], - [0.491022, 0.117179, 0.425552], - [0.497257, 0.119379, 0.424488], - [0.503493, 0.121575, 0.423356], - [0.509730, 0.123769, 0.422156], - [0.515967, 0.125960, 0.420887], - [0.522206, 0.128150, 0.419549], - [0.528444, 0.130341, 0.418142], - [0.534683, 0.132534, 0.416667], - [0.540920, 0.134729, 0.415123], - [0.547157, 0.136929, 0.413511], - [0.553392, 0.139134, 0.411829], - [0.559624, 0.141346, 0.410078], - [0.565854, 0.143567, 0.408258], - [0.572081, 0.145797, 0.406369], - [0.578304, 0.148039, 0.404411], - [0.584521, 0.150294, 0.402385], - [0.590734, 0.152563, 0.400290], - [0.596940, 0.154848, 0.398125], - [0.603139, 0.157151, 0.395891], - [0.609330, 0.159474, 0.393589], - [0.615513, 0.161817, 0.391219], - [0.621685, 0.164184, 0.388781], - [0.627847, 0.166575, 0.386276], - [0.633998, 0.168992, 0.383704], - [0.640135, 0.171438, 0.381065], - [0.646260, 0.173914, 0.378359], - [0.652369, 0.176421, 0.375586], - [0.658463, 0.178962, 0.372748], - [0.664540, 0.181539, 0.369846], - [0.670599, 0.184153, 0.366879], - [0.676638, 0.186807, 0.363849], - [0.682656, 0.189501, 0.360757], - [0.688653, 0.192239, 0.357603], - [0.694627, 0.195021, 0.354388], - [0.700576, 0.197851, 0.351113], - [0.706500, 0.200728, 0.347777], - [0.712396, 0.203656, 0.344383], - [0.718264, 0.206636, 0.340931], - [0.724103, 0.209670, 0.337424], - [0.729909, 0.212759, 0.333861], - [0.735683, 0.215906, 0.330245], - [0.741423, 0.219112, 0.326576], - [0.747127, 0.222378, 0.322856], - [0.752794, 0.225706, 0.319085], - [0.758422, 0.229097, 0.315266], - [0.764010, 0.232554, 0.311399], - [0.769556, 0.236077, 0.307485], - [0.775059, 0.239667, 0.303526], - [0.780517, 0.243327, 0.299523], - [0.785929, 0.247056, 0.295477], - [0.791293, 0.250856, 0.291390], - [0.796607, 0.254728, 0.287264], - [0.801871, 0.258674, 0.283099], - [0.807082, 0.262692, 0.278898], - [0.812239, 0.266786, 0.274661], - [0.817341, 0.270954, 0.270390], - [0.822386, 0.275197, 0.266085], - [0.827372, 0.279517, 0.261750], - [0.832299, 0.283913, 0.257383], - [0.837165, 0.288385, 0.252988], - [0.841969, 0.292933, 0.248564], - [0.846709, 0.297559, 0.244113], - [0.851384, 0.302260, 0.239636], - [0.855992, 0.307038, 0.235133], - [0.860533, 0.311892, 0.230606], - [0.865006, 0.316822, 0.226055], - [0.869409, 0.321827, 0.221482], - [0.873741, 0.326906, 0.216886], - [0.878001, 0.332060, 0.212268], - [0.882188, 0.337287, 0.207628], - [0.886302, 0.342586, 0.202968], - [0.890341, 0.347957, 0.198286], - [0.894305, 0.353399, 0.193584], - [0.898192, 0.358911, 0.188860], - [0.902003, 0.364492, 0.184116], - [0.905735, 0.370140, 0.179350], - [0.909390, 0.375856, 0.174563], - [0.912966, 0.381636, 0.169755], - [0.916462, 0.387481, 0.164924], - [0.919879, 0.393389, 0.160070], - [0.923215, 0.399359, 0.155193], - [0.926470, 0.405389, 0.150292], - [0.929644, 0.411479, 0.145367], - [0.932737, 0.417627, 0.140417], - [0.935747, 0.423831, 0.135440], - [0.938675, 0.430091, 0.130438], - [0.941521, 0.436405, 0.125409], - [0.944285, 0.442772, 0.120354], - [0.946965, 0.449191, 0.115272], - [0.949562, 0.455660, 0.110164], - [0.952075, 0.462178, 0.105031], - [0.954506, 0.468744, 0.099874], - [0.956852, 0.475356, 0.094695], - [0.959114, 0.482014, 0.089499], - [0.961293, 0.488716, 0.084289], - [0.963387, 0.495462, 0.079073], - [0.965397, 0.502249, 0.073859], - [0.967322, 0.509078, 0.068659], - [0.969163, 0.515946, 0.063488], - [0.970919, 0.522853, 0.058367], - [0.972590, 0.529798, 0.053324], - [0.974176, 0.536780, 0.048392], - [0.975677, 0.543798, 0.043618], - [0.977092, 0.550850, 0.039050], - [0.978422, 0.557937, 0.034931], - [0.979666, 0.565057, 0.031409], - [0.980824, 0.572209, 0.028508], - [0.981895, 0.579392, 0.026250], - [0.982881, 0.586606, 0.024661], - [0.983779, 0.593849, 0.023770], - [0.984591, 0.601122, 0.023606], - [0.985315, 0.608422, 0.024202], - [0.985952, 0.615750, 0.025592], - [0.986502, 0.623105, 0.027814], - [0.986964, 0.630485, 0.030908], - [0.987337, 0.637890, 0.034916], - [0.987622, 0.645320, 0.039886], - [0.987819, 0.652773, 0.045581], - [0.987926, 0.660250, 0.051750], - [0.987945, 0.667748, 0.058329], - [0.987874, 0.675267, 0.065257], - [0.987714, 0.682807, 0.072489], - [0.987464, 0.690366, 0.079990], - [0.987124, 0.697944, 0.087731], - [0.986694, 0.705540, 0.095694], - [0.986175, 0.713153, 0.103863], - [0.985566, 0.720782, 0.112229], - [0.984865, 0.728427, 0.120785], - [0.984075, 0.736087, 0.129527], - [0.983196, 0.743758, 0.138453], - [0.982228, 0.751442, 0.147565], - [0.981173, 0.759135, 0.156863], - [0.980032, 0.766837, 0.166353], - [0.978806, 0.774545, 0.176037], - [0.977497, 0.782258, 0.185923], - [0.976108, 0.789974, 0.196018], - [0.974638, 0.797692, 0.206332], - [0.973088, 0.805409, 0.216877], - [0.971468, 0.813122, 0.227658], - [0.969783, 0.820825, 0.238686], - [0.968041, 0.828515, 0.249972], - [0.966243, 0.836191, 0.261534], - [0.964394, 0.843848, 0.273391], - [0.962517, 0.851476, 0.285546], - [0.960626, 0.859069, 0.298010], - [0.958720, 0.866624, 0.310820], - [0.956834, 0.874129, 0.323974], - [0.954997, 0.881569, 0.337475], - [0.953215, 0.888942, 0.351369], - [0.951546, 0.896226, 0.365627], - [0.950018, 0.903409, 0.380271], - [0.948683, 0.910473, 0.395289], - [0.947594, 0.917399, 0.410665], - [0.946809, 0.924168, 0.426373], - [0.946392, 0.930761, 0.442367], - [0.946403, 0.937159, 0.458592], - [0.946903, 0.943348, 0.474970], - [0.947937, 0.949318, 0.491426], - [0.949545, 0.955063, 0.507860], - [0.951740, 0.960587, 0.524203], - [0.954529, 0.965896, 0.540361], - [0.957896, 0.971003, 0.556275], - [0.961812, 0.975924, 0.571925], - [0.966249, 0.980678, 0.587206], - [0.971162, 0.985282, 0.602154], - [0.976511, 0.989753, 0.616760], - [0.982257, 0.994109, 0.631017], - [0.988362, 0.998364, 0.644924]] + [0.002267, 0.001270, 0.018570], + [0.003299, 0.002249, 0.024239], + [0.004547, 0.003392, 0.030909], + [0.006006, 0.004692, 0.038558], + [0.007676, 0.006136, 0.046836], + [0.009561, 0.007713, 0.055143], + [0.011663, 0.009417, 0.063460], + [0.013995, 0.011225, 0.071862], + [0.016561, 0.013136, 0.080282], + [0.019373, 0.015133, 0.088767], + [0.022447, 0.017199, 0.097327], + [0.025793, 0.019331, 0.105930], + [0.029432, 0.021503, 0.114621], + [0.033385, 0.023702, 0.123397], + [0.037668, 0.025921, 0.132232], + [0.042253, 0.028139, 0.141141], + [0.046915, 0.030324, 0.150164], + [0.051644, 0.032474, 0.159254], + [0.056449, 0.034569, 0.168414], + [0.061340, 0.036590, 0.177642], + [0.066331, 0.038504, 0.186962], + [0.071429, 0.040294, 0.196354], + [0.076637, 0.041905, 0.205799], + [0.081962, 0.043328, 0.215289], + [0.087411, 0.044556, 0.224813], + [0.092990, 0.045583, 0.234358], + [0.098702, 0.046402, 0.243904], + [0.104551, 0.047008, 0.253430], + [0.110536, 0.047399, 0.262912], + [0.116656, 0.047574, 0.272321], + [0.122908, 0.047536, 0.281624], + [0.129285, 0.047293, 0.290788], + [0.135778, 0.046856, 0.299776], + [0.142378, 0.046242, 0.308553], + [0.149073, 0.045468, 0.317085], + [0.155850, 0.044559, 0.325338], + [0.162689, 0.043554, 0.333277], + [0.169575, 0.042489, 0.340874], + [0.176493, 0.041402, 0.348111], + [0.183429, 0.040329, 0.354971], + [0.190367, 0.039309, 0.361447], + [0.197297, 0.038400, 0.367535], + [0.204209, 0.037632, 0.373238], + [0.211095, 0.037030, 0.378563], + [0.217949, 0.036615, 0.383522], + [0.224763, 0.036405, 0.388129], + [0.231538, 0.036405, 0.392400], + [0.238273, 0.036621, 0.396353], + [0.244967, 0.037055, 0.400007], + [0.251620, 0.037705, 0.403378], + [0.258234, 0.038571, 0.406485], + [0.264810, 0.039647, 0.409345], + [0.271347, 0.040922, 0.411976], + [0.277850, 0.042353, 0.414392], + [0.284321, 0.043933, 0.416608], + [0.290763, 0.045644, 0.418637], + [0.297178, 0.047470, 0.420491], + [0.303568, 0.049396, 0.422182], + [0.309935, 0.051407, 0.423721], + [0.316282, 0.053490, 0.425116], + [0.322610, 0.055634, 0.426377], + [0.328921, 0.057827, 0.427511], + [0.335217, 0.060060, 0.428524], + [0.341500, 0.062325, 0.429425], + [0.347771, 0.064616, 0.430217], + [0.354032, 0.066925, 0.430906], + [0.360284, 0.069247, 0.431497], + [0.366529, 0.071579, 0.431994], + [0.372768, 0.073915, 0.432400], + [0.379001, 0.076253, 0.432719], + [0.385228, 0.078591, 0.432955], + [0.391453, 0.080927, 0.433109], + [0.397674, 0.083257, 0.433183], + [0.403894, 0.085580, 0.433179], + [0.410113, 0.087896, 0.433098], + [0.416331, 0.090203, 0.432943], + [0.422549, 0.092501, 0.432714], + [0.428768, 0.094790, 0.432412], + [0.434987, 0.097069, 0.432039], + [0.441207, 0.099338, 0.431594], + [0.447428, 0.101597, 0.431080], + [0.453651, 0.103848, 0.430498], + [0.459875, 0.106089, 0.429846], + [0.466100, 0.108322, 0.429125], + [0.472328, 0.110547, 0.428334], + [0.478558, 0.112764, 0.427475], + [0.484789, 0.114974, 0.426548], + [0.491022, 0.117179, 0.425552], + [0.497257, 0.119379, 0.424488], + [0.503493, 0.121575, 0.423356], + [0.509730, 0.123769, 0.422156], + [0.515967, 0.125960, 0.420887], + [0.522206, 0.128150, 0.419549], + [0.528444, 0.130341, 0.418142], + [0.534683, 0.132534, 0.416667], + [0.540920, 0.134729, 0.415123], + [0.547157, 0.136929, 0.413511], + [0.553392, 0.139134, 0.411829], + [0.559624, 0.141346, 0.410078], + [0.565854, 0.143567, 0.408258], + [0.572081, 0.145797, 0.406369], + [0.578304, 0.148039, 0.404411], + [0.584521, 0.150294, 0.402385], + [0.590734, 0.152563, 0.400290], + [0.596940, 0.154848, 0.398125], + [0.603139, 0.157151, 0.395891], + [0.609330, 0.159474, 0.393589], + [0.615513, 0.161817, 0.391219], + [0.621685, 0.164184, 0.388781], + [0.627847, 0.166575, 0.386276], + [0.633998, 0.168992, 0.383704], + [0.640135, 0.171438, 0.381065], + [0.646260, 0.173914, 0.378359], + [0.652369, 0.176421, 0.375586], + [0.658463, 0.178962, 0.372748], + [0.664540, 0.181539, 0.369846], + [0.670599, 0.184153, 0.366879], + [0.676638, 0.186807, 0.363849], + [0.682656, 0.189501, 0.360757], + [0.688653, 0.192239, 0.357603], + [0.694627, 0.195021, 0.354388], + [0.700576, 0.197851, 0.351113], + [0.706500, 0.200728, 0.347777], + [0.712396, 0.203656, 0.344383], + [0.718264, 0.206636, 0.340931], + [0.724103, 0.209670, 0.337424], + [0.729909, 0.212759, 0.333861], + [0.735683, 0.215906, 0.330245], + [0.741423, 0.219112, 0.326576], + [0.747127, 0.222378, 0.322856], + [0.752794, 0.225706, 0.319085], + [0.758422, 0.229097, 0.315266], + [0.764010, 0.232554, 0.311399], + [0.769556, 0.236077, 0.307485], + [0.775059, 0.239667, 0.303526], + [0.780517, 0.243327, 0.299523], + [0.785929, 0.247056, 0.295477], + [0.791293, 0.250856, 0.291390], + [0.796607, 0.254728, 0.287264], + [0.801871, 0.258674, 0.283099], + [0.807082, 0.262692, 0.278898], + [0.812239, 0.266786, 0.274661], + [0.817341, 0.270954, 0.270390], + [0.822386, 0.275197, 0.266085], + [0.827372, 0.279517, 0.261750], + [0.832299, 0.283913, 0.257383], + [0.837165, 0.288385, 0.252988], + [0.841969, 0.292933, 0.248564], + [0.846709, 0.297559, 0.244113], + [0.851384, 0.302260, 0.239636], + [0.855992, 0.307038, 0.235133], + [0.860533, 0.311892, 0.230606], + [0.865006, 0.316822, 0.226055], + [0.869409, 0.321827, 0.221482], + [0.873741, 0.326906, 0.216886], + [0.878001, 0.332060, 0.212268], + [0.882188, 0.337287, 0.207628], + [0.886302, 0.342586, 0.202968], + [0.890341, 0.347957, 0.198286], + [0.894305, 0.353399, 0.193584], + [0.898192, 0.358911, 0.188860], + [0.902003, 0.364492, 0.184116], + [0.905735, 0.370140, 0.179350], + [0.909390, 0.375856, 0.174563], + [0.912966, 0.381636, 0.169755], + [0.916462, 0.387481, 0.164924], + [0.919879, 0.393389, 0.160070], + [0.923215, 0.399359, 0.155193], + [0.926470, 0.405389, 0.150292], + [0.929644, 0.411479, 0.145367], + [0.932737, 0.417627, 0.140417], + [0.935747, 0.423831, 0.135440], + [0.938675, 0.430091, 0.130438], + [0.941521, 0.436405, 0.125409], + [0.944285, 0.442772, 0.120354], + [0.946965, 0.449191, 0.115272], + [0.949562, 0.455660, 0.110164], + [0.952075, 0.462178, 0.105031], + [0.954506, 0.468744, 0.099874], + [0.956852, 0.475356, 0.094695], + [0.959114, 0.482014, 0.089499], + [0.961293, 0.488716, 0.084289], + [0.963387, 0.495462, 0.079073], + [0.965397, 0.502249, 0.073859], + [0.967322, 0.509078, 0.068659], + [0.969163, 0.515946, 0.063488], + [0.970919, 0.522853, 0.058367], + [0.972590, 0.529798, 0.053324], + [0.974176, 0.536780, 0.048392], + [0.975677, 0.543798, 0.043618], + [0.977092, 0.550850, 0.039050], + [0.978422, 0.557937, 0.034931], + [0.979666, 0.565057, 0.031409], + [0.980824, 0.572209, 0.028508], + [0.981895, 0.579392, 0.026250], + [0.982881, 0.586606, 0.024661], + [0.983779, 0.593849, 0.023770], + [0.984591, 0.601122, 0.023606], + [0.985315, 0.608422, 0.024202], + [0.985952, 0.615750, 0.025592], + [0.986502, 0.623105, 0.027814], + [0.986964, 0.630485, 0.030908], + [0.987337, 0.637890, 0.034916], + [0.987622, 0.645320, 0.039886], + [0.987819, 0.652773, 0.045581], + [0.987926, 0.660250, 0.051750], + [0.987945, 0.667748, 0.058329], + [0.987874, 0.675267, 0.065257], + [0.987714, 0.682807, 0.072489], + [0.987464, 0.690366, 0.079990], + [0.987124, 0.697944, 0.087731], + [0.986694, 0.705540, 0.095694], + [0.986175, 0.713153, 0.103863], + [0.985566, 0.720782, 0.112229], + [0.984865, 0.728427, 0.120785], + [0.984075, 0.736087, 0.129527], + [0.983196, 0.743758, 0.138453], + [0.982228, 0.751442, 0.147565], + [0.981173, 0.759135, 0.156863], + [0.980032, 0.766837, 0.166353], + [0.978806, 0.774545, 0.176037], + [0.977497, 0.782258, 0.185923], + [0.976108, 0.789974, 0.196018], + [0.974638, 0.797692, 0.206332], + [0.973088, 0.805409, 0.216877], + [0.971468, 0.813122, 0.227658], + [0.969783, 0.820825, 0.238686], + [0.968041, 0.828515, 0.249972], + [0.966243, 0.836191, 0.261534], + [0.964394, 0.843848, 0.273391], + [0.962517, 0.851476, 0.285546], + [0.960626, 0.859069, 0.298010], + [0.958720, 0.866624, 0.310820], + [0.956834, 0.874129, 0.323974], + [0.954997, 0.881569, 0.337475], + [0.953215, 0.888942, 0.351369], + [0.951546, 0.896226, 0.365627], + [0.950018, 0.903409, 0.380271], + [0.948683, 0.910473, 0.395289], + [0.947594, 0.917399, 0.410665], + [0.946809, 0.924168, 0.426373], + [0.946392, 0.930761, 0.442367], + [0.946403, 0.937159, 0.458592], + [0.946903, 0.943348, 0.474970], + [0.947937, 0.949318, 0.491426], + [0.949545, 0.955063, 0.507860], + [0.951740, 0.960587, 0.524203], + [0.954529, 0.965896, 0.540361], + [0.957896, 0.971003, 0.556275], + [0.961812, 0.975924, 0.571925], + [0.966249, 0.980678, 0.587206], + [0.971162, 0.985282, 0.602154], + [0.976511, 0.989753, 0.616760], + [0.982257, 0.994109, 0.631017], + [0.988362, 0.998364, 0.644924], + ] return ColorMapper.from_palette_array(_data, range=range, **traits) + def plasma(range, **traits): """ Generator for the 'plasma' colormap from matplolib """ _data = [ @@ -7675,400 +8293,420 @@ def plasma(range, **traits): [0.946602, 0.955190, 0.150328], [0.944152, 0.961916, 0.146861], [0.941896, 0.968590, 0.140956], - [0.940015, 0.975158, 0.131326]] + [0.940015, 0.975158, 0.131326], + ] return ColorMapper.from_palette_array(_data, range=range, **traits) + def viridis(range, **traits): """ Generator for the 'viridis' colormap from matplolib """ _data = [ [0.267004, 0.004874, 0.329415], - [0.268510, 0.009605, 0.335427], - [0.269944, 0.014625, 0.341379], - [0.271305, 0.019942, 0.347269], - [0.272594, 0.025563, 0.353093], - [0.273809, 0.031497, 0.358853], - [0.274952, 0.037752, 0.364543], - [0.276022, 0.044167, 0.370164], - [0.277018, 0.050344, 0.375715], - [0.277941, 0.056324, 0.381191], - [0.278791, 0.062145, 0.386592], - [0.279566, 0.067836, 0.391917], - [0.280267, 0.073417, 0.397163], - [0.280894, 0.078907, 0.402329], - [0.281446, 0.084320, 0.407414], - [0.281924, 0.089666, 0.412415], - [0.282327, 0.094955, 0.417331], - [0.282656, 0.100196, 0.422160], - [0.282910, 0.105393, 0.426902], - [0.283091, 0.110553, 0.431554], - [0.283197, 0.115680, 0.436115], - [0.283229, 0.120777, 0.440584], - [0.283187, 0.125848, 0.444960], - [0.283072, 0.130895, 0.449241], - [0.282884, 0.135920, 0.453427], - [0.282623, 0.140926, 0.457517], - [0.282290, 0.145912, 0.461510], - [0.281887, 0.150881, 0.465405], - [0.281412, 0.155834, 0.469201], - [0.280868, 0.160771, 0.472899], - [0.280255, 0.165693, 0.476498], - [0.279574, 0.170599, 0.479997], - [0.278826, 0.175490, 0.483397], - [0.278012, 0.180367, 0.486697], - [0.277134, 0.185228, 0.489898], - [0.276194, 0.190074, 0.493001], - [0.275191, 0.194905, 0.496005], - [0.274128, 0.199721, 0.498911], - [0.273006, 0.204520, 0.501721], - [0.271828, 0.209303, 0.504434], - [0.270595, 0.214069, 0.507052], - [0.269308, 0.218818, 0.509577], - [0.267968, 0.223549, 0.512008], - [0.266580, 0.228262, 0.514349], - [0.265145, 0.232956, 0.516599], - [0.263663, 0.237631, 0.518762], - [0.262138, 0.242286, 0.520837], - [0.260571, 0.246922, 0.522828], - [0.258965, 0.251537, 0.524736], - [0.257322, 0.256130, 0.526563], - [0.255645, 0.260703, 0.528312], - [0.253935, 0.265254, 0.529983], - [0.252194, 0.269783, 0.531579], - [0.250425, 0.274290, 0.533103], - [0.248629, 0.278775, 0.534556], - [0.246811, 0.283237, 0.535941], - [0.244972, 0.287675, 0.537260], - [0.243113, 0.292092, 0.538516], - [0.241237, 0.296485, 0.539709], - [0.239346, 0.300855, 0.540844], - [0.237441, 0.305202, 0.541921], - [0.235526, 0.309527, 0.542944], - [0.233603, 0.313828, 0.543914], - [0.231674, 0.318106, 0.544834], - [0.229739, 0.322361, 0.545706], - [0.227802, 0.326594, 0.546532], - [0.225863, 0.330805, 0.547314], - [0.223925, 0.334994, 0.548053], - [0.221989, 0.339161, 0.548752], - [0.220057, 0.343307, 0.549413], - [0.218130, 0.347432, 0.550038], - [0.216210, 0.351535, 0.550627], - [0.214298, 0.355619, 0.551184], - [0.212395, 0.359683, 0.551710], - [0.210503, 0.363727, 0.552206], - [0.208623, 0.367752, 0.552675], - [0.206756, 0.371758, 0.553117], - [0.204903, 0.375746, 0.553533], - [0.203063, 0.379716, 0.553925], - [0.201239, 0.383670, 0.554294], - [0.199430, 0.387607, 0.554642], - [0.197636, 0.391528, 0.554969], - [0.195860, 0.395433, 0.555276], - [0.194100, 0.399323, 0.555565], - [0.192357, 0.403199, 0.555836], - [0.190631, 0.407061, 0.556089], - [0.188923, 0.410910, 0.556326], - [0.187231, 0.414746, 0.556547], - [0.185556, 0.418570, 0.556753], - [0.183898, 0.422383, 0.556944], - [0.182256, 0.426184, 0.557120], - [0.180629, 0.429975, 0.557282], - [0.179019, 0.433756, 0.557430], - [0.177423, 0.437527, 0.557565], - [0.175841, 0.441290, 0.557685], - [0.174274, 0.445044, 0.557792], - [0.172719, 0.448791, 0.557885], - [0.171176, 0.452530, 0.557965], - [0.169646, 0.456262, 0.558030], - [0.168126, 0.459988, 0.558082], - [0.166617, 0.463708, 0.558119], - [0.165117, 0.467423, 0.558141], - [0.163625, 0.471133, 0.558148], - [0.162142, 0.474838, 0.558140], - [0.160665, 0.478540, 0.558115], - [0.159194, 0.482237, 0.558073], - [0.157729, 0.485932, 0.558013], - [0.156270, 0.489624, 0.557936], - [0.154815, 0.493313, 0.557840], - [0.153364, 0.497000, 0.557724], - [0.151918, 0.500685, 0.557587], - [0.150476, 0.504369, 0.557430], - [0.149039, 0.508051, 0.557250], - [0.147607, 0.511733, 0.557049], - [0.146180, 0.515413, 0.556823], - [0.144759, 0.519093, 0.556572], - [0.143343, 0.522773, 0.556295], - [0.141935, 0.526453, 0.555991], - [0.140536, 0.530132, 0.555659], - [0.139147, 0.533812, 0.555298], - [0.137770, 0.537492, 0.554906], - [0.136408, 0.541173, 0.554483], - [0.135066, 0.544853, 0.554029], - [0.133743, 0.548535, 0.553541], - [0.132444, 0.552216, 0.553018], - [0.131172, 0.555899, 0.552459], - [0.129933, 0.559582, 0.551864], - [0.128729, 0.563265, 0.551229], - [0.127568, 0.566949, 0.550556], - [0.126453, 0.570633, 0.549841], - [0.125394, 0.574318, 0.549086], - [0.124395, 0.578002, 0.548287], - [0.123463, 0.581687, 0.547445], - [0.122606, 0.585371, 0.546557], - [0.121831, 0.589055, 0.545623], - [0.121148, 0.592739, 0.544641], - [0.120565, 0.596422, 0.543611], - [0.120092, 0.600104, 0.542530], - [0.119738, 0.603785, 0.541400], - [0.119512, 0.607464, 0.540218], - [0.119423, 0.611141, 0.538982], - [0.119483, 0.614817, 0.537692], - [0.119699, 0.618490, 0.536347], - [0.120081, 0.622161, 0.534946], - [0.120638, 0.625828, 0.533488], - [0.121380, 0.629492, 0.531973], - [0.122312, 0.633153, 0.530398], - [0.123444, 0.636809, 0.528763], - [0.124780, 0.640461, 0.527068], - [0.126326, 0.644107, 0.525311], - [0.128087, 0.647749, 0.523491], - [0.130067, 0.651384, 0.521608], - [0.132268, 0.655014, 0.519661], - [0.134692, 0.658636, 0.517649], - [0.137339, 0.662252, 0.515571], - [0.140210, 0.665859, 0.513427], - [0.143303, 0.669459, 0.511215], - [0.146616, 0.673050, 0.508936], - [0.150148, 0.676631, 0.506589], - [0.153894, 0.680203, 0.504172], - [0.157851, 0.683765, 0.501686], - [0.162016, 0.687316, 0.499129], - [0.166383, 0.690856, 0.496502], - [0.170948, 0.694384, 0.493803], - [0.175707, 0.697900, 0.491033], - [0.180653, 0.701402, 0.488189], - [0.185783, 0.704891, 0.485273], - [0.191090, 0.708366, 0.482284], - [0.196571, 0.711827, 0.479221], - [0.202219, 0.715272, 0.476084], - [0.208030, 0.718701, 0.472873], - [0.214000, 0.722114, 0.469588], - [0.220124, 0.725509, 0.466226], - [0.226397, 0.728888, 0.462789], - [0.232815, 0.732247, 0.459277], - [0.239374, 0.735588, 0.455688], - [0.246070, 0.738910, 0.452024], - [0.252899, 0.742211, 0.448284], - [0.259857, 0.745492, 0.444467], - [0.266941, 0.748751, 0.440573], - [0.274149, 0.751988, 0.436601], - [0.281477, 0.755203, 0.432552], - [0.288921, 0.758394, 0.428426], - [0.296479, 0.761561, 0.424223], - [0.304148, 0.764704, 0.419943], - [0.311925, 0.767822, 0.415586], - [0.319809, 0.770914, 0.411152], - [0.327796, 0.773980, 0.406640], - [0.335885, 0.777018, 0.402049], - [0.344074, 0.780029, 0.397381], - [0.352360, 0.783011, 0.392636], - [0.360741, 0.785964, 0.387814], - [0.369214, 0.788888, 0.382914], - [0.377779, 0.791781, 0.377939], - [0.386433, 0.794644, 0.372886], - [0.395174, 0.797475, 0.367757], - [0.404001, 0.800275, 0.362552], - [0.412913, 0.803041, 0.357269], - [0.421908, 0.805774, 0.351910], - [0.430983, 0.808473, 0.346476], - [0.440137, 0.811138, 0.340967], - [0.449368, 0.813768, 0.335384], - [0.458674, 0.816363, 0.329727], - [0.468053, 0.818921, 0.323998], - [0.477504, 0.821444, 0.318195], - [0.487026, 0.823929, 0.312321], - [0.496615, 0.826376, 0.306377], - [0.506271, 0.828786, 0.300362], - [0.515992, 0.831158, 0.294279], - [0.525776, 0.833491, 0.288127], - [0.535621, 0.835785, 0.281908], - [0.545524, 0.838039, 0.275626], - [0.555484, 0.840254, 0.269281], - [0.565498, 0.842430, 0.262877], - [0.575563, 0.844566, 0.256415], - [0.585678, 0.846661, 0.249897], - [0.595839, 0.848717, 0.243329], - [0.606045, 0.850733, 0.236712], - [0.616293, 0.852709, 0.230052], - [0.626579, 0.854645, 0.223353], - [0.636902, 0.856542, 0.216620], - [0.647257, 0.858400, 0.209861], - [0.657642, 0.860219, 0.203082], - [0.668054, 0.861999, 0.196293], - [0.678489, 0.863742, 0.189503], - [0.688944, 0.865448, 0.182725], - [0.699415, 0.867117, 0.175971], - [0.709898, 0.868751, 0.169257], - [0.720391, 0.870350, 0.162603], - [0.730889, 0.871916, 0.156029], - [0.741388, 0.873449, 0.149561], - [0.751884, 0.874951, 0.143228], - [0.762373, 0.876424, 0.137064], - [0.772852, 0.877868, 0.131109], - [0.783315, 0.879285, 0.125405], - [0.793760, 0.880678, 0.120005], - [0.804182, 0.882046, 0.114965], - [0.814576, 0.883393, 0.110347], - [0.824940, 0.884720, 0.106217], - [0.835270, 0.886029, 0.102646], - [0.845561, 0.887322, 0.099702], - [0.855810, 0.888601, 0.097452], - [0.866013, 0.889868, 0.095953], - [0.876168, 0.891125, 0.095250], - [0.886271, 0.892374, 0.095374], - [0.896320, 0.893616, 0.096335], - [0.906311, 0.894855, 0.098125], - [0.916242, 0.896091, 0.100717], - [0.926106, 0.897330, 0.104071], - [0.935904, 0.898570, 0.108131], - [0.945636, 0.899815, 0.112838], - [0.955300, 0.901065, 0.118128], - [0.964894, 0.902323, 0.123941], - [0.974417, 0.903590, 0.130215], - [0.983868, 0.904867, 0.136897], - [0.993248, 0.906157, 0.143936]] + [0.268510, 0.009605, 0.335427], + [0.269944, 0.014625, 0.341379], + [0.271305, 0.019942, 0.347269], + [0.272594, 0.025563, 0.353093], + [0.273809, 0.031497, 0.358853], + [0.274952, 0.037752, 0.364543], + [0.276022, 0.044167, 0.370164], + [0.277018, 0.050344, 0.375715], + [0.277941, 0.056324, 0.381191], + [0.278791, 0.062145, 0.386592], + [0.279566, 0.067836, 0.391917], + [0.280267, 0.073417, 0.397163], + [0.280894, 0.078907, 0.402329], + [0.281446, 0.084320, 0.407414], + [0.281924, 0.089666, 0.412415], + [0.282327, 0.094955, 0.417331], + [0.282656, 0.100196, 0.422160], + [0.282910, 0.105393, 0.426902], + [0.283091, 0.110553, 0.431554], + [0.283197, 0.115680, 0.436115], + [0.283229, 0.120777, 0.440584], + [0.283187, 0.125848, 0.444960], + [0.283072, 0.130895, 0.449241], + [0.282884, 0.135920, 0.453427], + [0.282623, 0.140926, 0.457517], + [0.282290, 0.145912, 0.461510], + [0.281887, 0.150881, 0.465405], + [0.281412, 0.155834, 0.469201], + [0.280868, 0.160771, 0.472899], + [0.280255, 0.165693, 0.476498], + [0.279574, 0.170599, 0.479997], + [0.278826, 0.175490, 0.483397], + [0.278012, 0.180367, 0.486697], + [0.277134, 0.185228, 0.489898], + [0.276194, 0.190074, 0.493001], + [0.275191, 0.194905, 0.496005], + [0.274128, 0.199721, 0.498911], + [0.273006, 0.204520, 0.501721], + [0.271828, 0.209303, 0.504434], + [0.270595, 0.214069, 0.507052], + [0.269308, 0.218818, 0.509577], + [0.267968, 0.223549, 0.512008], + [0.266580, 0.228262, 0.514349], + [0.265145, 0.232956, 0.516599], + [0.263663, 0.237631, 0.518762], + [0.262138, 0.242286, 0.520837], + [0.260571, 0.246922, 0.522828], + [0.258965, 0.251537, 0.524736], + [0.257322, 0.256130, 0.526563], + [0.255645, 0.260703, 0.528312], + [0.253935, 0.265254, 0.529983], + [0.252194, 0.269783, 0.531579], + [0.250425, 0.274290, 0.533103], + [0.248629, 0.278775, 0.534556], + [0.246811, 0.283237, 0.535941], + [0.244972, 0.287675, 0.537260], + [0.243113, 0.292092, 0.538516], + [0.241237, 0.296485, 0.539709], + [0.239346, 0.300855, 0.540844], + [0.237441, 0.305202, 0.541921], + [0.235526, 0.309527, 0.542944], + [0.233603, 0.313828, 0.543914], + [0.231674, 0.318106, 0.544834], + [0.229739, 0.322361, 0.545706], + [0.227802, 0.326594, 0.546532], + [0.225863, 0.330805, 0.547314], + [0.223925, 0.334994, 0.548053], + [0.221989, 0.339161, 0.548752], + [0.220057, 0.343307, 0.549413], + [0.218130, 0.347432, 0.550038], + [0.216210, 0.351535, 0.550627], + [0.214298, 0.355619, 0.551184], + [0.212395, 0.359683, 0.551710], + [0.210503, 0.363727, 0.552206], + [0.208623, 0.367752, 0.552675], + [0.206756, 0.371758, 0.553117], + [0.204903, 0.375746, 0.553533], + [0.203063, 0.379716, 0.553925], + [0.201239, 0.383670, 0.554294], + [0.199430, 0.387607, 0.554642], + [0.197636, 0.391528, 0.554969], + [0.195860, 0.395433, 0.555276], + [0.194100, 0.399323, 0.555565], + [0.192357, 0.403199, 0.555836], + [0.190631, 0.407061, 0.556089], + [0.188923, 0.410910, 0.556326], + [0.187231, 0.414746, 0.556547], + [0.185556, 0.418570, 0.556753], + [0.183898, 0.422383, 0.556944], + [0.182256, 0.426184, 0.557120], + [0.180629, 0.429975, 0.557282], + [0.179019, 0.433756, 0.557430], + [0.177423, 0.437527, 0.557565], + [0.175841, 0.441290, 0.557685], + [0.174274, 0.445044, 0.557792], + [0.172719, 0.448791, 0.557885], + [0.171176, 0.452530, 0.557965], + [0.169646, 0.456262, 0.558030], + [0.168126, 0.459988, 0.558082], + [0.166617, 0.463708, 0.558119], + [0.165117, 0.467423, 0.558141], + [0.163625, 0.471133, 0.558148], + [0.162142, 0.474838, 0.558140], + [0.160665, 0.478540, 0.558115], + [0.159194, 0.482237, 0.558073], + [0.157729, 0.485932, 0.558013], + [0.156270, 0.489624, 0.557936], + [0.154815, 0.493313, 0.557840], + [0.153364, 0.497000, 0.557724], + [0.151918, 0.500685, 0.557587], + [0.150476, 0.504369, 0.557430], + [0.149039, 0.508051, 0.557250], + [0.147607, 0.511733, 0.557049], + [0.146180, 0.515413, 0.556823], + [0.144759, 0.519093, 0.556572], + [0.143343, 0.522773, 0.556295], + [0.141935, 0.526453, 0.555991], + [0.140536, 0.530132, 0.555659], + [0.139147, 0.533812, 0.555298], + [0.137770, 0.537492, 0.554906], + [0.136408, 0.541173, 0.554483], + [0.135066, 0.544853, 0.554029], + [0.133743, 0.548535, 0.553541], + [0.132444, 0.552216, 0.553018], + [0.131172, 0.555899, 0.552459], + [0.129933, 0.559582, 0.551864], + [0.128729, 0.563265, 0.551229], + [0.127568, 0.566949, 0.550556], + [0.126453, 0.570633, 0.549841], + [0.125394, 0.574318, 0.549086], + [0.124395, 0.578002, 0.548287], + [0.123463, 0.581687, 0.547445], + [0.122606, 0.585371, 0.546557], + [0.121831, 0.589055, 0.545623], + [0.121148, 0.592739, 0.544641], + [0.120565, 0.596422, 0.543611], + [0.120092, 0.600104, 0.542530], + [0.119738, 0.603785, 0.541400], + [0.119512, 0.607464, 0.540218], + [0.119423, 0.611141, 0.538982], + [0.119483, 0.614817, 0.537692], + [0.119699, 0.618490, 0.536347], + [0.120081, 0.622161, 0.534946], + [0.120638, 0.625828, 0.533488], + [0.121380, 0.629492, 0.531973], + [0.122312, 0.633153, 0.530398], + [0.123444, 0.636809, 0.528763], + [0.124780, 0.640461, 0.527068], + [0.126326, 0.644107, 0.525311], + [0.128087, 0.647749, 0.523491], + [0.130067, 0.651384, 0.521608], + [0.132268, 0.655014, 0.519661], + [0.134692, 0.658636, 0.517649], + [0.137339, 0.662252, 0.515571], + [0.140210, 0.665859, 0.513427], + [0.143303, 0.669459, 0.511215], + [0.146616, 0.673050, 0.508936], + [0.150148, 0.676631, 0.506589], + [0.153894, 0.680203, 0.504172], + [0.157851, 0.683765, 0.501686], + [0.162016, 0.687316, 0.499129], + [0.166383, 0.690856, 0.496502], + [0.170948, 0.694384, 0.493803], + [0.175707, 0.697900, 0.491033], + [0.180653, 0.701402, 0.488189], + [0.185783, 0.704891, 0.485273], + [0.191090, 0.708366, 0.482284], + [0.196571, 0.711827, 0.479221], + [0.202219, 0.715272, 0.476084], + [0.208030, 0.718701, 0.472873], + [0.214000, 0.722114, 0.469588], + [0.220124, 0.725509, 0.466226], + [0.226397, 0.728888, 0.462789], + [0.232815, 0.732247, 0.459277], + [0.239374, 0.735588, 0.455688], + [0.246070, 0.738910, 0.452024], + [0.252899, 0.742211, 0.448284], + [0.259857, 0.745492, 0.444467], + [0.266941, 0.748751, 0.440573], + [0.274149, 0.751988, 0.436601], + [0.281477, 0.755203, 0.432552], + [0.288921, 0.758394, 0.428426], + [0.296479, 0.761561, 0.424223], + [0.304148, 0.764704, 0.419943], + [0.311925, 0.767822, 0.415586], + [0.319809, 0.770914, 0.411152], + [0.327796, 0.773980, 0.406640], + [0.335885, 0.777018, 0.402049], + [0.344074, 0.780029, 0.397381], + [0.352360, 0.783011, 0.392636], + [0.360741, 0.785964, 0.387814], + [0.369214, 0.788888, 0.382914], + [0.377779, 0.791781, 0.377939], + [0.386433, 0.794644, 0.372886], + [0.395174, 0.797475, 0.367757], + [0.404001, 0.800275, 0.362552], + [0.412913, 0.803041, 0.357269], + [0.421908, 0.805774, 0.351910], + [0.430983, 0.808473, 0.346476], + [0.440137, 0.811138, 0.340967], + [0.449368, 0.813768, 0.335384], + [0.458674, 0.816363, 0.329727], + [0.468053, 0.818921, 0.323998], + [0.477504, 0.821444, 0.318195], + [0.487026, 0.823929, 0.312321], + [0.496615, 0.826376, 0.306377], + [0.506271, 0.828786, 0.300362], + [0.515992, 0.831158, 0.294279], + [0.525776, 0.833491, 0.288127], + [0.535621, 0.835785, 0.281908], + [0.545524, 0.838039, 0.275626], + [0.555484, 0.840254, 0.269281], + [0.565498, 0.842430, 0.262877], + [0.575563, 0.844566, 0.256415], + [0.585678, 0.846661, 0.249897], + [0.595839, 0.848717, 0.243329], + [0.606045, 0.850733, 0.236712], + [0.616293, 0.852709, 0.230052], + [0.626579, 0.854645, 0.223353], + [0.636902, 0.856542, 0.216620], + [0.647257, 0.858400, 0.209861], + [0.657642, 0.860219, 0.203082], + [0.668054, 0.861999, 0.196293], + [0.678489, 0.863742, 0.189503], + [0.688944, 0.865448, 0.182725], + [0.699415, 0.867117, 0.175971], + [0.709898, 0.868751, 0.169257], + [0.720391, 0.870350, 0.162603], + [0.730889, 0.871916, 0.156029], + [0.741388, 0.873449, 0.149561], + [0.751884, 0.874951, 0.143228], + [0.762373, 0.876424, 0.137064], + [0.772852, 0.877868, 0.131109], + [0.783315, 0.879285, 0.125405], + [0.793760, 0.880678, 0.120005], + [0.804182, 0.882046, 0.114965], + [0.814576, 0.883393, 0.110347], + [0.824940, 0.884720, 0.106217], + [0.835270, 0.886029, 0.102646], + [0.845561, 0.887322, 0.099702], + [0.855810, 0.888601, 0.097452], + [0.866013, 0.889868, 0.095953], + [0.876168, 0.891125, 0.095250], + [0.886271, 0.892374, 0.095374], + [0.896320, 0.893616, 0.096335], + [0.906311, 0.894855, 0.098125], + [0.916242, 0.896091, 0.100717], + [0.926106, 0.897330, 0.104071], + [0.935904, 0.898570, 0.108131], + [0.945636, 0.899815, 0.112838], + [0.955300, 0.901065, 0.118128], + [0.964894, 0.902323, 0.123941], + [0.974417, 0.903590, 0.130215], + [0.983868, 0.904867, 0.136897], + [0.993248, 0.906157, 0.143936], + ] return ColorMapper.from_palette_array(_data, range=range, **traits) + # Colorbrewer quantitative colormaps + def accent(range, **traits): """ Generator for the 'accent' colormap from ColorBrewer. """ - data = [[0.49803921580314636, 0.7882353067398071, 0.49803921580314636], - [0.7450980544090271, 0.6823529601097107, 0.8313725590705872], - [0.9921568632125854, 0.7529411911964417, 0.5254902243614197], - [1.0, 1.0, 0.6000000238418579], - [0.21960784494876862, 0.42352941632270813, 0.6901960968971252], - [0.9411764740943909, 0.007843137718737125, 0.49803921580314636], - [0.7490196228027344, 0.35686275362968445, 0.09019608050584793], - [0.4000000059604645, 0.4000000059604645, 0.4000000059604645]] + data = [ + [0.49803921580314636, 0.7882353067398071, 0.49803921580314636], + [0.7450980544090271, 0.6823529601097107, 0.8313725590705872], + [0.9921568632125854, 0.7529411911964417, 0.5254902243614197], + [1.0, 1.0, 0.6000000238418579], + [0.21960784494876862, 0.42352941632270813, 0.6901960968971252], + [0.9411764740943909, 0.007843137718737125, 0.49803921580314636], + [0.7490196228027344, 0.35686275362968445, 0.09019608050584793], + [0.4000000059604645, 0.4000000059604645, 0.4000000059604645], + ] return DiscreteColorMapper.from_palette_array(data, range=range, **traits) def Dark2(range, **traits): """ Generator for the 'Dark2' colormap from ColorBrewer. """ - data = [[0.10588235408067703, 0.6196078658103943, 0.46666666865348816], - [0.8509804010391235, 0.37254902720451355, 0.007843137718737125], - [0.4588235318660736, 0.43921568989753723, 0.7019608020782471], - [0.9058823585510254, 0.16078431904315948, 0.5411764979362488], - [0.4000000059604645, 0.6509804129600525, 0.11764705926179886], - [0.9019607901573181, 0.6705882549285889, 0.007843137718737125], - [0.6509804129600525, 0.4627451002597809, 0.11372549086809158], - [0.4000000059604645, 0.4000000059604645, 0.4000000059604645]] + data = [ + [0.10588235408067703, 0.6196078658103943, 0.46666666865348816], + [0.8509804010391235, 0.37254902720451355, 0.007843137718737125], + [0.4588235318660736, 0.43921568989753723, 0.7019608020782471], + [0.9058823585510254, 0.16078431904315948, 0.5411764979362488], + [0.4000000059604645, 0.6509804129600525, 0.11764705926179886], + [0.9019607901573181, 0.6705882549285889, 0.007843137718737125], + [0.6509804129600525, 0.4627451002597809, 0.11372549086809158], + [0.4000000059604645, 0.4000000059604645, 0.4000000059604645], + ] return DiscreteColorMapper.from_palette_array(data, range=range, **traits) def Paired(range, **traits): """ Generator for the 'Paired' colormap from ColorBrewer. """ - data = [[0.6509804129600525, 0.8078431487083435, 0.8901960849761963], - [0.12156862765550613, 0.47058823704719543, 0.7058823704719543], - [0.6980392336845398, 0.8745098114013672, 0.5411764979362488], - [0.20000000298023224, 0.6274510025978088, 0.1725490242242813], - [0.9843137264251709, 0.6039215922355652, 0.6000000238418579], - [0.8901960849761963, 0.10196078568696976, 0.10980392247438431], - [0.9921568632125854, 0.7490196228027344, 0.43529412150382996], - [1.0, 0.49803921580314636, 0.0], - [0.7921568751335144, 0.6980392336845398, 0.8392156958580017], - [0.4156862795352936, 0.239215686917305, 0.6039215922355652], - [1.0, 1.0, 0.6000000238418579], - [0.6941176652908325, 0.3490196168422699, 0.1568627506494522]] + data = [ + [0.6509804129600525, 0.8078431487083435, 0.8901960849761963], + [0.12156862765550613, 0.47058823704719543, 0.7058823704719543], + [0.6980392336845398, 0.8745098114013672, 0.5411764979362488], + [0.20000000298023224, 0.6274510025978088, 0.1725490242242813], + [0.9843137264251709, 0.6039215922355652, 0.6000000238418579], + [0.8901960849761963, 0.10196078568696976, 0.10980392247438431], + [0.9921568632125854, 0.7490196228027344, 0.43529412150382996], + [1.0, 0.49803921580314636, 0.0], + [0.7921568751335144, 0.6980392336845398, 0.8392156958580017], + [0.4156862795352936, 0.239215686917305, 0.6039215922355652], + [1.0, 1.0, 0.6000000238418579], + [0.6941176652908325, 0.3490196168422699, 0.1568627506494522], + ] return DiscreteColorMapper.from_palette_array(data, range=range, **traits) def Pastel1(range, **traits): """ Generator for the 'Pastel1' colormap from ColorBrewer. """ - data = [[0.9843137264251709, 0.7058823704719543, 0.6823529601097107], - [0.7019608020782471, 0.8039215803146362, 0.8901960849761963], - [0.800000011920929, 0.9215686321258545, 0.772549033164978], - [0.8705882430076599, 0.7960784435272217, 0.8941176533699036], - [0.9960784316062927, 0.8509804010391235, 0.6509804129600525], - [1.0, 1.0, 0.800000011920929], - [0.8980392217636108, 0.8470588326454163, 0.7411764860153198], - [0.9921568632125854, 0.8549019694328308, 0.9254902005195618], - [0.9490196108818054, 0.9490196108818054, 0.9490196108818054]] + data = [ + [0.9843137264251709, 0.7058823704719543, 0.6823529601097107], + [0.7019608020782471, 0.8039215803146362, 0.8901960849761963], + [0.800000011920929, 0.9215686321258545, 0.772549033164978], + [0.8705882430076599, 0.7960784435272217, 0.8941176533699036], + [0.9960784316062927, 0.8509804010391235, 0.6509804129600525], + [1.0, 1.0, 0.800000011920929], + [0.8980392217636108, 0.8470588326454163, 0.7411764860153198], + [0.9921568632125854, 0.8549019694328308, 0.9254902005195618], + [0.9490196108818054, 0.9490196108818054, 0.9490196108818054], + ] return DiscreteColorMapper.from_palette_array(data, range=range, **traits) def Pastel2(range, **traits): - """ Generator for the 'Pastel2' colormap from ColorBrewer. + """Generator for the 'Pastel2' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ - data = [[0.7019608020782471, 0.886274516582489, 0.8039215803146362], - [0.9921568632125854, 0.8039215803146362, 0.6745098233222961], - [0.7960784435272217, 0.8352941274642944, 0.9098039269447327], - [0.95686274766922, 0.7921568751335144, 0.8941176533699036], - [0.9019607901573181, 0.9607843160629272, 0.7882353067398071], - [1.0, 0.9490196108818054, 0.6823529601097107], - [0.9450980424880981, 0.886274516582489, 0.800000011920929], - [0.800000011920929, 0.800000011920929, 0.800000011920929]] + data = [ + [0.7019608020782471, 0.886274516582489, 0.8039215803146362], + [0.9921568632125854, 0.8039215803146362, 0.6745098233222961], + [0.7960784435272217, 0.8352941274642944, 0.9098039269447327], + [0.95686274766922, 0.7921568751335144, 0.8941176533699036], + [0.9019607901573181, 0.9607843160629272, 0.7882353067398071], + [1.0, 0.9490196108818054, 0.6823529601097107], + [0.9450980424880981, 0.886274516582489, 0.800000011920929], + [0.800000011920929, 0.800000011920929, 0.800000011920929], + ] return DiscreteColorMapper.from_palette_array(data, range=range, **traits) def Set1(range, **traits): - """ Generator for the 'Set1' colormap from ColorBrewer. - """ - _data = [[0.8941176533699036, 0.10196078568696976, 0.10980392247438431], - [0.21568627655506134, 0.4941176474094391, 0.7215686440467834], - [0.3019607961177826, 0.686274528503418, 0.29019609093666077], - [0.5960784554481506, 0.30588236451148987, 0.6392157077789307], - [1.0, 0.49803921580314636, 0.0], - [1.0, 1.0, 0.20000000298023224], - [0.6509804129600525, 0.33725491166114807, 0.1568627506494522], - [0.9686274528503418, 0.5058823823928833, 0.7490196228027344], - [0.6000000238418579, 0.6000000238418579, 0.6000000238418579]] + """Generator for the 'Set1' colormap from ColorBrewer.""" + _data = [ + [0.8941176533699036, 0.10196078568696976, 0.10980392247438431], + [0.21568627655506134, 0.4941176474094391, 0.7215686440467834], + [0.3019607961177826, 0.686274528503418, 0.29019609093666077], + [0.5960784554481506, 0.30588236451148987, 0.6392157077789307], + [1.0, 0.49803921580314636, 0.0], + [1.0, 1.0, 0.20000000298023224], + [0.6509804129600525, 0.33725491166114807, 0.1568627506494522], + [0.9686274528503418, 0.5058823823928833, 0.7490196228027344], + [0.6000000238418579, 0.6000000238418579, 0.6000000238418579], + ] return DiscreteColorMapper.from_palette_array(_data, range=range, **traits) def Set2(range, **traits): - """ Generator for the 'Set1' colormap from ColorBrewer. + """Generator for the 'Set1' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ - data = [[0.4000000059604645, 0.7607843279838562, 0.6470588445663452], - [0.9882352948188782, 0.5529412031173706, 0.3843137323856354], - [0.5529412031173706, 0.6274510025978088, 0.7960784435272217], - [0.9058823585510254, 0.5411764979362488, 0.7647058963775635], - [0.6509804129600525, 0.8470588326454163, 0.3294117748737335], - [1.0, 0.8509804010391235, 0.18431372940540314], - [0.8980392217636108, 0.7686274647712708, 0.5803921818733215], - [0.7019608020782471, 0.7019608020782471, 0.7019608020782471]] + data = [ + [0.4000000059604645, 0.7607843279838562, 0.6470588445663452], + [0.9882352948188782, 0.5529412031173706, 0.3843137323856354], + [0.5529412031173706, 0.6274510025978088, 0.7960784435272217], + [0.9058823585510254, 0.5411764979362488, 0.7647058963775635], + [0.6509804129600525, 0.8470588326454163, 0.3294117748737335], + [1.0, 0.8509804010391235, 0.18431372940540314], + [0.8980392217636108, 0.7686274647712708, 0.5803921818733215], + [0.7019608020782471, 0.7019608020782471, 0.7019608020782471], + ] return DiscreteColorMapper.from_palette_array(data, range=range, **traits) def Set3(range, **traits): - """ Generator for the 'Set1' colormap from ColorBrewer. + """Generator for the 'Set1' colormap from ColorBrewer. Although the ColorBrewer colormaps are defined as discrete colormaps, we create continuous colormaps from them by linear interpolation in RGB colorspace. """ - data = [[0.5529412031173706, 0.8274509906768799, 0.7803921699523926], - [1.0, 1.0, 0.7019608020782471], - [0.7450980544090271, 0.729411780834198, 0.8549019694328308], - [0.9843137264251709, 0.501960813999176, 0.4470588266849518], - [0.501960813999176, 0.6941176652908325, 0.8274509906768799], - [0.9921568632125854, 0.7058823704719543, 0.3843137323856354], - [0.7019608020782471, 0.8705882430076599, 0.4117647111415863], - [0.9882352948188782, 0.8039215803146362, 0.8980392217636108], - [0.8509804010391235, 0.8509804010391235, 0.8509804010391235], - [0.7372549176216125, 0.501960813999176, 0.7411764860153198], - [0.800000011920929, 0.9215686321258545, 0.772549033164978], - [1.0, 0.929411768913269, 0.43529412150382996]] + data = [ + [0.5529412031173706, 0.8274509906768799, 0.7803921699523926], + [1.0, 1.0, 0.7019608020782471], + [0.7450980544090271, 0.729411780834198, 0.8549019694328308], + [0.9843137264251709, 0.501960813999176, 0.4470588266849518], + [0.501960813999176, 0.6941176652908325, 0.8274509906768799], + [0.9921568632125854, 0.7058823704719543, 0.3843137323856354], + [0.7019608020782471, 0.8705882430076599, 0.4117647111415863], + [0.9882352948188782, 0.8039215803146362, 0.8980392217636108], + [0.8509804010391235, 0.8509804010391235, 0.8509804010391235], + [0.7372549176216125, 0.501960813999176, 0.7411764860153198], + [0.800000011920929, 0.9215686321258545, 0.772549033164978], + [1.0, 0.929411768913269, 0.43529412150382996], + ] return DiscreteColorMapper.from_palette_array(data, range=range, **traits) diff --git a/chaco/default_colors.py b/chaco/default_colors.py index 2212fd7d0..998bf4cc3 100644 --- a/chaco/default_colors.py +++ b/chaco/default_colors.py @@ -4,17 +4,17 @@ # This is a palette of 10 nice colors to use for mapping/discrete # color differentiation. From ColorBrewer. cbrewer = [ - (0.65098039, 0.80784314, 0.89019608, 1.0), - (0.12156863, 0.47058824, 0.70588235, 1.0), - (0.69803922, 0.8745098 , 0.54117647, 1.0), - (0.2 , 0.62745098, 0.17254902, 1.0), - (0.98431373, 0.60392157, 0.6 , 1.0), - (0.89019608, 0.10196078, 0.10980392, 1.0), - (0.99215686, 0.74901961, 0.43529412, 1.0), - (1. , 0.49803922, 0. , 1.0), - (0.79215686, 0.69803922, 0.83921569, 1.0), - (0.41568627, 0.23921569, 0.60392157, 1.0), - ] + (0.65098039, 0.80784314, 0.89019608, 1.0), + (0.12156863, 0.47058824, 0.70588235, 1.0), + (0.69803922, 0.8745098, 0.54117647, 1.0), + (0.2, 0.62745098, 0.17254902, 1.0), + (0.98431373, 0.60392157, 0.6, 1.0), + (0.89019608, 0.10196078, 0.10980392, 1.0), + (0.99215686, 0.74901961, 0.43529412, 1.0), + (1.0, 0.49803922, 0.0, 1.0), + (0.79215686, 0.69803922, 0.83921569, 1.0), + (0.41568627, 0.23921569, 0.60392157, 1.0), +] palette11 = [ (0.725490, 0.329412, 0.615686, 1.0), @@ -28,7 +28,7 @@ (0.388235, 0.647059, 0.537255, 1.0), (0.545098, 0.686275, 0.874510, 1.0), (0.623529, 0.501961, 0.862745, 1.0), - ] +] palette14 = [ (0.286275, 0.235294, 0.545098, 1.0), @@ -45,8 +45,6 @@ (0.000000, 0.600000, 0.984314, 1.0), (0.470588, 0.917647, 0.478431, 1.0), (0.627451, 0.250980, 0.815686, 1.0), - ] +] PALETTES = [cbrewer, palette11, palette14] - - diff --git a/chaco/discrete_color_mapper.py b/chaco/discrete_color_mapper.py index 03e5670f1..ebf3160ba 100644 --- a/chaco/discrete_color_mapper.py +++ b/chaco/discrete_color_mapper.py @@ -1,4 +1,3 @@ - from numpy import asarray, floor, ones from traits.api import Array, Str, observe @@ -7,7 +6,7 @@ class DiscreteColorMapper(AbstractColormap): - """ Very simple colormaper for categorical data + """Very simple colormaper for categorical data This colormapper holds a palette of colors and expects to be given and array of integer values between 0 and the number of colors - 1. @@ -25,23 +24,24 @@ class DiscreteColorMapper(AbstractColormap): _palette = Array(shape=(None, (3, 4)), dtype=float) #: the palette as uint8 values - _uint8_palette = Array(shape=(None, (3, 4)), dtype='uint8') + _uint8_palette = Array(shape=(None, (3, 4)), dtype="uint8") @classmethod def from_palette_array(cls, palette, **traits): """ Creates a discrete color mapper from a palette array. """ palette = asarray(palette, dtype=float) # ignore range passed in and use fixed range instead - traits.pop('range', None) - range = DataRange1D(low=-0.5, high=len(palette)-0.5) + traits.pop("range", None) + range = DataRange1D(low=-0.5, high=len(palette) - 0.5) return cls(palette=palette, range=range, **traits) @classmethod def from_colormap(cls, colormap, steps, **traits): """ Creates a discrete color mapper from a palette array. """ from chaco.data_range_1d import DataRange1D - traits.pop('range', None) - range = DataRange1D(low=-0.5, high=steps-0.5) + + traits.pop("range", None) + range = DataRange1D(low=-0.5, high=steps - 0.5) # create the colormapper and sample from it colormapper = colormap(range, steps=steps) palette = colormapper.color_bands @@ -54,7 +54,7 @@ def map_screen(self, data): def map_index(self, data): """ Maps an array of data to an array of indexes into the palette """ index = asarray(data).round() - index = index.clip(0, len(self.palette)-1).astype(int, copy=False) + index = index.clip(0, len(self.palette) - 1).astype(int, copy=False) return index def map_uint8(self, data): @@ -65,11 +65,11 @@ def reverse_colormap(self): """ Reverses the palette of this colormap. """ self.palette = self.palette[::-1] - @observe('palette, color_depth') + @observe("palette, color_depth") def _update_palettes(self, event): """ Generate palette adjusted for color depth and fire update event""" n_colors, n_components = self.palette.shape - if self.color_depth == 'rgba': + if self.color_depth == "rgba": if n_components == 3: palette = ones(shape=(n_colors, 4)) palette[:, :3] = self.palette @@ -79,7 +79,7 @@ def _update_palettes(self, event): palette = self.palette[:, :3] palette = palette.clip(0.0, 1.0) - uint8_palette = floor(palette*256).clip(0, 255).astype('uint8') + uint8_palette = floor(palette * 256).clip(0, 255).astype("uint8") self._palette = palette self._uint8_palette = uint8_palette diff --git a/chaco/downsample/lttb.py b/chaco/downsample/lttb.py index b4b08f73d..53f52720b 100644 --- a/chaco/downsample/lttb.py +++ b/chaco/downsample/lttb.py @@ -13,7 +13,7 @@ def largest_triangle_three_buckets(points, n_buckets): - """ Apply the largest triangle three buckets algorithm to data points + """Apply the largest triangle three buckets algorithm to data points This function assumes that all values are finite and the index values are monotone increasing. diff --git a/chaco/downsample/tests/test_lttb.py b/chaco/downsample/tests/test_lttb.py index c0a1b13a6..b4eb2cf95 100644 --- a/chaco/downsample/tests/test_lttb.py +++ b/chaco/downsample/tests/test_lttb.py @@ -19,13 +19,12 @@ class TestLargestTriangleThreeBuckets(unittest.TestCase): - def test_timing(self): - statement = 'largest_triangle_three_buckets(a, n_buckets)' + statement = "largest_triangle_three_buckets(a, n_buckets)" timer = timeit.Timer(statement, setup=TIMING_SETUP) - t = min(timer.repeat(repeat=3, number=100))/100. + t = min(timer.repeat(repeat=3, number=100)) / 100.0 # Fairly arbitrary, but if we can't do a million points in 0.1 seconds # then this isn't worth it. A capable machine should be able to do @@ -36,7 +35,7 @@ def test_timing(self): self.assertLess(t, 0.1) def test_linear(self): - a = np.empty(shape=(101,2)) + a = np.empty(shape=(101, 2)) a[:, 0] = np.linspace(0.0, 10.0, 101) a[:, 1] = np.linspace(0.0, 10.0, 101) n_buckets = 12 @@ -44,23 +43,26 @@ def test_linear(self): result = largest_triangle_three_buckets(a, n_buckets) self.assertEqual(result.shape, (12, 2)) - assert_almost_equal(result, [ - [0.0, 0.0], - [0.1, 0.1], - [1.0, 1.0], - [2.0, 2.0], - [3.0, 3.0], - [4.0, 4.0], - [5.0, 5.0], - [6.0, 6.0], - [7.0, 7.0], - [8.0, 8.0], - [9.0, 9.0], - [10.0, 10.0], - ]) + assert_almost_equal( + result, + [ + [0.0, 0.0], + [0.1, 0.1], + [1.0, 1.0], + [2.0, 2.0], + [3.0, 3.0], + [4.0, 4.0], + [5.0, 5.0], + [6.0, 6.0], + [7.0, 7.0], + [8.0, 8.0], + [9.0, 9.0], + [10.0, 10.0], + ], + ) def test_spike(self): - a = np.empty(shape=(31,2)) + a = np.empty(shape=(31, 2)) a[:, 0] = np.linspace(0.0, 3.0, 31) a[:, 1] = np.linspace(0.0, 3.0, 31) a[15, 1] = 100.0 @@ -69,18 +71,21 @@ def test_spike(self): result = largest_triangle_three_buckets(a, n_buckets) self.assertEqual(result.shape, (5, 2)) - assert_almost_equal(result, [ - [0.0, 0.0], - [0.9, 0.9], - [1.5, 100], - [2.0, 2.0], - [3.0, 3.0], - ]) + assert_almost_equal( + result, + [ + [0.0, 0.0], + [0.9, 0.9], + [1.5, 100], + [2.0, 2.0], + [3.0, 3.0], + ], + ) def test_concave_up(self): - a = np.empty(shape=(101,2)) + a = np.empty(shape=(101, 2)) a[:, 0] = np.linspace(0.0, 10.0, 101) - a[:, 1] = np.linspace(0.0, 10.0, 101)**2 + a[:, 1] = np.linspace(0.0, 10.0, 101) ** 2 n_buckets = 12 result = largest_triangle_three_buckets(a, n_buckets) @@ -92,9 +97,9 @@ def test_concave_up(self): assert_almost_equal(result[:, 0], expected_points) def test_concave_down(self): - a = np.empty(shape=(101,2)) + a = np.empty(shape=(101, 2)) a[:, 0] = np.linspace(0.0, 10.0, 101) - a[:, 1] = -np.linspace(0.0, 10.0, 101)**2 + a[:, 1] = -np.linspace(0.0, 10.0, 101) ** 2 n_buckets = 12 result = largest_triangle_three_buckets(a, n_buckets) @@ -104,10 +109,10 @@ def test_concave_down(self): ) self.assertEqual(result.shape, (12, 2)) assert_almost_equal(result[:, 0], expected_points) - assert_almost_equal(result[:, 1], -expected_points**2) + assert_almost_equal(result[:, 1], -(expected_points ** 2)) def test_empty(self): - a = np.zeros(shape=(0,2)) + a = np.zeros(shape=(0, 2)) n_buckets = 0 result = largest_triangle_three_buckets(a, n_buckets) @@ -115,7 +120,7 @@ def test_empty(self): self.assertEqual(result.shape, (0, 2)) def test_negative_buckets(self): - a = np.zeros(shape=(10,2)) + a = np.zeros(shape=(10, 2)) n_buckets = -10 result = largest_triangle_three_buckets(a, n_buckets) @@ -123,7 +128,7 @@ def test_negative_buckets(self): assert_array_equal(result, a) def test_zero_buckets(self): - a = np.zeros(shape=(10,2)) + a = np.zeros(shape=(10, 2)) n_buckets = 0 result = largest_triangle_three_buckets(a, n_buckets) @@ -131,7 +136,7 @@ def test_zero_buckets(self): assert_array_equal(result, a) def test_single_bucket(self): - a = np.zeros(shape=(10,2)) + a = np.zeros(shape=(10, 2)) n_buckets = 1 result = largest_triangle_three_buckets(a, n_buckets) @@ -139,7 +144,7 @@ def test_single_bucket(self): assert_array_equal(result, a) def test_two_buckets(self): - a = np.zeros(shape=(10,2)) + a = np.zeros(shape=(10, 2)) n_buckets = 2 result = largest_triangle_three_buckets(a, n_buckets) @@ -147,9 +152,9 @@ def test_two_buckets(self): assert_array_equal(result, a) def test_three_buckets(self): - a = np.zeros(shape=(10,2)) + a = np.zeros(shape=(10, 2)) n_buckets = 3 result = largest_triangle_three_buckets(a, n_buckets) - assert_array_equal(result, [[0.0, 0.0]]*3) + assert_array_equal(result, [[0.0, 0.0]] * 3) diff --git a/chaco/errorbar_plot.py b/chaco/errorbar_plot.py index 3b6db3f46..50b042597 100644 --- a/chaco/errorbar_plot.py +++ b/chaco/errorbar_plot.py @@ -1,6 +1,3 @@ - - - # Major library imports from numpy import column_stack, compress, invert, isnan, transpose import logging @@ -16,10 +13,8 @@ logger = logging.getLogger(__name__) - class ErrorBarPlot(LinePlot): - """ Renders errorbars at various points. - """ + """Renders errorbars at various points.""" #: The datasource containing the low values value_low = Instance(AbstractDataSource) @@ -37,7 +32,7 @@ class ErrorBarPlot(LinePlot): _cached_data_pts = Any def map_screen(self, data_array): - """ data_array can be Nx2 or Nx3. In the former case, each row is + """data_array can be Nx2 or Nx3. In the former case, each row is treated as (index, value), and this method returns screen X and Y coordinates. In the latter case, each row is treated as (index, value_low, value_high), and the method returns either (x, ylow, yhigh) @@ -75,8 +70,8 @@ def _gather_points(self): if 0 in (l1, l2, l3) or not (l1 == l2 == l3): logger.warning( "Chaco: using empty dataset; index_len=%d, " - "value_low_len=%d, value_high_len=%d." - % (l1,l2,l3)) + "value_low_len=%d, value_high_len=%d." % (l1, l2, l3) + ) self._cached_data_pts = [] self._cache_valid = True return @@ -87,7 +82,9 @@ def _gather_points(self): value_range_mask = value_low_mask | value_high_mask nan_mask = invert(isnan(index_mask) | isnan(value_mask)) - point_mask = index_mask & value_mask & nan_mask & index_range_mask & value_range_mask + point_mask = ( + index_mask & value_mask & nan_mask & index_range_mask & value_range_mask + ) points = column_stack((index, value_low, value_high)) @@ -132,7 +129,7 @@ def _render(self, gc, points, icon_mode=False): self._draw_default_axes(gc) def _render_bar_endcap(self, gc, start, end, low, high, axis): - """ Renders the endcaps for endcap_style == "bar". start and end are + """Renders the endcaps for endcap_style == "bar". start and end are the two endpoints of the bare errorbar. axis is the column index corresponding to the index direction, so for orientation of 'h', axis is 0. @@ -140,15 +137,15 @@ def _render_bar_endcap(self, gc, start, end, low, high, axis): This method modifies start and end. """ delta = self.endcap_size / 2.0 - start[:,axis] -= delta - end[:,axis] += delta + start[:, axis] -= delta + end[:, axis] += delta - start[:,1-axis] = low - end[:,1-axis] = low + start[:, 1 - axis] = low + end[:, 1 - axis] = low gc.line_set(start, end) - start[:,1-axis] = high - end[:,1-axis] = high + start[:, 1 - axis] = high + end[:, 1 - axis] = high gc.line_set(start, end) gc.stroke_path() diff --git a/chaco/example_support.py b/chaco/example_support.py index 1feee78cc..2490431b6 100644 --- a/chaco/example_support.py +++ b/chaco/example_support.py @@ -1,7 +1,4 @@ - - -doc = \ -""" +doc = """ This file contains a support class that wraps up the boilerplate toolkit calls that virtually all the demo programs have to use, and doesn't actually do anything when run on its own. @@ -23,7 +20,7 @@ # early. Until it is fixed we just assume wx if we can import it. # Force the selection of a valid toolkit. if not ETSConfig.toolkit: - for toolkit, toolkit_module in (('wx', 'wx'), ('qt4', 'pyface.qt')): + for toolkit, toolkit_module in (("wx", "wx"), ("qt4", "pyface.qt")): try: __import__(toolkit_module) ETSConfig.toolkit = toolkit @@ -34,16 +31,17 @@ raise RuntimeError("Can't load wx or qt4 backend for Chaco.") -if ETSConfig.toolkit == 'wx': +if ETSConfig.toolkit == "wx": import wx class DemoFrame(wx.Frame): - """ Wraps boilerplate WX calls that almost all the demo programs have + """Wraps boilerplate WX calls that almost all the demo programs have to use. """ - def __init__ ( self, *args, **kw ): - wx.Frame.__init__( *(self,) + args, **kw ) - self.SetAutoLayout( True ) + + def __init__(self, *args, **kw): + wx.Frame.__init__(*(self,) + args, **kw) + self.SetAutoLayout(True) # Create the subclass's window self.plot_window = self._create_window() @@ -51,31 +49,32 @@ def __init__ ( self, *args, **kw ): sizer = wx.BoxSizer(wx.HORIZONTAL) sizer.Add(self.plot_window.control, 1, wx.EXPAND) self.SetSizer(sizer) - self.Show( True ) + self.Show(True) def _create_window(self): "Subclasses should override this method and return an enable.wx.Window" raise NotImplementedError - - def demo_main(demo_class, size=(400,400), title="Chaco plot"): + def demo_main(demo_class, size=(400, 400), title="Chaco plot"): "Takes the class of the demo to run as an argument." app = wx.PySimpleApp() frame = demo_class(None, size=size, title=title) app.SetTopWindow(frame) app.MainLoop() -elif ETSConfig.toolkit == 'qt4': + +elif ETSConfig.toolkit == "qt4": from pyface.qt import QtGui _app = QtGui.QApplication.instance() if _app is None: import sys + _app = QtGui.QApplication(sys.argv) class DemoFrame(QtGui.QWidget): - def __init__ (self, parent, **kw): + def __init__(self, parent, **kw): QtGui.QWidget.__init__(self) # Create the subclass's window @@ -87,11 +86,11 @@ def __init__ (self, parent, **kw): self.setLayout(layout) - if 'size' in kw: - self.resize(*kw['size']) + if "size" in kw: + self.resize(*kw["size"]) - if 'title' in kw: - self.setWindowTitle(kw['title']) + if "title" in kw: + self.setWindowTitle(kw["title"]) self.show() @@ -99,13 +98,13 @@ def _create_window(self): "Subclasses should override this method and return an enable.Window" raise NotImplementedError - - def demo_main(demo_class, size=(400,400), title="Chaco plot"): + def demo_main(demo_class, size=(400, 400), title="Chaco plot"): "Takes the class of the demo to run as an argument." frame = demo_class(None, size=size, title=title) _app.exec_() -elif ETSConfig.toolkit == 'pyglet': + +elif ETSConfig.toolkit == "pyglet": from enable.pyglet_backend.pyglet_app import get_app, PygletApp class DemoFrame(object): @@ -119,8 +118,8 @@ def __init__(self): def _create_window(self): raise NotImplementedError - def demo_main(demo_class, size=(640,480), title="Chaco Example"): - """ Runs a simple application in Pyglet using an instance of + def demo_main(demo_class, size=(640, 480), title="Chaco Example"): + """Runs a simple application in Pyglet using an instance of **demo_class** as the main window or frame. **demo_class** should be a subclass of DemoFrame or the pyglet diff --git a/chaco/filled_line_plot.py b/chaco/filled_line_plot.py index d61542566..05a599971 100644 --- a/chaco/filled_line_plot.py +++ b/chaco/filled_line_plot.py @@ -1,6 +1,3 @@ - - - from numpy import empty from traits.api import Property, Enum @@ -10,8 +7,9 @@ def Alias(name): - return Property(lambda obj: getattr(obj, name), - lambda obj, val: setattr(obj, name, val)) + return Property( + lambda obj: getattr(obj, name), lambda obj, val: setattr(obj, name, val) + ) class FilledLinePlot(PolygonPlot): @@ -42,17 +40,20 @@ def _render(self, gc, points): return render_method_dict = { - "hold": LinePlot._render_hold, - "connectedhold": LinePlot._render_connected_hold, - "connectedpoints": LinePlot._render_normal - } - render_lines = render_method_dict.get(self.render_style, LinePlot._render_normal) - - if self.fill_direction == 'down': - ox, oy = self.map_screen([[0,0]])[0] + "hold": LinePlot._render_hold, + "connectedhold": LinePlot._render_connected_hold, + "connectedpoints": LinePlot._render_normal, + } + render_lines = render_method_dict.get( + self.render_style, LinePlot._render_normal + ) + + if self.fill_direction == "down": + ox, oy = self.map_screen([[0, 0]])[0] else: - ox, oy = self.map_screen([[self.x_mapper.range.high, - self.y_mapper.range.high]])[0] + ox, oy = self.map_screen( + [[self.x_mapper.range.high, self.y_mapper.range.high]] + )[0] with gc: gc.clip_to_rect(self.x, self.y, self.width, self.height) @@ -60,19 +61,19 @@ def _render(self, gc, points): # If the fill color is not transparent, then draw the fill polygon first face_col = self.effective_face_color if not (len(face_col) == 4 and face_col[-1] == 0): - if self.render_style in ("hold","connectedhold"): + if self.render_style in ("hold", "connectedhold"): # Modify the points array before passing it in to render_polys: # Between every two points, create an intermediate point with # the first point's Y and the second point's X. (For vertical # plots, use the first point's X and the second point's Y.) - new_points = empty((points.shape[0]*2-1, 2)) + new_points = empty((points.shape[0] * 2 - 1, 2)) new_points[::2] = points if self.orientation == "h": - new_points[1::2,0] = points[1:,0] - new_points[1::2,1] = points[:-1,1] + new_points[1::2, 0] = points[1:, 0] + new_points[1::2, 1] = points[:-1, 1] else: - new_points[1::2,0] = points[:-1,0] - new_points[1::2,1] = points[1:,1] + new_points[1::2, 0] = points[:-1, 0] + new_points[1::2, 1] = points[1:, 1] points = new_points self._render_polys(gc, points, ox, oy) @@ -80,7 +81,9 @@ def _render(self, gc, points): # If the line color is not transparent, or tha same color # as the filled area: edge_col = self.effective_edge_color - if (not (len(edge_col) == 4 and edge_col[-1] == 0)) and edge_col != face_col: + if ( + not (len(edge_col) == 4 and edge_col[-1] == 0) + ) and edge_col != face_col: gc.set_stroke_color(edge_col) gc.set_line_width(self.edge_width) gc.set_line_dash(self.edge_style_) @@ -88,7 +91,6 @@ def _render(self, gc, points): # Nans, and its rendering methods expect lists of disjoint arrays. render_lines(gc, [points], self.orientation) - def _render_polys(self, gc, points, ox, oy): face_col = self.effective_face_color gc.set_fill_color(face_col) diff --git a/chaco/function_data_source.py b/chaco/function_data_source.py index 2f8274f37..db39641d1 100644 --- a/chaco/function_data_source.py +++ b/chaco/function_data_source.py @@ -14,7 +14,7 @@ class FunctionDataSource(ArrayDataSource): - """ A data source that lazily generates its data array from a callable. + """A data source that lazily generates its data array from a callable. The signature of the :attr:`func` attribute is `func(low, high)` where `low` and `high` are attributes of the :attr:`data_range` attribute @@ -23,6 +23,7 @@ class FunctionDataSource(ArrayDataSource): This class does not listen to the array for value changes; if you need that behavior, create a subclass that hooks up the appropriate listeners. """ + # The function to call with the low and high values of the range. # It should return an array of values. func = Callable @@ -36,7 +37,7 @@ def __init__(self, **kw): AbstractDataSource.__init__(self, **kw) self.recalculate() - @observe('data_range.updated') + @observe("data_range.updated") def recalculate(self, event=None): if self.func is not None and self.data_range is not None: newarray = self.func(self.data_range.low, self.data_range.high) @@ -45,8 +46,7 @@ def recalculate(self, event=None): self._data = array([], dtype=float) def set_data(self, *args, **kw): - raise RuntimeError("Cannot set numerical data on a {0}".format( - self.__class__)) + raise RuntimeError("Cannot set numerical data on a {0}".format(self.__class__)) def set_mask(self, mask): # This would be REALLY FREAKING SLICK, but it's current unimplemented diff --git a/chaco/function_image_data.py b/chaco/function_image_data.py index 75d47ef5a..331d68eff 100644 --- a/chaco/function_image_data.py +++ b/chaco/function_image_data.py @@ -9,8 +9,9 @@ # it would be awesome if there was a mechanism for returning # partial results as they become available. + class FunctionImageData(ImageData): - """ A class that provides data for a 2-D image based upon the range + """A class that provides data for a 2-D image based upon the range supplied. This class can be used as the data source for an image plot or contour plot. @@ -31,14 +32,14 @@ def __init__(self, **kw): # Explicitly construct the initial data set for ImageData self.recalculate() - @observe('data_range.updated') + @observe("data_range.updated") def recalculate(self, event=None): if self.func is not None and self.data_range is not None: newarray = self.func( self.data_range.x_range.low, self.data_range.x_range.high, self.data_range.y_range.low, - self.data_range.y_range.high + self.data_range.y_range.high, ) ImageData.set_data(self, newarray) else: diff --git a/chaco/grid.py b/chaco/grid.py index f909cb694..7744ab9cc 100644 --- a/chaco/grid.py +++ b/chaco/grid.py @@ -3,13 +3,24 @@ """ - from numpy import around, array, asarray, column_stack, float64, inf, zeros, zeros_like # Enthought library imports from enable.api import black_color_trait, LineStyle -from traits.api import Any, Bool, Callable, Enum, Float, Instance, \ - CInt, Trait, Property, TraitError, Tuple, observe +from traits.api import ( + Any, + Bool, + Callable, + Enum, + Float, + Instance, + CInt, + Trait, + Property, + TraitError, + Tuple, + observe, +) from traitsui.api import HGroup, Item, VGroup, View, TextEditor # Local, relative imports @@ -32,40 +43,49 @@ def float_or_auto(val): return val raise TraitError("Tick interval must be a number or 'auto'.") + # View for setting grid properties. -GridView = View(VGroup( - HGroup(Item("grid_interval", label="Interval", editor=TextEditor(evaluate=float_or_auto)), - Item("visible", label="Visible")), - Item("line_color", label="Color", style="custom"), - Item("line_style", label="Dash style"), - Item("line_width", label="Thickness") - ), - buttons = ["OK", "Cancel"] - ) +GridView = View( + VGroup( + HGroup( + Item( + "grid_interval", + label="Interval", + editor=TextEditor(evaluate=float_or_auto), + ), + Item("visible", label="Visible"), + ), + Item("line_color", label="Color", style="custom"), + Item("line_style", label="Dash style"), + Item("line_width", label="Thickness"), + ), + buttons=["OK", "Cancel"], +) def Alias(name): - return Property(lambda obj: getattr(obj, name), - lambda obj, val: setattr(obj, name, val)) + return Property( + lambda obj: getattr(obj, name), lambda obj, val: setattr(obj, name, val) + ) class PlotGrid(AbstractOverlay): - """ An overlay that represents a grid. + """An overlay that represents a grid. A grid is a set of parallel lines, horizontal or vertical. You can use multiple grids with different settings for the horizontal and vertical lines in a plot. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Data-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The mapper (and associated range) that drive this PlotGrid. mapper = Instance(AbstractMapper) #: The dataspace interval between grid lines. - grid_interval = Trait('auto', 'auto', Float) + grid_interval = Trait("auto", "auto", Float) #: The dataspace value at which to start this grid. If None, then #: uses the mapper.range.low. @@ -78,14 +98,14 @@ class PlotGrid(AbstractOverlay): #: A callable that implements the AbstractTickGenerator Interface. tick_generator = Instance(AbstractTickGenerator) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Layout traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The orientation of the grid lines. "horizontal" means that the grid #: lines are parallel to the X axis and the ticker and grid interval #: refer to the Y axis. - orientation = Enum('horizontal', 'vertical') + orientation = Enum("horizontal", "vertical") #: Draw the ticks starting at the end of the mapper range? If False, the #: ticks are drawn starting at 0. This setting can be useful to keep the @@ -113,15 +133,15 @@ class PlotGrid(AbstractOverlay): #: Dimensions that the grid is resizable in (overrides PlotComponent). resizable = "hv" - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Appearance traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The color of the grid lines. line_color = black_color_trait #: The style (i.e., dash pattern) of the grid lines. - line_style = LineStyle('solid') + line_style = LineStyle("solid") #: The thickness, in pixels, of the grid lines. line_width = CInt(1) @@ -130,9 +150,9 @@ class PlotGrid(AbstractOverlay): #: Default Traits UI View for modifying grid attributes. traits_view = GridView - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits; mostly cached information - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ _cache_valid = Bool(False) _tick_list = Any @@ -142,31 +162,29 @@ class PlotGrid(AbstractOverlay): # i.e. the direction corresponding to self.orientation _tick_extents = Any - #_length = Float(0.0) - + # _length = Float(0.0) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, **traits): # TODO: change this back to a factory in the instance trait some day self.tick_generator = DefaultTickGenerator() super(PlotGrid, self).__init__(**traits) - self.bgcolor = "none" #make sure we're transparent + self.bgcolor = "none" # make sure we're transparent @observe("bounds.items,position.items") def invalidate(self, event=None): - """ Invalidate cached information about the grid. - """ + """Invalidate cached information about the grid.""" self._reset_cache() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # PlotComponent and AbstractOverlay interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def do_layout(self, *args, **kw): - """ Tells this component to do layout at a given size. + """Tells this component to do layout at a given size. Overrides PlotComponent. """ @@ -175,34 +193,31 @@ def do_layout(self, *args, **kw): else: super(PlotGrid, self).do_layout(*args, **kw) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _do_layout(self): - """ Performs a layout. + """Performs a layout. Overrides PlotComponent. """ def _layout_as_overlay(self, size=None, force=False): - """ Lays out the axis as an overlay on another component. - """ + """Lays out the axis as an overlay on another component.""" if self.component is not None: self.position = self.component.position self.bounds = self.component.bounds def _reset_cache(self): - """ Clears the cached tick positions. - """ + """Clears the cached tick positions.""" self._tick_positions = array([], dtype=float) self._tick_extents = array([], dtype=float) self._cache_valid = False def _compute_ticks(self, component=None): - """ Calculates the positions for the grid lines. - """ - if (self.mapper is None): + """Calculates the positions for the grid lines.""" + if self.mapper is None: self._reset_cache() self._cache_valid = True return @@ -220,8 +235,12 @@ def _compute_ticks(self, component=None): screenhigh = self.mapper.map_screen(datalow) screenlow = self.mapper.map_screen(datahigh) - if (datalow == datahigh) or (screenlow == screenhigh) or \ - (datalow in [inf, -inf]) or (datahigh in [inf, -inf]): + if ( + (datalow == datahigh) + or (screenlow == screenhigh) + or (datalow in [inf, -inf]) + or (datahigh in [inf, -inf]) + ): self._reset_cache() self._cache_valid = True return @@ -237,21 +256,29 @@ def _compute_ticks(self, component=None): position = self.position if isinstance(self.mapper, LogMapper): - scale = 'log' + scale = "log" else: - scale = 'linear' - - ticks = self.tick_generator.get_ticks(datalow, datahigh, datalow, datahigh, - self.grid_interval, use_endpoints = False, - scale=scale) + scale = "linear" + + ticks = self.tick_generator.get_ticks( + datalow, + datahigh, + datalow, + datahigh, + self.grid_interval, + use_endpoints=False, + scale=scale, + ) tick_positions = self.mapper.map_screen(array(ticks, float64)) - if self.orientation == 'horizontal': - self._tick_positions = around(column_stack((zeros_like(tick_positions) + position[0], - tick_positions))) - elif self.orientation == 'vertical': - self._tick_positions = around(column_stack((tick_positions, - zeros_like(tick_positions) + position[1]))) + if self.orientation == "horizontal": + self._tick_positions = around( + column_stack((zeros_like(tick_positions) + position[0], tick_positions)) + ) + elif self.orientation == "vertical": + self._tick_positions = around( + column_stack((tick_positions, zeros_like(tick_positions) + position[1])) + ) else: raise self.NotImplementedError @@ -259,9 +286,9 @@ def _compute_ticks(self, component=None): self._tick_extents = zeros((len(ticks), 2), dtype=float) if self.transverse_bounds is None or self.transverse_mapper is None: # No mapping needed, just use the extents - if self.orientation == 'horizontal': + if self.orientation == "horizontal": extents = (position[0], position[0] + bounds[0]) - elif self.orientation == 'vertical': + elif self.orientation == "vertical": extents = (position[1], position[1] + bounds[1]) self._tick_extents[:] = extents elif callable(self.transverse_bounds): @@ -270,25 +297,30 @@ def _compute_ticks(self, component=None): if isinstance(data_extents, tuple): self._tick_extents[:] = tmapper.map_screen(asarray(data_extents)) else: - extents = array([tmapper.map_screen(data_extents[:,0]), - tmapper.map_screen(data_extents[:,1])]).T + extents = array( + [ + tmapper.map_screen(data_extents[:, 0]), + tmapper.map_screen(data_extents[:, 1]), + ] + ).T self._tick_extents = extents else: # Already a tuple - self._tick_extents[:] = self.transverse_mapper.map_screen(asarray(self.transverse_bounds)) + self._tick_extents[:] = self.transverse_mapper.map_screen( + asarray(self.transverse_bounds) + ) self._cache_valid = True - - def _draw_overlay(self, gc, view_bounds=None, mode='normal'): - """ Draws the overlay layer of a component. + def _draw_overlay(self, gc, view_bounds=None, mode="normal"): + """Draws the overlay layer of a component. Overrides PlotComponent. """ self._draw_component(gc, view_bounds, mode) def overlay(self, other_component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Overrides AbstractOverlay. """ @@ -299,7 +331,7 @@ def overlay(self, other_component, gc, view_bounds=None, mode="normal"): self._cache_valid = False def _draw_component(self, gc, view_bounds=None, mode="normal"): - """ Draws the component. + """Draws the component. This method is preserved for backwards compatibility. Overrides PlotComponent. @@ -330,14 +362,14 @@ def _draw_component(self, gc, view_bounds=None, mode="normal"): gc.begin_path() if self.orientation == "horizontal": starts = self._tick_positions.copy() - starts[:,0] = self._tick_extents[:,0] + starts[:, 0] = self._tick_extents[:, 0] ends = self._tick_positions.copy() - ends[:,0] = self._tick_extents[:,1] + ends[:, 0] = self._tick_extents[:, 1] else: starts = self._tick_positions.copy() - starts[:,1] = self._tick_extents[:,0] + starts[:, 1] = self._tick_extents[:, 0] ends = self._tick_positions.copy() - ends[:,1] = self._tick_extents[:,1] + ends[:, 1] = self._tick_extents[:, 1] if self.flip_axis: starts, ends = ends, starts gc.line_set(starts, ends) @@ -368,13 +400,13 @@ def _bounds_changed_for_component(self): def _bounds_items_changed_for_component(self): self.invalidate() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers for visual attributes. These mostly just call request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @observe("visible,line_color,line_style,line_weight") def visual_attr_changed(self, event=None): - """ Called when an attribute that affects the appearance of the grid + """Called when an attribute that affects the appearance of the grid is changed. """ if self.component: @@ -395,8 +427,8 @@ def _orientation_changed(self): ### Persistence ########################################################### def __getstate__(self): - state = super(PlotGrid,self).__getstate__() - for key in ['_cache_valid', '_tick_list', '_tick_positions', '_tick_extents']: + state = super(PlotGrid, self).__getstate__() + for key in ["_cache_valid", "_tick_list", "_tick_positions", "_tick_extents"]: if key in state: del state[key] diff --git a/chaco/grid_data_source.py b/chaco/grid_data_source.py index 9b40122d8..5ac11a503 100644 --- a/chaco/grid_data_source.py +++ b/chaco/grid_data_source.py @@ -14,30 +14,30 @@ class GridDataSource(AbstractDataSource): - """ Implements a structured gridded 2-D data source (suitable as an index + """Implements a structured gridded 2-D data source (suitable as an index for an image, for example). """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractDataSource traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The dimensionality of the indices into this data source (overrides #: AbstractDataSource). - index_dimension = Constant('image') + index_dimension = Constant("image") #: The dimensionality of the value at each index point (overrides #: AbstractDataSource). - value_dimension = Constant('scalar') + value_dimension = Constant("scalar") #: The sort order of the data (overrides AbstractDataSource). There is no #: overall sort order on 2-D data, but for gridded 2-D data, each axis can #: have a sort order. - sort_order =Tuple(SortOrderTrait, SortOrderTrait) + sort_order = Tuple(SortOrderTrait, SortOrderTrait) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Data grid ticks along the x (horizontal) axis. _xdata = Instance(ArrayDataSource, args=()) @@ -49,18 +49,18 @@ class GridDataSource(AbstractDataSource): # (overrides ArrayDataSource). ((min_x, max_x), (min_y, max_y)) _cached_bounds = Tuple - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ - def __init__(self, xdata=array([]), ydata=array([]), - sort_order=("none","none"), **kwargs): + def __init__( + self, xdata=array([]), ydata=array([]), sort_order=("none", "none"), **kwargs + ): super(GridDataSource, self).__init__(**kwargs) self.set_data(xdata, ydata, sort_order) def set_data(self, xdata, ydata, sort_order=None): - """ Sets the data, and optionally the sort order, for this data source. + """Sets the data, and optionally the sort order, for this data source. Parameters ---------- @@ -79,10 +79,9 @@ def set_data(self, xdata, ydata, sort_order=None): self._compute_bounds() self.data_changed = True - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractDataSource interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def get_data(self): """get_data() -> (xdata, ydata) @@ -118,13 +117,12 @@ def get_bounds(self): self._compute_bounds() return self._cached_bounds - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _compute_bounds(self, data=None): - """ Computes the minimum and maximum points (LLx, LLy) and (URx, URy) of + """Computes the minimum and maximum points (LLx, LLy) and (URx, URy) of the data. """ @@ -138,17 +136,12 @@ def _compute_bounds(self, data=None): self._cached_bounds = ((xbds[0], ybds[0]), (xbds[1], ybds[1])) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _metadata_changed(self, event): self.metadata_changed = True def _metadata_items_changed(self, event): self.metadata_changed = True - - - - - diff --git a/chaco/grid_mapper.py b/chaco/grid_mapper.py index 907d2e8ab..fa57836f5 100644 --- a/chaco/grid_mapper.py +++ b/chaco/grid_mapper.py @@ -63,9 +63,9 @@ class GridMapper(AbstractMapper): #: The aspect ratio that we wish to maintain aspect_ratio = Float(1.0) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private Traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ _updating_submappers = Bool(False) _updating_aspect = Bool(False) @@ -73,9 +73,9 @@ class GridMapper(AbstractMapper): _xmapper = Instance(Base1DMapper) _ymapper = Instance(Base1DMapper) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, x_type="linear", y_type="linear", range=None, **kwargs): # TODO: This is currently an implicit assumption, i.e. that the range @@ -112,7 +112,7 @@ def __init__(self, x_type="linear", y_type="linear", range=None, **kwargs): super(GridMapper, self).__init__(**kwargs) def map_screen(self, data_pts): - """ map_screen(data_pts) -> screen_array + """map_screen(data_pts) -> screen_array Maps values from data space into screen space. """ @@ -123,7 +123,7 @@ def map_screen(self, data_pts): return screen_pts def map_data(self, screen_pts): - """ map_data(screen_pts) -> data_vals + """map_data(screen_pts) -> data_vals Maps values from screen space into data space. """ @@ -136,9 +136,9 @@ def map_data(self, screen_pts): def map_data_array(self, screen_pts): return self.map_data(screen_pts) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private Methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _update_bounds(self): with self._update_submappers(): @@ -153,35 +153,33 @@ def _update_aspect_x(self): y_width = self._ymapper.high_pos - self._ymapper.low_pos if y_width == 0: return - y_scale = (self._ymapper.range.high - self._ymapper.range.low)/y_width + y_scale = (self._ymapper.range.high - self._ymapper.range.low) / y_width x_range_low = self._xmapper.range.low x_width = self._xmapper.high_pos - self._xmapper.low_pos sign = self._xmapper.sign * self._ymapper.sign if x_width == 0 or sign == 0: return - x_scale = sign*y_scale/self.aspect_ratio + x_scale = sign * y_scale / self.aspect_ratio with self._update_aspect(): - self._xmapper.range.set_bounds(x_range_low, x_range_low + - x_scale*x_width) + self._xmapper.range.set_bounds(x_range_low, x_range_low + x_scale * x_width) def _update_aspect_y(self): x_width = self._xmapper.high_pos - self._xmapper.low_pos if x_width == 0: return - x_scale = (self._xmapper.range.high - self._xmapper.range.low)/x_width + x_scale = (self._xmapper.range.high - self._xmapper.range.low) / x_width y_range_low = self._ymapper.range.low - y_width = self._ymapper.high_pos-self._ymapper.low_pos + y_width = self._ymapper.high_pos - self._ymapper.low_pos sign = self._xmapper.sign * self._ymapper.sign if y_width == 0 or sign == 0: return - y_scale = sign*x_scale*self.aspect_ratio + y_scale = sign * x_scale * self.aspect_ratio with self._update_aspect(): - self._ymapper.range.set_bounds(y_range_low, y_range_low + - y_scale*y_width) + self._ymapper.range.set_bounds(y_range_low, y_range_low + y_scale * y_width) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _range_changed(self, old, new): if old is not None: @@ -217,8 +215,7 @@ def _set_screen_bounds(self, new_bounds): self._update_bounds() def _get_screen_bounds(self): - return (self.x_low_pos, self.x_high_pos, - self.y_low_pos, self.y_high_pos) + return (self.x_low_pos, self.x_high_pos, self.y_low_pos, self.y_high_pos) def _updated_fired_for__xmapper(self): if not self._updating_aspect: diff --git a/chaco/horizon_plot.py b/chaco/horizon_plot.py index 1d8960957..069b04888 100644 --- a/chaco/horizon_plot.py +++ b/chaco/horizon_plot.py @@ -1,5 +1,3 @@ - - from numpy import array, float64, full_like, ndarray, transpose from traits.api import Instance, DelegatesTo, Bool, Int @@ -8,6 +6,7 @@ from chaco.base_xy_plot import BaseXYPlot from chaco.linear_mapper import LinearMapper + class BandedMapper(LinearMapper): bands = Int(4) @@ -21,11 +20,14 @@ def map_screen(self, data_array): return array([self.low_pos]) else: # Scale the data by the number of bands - return (data_array*self.bands - self.range.low) * self._scale + self.low_pos + return ( + data_array * self.bands - self.range.low + ) * self._scale + self.low_pos + class HorizonPlot(BaseXYPlot): - bands = DelegatesTo('value_mapper') + bands = DelegatesTo("value_mapper") color_mapper = Instance(ColorMapper) mirror = Bool(False) @@ -36,17 +38,17 @@ class HorizonPlot(BaseXYPlot): #: Override parent traits - orientation = 'h' + orientation = "h" def _color_mapper_changed(self, new): # change the number of steps to match the number of bands if not self.negative_bands: - new.steps = self.bands+1 + new.steps = self.bands + 1 else: - new.steps = self.bands*2+1 + new.steps = self.bands * 2 + 1 def _gather_points(self): - """ Collects the data points that are within the bounds of the plot and + """Collects the data points that are within the bounds of the plot and caches them. """ if self._cache_valid: @@ -63,7 +65,7 @@ def _gather_points(self): self._cache_valid = True return - points = transpose(array((index,value))) + points = transpose(array((index, value))) self._cached_data_pts = points self._cache_valid = True @@ -72,7 +74,7 @@ def _render(self, gc, points): if len(points) == 0: return - ox, oy = self.map_screen([[0,0]])[0] + ox, oy = self.map_screen([[0, 0]])[0] ylow, yhigh = self.value_mapper.screen_bounds y_plus_height = yhigh - oy @@ -84,28 +86,30 @@ def _render(self, gc, points): gc.clip_to_rect(self.x, self.y, self.width, self.height) # draw positive bands inc = -1 * array([0, y_plus_height]) - if self.negative_bands: render_bands = bands[self.bands+1:] - else: render_bands = bands[1:] + if self.negative_bands: + render_bands = bands[self.bands + 1 :] + else: + render_bands = bands[1:] for i, col in enumerate(render_bands): - self._render_fill(gc, col, points+i*inc, ox, oy) + self._render_fill(gc, col, points + i * inc, ox, oy) # draw negative bands if self.negative_bands: if self.mirror: - points[:,1] = oy - points[:,1] + points[:, 1] = oy - points[:, 1] zeroy = oy else: - points[:,1] += y_plus_height + points[:, 1] += y_plus_height inc *= -1 zeroy = int(yhigh) + 2 - for i, col in enumerate(bands[self.bands-1::-1]): - self._render_fill(gc, col, points+i*inc, ox, zeroy) + for i, col in enumerate(bands[self.bands - 1 :: -1]): + self._render_fill(gc, col, points + i * inc, ox, zeroy) - gc.set_stroke_color((.75, .75, .75)) + gc.set_stroke_color((0.75, 0.75, 0.75)) gc.set_line_width(2) gc.begin_path() gc.move_to(self.x, self.y) - gc.line_to(self.x+self.width, self.y) + gc.line_to(self.x + self.width, self.y) gc.stroke_path() def _render_fill(self, gc, face_col, points, ox, oy): diff --git a/chaco/image_data.py b/chaco/image_data.py index 2df59dde2..ff80c3f86 100644 --- a/chaco/image_data.py +++ b/chaco/image_data.py @@ -10,6 +10,7 @@ from .base import DimensionTrait, ImageTrait from .abstract_data_source import AbstractDataSource + class ImageData(AbstractDataSource): """ Represents a grid of data to be plotted using a Numpy 2-D grid. @@ -18,15 +19,16 @@ class ImageData(AbstractDataSource): dimensions. The appropriate dimensionality of the value array depends on the context in which the ImageData instance will be used. """ + #: The dimensionality of the data. - dimension = ReadOnly(DimensionTrait('image')) + dimension = ReadOnly(DimensionTrait("image")) #: Depth of the values at each i,j. Values that are used include: #: #: * 3: color images, without alpha channel #: * 4: color images, with alpha channel - value_depth = Int(1) # TODO: Modify ImageData to explicitly support scalar - # value arrays, as needed by CMapImagePlot + value_depth = Int(1) # TODO: Modify ImageData to explicitly support scalar + # value arrays, as needed by CMapImagePlot #: Holds the grid data that forms the image. The shape of the array is #: (N, M, D) where: @@ -60,10 +62,9 @@ class ImageData(AbstractDataSource): #: A read-only attribute that exposes the underlying array. raw_value = Property(ImageTrait) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The actual image data array. Can be MxN or NxM, depending on the value # of **transposed**. @@ -75,17 +76,18 @@ class ImageData(AbstractDataSource): # Cached value of min and max as long as **data** doesn't change. _bounds_cache = Tuple - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @classmethod def fromfile(cls, filename): - """ Alternate constructor to create an ImageData from an image file + """Alternate constructor to create an ImageData from an image file on disk. 'filename' may be a file path or a file object. """ from kiva.image import Image + img = Image(filename) imgdata = cls(data=img.bmp_array, transposed=False) fmt = img.format() @@ -95,41 +97,37 @@ def fromfile(cls, filename): elif fmt == "rgba32": imgdata.value_depth = 4 else: - raise ValueError("Unknown image format in file %s: %s" % - (filename, fmt)) + raise ValueError("Unknown image format in file %s: %s" % (filename, fmt)) return imgdata def get_width(self): - """ Returns the shape of the x-axis. - """ + """Returns the shape of the x-axis.""" if self.transposed: return self._data.shape[0] else: return self._data.shape[1] def get_height(self): - """ Returns the shape of the y-axis. - """ + """Returns the shape of the y-axis.""" if self.transposed: return self._data.shape[1] else: return self._data.shape[0] def get_array_bounds(self): - """ Always returns ((0, width), (0, height)) for x-bounds and y-bounds. - """ + """Always returns ((0, width), (0, height)) for x-bounds and y-bounds.""" if self.transposed: - b = ((0,self._data.shape[0]), (0,self._data.shape[1])) + b = ((0, self._data.shape[0]), (0, self._data.shape[1])) else: - b = ((0,self._data.shape[1]), (0,self._data.shape[0])) + b = ((0, self._data.shape[1]), (0, self._data.shape[0])) return b - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Datasource interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def get_data(self): - """ Returns the data for this data source. + """Returns the data for this data source. Implements AbstractDataSource. """ @@ -143,7 +141,7 @@ def is_masked(self): return False def get_bounds(self): - """ Returns the minimum and maximum values of the data source's data. + """Returns the minimum and maximum values of the data source's data. Implements AbstractDataSource. """ @@ -156,7 +154,8 @@ def get_bounds(self): # fmax.reduce to avoid this. self._cached_bounds = ( fmin.reduce(self.raw_value, axis=None), - fmax.reduce(self.raw_value, axis=None)) + fmax.reduce(self.raw_value, axis=None), + ) self._bounds_cache_valid = True return self._cached_bounds @@ -171,7 +170,7 @@ def get_size(self): return 0 def set_data(self, data): - """ Sets the data for this data source. + """Sets the data for this data source. Parameters ---------- @@ -180,9 +179,9 @@ def set_data(self, data): """ self._set_data(data) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_data(self): if self.transposed: @@ -198,10 +197,9 @@ def _set_data(self, newdata): def _get_raw_value(self): return self._data - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _metadata_changed(self, event): self.metadata_changed = True diff --git a/chaco/image_plot.py b/chaco/image_plot.py index bef02f1d3..c8d820797 100644 --- a/chaco/image_plot.py +++ b/chaco/image_plot.py @@ -10,7 +10,6 @@ """ - # Standard library imports from math import ceil, floor, pi from contextlib import contextmanager @@ -18,8 +17,18 @@ import numpy as np # Enthought library imports. -from traits.api import (Bool, Either, Enum, Instance, List, Range, Trait, - Tuple, Property, cached_property) +from traits.api import ( + Bool, + Either, + Enum, + Instance, + List, + Range, + Trait, + Tuple, + Property, + cached_property, +) from kiva.agg import GraphicsContextArray # Local relative imports @@ -32,20 +41,22 @@ except ImportError: pass else: - QUARTZ_INTERP_QUALITY = {"nearest": InterpolationQuality.none, - "bilinear": InterpolationQuality.low, - "bicubic": InterpolationQuality.high} + QUARTZ_INTERP_QUALITY = { + "nearest": InterpolationQuality.none, + "bilinear": InterpolationQuality.low, + "bicubic": InterpolationQuality.high, + } KIVA_DEPTH_MAP = {3: "rgb24", 4: "rgba32"} class ImagePlot(Base2DPlot): - """ A plot based on an image. - """ - #------------------------------------------------------------------------ + """A plot based on an image.""" + + # ------------------------------------------------------------------------ # Data-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Overall alpha value of the image. Ranges from 0.0 for transparent to 1.0 #: for full intensity. @@ -55,14 +66,14 @@ class ImagePlot(Base2DPlot): interpolation = Enum("nearest", "bilinear", "bicubic") #: Bool indicating whether x-axis is flipped. - x_axis_is_flipped = Property(depends_on=['orientation', 'origin']) + x_axis_is_flipped = Property(depends_on=["orientation", "origin"]) #: Bool indicating whether y-axis is flipped. - y_axis_is_flipped = Property(depends_on=['orientation', 'origin']) + y_axis_is_flipped = Property(depends_on=["orientation", "origin"]) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Are the cache traits valid? If False, new ones need to be computed. _image_cache_valid = Bool(False) @@ -76,25 +87,27 @@ class ImagePlot(Base2DPlot): # Bool indicating whether the origin is top-left or bottom-right. # The name "principal diagonal" is borrowed from linear algebra. - _origin_on_principal_diagonal = Property(depends_on='origin') + _origin_on_principal_diagonal = Property(depends_on="origin") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Properties - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @cached_property def _get_x_axis_is_flipped(self): - return ((self.orientation == 'h' and 'right' in self.origin) or - (self.orientation == 'v' and 'top' in self.origin)) + return (self.orientation == "h" and "right" in self.origin) or ( + self.orientation == "v" and "top" in self.origin + ) @cached_property def _get_y_axis_is_flipped(self): - return ((self.orientation == 'h' and 'top' in self.origin) or - (self.orientation == 'v' and 'right' in self.origin)) + return (self.orientation == "h" and "top" in self.origin) or ( + self.orientation == "v" and "right" in self.origin + ) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _index_data_changed_fired(self): self._image_cache_valid = False @@ -108,12 +121,12 @@ def _value_data_changed_fired(self): self._image_cache_valid = False self.request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Base2DPlot interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _render(self, gc): - """ Draw the plot to screen. + """Draw the plot to screen. Implements the Base2DPlot interface. """ @@ -151,9 +164,10 @@ def _render(self, gc): with self._temporary_interp_setting(gc): gc.draw_image(self._cached_image, self._cached_dest_rect) - def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, - index_only=False): - """ Maps a screen space point to an index into the plot's index + def map_index( + self, screen_pt, threshold=0.0, outside_returns_none=True, index_only=False + ): + """Maps a screen space point to an index into the plot's index array(s). Implements the AbstractPlotRenderer interface. Uses 0.0 for @@ -161,17 +175,18 @@ def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, """ # For image plots, treat hittesting threshold as 0.0, because it's # the only thing that really makes sense. - return Base2DPlot.map_index(self, screen_pt, 0.0, outside_returns_none, - index_only) + return Base2DPlot.map_index( + self, screen_pt, 0.0, outside_returns_none, index_only + ) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @cached_property def _get__origin_on_principal_diagonal(self): - bottom_right = 'bottom' in self.origin and 'right' in self.origin - top_left = 'top' in self.origin and 'left' in self.origin + bottom_right = "bottom" in self.origin and "right" in self.origin + top_left = "top" in self.origin and "left" in self.origin return bottom_right or top_left def _transpose_about_origin(self, gc): @@ -179,7 +194,7 @@ def _transpose_about_origin(self, gc): gc.scale_ctm(-1, 1) else: gc.scale_ctm(1, -1) - gc.rotate_ctm(pi/2) + gc.rotate_ctm(pi / 2) @contextmanager def _temporary_interp_setting(self, gc): @@ -203,7 +218,7 @@ def _temporary_interp_setting(self, gc): yield def _calc_virtual_screen_bbox(self): - """ Return the rectangle describing the image in screen space + """Return the rectangle describing the image in screen space assuming that the entire image could fit on screen. Zoomed-in images will have "virtual" sizes larger than the image. @@ -232,7 +247,7 @@ def _calc_virtual_screen_bbox(self): return [x_min, y_min, virtual_x_size, virtual_y_size] def _compute_cached_image(self, data=None, mapper=None): - """ Computes the correct screen coordinates and renders an image into + """Computes the correct screen coordinates and renders an image into `self._cached_image`. Parameters @@ -279,7 +294,7 @@ def _kiva_array_from_numpy_array(self, data): return GraphicsContextArray(data, pix_format=kiva_depth) def _calc_zoom_coords(self, image_rect): - """ Calculates the coordinates of a zoomed sub-image. + """Calculates the coordinates of a zoomed sub-image. Because of floating point limitations, it is not advisable to request a extreme level of zoom, e.g., idx or idy > 10^10. @@ -331,7 +346,7 @@ def _calc_zoom_coords(self, image_rect): return index_bounds, screen_rect def _array_bounds_from_screen_rect(self, image_rect): - """ Transform virtual-image rectangle into array indices. + """Transform virtual-image rectangle into array indices. The virtual-image rectangle is in screen coordinates and can be outside the plot bounds. This method converts the rectangle into array indices diff --git a/chaco/image_utils.py b/chaco/image_utils.py index c639c02de..d93b46786 100644 --- a/chaco/image_utils.py +++ b/chaco/image_utils.py @@ -1,10 +1,9 @@ - X_PARAMS = (0, 2) # index for x-position and width Y_PARAMS = (1, 3) # index for y-position and height def trim_screen_rect(screen_rect, view_rect, sub_array_size): - """ Trim sub-image screen rectangle for highly zoomed in states. + """Trim sub-image screen rectangle for highly zoomed in states. When zoomed into one or two pixels (in any dimension), the screen rectangle for those pixels can extend without bound outside of the plot area. This @@ -30,7 +29,7 @@ def trim_screen_rect(screen_rect, view_rect, sub_array_size): scale = 2 * view_rect[i_length] / float(image_length) if scale < 1: # Sub-image is two pixels wide, so pixel size is half the image - pixel_length = image_length/2 + pixel_length = image_length / 2 screen_rect[i_length] *= scale - screen_rect[i_pos] += (1-scale) * pixel_length + screen_rect[i_pos] += (1 - scale) * pixel_length return screen_rect diff --git a/chaco/jitterplot.py b/chaco/jitterplot.py index a5b95bee7..f260ecad5 100644 --- a/chaco/jitterplot.py +++ b/chaco/jitterplot.py @@ -18,18 +18,18 @@ class JitterPlot(ScatterPlot1D): # along the dimension orthogonal to the index direction. jitter_width = Int(50) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ _cached_screen_map = Any() # dict mapping index to value points - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Component/AbstractPlotRenderer interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def map_screen(self, data_array): - """ Maps an array of data points into screen space and returns it as + """Maps an array of data points into screen space and returns it as an array. Although the orthogonal (non-scaled) axis does not have a mapper, this method returns the scattered values in that dimension. @@ -63,18 +63,20 @@ def _make_jitter_vals(self, data_array): vals += self._marker_position return vals - def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, \ - index_only=True): - """ Maps a screen space point to an index into the plot's index array(s). - """ + def map_index( + self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=True + ): + """Maps a screen space point to an index into the plot's index array(s).""" screen_points = self._cached_screen_pts if len(screen_points) == 0: return None data_pt = self.map_data(screen_pt) - if ((data_pt < self.index_mapper.range.low) or \ - (data_pt > self.index_mapper.range.high)) and outside_returns_none: + if ( + (data_pt < self.index_mapper.range.low) + or (data_pt > self.index_mapper.range.high) + ) and outside_returns_none: return None if self._cached_data_pts_sorted is None: @@ -99,29 +101,31 @@ def map_index(self, screen_pt, threshold=2.0, outside_returns_none=True, \ return orig_ndx sx, sy = screen_points[orig_ndx] - if sqrt((screen_pt[0] - sx)**2 + (screen_pt[1] - sy)**2) <= threshold: + if sqrt((screen_pt[0] - sx) ** 2 + (screen_pt[1] - sy) ** 2) <= threshold: return orig_ndx else: return None - def _draw_plot(self, gc, view_bounds=None, mode="normal"): pts = self.get_screen_points() self._render(gc, pts) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def get_screen_points(self): if not self._screen_cache_valid: self._gather_points() pts = self.map_screen(self._cached_data) if self.orientation == "h": - self._cached_screen_map = dict((x,y) for x,y in zip(pts[:,0], pts[:,1])) + self._cached_screen_map = dict( + (x, y) for x, y in zip(pts[:, 0], pts[:, 1]) + ) else: - self._cached_screen_map = dict((y,x) for x,y in zip(pts[:,0], pts[:,1])) + self._cached_screen_map = dict( + (y, x) for x, y in zip(pts[:, 0], pts[:, 1]) + ) self._cached_screen_pts = pts self._screen_cache_valid = True self._cached_data_pts_sorted = None @@ -132,15 +136,15 @@ def _get_marker_position(self): x, y = self.position w, h = self.bounds - if self.orientation == 'v': + if self.orientation == "v": y, h = x, w - if self.alignment == 'center': - position = y + h/2.0 - self.jitter_width/2.0 - elif self.alignment in ['left', 'bottom']: + if self.alignment == "center": + position = y + h / 2.0 - self.jitter_width / 2.0 + elif self.alignment in ["left", "bottom"]: position = y - elif self.alignment in ['right', 'top']: - position = y + h - self.jitter_width/2.0 + elif self.alignment in ["right", "top"]: + position = y + h - self.jitter_width / 2.0 position += self.marker_offset return position diff --git a/chaco/label.py b/chaco/label.py index 7109a4102..20d93979f 100644 --- a/chaco/label.py +++ b/chaco/label.py @@ -2,7 +2,6 @@ """ - # Major library imports from math import cos, sin, pi from numpy import array, dot @@ -11,13 +10,11 @@ from enable.api import black_color_trait, transparent_color_trait from kiva.constants import FILL from kiva.trait_defs.kiva_font_trait import KivaFont -from traits.api import ( - Any, Bool, Float, HasTraits, Int, List, Str, observe -) +from traits.api import Any, Bool, Float, HasTraits, Int, List, Str, observe class Label(HasTraits): - """ A label used by overlays. + """A label used by overlays. Label is not a Component; it's just an object encapsulating text settings and appearance attributes. It can be used by components that need text @@ -30,7 +27,7 @@ class Label(HasTraits): # margin), while "center" refers to the horizontal and vertical center # of the bounding box. # TODO: Implement this and test thoroughly - #anchor = Enum("left", "right", "top", "bottom", "center", + # anchor = Enum("left", "right", "top", "bottom", "center", # "top left", "top right", "bottom left", "bottom right") #: The label text. Carriage returns (\n) are always connverted into @@ -70,9 +67,9 @@ class Label(HasTraits): #: A `max_width` of 0.0 means that lines will not be broken. max_width = Float(0.0) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ _bounding_box = List() _position_cache_valid = Bool(False) @@ -86,7 +83,7 @@ def __init__(self, **traits): self._bounding_box = [0, 0] def get_width_height(self, gc): - """ Returns the width and height of the label, in the rotated frame of + """Returns the width and height of the label, in the rotated frame of reference. """ self._fit_text_to_max_width(gc) @@ -95,8 +92,7 @@ def get_width_height(self, gc): return width, height def get_bounding_box(self, gc): - """ Returns a rectangular bounding box for the Label as (width,height). - """ + """Returns a rectangular bounding box for the Label as (width,height).""" width, height = self.get_width_height(gc) if self.rotate_angle in (90.0, 270.0): return (height, width) @@ -104,34 +100,42 @@ def get_bounding_box(self, gc): return (width, height) else: angle = self.rotate_angle - return (abs(width*cos(angle))+abs(height*sin(angle)), - abs(height*sin(angle))+abs(width*cos(angle))) + return ( + abs(width * cos(angle)) + abs(height * sin(angle)), + abs(height * sin(angle)) + abs(width * cos(angle)), + ) def get_bounding_poly(self, gc): - """ Returns a list [(x0,y0), (x1,y1),...] of tuples representing a + """Returns a list [(x0,y0), (x1,y1),...] of tuples representing a polygon that bounds the label. """ width, height = self.get_width_height(gc) - offset = array(self.get_bounding_box(gc))/2. + offset = array(self.get_bounding_box(gc)) / 2.0 # unrotated points relative to centre base_points = [ - array([[-width/2.], [-height/2.]]), - array([[-width/2.], [height/2.]]), - array([[width/2.], [height/2.]]), - array([[width/2.], [-height/2.]]), - array([[-width/2.], [-height/2.]]), + array([[-width / 2.0], [-height / 2.0]]), + array([[-width / 2.0], [height / 2.0]]), + array([[width / 2.0], [height / 2.0]]), + array([[width / 2.0], [-height / 2.0]]), + array([[-width / 2.0], [-height / 2.0]]), ] # rotate about centre, and offset to bounding box coords - points = [dot(self.get_rotation_matrix(), point).transpose()[0]+offset - for point in base_points] + points = [ + dot(self.get_rotation_matrix(), point).transpose()[0] + offset + for point in base_points + ] return points def get_rotation_matrix(self): - return array([[cos(self.rotate_angle), -sin(self.rotate_angle)], - [sin(self.rotate_angle), cos(self.rotate_angle)]]) + return array( + [ + [cos(self.rotate_angle), -sin(self.rotate_angle)], + [sin(self.rotate_angle), cos(self.rotate_angle)], + ] + ) def draw(self, gc): - """ Draws the label. + """Draws the label. This method assumes the graphics context has been translated to the correct position such that the origin is at the lower left-hand corner @@ -148,9 +152,9 @@ def draw(self, gc): # Rotate label about center of bounding box width, height = self._bounding_box - gc.translate_ctm(bb_width/2.0, bb_height/2.0) - gc.rotate_ctm(pi/180.0*self.rotate_angle) - gc.translate_ctm(-width/2.0, -height/2.0) + gc.translate_ctm(bb_width / 2.0, bb_height / 2.0) + gc.rotate_ctm(pi / 180.0 * self.rotate_angle) + gc.translate_ctm(-width / 2.0, -height / 2.0) # Draw border and fill background if self.bgcolor != "transparent": @@ -159,9 +163,13 @@ def draw(self, gc): if self.border_visible and self.border_width > 0: gc.set_stroke_color(self.border_color_) gc.set_line_width(self.border_width) - border_offset = (self.border_width-1)/2.0 - gc.rect(border_offset, border_offset, - width-2*border_offset, height-2*border_offset) + border_offset = (self.border_width - 1) / 2.0 + gc.rect( + border_offset, + border_offset, + width - 2 * border_offset, + height - 2 * border_offset, + ) gc.stroke_path() gc.set_fill_color(self.color_) @@ -185,23 +193,23 @@ def draw(self, gc): gc.set_text_position(x_offset, y_offset) gc.show_text(line) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _text_changed(self): - self._text_needs_fitting = (self.max_width > 0.0) + self._text_needs_fitting = self.max_width > 0.0 @observe("font,margin,text,rotate_angle") def _invalidate_position_cache(self, event): self._position_cache_valid = False - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _fit_text_to_max_width(self, gc): - """ Break the text into lines whose width is no greater than + """Break the text into lines whose width is no greater than `max_width`. """ if self._text_needs_fitting: @@ -209,7 +217,7 @@ def _fit_text_to_max_width(self, gc): with gc: gc.set_font(self.font) - for line in self.text.split('\n'): + for line in self.text.split("\n"): if line == "": lines.append(line) continue @@ -219,20 +227,20 @@ def _fit_text_to_max_width(self, gc): line_words = [] for word in line.split(): line_words.append(word) - test_line = ' '.join(line_words) + test_line = " ".join(line_words) width = gc.get_full_text_extent(test_line)[0] if width > self.max_width: if len(line_words) > 1: - lines.append(' '.join(line_words[:-1])) + lines.append(" ".join(line_words[:-1])) line_words = [word] else: lines.append(word) line_words = [] if len(line_words) > 0: - lines.append(' '.join(line_words)) + lines.append(" ".join(line_words)) else: lines.append(line) - self.trait_setq(text='\n'.join(lines)) + self.trait_setq(text="\n".join(lines)) self._text_needs_fitting = False def _calc_line_positions(self, gc): @@ -249,20 +257,19 @@ def _calc_line_positions(self, gc): max_width = 0 for line in self.text.split("\n")[::-1]: if line != "": - (width, height, descent, leading) = \ - gc.get_full_text_extent(line) + (width, height, descent, leading) = gc.get_full_text_extent( + line + ) ascent = height - abs(descent) if width > max_width: max_width = width - new_y_pos = prev_y_pos + prev_y_height \ - + self.line_spacing + new_y_pos = prev_y_pos + prev_y_height + self.line_spacing else: # For blank lines, we use the height of the previous # line, if there is one. The width is 0. leading = 0 if prev_y_height != -self.line_spacing: - new_y_pos = prev_y_pos + prev_y_height \ - + self.line_spacing + new_y_pos = prev_y_pos + prev_y_height + self.line_spacing ascent = prev_y_height else: new_y_pos = prev_y_pos @@ -275,7 +282,8 @@ def _calc_line_positions(self, gc): self._line_xpos = x_pos[::-1] self._line_ypos = y_pos[::-1] border_width = self.border_width if self.border_visible else 0 - self._bounding_box[0] = max_width + 2*margin + 2*border_width - self._bounding_box[1] = prev_y_pos + prev_y_height + margin \ - + 2*border_width + self._bounding_box[0] = max_width + 2 * margin + 2 * border_width + self._bounding_box[1] = ( + prev_y_pos + prev_y_height + margin + 2 * border_width + ) self._position_cache_valid = True diff --git a/chaco/label_axis.py b/chaco/label_axis.py index 25fc91217..ea81b5757 100644 --- a/chaco/label_axis.py +++ b/chaco/label_axis.py @@ -13,8 +13,7 @@ class LabelAxis(PlotAxis): - """ An axis whose ticks are labeled with text instead of numbers. - """ + """An axis whose ticks are labeled with text instead of numbers.""" #: List of labels to use on tick marks. labels = List(Str) @@ -26,11 +25,11 @@ class LabelAxis(PlotAxis): positions = ArrayOrNone() def _compute_tick_positions(self, gc, component=None): - """ Calculates the positions for the tick marks. + """Calculates the positions for the tick marks. Overrides PlotAxis. """ - if (self.mapper is None): + if self.mapper is None: self._reset_cache() self._cache_valid = True return @@ -40,8 +39,12 @@ def _compute_tick_positions(self, gc, component=None): screenhigh = self.mapper.high_pos screenlow = self.mapper.low_pos - if (datalow == datahigh) or (screenlow == screenhigh) or \ - (datalow in [inf, -inf]) or (datahigh in [inf, -inf]): + if ( + (datalow == datahigh) + or (screenlow == screenhigh) + or (datalow in [inf, -inf]) + or (datahigh in [inf, -inf]) + ): self._reset_cache() self._cache_valid = True return @@ -50,9 +53,12 @@ def _compute_tick_positions(self, gc, component=None): return # Get a set of ticks from the tick generator. - tick_list = array(self.tick_generator.get_ticks(datalow, datahigh, - datalow, datahigh, - self.tick_interval), float64) + tick_list = array( + self.tick_generator.get_ticks( + datalow, datahigh, datalow, datahigh, self.tick_interval + ), + float64, + ) # Find all the positions in the current range. pos_index = [] @@ -76,16 +82,22 @@ def _compute_tick_positions(self, gc, component=None): # the positions to be displayed. tick_indices = unique(searchsorted(pos, tick_list)) tick_indices = tick_indices[tick_indices < len(pos)] - tick_positions = take(pos, tick_indices) + tick_positions = take(pos, tick_indices) self._tick_label_list = take(self.labels, take(pos_index, tick_indices)) if datalow > datahigh: - raise RuntimeError("DataRange low is greater than high; unable to compute axis ticks.") - - mapped_label_positions = [((self.mapper.map_screen(pos)-screenlow) / \ - (screenhigh-screenlow)) for pos in tick_positions] - self._tick_positions = [self._axis_vector*tickpos + self._origin_point \ - for tickpos in mapped_label_positions] + raise RuntimeError( + "DataRange low is greater than high; unable to compute axis ticks." + ) + + mapped_label_positions = [ + ((self.mapper.map_screen(pos) - screenlow) / (screenhigh - screenlow)) + for pos in tick_positions + ] + self._tick_positions = [ + self._axis_vector * tickpos + self._origin_point + for tickpos in mapped_label_positions + ] self._tick_label_positions = self._tick_positions def _compute_labels(self, gc): @@ -96,11 +108,17 @@ def _compute_labels(self, gc): try: self.ticklabel_cache = [] for text in self._tick_label_list: - ticklabel = Label(text=text, font=self.tick_label_font, - color=self.tick_label_color, - rotate_angle=self.label_rotation) + ticklabel = Label( + text=text, + font=self.tick_label_font, + color=self.tick_label_color, + rotate_angle=self.label_rotation, + ) self.ticklabel_cache.append(ticklabel) - self._tick_label_bounding_boxes = [array(ticklabel.get_bounding_box(gc), float64) for ticklabel in self.ticklabel_cache] + self._tick_label_bounding_boxes = [ + array(ticklabel.get_bounding_box(gc), float64) + for ticklabel in self.ticklabel_cache + ] except: print_exc() diff --git a/chaco/lasso_overlay.py b/chaco/lasso_overlay.py index 1fb0a976a..7d115ff64 100644 --- a/chaco/lasso_overlay.py +++ b/chaco/lasso_overlay.py @@ -2,7 +2,6 @@ """ - from numpy import concatenate, newaxis # Enthought library imports @@ -12,18 +11,19 @@ # Local imports from .abstract_overlay import AbstractOverlay + class LassoOverlay(AbstractOverlay): - """ Draws a lasso selection region on top of a plot. + """Draws a lasso selection region on top of a plot. LassoOverlay gets its data from a LassoSelection. """ #: The LassoSelection that provides the data for this overlay. - lasso_selection = Instance('chaco.tools.lasso_selection.LassoSelection') + lasso_selection = Instance("chaco.tools.lasso_selection.LassoSelection") #: The fill color for the selection region. - selection_fill_color = ColorTrait('lightskyblue') + selection_fill_color = ColorTrait("lightskyblue") #: The border color for the selection region. - selection_border_color = ColorTrait('dodgerblue') + selection_border_color = ColorTrait("dodgerblue") #: The transparency level for the selection fill color. selection_alpha = Float(0.8) #: The width of the selection border. @@ -32,14 +32,14 @@ class LassoOverlay(AbstractOverlay): selection_border_dash = LineStyle #: The background color (overrides AbstractOverlay). - bgcolor = 'clear' + bgcolor = "clear" # Whether to draw the lasso # depends on the state of the lasso tool _draw_selection = Bool(False) def overlay(self, other_component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Implements AbstractOverlay. """ @@ -55,12 +55,12 @@ def _updated_changed_for_lasso_selection(self): self.component.request_redraw() def _event_state_fired_for_lasso_selection(self, val): - self._draw_selection = val == 'selecting' + self._draw_selection = val == "selecting" self.component.invalidate_draw() self.component.request_redraw() - def _draw_component(self, gc, view_bounds=None, mode='normal'): - """ Draws the component. + def _draw_component(self, gc, view_bounds=None, mode="normal"): + """Draws the component. This method is preserved for backwards compatibility with _old_draw(). Overrides PlotComponent. diff --git a/chaco/layers/status_layer.py b/chaco/layers/status_layer.py index cea16e9e8..99efa6f86 100644 --- a/chaco/layers/status_layer.py +++ b/chaco/layers/status_layer.py @@ -1,6 +1,3 @@ - - - import os.path import xml.etree.cElementTree as etree @@ -10,6 +7,7 @@ from enable.savage.svg.document import SVGDocument from enable.savage.svg.backends.kiva.renderer import Renderer as KivaRenderer + class StatusLayer(AbstractOverlay): filename = Str() @@ -21,7 +19,7 @@ class StatusLayer(AbstractOverlay): # The type determines if the layer is displayed as part of the component's # overlay or underlays - type = Enum('overlay', 'underlay') + type = Enum("overlay", "underlay") # The position of the legend with respect to its overlaid component. # @@ -51,20 +49,20 @@ def __init__(self, component, *args, **kw): super(StatusLayer, self).__init__(component, *args, **kw) if self.document is None: - if self.filename == '': - self.filename = os.path.join(os.path.dirname(__file__), 'data', - 'Dialog-error.svg') + if self.filename == "": + self.filename = os.path.join( + os.path.dirname(__file__), "data", "Dialog-error.svg" + ) tree = etree.parse(self.filename) root = tree.getroot() self.document = SVGDocument(root, renderer=KivaRenderer) - if hasattr(self.document, 'getSize'): + if hasattr(self.document, "getSize"): self.doc_width = self.document.getSize()[0] self.doc_height = self.document.getSize()[1] - def overlay(self, other_component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Implements AbstractOverlay. """ @@ -82,30 +80,31 @@ def overlay(self, other_component, gc, view_bounds=None, mode="normal"): # the overlay should be 50% of the width, if the plot is short and wide # the overlay should be 50% of the height. if gc.height() < gc.width(): - scale = (plot_height/self.doc_height)*self.scale_factor + scale = (plot_height / self.doc_height) * self.scale_factor else: - scale = (plot_width/self.doc_width)*self.scale_factor + scale = (plot_width / self.doc_width) * self.scale_factor - scale_width = scale*self.doc_width - scale_height = scale*self.doc_height + scale_width = scale * self.doc_width + scale_height = scale * self.doc_height # Set up the transforms to align the graphic to the desired position - if self.align == 'ur': - gc.translate_ctm(origin_x + (plot_width-scale_width), - origin_y + plot_height) - elif self.align == 'lr': - gc.translate_ctm(origin_x + (plot_width-scale_width), - origin_y + scale_height) - elif self.align == 'ul': - gc.translate_ctm(origin_x, - origin_y + plot_height) - elif self.align == 'll': - gc.translate_ctm(origin_x, - origin_y + scale_height) + if self.align == "ur": + gc.translate_ctm( + origin_x + (plot_width - scale_width), origin_y + plot_height + ) + elif self.align == "lr": + gc.translate_ctm( + origin_x + (plot_width - scale_width), origin_y + scale_height + ) + elif self.align == "ul": + gc.translate_ctm(origin_x, origin_y + plot_height) + elif self.align == "ll": + gc.translate_ctm(origin_x, origin_y + scale_height) else: - gc.translate_ctm(origin_x + (plot_width-scale_width)/2, - origin_y + (plot_height+scale_height)/2) - + gc.translate_ctm( + origin_x + (plot_width - scale_width) / 2, + origin_y + (plot_height + scale_height) / 2, + ) # SVG origin is the upper right with y positive down, so # we need to flip everything @@ -116,15 +115,15 @@ def overlay(self, other_component, gc, view_bounds=None, mode="normal"): self._draw_component(gc, view_bounds, mode) def fade_out(self): - interval = self.fade_out_time/self.fade_out_steps + interval = self.fade_out_time / self.fade_out_steps self.timer = Timer(interval, self._fade_out_step) def _fade_out_step(self): - """ Fades out the overlay over a half second. then removes it from - the other_component's overlays + """Fades out the overlay over a half second. then removes it from + the other_component's overlays """ if self.alpha <= 0: - if self.type == 'overlay': + if self.type == "overlay": self.component.overlays.remove(self) else: self.component.underlays.remove(self) @@ -134,10 +133,10 @@ def _fade_out_step(self): self.alpha -= 0.1 self.component.request_redraw() + class ErrorLayer(StatusLayer): - filename = os.path.join(os.path.dirname(__file__), 'data', - 'Dialog-error.svg') + filename = os.path.join(os.path.dirname(__file__), "data", "Dialog-error.svg") + class WarningLayer(StatusLayer): - filename = os.path.join(os.path.dirname(__file__), 'data', - 'Dialog-warning.svg') + filename = os.path.join(os.path.dirname(__file__), "data", "Dialog-warning.svg") diff --git a/chaco/layers/svg_range_selection_overlay.py b/chaco/layers/svg_range_selection_overlay.py index ac9cc08c7..644e53443 100644 --- a/chaco/layers/svg_range_selection_overlay.py +++ b/chaco/layers/svg_range_selection_overlay.py @@ -1,6 +1,3 @@ - - - import os import numpy @@ -9,36 +6,34 @@ from .status_layer import StatusLayer + class SvgRangeSelectionOverlay(StatusLayer): - """ This is a primitive range selection overlay which uses - a SVG to define the overlay. + """This is a primitive range selection overlay which uses + a SVG to define the overlay. - TODO: not inherit from StatusLayer, this was a convenience for a - quick prototype + TODO: not inherit from StatusLayer, this was a convenience for a + quick prototype - TODO: use 2 svgs, one which defines the border and does not scale, and - the other which defines the fill. + TODO: use 2 svgs, one which defines the border and does not scale, and + the other which defines the fill. """ - - - filename = os.path.join(os.path.dirname(__file__), 'data', - 'range_selection.svg') + filename = os.path.join(os.path.dirname(__file__), "data", "range_selection.svg") alpha = 0.5 # The axis to which this tool is perpendicular. axis = Enum("index", "value") - axis_index = Property(depends_on='axis') + axis_index = Property(depends_on="axis") # Mapping from screen space to data space. By default, it is just # self.component. - plot = Property(depends_on='component') + plot = Property(depends_on="component") # The mapper (and associated range) that drive this RangeSelectionOverlay. # By default, this is the mapper on self.plot that corresponds to self.axis. - mapper = Property(depends_on='plot') + mapper = Property(depends_on="plot") # The name of the metadata to look at for dataspace bounds. The metadata # can be either a tuple (dataspace_start, dataspace_end) in "selections" or @@ -46,7 +41,7 @@ class SvgRangeSelectionOverlay(StatusLayer): metadata_name = Str("selections") def overlay(self, component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Overrides AbstractOverlay. """ @@ -65,16 +60,16 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): origin_x = self.component.padding_left origin_y = self.component.padding_top - if self.axis == 'index': + if self.axis == "index": if isinstance(self.mapper, GridMapper): - scale_width = (coords[-1][0] - coords[0][0])/self.doc_width + scale_width = (coords[-1][0] - coords[0][0]) / self.doc_width else: - scale_width = (coords[0][-1] - coords[0][0])/self.doc_width - scale_height = float(plot_height)/self.doc_height + scale_width = (coords[0][-1] - coords[0][0]) / self.doc_width + scale_height = float(plot_height) / self.doc_height gc.translate_ctm(coords[0][0], origin_y + plot_height) else: - scale_height = (coords[0][-1] - coords[0][0])/self.doc_height - scale_width = float(plot_width)/self.doc_width + scale_height = (coords[0][-1] - coords[0][0]) / self.doc_height + scale_width = float(plot_width) / self.doc_width gc.translate_ctm(origin_x, coords[0][0]) # SVG origin is the upper right with y positive down, so @@ -86,7 +81,7 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): self._draw_component(gc, view_bounds, mode) def _get_selection_screencoords(self): - """ Returns a tuple of (x1, x2) screen space coordinates of the start + """Returns a tuple of (x1, x2) screen space coordinates of the start and end selection points. If there is no current selection, then returns None. @@ -102,12 +97,12 @@ def _get_selection_screencoords(self): return [] # All other metadata is interpreted as a mask on dataspace else: - ar = numpy.arange(0,len(selection), 1) + ar = numpy.arange(0, len(selection), 1) runs = arg_find_runs(ar[selection]) coords = [] for inds in runs: start = ds._data[ar[selection][inds[0]]] - end = ds._data[ar[selection][inds[1]-1]] + end = ds._data[ar[selection][inds[1] - 1]] coords.append(self.map_screen(numpy.array((start, end)))) return coords @@ -117,7 +112,7 @@ def _get_plot(self): @cached_property def _get_axis_index(self): - if self.axis == 'index': + if self.axis == "index": return 0 else: return 1 @@ -130,7 +125,7 @@ def _get_mapper(self): mapper = getattr(self.plot, self.axis + "_mapper") if isinstance(mapper, GridMapper): - if self.axis == 'index': + if self.axis == "index": return mapper._xmapper else: return mapper._ymapper diff --git a/chaco/legend.py b/chaco/legend.py index 36240841b..d36829837 100644 --- a/chaco/legend.py +++ b/chaco/legend.py @@ -3,14 +3,24 @@ """ - from numpy import array, zeros_like from enable.api import black_color_trait, white_color_trait from enable.font_metrics_provider import font_metrics_provider from kiva.trait_defs.kiva_font_trait import KivaFont -from traits.api import ArrayOrNone, Bool, CList, Dict, Enum, Float, \ - HasTraits, Instance, Int, List, Str +from traits.api import ( + ArrayOrNone, + Bool, + CList, + Dict, + Enum, + Float, + HasTraits, + Instance, + Int, + List, + Str, +) # Local relative imports from .abstract_overlay import AbstractOverlay @@ -21,10 +31,10 @@ class AbstractCompositeIconRenderer(HasTraits): - """ Abstract class for an icon renderer. - """ + """Abstract class for an icon renderer.""" + def render_icon(self, plots, gc, x, y, width, height): - """ Renders an icon representing the given list of plots onto the + """Renders an icon representing the given list of plots onto the graphics context, using the given dimensions and at the specified position. """ @@ -32,8 +42,8 @@ def render_icon(self, plots, gc, x, y, width, height): class CompositeIconRenderer(AbstractCompositeIconRenderer): - """ Renderer for composite icons. - """ + """Renderer for composite icons.""" + def render_icon(self, plots, *render_args): """ Renders an icon for a list of plots. """ types = set(map(type, plots)) @@ -44,8 +54,11 @@ def render_icon(self, plots, *render_args): elif types == set([ScatterPlot, LinePlot]): self._render_line_scatter(plots, *render_args) else: - raise ValueError("Don't know how to render combination plot with " +\ - "renderers " + str(types)) + raise ValueError( + "Don't know how to render combination plot with " + + "renderers " + + str(types) + ) def _render_scatterplots(self, plots, gc, x, y, width, height): # Don't support this for now @@ -63,10 +76,9 @@ def _render_line_scatter(self, plots, gc, x, y, width, height): scatter[0]._render_icon(gc, x, y, width, height) - class Legend(AbstractOverlay): - """ A legend for a plot. - """ + """A legend for a plot.""" + #: The font to use for the legend text. font = KivaFont("modern 12") @@ -140,7 +152,7 @@ class Legend(AbstractOverlay): resizable = "hv" #: An optional title string to show on the legend. - title = Str('') + title = Str("") #: If True, title is at top, if False then at bottom. title_at_top = Bool(True) @@ -152,9 +164,9 @@ class Legend(AbstractOverlay): #: PlotComponent). draw_layer = "overlay" - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private Traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # A cached list of Label instances _cached_labels = List @@ -175,23 +187,21 @@ class Legend(AbstractOverlay): _cached_label_positions = ArrayOrNone() def is_in(self, x, y): - """ overloads from parent class because legend alignment - and padding does not cooperatate with the basic implementation + """overloads from parent class because legend alignment + and padding does not cooperatate with the basic implementation - This may just be caused byt a questionable implementation of the - legend tool, but it works by adjusting the padding. The Component - class implementation of is_in uses the outer positions which - includes the padding + This may just be caused byt a questionable implementation of the + legend tool, but it works by adjusting the padding. The Component + class implementation of is_in uses the outer positions which + includes the padding """ in_x = (x >= self.x) and (x <= self.x + self.width) in_y = (y >= self.y) and (y <= self.y + self.height) return in_x and in_y - - def overlay(self, component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Implements AbstractOverlay. """ @@ -236,7 +246,7 @@ def _draw_overlay(self, gc, view_bounds=None, mode="normal"): PlotComponent._draw_overlay(self, gc, view_bounds, mode) def _draw_as_overlay(self, gc, view_bounds=None, mode="normal"): - """ Draws the overlay layer of a component. + """Draws the overlay layer of a component. Overrides PlotComponent. """ @@ -250,8 +260,7 @@ def _draw_as_overlay(self, gc, view_bounds=None, mode="normal"): # feature. with gc: - gc.clip_to_rect(int(self.x), int(self.y), - int(self.width), int(self.height)) + gc.clip_to_rect(int(self.x), int(self.y), int(self.width), int(self.height)) edge_space = self.border_width + self.border_padding icon_width, icon_height = self.icon_bounds @@ -261,7 +270,7 @@ def _draw_as_overlay(self, gc, view_bounds=None, mode="normal"): if self._cached_label_positions is not None: if len(self._cached_label_positions) > 0: - self._cached_label_positions[:,0] = icon_x + self._cached_label_positions[:, 0] = icon_x for i, label_name in enumerate(self._cached_label_names): # Compute the current label's position @@ -281,7 +290,7 @@ def _draw_as_overlay(self, gc, view_bounds=None, mode="normal"): # and assume that applies to all of them if not plots[0].visible: # TODO: the get_alpha() method isn't supported on the Mac kiva backend - #old_alpha = gc.get_alpha() + # old_alpha = gc.get_alpha() old_alpha = 1.0 gc.set_alpha(self.invisible_plot_alpha) else: @@ -289,11 +298,13 @@ def _draw_as_overlay(self, gc, view_bounds=None, mode="normal"): if len(plots) == 1: plots[0]._render_icon(*render_args) else: - self.composite_icon_renderer.render_icon(plots, *render_args) + self.composite_icon_renderer.render_icon( + plots, *render_args + ) elif plots is not None: # Single plot if not plots.visible: - #old_alpha = gc.get_alpha() + # old_alpha = gc.get_alpha() old_alpha = 1.0 gc.set_alpha(self.invisible_plot_alpha) else: @@ -320,7 +331,7 @@ def _draw_as_overlay(self, gc, view_bounds=None, mode="normal"): gc.set_alpha(old_alpha) def _render_error(self, gc, icon_x, icon_y, icon_width, icon_height): - """ Renders an error icon or performs some other action when a + """Renders an error icon or performs some other action when a plot is unable to render its icon. Returns True if something was actually drawn (and hence the legend @@ -369,7 +380,7 @@ def get_preferred_size(self): val = self.plots[name] # Rather than checking for a list/TraitListObject/etc., we just check # for the attribute first - if hasattr(val, 'visible'): + if hasattr(val, "visible"): if val.visible: visible_labels.append(name) visible_plots.append(val) @@ -389,7 +400,7 @@ def get_preferred_size(self): # For the legend title if self.title_at_top: labels.insert(0, self._create_label(self.title)) - label_names.insert(0, 'Legend Label') + label_names.insert(0, "Legend Label") visible_plots.insert(0, None) else: labels.append(self._create_label(self.title)) @@ -402,14 +413,21 @@ def get_preferred_size(self): if len(label_sizes) > 0: max_label_width = max(label_sizes[:, 0]) - total_label_height = sum(label_sizes[:, 1]) + (len(label_sizes)-1)*self.line_spacing + total_label_height = ( + sum(label_sizes[:, 1]) + (len(label_sizes) - 1) * self.line_spacing + ) else: max_label_width = 0 total_label_height = 0 - legend_width = max_label_width + self.icon_spacing + self.icon_bounds[0] \ - + self.hpadding + 2*self.border_padding - legend_height = total_label_height + self.vpadding + 2*self.border_padding + legend_width = ( + max_label_width + + self.icon_spacing + + self.icon_bounds[0] + + self.hpadding + + 2 * self.border_padding + ) + legend_height = total_label_height + self.vpadding + 2 * self.border_padding self._cached_labels = labels self._cached_label_sizes = label_sizes @@ -434,35 +452,58 @@ def get_label_at(self, x, y): return None def _do_layout(self): - if self.component is not None or len(self._cached_labels) == 0 or \ - self._cached_label_sizes is None or len(self._cached_label_names) == 0: + if ( + self.component is not None + or len(self._cached_labels) == 0 + or self._cached_label_sizes is None + or len(self._cached_label_names) == 0 + ): width, height = self.get_preferred_size() self.outer_bounds = [width, height] def _create_label(self, text): - """ Returns a new Label instance for the given text. Subclasses can + """Returns a new Label instance for the given text. Subclasses can override this method to customize the creation of labels. """ - return Label(text=text, font=self.font, margin=0, color=self.color_, - bgcolor="transparent", border_width=0) + return Label( + text=text, + font=self.font, + margin=0, + color=self.color_, + bgcolor="transparent", + border_width=0, + ) def _composite_icon_renderer_default(self): return CompositeIconRenderer() - #-- trait handlers -------------------------------------------------------- + # -- trait handlers -------------------------------------------------------- def _anytrait_changed(self, name, old, new): - if name in ("font", "border_padding", "padding", "line_spacing", - "icon_bounds", "icon_spacing", "labels", "plots", - "plots_items", "labels_items", "border_width", "align", - "position", "position_items", "bounds", "bounds_items", - "label_at_top"): + if name in ( + "font", + "border_padding", + "padding", + "line_spacing", + "icon_bounds", + "icon_spacing", + "labels", + "plots", + "plots_items", + "labels_items", + "border_width", + "align", + "position", + "position_items", + "bounds", + "bounds_items", + "label_at_top", + ): self._layout_needed = True if name == "color": self.get_preferred_size() def _plots_changed(self): - """ Invalidate the caches. - """ + """Invalidate the caches.""" self._cached_labels = [] self._cached_label_sizes = None self._cached_label_names = [] @@ -483,12 +524,12 @@ def _title_at_top_changed(self, old, new): # For the legend title if self.title_at_top: self._cached_labels.insert(0, self._create_label(self.title)) - self._cached_label_names.insert(0, '__legend_label__') + self._cached_label_names.insert(0, "__legend_label__") self._cached_visible_plots.insert(0, None) else: self._cached_labels.append(self._create_label(self.title)) self._cached_label_names.append(self.title) self._cached_visible_plots.append(None) -#-- end Legend ---------------------------------------------------------------- +# -- end Legend ---------------------------------------------------------------- diff --git a/chaco/line_scatterplot_1d.py b/chaco/line_scatterplot_1d.py index 76916a9d5..4fafadefd 100644 --- a/chaco/line_scatterplot_1d.py +++ b/chaco/line_scatterplot_1d.py @@ -4,7 +4,6 @@ """ - from numpy import empty # Enthought library imports @@ -27,13 +26,13 @@ class LineScatterPlot1D(Base1DPlot): #: The line dash style. line_style = LineStyle - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Selection and selection rendering # A selection on the lot is indicated by setting the index or value # datasource's 'selections' metadata item to a list of indices, or the # 'selection_mask' metadata to a boolean array of the same length as the # datasource. - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: whether or not to display a selection show_selection = Bool(True) @@ -53,16 +52,16 @@ class LineScatterPlot1D(Base1DPlot): #: The fade amount for unselected regions unselected_alpha = Float(0.3) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _draw_plot(self, gc, view_bounds=None, mode="normal"): """ Draw the plot """ coord = self._compute_screen_coord() lines = empty(shape=(len(coord), 4)) - if self.orientation == 'v': + if self.orientation == "v": lines[:, 0] = self.x lines[:, 1] = coord lines[:, 2] = self.x2 @@ -91,14 +90,25 @@ def _render(self, gc, lines): color = list(self.color_) color[3] *= self.unselected_alpha if unselected_lines.size > 0: - self._render_lines(gc, unselected_lines, self.color_, - self.line_width, self.line_style_) + self._render_lines( + gc, + unselected_lines, + self.color_, + self.line_width, + self.line_style_, + ) if selected_lines.size > 0: - self._render_lines(gc, selected_lines, self.selected_color_, - self.selected_line_width, self.selected_line_style_) + self._render_lines( + gc, + selected_lines, + self.selected_color_, + self.selected_line_width, + self.selected_line_style_, + ) else: - self._render_lines(gc, lines, self.color_, - self.line_width, self.line_style_) + self._render_lines( + gc, lines, self.color_, self.line_width, self.line_style_ + ) def _render_lines(self, gc, lines, color, width, dash): """ Render a collection of lines with a given style """ diff --git a/chaco/linear_mapper.py b/chaco/linear_mapper.py index 5b73c2456..16dd61e46 100644 --- a/chaco/linear_mapper.py +++ b/chaco/linear_mapper.py @@ -14,7 +14,7 @@ class LinearMapper(Base1DMapper): - """ Maps a 1-D data space to and from screen space by specifying a range in + """Maps a 1-D data space to and from screen space by specifying a range in data space and a corresponding fixed line in screen space. This class concerns itself only with metric and not with orientation. So, to @@ -22,9 +22,9 @@ class LinearMapper(Base1DMapper): and **high_pos**. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Number of screen space units per data space unit. _scale = Float(1.0) @@ -33,12 +33,12 @@ class LinearMapper(Base1DMapper): # Is the range of the data space empty? _null_data_range = Bool(False) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def map_screen(self, data_array): - """ map_screen(data_array) -> screen_array + """map_screen(data_array) -> screen_array Overrides AbstractMapper. Maps values from data space into screen space. """ @@ -52,7 +52,7 @@ def map_screen(self, data_array): return (data_array - self.range.low) * self._scale + self.low_pos def map_data(self, screen_val): - """ map_data(screen_val) -> data_val + """map_data(screen_val) -> data_val Overrides AbstractMapper. Maps values from screen space into data space. """ @@ -65,16 +65,16 @@ def map_data(self, screen_val): return (screen_val - self.low_pos) / self._scale + self.range.low def map_data_array(self, screen_vals): - """ map_data_array(screen_vals) -> data_vals + """map_data_array(screen_vals) -> data_vals Overrides AbstractMapper. Maps an array of values from screen space into data space. """ return self.map_data(screen_vals) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _compute_scale(self): if self._cache_valid: diff --git a/chaco/lineplot.py b/chaco/lineplot.py index e80aac08c..f92d312dc 100644 --- a/chaco/lineplot.py +++ b/chaco/lineplot.py @@ -2,13 +2,25 @@ """ - # Standard library imports import warnings # Major library imports -from numpy import argsort, array, concatenate, inf, invert, isnan, \ - take, transpose, zeros, sqrt, argmin, clip, column_stack +from numpy import ( + argsort, + array, + concatenate, + inf, + invert, + isnan, + take, + transpose, + zeros, + sqrt, + argmin, + clip, + column_stack, +) # Enthought library imports from enable.api import black_color_trait, ColorTrait, LineStyle @@ -20,22 +32,22 @@ from .base_xy_plot import BaseXYPlot - class LinePlot(BaseXYPlot): - """ A plot consisting of a line. + """A plot consisting of a line. This is the most fundamental object to use to create line plots. However, it is somewhat low-level and therefore creating one properly to do what you want can require some verbose code. The create_line_plot() function in plot_factory.py can hide some of this verbosity for common cases. """ + #: The color of the line. color = black_color_trait #: The RGBA tuple for rendering lines. It is always a tuple of length 4. #: It has the same RGB values as :attr:`color`, and its alpha value is the #: alpha value of self.color multiplied by self.alpha. - effective_color = Property(Tuple, depends_on=['color', 'alpha']) + effective_color = Property(Tuple, depends_on=["color", "alpha"]) #: The color to use to highlight the line when selected. selected_color = ColorTrait("lightyellow") @@ -68,12 +80,16 @@ class LinePlot(BaseXYPlot): render_style = Enum("connectedpoints", "hold", "connectedhold") #: Traits UI View for customizing the plot. - traits_view = View(Item("color", style="custom"), "line_width", "line_style", - buttons=["OK", "Cancel"]) - - #------------------------------------------------------------------------ + traits_view = View( + Item("color", style="custom"), + "line_width", + "line_style", + buttons=["OK", "Cancel"], + ) + + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Cached list of non-NaN arrays of (x,y) data-space points; regardless of # self.orientation, this is always stored as (index_pt, value_pt). This is @@ -83,8 +99,7 @@ class LinePlot(BaseXYPlot): # Cached list of non-NaN arrays of (x,y) screen-space points. _cached_screen_pts = List - - def hittest(self, screen_pt, threshold=7.0, return_distance = False): + def hittest(self, screen_pt, threshold=7.0, return_distance=False): """ Tests whether the given screen point is within *threshold* pixels of any data points on the line. If so, then it returns the (x,y) value of @@ -98,8 +113,9 @@ def hittest(self, screen_pt, threshold=7.0, return_distance = False): data_pt = (self.index.get_data()[ndx], self.value.get_data()[ndx]) if return_distance: scrn_pt = self.map_screen(data_pt) - dist = sqrt((screen_pt[0] - scrn_pt[0])**2 - + (screen_pt[1] - scrn_pt[1])**2) + dist = sqrt( + (screen_pt[0] - scrn_pt[0]) ** 2 + (screen_pt[1] - scrn_pt[1]) ** 2 + ) return (data_pt[0], data_pt[1], dist) else: return data_pt @@ -109,11 +125,11 @@ def hittest(self, screen_pt, threshold=7.0, return_distance = False): # Must check all lines within threshold along the major axis, # so determine the bounds of the region of interest in dataspace if self.orientation == "h": - dmax = self.map_data((screen_pt[0]+threshold, screen_pt[1])) - dmin = self.map_data((screen_pt[0]-threshold, screen_pt[1])) + dmax = self.map_data((screen_pt[0] + threshold, screen_pt[1])) + dmin = self.map_data((screen_pt[0] - threshold, screen_pt[1])) else: - dmax = self.map_data((screen_pt[0], screen_pt[1]+threshold)) - dmin = self.map_data((screen_pt[0], screen_pt[1]-threshold)) + dmax = self.map_data((screen_pt[0], screen_pt[1] + threshold)) + dmin = self.map_data((screen_pt[0], screen_pt[1] - threshold)) xmin, xmax = self.index.get_bounds() @@ -121,26 +137,42 @@ def hittest(self, screen_pt, threshold=7.0, return_distance = False): if dmin < xmin: ndx1 = 0 elif dmin > xmax: - ndx1 = len(self.value.get_data())-1 + ndx1 = len(self.value.get_data()) - 1 else: - ndx1 = reverse_map_1d(self.index.get_data(), dmin, - self.index.sort_order) + ndx1 = reverse_map_1d( + self.index.get_data(), dmin, self.index.sort_order + ) if dmax < xmin: ndx2 = 0 elif dmax > xmax: - ndx2 = len(self.value.get_data())-1 + ndx2 = len(self.value.get_data()) - 1 else: - ndx2 = reverse_map_1d(self.index.get_data(), dmax, - self.index.sort_order) - - start_ndx = max(0, min(ndx1-1, ndx2-1,)) - end_ndx = min(len(self.value.get_data())-1, max(ndx1+1, ndx2+1)) + ndx2 = reverse_map_1d( + self.index.get_data(), dmax, self.index.sort_order + ) + + start_ndx = max( + 0, + min( + ndx1 - 1, + ndx2 - 1, + ), + ) + end_ndx = min(len(self.value.get_data()) - 1, max(ndx1 + 1, ndx2 + 1)) # Compute the distances to all points in the range of interest - start = array([ self.index.get_data()[start_ndx:end_ndx], - self.value.get_data()[start_ndx:end_ndx] ]) - end = array([ self.index.get_data()[start_ndx+1:end_ndx+1], - self.value.get_data()[start_ndx+1:end_ndx+1] ]) + start = array( + [ + self.index.get_data()[start_ndx:end_ndx], + self.value.get_data()[start_ndx:end_ndx], + ] + ) + end = array( + [ + self.index.get_data()[start_ndx + 1 : end_ndx + 1], + self.value.get_data()[start_ndx + 1 : end_ndx + 1], + ] + ) # Convert to screen points s_start = transpose(self.map_screen(transpose(start))) @@ -157,8 +189,7 @@ def hittest(self, screen_pt, threshold=7.0, return_distance = False): px, py = _t_to_point(t, s_start, s_end) # Calculate distances - dist = sqrt((px - screen_pt[0])**2 + - (py - screen_pt[1])**2) + dist = sqrt((px - screen_pt[0]) ** 2 + (py - screen_pt[1]) ** 2) # Find the minimum n = argmin(dist) @@ -205,7 +236,7 @@ def interpolate(self, index_value): y1 = value_data[ndx + 1] if x1 != x0: - slope = float(y1 - y0)/float(x1 - x0) + slope = float(y1 - y0) / float(x1 - x0) dx = index_value - x0 yp = y0 + slope * dx else: @@ -220,9 +251,9 @@ def get_screen_points(self): else: return [self.map_screen(ary) for ary in self._cached_data_pts] - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods; implements the BaseXYPlot stub methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _gather_points(self): """ @@ -238,7 +269,10 @@ def _gather_points(self): value = self.value.get_data() # Check to see if the data is completely outside the view region - for ds, rng in ((self.index, self.index_range), (self.value, self.value_range)): + for ds, rng in ( + (self.index, self.index_range), + (self.value, self.value_range), + ): low, high = ds.get_bounds() if low > rng.high or high < rng.low: self._cached_data_pts = [] @@ -251,8 +285,10 @@ def _gather_points(self): size_diff = len(value) - len(index) if size_diff > 0: - warnings.warn('Chaco.LinePlot: len(value) %d - len(index) %d = %d\n' \ - % (len(value), len(index), size_diff)) + warnings.warn( + "Chaco.LinePlot: len(value) %d - len(index) %d = %d\n" + % (len(value), len(index), size_diff) + ) index_max = len(index) value = value[:index_max] else: @@ -261,21 +297,25 @@ def _gather_points(self): # TODO: restore the functionality of rendering highlighted portions # of the line - #selection = self.index.metadata.get(self.metadata_name, None) - #if selection is not None and type(selection) in (ndarray, list) and \ + # selection = self.index.metadata.get(self.metadata_name, None) + # if selection is not None and type(selection) in (ndarray, list) and \ # len(selection) > 0: # Split the index and value raw data into non-NaN chunks mask = invert(isnan(value)) & invert(isnan(index)) # throw out index and value points outside the visible region - mask = intersect_range(index, self.index_range.low, - self.index_range.high, mask) - mask = intersect_range(value, self.value_range.low, - self.value_range.high, mask) - - points = [column_stack([index[start:end], value[start:end]]) - for start, end in arg_true_runs(mask)] + mask = intersect_range( + index, self.index_range.low, self.index_range.high, mask + ) + mask = intersect_range( + value, self.value_range.low, self.value_range.high, mask + ) + + points = [ + column_stack([index[start:end], value[start:end]]) + for start, end in arg_true_runs(mask) + ] self._cached_data_pts = points self._cache_valid = True @@ -289,8 +329,11 @@ def _downsample(self): else: # TODO: implement other downsampling methods from chaco.downsample.lttb import largest_triangle_three_buckets - downsampled = [largest_triangle_three_buckets(p, delta_screen) - for p in self._cached_data_pts] + + downsampled = [ + largest_triangle_three_buckets(p, delta_screen) + for p in self._cached_data_pts + ] self._cached_screen_pts = [self.map_screen(p) for p in downsampled] self._screen_cache_valid = True @@ -306,15 +349,15 @@ def _render(self, gc, points, selected_points=None): gc.clip_to_rect(self.x, self.y, self.width, self.height) render_method_dict = { - "hold": self._render_hold, - "connectedhold": self._render_connected_hold, - "connectedpoints": self._render_normal - } + "hold": self._render_hold, + "connectedhold": self._render_connected_hold, + "connectedpoints": self._render_normal, + } render = render_method_dict.get(self.render_style, self._render_normal) if selected_points is not None: gc.set_stroke_color(self.selected_color_) - gc.set_line_width(self.line_width+10.0) + gc.set_line_width(self.line_width + 10.0) gc.set_line_dash(self.selected_line_style_) render(gc, selected_points, self.orientation) @@ -338,11 +381,11 @@ def _render_normal(cls, gc, points, orientation): @classmethod def _render_hold(cls, gc, points, orientation): for starts in points: - x,y = starts.T + x, y = starts.T if orientation == "h": - ends = transpose(array( (x[1:], y[:-1]) )) + ends = transpose(array((x[1:], y[:-1]))) else: - ends = transpose(array( (x[:-1], y[1:]) )) + ends = transpose(array((x[:-1], y[1:]))) gc.begin_path() gc.line_set(starts[:-1], ends) gc.stroke_path() @@ -350,11 +393,11 @@ def _render_hold(cls, gc, points, orientation): @classmethod def _render_connected_hold(cls, gc, points, orientation): for starts in points: - x,y = starts.T + x, y = starts.T if orientation == "h": - ends = transpose(array( (x[1:], y[:-1]) )) + ends = transpose(array((x[1:], y[:-1]))) else: - ends = transpose(array( (x[:-1], y[1:]) )) + ends = transpose(array((x[:-1], y[1:]))) gc.begin_path() gc.line_set(starts[:-1], ends) gc.line_set(ends, starts[1:]) @@ -366,8 +409,8 @@ def _render_icon(self, gc, x, y, width, height): gc.set_line_width(self.line_width) gc.set_line_dash(self.line_style_) gc.set_antialias(0) - gc.move_to(x, y+height/2) - gc.line_to(x+width, y+height/2) + gc.move_to(x, y + height / 2) + gc.line_to(x + width, y + height / 2) gc.stroke_path() def _downsample_vectorized(self): @@ -375,17 +418,17 @@ def _downsample_vectorized(self): Analyzes the screen-space points stored in self._cached_data_pts and replaces them with a downsampled set. """ - pts = self._cached_screen_pts #.astype(int) + pts = self._cached_screen_pts # .astype(int) # some boneheaded short-circuits m = self.index_mapper if (pts.shape[0] < 400) or (pts.shape[0] < m.high_pos - m.low_pos): return - pts2 = concatenate((array([[0.0,0.0]]), pts[:-1])) + pts2 = concatenate((array([[0.0, 0.0]]), pts[:-1])) z = abs(pts - pts2) - d = z[:,0] + z[:,1] - #... TODO ... + d = z[:, 0] + z[:, 1] + # ... TODO ... def _alpha_changed(self): self.invalidate_draw() @@ -404,8 +447,8 @@ def _line_width_changed(self): self.request_redraw() def __getstate__(self): - state = super(LinePlot,self).__getstate__() - for key in ['traits_view']: + state = super(LinePlot, self).__getstate__() + for key in ["traits_view"]: if key in state: del state[key] @@ -417,23 +460,24 @@ def _get_effective_color(self): c = self.color_[:3] + (alpha * self.alpha,) return c + def _closest_point(target, p1, p2): - '''Utility function for hittest: + """Utility function for hittest: finds the point on the line between p1 and p2 to the target. Returns the 't' value of that point where the line is parametrized as t -> p1*(1-t) + p2*t Notably, if t=0 is p1, t=2 is p2 and anything outside that range is a point outisde p1, p2 on the line - Note: can divide by zero, so user should check for that''' - t = ((p1[0] - target[0])*(p1[0]-p2[0]) \ - + (p1[1] - target[1])*(p1[1]-p2[1]))\ - / ((p1[0] - p2[0])*(p1[0] - p2[0]) + (p1[1] - p2[1])*(p1[1] - p2[1])) + Note: can divide by zero, so user should check for that""" + t = ( + (p1[0] - target[0]) * (p1[0] - p2[0]) + (p1[1] - target[1]) * (p1[1] - p2[1]) + ) / ((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1])) return t + def _t_to_point(t, p1, p2): - '''utility function for hittest for use with _closest_point + """utility function for hittest for use with _closest_point returns the point corresponding to the parameter t - on the line going between p1 and p2''' - return ( p1[0]*(1-t) + p2[0]*t, - p1[1]*(1-t) + p2[1]*t ) + on the line going between p1 and p2""" + return (p1[0] * (1 - t) + p2[0] * t, p1[1] * (1 - t) + p2[1] * t) diff --git a/chaco/log_mapper.py b/chaco/log_mapper.py index 3fea239de..6bd700d88 100644 --- a/chaco/log_mapper.py +++ b/chaco/log_mapper.py @@ -1,33 +1,34 @@ """ Defines the LogMapper and InvalidDataRangeException classes. """ # Major library imports -from numpy import array, isnan, log, log10, exp, zeros, sometrue,\ - floor, ceil, ndarray +from numpy import array, isnan, log, log10, exp, zeros, sometrue, floor, ceil, ndarray import numpy as np # Enthought library imports from traits.api import Bool, Float -#Local relative imports +# Local relative imports from .base_1d_mapper import Base1DMapper LOG_MINIMUM = 0.0 + class InvalidDataRangeException(Exception): pass + class LogMapper(Base1DMapper): - """ Defines a 1-D logarithmic scale mapping from a 1-D region in input + """Defines a 1-D logarithmic scale mapping from a 1-D region in input space to a 1-D region in output space. """ #: The value to map when asked to map values <= LOG_MINIMUM to screen space. fill_value = Float(1.0) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ _inter_scale = Float(0.0) _inter_offset = Float(0.0) @@ -36,12 +37,12 @@ class LogMapper(Base1DMapper): _null_screen_range = Bool(False) _null_data_range = Bool(False) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def map_screen(self, data_array): - """ map_screen(data_array) -> screen_array + """map_screen(data_array) -> screen_array Overrides AbstractMapper. Maps values from data space to screen space. """ @@ -52,15 +53,17 @@ def map_screen(self, data_array): if not self._cache_valid: self._compute_scale() if self._inter_scale == 0.0: - intermediate = data_array*0.0 + intermediate = data_array * 0.0 else: try: - with np.errstate(invalid='ignore'): + with np.errstate(invalid="ignore"): mask = (data_array <= LOG_MINIMUM) | isnan(data_array) if sometrue(mask): data_array = array(data_array, copy=True, ndmin=1) data_array[mask] = self.fill_value - intermediate = (log(data_array) - self._inter_offset)/self._inter_scale + intermediate = ( + log(data_array) - self._inter_offset + ) / self._inter_scale except ValueError: intermediate = zeros(len(data_array)) @@ -68,7 +71,7 @@ def map_screen(self, data_array): return result def map_data(self, screen_val): - """ map_data(screen_val) -> data_val + """map_data(screen_val) -> data_val Overrides Abstract Mapper. Maps values from screen space into data space. """ @@ -76,16 +79,16 @@ def map_data(self, screen_val): self._compute_scale() if self._null_screen_range or self._null_data_range: return array([self.range.low]) - #First convert to a [0,1] space, then to the data space - intermediate = (screen_val-self._screen_offset)/self._screen_scale - return exp(self._inter_scale*intermediate + self._inter_offset) + # First convert to a [0,1] space, then to the data space + intermediate = (screen_val - self._screen_offset) / self._screen_scale + return exp(self._inter_scale * intermediate + self._inter_offset) def map_data_array(self, screen_vals): return self.map_data(screen_vals) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_safe_scale(self, range): orig_low = range.low @@ -136,7 +139,7 @@ def _compute_scale(self): self._inter_scale = log(high) self._inter_offset = 0.0 else: - self._inter_scale = log(high)-log(low) + self._inter_scale = log(high) - log(low) self._inter_offset = log(low) self._screen_scale = screen_range self._screen_offset = self.low_pos diff --git a/chaco/multi_array_data_source.py b/chaco/multi_array_data_source.py index 0682404d8..1ae31dbcf 100644 --- a/chaco/multi_array_data_source.py +++ b/chaco/multi_array_data_source.py @@ -14,7 +14,7 @@ class MultiArrayDataSource(AbstractDataSource): - """ A data source representing a single, continuous array of + """A data source representing a single, continuous array of multidimensional numerical data. It is useful, for example, to define 2D vector data at each point of @@ -25,9 +25,9 @@ class MultiArrayDataSource(AbstractDataSource): such behavior, define a subclass that hooks up the appropriate listeners. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractDataSource traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The dimensionality of the indices into this data source (overrides #: AbstractDataSource). @@ -42,10 +42,9 @@ class MultiArrayDataSource(AbstractDataSource): #: one that's used everywhere. sort_order = SortOrderTrait - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The data array itself. _data = NumericalSequenceTrait @@ -68,7 +67,7 @@ def __init__(self, data=array([]), sort_order="ascending", **traits): self.sort_order = sort_order self.data_changed = True - def get_data(self, axes = None, remove_nans=False): + def get_data(self, axes=None, remove_nans=False): """get_data() -> data_array If called with no arguments, this method returns a data array. @@ -128,7 +127,7 @@ def get_size(self): return size def get_value_size(self): - """ get_value_size() -> size + """get_value_size() -> size Returns the size along the value dimension. """ @@ -138,8 +137,7 @@ def get_value_size(self): return size - - def get_bounds(self, value = None, index = None): + def get_bounds(self, value=None, index=None): """get_bounds() -> tuple(min, max) Returns a tuple (min, max) of the bounding values for the data source. @@ -181,19 +179,19 @@ def get_bounds(self, value = None, index = None): # value is None and index is None: with warnings.catch_warnings(): warnings.filterwarnings( - 'ignore', "All-NaN (slice|axis) encountered", RuntimeWarning) + "ignore", "All-NaN (slice|axis) encountered", RuntimeWarning + ) maxi = nanmax(self._data) mini = nanmin(self._data) return (mini, maxi) def get_shape(self): - """ Returns the shape of the multi-dimensional data source. - """ + """Returns the shape of the multi-dimensional data source.""" return shape(self._data) def set_data(self, value): - """ Sets the data for this data source. + """Sets the data for this data source. Parameters ---------- @@ -204,17 +202,17 @@ def set_data(self, value): self.data_changed = True def _set_data(self, value): - """ Forces 1-D data to 2-D. - """ + """Forces 1-D data to 2-D.""" if len(value.shape) == 1: if self.index_dimension == 0: - value = value[:,newaxis] + value = value[:, newaxis] else: - value = value[newaxis,:] + value = value[newaxis, :] if len(value.shape) != 2: - msg = 'Input is %d dimensional, but it must be 1 or 2' \ - 'dimensional.' % len(value.shape) + msg = "Input is %d dimensional, but it must be 1 or 2" "dimensional." % len( + value.shape + ) raise ValueError(msg) self._data = value diff --git a/chaco/multi_line_plot.py b/chaco/multi_line_plot.py index 1a4f4c1bd..ab446c61f 100644 --- a/chaco/multi_line_plot.py +++ b/chaco/multi_line_plot.py @@ -2,7 +2,6 @@ """ - # Standard library imports import warnings from math import ceil, floor @@ -13,8 +12,18 @@ # Enthought library imports from enable.api import black_color_trait, ColorTrait, LineStyle -from traits.api import Float, List, Str, Trait, \ - Bool, Callable, Property, cached_property, Instance, Array +from traits.api import ( + Float, + List, + Str, + Trait, + Bool, + Callable, + Property, + cached_property, + Instance, + Array, +) from traitsui.api import Item, View, ScrubberEditor, HGroup from .array_data_source import ArrayDataSource @@ -23,7 +32,7 @@ class MultiLinePlot(BaseXYPlot): - """ A plot consisting of multiple lines. + """A plot consisting of multiple lines. The data to be plotted must come from a two-dimensional array with shape M by N stored in a MultiArrayDataSource object. M is the number of lines to be plotted, @@ -129,20 +138,32 @@ class MultiLinePlot(BaseXYPlot): #: Normalized amplitude is the value exposed to the user. normalized_amplitude = Float(-0.5) - amplitude_scale = Property(Float, depends_on=['global_min', 'global_max', 'data', - 'use_global_bounds', 'yindex']) + amplitude_scale = Property( + Float, + depends_on=["global_min", "global_max", "data", "use_global_bounds", "yindex"], + ) - amplitude = Property(Float, depends_on=['normalized_amplitude', - 'amplitude_scale']) + amplitude = Property(Float, depends_on=["normalized_amplitude", "amplitude_scale"]) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The projected 2D numpy array. - _trace_data = Property(Array, depends_on=['index', 'index.data_changed', - 'value', 'value.data_changed', 'yindex', 'yindex.data_changed', - 'amplitude', 'scale', 'offset']) + _trace_data = Property( + Array, + depends_on=[ + "index", + "index.data_changed", + "value", + "value.data_changed", + "yindex", + "yindex.data_changed", + "amplitude", + "scale", + "offset", + ], + ) # Cached list of non-NaN arrays of (x,y) data-space points; regardless of # self.orientation, this is always stored as (index_pt, value_pt). This is @@ -152,47 +173,54 @@ class MultiLinePlot(BaseXYPlot): # Cached list of non-NaN arrays of (x,y) screen-space points. _cached_screen_pts = List - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def trait_view(self, obj): """Create a minimalist View, with just the amplitude and color attributes.""" # Minimalist Traits UI View for customizing the plot: only the trace amplitude # and line color are exposed. view = View( - HGroup( - Item('use_global_bounds'), - # Item('normalized_amplitude'), - # Item('normalized_amplitude', editor=RangeEditor()), - Item('normalized_amplitude', - editor=ScrubberEditor(increment=0.2, hover_color=0xFFFFFF, active_color=0xA0CD9E, - border_color=0x0000FF)), + HGroup( + Item("use_global_bounds"), + # Item('normalized_amplitude'), + # Item('normalized_amplitude', editor=RangeEditor()), + Item( + "normalized_amplitude", + editor=ScrubberEditor( + increment=0.2, + hover_color=0xFFFFFF, + active_color=0xA0CD9E, + border_color=0x0000FF, ), - Item("color", label="Trace color", style="simple"), - width=480, - title="Trace Plot Line Attributes", - buttons=["OK", "Cancel"]) + ), + ), + Item("color", label="Trace color", style="simple"), + width=480, + title="Trace Plot Line Attributes", + buttons=["OK", "Cancel"], + ) return view - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # See base_xy_plot.py for these: ## def hittest(self, screen_pt, threshold=7.0): ## def interpolate(self, index_value): - def get_screen_points(self): self._gather_points() - scrn_pts_list = [[self.map_screen(ary) for ary in line] - for line in self._cached_data_pts] + scrn_pts_list = [ + [self.map_screen(ary) for ary in line] for line in self._cached_data_pts + ] return scrn_pts_list - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @cached_property def _get_amplitude_scale(self): @@ -239,11 +267,12 @@ def _get__trace_data(self): # Get the array from `value` data = self.value._data coordinates = self.yindex.get_data() - channel_data = self.scale*(self.amplitude*data + coordinates[:,np.newaxis]) \ - + self.offset + channel_data = ( + self.scale * (self.amplitude * data + coordinates[:, np.newaxis]) + + self.offset + ) return channel_data - def _gather_points(self): """ Collects the data points that are within the bounds of the plot and @@ -269,8 +298,23 @@ def _gather_points(self): if self.fast_clip: coord_min = float(coordinates[0]) coord_max = coordinates[-1] - slice_min = max(0,ceil((varray.shape[0]-1)*(self.value_range.low - coord_min)/(coord_max - coord_min))) - slice_max = min(varray.shape[0], 1+floor((varray.shape[0]-1)*(self.value_range.high - coord_min)/(coord_max - coord_min))) + slice_min = max( + 0, + ceil( + (varray.shape[0] - 1) + * (self.value_range.low - coord_min) + / (coord_max - coord_min) + ), + ) + slice_max = min( + varray.shape[0], + 1 + + floor( + (varray.shape[0] - 1) + * (self.value_range.high - coord_min) + / (coord_max - coord_min) + ), + ) varray = varray[slice_min:slice_max] # FIXME: The y coordinates must also be sliced to match varray. @@ -292,18 +336,24 @@ def _gather_points(self): self._cached_valid = True return - if len(index) == 0 or varray.shape[0] == 0 or varray.shape[1] == 0 \ - or len(index) != varray.shape[1]: + if ( + len(index) == 0 + or varray.shape[0] == 0 + or varray.shape[1] == 0 + or len(index) != varray.shape[1] + ): self._cached_data_pts = [] self._cache_valid = True return size_diff = varray.shape[1] - len(index) if size_diff > 0: - warnings.warn('Chaco.LinePlot: value.shape[1] %d - len(index) %d = %d\n' \ - % (varray.shape[1], len(index), size_diff)) + warnings.warn( + "Chaco.LinePlot: value.shape[1] %d - len(index) %d = %d\n" + % (varray.shape[1], len(index), size_diff) + ) index_max = len(index) - varray = varray[:,:index_max] + varray = varray[:, :index_max] else: index_max = varray.shape[1] index = index[:index_max] @@ -325,14 +375,19 @@ def _gather_points(self): block_value = varray[k, start:end] index_mask = self.index_mapper.range.mask_data(block_index) - runs = [r for r in arg_find_runs(index_mask, "flat") \ - if index_mask[r[0]] != 0] + runs = [ + r + for r in arg_find_runs(index_mask, "flat") + if index_mask[r[0]] != 0 + ] # Check to see if our data view region is between two points in the # index data. If so, then we have to reverse map our current view # into the appropriate index and draw the bracketing points. if runs == []: - data_pt = self.map_data((self.x_mapper.low_pos, self.y_mapper.low_pos)) + data_pt = self.map_data( + (self.x_mapper.low_pos, self.y_mapper.low_pos) + ) if self.index.sort_order == "none": indices = argsort(index) sorted_index = take(index, indices) @@ -351,9 +406,11 @@ def _gather_points(self): # of the source data continue - - z = transpose(array((sorted_index[ndx:ndx+2], - sorted_value[ndx:ndx+2]))) + z = transpose( + array( + (sorted_index[ndx : ndx + 2], sorted_value[ndx : ndx + 2]) + ) + ) points.append(z) else: @@ -367,8 +424,9 @@ def _gather_points(self): if end != data_end: end += 1 - run_data = transpose(array((block_index[start:end], - block_value[start:end]))) + run_data = transpose( + array((block_index[start:end], block_value[start:end])) + ) points.append(run_data) line_points.append(points) @@ -379,7 +437,6 @@ def _gather_points(self): ## def _downsample(self): ## def _downsample_vectorized(self): - def _render(self, gc, line_points, selected_points=None): if len(line_points) == 0: @@ -393,7 +450,7 @@ def _render(self, gc, line_points, selected_points=None): if selected_points is not None: gc.set_stroke_color(self.selected_color_) - gc.set_line_width(self.line_width+10.0) + gc.set_line_width(self.line_width + 10.0) gc.set_line_dash(self.selected_line_style_) render(gc, selected_points) @@ -431,11 +488,10 @@ def _render_icon(self, gc, x, y, width, height): gc.set_line_width(self.line_width) gc.set_line_dash(self.line_style_) gc.set_antialias(0) - gc.move_to(x, y+height/2) - gc.line_to(x+width, y+height/2) + gc.move_to(x, y + height / 2) + gc.line_to(x + width, y + height / 2) gc.stroke_path() - def _alpha_changed(self): self.invalidate_draw() self.request_redraw() @@ -458,8 +514,8 @@ def _amplitude_changed(self): self.request_redraw() def __getstate__(self): - state = super(MultiLinePlot,self).__getstate__() - for key in ['traits_view']: + state = super(MultiLinePlot, self).__getstate__() + for key in ["traits_view"]: if key in state: del state[key] diff --git a/chaco/overlays/aligned_container_overlay.py b/chaco/overlays/aligned_container_overlay.py index 80b5010bc..8519f9788 100644 --- a/chaco/overlays/aligned_container_overlay.py +++ b/chaco/overlays/aligned_container_overlay.py @@ -5,8 +5,9 @@ from .container_overlay import ContainerOverlay + class AlignedContainerOverlay(ContainerOverlay): - """ Container overlay that aligns itself to the plot + """Container overlay that aligns itself to the plot This overlay takes an alignment which specifies which corner of its container it should align itself with ("ur", "ul", "ll", or "lr"). @@ -14,6 +15,7 @@ class AlignedContainerOverlay(ContainerOverlay): can be specified which gives the point to draw the component at, and the align is use to lay the container out relative to that position. """ + # XXX allow 'c' for center as an alignment option? # XXX make this alignment stuff a Container subclass? A generic mixin? @@ -36,8 +38,7 @@ def overlay(self, other, gc, view_bounds, mode): # XXX should this method really be _do_layout? def _compute_position(self, component): - """ Given the alignment and size of the overlay, position it. - """ + """Given the alignment and size of the overlay, position it.""" if self.layout_needed: self.do_layout() valign, halign = self.align diff --git a/chaco/overlays/api.py b/chaco/overlays/api.py index db691d4f2..0bf358e78 100644 --- a/chaco/overlays/api.py +++ b/chaco/overlays/api.py @@ -4,5 +4,10 @@ from .text_grid_overlay import TextGridOverlay from ..text_box_overlay import TextBoxOverlay from ..tools.image_inspector_tool import ImageInspectorOverlay -from .simple_inspector_overlay import SimpleInspectorOverlay, basic_formatter,\ - datetime_formatter, date_formatter, time_formatter +from .simple_inspector_overlay import ( + SimpleInspectorOverlay, + basic_formatter, + datetime_formatter, + date_formatter, + time_formatter, +) diff --git a/chaco/overlays/container_overlay.py b/chaco/overlays/container_overlay.py index a097a11c6..178a6b4e9 100644 --- a/chaco/overlays/container_overlay.py +++ b/chaco/overlays/container_overlay.py @@ -11,11 +11,12 @@ class ContainerOverlay(Container, PlotComponent): - """ Container which is also a Chaco plot overlay + """Container which is also a Chaco plot overlay Since this is an Enable container, any Components that it contains will be rendered into the overlay layer of the plot. """ + # XXX this works, but I'm not sure that it's quite right. # The component that this object overlays. This can be None. By default, if diff --git a/chaco/overlays/coordinate_line_overlay.py b/chaco/overlays/coordinate_line_overlay.py index 20efe39f6..326559b0e 100644 --- a/chaco/overlays/coordinate_line_overlay.py +++ b/chaco/overlays/coordinate_line_overlay.py @@ -5,7 +5,6 @@ """ - from traits.api import Instance, Float, Array from enable.api import black_color_trait, LineStyle, Component from chaco.abstract_overlay import AbstractOverlay @@ -44,9 +43,9 @@ class CoordinateLineOverlay(AbstractOverlay): # Typically this will be a Plot instance. component = Instance(Component) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Override AbstractOverlay methods - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def overlay(self, component, gc, view_bounds, mode="normal"): @@ -70,9 +69,9 @@ def overlay(self, component, gc, view_bounds, mode="normal"): for screen_y in y_pts: self._draw_horizontal_line(gc, screen_y) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Private methods - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _draw_vertical_line(self, gc, screen_x): if screen_x < self.component.x or screen_x > self.component.x2: @@ -84,6 +83,9 @@ def _draw_vertical_line(self, gc, screen_x): def _draw_horizontal_line(self, gc, screen_y): if screen_y < self.component.y or screen_y > self.component.y2: return - gc.move_to(self.component.x, screen_y,) + gc.move_to( + self.component.x, + screen_y, + ) gc.line_to(self.component.x2, screen_y) gc.stroke_path() diff --git a/chaco/overlays/databox.py b/chaco/overlays/databox.py index b7707fcff..9d55922b6 100644 --- a/chaco/overlays/databox.py +++ b/chaco/overlays/databox.py @@ -22,9 +22,9 @@ class DataBox(AbstractOverlay): # need to be improved that they change both dimensions at once. affinity = Enum("image", "screen") - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Appearance properties (for Box mode) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # The color of the selection box. color = ColorTrait("lightskyblue") @@ -43,12 +43,12 @@ class DataBox(AbstractOverlay): # The thickness of selection rectangle border. border_size = Int(1) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Private Traits - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- - _data_position = CList([0,0]) - _data_bounds = CList([0,0]) + _data_position = CList([0, 0]) + _data_bounds = CList([0, 0]) _position_valid = False _bounds_valid = False @@ -60,11 +60,15 @@ def __init__(self, *args, **kw): if hasattr(self.component, "range2d"): self.component.range2d._xrange.observe(self.my_component_moved, "updated") self.component.range2d._yrange.observe(self.my_component_moved, "updated") - elif hasattr(self.component, "x_mapper") and hasattr(self.component, "y_mapper"): + elif hasattr(self.component, "x_mapper") and hasattr( + self.component, "y_mapper" + ): self.component.x_mapper.range.observe(self.my_component_moved, "updated") self.component.y_mapper.range.observe(self.my_component_moved, "updated") else: - raise RuntimeError("DataBox cannot find a suitable mapper on its component.") + raise RuntimeError( + "DataBox cannot find a suitable mapper on its component." + ) self.component.observe(self.my_component_resized, "bounds.items") def overlay(self, component, gc, view_bounds=None, mode="normal"): @@ -113,9 +117,9 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): gc.rect(*rect) gc.stroke_path() - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Property setters/getters, event handlers - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- def _get_data_position(self): return self._data_position @@ -133,7 +137,7 @@ def _set_data_bounds(self, val): self._bounds_valid = False self.trait_property_changed("data_bounds", self._data_bounds) - @observe('position.items') + @observe("position.items") def _update_position(self, event=None): if self._updating: return @@ -143,7 +147,7 @@ def _update_position(self, event=None): self._data_position = tmp self.trait_property_changed("data_position", self._data_position) - @observe('bounds.items') + @observe("bounds.items") def _update_bounds(self, event=None): if self._updating: return @@ -164,5 +168,3 @@ def my_component_moved(self, event=None): def my_component_resized(self, event=None): self._bounds_valid = False self._position_valid = False - - diff --git a/chaco/overlays/simple_inspector_overlay.py b/chaco/overlays/simple_inspector_overlay.py index a0e7acd9f..cf86350ad 100644 --- a/chaco/overlays/simple_inspector_overlay.py +++ b/chaco/overlays/simple_inspector_overlay.py @@ -14,6 +14,7 @@ from .text_grid_overlay import TextGridOverlay + def basic_formatter(key, decimals): """Create a basic ': ' formatting function @@ -34,12 +35,15 @@ def basic_formatter(key, decimals): format A factory function that takes a dictionary and returns a string. """ - format_string = '%s: %%(%s).%df' % (key, key, decimals) + format_string = "%s: %%(%s).%df" % (key, key, decimals) + def format(**kwargs): return format_string % kwargs + return format -def datetime_formatter(key, time_format='%Y/%m/%d %H:%M:%S'): + +def datetime_formatter(key, time_format="%Y/%m/%d %H:%M:%S"): """Create a datetime formatting function This factory creates a function that formats a specified key and with a @@ -61,11 +65,14 @@ def datetime_formatter(key, time_format='%Y/%m/%d %H:%M:%S'): A factory function that takes a dictionary and returns a string. """ import datetime + def format(**kwargs): dt = datetime.datetime.fromtimestamp(kwargs[key]) - return key+': '+dt.strftime(time_format) + return key + ": " + dt.strftime(time_format) + return format + def time_formatter(key): """Create a time formatting function @@ -85,7 +92,8 @@ def time_formatter(key): format A factory function that takes a dictionary and returns a string. """ - return datetime_formatter(key, time_format='%H:%M:%S') + return datetime_formatter(key, time_format="%H:%M:%S") + def date_formatter(key): """Create a date formatting function @@ -106,11 +114,11 @@ def date_formatter(key): format A factory function that takes a dictionary and returns a string. """ - return datetime_formatter(key, time_format='%Y/%m/%d') + return datetime_formatter(key, time_format="%Y/%m/%d") class SimpleInspectorOverlay(TextGridOverlay): - """ Simple inspector overlay for plots + """Simple inspector overlay for plots This is a simple overlay that listens for new_value events on a SimpleInspectorTool and displays formatted values in a grid. @@ -125,6 +133,7 @@ class SimpleInspectorOverlay(TextGridOverlay): appropriate field_formatters this class can be used with any inspector tool that follows the same API. """ + # XXX We should probably refactor this into a BaseInspectorOverlay # which handles the visibility and basic event handling, and smaller # version of this class which handles inserting values into a text grid @@ -152,7 +161,7 @@ class SimpleInspectorOverlay(TextGridOverlay): ######################################################################### def _field_formatters_default(self): - return [[basic_formatter('x', 2)], [basic_formatter('y', 2)]] + return [[basic_formatter("x", 2)], [basic_formatter("y", 2)]] def _new_value_updated(self, event): new_value_event = event.new @@ -168,8 +177,9 @@ def _new_value_updated(self, event): d = new_value_event text = [] - self.text_grid.string_array = array([[formatter(**d) for formatter in row] - for row in self.field_formatters]) + self.text_grid.string_array = array( + [[formatter(**d) for formatter in row] for row in self.field_formatters] + ) self.text_grid.request_redraw() @@ -179,10 +189,10 @@ def _visible_changed(self): def _inspector_changed(self, old, new): if old: - old.observe(self._new_value_updated, 'new_value', remove=True) + old.observe(self._new_value_updated, "new_value", remove=True) old.observe(self._tool_visible_changed, "visible", remove=True) if new: - new.observe(self._new_value_updated, 'new_value') + new.observe(self._new_value_updated, "new_value") new.observe(self._tool_visible_changed, "visible") self._tool_visible_changed() @@ -190,4 +200,3 @@ def _tool_visible_changed(self, event=None): self.visibility = self.inspector.visible if self.visibility != "auto": self.visible = self.visibility - diff --git a/chaco/overlays/tests/test_databox.py b/chaco/overlays/tests/test_databox.py index 2ee57df9b..5eeb05c90 100644 --- a/chaco/overlays/tests/test_databox.py +++ b/chaco/overlays/tests/test_databox.py @@ -3,14 +3,13 @@ from traits.testing.api import UnittestTools -from chaco.api import ( - CMapImagePlot, GridDataSource, GridMapper, DataRange2D, ImageData -) +from chaco.api import CMapImagePlot, GridDataSource, GridMapper, DataRange2D, ImageData from chaco.overlays.databox import DataBox class TestDataBox(unittest.TestCase, UnittestTools): """Test the DataBox""" + def setUp(self): # Set up plot component containing @@ -19,7 +18,8 @@ def setUp(self): # Add some fake 2D data for the box's component index = GridDataSource( - xdata=xs, ydata=ys, sort_order=('ascending', 'ascending')) + xdata=xs, ydata=ys, sort_order=("ascending", "ascending") + ) index_mapper = GridMapper(range=DataRange2D(index)) color_source = ImageData(data=np.ones(shape=(5, 5)), depth=1) @@ -44,16 +44,11 @@ def test_update_data_position(self): """ # Check that data position property is changed when position is changed - with self.assertTraitChanges(self.databox, 'data_position') as result: + with self.assertTraitChanges(self.databox, "data_position") as result: self.databox.position = [1, 1] # Without moving the DataBox, data_position trait defaults # to the list [0.0, 0.0] starting_position = [0.0, 0.0] - expected = ( - self.databox, - 'data_position', - starting_position, - starting_position - ) + expected = (self.databox, "data_position", starting_position, starting_position) self.assertSequenceEqual([expected], result.events) diff --git a/chaco/overlays/text_grid_overlay.py b/chaco/overlays/text_grid_overlay.py index a28052742..5c34daeac 100644 --- a/chaco/overlays/text_grid_overlay.py +++ b/chaco/overlays/text_grid_overlay.py @@ -6,13 +6,15 @@ from .aligned_container_overlay import AlignedContainerOverlay + class TextGridOverlay(AlignedContainerOverlay): - """ Overlay for plots containing a TextGrid + """Overlay for plots containing a TextGrid This subclass of AlignedContainerOverlay has a TextGrid which it displays. Subclasses or users are responsible for the content and formatting of the TextGrid. """ + # The text grid component we contain. text_grid = Instance(TextGrid) @@ -25,6 +27,6 @@ def _text_grid_changed(self, old, new): self.add(new) def _text_grid_default(self): - text_grid = TextGrid(font='modern 12', cell_border_width=0) + text_grid = TextGrid(font="modern 12", cell_border_width=0) self.add(text_grid) return text_grid diff --git a/chaco/pdf_graphics_context.py b/chaco/pdf_graphics_context.py index cec9bf362..d3ac3df86 100644 --- a/chaco/pdf_graphics_context.py +++ b/chaco/pdf_graphics_context.py @@ -1,9 +1,8 @@ - # Major library imports import warnings try: -# PDF imports from reportlab + # PDF imports from reportlab from reportlab.pdfgen.canvas import Canvas from reportlab.lib.pagesizes import letter, A4, landscape from reportlab.lib.units import inch, cm, mm, pica @@ -21,7 +20,7 @@ "letter": letter, "A4": A4, "landscape_letter": landscape(letter), - "landscape_A4": landscape(A4) + "landscape_A4": landscape(A4), } UNITS_MAP = { @@ -32,9 +31,9 @@ } if Canvas is not None: + class PdfPlotGraphicsContext(GraphicsContext): - """ A convenience class for rendering PlotComponents onto PDF - """ + """A convenience class for rendering PlotComponents onto PDF""" # The name of the file that this graphics context will use when # gc.save() is called without a filename being supplied. @@ -54,10 +53,16 @@ class PdfPlotGraphicsContext(GraphicsContext): dest_box = (0.5, 0.5, -0.5, -0.5) # The units of the values in dest_box - dest_box_units = "inch" # Enum("inch", "cm", "mm", "pica") - - def __init__(self, pdf_canvas=None, filename=None, pagesize=None, - dest_box=None, dest_box_units=None): + dest_box_units = "inch" # Enum("inch", "cm", "mm", "pica") + + def __init__( + self, + pdf_canvas=None, + filename=None, + pagesize=None, + dest_box=None, + dest_box_units=None, + ): if filename: self.filename = filename if pagesize: @@ -73,7 +78,7 @@ def __init__(self, pdf_canvas=None, filename=None, pagesize=None, GraphicsContext.__init__(self, pdf_canvas) def add_page(self): - """ Adds a new page to the PDF canvas and makes that the current + """Adds a new page to the PDF canvas and makes that the current drawing target. """ if self.gc is None: @@ -86,9 +91,10 @@ def add_page(self): # We'll need to call _initialize_page() before drawing self._page_initialized = False - def render_component(self, component, container_coords=False, - halign="center", valign="top"): - """ Erases the current contents of the graphics context and renders + def render_component( + self, component, container_coords=False, halign="center", valign="top" + ): + """Erases the current contents of the graphics context and renders the given component at the maximum possible scaling while preserving aspect ratio. @@ -186,9 +192,13 @@ def save(self, filename=None): self.gc.save() def _create_new_canvas(self): - """ Create the PDF canvas context. - """ - x, y, w, h, = self._get_bounding_box() + """Create the PDF canvas context.""" + ( + x, + y, + w, + h, + ) = self._get_bounding_box() if w < 0 or h < 0: self.gc = None return @@ -200,8 +210,7 @@ def _create_new_canvas(self): return gc def _get_bounding_box(self): - """ Compute the bounding rect of a page. - """ + """Compute the bounding rect of a page.""" pagesize = PAGE_SIZE_MAP[self.pagesize] units = UNITS_MAP[self.dest_box_units] @@ -221,9 +230,13 @@ def _get_bounding_box(self): return x, y, w, h def _initialize_page(self, gc): - """ Make sure the origin is set to something consistent. - """ - x, y, w, h, = self._get_bounding_box() + """Make sure the origin is set to something consistent.""" + ( + x, + y, + w, + h, + ) = self._get_bounding_box() gc.translate(x, y) diff --git a/chaco/plot.py b/chaco/plot.py index f1d369642..e4f96fcb3 100644 --- a/chaco/plot.py +++ b/chaco/plot.py @@ -47,14 +47,13 @@ from .jitterplot import JitterPlot - - -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # The Plot class -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- + class Plot(DataView): - """ Represents a correlated set of data, renderers, and axes in a single + """Represents a correlated set of data, renderers, and axes in a single screen region. A Plot can reference an arbitrary amount of data and can have an @@ -75,9 +74,9 @@ class Plot(DataView): data sources, create those data sources before handing them to the Plot. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Data-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The PlotData instance that drives this plot. data = Instance(AbstractPlotData) @@ -85,9 +84,9 @@ class Plot(DataView): #: Mapping of data names from self.data to their respective datasources. datasources = Dict(Str, Instance(AbstractDataSource)) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # General plotting traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Mapping of plot names to *lists* of plot renderers. plots = Dict(Str, List) @@ -102,8 +101,18 @@ class Plot(DataView): #: List of colors to cycle through when auto-coloring is requested. Picked #: and ordered to be red-green color-blind friendly, though should not #: be an issue for blue-yellow. - auto_colors = List(["green", "lightgreen", "blue", "lightblue", "red", - "pink", "darkgray", "silver"]) + auto_colors = List( + [ + "green", + "lightgreen", + "blue", + "lightblue", + "red", + "pink", + "darkgray", + "silver", + ] + ) # index into auto_colors list _auto_color_idx = Int(-1) @@ -113,29 +122,33 @@ class Plot(DataView): #: Mapping of renderer type string to renderer class #: This can be overriden to customize what renderer type the Plot #: will instantiate for its various plotting methods. - renderer_map = Dict(dict(line = LinePlot, - bar = BarPlot, - scatter = ScatterPlot, - polygon = PolygonPlot, - filled_line = FilledLinePlot, - cmap_scatter = ColormappedScatterPlot, - cmap_segment = ColormappedSegmentPlot, - img_plot = ImagePlot, - cmap_img_plot = CMapImagePlot, - contour_line_plot = ContourLinePlot, - contour_poly_plot = ContourPolyPlot, - candle = CandlePlot, - quiver = QuiverPlot, - scatter_1d = ScatterPlot1D, - segment = SegmentPlot, - text = TextPlot, - textplot_1d = TextPlot1D, - line_scatter_1d = LineScatterPlot1D, - jitterplot = JitterPlot)) - - #------------------------------------------------------------------------ + renderer_map = Dict( + dict( + line=LinePlot, + bar=BarPlot, + scatter=ScatterPlot, + polygon=PolygonPlot, + filled_line=FilledLinePlot, + cmap_scatter=ColormappedScatterPlot, + cmap_segment=ColormappedSegmentPlot, + img_plot=ImagePlot, + cmap_img_plot=CMapImagePlot, + contour_line_plot=ContourLinePlot, + contour_poly_plot=ContourPolyPlot, + candle=CandlePlot, + quiver=QuiverPlot, + scatter_1d=ScatterPlot1D, + segment=SegmentPlot, + text=TextPlot, + textplot_1d=TextPlot1D, + line_scatter_1d=LineScatterPlot1D, + jitterplot=JitterPlot, + ) + ) + + # ------------------------------------------------------------------------ # Annotations and decorations - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The title of the plot. title = Property() @@ -161,13 +174,13 @@ class Plot(DataView): #: Convenience attribute for legend.align; can be "ur", "ul", "ll", "lr". legend_alignment = Property - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, data=None, **kwtraits): - if 'origin' in kwtraits: - self.default_origin = kwtraits.pop('origin') + if "origin" in kwtraits: + self.default_origin = kwtraits.pop("origin") if "title" in kwtraits: title = kwtraits.pop("title") else: @@ -179,25 +192,34 @@ def __init__(self, data=None, **kwtraits): elif type(data) in (ndarray, tuple, list): self.data = ArrayPlotData(data) else: - raise ValueError("Don't know how to create PlotData for data " - "of type {0}".format(type(data))) + raise ValueError( + "Don't know how to create PlotData for data " + "of type {0}".format(type(data)) + ) if not self._title: - self._title = PlotLabel(font="swiss 16", visible=False, - overlay_position="top", component=self) + self._title = PlotLabel( + font="swiss 16", visible=False, overlay_position="top", component=self + ) if title is not None: self.title = title if not self.legend: - self.legend = Legend(visible=False, align="ur", error_icon="blank", - padding=10, component=self) + self.legend = Legend( + visible=False, + align="ur", + error_icon="blank", + padding=10, + component=self, + ) # ensure that we only get displayed once by new_window() self._plot_ui_info = None - def add_xy_plot(self, index_name, value_name, renderer_factory, name=None, - origin=None, **kwds): - """ Add a BaseXYPlot renderer subclass to this Plot. + def add_xy_plot( + self, index_name, value_name, renderer_factory, name=None, origin=None, **kwds + ): + """Add a BaseXYPlot renderer subclass to this Plot. Parameters ---------- @@ -235,12 +257,12 @@ def add_xy_plot(self, index_name, value_name, renderer_factory, name=None, vmap = LogMapper(range=self.value_range) renderer = renderer_factory( - index = index, - value = value, - index_mapper = imap, - value_mapper = vmap, - orientation = self.orientation, - origin = origin, + index=index, + value=value, + index_mapper=imap, + value_mapper=vmap, + orientation=self.orientation, + origin=origin, **kwds ) self.add(renderer) @@ -248,9 +270,17 @@ def add_xy_plot(self, index_name, value_name, renderer_factory, name=None, self.invalidate_and_redraw() return self.plots[name] - def plot(self, data, type="line", name=None, index_scale="linear", - value_scale="linear", origin=None, **styles): - """ Adds a new sub-plot using the given data and plot style. + def plot( + self, + data, + type="line", + name=None, + index_scale="linear", + value_scale="linear", + origin=None, + **styles + ): + """Adds a new sub-plot using the given data and plot style. Parameters ---------- @@ -324,16 +354,16 @@ def plot(self, data, type="line", name=None, index_scale="linear", if origin is None: origin = self.default_origin - if plot_type in ("line", "scatter", "polygon", "bar", "filled_line", - "segment"): + if plot_type in ("line", "scatter", "polygon", "bar", "filled_line", "segment"): # Tie data to the index range if len(data) == 1: if self.default_index is None: # Create the default index based on the length of the first # data series value = self._get_or_create_datasource(data[0]) - self.default_index = ArrayDataSource(arange(len(value.get_data())), - sort_order="none") + self.default_index = ArrayDataSource( + arange(len(value.get_data())), sort_order="none" + ) self.index_range.add(self.default_index) index = self.default_index else: @@ -353,63 +383,81 @@ def plot(self, data, type="line", name=None, index_scale="linear", cls = self.renderer_map[plot_type] # handle auto-coloring request if styles.get("color") == "auto": - self._auto_color_idx = \ - (self._auto_color_idx + 1) % len(self.auto_colors) + self._auto_color_idx = (self._auto_color_idx + 1) % len( + self.auto_colors + ) styles["color"] = self.auto_colors[self._auto_color_idx] elif plot_type in ("polygon", "filled_line"): cls = self.renderer_map[plot_type] # handle auto-coloring request if styles.get("edge_color") == "auto": - self._auto_edge_color_idx = \ - (self._auto_edge_color_idx + 1) % len(self.auto_colors) - styles["edge_color"] = self.auto_colors[self._auto_edge_color_idx] + self._auto_edge_color_idx = ( + self._auto_edge_color_idx + 1 + ) % len(self.auto_colors) + styles["edge_color"] = self.auto_colors[ + self._auto_edge_color_idx + ] if styles.get("face_color") == "auto": - self._auto_face_color_idx = \ - (self._auto_face_color_idx + 1) % len(self.auto_colors) - styles["face_color"] = self.auto_colors[self._auto_face_color_idx] - elif plot_type == 'bar': + self._auto_face_color_idx = ( + self._auto_face_color_idx + 1 + ) % len(self.auto_colors) + styles["face_color"] = self.auto_colors[ + self._auto_face_color_idx + ] + elif plot_type == "bar": cls = self.renderer_map[plot_type] # handle auto-coloring request if styles.get("color") == "auto": - self._auto_color_idx = \ - (self._auto_color_idx + 1) % len(self.auto_colors) + self._auto_color_idx = (self._auto_color_idx + 1) % len( + self.auto_colors + ) styles["fill_color"] = self.auto_colors[self._auto_color_idx] else: raise ValueError("Unhandled plot type: " + plot_type) if self.index_scale == "linear": - imap = LinearMapper(range=self.index_range, - stretch_data=self.index_mapper.stretch_data) + imap = LinearMapper( + range=self.index_range, + stretch_data=self.index_mapper.stretch_data, + ) else: - imap = LogMapper(range=self.index_range, - stretch_data=self.index_mapper.stretch_data) + imap = LogMapper( + range=self.index_range, + stretch_data=self.index_mapper.stretch_data, + ) if self.value_scale == "linear": - vmap = LinearMapper(range=self.value_range, - stretch_data=self.value_mapper.stretch_data) + vmap = LinearMapper( + range=self.value_range, + stretch_data=self.value_mapper.stretch_data, + ) else: - vmap = LogMapper(range=self.value_range, - stretch_data=self.value_mapper.stretch_data) + vmap = LogMapper( + range=self.value_range, + stretch_data=self.value_mapper.stretch_data, + ) - plot = cls(index=index, - value=value, - index_mapper=imap, - value_mapper=vmap, - orientation=self.orientation, - origin = origin, - **styles) + plot = cls( + index=index, + value=value, + index_mapper=imap, + value_mapper=vmap, + orientation=self.orientation, + origin=origin, + **styles + ) self.add(plot) new_plots.append(plot) - if plot_type == 'bar': + if plot_type == "bar": # For bar plots, compute the ranges from the data to make the # plot look clean. def custom_index_func(data_low, data_high, margin, tight_bounds): - """ Compute custom bounds of the plot along index (in + """Compute custom bounds of the plot along index (in data space). """ - bar_width = styles.get('bar_width', cls().bar_width) + bar_width = styles.get("bar_width", cls().bar_width) plot_low = data_low - bar_width plot_high = data_high + bar_width return plot_low, plot_high @@ -418,11 +466,11 @@ def custom_index_func(data_low, data_high, margin, tight_bounds): self.index_range.bounds_func = custom_index_func def custom_value_func(data_low, data_high, margin, tight_bounds): - """ Compute custom bounds of the plot along value (in + """Compute custom bounds of the plot along value (in data space). """ - plot_low = data_low - (data_high-data_low)*0.1 - plot_high = data_high + (data_high-data_low)*0.1 + plot_low = data_low - (data_high - data_low) * 0.1 + plot_high = data_high + (data_high - data_low) * 0.1 return plot_low, plot_high if self.value_range.bounds_func is None: @@ -447,36 +495,46 @@ def custom_value_func(data_low, data_high, margin, tight_bounds): text = self._get_or_create_datasource(data[2]) if self.index_scale == "linear": - imap = LinearMapper(range=self.index_range, - stretch_data=self.index_mapper.stretch_data) + imap = LinearMapper( + range=self.index_range, stretch_data=self.index_mapper.stretch_data + ) else: - imap = LogMapper(range=self.index_range, - stretch_data=self.index_mapper.stretch_data) + imap = LogMapper( + range=self.index_range, stretch_data=self.index_mapper.stretch_data + ) if self.value_scale == "linear": - vmap = LinearMapper(range=self.value_range, - stretch_data=self.value_mapper.stretch_data) + vmap = LinearMapper( + range=self.value_range, stretch_data=self.value_mapper.stretch_data + ) else: - vmap = LogMapper(range=self.value_range, - stretch_data=self.value_mapper.stretch_data) + vmap = LogMapper( + range=self.value_range, stretch_data=self.value_mapper.stretch_data + ) cls = self.renderer_map[plot_type] - plot = cls(index=index, - index_mapper=imap, - value=value, - value_mapper=vmap, - text=text, - orientation=self.orientation, - origin=origin, - **styles) + plot = cls( + index=index, + index_mapper=imap, + value=value, + value_mapper=vmap, + text=text, + orientation=self.orientation, + origin=origin, + **styles + ) self.add(plot) self.plots[name] = [plot] elif plot_type in ("cmap_scatter", "cmap_segment"): if plot_type == "cmap_scatter" and len(data) != 3: - raise ValueError("Colormapped scatter plots require (index, value, color) data") + raise ValueError( + "Colormapped scatter plots require (index, value, color) data" + ) elif len(data) > 4 or len(data) < 3: - raise ValueError("Colormapped segment plots require (index, value, color) or (index, value, color, width) data") + raise ValueError( + "Colormapped segment plots require (index, value, color) or (index, value, color, width) data" + ) index = self._get_or_create_datasource(data[0]) if self.default_index is None: @@ -520,33 +578,39 @@ def custom_value_func(data_low, data_high, margin, tight_bounds): size_min = styles.pop("size_min", 1) size_max = styles.pop("size_max", 10) - sizemap = LinearMapper(low_pos=size_min, high_pos=size_max, - range=size_range) - + sizemap = LinearMapper( + low_pos=size_min, high_pos=size_max, range=size_range + ) if self.index_scale == "linear": - imap = LinearMapper(range=self.index_range, - stretch_data=self.index_mapper.stretch_data) + imap = LinearMapper( + range=self.index_range, stretch_data=self.index_mapper.stretch_data + ) else: - imap = LogMapper(range=self.index_range, - stretch_data=self.index_mapper.stretch_data) + imap = LogMapper( + range=self.index_range, stretch_data=self.index_mapper.stretch_data + ) if self.value_scale == "linear": - vmap = LinearMapper(range=self.value_range, - stretch_data=self.value_mapper.stretch_data) + vmap = LinearMapper( + range=self.value_range, stretch_data=self.value_mapper.stretch_data + ) else: - vmap = LogMapper(range=self.value_range, - stretch_data=self.value_mapper.stretch_data) + vmap = LogMapper( + range=self.value_range, stretch_data=self.value_mapper.stretch_data + ) cls = self.renderer_map[plot_type] - plot = cls(index=index, - index_mapper=imap, - value=value, - value_mapper=vmap, - color_data=color, - color_mapper=self.color_mapper, - orientation=self.orientation, - origin=origin, - **styles) + plot = cls( + index=index, + index_mapper=imap, + value=value, + value_mapper=vmap, + color_data=color, + color_mapper=self.color_mapper, + orientation=self.orientation, + origin=origin, + **styles + ) if len(data) == 4: plot.width_data = size plot.width_mapper = sizemap @@ -559,11 +623,18 @@ def custom_value_func(data_low, data_high, margin, tight_bounds): return self.plots[name] - - def img_plot(self, data, name=None, colormap=None, - xbounds=None, ybounds=None, origin=None, hide_grids=True, - **styles): - """ Adds image plots to this Plot object. + def img_plot( + self, + data, + name=None, + colormap=None, + xbounds=None, + ybounds=None, + origin=None, + hide_grids=True, + **styles + ): + """Adds image plots to this Plot object. If *data* has shape (N, M, 3) or (N, M, 4), then it is treated as RGB or RGBA (respectively) and *colormap* is ignored. @@ -604,7 +675,7 @@ def img_plot(self, data, name=None, colormap=None, value = self._get_or_create_datasource(data) array_data = value.get_data() if len(array_data.shape) == 3: - if array_data.shape[2] not in (3,4): + if array_data.shape[2] not in (3, 4): raise ValueError("Image plots require color depth of 3 or 4.") cls = self.renderer_map["img_plot"] kwargs = dict(**styles) @@ -622,13 +693,31 @@ def img_plot(self, data, name=None, colormap=None, self.color_mapper = colormap cls = self.renderer_map["cmap_img_plot"] kwargs = dict(value_mapper=colormap, **styles) - return self._create_2d_plot(cls, name, origin, xbounds, ybounds, value, - hide_grids, cell_plot=True, **kwargs) - + return self._create_2d_plot( + cls, + name, + origin, + xbounds, + ybounds, + value, + hide_grids, + cell_plot=True, + **kwargs + ) - def contour_plot(self, data, type="line", name=None, poly_cmap=None, - xbounds=None, ybounds=None, origin=None, hide_grids=True, **styles): - """ Adds contour plots to this Plot object. + def contour_plot( + self, + data, + type="line", + name=None, + poly_cmap=None, + xbounds=None, + ybounds=None, + origin=None, + hide_grids=True, + **styles + ): + """Adds contour plots to this Plot object. Parameters ---------- @@ -677,23 +766,31 @@ def contour_plot(self, data, type="line", name=None, poly_cmap=None, cmap = kwargs["colors"] if isinstance(cmap, FunctionType): kwargs["colors"] = cmap(DataRange1D(value)) - elif getattr(cmap, 'range', 'dummy') is None: + elif getattr(cmap, "range", "dummy") is None: cmap.range = DataRange1D(value) elif type == "poly": if poly_cmap is None: poly_cmap = Spectral(DataRange1D(value)) elif isinstance(poly_cmap, FunctionType): poly_cmap = poly_cmap(DataRange1D(value)) - elif getattr(poly_cmap, 'range', 'dummy') is None: + elif getattr(poly_cmap, "range", "dummy") is None: poly_cmap.range = DataRange1D(value) cls = self.renderer_map["contour_poly_plot"] kwargs = dict(color_mapper=poly_cmap, **styles) else: raise ValueError("Unhandled contour plot type: " + type) - return self._create_2d_plot(cls, name, origin, xbounds, ybounds, value, - hide_grids, cell_plot=False, **kwargs) - + return self._create_2d_plot( + cls, + name, + origin, + xbounds, + ybounds, + value, + hide_grids, + cell_plot=False, + **kwargs + ) def _process_2d_bounds(self, bounds, array_data, axis, cell_plot): """Transform an arbitrary bounds definition into a linspace. @@ -733,9 +830,11 @@ def _process_2d_bounds(self, bounds, array_data, axis, cell_plot): elif isinstance(bounds, ndarray) and bounds.ndim == 1: if len(bounds) != num_ticks: # bounds is 1D, but of the wrong size - msg = ("1D bounds of an image plot needs to have 1 more " - "element than its corresponding data shape, because " - "they represent the locations of pixel boundaries.") + msg = ( + "1D bounds of an image plot needs to have 1 more " + "element than its corresponding data shape, because " + "they represent the locations of pixel boundaries." + ) raise ValueError(msg) else: return bounds @@ -745,23 +844,35 @@ def _process_2d_bounds(self, bounds, array_data, axis, cell_plot): # This is triggered when doing something like # >>> xbounds, ybounds = meshgrid(...) if bounds.shape[axis] != num_ticks: - msg = ("2D bounds of an image plot needs to have the same " - "shape as the underlying data, because " - "they are assumed to be generated from meshgrids.") + msg = ( + "2D bounds of an image plot needs to have the same " + "shape as the underlying data, because " + "they are assumed to be generated from meshgrids." + ) raise ValueError(msg) else: if axis == 0: - bounds = bounds[:,0] + bounds = bounds[:, 0] else: - bounds = bounds[0,:] + bounds = bounds[0, :] return bounds - raise ValueError("bounds must be None, a tuple, an array, " - "or a PlotData name") - + raise ValueError( + "bounds must be None, a tuple, an array, " "or a PlotData name" + ) - def _create_2d_plot(self, cls, name, origin, xbounds, ybounds, value_ds, - hide_grids, cell_plot=False, **kwargs): + def _create_2d_plot( + self, + cls, + name, + origin, + xbounds, + ybounds, + value_ds, + hide_grids, + cell_plot=False, + **kwargs + ): if name is None: name = self._make_new_plot_name() if origin is None: @@ -781,18 +892,22 @@ def _create_2d_plot(self, cls, name, origin, xbounds, ybounds, value_ds, ys = self._process_2d_bounds(ybounds, array_data, 0, cell_plot) # Create the index and add its datasources to the appropriate ranges - index = GridDataSource(xs, ys, sort_order=('ascending', 'ascending')) + index = GridDataSource(xs, ys, sort_order=("ascending", "ascending")) self.range2d.add(index) - mapper = GridMapper(range=self.range2d, - stretch_data_x=self.x_mapper.stretch_data, - stretch_data_y=self.y_mapper.stretch_data) + mapper = GridMapper( + range=self.range2d, + stretch_data_x=self.x_mapper.stretch_data, + stretch_data_y=self.y_mapper.stretch_data, + ) - plot = cls(index=index, - value=value_ds, - index_mapper=mapper, - orientation=self.orientation, - origin=origin, - **kwargs) + plot = cls( + index=index, + value=value_ds, + index_mapper=mapper, + orientation=self.orientation, + origin=origin, + **kwargs + ) if hide_grids: self.x_grid.visible = False @@ -802,10 +917,8 @@ def _create_2d_plot(self, cls, name, origin, xbounds, ybounds, value_ds, self.plots[name] = [plot] return self.plots[name] - - def candle_plot(self, data, name=None, value_scale="linear", origin=None, - **styles): - """ Adds a new sub-plot using the given data and plot style. + def candle_plot(self, data, name=None, value_scale="linear", origin=None, **styles): + """Adds a new sub-plot using the given data and plot style. Parameters ---------- @@ -886,53 +999,59 @@ def candle_plot(self, data, name=None, value_scale="linear", origin=None, min = None max = None elif len(data) == 5: - index, min, bar_min, bar_max, max = \ - map(self._get_or_create_datasource, data) + index, min, bar_min, bar_max, max = map( + self._get_or_create_datasource, data + ) self.value_range.add(min, bar_min, bar_max, max) center = None elif len(data) == 6: - index, min, bar_min, center, bar_max, max = \ - map(self._get_or_create_datasource, data) + index, min, bar_min, center, bar_max, max = map( + self._get_or_create_datasource, data + ) self.value_range.add(min, bar_min, center, bar_max, max) self.index_range.add(index) if styles.get("bar_color") == "auto" or styles.get("color") == "auto": - self._auto_color_idx = \ - (self._auto_color_idx + 1) % len(self.auto_colors) + self._auto_color_idx = (self._auto_color_idx + 1) % len(self.auto_colors) styles["color"] = self.auto_colors[self._auto_color_idx] if self.index_scale == "linear": - imap = LinearMapper(range=self.index_range, - stretch_data=self.index_mapper.stretch_data) + imap = LinearMapper( + range=self.index_range, stretch_data=self.index_mapper.stretch_data + ) else: - imap = LogMapper(range=self.index_range, - stretch_data=self.index_mapper.stretch_data) + imap = LogMapper( + range=self.index_range, stretch_data=self.index_mapper.stretch_data + ) if self.value_scale == "linear": - vmap = LinearMapper(range=self.value_range, - stretch_data=self.value_mapper.stretch_data) + vmap = LinearMapper( + range=self.value_range, stretch_data=self.value_mapper.stretch_data + ) else: - vmap = LogMapper(range=self.value_range, - stretch_data=self.value_mapper.stretch_data) + vmap = LogMapper( + range=self.value_range, stretch_data=self.value_mapper.stretch_data + ) cls = self.renderer_map["candle"] - plot = cls(index = index, - min_values = min, - bar_min = bar_min, - center_values = center, - bar_max = bar_max, - max_values = max, - index_mapper = imap, - value_mapper = vmap, - orientation = self.orientation, - origin = self.origin, - **styles) + plot = cls( + index=index, + min_values=min, + bar_min=bar_min, + center_values=center, + bar_max=bar_max, + max_values=max, + index_mapper=imap, + value_mapper=vmap, + orientation=self.orientation, + origin=self.origin, + **styles + ) self.add(plot) self.plots[name] = [plot] return [plot] - def quiverplot(self, data, name=None, origin=None, - **styles): - """ Adds a new sub-plot using the given data and plot style. + def quiverplot(self, data, name=None, origin=None, **styles): + """Adds a new sub-plot using the given data and plot style. Parameters ---------- @@ -976,28 +1095,39 @@ def quiverplot(self, data, name=None, origin=None, self.index_range.add(index) self.value_range.add(value) - imap = LinearMapper(range=self.index_range, - stretch_data=self.index_mapper.stretch_data) - vmap = LinearMapper(range=self.value_range, - stretch_data=self.value_mapper.stretch_data) + imap = LinearMapper( + range=self.index_range, stretch_data=self.index_mapper.stretch_data + ) + vmap = LinearMapper( + range=self.value_range, stretch_data=self.value_mapper.stretch_data + ) cls = self.renderer_map["quiver"] - plot = cls(index = index, - value = value, - vectors = vectors, - index_mapper = imap, - value_mapper = vmap, - name = name, - origin = origin, - **styles - ) + plot = cls( + index=index, + value=value, + vectors=vectors, + index_mapper=imap, + value_mapper=vmap, + name=name, + origin=origin, + **styles + ) self.add(plot) self.plots[name] = [plot] return [plot] - def plot_1d(self, data, type='scatter_1d', name=None, orientation=None, - direction=None, scale="linear", **styles): - """ Adds a new sub-plot using the given data and plot style. + def plot_1d( + self, + data, + type="scatter_1d", + name=None, + orientation=None, + direction=None, + scale="linear", + **styles + ): + """Adds a new sub-plot using the given data and plot style. Parameters ---------- @@ -1042,20 +1172,19 @@ def plot_1d(self, data, type='scatter_1d', name=None, orientation=None, orientation = self.orientation if direction is None: - if orientation == 'v': + if orientation == "v": if "bottom" in self.origin: - direction = 'normal' + direction = "normal" else: - direction = 'flipped' + direction = "flipped" else: if "left" in self.origin: - direction = 'normal' + direction = "normal" else: - direction = 'flipped' + direction = "flipped" plots = [] - if plot_type in ("scatter_1d", "textplot_1d", "line_scatter_1d", - "jitterplot"): + if plot_type in ("scatter_1d", "textplot_1d", "line_scatter_1d", "jitterplot"): # Tie data to the index range index = self._get_or_create_datasource(data[0]) if self.default_index is None: @@ -1078,18 +1207,22 @@ def plot_1d(self, data, type='scatter_1d', name=None, orientation=None, index_range.add(index) if scale == "linear": - imap = LinearMapper(range=index_range, - stretch_data=index_mapper.stretch_data) + imap = LinearMapper( + range=index_range, stretch_data=index_mapper.stretch_data + ) else: - imap = LogMapper(range=index_range, - stretch_data=index_mapper.stretch_data) + imap = LogMapper( + range=index_range, stretch_data=index_mapper.stretch_data + ) cls = self.renderer_map[plot_type] - plot = cls(index=index, - index_mapper=imap, - orientation=orientation, - direction=direction, - **styles) + plot = cls( + index=index, + index_mapper=imap, + orientation=orientation, + direction=direction, + **styles + ) plots.append(plot) self.add(plot) elif plot_type in ("textplot_1d",): @@ -1098,25 +1231,28 @@ def plot_1d(self, data, type='scatter_1d', name=None, orientation=None, value = self._get_or_create_datasource(source) if scale == "linear": - imap = LinearMapper(range=index_range, - stretch_data=index_mapper.stretch_data) + imap = LinearMapper( + range=index_range, stretch_data=index_mapper.stretch_data + ) else: - imap = LogMapper(range=index_range, - stretch_data=index_mapper.stretch_data) + imap = LogMapper( + range=index_range, stretch_data=index_mapper.stretch_data + ) cls = self.renderer_map[plot_type] - plot = cls(index=index, - index_mapper=imap, - value=value, - orientation=orientation, - direction=direction, - **styles) + plot = cls( + index=index, + index_mapper=imap, + value=value, + orientation=orientation, + direction=direction, + **styles + ) plots.append(plot) self.add(plot) self.plots[name] = plots return plots - def delplot(self, *names): """ Removes the named sub-plots. """ @@ -1134,8 +1270,8 @@ def delplot(self, *names): # Cull the candidate list of sources to remove by checking the other plots sources_in_use = set() for p in itertools.chain(*list(self.plots.values())): - sources_in_use.add(p.index) - sources_in_use.add(p.value) + sources_in_use.add(p.index) + sources_in_use.add(p.value) unused_sources = deleted_sources - sources_in_use - set([None]) @@ -1151,15 +1287,14 @@ def delplot(self, *names): warnings.warn("Couldn't remove datasource from datarange.") def hideplot(self, *names): - """ Convenience function to sets the named plots to be invisible. Their + """Convenience function to sets the named plots to be invisible. Their renderers are not removed, and they are still in the list of plots. """ for renderer in itertools.chain(*[self.plots[name] for name in names]): renderer.visible = False def showplot(self, *names): - """ Convenience function to sets the named plots to be visible. - """ + """Convenience function to sets the named plots to be visible.""" for renderer in itertools.chain(*[self.plots[name] for name in names]): renderer.visible = True @@ -1169,6 +1304,7 @@ def new_window(self, configure=False): Don't call this if the plot is already displayed in a window. """ from chaco.ui.plot_window import PlotWindow + if self._plot_ui_info is None: if configure: self._plot_ui_info = PlotWindow(plot=self).configure_traits() @@ -1176,15 +1312,12 @@ def new_window(self, configure=False): self._plot_ui_info = PlotWindow(plot=self).edit_traits() return self._plot_ui_info - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ - - + # ------------------------------------------------------------------------ def _make_new_plot_name(self): - """ Returns a string that is not already used as a plot title. - """ + """Returns a string that is not already used as a plot title.""" n = len(self.plots) plot_template = "plot%d" while 1: @@ -1196,7 +1329,7 @@ def _make_new_plot_name(self): return name def _get_or_create_datasource(self, name): - """ Returns the data source associated with the given name, or creates + """Returns the data source associated with the given name, or creates it if it doesn't exist. """ @@ -1211,24 +1344,27 @@ def _get_or_create_datasource(self, name): ds = ArrayDataSource(data, sort_order="none") elif len(data.shape) == 2: ds = ImageData(data=data, value_depth=1) - elif len(data.shape) == 3 and data.shape[2] in (3,4): + elif len(data.shape) == 3 and data.shape[2] in (3, 4): ds = ImageData(data=data, value_depth=int(data.shape[2])) else: - raise ValueError("Unhandled array shape in creating new " - "plot: %s" % str(data.shape)) + raise ValueError( + "Unhandled array shape in creating new " + "plot: %s" % str(data.shape) + ) elif isinstance(data, AbstractDataSource): ds = data else: - raise ValueError("Couldn't create datasource for data of " - "type %s" % type(data)) + raise ValueError( + "Couldn't create datasource for data of " "type %s" % type(data) + ) self.datasources[name] = ds return self.datasources[name] - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _color_mapper_changed(self): for plist in self.plots.values(): @@ -1266,57 +1402,79 @@ def _plots_items_changed(self, event): self.legend.plots = self.plots def _index_scale_changed(self, old, new): - if old is None: return - if new == old: return - if not self.range2d: return + if old is None: + return + if new == old: + return + if not self.range2d: + return if self.index_scale == "linear": - imap = LinearMapper(range=self.index_range, - screen_bounds=self.index_mapper.screen_bounds, - stretch_data=self.index_mapper.stretch_data) + imap = LinearMapper( + range=self.index_range, + screen_bounds=self.index_mapper.screen_bounds, + stretch_data=self.index_mapper.stretch_data, + ) else: - imap = LogMapper(range=self.index_range, - screen_bounds=self.index_mapper.screen_bounds, - stretch_data=self.index_mapper.stretch_data) + imap = LogMapper( + range=self.index_range, + screen_bounds=self.index_mapper.screen_bounds, + stretch_data=self.index_mapper.stretch_data, + ) self.index_mapper = imap for key in self.plots: for plot in self.plots[key]: if not isinstance(plot, BaseXYPlot): raise ValueError("log scale only supported on XY plots") if self.index_scale == "linear": - imap = LinearMapper(range=plot.index_range, - screen_bounds=plot.index_mapper.screen_bounds, - stretch_data=self.index_mapper.stretch_data) + imap = LinearMapper( + range=plot.index_range, + screen_bounds=plot.index_mapper.screen_bounds, + stretch_data=self.index_mapper.stretch_data, + ) else: - imap = LogMapper(range=plot.index_range, - screen_bounds=plot.index_mapper.screen_bounds, - stretch_data=self.index_mapper.stretch_data) + imap = LogMapper( + range=plot.index_range, + screen_bounds=plot.index_mapper.screen_bounds, + stretch_data=self.index_mapper.stretch_data, + ) plot.index_mapper = imap def _value_scale_changed(self, old, new): - if old is None: return - if new == old: return - if not self.range2d: return + if old is None: + return + if new == old: + return + if not self.range2d: + return if self.value_scale == "linear": - vmap = LinearMapper(range=self.value_range, - screen_bounds=self.value_mapper.screen_bounds, - stretch_data=self.value_mapper.stretch_data) + vmap = LinearMapper( + range=self.value_range, + screen_bounds=self.value_mapper.screen_bounds, + stretch_data=self.value_mapper.stretch_data, + ) else: - vmap = LogMapper(range=self.value_range, - screen_bounds=self.value_mapper.screen_bounds, - stretch_data=self.value_mapper.stretch_data) + vmap = LogMapper( + range=self.value_range, + screen_bounds=self.value_mapper.screen_bounds, + stretch_data=self.value_mapper.stretch_data, + ) self.value_mapper = vmap for key in self.plots: for plot in self.plots[key]: if not isinstance(plot, BaseXYPlot): raise ValueError("log scale only supported on XY plots") if self.value_scale == "linear": - vmap = LinearMapper(range=plot.value_range, - screen_bounds=plot.value_mapper.screen_bounds, - stretch_data=self.value_mapper.stretch_data) + vmap = LinearMapper( + range=plot.value_range, + screen_bounds=plot.value_mapper.screen_bounds, + stretch_data=self.value_mapper.stretch_data, + ) else: - vmap = LogMapper(range=plot.value_range, - screen_bounds=plot.value_mapper.screen_bounds, - stretch_data=self.value_mapper.stretch_data) + vmap = LogMapper( + range=plot.value_range, + screen_bounds=plot.value_mapper.screen_bounds, + stretch_data=self.value_mapper.stretch_data, + ) plot.value_mapper = vmap def __title_changed(self, old, new): @@ -1328,11 +1486,11 @@ def _legend_changed(self, old, new): new.plots = self.plots def _handle_range_changed(self, name, old, new): - """ Overrides the DataView default behavior. + """Overrides the DataView default behavior. Primarily changes how the list of renderers is looked up. """ - mapper = getattr(self, name+"_mapper") + mapper = getattr(self, name + "_mapper") if mapper.range == old: mapper.range = new if old is not None: @@ -1345,9 +1503,9 @@ def _handle_range_changed(self, name, old, new): if hasattr(renderer, range_name): setattr(renderer, range_name, new) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property getters and setters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _set_legend_alignment(self, align): if self.legend: diff --git a/chaco/plot_canvas.py b/chaco/plot_canvas.py index b31ac2cbf..fb20da139 100644 --- a/chaco/plot_canvas.py +++ b/chaco/plot_canvas.py @@ -1,4 +1,3 @@ - # Enthought library imports from enable.api import Canvas from traits.api import Instance, Tuple @@ -6,22 +5,23 @@ # Local, relative chaco imports from .plot_containers import DEFAULT_DRAWING_ORDER + class PlotCanvas(Canvas): - """ The PlotCanvas is basically like Canvas, but we inherit some behaviors + """The PlotCanvas is basically like Canvas, but we inherit some behaviors from PlotComponent as well. Some methods are redefined in here to explicitly make sure we get the right dispatch order. """ - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Public traits - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Default size to use for resizable components placed onto us. default_component_size = Tuple(200, 200) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Inherited traits - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Explicitly use the Chaco drawing order instead of the Enable one draw_order = Instance(list, args=(DEFAULT_DRAWING_ORDER,)) @@ -33,10 +33,9 @@ class PlotCanvas(Canvas): # Override the definition from Component use_backbuffer = False - - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Inherited methods - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- def draw(self, gc, view_bounds=None, mode="default"): if self.view_bounds is None: @@ -49,7 +48,7 @@ def _dispatch_draw(self, layer, gc, view_bounds, mode): Canvas._dispatch_draw(self, layer, gc, view_bounds, mode) def get_preferred_size(self, components=None): - """ Returns the size (width,height) that is preferred for this + """Returns the size (width,height) that is preferred for this components. """ if self.view_bounds is not None: diff --git a/chaco/plot_canvas_toolbar.py b/chaco/plot_canvas_toolbar.py index a5200b59b..9ed14b74e 100644 --- a/chaco/plot_canvas_toolbar.py +++ b/chaco/plot_canvas_toolbar.py @@ -1,4 +1,3 @@ - from traits.api import Any, Enum, Int from enable.drawing.api import ToolbarButton @@ -32,9 +31,8 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): self._do_layout() pref_size = self.get_preferred_size() - # Special check for when we are overlaying an instance of enable.Canvas - if hasattr(component, 'view_bounds'): + if hasattr(component, "view_bounds"): cx, cy, cx2, cy2 = component.view_bounds cwidth = cx2 - cx + 1 cheight = cy2 - cy + 1 @@ -47,14 +45,14 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): elif self.align in ("lr", "ll", "bottom"): y = cy else: - y = cy + (cheight - pref_size[1])/2 + y = cy + (cheight - pref_size[1]) / 2 if self.align in ("ur", "lr", "right"): x = cx + cwidth - self.outer_width elif self.align in ("ul", "ll", "left"): x = cx else: - x = cx + (cwidth - pref_size[0])/2 + x = cx + (cwidth - pref_size[0]) / 2 self.outer_position = [x, y] VPlotContainer._draw(self, gc, view_bounds, mode) diff --git a/chaco/plot_component.py b/chaco/plot_component.py index 94e78cac2..d7a8f30c7 100644 --- a/chaco/plot_component.py +++ b/chaco/plot_component.py @@ -6,8 +6,16 @@ from traits.api import Bool, Instance, observe, Str -DEFAULT_DRAWING_ORDER = ["background", "image", "underlay", "plot", - "selection", "border", "annotation", "overlay"] +DEFAULT_DRAWING_ORDER = [ + "background", + "image", + "underlay", + "plot", + "selection", + "border", + "annotation", + "overlay", +] class PlotComponent(Component): @@ -26,9 +34,9 @@ class PlotComponent(Component): requires_redraw=True in the definition of the trait. """ - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Rendering control traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The order in which various rendering classes on this component are drawn. #: Note that if this component is placed in a container, in most cases @@ -59,13 +67,14 @@ class PlotComponent(Component): use_draw_order = Bool(True) def _use_draw_order_changed(self, old, new): - """ Handler to catch the case when someone is trying to use the + """Handler to catch the case when someone is trying to use the old-style drawing mechanism, which is now unsupported. """ if new == False: - raise RuntimeError("The old-style drawing mechanism is no longer " \ - "supported in Chaco.") + raise RuntimeError( + "The old-style drawing mechanism is no longer " "supported in Chaco." + ) - @observe('+requires_redraw') + @observe("+requires_redraw") def _plot_component_invalidated(self, event): self.invalidate_and_redraw() diff --git a/chaco/plot_containers.py b/chaco/plot_containers.py index b95816b7c..f9f0acfbd 100644 --- a/chaco/plot_containers.py +++ b/chaco/plot_containers.py @@ -4,10 +4,25 @@ from numpy import amax, any, arange, array, cumsum, hstack, sum, zeros, zeros_like # Enthought library imports -from traits.api import Any, Array, Either, Enum, Float, Instance, \ - List, Property, String, Trait, Tuple, Int -from enable.simple_layout import simple_container_get_preferred_size, \ - simple_container_do_layout +from traits.api import ( + Any, + Array, + Either, + Enum, + Float, + Instance, + List, + Property, + String, + Trait, + Tuple, + Int, +) +from enable.simple_layout import ( + simple_container_get_preferred_size, + simple_container_do_layout, +) + try: from enable.api import ConstraintsContainer except ImportError: @@ -17,25 +32,38 @@ from .base_plot_container import BasePlotContainer -__all__ = ["OverlayPlotContainer", "HPlotContainer", "VPlotContainer", \ - "GridPlotContainer"] +__all__ = [ + "OverlayPlotContainer", + "HPlotContainer", + "VPlotContainer", + "GridPlotContainer", +] -DEFAULT_DRAWING_ORDER = ["background", "image", "underlay", "plot", - "selection", "border", "annotation", "overlay"] +DEFAULT_DRAWING_ORDER = [ + "background", + "image", + "underlay", + "plot", + "selection", + "border", + "annotation", + "overlay", +] # Enable constraints layout is only available if kiwisolver is installed! if ConstraintsContainer is not None: + class ConstraintsPlotContainer(ConstraintsContainer): - """ A Plot container that supports constraints-based layout - """ + """A Plot container that supports constraints-based layout""" + # !! Bits copied from BasePlotContainer !! container_under_layers = Tuple("background", "image", "underlay", "plot") draw_order = Instance(list, args=(DEFAULT_DRAWING_ORDER,)) - draw_layer = String('plot') + draw_layer = String("plot") # !! Bits copied from BasePlotContainer !! - __all__.append('ConstraintsPlotContainer') + __all__.append("ConstraintsPlotContainer") class OverlayPlotContainer(BasePlotContainer): @@ -53,15 +81,14 @@ class OverlayPlotContainer(BasePlotContainer): _cached_preferred_size = Tuple def get_preferred_size(self, components=None): - """ Returns the size (width,height) that is preferred for this component. + """Returns the size (width,height) that is preferred for this component. Overrides PlotComponent """ return simple_container_get_preferred_size(self, components=components) def _do_layout(self): - """ Actually performs a layout (called by do_layout()). - """ + """Actually performs a layout (called by do_layout()).""" simple_container_do_layout(self) @@ -85,7 +112,7 @@ class StackedPlotContainer(BasePlotContainer): stack_index = 0 def get_preferred_size(self, components=None): - """ Returns the size (width,height) that is preferred for this component. + """Returns the size (width,height) that is preferred for this component. Overrides PlotComponent. """ @@ -120,31 +147,35 @@ def get_preferred_size(self, components=None): if total_size >= self.spacing: total_size -= self.spacing - if (self.stack_dimension not in self.resizable) and \ - (self.stack_dimension not in self.fit_components): + if (self.stack_dimension not in self.resizable) and ( + self.stack_dimension not in self.fit_components + ): total_size = self.bounds[ndx] elif no_visible_components or (total_size == 0): total_size = self.default_size[ndx] - if (self.other_dimension not in self.resizable) and \ - (self.other_dimension not in self.fit_components): + if (self.other_dimension not in self.resizable) and ( + self.other_dimension not in self.fit_components + ): max_other_size = self.bounds[other_ndx] elif no_visible_components or (max_other_size == 0): max_other_size = self.default_size[other_ndx] if ndx == 0: - self._cached_preferred_size = (total_size + self.hpadding, - max_other_size + self.vpadding) + self._cached_preferred_size = ( + total_size + self.hpadding, + max_other_size + self.vpadding, + ) else: - self._cached_preferred_size = (max_other_size + self.hpadding, - total_size + self.vpadding) + self._cached_preferred_size = ( + max_other_size + self.hpadding, + total_size + self.vpadding, + ) return self._cached_preferred_size - def _do_stack_layout(self, components, align): - """ Helper method that does the actual work of layout. - """ + """Helper method that does the actual work of layout.""" size = list(self.bounds) if self.fit_components != "": @@ -208,8 +239,9 @@ def _do_stack_layout(self, components, align): bounds = new_bounds_dict.get(component, list(component.outer_bounds)) cur_pos += bounds[ndx] + self.spacing - if (bounds[other_ndx] > size[other_ndx]) or \ - (other_dim in component.resizable): + if (bounds[other_ndx] > size[other_ndx]) or ( + other_dim in component.resizable + ): # If the component is resizable in the other dimension or it exceeds the # container bounds, set it to the maximum size of the container @@ -232,8 +264,8 @@ def _do_stack_layout(self, components, align): # PICKLE FIXME: blocked with _pickles, but not sure that was correct. def __getstate__(self): - state = super(StackedPlotContainer,self).__getstate__() - for key in ['stack_dimension', 'other_dimension', 'stack_index']: + state = super(StackedPlotContainer, self).__getstate__() + for key in ["stack_dimension", "other_dimension", "stack_index"]: if key in state: del state[key] return state @@ -261,8 +293,7 @@ class HPlotContainer(StackedPlotContainer): _cached_preferred_size = Tuple def _do_layout(self): - """ Actually performs a layout (called by do_layout()). - """ + """Actually performs a layout (called by do_layout()).""" if self.stack_order == "left_to_right": components = self.components else: @@ -280,14 +311,13 @@ def _do_layout(self): ### Persistence ########################################################### def __getstate__(self): - state = super(HPlotContainer,self).__getstate__() - for key in ['_cached_preferred_size']: + state = super(HPlotContainer, self).__getstate__() + for key in ["_cached_preferred_size"]: if key in state: del state[key] return state - class VPlotContainer(StackedPlotContainer): """ A plot container that stacks plot components vertically. @@ -314,8 +344,7 @@ class VPlotContainer(StackedPlotContainer): spacing = Float(0.0) def _do_layout(self): - """ Actually performs a layout (called by do_layout()). - """ + """Actually performs a layout (called by do_layout()).""" if self.stack_order == "bottom_to_top": components = self.components else: @@ -331,7 +360,7 @@ def _do_layout(self): class GridPlotContainer(BasePlotContainer): - """ A GridPlotContainer consists of rows and columns in a tabular format. + """A GridPlotContainer consists of rows and columns in a tabular format. Each cell's width is the same as all other cells in its column, and each cell's height is the same as all other cells in its row. @@ -358,7 +387,7 @@ class GridPlotContainer(BasePlotContainer): #: specification. If there are fewer components than cells, the remaining #: cells are filled in with spaces. If there are more components than cells, #: the remainder wrap onto new rows as appropriate. - shape = Trait((0,0), Either(Tuple, List, Array)) + shape = Trait((0, 0), Either(Tuple, List, Array)) #: This property exposes the underlying grid structure of the container, #: and is the preferred way of setting and reading its contents. @@ -378,7 +407,7 @@ class GridPlotContainer(BasePlotContainer): _v_size_prefs = Any class SizePrefs(object): - """ Object to hold size preferences across spans in a particular + """Object to hold size preferences across spans in a particular dimension. For instance, if SizePrefs is being used for the row axis, then each element in the arrays below express sizing information about the corresponding column. @@ -405,8 +434,8 @@ class SizePrefs(object): index = Int(0) def __init__(self, length, direction): - """ Initializes this prefs object with empty arrays of the given - length and with the given direction. """ + """Initializes this prefs object with empty arrays of the given + length and with the given direction.""" self.fixed_lengths = zeros(length) self.resizable_lengths = zeros(length) self.direction = direction @@ -416,9 +445,9 @@ def __init__(self, length, direction): self.index = 1 def update_from_component(self, component, index): - """ Given a component at a particular index along this SizePref's + """Given a component at a particular index along this SizePref's axis, integrates the component's resizability and sizing information - into self.fixed_lengths and self.resizable_lengths. """ + into self.fixed_lengths and self.resizable_lengths.""" resizable = self.direction in component.resizable pref_size = component.get_preferred_size() self.update_from_pref_size(pref_size[self.index], index, resizable) @@ -435,7 +464,7 @@ def get_preferred_size(self): return amax((self.fixed_lengths, self.resizable_lengths), axis=0) def compute_size_array(self, size): - """ Given a length along the axis corresponding to this SizePref, + """Given a length along the axis corresponding to this SizePref, returns an array of lengths to assign each cell, taking into account resizability and preferred sizes. """ @@ -469,9 +498,10 @@ def compute_size_array(self, size): fixed_size = sum(fixed_lengths) fixed_length_indices = fixed_lengths > resizable_lengths resizable_indices = resizable_lengths > fixed_lengths - fully_resizable_indices = (resizable_lengths + fixed_lengths == 0) - preferred_size = sum(fixed_lengths[fixed_length_indices]) + \ - sum(resizable_lengths[~fixed_length_indices]) + fully_resizable_indices = resizable_lengths + fixed_lengths == 0 + preferred_size = sum(fixed_lengths[fixed_length_indices]) + sum( + resizable_lengths[~fixed_length_indices] + ) # Regardless of the relationship between available space and # resizable preferred sizes, columns/rows where the non-resizable @@ -503,14 +533,17 @@ def compute_size_array(self, size): # room for them and no fully resizable components to take up # the extra space, then we just scale the resizable components # up or down based on the amount of extra space available. - delta_lengths = resizable_lengths[resizable_indices] - \ - fixed_lengths[resizable_indices] + delta_lengths = ( + resizable_lengths[resizable_indices] + - fixed_lengths[resizable_indices] + ) desired_space = sum(delta_lengths) if desired_space > 0: - avail_space = size - sum(fixed_lengths) #[fixed_length_indices]) + avail_space = size - sum(fixed_lengths) # [fixed_length_indices]) scale = avail_space / desired_space - return_lengths[resizable_indices] = (fixed_lengths[resizable_indices] + \ - scale * delta_lengths).astype(int) + return_lengths[resizable_indices] = ( + fixed_lengths[resizable_indices] + scale * delta_lengths + ).astype(int) elif fully_resizable_indices.any(): # We have enough room to fit all the non-resizable components @@ -529,9 +562,8 @@ def compute_size_array(self, size): return return_lengths - def get_preferred_size(self, components=None): - """ Returns the size (width,height) that is preferred for this component. + """Returns the size (width,height) that is preferred for this component. Overrides PlotComponent. """ @@ -571,12 +603,13 @@ def get_preferred_size(self, components=None): spacing = zeros(2) else: spacing = array(self.spacing) - total_spacing = array(components.shape[::-1]) * spacing * 2 * (total_size>0) + total_spacing = array(components.shape[::-1]) * spacing * 2 * (total_size > 0) total_size += total_spacing for orientation, ndx in (("h", 0), ("v", 1)): - if (orientation not in self.resizable) and \ - (orientation not in self.fit_components): + if (orientation not in self.resizable) and ( + orientation not in self.fit_components + ): total_size[ndx] = self.outer_bounds[ndx] elif no_visible_components or (total_size[ndx] == 0): total_size[ndx] = self.default_size[ndx] @@ -608,7 +641,7 @@ def _do_layout(self): # the bounds and positions of all the components. shape = array(self._grid.shape).transpose() if self.spacing is None: - spacing = array([0,0]) + spacing = array([0, 0]) else: spacing = array(self.spacing) total_spacing = spacing * 2 * shape @@ -623,8 +656,12 @@ def _do_layout(self): # to be aligned in H and V. summed_widths = cumsum(hstack(([0], widths[:-1]))) summed_heights = cumsum(hstack(([0], heights[-1:0:-1]))) - h_positions = (2*(arange(self._grid.shape[1])+1) - 1) * spacing[0] + summed_widths - v_positions = (2*(arange(self._grid.shape[0])+1) - 1) * spacing[1] + summed_heights + h_positions = (2 * (arange(self._grid.shape[1]) + 1) - 1) * spacing[ + 0 + ] + summed_widths + v_positions = (2 * (arange(self._grid.shape[0]) + 1) - 1) * spacing[ + 1 + ] + summed_heights v_positions = v_positions[::-1] # Loop over all rows and columns, assigning position, setting bounds for @@ -655,7 +692,7 @@ def _do_layout(self): elif halign == "center": x += (w - component.outer_width) / 2 - component.outer_position = [x,y] + component.outer_position = [x, y] bounds = list(component.outer_bounds) if "h" in r: bounds[0] = w @@ -666,7 +703,7 @@ def _do_layout(self): component.do_layout() def _reflow_layout(self): - """ Re-computes self._grid based on self.components and self.shape. + """Re-computes self._grid based on self.components and self.shape. Adjusts self.shape accordingly. """ numcells = self.shape[0] * self.shape[1] @@ -675,7 +712,7 @@ def _reflow_layout(self): self.shape = (numrows, numcols) grid = array(self.components, dtype=object) grid.resize(self.shape) - grid[grid==0] = None + grid[grid == 0] = None self._grid = grid self._layout_needed = True diff --git a/chaco/plot_factory.py b/chaco/plot_factory.py index c3f73c4ce..889b82787 100644 --- a/chaco/plot_factory.py +++ b/chaco/plot_factory.py @@ -18,6 +18,7 @@ from .lineplot import LinePlot from .polar_line_renderer import PolarLineRenderer + def _create_data_sources(data, index_sort="none"): """ Returns datasources for index and value based on the inputs. Assumes that @@ -28,26 +29,41 @@ def _create_data_sources(data, index_sort="none"): if type(index) in (list, tuple, ndarray): index = ArrayDataSource(array(index), sort_order=index_sort) elif not isinstance(index, AbstractDataSource): - raise RuntimeError("Need an array or list of values or a DataSource, got %s instead." % type(index)) + raise RuntimeError( + "Need an array or list of values or a DataSource, got %s instead." + % type(index) + ) if type(value) in (list, tuple, ndarray): value = ArrayDataSource(array(value)) elif not isinstance(value, AbstractDataSource): - raise RuntimeError("Need an array or list of values or a DataSource, got %s instead." % type(index)) + raise RuntimeError( + "Need an array or list of values or a DataSource, got %s instead." + % type(index) + ) return index, value else: raise RuntimeError("Unable to create datasources.") -def create_scatter_plot(data=[], index_bounds=None, value_bounds=None, - orientation="h", color="green", marker="square", - marker_size=4, - bgcolor="transparent", outline_color="black", - border_visible=True, - add_grid=False, add_axis=False, - index_sort="none", **renderer_traits): - """ Creates a ScatterPlot renderer from a single Nx2 data array or a tuple +def create_scatter_plot( + data=[], + index_bounds=None, + value_bounds=None, + orientation="h", + color="green", + marker="square", + marker_size=4, + bgcolor="transparent", + outline_color="black", + border_visible=True, + add_grid=False, + add_axis=False, + index_sort="none", + **renderer_traits +): + """Creates a ScatterPlot renderer from a single Nx2 data array or a tuple of two length-N 1-D arrays. The data must be sorted on the index if any reverse-mapping tools are to be used. @@ -70,16 +86,20 @@ def create_scatter_plot(data=[], index_bounds=None, value_bounds=None, value_range.add(value) value_mapper = LinearMapper(range=value_range) - plot = ScatterPlot(index=index, value=value, - index_mapper=index_mapper, - value_mapper=value_mapper, - orientation=orientation, - marker=marker, - marker_size=marker_size, - color=color, - bgcolor=bgcolor, - outline_color=outline_color, - border_visible=border_visible, **renderer_traits) + plot = ScatterPlot( + index=index, + value=value, + index_mapper=index_mapper, + value_mapper=value_mapper, + orientation=orientation, + marker=marker, + marker_size=marker_size, + color=color, + bgcolor=bgcolor, + outline_color=outline_color, + border_visible=border_visible, + **renderer_traits + ) if add_grid: add_default_grids(plot, orientation) @@ -88,13 +108,23 @@ def create_scatter_plot(data=[], index_bounds=None, value_bounds=None, return plot -def create_line_plot(data=[], index_bounds=None, value_bounds=None, - orientation="h", color="red", width=1.0, - dash="solid", value_mapper_class=LinearMapper, - bgcolor="transparent", border_visible=False, - add_grid=False, add_axis=False, - index_sort="none", **renderer_traits): - """ Creates a LinePlot renderer from a single Nx2 data array or a tuple of +def create_line_plot( + data=[], + index_bounds=None, + value_bounds=None, + orientation="h", + color="red", + width=1.0, + dash="solid", + value_mapper_class=LinearMapper, + bgcolor="transparent", + border_visible=False, + add_grid=False, + add_axis=False, + index_sort="none", + **renderer_traits +): + """Creates a LinePlot renderer from a single Nx2 data array or a tuple of two length-N 1-D arrays. The data must be sorted on the index if any reverse-mapping tools are to be used. @@ -116,15 +146,19 @@ def create_line_plot(data=[], index_bounds=None, value_bounds=None, value_range.add(value) value_mapper = value_mapper_class(range=value_range) - plot = LinePlot(index=index, value=value, - index_mapper = index_mapper, - value_mapper = value_mapper, - orientation = orientation, - color = color, - bgcolor = bgcolor, - line_width = width, - line_style = dash, - border_visible=border_visible, **renderer_traits) + plot = LinePlot( + index=index, + value=value, + index_mapper=index_mapper, + value_mapper=value_mapper, + orientation=orientation, + color=color, + bgcolor=bgcolor, + line_width=width, + line_style=dash, + border_visible=border_visible, + **renderer_traits + ) if add_grid: add_default_grids(plot, orientation) @@ -133,15 +167,25 @@ def create_line_plot(data=[], index_bounds=None, value_bounds=None, return plot -def create_bar_plot(data=[], index_bounds=None, value_bounds=None, - orientation="h", color="red", bar_width=10.0, - value_mapper_class=LinearMapper, - line_color="black", - fill_color="red", line_width=1, - bgcolor="transparent", border_visible=False, - antialias=True, - add_grid=False, add_axis=False, **renderer_traits): - """ Creates a BarPlot renderer from a single Nx2 data array or a tuple of +def create_bar_plot( + data=[], + index_bounds=None, + value_bounds=None, + orientation="h", + color="red", + bar_width=10.0, + value_mapper_class=LinearMapper, + line_color="black", + fill_color="red", + line_width=1, + bgcolor="transparent", + border_visible=False, + antialias=True, + add_grid=False, + add_axis=False, + **renderer_traits +): + """Creates a BarPlot renderer from a single Nx2 data array or a tuple of two length-N 1-D arrays. The data must be sorted on the index if any reverse-mapping tools are to be used. @@ -164,16 +208,19 @@ def create_bar_plot(data=[], index_bounds=None, value_bounds=None, value_mapper = value_mapper_class(range=value_range) # Create the plot - plot = BarPlot(index=index, - value=value, - value_mapper=value_mapper, - index_mapper=index_mapper, - orientation=orientation, - line_color=line_color, - fill_color=fill_color, - line_width=line_width, - bar_width=bar_width, - antialias=antialias, **renderer_traits) + plot = BarPlot( + index=index, + value=value, + value_mapper=value_mapper, + index_mapper=index_mapper, + orientation=orientation, + line_color=line_color, + fill_color=fill_color, + line_width=line_width, + bar_width=bar_width, + antialias=antialias, + **renderer_traits + ) if add_grid: add_default_grids(plot, orientation) @@ -182,10 +229,17 @@ def create_bar_plot(data=[], index_bounds=None, value_bounds=None, return plot -def create_polar_plot(data, orientation='h', color='black', width=1.0, - dash="solid", grid="dot", value_mapper_class=PolarMapper, - **renderer_traits): - """ Creates a polar plot renderer from a single Nx2 data array or a tuple +def create_polar_plot( + data, + orientation="h", + color="black", + width=1.0, + dash="solid", + grid="dot", + value_mapper_class=PolarMapper, + **renderer_traits +): + """Creates a polar plot renderer from a single Nx2 data array or a tuple of two length-N 1-D arrays. The data must be sorted on the index if any reverse-mapping tools are to be used. @@ -195,10 +249,10 @@ def create_polar_plot(data, orientation='h', color='black', width=1.0, data = transpose(array(data)) r_data, t_data = transpose(data) - index_data= r_data*cos(t_data) - value_data= r_data*sin(t_data) + index_data = r_data * cos(t_data) + value_data = r_data * sin(t_data) - index = ArrayDataSource(index_data, sort_order='ascending') + index = ArrayDataSource(index_data, sort_order="ascending") # Typically the value data is unsorted value = ArrayDataSource(value_data) @@ -210,20 +264,25 @@ def create_polar_plot(data, orientation='h', color='black', width=1.0, value_range.add(value) value_mapper = value_mapper_class(range=value_range) - plot = PolarLineRenderer(index=index, value=value, - index_mapper = index_mapper, - value_mapper = value_mapper, - orientation = orientation, - color = color, - line_width = width, - line_style = dash, - grid_style = grid, **renderer_traits) + plot = PolarLineRenderer( + index=index, + value=value, + index_mapper=index_mapper, + value_mapper=value_mapper, + orientation=orientation, + color=color, + line_width=width, + line_style=dash, + grid_style=grid, + **renderer_traits + ) return plot -def add_default_axes(plot, orientation="normal", vtitle="", htitle="", - axis_class=PlotAxis): +def add_default_axes( + plot, orientation="normal", vtitle="", htitle="", axis_class=PlotAxis +): """ Creates left and bottom axes for a plot. Assumes that the index is horizontal and value is vertical by default; set *orientation* to @@ -236,15 +295,11 @@ def add_default_axes(plot, orientation="normal", vtitle="", htitle="", v_mapper = plot.index_mapper h_mapper = plot.value_mapper - left = axis_class(orientation='left', - title= vtitle, - mapper=v_mapper, - component=plot) + left = axis_class(orientation="left", title=vtitle, mapper=v_mapper, component=plot) - bottom = axis_class(orientation='bottom', - title= htitle, - mapper=h_mapper, - component=plot) + bottom = axis_class( + orientation="bottom", title=htitle, mapper=h_mapper, component=plot + ) plot.underlays.append(left) plot.underlays.append(bottom) @@ -264,13 +319,21 @@ def add_default_grids(plot, orientation="normal"): v_mapper = plot.value_mapper h_mapper = plot.index_mapper - vgrid = PlotGrid(mapper=v_mapper, orientation='vertical', - component=plot, - line_color="lightgray", line_style="dot") - - hgrid = PlotGrid(mapper=h_mapper, orientation='horizontal', - component=plot, - line_color="lightgray", line_style="dot") + vgrid = PlotGrid( + mapper=v_mapper, + orientation="vertical", + component=plot, + line_color="lightgray", + line_style="dot", + ) + + hgrid = PlotGrid( + mapper=h_mapper, + orientation="horizontal", + component=plot, + line_color="lightgray", + line_style="dot", + ) plot.underlays.append(vgrid) plot.underlays.append(hgrid) diff --git a/chaco/plot_graphics_context.py b/chaco/plot_graphics_context.py index 9a55118d1..a90e2b3b9 100644 --- a/chaco/plot_graphics_context.py +++ b/chaco/plot_graphics_context.py @@ -2,12 +2,12 @@ """ - from enable.kiva_graphics_context import GraphicsContext + class PlotGraphicsContextMixin(object): - """ A Kiva graphics context, which facilitates rendering plots and plot + """A Kiva graphics context, which facilitates rendering plots and plot components into an offscreen or memory buffer. Its only real difference from a Kiva graphics context is that this @@ -16,20 +16,21 @@ class correctly offsets the coordinate frame by (0.5, 0.5) and increases into on-screen windows through Enable, this transformation step is handled by Enable. """ + # FIXME: Right now this does not resize correctly. (But you shouldn't # resize your GC, anyway!) def __init__(self, size_or_ary, *args, **kw): - scale = kw.pop('dpi', 72.0) / 72.0 + scale = kw.pop("dpi", 72.0) / 72.0 if type(size_or_ary) in (list, tuple) and len(size_or_ary) == 2: - size_or_ary = (size_or_ary[0]*scale + 1, size_or_ary[1]*scale + 1) + size_or_ary = (size_or_ary[0] * scale + 1, size_or_ary[1] * scale + 1) super(PlotGraphicsContextMixin, self).__init__(size_or_ary, *args, **kw) self.translate_ctm(0.5, 0.5) self.scale_ctm(scale, scale) def render_component(self, component, container_coords=False): - """ Renders the given component. + """Renders the given component. Parameters ---------- @@ -57,13 +58,15 @@ def render_component(self, component, container_coords=False): component.draw(self, view_bounds=(0, 0, self.width(), self.height())) def clip_to_rect(self, x, y, width, height): - """ Offsets the coordinate frame by (0.5, 0.5) and increases the actual + """Offsets the coordinate frame by (0.5, 0.5) and increases the actual size of the image by 1 pixel in each dimension. Overrides Kiva GraphicsContext. """ - super(PlotGraphicsContextMixin, self).clip_to_rect(x-0.5, y-0.5, width+1, height+1) + super(PlotGraphicsContextMixin, self).clip_to_rect( + x - 0.5, y - 0.5, width + 1, height + 1 + ) + class PlotGraphicsContext(PlotGraphicsContextMixin, GraphicsContext): pass - diff --git a/chaco/plot_label.py b/chaco/plot_label.py index 8d1da0d80..736ed7ea3 100644 --- a/chaco/plot_label.py +++ b/chaco/plot_label.py @@ -2,7 +2,6 @@ """ - from enable.font_metrics_provider import font_metrics_provider from traits.api import DelegatesTo, Enum, Instance, Str, Trait @@ -12,8 +11,9 @@ LabelDelegate = DelegatesTo("_label") + class PlotLabel(AbstractOverlay): - """ A label used by plots. + """A label used by plots. This class wraps a simple Label instance, and delegates some traits to it. """ @@ -34,9 +34,9 @@ class PlotLabel(AbstractOverlay): margin = LabelDelegate line_spacing = LabelDelegate - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Layout-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Horizontal justification used if the label has more horizontal space #: than it needs. @@ -58,15 +58,15 @@ class PlotLabel(AbstractOverlay): # Should this PlotLabel modify the padding on its underlying component # if there is not enough room to lay out the text? # FIXME: This could cause cycles in layout, so not implemented for now - #modify_component = Bool(True) + # modify_component = Bool(True) #: By default, this acts like a component and will render on the main #: "plot" layer unless its **component** attribute gets set. draw_layer = "plot" - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The label has a fixed height and can be resized horizontally. (Overrides #: PlotComponent.) @@ -75,20 +75,19 @@ class PlotLabel(AbstractOverlay): # The Label instance this plot label is wrapping. _label = Instance(Label, args=()) - def __init__(self, text="", *args, **kw): super(PlotLabel, self).__init__(*args, **kw) self.text = text def overlay(self, component, gc, view_bounds=None, mode="normal"): - """ Draws this label overlaid on another component. + """Draws this label overlaid on another component. Overrides AbstractOverlay. """ self._draw_overlay(gc, view_bounds, mode) def get_preferred_size(self): - """ Returns the label's preferred size. + """Returns the label's preferred size. Overrides PlotComponent. """ @@ -97,7 +96,7 @@ def get_preferred_size(self): return size def do_layout(self): - """ Tells this component to do layout. + """Tells this component to do layout. Overrides PlotComponent. """ @@ -107,7 +106,7 @@ def do_layout(self): self._layout_as_component() def _draw_overlay(self, gc, view_bounds=None, mode="normal"): - """ Draws the overlay layer of a component. + """Draws the overlay layer of a component. Overrides PlotComponent. """ @@ -130,7 +129,7 @@ def _draw_overlay(self, gc, view_bounds=None, mode="normal"): with gc: # XXX: Uncomment this after we fix kiva GL backend's clip stack - #gc.clip_to_rect(self.x, self.y, self.width, self.height) + # gc.clip_to_rect(self.x, self.y, self.width, self.height) # We have to translate to our position because the label # tries to draw at (0,0). @@ -147,8 +146,7 @@ def _layout_as_component(self, size=None, force=False): pass def _layout_as_overlay(self, size=None, force=False): - """ Lays out the label as an overlay on another component. - """ + """Lays out the label as an overlay on another component.""" if self.component is not None: orientation = self.overlay_position outside = True diff --git a/chaco/plot_template.py b/chaco/plot_template.py index d830799c4..560d3d45b 100644 --- a/chaco/plot_template.py +++ b/chaco/plot_template.py @@ -19,7 +19,6 @@ from traits.api import Bool, Dict, HasTraits, Instance, Str - def bind_template(template, vars, type_check=False): """ A convenience method for binding a plot template to set of variables. @@ -39,14 +38,13 @@ def bind_template(template, vars, type_check=False): class PlotTemplateException(Exception): - """ Raised for errors in plot templates. - """ + """Raised for errors in plot templates.""" + pass class TemplateDescriptor(HasTraits): - """ Describes the names and types of template variables for a template. - """ + """Describes the names and types of template variables for a template.""" # A dict with the template variable names as keys. If the template is # unbound, the values are string representations of the types of objects @@ -56,29 +54,29 @@ class TemplateDescriptor(HasTraits): vars = Dict - - class Templatizable(HasTraits): - """ Mix-in class that makes objects capable of being incorporated + """Mix-in class that makes objects capable of being incorporated into a Chaco template. Primarily defines the protocol used to query the class for its contents. """ - def templatize(self, my_name, ): - """ Returns a dict mapping the name of the child in the local name space + def templatize( + self, + my_name, + ): + """Returns a dict mapping the name of the child in the local name space to a Templatizable object reference. """ raise NotImplementedError def __gettemplate__(self): - """ Returns a templatized version of the object. - """ + """Returns a templatized version of the object.""" -# def bind(self, + # def bind(self, def rebind(self, obj): - """ Replaces this object with the state in peer object *obj*. + """Replaces this object with the state in peer object *obj*. This method allows PlotTemplates to be used as live, application-level templates and not merely as a means to generating a plot script. @@ -92,27 +90,25 @@ def rebind(self, obj): class PlotTemplate(HasTraits): - """ Abstract base class for plot templates. - """ - pass - + """Abstract base class for plot templates.""" + pass class AbstractTemplatizer(HasTraits): - """ A Templatizer accepts any subclass of Templatizable and returns a + """A Templatizer accepts any subclass of Templatizable and returns a PlotTemplate. """ - class CodeMetadata(HasTraits): - """ Represents all the metadata about a plot template, to be stored into + """Represents all the metadata about a plot template, to be stored into the generated code. The generated code for a plot template must create one of these objects, which is then used to drive the loading of the rest of the template. """ + # Not used for now, but could be handled later. version = "1.0" @@ -130,33 +126,33 @@ class CodeMetadata(HasTraits): # this for aesthetic or readability reasons. root_name = Str + class CodeTemplate(PlotTemplate): - """ A Chaco plot template. + """A Chaco plot template. Because Chaco plot templates are just executable code that produces Chaco plots, the PlotTemplate class is used to manage, interact with, and inspect the code for the template. """ - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Configuration and general state of the template - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Is the template completely bound? is_bound = Bool(False) - - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Object graph traits - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # The top-level Templatizable component in the plot. root = Instance(Templatizable) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Code-related traits # These are used during the actual code generation process. - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Global variables used during the code generation process. code_globals = Dict @@ -164,22 +160,21 @@ class CodeTemplate(PlotTemplate): code_imports = Dict def create_strings(self): - """ Returns a list of strings which can be passed to bind_template(). - """ + """Returns a list of strings which can be passed to bind_template().""" # TODO: do we need this?? can we do live generation?!!! pass def load_from_strings(self, stringlist): - """ Fills this plot template with the template in *stringlist*. + """Fills this plot template with the template in *stringlist*. NOTE: Don't use this to bind a template to data! There is a much easier way to do that: use the bind_template() function. """ pass - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Private methods - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- def _write_metadata(self): """ @@ -188,27 +183,30 @@ def _write_metadata(self): """ pass - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Methods used by Templatizable objects to query the generator about the # state of code generation. - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- def create_global(self, name_hint): - """ Requests that a new global symbol be allocated with the given name. + """Requests that a new global symbol be allocated with the given name. Returns the actual name that was created. """ pass - def create_import(self, import_line, ): - """ Adds another import line, verbatim, to the top of the output code. + def create_import( + self, + import_line, + ): + """Adds another import line, verbatim, to the top of the output code. No order of imports is guaranteed. """ pass def create_template_var(self, name_hint): - """ Creates a new variable for parameterizing the template. + """Creates a new variable for parameterizing the template. Returns a string that represents the special token to be used in the output code to signal where the template value can be bound. @@ -216,7 +214,7 @@ def create_template_var(self, name_hint): pass def create_function(self, name_hint): - """ Requests that a new function be allocated with the given name. + """Requests that a new function be allocated with the given name. Returns the actual name that was created. """ diff --git a/chaco/plotscrollbar.py b/chaco/plotscrollbar.py index d434af987..34cc70415 100644 --- a/chaco/plotscrollbar.py +++ b/chaco/plotscrollbar.py @@ -1,9 +1,8 @@ - - from traits.api import Any, Enum, Int, Property, Trait from enable.api import NativeScrollBar + class PlotScrollBar(NativeScrollBar): """ A ScrollBar that can be wired up to anything with an xrange or yrange @@ -21,9 +20,9 @@ class PlotScrollBar(NativeScrollBar): # mapper on **plot** that corresponds to **axis**. mapper = Property - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The value of the override plot to use, if any. If None, then uses # self.component. @@ -36,13 +35,12 @@ class PlotScrollBar(NativeScrollBar): # Stores the index (0 or 1) corresponding to self.axis _axis_index = Trait(None, None, Int) - - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Public methods - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def force_data_update(self): - """ This forces the scrollbar to recompute its range bounds. This + """This forces the scrollbar to recompute its range bounds. This should be used if datasources are changed out on the range, or if the data ranges on existing datasources of the range are changed. """ @@ -70,9 +68,9 @@ def _get_abs_coords(self, x, y): else: return self.component.get_absolute_coords(x, y) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Scrollbar - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _handle_dataspace_update(self): # This method reponds to changes from the dataspace side, e.g. @@ -80,8 +78,9 @@ def _handle_dataspace_update(self): # Get the current datasource bounds range = self.mapper.range - bounds_list = [source.get_bounds() for source in range.sources \ - if source.get_size() > 0] + bounds_list = [ + source.get_bounds() for source in range.sources if source.get_size() > 0 + ] mins, maxes = zip(*bounds_list) dmin = min(mins) dmax = max(maxes) @@ -95,14 +94,16 @@ def _handle_dataspace_update(self): # Compute the size available for the scrollbar to scroll in scrollrange = (totalmax - totalmin) - view - if round(scrollrange/20.0) > 0.0: - ticksize = scrollrange / round(scrollrange/20.0) + if round(scrollrange / 20.0) > 0.0: + ticksize = scrollrange / round(scrollrange / 20.0) else: ticksize = 1 foo = (totalmin, totalmax, view, ticksize) print("scrollrange:", foo) - self.trait_setq(range = foo, - scroll_position = max(min(self.scroll_position, totalmax-view), totalmin)) + self.trait_setq( + range=foo, + scroll_position=max(min(self.scroll_position, totalmax - view), totalmin), + ) self._scroll_updated = True self.request_redraw() @@ -115,9 +116,9 @@ def _scroll_position_changed(self): new_scroll_pos = self.scroll_position range.set_bounds(new_scroll_pos, new_scroll_pos + view_width) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Event listeners - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _component_changed(self, old, new): # Check to see if we're currently overriding the value of self.component @@ -145,13 +146,11 @@ def __plot_changed(self, old, new): def _modify_plot_listeners(self, plot, action="attach"): if action == "attach": - remove=False + remove = False else: - remove=True - plot.observe(self._component_bounds_handler, - "bounds.items", remove=remove) - plot.observe(self._component_pos_handler, - "position.items", remove=remove) + remove = True + plot.observe(self._component_bounds_handler, "bounds.items", remove=remove) + plot.observe(self._component_pos_handler, "position.items", remove=remove) def _component_bounds_handler(self, event): self._handle_dataspace_update() @@ -162,15 +161,15 @@ def _component_pos_handler(self, event): self._widget_moved = True def _update_mapper_listeners(self): - #if self._mapper + # if self._mapper pass def _handle_mapper_updated(self): self._handle_dataspace_update() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property getter/setters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_plot(self): if self._plot is not None: @@ -199,22 +198,22 @@ def _get_axis_index(self): def _set_axis_index(self, val): self._axis_index = val - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_axis_coord(self, event, axis="index"): - """ Returns the coordinate of the event along the axis of interest + """Returns the coordinate of the event along the axis of interest to this tool (or along the orthogonal axis, if axis="value"). """ event_pos = (event.x, event.y) if axis == "index": - return event_pos[ self.axis_index ] + return event_pos[self.axis_index] else: - return event_pos[ 1 - self.axis_index ] + return event_pos[1 - self.axis_index] def _determine_axis(self): - """ Determines whether the index of the coordinate along this tool's + """Determines whether the index of the coordinate along this tool's axis of interest is the first or second element of an (x,y) coordinate tuple. @@ -226,7 +225,7 @@ def _determine_axis(self): return 0 else: return 1 - else: # self.axis == "value" + else: # self.axis == "value" if self.plot.orientation == "h": return 1 else: diff --git a/chaco/plugin/chaco_plugin.py b/chaco/plugin/chaco_plugin.py index 02845532a..3af765b04 100644 --- a/chaco/plugin/chaco_plugin.py +++ b/chaco/plugin/chaco_plugin.py @@ -5,22 +5,20 @@ from traits.api import List -ID = 'chaco' -ICHACO_SESSION = ID + '.plugin.session_service.SessionService' +ID = "chaco" +ICHACO_SESSION = ID + ".plugin.session_service.SessionService" class ChacoPlugin(Plugin): - """ Envisage 3 plugin for Chaco functionality. - """ + """Envisage 3 plugin for Chaco functionality.""" id = ID - name = 'Chaco plugin' + name = "Chaco plugin" #### Contributions to extension points made by this plugin ################# # Extension point Ids. - COMMANDS = 'envisage.plugins.python_shell.commands' - + COMMANDS = "envisage.plugins.python_shell.commands" contributed_commands = List(contributes_to=COMMANDS) @@ -33,17 +31,17 @@ def _contributed_commands_default(self): #### Plugin interface ###################################################### def start(self): - """ Monkeypatch the Chaco shell subsystem. - """ + """Monkeypatch the Chaco shell subsystem.""" from chaco import shell from chaco.shell import commands from chaco.plugin.workbench_session import WorkbenchSession commands.session = shell.session = WorkbenchSession( - application=self.application) + application=self.application + ) def show(): - """ Shows all the figure windows that have been created thus far, and + """Shows all the figure windows that have been created thus far, and creates a GUI main loop. This function is useful in scripts to show plots and keep their windows open, and has no effect when used from the interpreter prompt. @@ -54,4 +52,3 @@ def show(): win.raise_window() commands.show = show - diff --git a/chaco/plugin/plot_editor.py b/chaco/plugin/plot_editor.py index be78bd5c3..aa751f1a1 100644 --- a/chaco/plugin/plot_editor.py +++ b/chaco/plugin/plot_editor.py @@ -6,26 +6,22 @@ class PlotUI(HasTraits): - """ Simple Traits UI proxy for a Chaco plot. - """ + """Simple Traits UI proxy for a Chaco plot.""" # The plot. component = Any() traits_view = tui.View( - tui.Item('component', editor=ComponentEditor(), show_label=False), - + tui.Item("component", editor=ComponentEditor(), show_label=False), resizable=True, ) class PlotEditor(TraitsUIEditor): - """ A Workbench Editor showing a Chaco plot for the shell interface. - """ + """A Workbench Editor showing a Chaco plot for the shell interface.""" - bgcolor = Str('white') - image_default_origin = Enum("bottom left", "top left", - "bottom right", "top right") + bgcolor = Str("white") + image_default_origin = Enum("bottom left", "top left", "bottom right", "top right") # The plot. component = Property(Any) @@ -38,8 +34,14 @@ class PlotEditor(TraitsUIEditor): # to notify it of our being closed, etc. session = Any() - def __init__(self, is_image=False, bgcolor="white", - image_default_origin="top left", *args, **kw): + def __init__( + self, + is_image=False, + bgcolor="white", + image_default_origin="top left", + *args, + **kw + ): super(TraitsUIEditor, self).__init__(**kw) @@ -55,7 +57,6 @@ def __init__(self, is_image=False, bgcolor="white", self.obj = PlotUI(component=top_container) - #### PlotWindow interface ################################################## def get_container(self): @@ -71,7 +72,7 @@ def iconize(self, iconize): """ def maximize(self, maximize): - """ If *maximize* is True, maximizes the window size; restores if False. + """If *maximize* is True, maximizes the window size; restores if False. Do nothing in this implementation. """ @@ -85,16 +86,13 @@ def set_title(self, title): def raise_window(self): self.window.activate_editor(self) - #### Editor interface ###################################################### def destroy_control(self): - """ Destroy the toolkit-specific control that represents the part. - """ + """Destroy the toolkit-specific control that represents the part.""" self._on_window_close() super(TraitsUIEditor, self).destroy_control() - #### Private interface ##################################################### def _get_container(self): @@ -135,4 +133,3 @@ def _on_window_close(self): self.session.del_window(ndx) except ValueError: pass - diff --git a/chaco/plugin/workbench_session.py b/chaco/plugin/workbench_session.py index aa5546c41..905d686e2 100644 --- a/chaco/plugin/workbench_session.py +++ b/chaco/plugin/workbench_session.py @@ -9,7 +9,7 @@ class WorkbenchSession(PlotSession): - """ A Chaco Shell PlotSession which raises Workbench Editors instead of + """A Chaco Shell PlotSession which raises Workbench Editors instead of free-standing windows. """ @@ -27,7 +27,8 @@ def new_window(self, name=None, title=None, is_image=False): for the new window. """ workbench = self.application.get_service( - 'envisage.ui.workbench.workbench.Workbench') + "envisage.ui.workbench.workbench.Workbench" + ) new_win = PlotEditor( is_image=is_image, size=(self.prefs.window_width, self.prefs.window_height), @@ -52,6 +53,4 @@ def new_window(self, name=None, title=None, is_image=False): workbench.edit(new_win.obj, kind=lambda *args, **kwds: new_win) - return len(self.windows)-1 - - + return len(self.windows) - 1 diff --git a/chaco/point_data_source.py b/chaco/point_data_source.py index 6aa1beea2..de5d00594 100644 --- a/chaco/point_data_source.py +++ b/chaco/point_data_source.py @@ -14,7 +14,7 @@ class PointDataSource(ArrayDataSource): - """ A data source representing a (possibly unordered) set of (X,Y) points. + """A data source representing a (possibly unordered) set of (X,Y) points. This is internally always represented by an Nx2 array, so that data[i] refers to a single point (represented as a length-2 array). @@ -25,14 +25,13 @@ class PointDataSource(ArrayDataSource): """ - #: The dimensionality of the indices into this data source (overrides #: ArrayDataSource). - index_dimension = ReadOnly('scalar') + index_dimension = ReadOnly("scalar") #: The dimensionality of the value at each index point (overrides #: ArrayDataSource). - value_dimension = ReadOnly('point') + value_dimension = ReadOnly("point") #: The sort order of the data. Although sort order is less common with point #: data, it can be useful in case where the value data is sorted along some @@ -47,10 +46,9 @@ class PointDataSource(ArrayDataSource): #: whichever one has the best binary-search performance for hit-testing. sort_index = Enum(0, 1) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The actual data (overrides ArrayDataSource). _data = PointTrait @@ -66,18 +64,22 @@ class PointDataSource(ArrayDataSource): # List of Y positions. _ydata = Property - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractDataSource interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ - def __init__(self, data = transpose(array([[],[]])), **kw): + def __init__(self, data=transpose(array([[], []])), **kw): shape = data.shape if (len(shape) != 2) or (shape[1] != 2): - raise RuntimeError("PointDataSource constructor requires Nx2 array, but got array of shape " + str(shape) + " instead.") + raise RuntimeError( + "PointDataSource constructor requires Nx2 array, but got array of shape " + + str(shape) + + " instead." + ) super(PointDataSource, self).__init__(data, **kw) def get_data(self): - """ Returns the data for this data source, or (0.0, 0.0) if it has no + """Returns the data for this data source, or (0.0, 0.0) if it has no data. Overrides ArryDataSource. @@ -116,49 +118,49 @@ def reverse_map(self, pt, index=0, outside_returns_none=True): raise ValueError("Index must be 0 or 1.") # This basically reduces to a scalar data search along self.data[index]. - lowerleft, upperright= self._cached_bounds + lowerleft, upperright = self._cached_bounds min_val = lowerleft[index] max_val = upperright[index] val = pt[index] - if (val < min_val): + if val < min_val: if outside_returns_none: return None else: return self._min_index - elif (val > max_val): + elif val > max_val: if outside_returns_none: return None else: return self._max_index else: - return reverse_map_1d(self._data[:,index], val, self.sort_order) + return reverse_map_1d(self._data[:, index], val, self.sort_order) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _compute_bounds(self): - """ Computes the minimum and maximum values of self._data. + """Computes the minimum and maximum values of self._data. Overrides ArrayDataSource. """ if len(self._data) == 0: - self._cached_bounds = ((0.0,0.0), (0.0,0.0)) + self._cached_bounds = ((0.0, 0.0), (0.0, 0.0)) elif len(self._data) == 1: - x,y = self._data[0] - self._cached_bounds = ((x,y), (x,y)) + x, y = self._data[0] + self._cached_bounds = ((x, y), (x, y)) else: # calculate the X and Y values independently - x = self._data[:,0] + x = self._data[:, 0] min_x = min(x) max_x = max(x) - y = self._data[:,1] + y = self._data[:, 1] min_y = min(y) max_y = max(y) - self._cached_bounds = ((min_x,min_y), (max_x,max_y)) + self._cached_bounds = ((min_x, min_y), (max_x, max_y)) def _get__xdata(self): - return ArrayDataSource(self._data[:,0]) + return ArrayDataSource(self._data[:, 0]) def _get__ydata(self): - return ArrayDataSource(self._data[:,1]) + return ArrayDataSource(self._data[:, 1]) diff --git a/chaco/polar_line_renderer.py b/chaco/polar_line_renderer.py index 9209f85e0..5cf06ee15 100644 --- a/chaco/polar_line_renderer.py +++ b/chaco/polar_line_renderer.py @@ -2,7 +2,6 @@ """ - # Major library imports from numpy import array, cos, pi, sin, transpose @@ -15,23 +14,23 @@ class PolarLineRenderer(AbstractPlotRenderer): - """ A renderer for polar line plots. - """ - #------------------------------------------------------------------------ + """A renderer for polar line plots.""" + + # ------------------------------------------------------------------------ # Appearance-related traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The color of the origin axis. - origin_axis_color_ = (0,0,0,1) + origin_axis_color_ = (0, 0, 0, 1) # The width of the origin axis. origin_axis_width = 2.0 # The origin axis is visible. - origin_axis_visible=True + origin_axis_visible = True # The grid is visible. - grid_visible= True + grid_visible = True # The orientation of the plot is horizontal; for any other value, it is # transposed - orientation = 'h' + orientation = "h" # The color of the line. color = black_color_trait # The width of the line. @@ -39,7 +38,7 @@ class PolarLineRenderer(AbstractPlotRenderer): # The style of the line. line_style = LineStyle("solid") # The style of the grid lines. - grid_style= LineStyle("dot") + grid_style = LineStyle("dot") def _gather_points(self): """ @@ -50,11 +49,11 @@ def _gather_points(self): x = self.index.get_data() y = self.value.get_data() - rad= min(self.width/2.0,self.height/2.0) - sx = x*rad+ self.x + self.width/2.0 - sy = y*rad+ self.y + self.height/2.0 + rad = min(self.width / 2.0, self.height / 2.0) + sx = x * rad + self.x + self.width / 2.0 + sy = y * rad + self.y + self.height / 2.0 - points = transpose(array((sx,sy))) + points = transpose(array((sx, sy))) self._cached_data_pts = points self._cache_valid = True @@ -62,17 +61,16 @@ def _data_changed(self): self._cache_valid = False def _update_mappers(self): - #Dunno if there is anything else to do here + # Dunno if there is anything else to do here self._cache_valid = False def _render(self, gc, points): - """ Actually draw the plot. - """ + """Actually draw the plot.""" with gc: gc.set_antialias(True) self._draw_default_axes(gc) self._draw_default_grid(gc) - if len(points)>0: + if len(points) > 0: gc.clip_to_rect(self.x, self.y, self.width, self.height) gc.set_stroke_color(self.color_) gc.set_line_width(self.line_width) @@ -83,7 +81,7 @@ def _render(self, gc, points): gc.stroke_path() def map_screen(self, data_array): - """ Maps an array of data points into screen space and returns it as + """Maps an array of data points into screen space and returns it as an array. Implements the AbstractPlotRenderer interface. @@ -101,37 +99,32 @@ def map_screen(self, data_array): sx = self.index_mapper.map_screen(x_ary) sy = self.value_mapper.map_screen(y_ary) - if self.orientation == 'h': + if self.orientation == "h": return transpose(array((sx, sy))) else: return transpose(array((sy, sx))) def map_data(self, screen_pt): - """ Maps a screen space point into the "index" space of the plot. + """Maps a screen space point into the "index" space of the plot. Implements the AbstractPlotRenderer interface. """ - if self.orientation == 'h': + if self.orientation == "h": x, y = screen_pt else: - y,x = screen_pt - return array((self.index_mapper.map_data(x), - self.value_mapper.map_data(y))) - + y, x = screen_pt + return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) def _downsample(self): return self.map_screen(self._cached_data_pts) def _draw_plot(self, *args, **kw): - """ Draws the 'plot' layer. - """ + """Draws the 'plot' layer.""" # Simple compatibility with new-style rendering loop return self._draw_component(*args, **kw) - - def _draw_component(self, gc, view_bounds=None, mode='normal'): - """ Renders the component. - """ + def _draw_component(self, gc, view_bounds=None, mode="normal"): + """Renders the component.""" self._gather_points() self._render(gc, self._cached_data_pts) @@ -151,21 +144,21 @@ def _draw_default_axes(self, gc): gc.set_stroke_color(self.origin_axis_color_) gc.set_line_width(self.origin_axis_width) gc.set_line_dash(self.grid_style_) - x_data,y_data= transpose(self._cached_data_pts) - x_center=self.x + self.width/2.0 - y_center=self.y + self.height/2.0 + x_data, y_data = transpose(self._cached_data_pts) + x_center = self.x + self.width / 2.0 + y_center = self.y + self.height / 2.0 for theta in range(12): - r= min(self.width/2.0,self.height/2.0) - x= r*cos(theta*pi/6) + x_center - y= r*sin(theta*pi/6) + y_center - data_pts= array([[x_center,y_center],[x,y]]) - start,end = data_pts - gc.move_to(int(start[0]), int(start[1])) - gc.line_to(int(end[0]), int(end[1])) - gc.stroke_path() - - def _draw_default_grid(self,gc): + r = min(self.width / 2.0, self.height / 2.0) + x = r * cos(theta * pi / 6) + x_center + y = r * sin(theta * pi / 6) + y_center + data_pts = array([[x_center, y_center], [x, y]]) + start, end = data_pts + gc.move_to(int(start[0]), int(start[1])) + gc.line_to(int(end[0]), int(end[1])) + gc.stroke_path() + + def _draw_default_grid(self, gc): if not self.grid_visible: return @@ -173,11 +166,11 @@ def _draw_default_grid(self,gc): gc.set_stroke_color(self.origin_axis_color_) gc.set_line_width(self.origin_axis_width) gc.set_line_dash(self.grid_style_) - x_data,y_data = transpose(self._cached_data_pts) - x_center = self.x + self.width/2.0 - y_center = self.y + self.height/2.0 - rad = min(self.width/2.0, self.height/2.0) - for r_part in range(1,5): - r = rad*r_part/4 - gc.arc(x_center, y_center, r, 0, 2*pi) + x_data, y_data = transpose(self._cached_data_pts) + x_center = self.x + self.width / 2.0 + y_center = self.y + self.height / 2.0 + rad = min(self.width / 2.0, self.height / 2.0) + for r_part in range(1, 5): + r = rad * r_part / 4 + gc.arc(x_center, y_center, r, 0, 2 * pi) gc.stroke_path() diff --git a/chaco/polar_mapper.py b/chaco/polar_mapper.py index a8362c3a8..afb0a531c 100644 --- a/chaco/polar_mapper.py +++ b/chaco/polar_mapper.py @@ -24,21 +24,21 @@ class PolarMapper(AbstractMapper): "flip" the screen space orientation, swap the values for **low_pos** and **high_pos**. """ - #------------------------------------------------------------------------ - # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ + # Private traits + # ------------------------------------------------------------------------ - _scale = Float(1.0) # number of screen space units per data space unit + _scale = Float(1.0) # number of screen space units per data space unit _null_screen_range = Bool(False) _null_data_range = Bool(False) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def map_screen(self, data_array): - """ map_screen(data_array) -> screen_array + """map_screen(data_array) -> screen_array Converts radius and theta values from *data_array* to x and y values and then maps @@ -51,7 +51,7 @@ def map_screen(self, data_array): return (data_array - self.range.low) * self._scale + self.low_pos def map_data(self, screen_val): - """ map_data(screen_val) -> data_val + """map_data(screen_val) -> data_val Maps values from screen space into data space. """ @@ -61,9 +61,9 @@ def map_data(self, screen_val): else: return (screen_val - self.low_pos) / self._scale + self.range.low - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _compute_scale(self): if self._cache_valid: diff --git a/chaco/polygon_plot.py b/chaco/polygon_plot.py index f4495f1ba..39d1c2173 100644 --- a/chaco/polygon_plot.py +++ b/chaco/polygon_plot.py @@ -2,21 +2,20 @@ """ - # Major library imports import numpy as np # Enthought library imports. -from enable.api import LineStyle, black_color_trait, \ - transparent_color_trait +from enable.api import LineStyle, black_color_trait, transparent_color_trait from kiva.api import points_in_polygon from traits.api import Enum, Float, Tuple, Property, cached_property, observe # Local imports. from .base_xy_plot import BaseXYPlot + class PolygonPlot(BaseXYPlot): - """ Plots a polygon in dataspace. + """Plots a polygon in dataspace. Assuming that the index and value mappers are linear mappers, and that "index" corresponds to X-coordinates and "value" corresponds to @@ -54,19 +53,19 @@ class PolygonPlot(BaseXYPlot): #: The RGBA tuple for rendering edges. It is always a tuple of length 4. #: It has the same RGB values as :attr:`edge_color`, and its alpha value #: is the alpha value of self.edge_color multiplied by self.alpha. - effective_edge_color = Property(Tuple, depends_on=['edge_color', 'alpha']) + effective_edge_color = Property(Tuple, depends_on=["edge_color", "alpha"]) #: The RGBA tuple for rendering the face. It is always a tuple of length #: 4. It has the same RGB values as :attr:`face_color`, and its alpha #: value is the alpha value of self.face_color multiplied by self.alpha. - effective_face_color = Property(Tuple, depends_on=['face_color', 'alpha']) + effective_face_color = Property(Tuple, depends_on=["face_color", "alpha"]) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Private 'BaseXYPlot' interface - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _gather_points(self): - """ Collects the data points that are within the bounds of the plot and + """Collects the data points that are within the bounds of the plot and caches them. """ if self._cache_valid: @@ -83,15 +82,13 @@ def _gather_points(self): self._cache_valid = True return - points = np.transpose(np.array((index,value))) + points = np.transpose(np.array((index, value))) self._cached_data_pts = points self._cache_valid = True - def _render(self, gc, points): - """ Renders an Nx2 array of screen-space points as a polygon. - """ + """Renders an Nx2 array of screen-space points as a polygon.""" with gc: gc.clip_to_rect(self.x, self.y, self.width, self.height) gc.set_stroke_color(self.effective_edge_color) @@ -103,9 +100,8 @@ def _render(self, gc, points): gc.close_path() gc.draw_path() - def _render_icon(self, gc, x, y, width, height): - """ Renders a representation of this plot as an icon into the box + """Renders a representation of this plot as an icon into the box defined by the parameters. Used by the legend. @@ -114,12 +110,12 @@ def _render_icon(self, gc, x, y, width, height): gc.set_stroke_color(self.effective_edge_color) gc.set_line_width(self.edge_width) gc.set_fill_color(self.effective_face_color) - if hasattr(self, 'line_style_'): + if hasattr(self, "line_style_"): gc.set_line_dash(self.line_style_) - gc.draw_rect((x,y,width,height)) + gc.draw_rect((x, y, width, height)) def hittest(self, screen_pt, threshold=7.0, return_distance=False): - """ Performs point-in-polygon testing or point/line proximity testing. + """Performs point-in-polygon testing or point/line proximity testing. If self.hittest_type is "line" or "point", then behaves like the parent class BaseXYPlot.hittest(). @@ -138,9 +134,9 @@ def hittest(self, screen_pt, threshold=7.0, return_distance=False): else: return False - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property getters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @cached_property def _get_effective_edge_color(self): diff --git a/chaco/quiverplot.py b/chaco/quiverplot.py index 6d986644e..962dbcf50 100644 --- a/chaco/quiverplot.py +++ b/chaco/quiverplot.py @@ -1,6 +1,3 @@ - - - from numpy import array, compress, matrix, newaxis, sqrt, zeros # Enthought library imports @@ -11,12 +8,13 @@ from .abstract_data_source import AbstractDataSource from .scatterplot import ScatterPlot + class QuiverPlot(ScatterPlot): #: Determines how to interpret the data in the **vectors** data source. #: "vector": each tuple is a (dx, dy) #: "radial": each tuple is an (r, theta) - data_type = Enum("vector", "radial") # TODO: implement "radial" + data_type = Enum("vector", "radial") # TODO: implement "radial" #: A datasource that returns an Nx2 array array indicating directions #: of the vectors. The interpretation of this array is dependent on @@ -25,9 +23,9 @@ class QuiverPlot(ScatterPlot): #: Usually this will be a MultiArrayDataSource. vectors = Instance(AbstractDataSource) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Visual attributes of the vector - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The color of the lines line_color = ColorTrait("black") @@ -38,9 +36,9 @@ class QuiverPlot(ScatterPlot): #: The length, in pixels, of the arrowhead arrow_size = Int(5) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ _cached_vector_data = Array _selected_vector_data = Array @@ -85,17 +83,21 @@ def _render(self, gc, points, icon_mode=False): if self.arrow_size > 0: vec = self._cached_vector_data - unit_vec = vec / sqrt(vec[:,0] ** 2 + vec[:,1] ** 2)[:, newaxis] - a = 0.707106781 # sqrt(2)/2 + unit_vec = vec / sqrt(vec[:, 0] ** 2 + vec[:, 1] ** 2)[:, newaxis] + a = 0.707106781 # sqrt(2)/2 # Draw the left arrowhead (for an arrow pointing straight up) - arrow_ends = ends - array(unit_vec * matrix([[a, a], [-a, a]])) * self.arrow_size + arrow_ends = ( + ends - array(unit_vec * matrix([[a, a], [-a, a]])) * self.arrow_size + ) gc.begin_path() gc.line_set(ends, arrow_ends) gc.stroke_path() # Draw the left arrowhead (for an arrow pointing straight up) - arrow_ends = ends - array(unit_vec * matrix([[a, -a], [a, a]])) * self.arrow_size + arrow_ends = ( + ends - array(unit_vec * matrix([[a, -a], [a, a]])) * self.arrow_size + ) gc.begin_path() gc.line_set(ends, arrow_ends) gc.stroke_path() diff --git a/chaco/scales/formatters.py b/chaco/scales/formatters.py index 94ad19252..726efdd5e 100644 --- a/chaco/scales/formatters.py +++ b/chaco/scales/formatters.py @@ -9,26 +9,31 @@ import warnings -__all__ = ['NullFormatter', 'BasicFormatter', 'IntegerFormatter', - 'OffsetFormatter', 'TimeFormatter', 'strftimeEx'] +__all__ = [ + "NullFormatter", + "BasicFormatter", + "IntegerFormatter", + "OffsetFormatter", + "TimeFormatter", + "strftimeEx", +] + class NullFormatter(object): - """ Formatter for empty labels. - """ + """Formatter for empty labels.""" + def format(ticks, numlabels=None, char_width=None): - """ Returns a list containing an empty label for each item in *ticks*. - """ + """Returns a list containing an empty label for each item in *ticks*.""" return [""] * len(ticks) def estimate_width(start, end, numlabels=None, char_width=None): - """ Returns 0 for width and 0 for number of labels. - """ + """Returns 0 for width and 0 for number of labels.""" return 0, 0 class BasicFormatter(object): - """ Formatter for numeric labels. - """ + """Formatter for numeric labels.""" + # This is a class-level default that is related to the algorithm in format() avg_label_width = 7.0 @@ -45,7 +50,7 @@ def __init__(self, **kwds): self.__dict__.update(kwds) def oldformat(self, ticks, numlabels=None, char_width=None): - """ This function is adapted from matplotlib's "OldScalarFormatter". + """This function is adapted from matplotlib's "OldScalarFormatter". Parameters ---------- @@ -66,33 +71,39 @@ def oldformat(self, ticks, numlabels=None, char_width=None): d = abs(ticks[-1] - ticks[0]) for x in ticks: - if abs(x)<1e4 and x==int(x): - labels.append('%d' % x) + if abs(x) < 1e4 and x == int(x): + labels.append("%d" % x) continue - if d < 1e-2: fmt = '%1.3e' - elif d < 1e-1: fmt = '%1.3f' - elif d > 1e5: fmt = '%1.1e' - elif d > 10 : fmt = '%1.1f' - elif d > 1 : fmt = '%1.2f' - else: fmt = '%1.3f' - s = fmt % x - tup = s.split('e') - if len(tup)==2: - mantissa = tup[0].rstrip('0').rstrip('.') - sign = tup[1][0].replace('+', '') - exponent = tup[1][1:].lstrip('0') + if d < 1e-2: + fmt = "%1.3e" + elif d < 1e-1: + fmt = "%1.3f" + elif d > 1e5: + fmt = "%1.1e" + elif d > 10: + fmt = "%1.1f" + elif d > 1: + fmt = "%1.2f" + else: + fmt = "%1.3f" + s = fmt % x + tup = s.split("e") + if len(tup) == 2: + mantissa = tup[0].rstrip("0").rstrip(".") + sign = tup[1][0].replace("+", "") + exponent = tup[1][1:].lstrip("0") if sign or exponent: - s = '%se%s%s' %(mantissa, sign, exponent) + s = "%se%s%s" % (mantissa, sign, exponent) else: s = mantissa else: - s = s.rstrip('0').rstrip('.') + s = s.rstrip("0").rstrip(".") labels.append(s) return labels def format(self, ticks, numlabels=None, char_width=None, fill_ratio=0.3): - """ Does "nice" formatting of floating-point numbers. *numlabels* is + """Does "nice" formatting of floating-point numbers. *numlabels* is ignored in this method. """ if len(ticks) == 0: @@ -100,8 +111,10 @@ def format(self, ticks, numlabels=None, char_width=None, fill_ratio=0.3): ticks = asarray(ticks) if self.use_scientific: - scientific = (((ticks % 10 ** self.scientific_limits[1]) == 0) | - (abs(ticks) <= 10 ** self.scientific_limits[0])).all() + scientific = ( + ((ticks % 10 ** self.scientific_limits[1]) == 0) + | (abs(ticks) <= 10 ** self.scientific_limits[0]) + ).all() else: scientific = False @@ -136,7 +149,7 @@ def format(self, ticks, numlabels=None, char_width=None, fill_ratio=0.3): return labels def _nice_sci(self, val, mdigits, force_sign=False): - """ Formats *val* nicely using scientific notation. *mdigits* is the + """Formats *val* nicely using scientific notation. *mdigits* is the max number of digits to use for the mantissa. If *force_sign* is True, then always show the sign of the mantissa, otherwise only show the sign if *val* is negative. @@ -145,7 +158,7 @@ def _nice_sci(self, val, mdigits, force_sign=False): e = int(floor(log10(abs(val)))) else: e = 0 - m = val / float(10**e) + m = val / float(10 ** e) m_str = str(m) # Safely truncating the mantissa is somewhat tricky. The minimum @@ -181,10 +194,10 @@ def _nice_sci(self, val, mdigits, force_sign=False): return m_str - - def estimate_width(self, start, end, numlabels=None, char_width=None, - fill_ratio=0.3, ticker=None): - """ Returns an estimate of the total number of characters used by the + def estimate_width( + self, start, end, numlabels=None, char_width=None, fill_ratio=0.3, ticker=None + ): + """Returns an estimate of the total number of characters used by the the labels for the given set of inputs, as well as the number of labels. Parameters @@ -231,17 +244,15 @@ def estimate_width(self, start, end, numlabels=None, char_width=None, class IntegerFormatter(BasicFormatter): - """ Format integer tick labels as integers. - """ + """Format integer tick labels as integers.""" def format(self, ticks, numlabels=None, char_width=None, fill_ratio=0.3): - """ Formats integer tick labels. - """ + """Formats integer tick labels.""" return list(map(str, map(int, ticks))) class OffsetFormatter(BasicFormatter): - """ This formatter is like BasicFormatter, but it supports formatting + """This formatter is like BasicFormatter, but it supports formatting ticks using an offset. This is useful for viewing small ranges within big numbers. """ @@ -291,7 +302,6 @@ class OffsetFormatter(BasicFormatter): # The offset generated by the last call to format() offset = None - def _compute_offset(self, ticks): first, last = ticks[0], ticks[-1] data_range = ticks[-1] - ticks[0] @@ -302,14 +312,13 @@ def _compute_offset(self, ticks): else: return floor(amin(ticks) / pow_of_ten) * pow_of_ten - def format(self, ticks, numlabels=None, char_width=None): if len(ticks) == 0: return [] data_range = ticks[-1] - ticks[0] avg_data = sum(abs(ticks)) / len(ticks) - if self.use_offset and data_range/avg_data < self.offset_threshold: + if self.use_offset and data_range / avg_data < self.offset_threshold: offset = self._compute_offset(ticks) intermed_ticks = asarray(ticks) - offset @@ -340,8 +349,9 @@ def format(self, ticks, numlabels=None, char_width=None): else: return BasicFormatter.format(self, ticks, numlabels, char_width) - def estimate_width(self, start, end, numlabels=None, char_width=None, - fill_ratio=0.3, ticker=None): + def estimate_width( + self, start, end, numlabels=None, char_width=None, fill_ratio=0.3, ticker=None + ): if numlabels == 0 or char_width == 0: return (0, 0) @@ -352,9 +362,7 @@ def estimate_width(self, start, end, numlabels=None, char_width=None, avg_size = len("%g%g" % (start, end)) / 2.0 initial_estimate = round(fill_ratio * char_width / avg_size) else: - raise ValueError( - "num_labels and char_width should not both be None." - ) + raise ValueError("num_labels and char_width should not both be None.") est_ticks = int(ticker.num_ticks(start, end, initial_estimate)) elif numlabels: @@ -364,9 +372,9 @@ def estimate_width(self, start, end, numlabels=None, char_width=None, elif char_width: est_ticks = round(fill_ratio * char_width / avg_size) - start, mid, end = map(len, self.format([start, (start+end)/2.0, end])) + start, mid, end = map(len, self.format([start, (start + end) / 2.0, end])) if est_ticks > 2: - size = start + end + (est_ticks-2) * mid + size = start + end + (est_ticks - 2) * mid else: size = start + end @@ -392,14 +400,14 @@ def strftimeEx(fmt, t, timetuple=None): if "%(ms)" in fmt: # Assume that fmt does not also contain %(ms_) and %(us). # (It really doesn't make sense to mix %(ms) with those.) - secs, frac = divmod(round(t,3), 1) - ms = int(round(1e3*frac)) + secs, frac = divmod(round(t, 3), 1) + ms = int(round(1e3 * frac)) fmt = fmt.replace("%(ms)", "%03d" % ms) else: # Assume fmt contains %(ms_) and %(us). - secs, frac = divmod(round(t,6), 1) - ms = int(round(1e3*frac)) - ms_, us = divmod(int(round(1e6*frac)),1000) + secs, frac = divmod(round(t, 6), 1) + ms = int(round(1e3 * frac)) + ms_, us = divmod(int(round(1e6 * frac)), 1000) fmt = fmt.replace("%(ms_)", "%03d" % ms_) fmt = fmt.replace("%(us)", "%03d" % us) @@ -410,17 +418,16 @@ def strftimeEx(fmt, t, timetuple=None): def _two_digit_year(t): - """ Round to the nearest Jan 1, roughly. - """ + """Round to the nearest Jan 1, roughly.""" dt = safe_fromtimestamp(t) year = dt.year if dt.month >= 7: year += 1 return "'%02d" % (year % 100) + def _four_digit_year(t): - """ Round to the nearest Jan 1, roughly. - """ + """Round to the nearest Jan 1, roughly.""" dt = safe_fromtimestamp(t) year = dt.year if dt.month >= 7: @@ -429,26 +436,39 @@ def _four_digit_year(t): class TimeFormatter(object): - """ Formatter for time values. - """ + """Formatter for time values.""" + # This table of format is convert into the 'formats' dict. Each tuple of # formats must be ordered from shortest to longest. _formats = { - 'microseconds': ('%(us)us', '%(ms_).%(us)ms'), - 'milliseconds': ('%(ms)ms', '%S.%(ms)s'), - 'seconds': (':%S', '%Ss'), - 'minsec': ('%M:%S',), # '%Mm%S', '%Mm%Ss'), - 'minutes': ('%Mm',), - 'hourmin': ('%H:%M',), #'%Hh%M', '%Hh%Mm', '%H:%M:%S','%Hh %Mm %Ss'), - 'hours': ('%Hh', '%H:%M'), - 'days': ('%m/%d', '%a%d',), - 'months': ('%m/%Y', '%b%y'), - 'years': (_two_digit_year, _four_digit_year), - } + "microseconds": ("%(us)us", "%(ms_).%(us)ms"), + "milliseconds": ("%(ms)ms", "%S.%(ms)s"), + "seconds": (":%S", "%Ss"), + "minsec": ("%M:%S",), # '%Mm%S', '%Mm%Ss'), + "minutes": ("%Mm",), + "hourmin": ("%H:%M",), #'%Hh%M', '%Hh%Mm', '%H:%M:%S','%Hh %Mm %Ss'), + "hours": ("%Hh", "%H:%M"), + "days": ( + "%m/%d", + "%a%d", + ), + "months": ("%m/%Y", "%b%y"), + "years": (_two_digit_year, _four_digit_year), + } # Labels of time units, from finest to coarsest. - format_order = ['microseconds', 'milliseconds', 'seconds', 'minsec', 'minutes', - 'hourmin', 'hours', 'days', 'months', 'years'] + format_order = [ + "microseconds", + "milliseconds", + "seconds", + "minsec", + "minutes", + "hourmin", + "hours", + "days", + "months", + "years", + ] # A dict whose are keys are the strings in **format_order**; each value is # two arrays, (widths, format strings/functions). @@ -490,19 +510,20 @@ def _get_resolution(self, resolution, interval): resol = "hourmin" else: resol = "minutes" - elif r < 24*3600: + elif r < 24 * 3600: resol = "hours" - elif r < 30*24*3600: + elif r < 30 * 24 * 3600: resol = "days" - elif r < 365*24*3600: + elif r < 365 * 24 * 3600: resol = "months" else: resol = "years" return resol - def format(self, ticks, numlabels=None, char_width=None, fill_ratio = 0.3, - ticker=None): - """ Formats a set of time values. + def format( + self, ticks, numlabels=None, char_width=None, fill_ratio=0.3, ticker=None + ): + """Formats a set of time values. Parameters ---------- @@ -555,13 +576,15 @@ def format(self, ticks, numlabels=None, char_width=None, fill_ratio = 0.3, # a problem with the tick at midnight, january 1st, 0 a.d. being incorrectly # promoted at certain tick resolutions. time_tuple_ndx_for_resol = dict.fromkeys(self.format_order, 0) - time_tuple_ndx_for_resol.update( { - "seconds" : 5, - "minsec" : 4, - "minutes" : 4, - "hourmin" : 3, - "hours" : 3, - }) + time_tuple_ndx_for_resol.update( + { + "seconds": 5, + "minsec": 4, + "minutes": 4, + "hourmin": 3, + "hours": 3, + } + ) # As we format each tick, check to see if we are at a boundary of the # next higher unit of time. If so, replace the current format with one @@ -584,14 +607,17 @@ def format(self, ticks, numlabels=None, char_width=None, fill_ratio = 0.3, # time is by checking that we have 0 units of the resolution, i.e. # we are at zero minutes, so display hours, or we are at zero seconds, # so display minutes (and if that is zero as well, then display hours). - while tm[ time_tuple_ndx_for_resol[self.format_order[next_ndx]] ] == 0: + while tm[time_tuple_ndx_for_resol[self.format_order[next_ndx]]] == 0: next_ndx += 1 if next_ndx == len(self.format_order): break if resol in ("minsec", "hourmin") and not hybrid_handled: - if (resol == "minsec" and tm.tm_min == 0 and tm.tm_sec != 0) or \ - (resol == "hourmin" and tm.tm_hour == 0 and tm.tm_min != 0): - next_format = self.formats[self.format_order[resol_ndx-1]][1][0] + if (resol == "minsec" and tm.tm_min == 0 and tm.tm_sec != 0) or ( + resol == "hourmin" and tm.tm_hour == 0 and tm.tm_min != 0 + ): + next_format = self.formats[self.format_order[resol_ndx - 1]][1][ + 0 + ] s = strftimeEx(next_format, t, tm) break else: @@ -601,19 +627,20 @@ def format(self, ticks, numlabels=None, char_width=None, fill_ratio = 0.3, s = strftimeEx(next_format, t, tm) if self.strip_leading_zeros: - ss = s.lstrip('0') - if ss != s and (ss == '' or not ss[0].isdigit()): + ss = s.lstrip("0") + if ss != s and (ss == "" or not ss[0].isdigit()): # A label such as '000ms' should leave one zero. - ss = '0' + ss + ss = "0" + ss labels.append(ss) else: labels.append(s) return labels - def estimate_width(self, start, end, numlabels=None, char_width=None, - fill_ratio = 0.2, ticker=None): - """ Returns an estimate of the total number of characters used by the + def estimate_width( + self, start, end, numlabels=None, char_width=None, fill_ratio=0.2, ticker=None + ): + """Returns an estimate of the total number of characters used by the the labels for the given set of inputs, as well as the number of labels. Parameters @@ -669,8 +696,6 @@ def estimate_width(self, start, end, numlabels=None, char_width=None, width *= numlabels else: # Just pick the middle of the pack of format widths - width = widths[ int(len(widths) / 2) ] * numlabels + width = widths[int(len(widths) / 2)] * numlabels return numlabels, width - - diff --git a/chaco/scales/safetime.py b/chaco/scales/safetime.py index 60007e1f0..5dfa5d03b 100644 --- a/chaco/scales/safetime.py +++ b/chaco/scales/safetime.py @@ -4,13 +4,19 @@ import warnings import time as stdlib_time + # Yup, we're exposing everything from time. from time import * from datetime import datetime, timedelta, MINYEAR, MAXYEAR -__all__ = ([x for x in dir(stdlib_time) if not x.startswith('_')] - + ['safe_fromtimestamp', 'datetime', 'timedelta', 'MINYEAR', 'MAXYEAR', - 'EPOCH']) +__all__ = [x for x in dir(stdlib_time) if not x.startswith("_")] + [ + "safe_fromtimestamp", + "datetime", + "timedelta", + "MINYEAR", + "MAXYEAR", + "EPOCH", +] # On Windows 10, datetime.fromtimestamp fails with an OSError for timestamps @@ -23,7 +29,7 @@ # Can't monkeypatch methods of anything in datetime, so we have to wrap them def safe_fromtimestamp(timestamp, *args, **kwds): - """ safe_fromtimestamp(timestamp) -> UTC time from POSIX timestamp. + """safe_fromtimestamp(timestamp) -> UTC time from POSIX timestamp. Timestamps outside of the valid range will be assigned datetime objects of Jan 1 of either MINYEAR or MAXYEAR, whichever appears closest. @@ -40,8 +46,9 @@ def safe_fromtimestamp(timestamp, *args, **kwds): else: return datetime(MAXYEAR, 1, 1, 0, 0, 0) + def mktime(t): - """ mktime(tuple) -> floating point number + """mktime(tuple) -> floating point number Convert a time tuple in local time to seconds since the Epoch. Invalid time tuples will be assigned the value 0.0 and a warning will be issued. @@ -53,8 +60,9 @@ def mktime(t): # mktime() returns a float return 0.0 + def doy(dt): - """ Find the day of year of the datetime. + """Find the day of year of the datetime. The returned DoY is in the range [1-366]. """ @@ -63,8 +71,10 @@ def doy(dt): doy = (date - jan01).days + 1 return doy + struct_time = type(stdlib_time.localtime()) + def localtime(t=None): """ localtime([seconds]) -> (tm_year,tm_mon,tm_day,tm_hour,tm_min,tm_sec,tm_wday,tm_yday,tm_isdst) @@ -78,7 +88,15 @@ def localtime(t=None): dt = datetime.now() else: dt = safe_fromtimestamp(t) - timetuple = (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, - dt.weekday(), doy(dt), -1) + timetuple = ( + dt.year, + dt.month, + dt.day, + dt.hour, + dt.minute, + dt.second, + dt.weekday(), + doy(dt), + -1, + ) return struct_time(timetuple) - diff --git a/chaco/scales/scales.py b/chaco/scales/scales.py index 4074e0f23..4c761661c 100644 --- a/chaco/scales/scales.py +++ b/chaco/scales/scales.py @@ -12,13 +12,23 @@ from .formatters import BasicFormatter -__all__ = ["AbstractScale", "DefaultScale", "FixedScale", "Pow10Scale", - "LogScale", "ScaleSystem", "heckbert_interval", "frange"] +__all__ = [ + "AbstractScale", + "DefaultScale", + "FixedScale", + "Pow10Scale", + "LogScale", + "ScaleSystem", + "heckbert_interval", + "frange", +] + def frange(min, max, delta): """ Floating point range. """ count = int(round((max - min) / delta)) + 1 - return [min + i*delta for i in range(count)] + return [min + i * delta for i in range(count)] + class AbstractScale(object): """ Defines the general interface for scales. """ @@ -26,7 +36,7 @@ class AbstractScale(object): DEFAULT_NUM_TICKS = 8 def ticks(self, start, end, desired_ticks=None): - """ Returns the set of "nice" positions on this scale that enclose and + """Returns the set of "nice" positions on this scale that enclose and fall inside the interval (*start*,*end*). Parameters @@ -42,7 +52,7 @@ def ticks(self, start, end, desired_ticks=None): raise NotImplementedError def num_ticks(self, start, end, desired_ticks=None): - """ Returns an approximate number of ticks that this scale + """Returns an approximate number of ticks that this scale produces for the given interval. This method is used by the scale system to determine whether this is @@ -65,7 +75,7 @@ def num_ticks(self, start, end, desired_ticks=None): raise NotImplementedError def labels(self, start, end, numlabels=None, char_width=None): - """ Returns a series of ticks and corresponding strings for labels + """Returns a series of ticks and corresponding strings for labels that fall inside the interval (*start*,*end*). Parameters @@ -87,7 +97,7 @@ def labels(self, start, end, numlabels=None, char_width=None): return list(zip(ticks, labels)) def label_width(self, start, end, numlabels=None, char_width=None): - """ Returns an estimate of the total number of characters used by the + """Returns an estimate of the total number of characters used by the the labels that this scale produces for the given set of inputs, as well as the number of labels. @@ -106,15 +116,17 @@ def label_width(self, start, end, numlabels=None, char_width=None): ------- (numlabels, total label width) """ - return self.formatter.estimate_width(start, end, numlabels, char_width, - ticker=self) + return self.formatter.estimate_width( + start, end, numlabels, char_width, ticker=self + ) class FixedScale(AbstractScale): - """ A scale with fixed resolution, and "nice" points that line up at + """A scale with fixed resolution, and "nice" points that line up at multiples of the resolution. An optional zero value can be defined that offsets the "nice" points to (N*resolution+zero). """ + def __init__(self, resolution, zero=0.0, formatter=None): self.resolution = resolution self.zero = zero @@ -123,7 +135,7 @@ def __init__(self, resolution, zero=0.0, formatter=None): self.formatter = formatter def ticks(self, start, end, desired_ticks=None): - """ For FixedScale, *desired_ticks* is ignored. + """For FixedScale, *desired_ticks* is ignored. Overrides AbstractScale. """ @@ -134,11 +146,11 @@ def ticks(self, start, end, desired_ticks=None): end -= self.zero start_tick = int(ceil(start / res)) end_tick = int(floor(end / res)) - ticks = [i*res for i in range(start_tick, end_tick+1)] + ticks = [i * res for i in range(start_tick, end_tick + 1)] return ticks def num_ticks(self, start, end, desired_ticks=None): - """ For FixedScale, *desired_ticks* is ignored. + """For FixedScale, *desired_ticks* is ignored. Overrides AbstractScale. """ @@ -147,8 +159,9 @@ def num_ticks(self, start, end, desired_ticks=None): else: return (end - start) / self.resolution + def _nice(x, round=False): - """ Returns a bracketing interval around interval *x*, whose endpoints fall + """Returns a bracketing interval around interval *x*, whose endpoints fall on "nice" values. If *round* is False, then it uses ceil(range) This function is adapted from the original in Graphics Gems; the boundaries @@ -157,6 +170,7 @@ def _nice(x, round=False): """ if x <= 0: import warnings + warnings.warn("Invalid (negative) range passed to tick interval calculation") x = abs(x) expv = floor(log10(x)) @@ -181,8 +195,9 @@ def _nice(x, round=False): nf = 10.0 return nf * pow(10, expv) + def heckbert_interval(data_low, data_high, numticks=8, nicefunc=_nice, enclose=False): - """ Returns a "nice" range and resolution for an interval and a preferred + """Returns a "nice" range and resolution for an interval and a preferred number of ticks, using Paul Heckbert's algorithm in Graphics Gems. If *enclose* is True, then the function returns a min and a max that fall @@ -208,16 +223,17 @@ def heckbert_interval(data_low, data_high, numticks=8, nicefunc=_nice, enclose=F class DefaultScale(AbstractScale): - """ A dynamic scale that tries to place ticks at nice numbers (1, 2, 5, 10) + """A dynamic scale that tries to place ticks at nice numbers (1, 2, 5, 10) so that ticks don't "pop" as the resolution changes. """ + def __init__(self, formatter=None): if formatter is None: formatter = BasicFormatter() self.formatter = formatter def ticks(self, start, end, desired_ticks=8): - """ Returns the set of "nice" positions on this scale that enclose and + """Returns the set of "nice" positions on this scale that enclose and fall inside the interval (*start*,*end*). Implements AbstractScale. @@ -228,7 +244,7 @@ def ticks(self, start, end, desired_ticks=8): return frange(min, max, delta) def num_ticks(self, start, end, desired_ticks=8): - """ Returns an approximate number of ticks that this scale + """Returns an approximate number of ticks that this scale produces for the given interval. Implements AbstractScale. @@ -237,7 +253,7 @@ def num_ticks(self, start, end, desired_ticks=8): class Pow10Scale(AbstractScale): - """ A dynamic scale that shows only whole multiples of powers of 10 + """A dynamic scale that shows only whole multiples of powers of 10 (including powers < 1). """ @@ -247,20 +263,20 @@ def __init__(self, formatter=None): self.formatter = formatter def ticks(self, start, end, desired_ticks=8): - """ Returns the set of "nice" positions on this scale that enclose and + """Returns the set of "nice" positions on this scale that enclose and fall inside the interval (*start*,*end*). Implements AbstractScale. """ if start == end or isnan(start) or isnan(end): return [start] - min, max, delta = heckbert_interval(start, end, desired_ticks, - nicefunc=self._nice_pow10, - enclose = True) + min, max, delta = heckbert_interval( + start, end, desired_ticks, nicefunc=self._nice_pow10, enclose=True + ) return frange(min, max, delta) def num_ticks(self, start, end, desired_ticks=8): - """ Returns an approximate number of ticks that this scale + """Returns an approximate number of ticks that this scale produces for the given interval. Implements AbstractScale. @@ -272,9 +288,10 @@ def _nice_pow10(self, x, round=False): class LogScale(AbstractScale): - """ A dynamic scale that only produces ticks and labels that work well when + """A dynamic scale that only produces ticks and labels that work well when plotting data on a logarithmic scale. """ + def __init__(self, formatter=None): if formatter is None: formatter = BasicFormatter() @@ -284,52 +301,52 @@ def __init__(self, formatter=None): # For a given base interval size i (i.e. "magic number"), there is a one-to-one # mapping between the nice tick values and the integers. - def _irep_to_value(self,n,i): - """ For a given "magic number" i (i.e. spacing of the evenly spaced ticks + def _irep_to_value(self, n, i): + """For a given "magic number" i (i.e. spacing of the evenly spaced ticks in the decade [1,10]), compute the tick value of the given integer representation.""" if i == 1: - j,k = divmod(n,9) - v = (k+1)*10**j + j, k = divmod(n, 9) + v = (k + 1) * 10 ** j return v else: - j,k = divmod(n,int(10.0/i)) + j, k = divmod(n, int(10.0 / i)) if k == 0: - v = 10**j + v = 10 ** j else: - v = i*k*10**j + v = i * k * 10 ** j return v - def _power_and_interval(self,x,i): + def _power_and_interval(self, x, i): # j is the power of 10 of the decade in which x lies j = int(ceil(log10(x))) - 1 # b is the interval size of the evenly spaced ticks in the decade - b = i*10**j - return (j,b) + b = i * 10 ** j + return (j, b) - def _power_and_index_to_irep(self,j,k,i): + def _power_and_index_to_irep(self, j, k, i): if i == 1: - n = j*9+(k-1) + n = j * 9 + (k - 1) else: - n = j*int(10.0/i)+k + n = j * int(10.0 / i) + k return n - def _logtickceil_as_irep(self,x,i): - """ For a given "magic number" i (i.e. spacing of the evenly spaced ticks + def _logtickceil_as_irep(self, x, i): + """For a given "magic number" i (i.e. spacing of the evenly spaced ticks in the decade [1,10]), compute the integer representation of the smallest tick not less than x.""" - j,b = self._power_and_interval(x,i) - k = int(ceil(float(x)/b)) - n = self._power_and_index_to_irep(j,k,i) + j, b = self._power_and_interval(x, i) + k = int(ceil(float(x) / b)) + n = self._power_and_index_to_irep(j, k, i) return n - def _logtickfloor_as_irep(self,x,i): - """ For a given "magic number" i (i.e. spacing of the evenly spaced ticks + def _logtickfloor_as_irep(self, x, i): + """For a given "magic number" i (i.e. spacing of the evenly spaced ticks in the decade [1,10]), compute the integer representation of the largest tick not greater than x.""" - j,b = self._power_and_interval(x,i) - k = int(floor(float(x)/b)) - n = self._power_and_index_to_irep(j,k,i) + j, b = self._power_and_interval(x, i) + k = int(floor(float(x) / b)) + n = self._power_and_index_to_irep(j, k, i) return n def ticks(self, start, end, desired_ticks=8): @@ -352,16 +369,15 @@ def ticks(self, start, end, desired_ticks=8): if log_interval < 1.0: # If the data is spaced by less than a factor of 10, then use # regular/linear ticking - min, max, delta = heckbert_interval(start, end, desired_ticks, - enclose=True) + min, max, delta = heckbert_interval(start, end, desired_ticks, enclose=True) return frange(min, max, delta) elif log_interval < desired_ticks: magic_numbers = [1, 2, 5] for interval in magic_numbers: - n1 = self._logtickceil_as_irep(start,interval) - n2 = self._logtickfloor_as_irep(end,interval) - ticks = [self._irep_to_value(n,interval) for n in range(n1,n2+1)] + n1 = self._logtickceil_as_irep(start, interval) + n2 = self._logtickfloor_as_irep(end, interval) + ticks = [self._irep_to_value(n, interval) for n in range(n1, n2 + 1)] if len(ticks) < desired_ticks * 1.5: return ticks return ticks @@ -371,24 +387,26 @@ def ticks(self, start, end, desired_ticks=8): startlog = ceil(log_start) endlog = floor(log_end) expticks = linspace(startlog, endlog, endlog - startlog + 1) - return 10**expticks + return 10 ** expticks def num_ticks(self, start, end, desired_ticks=8): - """ Returns an approximate number of ticks that this scale + """Returns an approximate number of ticks that this scale produces for the given interval. Implements AbstractScale. """ return len(self.ticks(start, end, desired_ticks)) + ############################################################################## # # ScaleSystem # ############################################################################## + class ScaleSystem(object): - """ Represents a collection of scales over some range of resolutions. + """Represents a collection of scales over some range of resolutions. This class has settings for a default scale that is used when ticking an interval that is smaller than the finest resolution scale or larger than @@ -396,7 +414,7 @@ class ScaleSystem(object): """ def __init__(self, *scales, **kw): - """ Creates a ScaleSystem + """Creates a ScaleSystem Usage:: @@ -413,9 +431,8 @@ def __init__(self, *scales, **kw): self.fill_ratio = 0.3 self.default_numticks = 8 - def ticks(self, start, end, numticks=None): - """ Computes nice locations for tick marks. + """Computes nice locations for tick marks. Parameters ========== @@ -445,7 +462,7 @@ def ticks(self, start, end, numticks=None): return ticks def labels(self, start, end, numlabels=None, char_width=None): - """ Computes position and labels for an interval + """Computes position and labels for an interval Parameters ---------- @@ -507,18 +524,19 @@ def labels(self, start, end, numlabels=None, char_width=None): else: scales = self.scales - counts, widths = zip(*[s.label_width(start, end, char_width=char_width) \ - for s in scales]) + counts, widths = zip( + *[s.label_width(start, end, char_width=char_width) for s in scales] + ) widths = array(widths) - closest = argmin(abs(widths - char_width*self.fill_ratio)) + closest = argmin(abs(widths - char_width * self.fill_ratio)) if numlabels is None: numlabels = scales[closest].num_ticks(start, end, counts[closest]) - labels = scales[closest].labels(start, end, numlabels, - char_width=char_width) + labels = scales[closest].labels( + start, end, numlabels, char_width=char_width + ) return labels - def _get_scale(self, start, end, numticks): if len(self.scales) == 0: closest_scale = self.default_scale @@ -530,9 +548,12 @@ def _get_scale(self, start, end, numticks): # what the scales offer and the desired number of ticks; if so, revert # to using the default scale approx_ticks = closest_scale.num_ticks(start, end, numticks) - if (approx_ticks == 0) or (numticks == 0) or \ - (abs(approx_ticks - numticks) / numticks > 1.2) or \ - (abs(numticks - approx_ticks) / approx_ticks > 1.2): + if ( + (approx_ticks == 0) + or (numticks == 0) + or (abs(approx_ticks - numticks) / numticks > 1.2) + or (abs(numticks - approx_ticks) / approx_ticks > 1.2) + ): closest_scale = self.default_scale return closest_scale @@ -546,7 +567,8 @@ def _get_scale_bisect(self, start, end, numticks): def _get_scale_np(self, start, end, numticks): # Extract the intervals from the scales we were given - scale_intervals = array([s.num_ticks(start, end, numticks) for s in self.scales]) + scale_intervals = array( + [s.num_ticks(start, end, numticks) for s in self.scales] + ) closest = argmin(abs(scale_intervals - numticks)) return self.scales[closest] - diff --git a/chaco/scales/tests/test_formatters.py b/chaco/scales/tests/test_formatters.py index 99222768b..e1466a608 100644 --- a/chaco/scales/tests/test_formatters.py +++ b/chaco/scales/tests/test_formatters.py @@ -3,12 +3,12 @@ from chaco.scales.formatters import strftimeEx, TimeFormatter -#---------------------------------------------------------------- +# ---------------------------------------------------------------- # strftimeEx tests -#---------------------------------------------------------------- +# ---------------------------------------------------------------- -class TestStrftimeEx(unittest.TestCase): +class TestStrftimeEx(unittest.TestCase): def test_strftimeEx_01(self): t = 0.123 fmt = "%(ms)" @@ -71,12 +71,13 @@ def test_strftimeEx_07(self): expected = "07 999" self.assertEqual(result, expected) -#---------------------------------------------------------------- + +# ---------------------------------------------------------------- # TimeFormatter tests -#---------------------------------------------------------------- +# ---------------------------------------------------------------- -class TestTimeFormatter(unittest.TestCase): +class TestTimeFormatter(unittest.TestCase): def test_time_formatter_01(self): tf = TimeFormatter() ticks = [10.005, 10.0053, 10.0056] diff --git a/chaco/scales/tests/test_scales.py b/chaco/scales/tests/test_scales.py index fdd4297a0..98e157722 100644 --- a/chaco/scales/tests/test_scales.py +++ b/chaco/scales/tests/test_scales.py @@ -8,91 +8,139 @@ class TicksTestCase(unittest.TestCase): """ Base class for scale and scale system unit tests """ + def assert_empty(self, arg): self.assertEqual(len(arg), 0) def check_ticks(self, ticks1, ticks2): - self.assertEqual(len(ticks1),len(ticks2)) + self.assertEqual(len(ticks1), len(ticks2)) for t1, t2 in zip(ticks1, ticks2): self.assertAlmostEqual(t1, t2, 6) def check_labels(self, labels1, labels2): - self.assertEqual(len(labels1),len(labels2)) - for t1, t2, in zip(labels1, labels2): + self.assertEqual(len(labels1), len(labels2)) + for ( + t1, + t2, + ) in zip(labels1, labels2): self.assertEqual(t1, t2) class ScalesTestCase(TicksTestCase): - def test_pow10(self): scale = Pow10Scale() - ticks = scale.ticks(5,15,8) + ticks = scale.ticks(5, 15, 8) self.check_ticks(ticks, frange(5, 15, 1.0)) - ticks = scale.ticks(5,105,8) + ticks = scale.ticks(5, 105, 8) self.check_ticks(ticks, frange(10, 100, 10.0)) def test_log_scale_subdecade(self): # Test cases where log_interval is less than 1. scale = LogScale() ticks = scale.ticks(1.0, 2.0) - self.check_ticks(ticks, array((1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0))) - ticks = scale.ticks(0.9,2.1) + self.check_ticks( + ticks, array((1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0)) + ) + ticks = scale.ticks(0.9, 2.1) self.check_ticks(ticks, array((1.0, 1.25, 1.5, 1.75, 2.0))) - ticks = scale.ticks(1.1,9.9) + ticks = scale.ticks(1.1, 9.9) self.check_ticks(ticks, array((2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0))) - def test_log_scale_interval1(self): # Test the case where 1 < log_interval < desired_ticks, and interval=1 # is the case that generates the ticks. scale = LogScale() - ticks = scale.ticks(1.0,10.1) - self.check_ticks(ticks, array((1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0))) - ticks = scale.ticks(9.3,99.9) - self.check_ticks(ticks, array((10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0))) - ticks = scale.ticks(9.9,100.0) - self.check_ticks(ticks, array((10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0))) - + ticks = scale.ticks(1.0, 10.1) + self.check_ticks( + ticks, array((1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0)) + ) + ticks = scale.ticks(9.3, 99.9) + self.check_ticks( + ticks, array((10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0)) + ) + ticks = scale.ticks(9.9, 100.0) + self.check_ticks( + ticks, array((10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0)) + ) def test_log_scale(self): scale = LogScale() ticks = scale.ticks(0.1, 10.0) - self.check_ticks(ticks, array((0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0))) + self.check_ticks( + ticks, array((0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0)) + ) ticks = scale.ticks(10.0, 1000.0) - self.check_ticks(ticks, array((10.0, 20.0, 40.0, 60.0, 80.0, 100.0, - 200.0, 400.0, 600.0, 800.0, 1000.0))) + self.check_ticks( + ticks, + array( + ( + 10.0, + 20.0, + 40.0, + 60.0, + 80.0, + 100.0, + 200.0, + 400.0, + 600.0, + 800.0, + 1000.0, + ) + ), + ) ticks = scale.ticks(9.9, 1000.0) - self.check_ticks(ticks, array((10.0, 20.0, 40.0, 60.0, 80.0, 100.0, - 200.0, 400.0, 600.0, 800.0, 1000.0))) + self.check_ticks( + ticks, + array( + ( + 10.0, + 20.0, + 40.0, + 60.0, + 80.0, + 100.0, + 200.0, + 400.0, + 600.0, + 800.0, + 1000.0, + ) + ), + ) ticks = scale.ticks(5.0, 4300) self.check_ticks(ticks, array((5, 10, 50, 100, 500, 1000))) # Test case when the log_interval is greater than 8 (the # default desired_ticks) - ticks = scale.ticks(1e-3,1e6) - self.check_ticks(ticks, array((1e-3, 1e-2, 1e-1, 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6))) + ticks = scale.ticks(1e-3, 1e6) + self.check_ticks( + ticks, array((1e-3, 1e-2, 1e-1, 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6)) + ) class ScaleSystemTestCase(TicksTestCase): - def test_defaults(self): ticker = ScaleSystem() ticks = ticker.ticks(5, 30, 10) self.check_ticks(ticks, frange(5.0, 30.0, 2.5)) def test_fixed_scales(self): - scales = [FixedScale(resolution = 1.0), - FixedScale(resolution = 10.0), - FixedScale(resolution = 100.0)] + scales = [ + FixedScale(resolution=1.0), + FixedScale(resolution=10.0), + FixedScale(resolution=100.0), + ] ticker = ScaleSystem(default_scale=None, *scales) self.check_ticks(ticker.ticks(5, 35, 3), (10.0, 20.0, 30.0)) self.check_ticks(ticker.ticks(5, 35, 20), frange(5.0, 35.0, 1.0)) self.check_ticks(ticker.ticks(5, 614, 10), (100, 200, 300, 400, 500, 600)) def test_revert_to_default(self): - scales = [FixedScale(resolution = 1.0), - FixedScale(resolution = 10.0), - FixedScale(resolution = 100.0)] + scales = [ + FixedScale(resolution=1.0), + FixedScale(resolution=10.0), + FixedScale(resolution=100.0), + ] ticker = ScaleSystem(*scales) ticks = ticker.ticks(2.0, 3.0, 10) self.check_ticks(ticks, frange(2.0, 3.0, 0.1)) @@ -101,14 +149,12 @@ def test_translation(self): pass - class BasicFormatterTestCase(TicksTestCase): - def test_format(self): fmt = BasicFormatter() # test with a fixed scale - scale = FixedScale(resolution = 1.0) + scale = FixedScale(resolution=1.0) start, end = 12.0, 18.0 numlabels = 8 @@ -117,30 +163,31 @@ def test_format(self): # desired = [str(float(x)) for x in range(12, 19)] ## This test fails when desired is created with str(float(x)). ## The format function returns "12",...,"18", not "12.0",...,"18.0". - desired = ["12","13","14","15","16","17","18"] + desired = ["12", "13", "14", "15", "16", "17", "18"] self.check_labels(labels, desired) def test_format_small_numbers(self): fmt = BasicFormatter() numlabels = 8 # test with small numbers - scale = FixedScale(resolution = 1e-4) + scale = FixedScale(resolution=1e-4) start, end = 5e-5, 8.5e-4 ticks = scale.ticks(start, end, numlabels) labels = fmt.format(ticks, numlabels, None) - desired = [str(float(i))+"e-4" for i in range(1, 9)] + desired = [str(float(i)) + "e-4" for i in range(1, 9)] self.check_labels(labels, desired) def test2_nice_sci(self): # The table of numerical values and their proper representation # given a certain number of mantissa digits - vals = [ (3.14159e10, (2, "3e10"), (3, '3.1e10'), (5, '3.141e10')), - (123456789, (3, '1.2e8'), (5, '1.234e8')), - (-123456, (2, "-1e5"), (3, "-1e5"), (4, "-1.2e5")), - (123, (2, "1e2"), (3, "1.2e2"), (4, "1.23e2")), - (1.234, (2, "1"), (3, "1.2"), (4, "1.23")), - ] + vals = [ + (3.14159e10, (2, "3e10"), (3, "3.1e10"), (5, "3.141e10")), + (123456789, (3, "1.2e8"), (5, "1.234e8")), + (-123456, (2, "-1e5"), (3, "-1e5"), (4, "-1.2e5")), + (123, (2, "1e2"), (3, "1.2e2"), (4, "1.23e2")), + (1.234, (2, "1"), (3, "1.2"), (4, "1.23")), + ] fmt = BasicFormatter() for lst in vals: val = lst[0] @@ -153,11 +200,12 @@ def test_estimate_default_scale(self): scale = DefaultScale() # Test using numlabels - test_intervals = ((12., 18., 8), - (-4., 16., 10), - (5e-5, 8.5e-4, 8), - (3e8, 6e8, 8), - ) + test_intervals = ( + (12.0, 18.0, 8), + (-4.0, 16.0, 10), + (5e-5, 8.5e-4, 8), + (3e8, 6e8, 8), + ) for start, end, numlabels in test_intervals: estimate = fmt.estimate_width(start, end, numlabels, ticker=scale)[1] ticks = scale.ticks(start, end, numlabels) @@ -169,16 +217,25 @@ def test_estimate_default_scale(self): def test_width_based_default_scale(self): scale = ScaleSystem() - test_intervals = ((1, 100, 80), - (1, 100, 40), - (1, 100, 20),) + test_intervals = ( + (1, 100, 80), + (1, 100, 40), + (1, 100, 20), + ) res0 = [ - (10.0, '10'), (20.0, '20'), (30.0, '30'), (40.0, '40'), - (50.0, '50'), (60.0, '60'), (70.0, '70'), (80.0, '80'), - (90.0, '90'), (100.0, '100') + (10.0, "10"), + (20.0, "20"), + (30.0, "30"), + (40.0, "40"), + (50.0, "50"), + (60.0, "60"), + (70.0, "70"), + (80.0, "80"), + (90.0, "90"), + (100.0, "100"), ] - res1 = [(25.0, '25'), (50.0, '50'), (75.0, '75'), (100.0, '100')] - res2 = [(100.0, '100')] + res1 = [(25.0, "25"), (50.0, "50"), (75.0, "75"), (100.0, "100")] + res2 = [(100.0, "100")] all_expected = [res0, res1, res2] for (start, end, width), expected in zip(test_intervals, all_expected): @@ -186,21 +243,25 @@ def test_width_based_default_scale(self): self.assertEqual(labels, expected) def test_scale_system(self): - scale = ScaleSystem(FixedScale(resolution = 1.0), - FixedScale(resolution = 2.5), - FixedScale(resolution = 5.0), - FixedScale(resolution = 10.0), - FixedScale(resolution = 20.0), - FixedScale(resolution = 100.0)) - - test_intervals = ((1,100,200), - (1, 100, 80), - (1, 100, 40), - (1, 100, 20), - (1, 100, 5), - (1, 10, 100), - (1, 10, 50), - (1, 10, 20),) + scale = ScaleSystem( + FixedScale(resolution=1.0), + FixedScale(resolution=2.5), + FixedScale(resolution=5.0), + FixedScale(resolution=10.0), + FixedScale(resolution=20.0), + FixedScale(resolution=100.0), + ) + + test_intervals = ( + (1, 100, 200), + (1, 100, 80), + (1, 100, 40), + (1, 100, 20), + (1, 100, 5), + (1, 10, 100), + (1, 10, 50), + (1, 10, 20), + ) expected_lengths = [40, 10, 5, 5, 1, 10, 10, 4] for (start, end, width), ll in zip(test_intervals, expected_lengths): @@ -209,20 +270,21 @@ def test_scale_system(self): class OffsetFormatterTestCase(TicksTestCase): - def test_format(self): - test_ranges = [(12003, 12015, 1.0), - (1.2003, 1.2015, 1e-4), - (-1.2015, -1.2003, 1e-4)] + test_ranges = [ + (12003, 12015, 1.0), + (1.2003, 1.2015, 1e-4), + (-1.2015, -1.2003, 1e-4), + ] for start, end, resol in test_ranges: fmt = OffsetFormatter() - fmt.use_offset=True + fmt.use_offset = True fmt.offset_format = "decimal" fmt.end_label_format = "sci" - scale = FixedScale(resolution = resol) + scale = FixedScale(resolution=resol) numlabels = 12 ticks = scale.ticks(start, end, numlabels) labels = fmt.format(ticks, numlabels, None) diff --git a/chaco/scales/tests/test_time_scale.py b/chaco/scales/tests/test_time_scale.py index 7cc2e2de2..ac4f0440d 100644 --- a/chaco/scales/tests/test_time_scale.py +++ b/chaco/scales/tests/test_time_scale.py @@ -6,8 +6,7 @@ import numpy as np import numpy.testing as nptest -from chaco.scales.time_scale import ( - tfrac, trange, TimeScale, CalendarScaleSystem) +from chaco.scales.time_scale import tfrac, trange, TimeScale, CalendarScaleSystem from chaco.scales.api import TimeFormatter # Note on testing: @@ -28,19 +27,19 @@ # Note that we don't actually change the timezone for the process, but this is # good enough to test the logic for the tfrac and trange functions. -#---------------------------------------------------------------- +# ---------------------------------------------------------------- # Utilities -#---------------------------------------------------------------- +# ---------------------------------------------------------------- # Interesting timezone offsets UTC = 0.0 -ALICE_SPRINGS = 9.5*3600 -HONOLULU = -10.0*3600 +ALICE_SPRINGS = 9.5 * 3600 +HONOLULU = -10.0 * 3600 @contextlib.contextmanager def set_timezone(tz): - """ Temporarily select the timezone to use. + """Temporarily select the timezone to use. This works by temporarily replacing the EPOCH module variable with a different value. @@ -67,12 +66,12 @@ def set_timezone(tz): chaco.scales.time_scale.EPOCH = old_epoch -#---------------------------------------------------------------- +# ---------------------------------------------------------------- # tfrac tests -#---------------------------------------------------------------- +# ---------------------------------------------------------------- -class TestTFrac(unittest.TestCase): +class TestTFrac(unittest.TestCase): def test_tfrac_years_01(self): with set_timezone(UTC): t = 3601 @@ -85,7 +84,9 @@ def test_tfrac_years_01_Alice_Springs(self): with set_timezone(ALICE_SPRINGS): t = 3601 (base, frac) = tfrac(t, years=1) - self.assertEqual(base, 3600 * -9.5) # Alice Springs year start UTC timestamp + self.assertEqual( + base, 3600 * -9.5 + ) # Alice Springs year start UTC timestamp self.assertEqual(frac, 3600 * 10.5 + 1) # 10:30:01 in the morning Jan 1 def test_tfrac_years_01_Honolulu(self): @@ -93,8 +94,12 @@ def test_tfrac_years_01_Honolulu(self): with set_timezone(HONOLULU): t = 3601 (base, frac) = tfrac(t, years=1) - self.assertEqual(base, 3600 * (-365*24 + 10)) # previous Honolulu year start UTC timestamp - self.assertEqual(frac, 3600 * (364*24 + 15) + 1) # 15:00:01 in the afternoon, Dec 31 + self.assertEqual( + base, 3600 * (-365 * 24 + 10) + ) # previous Honolulu year start UTC timestamp + self.assertEqual( + frac, 3600 * (364 * 24 + 15) + 1 + ) # 15:00:01 in the afternoon, Dec 31 def test_tfrac_years_02(self): with set_timezone(UTC): @@ -108,7 +113,9 @@ def test_tfrac_years_02_Alice_Springs(self): with set_timezone(ALICE_SPRINGS): t = 3601 (base, frac) = tfrac(t, years=10) - self.assertEqual(base, 3600 * -9.5) # Alice Springs decade start UTC timestamp + self.assertEqual( + base, 3600 * -9.5 + ) # Alice Springs decade start UTC timestamp self.assertEqual(frac, 3600 * 10.5 + 1) # 10:30:01 in the morning Jan 1 def test_tfrac_years_02_Honolulu(self): @@ -117,9 +124,9 @@ def test_tfrac_years_02_Honolulu(self): t = 3601 (base, frac) = tfrac(t, years=10) # previous Honolulu decade start UTC timestamp (including leap years) - self.assertEqual(base, 3600 * (-(365*10 + 3)*24 + 10)) + self.assertEqual(base, 3600 * (-(365 * 10 + 3) * 24 + 10)) # 15:00:01 in the afternoon, Dec 31, 9 years into decade - self.assertEqual(frac, 3600 * ((365*9+3 + 364)*24 + 15) + 1) + self.assertEqual(frac, 3600 * ((365 * 9 + 3 + 364) * 24 + 15) + 1) def test_tfrac_days_01(self): with set_timezone(UTC): @@ -141,12 +148,14 @@ def test_tfrac_days_01_Honolulu(self): with set_timezone(HONOLULU): t = 3601 (base, frac) = tfrac(t, days=1) - self.assertEqual(base, 3600 * (-24 + 10)) # previous Honolulu day start UTC timestamp + self.assertEqual( + base, 3600 * (-24 + 10) + ) # previous Honolulu day start UTC timestamp self.assertEqual(frac, 3600 * 15 + 1) # 15:00:01 in the afternoon def test_tfrac_days_02(self): with set_timezone(UTC): - t = 3*24.0*3600 + 1000.0 + t = 3 * 24.0 * 3600 + 1000.0 (base, frac) = tfrac(t, days=1) self.assertEqual(base, 3600 * 24 * 3) self.assertEqual(frac, 1000) @@ -154,7 +163,7 @@ def test_tfrac_days_02(self): def test_tfrac_days_02_Alice_Springs(self): # Australia/North (UTC+09:30, never DST) with set_timezone(ALICE_SPRINGS): - t = 3*24.0*3600 + 1000.0 + t = 3 * 24.0 * 3600 + 1000.0 (base, frac) = tfrac(t, days=1) self.assertEqual(base, 3600 * (24 * 3 - 9.5)) self.assertEqual(frac, 3600 * 9.5 + 1000) @@ -162,7 +171,7 @@ def test_tfrac_days_02_Alice_Springs(self): def test_tfrac_days_02_Honolulu(self): # Pacific/Honolulu (UTC-10:00, never DST) with set_timezone(HONOLULU): - t = 3*24.0*3600 + 1000.0 + t = 3 * 24.0 * 3600 + 1000.0 (base, frac) = tfrac(t, days=1) self.assertEqual(base, 3600 * (24 * 2 + 10)) self.assertEqual(frac, 3600 * (24 - 10) + 1000) @@ -232,7 +241,7 @@ def test_tfrac_hours_05(self): t = 3600 * 15.5 (base, frac) = tfrac(t, hours=6) self.assertEqual(base, 3600 * 12.0) - self.assertEqual(frac, 3600 * 3.5) + self.assertEqual(frac, 3600 * 3.5) def test_tfrac_hours_05_Alice_Springs(self): # Australia/North (UTC+09:30, never DST) @@ -240,7 +249,7 @@ def test_tfrac_hours_05_Alice_Springs(self): t = 3600 * 15.5 (base, frac) = tfrac(t, hours=6) self.assertEqual(base, 3600 * 14.5) - self.assertEqual(frac, 3600 * 1.0) + self.assertEqual(frac, 3600 * 1.0) def test_tfrac_minutes_01(self): t = 3601 @@ -276,13 +285,13 @@ def test_tfrac_milliseconds_02(self): t = 10.0625 (base, frac) = tfrac(t, milliseconds=1) self.assertEqual(base, 10.062) - self.assertEqual(frac, 0.0005) + self.assertEqual(frac, 0.0005) def test_tfrac_milliseconds_03(self): t = 10.0625 (base, frac) = tfrac(t, milliseconds=10) self.assertEqual(base, 10.06) - self.assertEqual(frac, 0.0025) + self.assertEqual(frac, 0.0025) def test_tfrac_milliseconds_04(self): t = 1.0078121 @@ -299,12 +308,12 @@ def test_tfrac_milliseconds_05(self): self.assertEqual(frac, 0.000806) -#---------------------------------------------------------------- +# ---------------------------------------------------------------- # trange tests -#---------------------------------------------------------------- +# ---------------------------------------------------------------- -class TestTRange(unittest.TestCase): +class TestTRange(unittest.TestCase): def test_trange_hours_01(self): with set_timezone(UTC): r = trange(0, 1, hours=1) @@ -419,22 +428,22 @@ def test_trange_milliseconds_01(self): def test_trange_milliseconds_02(self): r = trange(-0.002, 0.001, milliseconds=1) nptest.assert_allclose( - np.array(r), np.linspace(-0.002, 0.001, 4), rtol=1e-5, atol=1e-5) + np.array(r), np.linspace(-0.002, 0.001, 4), rtol=1e-5, atol=1e-5 + ) -#---------------------------------------------------------------- +# ---------------------------------------------------------------- # TimeScale tests -#---------------------------------------------------------------- +# ---------------------------------------------------------------- # Could use more tests here... --WW -class TestTimeScale(unittest.TestCase): +class TestTimeScale(unittest.TestCase): def test_time_scale_seconds_01(self): ts = TimeScale(seconds=1) ticks = ts.ticks(0, 10) - nptest.assert_array_equal( - np.array(ticks), np.linspace(0.0, 10.0, 11)) + nptest.assert_array_equal(np.array(ticks), np.linspace(0.0, 10.0, 11)) def test_time_scale_seconds_02(self): ts = TimeScale(seconds=2) @@ -448,7 +457,7 @@ def test_time_scale_milliseconds_01(self): nptest.assert_array_equal(np.array(ticks), np.linspace(0.0, 0.1, 11)) def test_time_scale_with_formatter(self): - """ Regression test for TimeScale() with formatter keyword. + """Regression test for TimeScale() with formatter keyword. Using the formatter keyword in the constructor of TimeScale could raise a KeyError. This test passes if no exception is @@ -458,17 +467,17 @@ def test_time_scale_with_formatter(self): ts = TimeScale(minutes=1, formatter=TimeFormatter()) -#---------------------------------------------------------------- +# ---------------------------------------------------------------- # CalendarScaleSystem tests -#---------------------------------------------------------------- +# ---------------------------------------------------------------- -class TestCalendarScaleSystem(unittest.TestCase): +class TestCalendarScaleSystem(unittest.TestCase): def test_calendar_scale_system_01(self): css = CalendarScaleSystem() - ticks = css.ticks(0,10) + ticks = css.ticks(0, 10) self.assertEqual(len(ticks), 11) - nptest.assert_array_equal(np.array(ticks), np.linspace(0,10,11)) + nptest.assert_array_equal(np.array(ticks), np.linspace(0, 10, 11)) # TODO: Add more tests of the ticks() and labels() methods of diff --git a/chaco/scales/tests/test_time_scale_resolution.py b/chaco/scales/tests/test_time_scale_resolution.py index d7b33c3f4..001ddf88b 100644 --- a/chaco/scales/tests/test_time_scale_resolution.py +++ b/chaco/scales/tests/test_time_scale_resolution.py @@ -12,8 +12,9 @@ def DTS(*args, **kw): """ Returns a unix-timestamp-like time """ return dt_to_sec(DT(*args, **kw)) + def sec_from_hms(start, *times): - """ Returns a list of times based on adding each offset tuple in times + """Returns a list of times based on adding each offset tuple in times to the start time (which should be in seconds). Offset tuples can be in any of the forms: (hours), (hours,minutes), or (hours,minutes,seconds). """ @@ -26,19 +27,18 @@ def sec_from_hms(start, *times): cur += t[1] * 60 if len(t) > 2: cur += t[2] - ret.append(start+cur) + ret.append(start + cur) return ret class TRangeTestCase(TicksTestCase): - def test_null_ranges(self): ranges = ( - ((2005,3,15,10,23,15), (2005,3,15,10,23,45), {"minutes":1}), - ((2005,3,15,10,23), (2005,3,15,10,47), {"hours":1}), - ((2005,3,15,5,23), (2005,3,15,18,43), {"days":1}), - ((2005,3,15,10,30), (2005,12,25,18,30), {"years":1}) - ) + ((2005, 3, 15, 10, 23, 15), (2005, 3, 15, 10, 23, 45), {"minutes": 1}), + ((2005, 3, 15, 10, 23), (2005, 3, 15, 10, 47), {"hours": 1}), + ((2005, 3, 15, 5, 23), (2005, 3, 15, 18, 43), {"days": 1}), + ((2005, 3, 15, 10, 30), (2005, 12, 25, 18, 30), {"years": 1}), + ) for start, end, kw in ranges: self.assert_empty(trange(DTS(*start), DTS(*end), **kw)) @@ -48,9 +48,9 @@ def test_microseconds(self): # more than machine precision. base = DTS(2005, 3, 15, 10, 45, 10) start = base + 0.0000027 - end = base + 0.0000177 + end = base + 0.0000177 ticks = trange(start, end, microseconds=5) - desired = [base+i for i in (5e-6, 10e-6, 15e-6)] + desired = [base + i for i in (5e-6, 10e-6, 15e-6)] self.check_ticks(ticks, desired) def test_milliseconds(self): @@ -61,44 +61,43 @@ def test_milliseconds(self): desired = [base + i for i in (0.003, 0.004, 0.005, 0.006, 0.007)] self.check_ticks(ticks, desired) ticks = trange(start, end, milliseconds=2) - self.check_ticks(ticks, (base+0.004, base+0.006)) + self.check_ticks(ticks, (base + 0.004, base + 0.006)) def test_daily(self): base = DTS(2005, 1, 1) - secs_per_day = 24*3600 - ticks = trange(base, base + secs_per_day*5, days=1) - desired = [base+i*secs_per_day for i in range(6)] + secs_per_day = 24 * 3600 + ticks = trange(base, base + secs_per_day * 5, days=1) + desired = [base + i * secs_per_day for i in range(6)] self.check_ticks(ticks, desired) def test_daily_leap(self): start = DTS(2004, 2, 27) end = DTS(2004, 3, 2) ticks = trange(start, end, days=1) - desired = [start + i*24*3600 for i in range(5)] + desired = [start + i * 24 * 3600 for i in range(5)] self.check_ticks(ticks, desired) def test_hourly(self): # test between Feb 29,2004 10:15pm and Mar 1st 3:15am - ticks = trange(DTS(2004,2,29,22,15), DTS(2004,3,1,3,15), hours=1) - start = DTS(2004,2,29,23) - desired = [start + i*3600 for i in range(5)] + ticks = trange(DTS(2004, 2, 29, 22, 15), DTS(2004, 3, 1, 3, 15), hours=1) + start = DTS(2004, 2, 29, 23) + desired = [start + i * 3600 for i in range(5)] self.check_ticks(ticks, desired) def test_multiday_increment(self): start = DTS(2005, 1, 1) - ticks = trange(start, start + 9*24*3600, days=3) - desired = [start+i*3*24*3600 for i in range(4)] + ticks = trange(start, start + 9 * 24 * 3600, days=3) + desired = [start + i * 3 * 24 * 3600 for i in range(4)] self.check_ticks(ticks, desired) class TimeScaleTestCase(TicksTestCase): - def test_hourly(self): ts = TimeScale(hours=1) start = DTS(2005, 3, 15, 10, 30) end = DTS(2005, 3, 15, 16, 59) desired_start = DTS(2005, 3, 15) - desired = [desired_start + i*3600 for i in (11, 12, 13, 14, 15, 16)] + desired = [desired_start + i * 3600 for i in (11, 12, 13, 14, 15, 16)] self.check_ticks(ts.ticks(start, end), desired) def test_minutes(self): @@ -106,31 +105,48 @@ def test_minutes(self): start = DTS(2005, 3, 15, 10, 20) end = DTS(2005, 3, 15, 11, 55) dstart = DTS(2005, 3, 15) - desired = ((10,30), (10,45), (11,00), (11,15), (11,30), (11,45)) - self.check_ticks(ts.ticks(start, end), - sec_from_hms(dstart, *desired)) + desired = ((10, 30), (10, 45), (11, 00), (11, 15), (11, 30), (11, 45)) + self.check_ticks(ts.ticks(start, end), sec_from_hms(dstart, *desired)) def test_day_of_month(self): - ts = TimeScale(day_of_month=(1,8,15,22)) - start = DTS(2005,3,12) - end = DTS(2005,5,3) - desired = list(starmap(DTS, ((2005,3,15), (2005,3,22), (2005,4,1), (2005,4,8), - (2005,4,15), (2005,4,22), (2005,5,1)))) - self.check_ticks(ts.ticks(start,end), desired) + ts = TimeScale(day_of_month=(1, 8, 15, 22)) + start = DTS(2005, 3, 12) + end = DTS(2005, 5, 3) + desired = list( + starmap( + DTS, + ( + (2005, 3, 15), + (2005, 3, 22), + (2005, 4, 1), + (2005, 4, 8), + (2005, 4, 15), + (2005, 4, 22), + (2005, 5, 1), + ), + ) + ) + self.check_ticks(ts.ticks(start, end), desired) # test adjacent months start = DTS(2005, 3, 12) end = DTS(2005, 4, 10) - desired = list(starmap(DTS, ((2005,3,15), (2005,3,22), (2005,4,1), (2005,4,8)))) - self.check_ticks(ts.ticks(start,end), desired) - + desired = list( + starmap(DTS, ((2005, 3, 15), (2005, 3, 22), (2005, 4, 1), (2005, 4, 8))) + ) + self.check_ticks(ts.ticks(start, end), desired) def test_month_of_year(self): - ts = TimeScale(month_of_year=(1,4,8)) - start = DTS(2005,1,1) - end = DTS(2006,5,1) - desired = list(starmap(DTS, ((2005,1,1), (2005,4,1), (2005,8,1), (2006,1,1), (2006,4,1)))) - self.check_ticks(ts.ticks(start,end), desired) + ts = TimeScale(month_of_year=(1, 4, 8)) + start = DTS(2005, 1, 1) + end = DTS(2006, 5, 1) + desired = list( + starmap( + DTS, + ((2005, 1, 1), (2005, 4, 1), (2005, 8, 1), (2006, 1, 1), (2006, 4, 1)), + ) + ) + self.check_ticks(ts.ticks(start, end), desired) def test_microsecond(self): # This test is dicey, because the values being tested are close to @@ -140,7 +156,7 @@ def test_microsecond(self): start = base + 2.8e-6 end = base + 9.2e-6 ticks = ts.ticks(start, end) - desired = [base+i for i in (3e-6, 4e-6, 5e-6, 6e-6, 7e-6, 8e-6, 9e-6)] + desired = [base + i for i in (3e-6, 4e-6, 5e-6, 6e-6, 7e-6, 8e-6, 9e-6)] self.check_ticks(ticks, desired) @@ -149,24 +165,38 @@ class CalendarScaleSystemTestCase(TicksTestCase): # within a single ScaleSystem. def test_hourly_scales(self): - scales = [TimeScale(seconds=dt) for dt in (1, 5, 15, 30)] + \ - [TimeScale(minutes=dt) for dt in (1, 5, 15, 30)] + \ - [TimeScale(hours=dt) for dt in (1, 2, 3, 4, 6, 12)] + scales = ( + [TimeScale(seconds=dt) for dt in (1, 5, 15, 30)] + + [TimeScale(minutes=dt) for dt in (1, 5, 15, 30)] + + [TimeScale(hours=dt) for dt in (1, 2, 3, 4, 6, 12)] + ) def test_yearly_scales(self): ticker = ScaleSystem(TimeScale(month_of_year=1), default_scale=None) - ticks = ticker.ticks(DTS(2000,1,1), DTS(2007,1,1), 10) - desired = list(starmap(DTS, ((2000,1,1), (2001,1,1), (2002,1,1), (2003,1,1), - (2004,1,1), (2005,1,1), (2006,1,1), (2007,1,1)))) + ticks = ticker.ticks(DTS(2000, 1, 1), DTS(2007, 1, 1), 10) + desired = list( + starmap( + DTS, + ( + (2000, 1, 1), + (2001, 1, 1), + (2002, 1, 1), + (2003, 1, 1), + (2004, 1, 1), + (2005, 1, 1), + (2006, 1, 1), + (2007, 1, 1), + ), + ) + ) self.check_ticks(ticks, desired) class TimeFormatterTestCase(TicksTestCase): - def test_widths(self): fmt = TimeFormatter() - scale = TimeScale(minutes = 5) - test_intervals = ([(2005,3,15,10,30), (2005,3,15,10,50), 50],) + scale = TimeScale(minutes=5) + test_intervals = ([(2005, 3, 15, 10, 30), (2005, 3, 15, 10, 50), 50],) expected = (4.0, 12.0) for start, end, width in test_intervals: est_width = scale.label_width(DTS(*start), DTS(*end), char_width=width) @@ -175,9 +205,9 @@ def test_widths(self): def test_labels(self): fmt = TimeFormatter() scale = ScaleSystem(*HMSScales) - expected_labels = ['{}m'.format(m) for m in range(30, 51)] - - test_intervals = ([(2005,3,15,10,30), (2005,3,15,10,50), 150],) + expected_labels = ["{}m".format(m) for m in range(30, 51)] + + test_intervals = ([(2005, 3, 15, 10, 30), (2005, 3, 15, 10, 50), 150],) for start, end, width in test_intervals: labels = scale.labels(DTS(*start), DTS(*end), char_width=width) labels = [label for (_, label) in labels] diff --git a/chaco/scales/time_scale.py b/chaco/scales/time_scale.py index 0198f1b63..9d0eea21f 100644 --- a/chaco/scales/time_scale.py +++ b/chaco/scales/time_scale.py @@ -6,27 +6,32 @@ from .scales import AbstractScale, ScaleSystem, frange, heckbert_interval from .formatters import TimeFormatter -from .safetime import (safe_fromtimestamp, datetime, timedelta, EPOCH, - MINYEAR, MAXYEAR) +from .safetime import safe_fromtimestamp, datetime, timedelta, EPOCH, MINYEAR, MAXYEAR # Labels for date and time units. -datetime_scale = ["microsecond", "second", "minute", "hour", - "day", "month", "year"] +datetime_scale = ["microsecond", "second", "minute", "hour", "day", "month", "year"] datetime_zeros = list(zip(datetime_scale, [0, 0, 0, 0, 1, 1, 1])) -__all__ = ["TimeScale", "CalendarScaleSystem", "HMSScales", "MDYScales", - "trange", "tfrac", "td_to_sec", "dt_to_sec"] +__all__ = [ + "TimeScale", + "CalendarScaleSystem", + "HMSScales", + "MDYScales", + "trange", + "tfrac", + "td_to_sec", + "dt_to_sec", +] def td_to_sec(td): - """ Returns the floating point number of seconds in a timedelta object. - """ + """Returns the floating point number of seconds in a timedelta object.""" return td.days * 24 * 3600 + td.seconds + td.microseconds * 1e-6 def dt_to_sec(t): - """ Returns the floating point number of seconds since the UNIX epoch + """Returns the floating point number of seconds since the UNIX epoch corresponding to the given datetime instance. This value is more accurate than mktime(t.timetuple()) because it @@ -36,7 +41,7 @@ def dt_to_sec(t): def tfrac(t, **time_unit): - """ Performs a calendar-aware split of a time into (aligned_time, frac) + """Performs a calendar-aware split of a time into (aligned_time, frac) over an interval that is a multiple of one of the following time units: "microseconds" "milliseconds", "seconds", "minutes", "hours", "days", "years" @@ -68,7 +73,9 @@ def tfrac(t, **time_unit): """ time_units = list(time_unit.items()) if len(time_unit) > 1: - raise ValueError("tfrac() only takes one keyword argument, got %d" % len(time_units)) + raise ValueError( + "tfrac() only takes one keyword argument, got %d" % len(time_units) + ) unit, period = time_units[0] if unit == "milliseconds": unit = "microsecond" @@ -90,24 +97,26 @@ def tfrac(t, **time_unit): return dt_to_sec(whole), frac + def _advance_month(dt, months): - """ Advance a datetime object by a given number of months. - """ + """Advance a datetime object by a given number of months.""" new_month = dt.month + months - years, extra_months = divmod(new_month-1, 12) + years, extra_months = divmod(new_month - 1, 12) new_month = extra_months + 1 - return dt.replace(year=dt.year+years, month=new_month) + return dt.replace(year=dt.year + years, month=new_month) + def trange_months(start, end, months): - """ Create a range of timestamps separated by a given number of months. + """Create a range of timestamps separated by a given number of months. The start of the iteration is always aligned to Jan 1 2000. """ dt_start = safe_fromtimestamp(start) dt_end = safe_fromtimestamp(end) dmonths = (12 * (dt_start.year - 2000) + dt_start.month - 1) % months - dt = _advance_month(dt_start.replace(day=1, hour=0, minute=0, second=0, - microsecond=0), -dmonths) + dt = _advance_month( + dt_start.replace(day=1, hour=0, minute=0, second=0, microsecond=0), -dmonths + ) while dt < dt_start: dt = _advance_month(dt, months) timestamps = [] @@ -116,13 +125,14 @@ def trange_months(start, end, months): dt = _advance_month(dt, months) return timestamps + def _advance_years(dt, years): - """ Advance a datetime object by a given number of years. - """ - return dt.replace(year=dt.year+years) + """Advance a datetime object by a given number of years.""" + return dt.replace(year=dt.year + years) + def trange_years(start, end, years): - """ Create a range of timestamps separated by a given number of years. + """Create a range of timestamps separated by a given number of years. The start of the iteration is aligned to Jan 1 2000. """ @@ -131,7 +141,7 @@ def trange_years(start, end, years): dyears = (dt_start.year - 2000) % years if dyears < 0: dyears += years - dt = datetime(dt_start.year-dyears, 1, 1, 0, 0, 0, 0) + dt = datetime(dt_start.year - dyears, 1, 1, 0, 0, 0, 0) while dt < dt_start: dt = _advance_years(dt, years) timestamps = [] @@ -140,8 +150,9 @@ def trange_years(start, end, years): dt = _advance_years(dt, years) return timestamps + def trange(start, end, **time_unit): - """ Like range(), but for times, and with "natural" alignment depending on + """Like range(), but for times, and with "natural" alignment depending on the interval. For example:: @@ -166,13 +177,15 @@ def trange(start, end, **time_unit): time_units = list(time_unit.items()) if len(time_units) != 1: - raise ValueError("trange() only takes one keyword argument, got %d" % len(time_units)) + raise ValueError( + "trange() only takes one keyword argument, got %d" % len(time_units) + ) # Months and years are non-uniform, so we special-case them. unit, value = time_units[0] - if unit == 'months': + if unit == "months": return trange_months(start, end, value) - elif unit == 'years': + elif unit == "years": return trange_years(start, end, value) # Express start and end ticks as (date, frac) where date is calendar-aligned @@ -190,18 +203,20 @@ def trange(start, end, **time_unit): first_tick_ndx = 1 # Convert months and years into days - time_unit["days"] = time_unit.setdefault("days", 0) + \ - 365 * time_unit.pop("years", 0) + \ - 30 * time_unit.pop("months", 0) + time_unit["days"] = ( + time_unit.setdefault("days", 0) + + 365 * time_unit.pop("years", 0) + + 30 * time_unit.pop("months", 0) + ) delta = td_to_sec(timedelta(**time_unit)) count = (end_whole - start_whole) / delta - ticks = [start_whole + i*delta for i in range(int(round(count))+1)] + ticks = [start_whole + i * delta for i in range(int(round(count)) + 1)] return ticks[first_tick_ndx:] class TimeScale(AbstractScale): - """ A scale based on time intervals and calendar dates. The valid + """A scale based on time intervals and calendar dates. The valid intervals are: Natural time: @@ -214,22 +229,22 @@ class TimeScale(AbstractScale): """ # This is used to compute an approximate resolution for each type of scale. - SECS_PER_UNIT = {"microseconds": 1e-6, - "milliseconds": 1e-3, - "seconds": 1, - "minutes": 60, - "hours": 3600, - "days": 24*3600, - "day_of_month": 30*24*3600, - "month_of_year": 365*24*3600, - "years": 365*24*3600, - } + SECS_PER_UNIT = { + "microseconds": 1e-6, + "milliseconds": 1e-3, + "seconds": 1, + "minutes": 60, + "hours": 3600, + "days": 24 * 3600, + "day_of_month": 30 * 24 * 3600, + "month_of_year": 365 * 24 * 3600, + "years": 365 * 24 * 3600, + } CALENDAR_UNITS = ("day_of_month", "month_of_year") def __init__(self, **kw_interval): - """ Defines the time period that this scale uses. - """ + """Defines the time period that this scale uses.""" self.formatter = kw_interval.pop("formatter", TimeFormatter()) unit, val = list(kw_interval.items())[0] self.unit = unit @@ -245,7 +260,7 @@ def __init__(self, **kw_interval): self.resolution = val * self.SECS_PER_UNIT[unit] def num_ticks(self, start, end, desired_ticks=None): - """ Returns an approximate number of ticks that this scale + """Returns an approximate number of ticks that this scale produces for the given interval. Implements AbstractScale. @@ -259,7 +274,7 @@ def num_ticks(self, start, end, desired_ticks=None): return (end - start) / self.resolution def ticks(self, start, end, desired_ticks=None): - """ Returns the set of "nice" positions on this scale that enclose and + """Returns the set of "nice" positions on this scale that enclose and fall inside the interval (*start*,*end*). Implements AbstractScale. The *start* and *end* parameters are @@ -277,8 +292,9 @@ def ticks(self, start, end, desired_ticks=None): if desired_ticks is None: min, max, delta = heckbert_interval(start, end, enclose=True) else: - min, max, delta = heckbert_interval(start, end, desired_ticks, - enclose=True) + min, max, delta = heckbert_interval( + start, end, desired_ticks, enclose=True + ) min *= secs_per_unit max *= secs_per_unit delta *= secs_per_unit @@ -302,18 +318,21 @@ def cal_ticks(self, start, end): # get range of years of interest # add 2 because of python ranges + guard against timezone shifts # eg. if 20000101 -> 19991231 because of local timezone, end is 1999+2 - years = range(start_dt.year, min(end_dt.year+2, MAXYEAR+1)) + years = range(start_dt.year, min(end_dt.year + 2, MAXYEAR + 1)) if self.unit == "day_of_month": # get naive datetimes for start of each day of each month # in range of years. Excess will be discarded later. months = range(1, 13) - dates = [datetime(year, month, i) - for year in years for month in months for i in self.vals] + dates = [ + datetime(year, month, i) + for year in years + for month in months + for i in self.vals + ] elif self.unit == "month_of_year": # get naive datetimes for start of each month in range of years - dates = [datetime(year, month, 1) - for year in years for month in self.vals] + dates = [datetime(year, month, 1) for year in years for month in self.vals] else: raise ValueError("Unknown calendar unit '%s'" % self.unit) @@ -326,54 +345,58 @@ def cal_ticks(self, start, end): return ticks def labels(self, start, end, numlabels=None, char_width=None): - """ Returns a series of ticks and corresponding strings for labels + """Returns a series of ticks and corresponding strings for labels that fall inside the interval (*start*,*end*). Overrides AbstractScale. """ ticks = self.ticks(start, end, numlabels) - labels = self.formatter.format(ticks, numlabels, char_width, - ticker=self) + labels = self.formatter.format(ticks, numlabels, char_width, ticker=self) return list(zip(ticks, labels)) def label_width(self, start, end, numlabels=None, char_width=None): - """ Returns an estimate of total number of characters used by the + """Returns an estimate of total number of characters used by the the labels that this scale will produce for the given set of inputs, as well as the number of labels. Overrides AbstractScale. """ - return self.formatter.estimate_width(start, end, numlabels, char_width, - ticker=self) + return self.formatter.estimate_width( + start, end, numlabels, char_width, ticker=self + ) # Declare some default scale systems # Default time scale for hours, minutes, seconds, and milliseconds. -HMSScales = [TimeScale(microseconds=1), TimeScale(milliseconds=1)] + \ - [TimeScale(seconds=dt) for dt in (1, 5, 15, 30)] + \ - [TimeScale(minutes=dt) for dt in (1, 5, 15, 30)] + \ - [TimeScale(hours=dt) for dt in (1, 2, 3, 4, 6, 12, 24)] +HMSScales = ( + [TimeScale(microseconds=1), TimeScale(milliseconds=1)] + + [TimeScale(seconds=dt) for dt in (1, 5, 15, 30)] + + [TimeScale(minutes=dt) for dt in (1, 5, 15, 30)] + + [TimeScale(hours=dt) for dt in (1, 2, 3, 4, 6, 12, 24)] +) # Default time scale for months, days, and years. -MDYScales = [TimeScale(day_of_month=list(range(1,31,3))), - TimeScale(day_of_month=(1,8,15,22)), - TimeScale(day_of_month=(1,15)), - TimeScale(month_of_year=list(range(1,13))), - TimeScale(month_of_year=list(range(1,13,3))), - TimeScale(month_of_year=(1,7)), - TimeScale(month_of_year=(1,)),] + \ - [TimeScale(years=dt) for dt in (1,2,5,10)] +MDYScales = [ + TimeScale(day_of_month=list(range(1, 31, 3))), + TimeScale(day_of_month=(1, 8, 15, 22)), + TimeScale(day_of_month=(1, 15)), + TimeScale(month_of_year=list(range(1, 13))), + TimeScale(month_of_year=list(range(1, 13, 3))), + TimeScale(month_of_year=(1, 7)), + TimeScale(month_of_year=(1,)), +] + [TimeScale(years=dt) for dt in (1, 2, 5, 10)] + class CalendarScaleSystem(ScaleSystem): - """ Scale system for calendars. + """Scale system for calendars. This class has a pre-defined set of nice "time points" to use for ticking and labelling. """ def __init__(self, *scales, **kw): - """ Creates a new CalendarScaleSystem. + """Creates a new CalendarScaleSystem. If scales are not provided, then it defaults to HMSScales and MDYScales. """ @@ -386,8 +409,9 @@ def _get_scale(self, start, end, numticks): if self.default_scale is not None: closest_scale = self.default_scale else: - raise ValueError("CalendarScaleSystem has not be configured " - "with any scales.") + raise ValueError( + "CalendarScaleSystem has not be configured " "with any scales." + ) elif end - start < 1e-6 or end - start > 1e5 * 365 * 24 * 3600: closest_scale = self.default_scale else: diff --git a/chaco/scales_tick_generator.py b/chaco/scales_tick_generator.py index 9c8679b80..be60daf3a 100644 --- a/chaco/scales_tick_generator.py +++ b/chaco/scales_tick_generator.py @@ -14,23 +14,34 @@ class ScalesTickGenerator(AbstractTickGenerator): - scale = Any #Instance(ScaleSystem, args=()) + scale = Any # Instance(ScaleSystem, args=()) font = Any def _scale_default(self): return ScaleSystem() - def get_ticks(self, data_low, data_high, bounds_low, bounds_high, interval, - use_endpoints=False, scale=None): + def get_ticks( + self, + data_low, + data_high, + bounds_low, + bounds_high, + interval, + use_endpoints=False, + scale=None, + ): if interval != "auto": - ticks = self.scale.ticks(data_low, data_high, (data_high - data_low) / interval) + ticks = self.scale.ticks( + data_low, data_high, (data_high - data_low) / interval + ) else: ticks = self.scale.ticks(data_low, data_high) return ticks - def get_ticks_and_labels(self, data_low, data_high, bounds_low, bounds_high, - orientation = "h"): + def get_ticks_and_labels( + self, data_low, data_high, bounds_low, bounds_high, orientation="h" + ): # TODO: add support for Interval # TODO: add support for vertical labels metrics = font_metrics_provider() @@ -39,8 +50,13 @@ def get_ticks_and_labels(self, data_low, data_high, bounds_low, bounds_high, test_str = "0123456789-+" charsize = metrics.get_full_text_extent(test_str)[0] / len(test_str) numchars = (bounds_high - bounds_low) / charsize - tmp = list(zip(*self.scale.labels(data_low, data_high, numlabels=8, - char_width=numchars))) + tmp = list( + zip( + *self.scale.labels( + data_low, data_high, numlabels=8, char_width=numchars + ) + ) + ) # Check to make sure we actually have labels/ticks to show before # unpacking the return tuple into (tick_array, labels). if len(tmp) == 0: diff --git a/chaco/scatter_inspector_overlay.py b/chaco/scatter_inspector_overlay.py index 9f96ee4ef..14ac13342 100644 --- a/chaco/scatter_inspector_overlay.py +++ b/chaco/scatter_inspector_overlay.py @@ -1,6 +1,3 @@ - - - # Major library imports from numpy import array, asarray @@ -13,6 +10,7 @@ from .abstract_overlay import AbstractOverlay from .scatterplot import render_markers + class ScatterInspectorOverlay(AbstractOverlay): """ Highlights points on a scatterplot as the mouse moves over them. @@ -23,7 +21,7 @@ class ScatterInspectorOverlay(AbstractOverlay): """ #: The style to use when a point is hovered over - hover_metadata_name = Str('hover') + hover_metadata_name = Str("hover") hover_marker = Trait(None, None, MarkerTrait) hover_marker_size = Trait(None, None, Int) hover_line_width = Trait(None, None, Float) @@ -31,7 +29,7 @@ class ScatterInspectorOverlay(AbstractOverlay): hover_outline_color = Trait(None, None, ColorTrait) #: The style to use when a point has been selected by a click - selection_metadata_name = Str('selections') + selection_metadata_name = Str("selections") selection_marker = Trait(None, None, MarkerTrait) selection_marker_size = Trait(None, None, Int) selection_line_width = Trait(None, None, Float) @@ -41,7 +39,7 @@ class ScatterInspectorOverlay(AbstractOverlay): # For now, implement the equivalent of this Traits 3 feature manually # using a series of trait change handlers (defined at the end of the # class) - #@on_trait_change('component.index.metadata_changed,component.value.metadata_changed') + # @on_trait_change('component.index.metadata_changed,component.value.metadata_changed') def metadata_updated(self, event): if self.component is not None: self.component.request_redraw() @@ -53,7 +51,7 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): for inspect_type in (self.hover_metadata_name, self.selection_metadata_name): if inspect_type in plot.index.metadata: - #if hasattr(plot,"value") and not inspect_type in plot.value.metadata: + # if hasattr(plot,"value") and not inspect_type in plot.value.metadata: # continue index = plot.index.metadata.get(inspect_type, None) @@ -68,13 +66,14 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): # selection model, we will only use the selection on the # index. The assumption that they are the same is # implicit, though unchecked, already. - #value = plot.value.metadata.get(inspect_type, None) + # value = plot.value.metadata.get(inspect_type, None) value = index if hasattr(plot, "value"): value_data = plot.value.get_data() - screen_pts = plot.map_screen(array([index_data[index], - value_data[value]]).T) + screen_pts = plot.map_screen( + array([index_data[index], value_data[value]]).T + ) else: screen_pts = plot.map_screen(index_data[index]) @@ -105,7 +104,7 @@ def _render_marker_at_indices(self, gc, screen_pts, prefix, sep="_"): else: valname = attr - tmp = getattr(self, prefix+sep+valname) + tmp = getattr(self, prefix + sep + valname) if tmp is not None: kwargs[attr] = tmp else: @@ -120,15 +119,14 @@ def _render_marker_at_indices(self, gc, screen_pts, prefix, sep="_"): gc.clip_to_rect(plot.x, plot.y, plot.width, plot.height) render_markers(gc, screen_pts, **kwargs) - def _draw_overlay(self, gc, view_bounds=None, mode="normal"): self.overlay(self.component, gc, view_bounds, mode) def _component_changed(self, old, new): if old: - old.observe(self._ds_changed, 'index', remove=True) + old.observe(self._ds_changed, "index", remove=True) if hasattr(old, "value"): - old.observe(self._ds_changed, 'value', remove=True) + old.observe(self._ds_changed, "value", remove=True) if new: for dsname in ("index", "value"): if not hasattr(new, dsname): @@ -137,16 +135,13 @@ def _component_changed(self, old, new): if getattr(new, dsname): self._ds_changed( TraitChangeEvent( - object=new, - name=dsname, - old=None, - new=getattr(new, dsname) + object=new, name=dsname, old=None, new=getattr(new, dsname) ) ) def _ds_changed(self, event): old, new = event.old, event.new if old: - old.observe(self.metadata_updated, 'metadata_changed', remove=True) + old.observe(self.metadata_updated, "metadata_changed", remove=True) if new: - new.observe(self.metadata_updated, 'metadata_changed') + new.observe(self.metadata_updated, "metadata_changed") diff --git a/chaco/scatter_markers.py b/chaco/scatter_markers.py index b76fbe972..ed0449576 100644 --- a/chaco/scatter_markers.py +++ b/chaco/scatter_markers.py @@ -2,16 +2,34 @@ # have since been moved to the enable.markers module. from enable.compiled_path import CompiledPath -from enable.markers import AbstractMarker, SquareMarker, \ - CircleMarker, TriangleMarker, Inverted_TriangleMarker, PlusMarker, \ - CrossMarker, DiamondMarker, DotMarker, PixelMarker, CustomMarker, \ - marker_trait, MarkerNameDict, marker_names - -from kiva.constants import STROKE, FILL_STROKE, \ - SQUARE_MARKER, DIAMOND_MARKER, CIRCLE_MARKER, \ - CROSS_MARKER, TRIANGLE_MARKER, \ - INVERTED_TRIANGLE_MARKER, PLUS_MARKER, DOT_MARKER, \ - PIXEL_MARKER, NO_MARKER - - +from enable.markers import ( + AbstractMarker, + SquareMarker, + CircleMarker, + TriangleMarker, + Inverted_TriangleMarker, + PlusMarker, + CrossMarker, + DiamondMarker, + DotMarker, + PixelMarker, + CustomMarker, + marker_trait, + MarkerNameDict, + marker_names, +) +from kiva.constants import ( + STROKE, + FILL_STROKE, + SQUARE_MARKER, + DIAMOND_MARKER, + CIRCLE_MARKER, + CROSS_MARKER, + TRIANGLE_MARKER, + INVERTED_TRIANGLE_MARKER, + PLUS_MARKER, + DOT_MARKER, + PIXEL_MARKER, + NO_MARKER, +) diff --git a/chaco/scatterplot.py b/chaco/scatterplot.py index 436ed6414..1c1398cbc 100644 --- a/chaco/scatterplot.py +++ b/chaco/scatterplot.py @@ -6,15 +6,43 @@ import itertools # Major library imports -from numpy import around, array, asarray, column_stack, \ - isfinite, isnan, nanargmin, ndarray, sqrt, sum, transpose, where +from numpy import ( + around, + array, + asarray, + column_stack, + isfinite, + isnan, + nanargmin, + ndarray, + sqrt, + sum, + transpose, + where, +) # Enthought library imports -from enable.api import black_color_trait, ColorTrait, AbstractMarker, \ - CustomMarker, MarkerNameDict, MarkerTrait +from enable.api import ( + black_color_trait, + ColorTrait, + AbstractMarker, + CustomMarker, + MarkerNameDict, + MarkerTrait, +) from kiva.constants import STROKE -from traits.api import Any, Array, ArrayOrNone, Bool, Float, Callable, \ - Property, Tuple, Either, cached_property +from traits.api import ( + Any, + Array, + ArrayOrNone, + Bool, + Float, + Callable, + Property, + Tuple, + Either, + cached_property, +) from traitsui.api import View, VGroup, Item # Local relative imports @@ -22,31 +50,42 @@ from .speedups import scatterplot_gather_points from .base import reverse_map_1d -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Traits UI View for customizing a scatter plot. -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ + class ScatterPlotView(View): - """ Traits UI View for customizing a scatter plot. - """ + """Traits UI View for customizing a scatter plot.""" + def __init__(self): vgroup = VGroup( - Item("marker", label="Marker type"), - Item("marker_size", label="Size"), - Item("color", label="Color", style="custom"), - ) + Item("marker", label="Marker type"), + Item("marker_size", label="Size"), + Item("color", label="Color", style="custom"), + ) super(ScatterPlotView, self).__init__(vgroup) self.buttons = ["OK", "Cancel"] -#------------------------------------------------------------------------------ -# Helper functions for scatterplot rendering -#------------------------------------------------------------------------------ - -def render_markers(gc, points, marker, marker_size, - color, line_width, outline_color, - custom_symbol=None, debug=False, point_mask=None): - """ Helper function for a PlotComponent instance to render a +# ------------------------------------------------------------------------------ +# Helper functions for scatterplot rendering +# ------------------------------------------------------------------------------ + + +def render_markers( + gc, + points, + marker, + marker_size, + color, + line_width, + outline_color, + custom_symbol=None, + debug=False, + point_mask=None, +): + """Helper function for a PlotComponent instance to render a set of (x,y) points onto a graphics context. Currently, it makes some assumptions about the attributes on the plot object; these may be factored out eventually. @@ -104,14 +143,14 @@ def render_markers(gc, points, marker, marker_size, # try fastest routine if not isinstance(marker, CustomMarker): # get fast renderer, or dummy if not implemented - renderer = getattr(gc, 'draw_marker_at_points', lambda *a: 0) + renderer = getattr(gc, "draw_marker_at_points", lambda *a: 0) result = renderer(points, marker_size, marker.kiva_marker) # it worked, we're done if result != 0: return # try next fastest routine - if hasattr(gc, 'draw_path_at_points'): + if hasattr(gc, "draw_path_at_points"): if not isinstance(marker, CustomMarker): path = gc.get_empty_path() marker.add_to_path(path, marker_size) @@ -133,7 +172,7 @@ def render_markers(gc, points, marker, marker_size, if not marker.antialias: gc.set_antialias(False) if not isinstance(marker, CustomMarker): - for pt,size in zip(points, marker_size): + for pt, size in zip(points, marker_size): sx, sy = pt with gc: gc.translate_ctm(sx, sy) @@ -142,7 +181,7 @@ def render_markers(gc, points, marker, marker_size, gc.draw_path(marker.draw_mode) else: path = custom_symbol - for pt,size in zip(points, marker_size): + for pt, size in zip(points, marker_size): sx, sy = pt with gc: gc.translate_ctm(sx, sy) @@ -150,9 +189,10 @@ def render_markers(gc, points, marker, marker_size, gc.add_path(path) gc.draw_path(STROKE) -#------------------------------------------------------------------------------ + +# ------------------------------------------------------------------------------ # The scatter plot -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ class ScatterPlot(BaseXYPlot): @@ -166,9 +206,9 @@ class ScatterPlot(BaseXYPlot): # the right thing. custom_symbol = Any - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Styles on a ScatterPlot - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The type of marker to use. This is a mapped trait using strings as the # keys. @@ -195,24 +235,23 @@ class ScatterPlot(BaseXYPlot): # The RGBA tuple for rendering lines. It is always a tuple of length 4. # It has the same RGB values as color_, and its alpha value is the alpha # value of self.color multiplied by self.alpha. - effective_color = Property(Tuple, depends_on=['color', 'alpha']) + effective_color = Property(Tuple, depends_on=["color", "alpha"]) # The RGBA tuple for rendering the fill. It is always a tuple of length 4. # It has the same RGB values as outline_color_, and its alpha value is the # alpha value of self.outline_color multiplied by self.alpha. - effective_outline_color = Property(Tuple, depends_on=['outline_color', 'alpha']) - + effective_outline_color = Property(Tuple, depends_on=["outline_color", "alpha"]) # Traits UI View for customizing the plot. traits_view = ScatterPlotView() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Selection and selection rendering # A selection on the lot is indicated by setting the index or value # datasource's 'selections' metadata item to a list of indices, or the # 'selection_mask' metadata to a boolean array of the same length as the # datasource. - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ show_selection = Bool(True) @@ -226,9 +265,9 @@ class ScatterPlot(BaseXYPlot): selection_outline_color = black_color_trait - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ _cached_selected_pts = ArrayOrNone _cached_selected_screen_pts = Array @@ -236,12 +275,12 @@ class ScatterPlot(BaseXYPlot): _cached_selection_point_mask = Array _selection_cache_valid = Bool(False) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Overridden PlotRenderer methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def map_screen(self, data_array): - """ Maps an array of data points into screen space and returns it as + """Maps an array of data points into screen space and returns it as an array. Implements the AbstractPlotRenderer interface. @@ -266,20 +305,20 @@ def map_screen(self, data_array): return column_stack([sy, sx]) def map_data(self, screen_pt, all_values=True): - """ Maps a screen space point into the "index" space of the plot. + """Maps a screen space point into the "index" space of the plot. Overrides the BaseXYPlot implementation, and always returns an array of (index, value) tuples. """ x, y = screen_pt - if self.orientation == 'v': + if self.orientation == "v": x, y = y, x - return array((self.index_mapper.map_data(x), - self.value_mapper.map_data(y))) + return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) - def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, \ - index_only = False): - """ Maps a screen space point to an index into the plot's index array(s). + def map_index( + self, screen_pt, threshold=0.0, outside_returns_none=True, index_only=False + ): + """Maps a screen space point to an index into the plot's index array(s). Overrides the BaseXYPlot implementation.. """ @@ -294,8 +333,10 @@ def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, \ # The rest of this was copied out of BaseXYPlot. # We can't just used BaseXYPlot.map_index because # it expect map_data to return a value, not a pair. - if ((data_pt < self.index_mapper.range.low) or \ - (data_pt > self.index_mapper.range.high)) and outside_returns_none: + if ( + (data_pt < self.index_mapper.range.low) + or (data_pt > self.index_mapper.range.high) + ) and outside_returns_none: return None try: @@ -319,8 +360,8 @@ def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, \ y = value_data[ndx] if isnan(x) or isnan(y): return None - sx, sy = self.map_screen([x,y]) - if ((threshold == 0.0) or (screen_pt[0]-sx) < threshold): + sx, sy = self.map_screen([x, y]) + if (threshold == 0.0) or (screen_pt[0] - sx) < threshold: return ndx else: return None @@ -331,20 +372,19 @@ def map_index(self, screen_pt, threshold=0.0, outside_returns_none=True, \ if len(screen_points) == 0: return None if index_only: - distances = abs(screen_points[:,0] - screen_pt[0]) + distances = abs(screen_points[:, 0] - screen_pt[0]) else: delta = screen_points - array([screen_pt]) - distances = sqrt(sum(delta*delta, axis=1)) + distances = sqrt(sum(delta * delta, axis=1)) closest_ndx = nanargmin(distances) if distances[closest_ndx] <= threshold: return closest_ndx else: return None - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods; implements the BaseXYPlot stub methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _gather_points_old(self): """ @@ -369,8 +409,7 @@ def _gather_points_old(self): index_range_mask = self.index_mapper.range.mask_data(index) value_range_mask = self.value_mapper.range.mask_data(value) - nan_mask = (isfinite(index) & index_mask & - isfinite(value) & value_mask) + nan_mask = isfinite(index) & index_mask & isfinite(value) & value_mask point_mask = nan_mask & index_range_mask & value_range_mask if not self._cache_valid: @@ -392,17 +431,17 @@ def _gather_points_old(self): # and this will fall out... point_mask = point_mask.copy() for ds in (self.index, self.value): - if ds.metadata.get('selection_masks', None) is not None: + if ds.metadata.get("selection_masks", None) is not None: try: - for mask in ds.metadata['selection_masks']: + for mask in ds.metadata["selection_masks"]: point_mask &= mask indices = where(point_mask == True) points = column_stack([index[indices], value[indices]]) except: continue - elif ds.metadata.get('selections', None) is not None: + elif ds.metadata.get("selections", None) is not None: try: - indices = ds.metadata['selections'] + indices = ds.metadata["selections"] point_mask = point_mask[indices] points = column_stack([index[indices], value[indices]]) except: @@ -434,16 +473,22 @@ def _gather_points_fast(self): kw = {} for axis in ("index", "value"): ds = getattr(self, axis) - if ds.metadata.get('selections', None) is not None: - kw[axis + "_sel"] = ds.metadata['selections'] - if ds.metadata.get('selection_mask', None) is not None: - kw[axis + "_sel_mask"] = ds.metadata['selection_mask'] - - points, selections = scatterplot_gather_points(index, index_range.low, index_range.high, - value, value_range.low, value_range.high, - index_mask = index_mask, - value_mask = value_mask, - **kw) + if ds.metadata.get("selections", None) is not None: + kw[axis + "_sel"] = ds.metadata["selections"] + if ds.metadata.get("selection_mask", None) is not None: + kw[axis + "_sel_mask"] = ds.metadata["selection_mask"] + + points, selections = scatterplot_gather_points( + index, + index_range.low, + index_range.high, + value, + value_range.low, + value_range.high, + index_mask=index_mask, + value_mask=value_mask, + **kw + ) if not self._cache_valid: self._cached_data_pts = points @@ -457,9 +502,8 @@ def _gather_points_fast(self): self._cached_selected_pts = None self._selection_cache_valid = True - def _gather_points(self): - #self._gather_points_fast() + # self._gather_points_fast() self._gather_points_old() def _render(self, gc, points, icon_mode=False): @@ -473,16 +517,31 @@ def _render(self, gc, points, icon_mode=False): gc.save_state() gc.clip_to_rect(self.x, self.y, self.width, self.height) - self.render_markers_func(gc, points, self.marker, self.marker_size, - self.effective_color, self.line_width, self.effective_outline_color, - self.custom_symbol, point_mask=self._cached_point_mask) + self.render_markers_func( + gc, + points, + self.marker, + self.marker_size, + self.effective_color, + self.line_width, + self.effective_outline_color, + self.custom_symbol, + point_mask=self._cached_point_mask, + ) if self._cached_selected_pts is not None and len(self._cached_selected_pts) > 0: sel_pts = self.map_screen(self._cached_selected_pts) - self.render_markers_func(gc, sel_pts, self.selection_marker, - self.selection_marker_size, self.selection_color_, - self.selection_line_width, self.selection_outline_color_, - self.custom_symbol, point_mask=self._cached_point_mask) + self.render_markers_func( + gc, + sel_pts, + self.selection_marker, + self.selection_marker_size, + self.selection_color_, + self.selection_line_width, + self.selection_outline_color_, + self.custom_symbol, + point_mask=self._cached_point_mask, + ) if not icon_mode: # Draw the default axes, if necessary @@ -490,12 +549,12 @@ def _render(self, gc, points, icon_mode=False): gc.restore_state() def _render_icon(self, gc, x, y, width, height): - point = array([x+width/2, y+height/2]) + point = array([x + width / 2, y + height / 2]) self._render(gc, [point], icon_mode=True) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _alpha_changed(self): self.invalidate_draw() @@ -529,16 +588,16 @@ def _either_metadata_updated(self, event): self.invalidate_draw() self.request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Defaults - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _marker_size_default(self): return 4.0 - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Properties - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @cached_property def _get_effective_color(self): diff --git a/chaco/scatterplot_1d.py b/chaco/scatterplot_1d.py index 7efb8398a..68e0c00c1 100644 --- a/chaco/scatterplot_1d.py +++ b/chaco/scatterplot_1d.py @@ -3,8 +3,6 @@ """ - - from numpy import empty # Enthought library imports @@ -45,13 +43,13 @@ class ScatterPlot1D(Base1DPlot): # The color of the outline to draw around the marker. outline_color = black_color_trait - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Selection and selection rendering # A selection on the lot is indicated by setting the index or value # datasource's 'selections' metadata item to a list of indices, or the # 'selection_mask' metadata to a boolean array of the same length as the # datasource. - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: the plot data metadata name to watch for selection information selection_metadata_name = Str("selections") @@ -89,12 +87,11 @@ class ScatterPlot1D(Base1DPlot): #: private trait holding postion of markers relative to non-index direction _marker_position = Float - def _draw_plot(self, gc, view_bounds=None, mode="normal"): coord = self._compute_screen_coord() pts = empty(shape=(len(coord), 2)) - if self.orientation == 'v': + if self.orientation == "v": pts[:, 1] = coord pts[:, 0] = self._marker_position else: @@ -120,19 +117,38 @@ def _render(self, gc, pts): outline_color = list(self.outline_color_) outline_color[3] *= self.unselected_alpha if unselected_pts.size > 0: - self.render_markers_func(gc, unselected_pts, self.marker, - self.marker_size, tuple(color), - self.unselected_line_width, tuple(outline_color), - self.custom_symbol) + self.render_markers_func( + gc, + unselected_pts, + self.marker, + self.marker_size, + tuple(color), + self.unselected_line_width, + tuple(outline_color), + self.custom_symbol, + ) if selected_pts.size > 0: - self.render_markers_func(gc, selected_pts, self.marker, - self.marker_size, self.selection_color_, - self.line_width, self.outline_color_, - self.custom_symbol) + self.render_markers_func( + gc, + selected_pts, + self.marker, + self.marker_size, + self.selection_color_, + self.line_width, + self.outline_color_, + self.custom_symbol, + ) else: - self.render_markers_func(gc, pts, self.marker, - self.marker_size, self.color_, self.line_width, - self.outline_color_, self.custom_symbol) + self.render_markers_func( + gc, + pts, + self.marker, + self.marker_size, + self.color_, + self.line_width, + self.outline_color_, + self.custom_symbol, + ) def __marker_positon_default(self): return self._get_marker_position() @@ -141,14 +157,14 @@ def _get_marker_position(self): x, y = self.position w, h = self.bounds - if self.orientation == 'v': + if self.orientation == "v": y, h = x, w - if self.alignment == 'center': - position = y + h/2.0 - elif self.alignment in ['left', 'bottom']: + if self.alignment == "center": + position = y + h / 2.0 + elif self.alignment in ["left", "bottom"]: position = y - elif self.alignment in ['right', 'top']: + elif self.alignment in ["right", "top"]: position = y + h position += self.marker_offset diff --git a/chaco/segment_plot.py b/chaco/segment_plot.py index e7c75533e..fff539142 100644 --- a/chaco/segment_plot.py +++ b/chaco/segment_plot.py @@ -3,7 +3,15 @@ from enable.api import ColorTrait, LineStyle, black_color_trait from kiva.api import CAP_ROUND from traits.api import ( - Array, Bool, Enum, Float, Instance, Property, Str, cached_property, observe + Array, + Bool, + Enum, + Float, + Instance, + Property, + Str, + cached_property, + observe, ) from chaco.abstract_colormap import AbstractColormap @@ -40,10 +48,10 @@ class SegmentPlot(BaseXYPlot): #: For non-linear segments, the tangent at the start matches the #: orientation of the plot (ie. horizontal orientation means #: a horizontal tangent). - render_style = Enum('line', 'orthogonal', 'quad', 'cubic') + render_style = Enum("line", "orthogonal", "quad", "cubic") #: When rendering certain styles, which orientation to prefer. - render_orientation = Enum('index', 'value') + render_orientation = Enum("index", "value") #: Whether to draw segments using a constant color or colormapped data. color_by_data = Bool(False) @@ -73,7 +81,7 @@ class SegmentPlot(BaseXYPlot): selection_metadata_name = Str("selections") #: The color to use for selected segments. Not used if color by data. - selection_color = ColorTrait('yellow') + selection_color = ColorTrait("yellow") #: The alpha fade to use for non-selected segments. selection_alpha = Float(0.3) @@ -88,20 +96,25 @@ class SegmentPlot(BaseXYPlot): effective_colors = Property( Array, depends_on=[ - 'color_by_data', 'alpha', 'color_mapper.updated', - 'color_data.data_changed', 'alpha', 'selection_mask', - 'selection_color', 'selection_alpha' - ] + "color_by_data", + "alpha", + "color_mapper.updated", + "color_data.data_changed", + "alpha", + "selection_mask", + "selection_color", + "selection_alpha", + ], ) #: The widths of the individual lines in screen units, if mapped to data. #: The values are computed with the width mapper. screen_widths = Property( - Array, depends_on=['width_mapper.updated', 'width_data.data_changed'] + Array, depends_on=["width_mapper.updated", "width_data.data_changed"] ) selected_mask = Property( - depends_on=['selection_metadata_name', 'index.metadata_changed'] + depends_on=["selection_metadata_name", "index.metadata_changed"] ) # These BaseXYPlot methods either don't make sense or aren't currently @@ -120,7 +133,7 @@ def map_index(self, *args, **kwargs): raise NotImplementedError() def _gather_points(self): - """ Collects the data points that are within the bounds of the plot and + """Collects the data points that are within the bounds of the plot and caches them. """ if self._cache_valid: @@ -142,7 +155,7 @@ def _gather_points(self): self._cache_valid = True def _render(self, gc, segments): - """ Render an array of shape (N, 2, 2) of screen-space + """Render an array of shape (N, 2, 2) of screen-space points as a collection of segments. """ @@ -161,18 +174,18 @@ def _render(self, gc, segments): ends = segments[:, 1] starts = starts.ravel().view(point_dtype) ends = ends.ravel().view(point_dtype) - if self.render_style == 'orthogonal': + if self.render_style == "orthogonal": self._render_orthogonal(gc, starts, ends, colors, widths) - elif self.render_style == 'quad': + elif self.render_style == "quad": self._render_quad(gc, starts, ends, colors, widths) - elif self.render_style == 'cubic': + elif self.render_style == "cubic": self._render_cubic(gc, starts, ends, colors, widths) else: self._render_line(gc, starts, ends, colors, widths) def _render_line(self, gc, starts, ends, colors, widths): """ Render straight lines connecting the start point and end point. """ - if len(widths) == 1 and len(colors) == 1 and colors[0]['a'] == 1.0: + if len(widths) == 1 and len(colors) == 1 and colors[0]["a"] == 1.0: # no alpha, can draw a single unconnected path, faster starts = starts.view(float).reshape(-1, 2) ends = ends.view(float).reshape(-1, 2) @@ -181,17 +194,15 @@ def _render_line(self, gc, starts, ends, colors, widths): gc.line_set(starts, ends) gc.stroke_path() else: - for color, width, start, end in np.broadcast( - colors, widths, starts, ends - ): + for color, width, start, end in np.broadcast(colors, widths, starts, ends): gc.set_stroke_color(color) gc.set_line_width(float(width)) - gc.move_to(start['x'], start['y']) - gc.line_to(end['x'], end['y']) + gc.move_to(start["x"], start["y"]) + gc.line_to(end["x"], end["y"]) gc.stroke_path() def _render_orthogonal(self, gc, starts, ends, colors, widths): - """ Render orthogonal lines connecting the start point and end point. + """Render orthogonal lines connecting the start point and end point. Draw the orthogonal line in the direction determined by the orientation. For horizontal orientation, the horizontal segment is @@ -199,22 +210,22 @@ def _render_orthogonal(self, gc, starts, ends, colors, widths): first. """ mids = np.empty(len(starts), dtype=point_dtype) - if self.render_orientation == 'index': - if self.orientation == 'h': - mids['x'] = ends['x'] - mids['y'] = starts['y'] + if self.render_orientation == "index": + if self.orientation == "h": + mids["x"] = ends["x"] + mids["y"] = starts["y"] else: - mids['x'] = starts['x'] - mids['y'] = ends['y'] + mids["x"] = starts["x"] + mids["y"] = ends["y"] else: - if self.orientation == 'h': - mids['x'] = starts['x'] - mids['y'] = ends['y'] + if self.orientation == "h": + mids["x"] = starts["x"] + mids["y"] = ends["y"] else: - mids['x'] = ends['x'] - mids['y'] = starts['y'] + mids["x"] = ends["x"] + mids["y"] = starts["y"] - if len(widths) == 1 and len(colors) == 1 and colors[0]['a'] == 1.0: + if len(widths) == 1 and len(colors) == 1 and colors[0]["a"] == 1.0: # no alpha, can draw a single unconnected path, faster starts = starts.view(float).reshape(-1, 2) mids = mids.view(float).reshape(-1, 2) @@ -230,13 +241,13 @@ def _render_orthogonal(self, gc, starts, ends, colors, widths): ): gc.set_stroke_color(color) gc.set_line_width(float(width)) - gc.move_to(start['x'], start['y']) - gc.line_to(mid['x'], mid['y']) - gc.line_to(end['x'], end['y']) + gc.move_to(start["x"], start["y"]) + gc.line_to(mid["x"], mid["y"]) + gc.line_to(end["x"], end["y"]) gc.stroke_path() def _render_quad(self, gc, starts, ends, colors, widths): - """ Render quadratic Bezier curves connecting the start and end points. + """Render quadratic Bezier curves connecting the start and end points. Draw the orthogonal line in the direction determined by the plot orientation. For horizontal orientation, the start point tangent is @@ -244,28 +255,28 @@ def _render_quad(self, gc, starts, ends, colors, widths): vertical. """ mids = np.empty(len(starts), dtype=point_dtype) - if self.render_orientation == 'index': - if self.orientation == 'h': - mids['x'] = ends['x'] - mids['y'] = starts['y'] + if self.render_orientation == "index": + if self.orientation == "h": + mids["x"] = ends["x"] + mids["y"] = starts["y"] else: - mids['x'] = starts['x'] - mids['y'] = ends['y'] + mids["x"] = starts["x"] + mids["y"] = ends["y"] else: - if self.orientation == 'h': - mids['x'] = starts['x'] - mids['y'] = ends['y'] + if self.orientation == "h": + mids["x"] = starts["x"] + mids["y"] = ends["y"] else: - mids['x'] = ends['x'] - mids['y'] = starts['y'] + mids["x"] = ends["x"] + mids["y"] = starts["y"] - if len(widths) == 1 and len(colors) == 1 and colors[0]['a'] == 1.0: + if len(widths) == 1 and len(colors) == 1 and colors[0]["a"] == 1.0: # no alpha, can draw a single unconnected path, faster gc.set_line_width(widths[0]) gc.set_stroke_color(colors[0]) for start, end, mid in np.broadcast(starts, ends, mids): - gc.move_to(start['x'], start['y']) - gc.quad_curve_to(mid['x'], mid['y'], end['x'], end['y']) + gc.move_to(start["x"], start["y"]) + gc.quad_curve_to(mid["x"], mid["y"], end["x"], end["y"]) gc.stroke_path() else: for color, width, start, end, mid in np.broadcast( @@ -273,12 +284,12 @@ def _render_quad(self, gc, starts, ends, colors, widths): ): gc.set_stroke_color(color) gc.set_line_width(float(width)) - gc.move_to(start['x'], start['y']) - gc.quad_curve_to(mid['x'], mid['y'], end['x'], end['y']) + gc.move_to(start["x"], start["y"]) + gc.quad_curve_to(mid["x"], mid["y"], end["x"], end["y"]) gc.stroke_path() def _render_cubic(self, gc, starts, ends, colors, widths): - """ Render quadratic Bezier curves connecting the start and end points. + """Render quadratic Bezier curves connecting the start and end points. Draw the orthogonal line in the direction determined by the plot orientation. For horizontal orientation, the start point and end @@ -287,40 +298,37 @@ def _render_cubic(self, gc, starts, ends, colors, widths): """ mids_1 = np.empty(len(starts), dtype=point_dtype) mids_2 = np.empty(len(starts), dtype=point_dtype) - if self.render_orientation == 'index': - if self.orientation == 'h': - mids_1['x'] = (starts['x'] + ends['x']) / 2 - mids_1['y'] = starts['y'] - mids_2['x'] = mids_1['x'] - mids_2['y'] = ends['y'] + if self.render_orientation == "index": + if self.orientation == "h": + mids_1["x"] = (starts["x"] + ends["x"]) / 2 + mids_1["y"] = starts["y"] + mids_2["x"] = mids_1["x"] + mids_2["y"] = ends["y"] else: - mids_1['x'] = starts['x'] - mids_1['y'] = (starts['y'] + ends['y']) / 2 - mids_2['x'] = ends['x'] - mids_2['y'] = mids_1['y'] + mids_1["x"] = starts["x"] + mids_1["y"] = (starts["y"] + ends["y"]) / 2 + mids_2["x"] = ends["x"] + mids_2["y"] = mids_1["y"] else: - if self.orientation == 'h': - mids_1['x'] = starts['x'] - mids_1['y'] = (starts['y'] + ends['y']) / 2 - mids_2['x'] = ends['x'] - mids_2['y'] = mids_1['y'] + if self.orientation == "h": + mids_1["x"] = starts["x"] + mids_1["y"] = (starts["y"] + ends["y"]) / 2 + mids_2["x"] = ends["x"] + mids_2["y"] = mids_1["y"] else: - mids_1['x'] = (starts['x'] + ends['x']) / 2 - mids_1['y'] = starts['y'] - mids_2['x'] = mids_1['x'] - mids_2['y'] = ends['y'] + mids_1["x"] = (starts["x"] + ends["x"]) / 2 + mids_1["y"] = starts["y"] + mids_2["x"] = mids_1["x"] + mids_2["y"] = ends["y"] - if len(widths) == 1 and len(colors) == 1 and colors[0]['a'] == 1.0: + if len(widths) == 1 and len(colors) == 1 and colors[0]["a"] == 1.0: # no alpha, can draw a single unconnected path, faster gc.set_line_width(widths[0]) gc.set_stroke_color(colors[0]) - for start, end, mid_1, mid_2 in np.broadcast( - starts, ends, mids_1, mids_2 - ): - gc.move_to(start['x'], start['y']) + for start, end, mid_1, mid_2 in np.broadcast(starts, ends, mids_1, mids_2): + gc.move_to(start["x"], start["y"]) gc.curve_to( - mid_1['x'], mid_1['y'], mid_2['x'], mid_2['y'], end['x'], - end['y'] + mid_1["x"], mid_1["y"], mid_2["x"], mid_2["y"], end["x"], end["y"] ) gc.stroke_path() else: @@ -329,15 +337,14 @@ def _render_cubic(self, gc, starts, ends, colors, widths): ): gc.set_stroke_color(color) gc.set_line_width(float(width)) - gc.move_to(start['x'], start['y']) + gc.move_to(start["x"], start["y"]) gc.curve_to( - mid_1['x'], mid_1['y'], mid_2['x'], mid_2['y'], end['x'], - end['y'] + mid_1["x"], mid_1["y"], mid_2["x"], mid_2["y"], end["x"], end["y"] ) gc.stroke_path() def _render_icon(self, gc, x, y, width, height): - """ Renders a representation of this plot as an icon into the box + """Renders a representation of this plot as an icon into the box defined by the parameters. Used by the legend. @@ -345,14 +352,14 @@ def _render_icon(self, gc, x, y, width, height): with gc: gc.set_stroke_color(self.color_) gc.set_line_width(self.line_width) - if hasattr(self, 'line_style_'): + if hasattr(self, "line_style_"): gc.set_line_dash(self.line_style_) gc.move_to(x, y) gc.line_to(width, height) @observe( - 'alpha, color_data:data_changed, color_mapper:updated, ' - 'width_data:data_changed, width_mapper.updated, +redraw' + "alpha, color_data:data_changed, color_mapper:updated, " + "width_data:data_changed, width_mapper.updated, +redraw" ) def _attributes_updated(self, event): self.invalidate_draw() @@ -366,25 +373,24 @@ def _get_effective_colors(self): else: if self.selected_mask is not None: colors = np.ones((len(self.selected_mask), 4)) - colors[self.selected_mask, :len(self.selection_color_) - ] = self.selection_color_ - colors[~self.selected_mask, :len(self.color_)] = self.color_ + colors[ + self.selected_mask, : len(self.selection_color_) + ] = self.selection_color_ + colors[~self.selected_mask, : len(self.color_)] = self.color_ else: colors = np.ones((1, 4)) - colors[:, :len(self.color_)] = self.color_ + colors[:, : len(self.color_)] = self.color_ if colors.shape[-1] == 4: colors[:, -1] *= self.alpha else: - colors = np.column_stack([ - colors, np.full(len(colors), self.alpha) - ]) + colors = np.column_stack([colors, np.full(len(colors), self.alpha)]) if self.selected_mask is not None: colors[~self.selected_mask, -1] *= self.selection_alpha colors = colors.astype(np.float32).view(rgba_dtype) - colors.shape = (-1, ) + colors.shape = (-1,) return colors diff --git a/chaco/selectable_legend.py b/chaco/selectable_legend.py index 2bfa8d0c9..11f4b9891 100644 --- a/chaco/selectable_legend.py +++ b/chaco/selectable_legend.py @@ -1,9 +1,9 @@ - from chaco.tools.select_tool import SelectTool from traits.api import List from .legend import Legend + class SelectableLegend(Legend, SelectTool): # A list of indices into self._cached_labels that indicates which labels @@ -13,9 +13,9 @@ class SelectableLegend(Legend, SelectTool): # A cached list of tuples (x,y,w,h) of each label's geometry _cached_label_dims = List - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Legend methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _do_layout(self): Legend._do_layout(self) @@ -33,19 +33,25 @@ def _compute_label_dims(self): label_width, label_height = self._cached_label_sizes[i] y -= label_height icon_y = y + (label_height - icon_height) / 2 - dims.append((icon_x, icon_y, icon_width + self.icon_spacing + label_width, - label_height)) + dims.append( + ( + icon_x, + icon_y, + icon_width + self.icon_spacing + label_width, + label_height, + ) + ) y -= self.line_spacing self._cached_label_dims = dims - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # SelectTool interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_selection_state(self, event): for ndx, dims in enumerate(self._cached_label_dims): x, y, w, h = dims - if (x <= event.x <= x+w) and (y <= event.y <= y+h): + if (x <= event.x <= x + w) and (y <= event.y <= y + h): return (ndx in self.selections), True else: if len(self._cached_label_dims) > 0: @@ -56,7 +62,7 @@ def _get_selection_state(self, event): def _get_selection_token(self, event): for ndx, dims in enumerate(self._cached_label_dims): x, y, w, h = dims - if (x <= event.x <= x+w) and (y <= event.y <= y+h): + if (x <= event.x <= x + w) and (y <= event.y <= y + h): return ndx else: return None @@ -70,4 +76,3 @@ def _select(self, index, append=True): def _deselect(self, index=None): if index in self.selections: self.selections.remove(index) - diff --git a/chaco/serializable.py b/chaco/serializable.py index 4228c12aa..d683bef93 100644 --- a/chaco/serializable.py +++ b/chaco/serializable.py @@ -2,8 +2,6 @@ """ - - class Serializable(object): """ Mix-in class to help serialization. Serializes just the attributes in @@ -26,7 +24,7 @@ class Serializable(object): # # This is a double-underscore variable so that Python's attribute name # will shield base class -# __pickle_parents = None + # __pickle_parents = None def _get_pickle_parents(self): """ @@ -58,7 +56,7 @@ def _post_load(self): you want post_load() to happen in the same order as MRO, which super() does automatically. """ - print('Serializable._post_load') + print("Serializable._post_load") pass def _do_setstate(self, state): @@ -73,9 +71,10 @@ def _do_setstate(self, state): # Quietly set all the attributes self.trait_setq(**state) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ + # def __getstate__(self): # #idstring = self.__class__.__name__ + " id=" + str(id(self)) @@ -104,8 +103,8 @@ def _do_setstate(self, state): # # return state - #~ def __setstate__(self, state): - #~ idstring = self.__class__.__name__ + " id=" + str(id(self)) - #~ self._do_setstate(state) - #~ self._post_load() - #~ return +# ~ def __setstate__(self, state): +# ~ idstring = self.__class__.__name__ + " id=" + str(id(self)) +# ~ self._do_setstate(state) +# ~ self._post_load() +# ~ return diff --git a/chaco/shell/__init__.py b/chaco/shell/__init__.py index 819e3279c..3d6090306 100644 --- a/chaco/shell/__init__.py +++ b/chaco/shell/__init__.py @@ -1,2 +1 @@ - from .commands import * diff --git a/chaco/shell/chaco_shell_error.py b/chaco/shell/chaco_shell_error.py index 131aea804..1387866ea 100644 --- a/chaco/shell/chaco_shell_error.py +++ b/chaco/shell/chaco_shell_error.py @@ -1,7 +1,8 @@ """ Defines the ChacoShellError class. """ + class ChacoShellError(RuntimeError): - """ Error raised by the Chaco shell. - """ + """Error raised by the Chaco shell.""" + pass diff --git a/chaco/shell/commands.py b/chaco/shell/commands.py index bfead8933..588a7b6c8 100644 --- a/chaco/shell/commands.py +++ b/chaco/shell/commands.py @@ -2,7 +2,6 @@ """ - try: from wx import GetApp except ImportError: @@ -13,7 +12,7 @@ from chaco.tools.zoom_tool import ZoomTool # Note: these are imported to be exposed in the namespace. -from chaco.scales.scales import (FixedScale, Pow10Scale, LogScale) +from chaco.scales.scales import FixedScale, Pow10Scale, LogScale from chaco.scales.time_scale import CalendarScaleSystem from chaco.default_colormaps import * @@ -23,9 +22,10 @@ session = PlotSession() -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ # General help commands -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ + def chaco_commands(): """ @@ -136,12 +136,14 @@ def chaco_commands(): load_prefs -- loads a previously-saved set of preferences """ -#------------------------------------------------------------------------ + +# ------------------------------------------------------------------------ # Window management commands -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ + def figure(name=None, title=None): - """ Creates a new figure window and returns its index. + """Creates a new figure window and returns its index. Parameters ---------- @@ -160,7 +162,7 @@ def figure(name=None, title=None): def activate(ident=None): - """ Activates and raises a figure window. + """Activates and raises a figure window. Parameters ---------- @@ -179,7 +181,7 @@ def activate(ident=None): def show(): - """ Shows all the figure windows that have been created thus far, and + """Shows all the figure windows that have been created thus far, and creates a GUI main loop. This function is useful in scripts to show plots and keep their windows open, and has no effect when used from the interpreter prompt. @@ -187,8 +189,11 @@ def show(): from traits.etsconfig.api import ETSConfig from pyface.util import guisupport - is_event_loop_running = getattr(guisupport, 'is_event_loop_running_' + ETSConfig.toolkit) - start_event_loop = getattr(guisupport, 'start_event_loop_' + ETSConfig.toolkit) + + is_event_loop_running = getattr( + guisupport, "is_event_loop_running_" + ETSConfig.toolkit + ) + start_event_loop = getattr(guisupport, "start_event_loop_" + ETSConfig.toolkit) if not is_event_loop_running(): frame = session.active_window @@ -197,7 +202,7 @@ def show(): def close(ident=None): - """ Closes a figure window + """Closes a figure window Parameters ---------- @@ -208,7 +213,7 @@ def close(ident=None): win_list = [] if ident is None: win_list.append(session.active_window) - elif ident == 'all': + elif ident == "all": win_list = session.windows else: win_list.append(session.get_window(ident)) @@ -233,7 +238,7 @@ def colormap(map): def hold(state=None): - """ Turns "hold" on or off, or toggles the current state if none + """Turns "hold" on or off, or toggles the current state if none is given. Parameters @@ -253,12 +258,14 @@ def curplot(): else: return None -#------------------------------------------------------------------------ + +# ------------------------------------------------------------------------ # Plotting functions -#------------------------------------------------------------------------ +# ------------------------------------------------------------------------ + def _do_plot_boilerplate(kwargs, image=False): - """ Used by various plotting functions. Checks/handles hold state, + """Used by various plotting functions. Checks/handles hold state, returns a Plot object for the plotting function to use. """ @@ -284,7 +291,9 @@ def _do_plot_boilerplate(kwargs, image=False): if not PanTool in existing_tools: cont.tools.append(PanTool(cont)) if not ZoomTool in existing_tools: - cont.overlays.append(ZoomTool(cont, tool_mode="box", always_on=True, drag_button="right")) + cont.overlays.append( + ZoomTool(cont, tool_mode="box", always_on=True, drag_button="right") + ) if not session.hold: cont.delplot(*list(cont.plots.keys())) @@ -293,7 +302,7 @@ def _do_plot_boilerplate(kwargs, image=False): def plot(*data, **kwargs): - """ Plots data in a Matlab-compatible way. Data is assumed to be + """Plots data in a Matlab-compatible way. Data is assumed to be X vs Y. Any additional *kwargs* passed in are broadcast to all plots. Example:: @@ -306,14 +315,13 @@ def plot(*data, **kwargs): cont = _do_plot_boilerplate(kwargs) - plots = plot_maker.do_plot(session.data, cont, - *data, **kwargs) + plots = plot_maker.do_plot(session.data, cont, *data, **kwargs) cont.request_redraw() def semilogx(*data, **kwargs): - """ Plots data on a semilog scale in a Matlab-compatible way. Data is + """Plots data on a semilog scale in a Matlab-compatible way. Data is assumed to be X vs Y. Any additional *kwargs* passed in are broadcast to all plots. @@ -332,7 +340,7 @@ def semilogx(*data, **kwargs): def semilogy(*data, **kwargs): - """ Plots data on a semilog scale in a Matlab-compatible way. Data is + """Plots data on a semilog scale in a Matlab-compatible way. Data is assumed to be X vs Y. Any additional *kwargs* passed in are broadcast to all plots. @@ -351,7 +359,7 @@ def semilogy(*data, **kwargs): def loglog(*data, **kwargs): - """ Plots data on a log-log scale in a Matlab-compatible way. Data is + """Plots data on a log-log scale in a Matlab-compatible way. Data is assumed to be X vs Y. Any additional *kwargs* passed in are broadcast to all plots. @@ -377,7 +385,7 @@ def imread(*data, **kwargs): def imshow(*data, **kwargs): - """ Creates an image plot from a file on disk. Takes either + """Creates an image plot from a file on disk. Takes either filename or image data. Any additional *kwargs* passed in are broadcast to all plots. @@ -398,13 +406,12 @@ def imshow(*data, **kwargs): if "colormap" not in kwargs: kwargs["colormap"] = session.colormap - plots = plot_maker.do_imshow(session.data, cont, - *data, **kwargs) + plots = plot_maker.do_imshow(session.data, cont, *data, **kwargs) cont.request_redraw() def pcolor(*data, **kwargs): - """ Colormaps scalar data in a roughly Matlab-compatible way. Data are + """Colormaps scalar data in a roughly Matlab-compatible way. Data are assumed to be a scalar image. Any additional *kwargs* passed in are broadcast to all plots. @@ -421,13 +428,12 @@ def pcolor(*data, **kwargs): cont = _do_plot_boilerplate(kwargs) - plots = plot_maker.do_pcolor(session.data, session.colormap, cont, - *data, **kwargs) + plots = plot_maker.do_pcolor(session.data, session.colormap, cont, *data, **kwargs) cont.request_redraw() def contour(*data, **kwargs): - """ Contour line plots of scalar data in a roughly Matlab-compatible way. + """Contour line plots of scalar data in a roughly Matlab-compatible way. Data are assumed to be a scalar image. Any additional *kwargs* passed in are broadcast to all plots. @@ -444,13 +450,14 @@ def contour(*data, **kwargs): cont = _do_plot_boilerplate(kwargs) - plots = plot_maker.do_contour(session.data, session.colormap, cont, - "line", *data, **kwargs) + plots = plot_maker.do_contour( + session.data, session.colormap, cont, "line", *data, **kwargs + ) cont.request_redraw() def contourf(*data, **kwargs): - """ Contour polygon plots of scalar data in a roughly Matlab-compatible way. + """Contour polygon plots of scalar data in a roughly Matlab-compatible way. Data are assumed to be a scalar image. Any additional *kwargs* passed in are broadcast to all plots. @@ -467,13 +474,14 @@ def contourf(*data, **kwargs): cont = _do_plot_boilerplate(kwargs) - plots = plot_maker.do_contour(session.data, session.colormap, cont, - "poly", *data, **kwargs) + plots = plot_maker.do_contour( + session.data, session.colormap, cont, "poly", *data, **kwargs + ) cont.request_redraw() def plotv(*args, **kwargs): - """ Creates a plot of a particular type, or using a "best guess" + """Creates a plot of a particular type, or using a "best guess" approach based on the data, using chaco semantics. The number and shape of data arrays determine how the data is @@ -536,9 +544,10 @@ def plotv(*args, **kwargs): cont.request_redraw() -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Annotations -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- + def xtitle(text): """ Sets the horizontal axis label to *text*. """ @@ -555,6 +564,7 @@ def ytitle(text): p.y_axis.title = text p.request_redraw() + def title(text): """ Sets the plot title to *text*. """ p = curplot() @@ -562,6 +572,7 @@ def title(text): p.title = text p.request_redraw() + _axis_params = """Parameters ---------- title : str @@ -601,6 +612,7 @@ def title(text): axis_line_style : LineStyle('solid') The dash style of the axis line""" + def xaxis(**kwds): """ Configures the x-axis. @@ -619,7 +631,9 @@ def xaxis(**kwds): p.x_axis.visible ^= True p.request_redraw() -xaxis.__doc__ = """ Configures the x-axis. + +xaxis.__doc__ = ( + """ Configures the x-axis. Usage ----- @@ -627,7 +641,10 @@ def xaxis(**kwds): * ``xaxis(**kwds)``: set parameters of the horizontal axis. %s - """ % _axis_params + """ + % _axis_params +) + def yaxis(**kwds): """ Configures the y-axis. @@ -647,7 +664,9 @@ def yaxis(**kwds): p.y_axis.visible ^= True p.request_redraw() -yaxis.__doc__ = """ Configures the y-axis. + +yaxis.__doc__ = ( + """ Configures the y-axis. Usage ----- @@ -655,7 +674,9 @@ def yaxis(**kwds): * ``yaxis(**kwds)``: set parameters of the vertical axis. %s - """ % _axis_params + """ + % _axis_params +) def xgrid(): @@ -665,6 +686,7 @@ def xgrid(): p.x_grid.visible ^= True p.request_redraw() + def ygrid(): """ Toggles the grid perpendicular to the Y axis. """ p = curplot() @@ -672,28 +694,31 @@ def ygrid(): p.y_grid.visible ^= True p.request_redraw() + def _set_scale(axis, system): p = curplot() if p: - if axis == 'x': - log_linear_trait = 'index_scale' + if axis == "x": + log_linear_trait = "index_scale" ticks = p.x_ticks else: - log_linear_trait = 'value_scale' + log_linear_trait = "value_scale" ticks = p.y_ticks - if system == 'time': + if system == "time": system = CalendarScaleSystem() if isinstance(system, str): setattr(p, log_linear_trait, system) else: if system is None: system = dict(linear=p.linear_scale, log=p.log_scale).get( - p.get(log_linear_trait), p.linear_scale) + p.get(log_linear_trait), p.linear_scale + ) ticks.scale = system p.request_redraw() + def xscale(system=None): - """ Change the scale system for the X-axis ticks. + """Change the scale system for the X-axis ticks. Usage ----- @@ -703,10 +728,11 @@ def xscale(system=None): * ``xscale('linear')``: use a generic linear-scale. * ``xscale(some_scale_system)``: use an arbitrary ScaleSystem object. """ - _set_scale('x', system) + _set_scale("x", system) + def yscale(system=None): - """ Change the scale system for the Y-axis ticks. + """Change the scale system for the Y-axis ticks. Usage ----- @@ -716,10 +742,11 @@ def yscale(system=None): * ``yscale('linear')``: use a generic linear-scale. * ``yscale(some_scale_system)``: use an arbitrary ScaleSystem object. """ - _set_scale('y', system) + _set_scale("y", system) + def legend(setting=None): - """ Sets or toggles the presence of the legend + """Sets or toggles the presence of the legend Usage ----- @@ -735,9 +762,10 @@ def legend(setting=None): p.request_redraw() -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Tools -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- + def tool(): """ Toggles tools on and off. """ @@ -746,13 +774,15 @@ def tool(): pass - -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Saving and IO -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- + -def save(filename="chacoplot.png", dpi=72, pagesize="letter", dest_box=None, units="inch"): - """ Saves the active plot to an file. Currently supported file types +def save( + filename="chacoplot.png", dpi=72, pagesize="letter", dest_box=None, units="inch" +): + """Saves the active plot to an file. Currently supported file types are: bmp, png, jpg. """ p = curplot() @@ -761,17 +791,21 @@ def save(filename="chacoplot.png", dpi=72, pagesize="letter", dest_box=None, uni return import os.path + ext = os.path.splitext(filename)[-1] if ext == ".pdf": print("Warning: the PDF backend is still a little buggy.") from chaco.pdf_graphics_context import PdfPlotGraphicsContext + # Set some default PDF options if none are provided if dest_box is None: dest_box = (0.5, 0.5, -0.5, -0.5) - gc = PdfPlotGraphicsContext(filename = filename, - pagesize = pagesize, - dest_box = dest_box, - dest_box_units = units) + gc = PdfPlotGraphicsContext( + filename=filename, + pagesize=pagesize, + dest_box=dest_box, + dest_box_units=units, + ) # temporarily turn off the backbuffer for offscreen rendering use_backbuffer = p.use_backbuffer @@ -785,6 +819,7 @@ def save(filename="chacoplot.png", dpi=72, pagesize="letter", dest_box=None, uni elif ext in [".bmp", ".png", ".jpg"]: from chaco.plot_graphics_context import PlotGraphicsContext + gc = PlotGraphicsContext(tuple(p.outer_bounds), dpi=dpi) # temporarily turn off the backbuffer for offscreen rendering diff --git a/chaco/shell/plot_maker.py b/chaco/shell/plot_maker.py index 072ca2f3c..948c20c48 100644 --- a/chaco/shell/plot_maker.py +++ b/chaco/shell/plot_maker.py @@ -11,14 +11,13 @@ from numpy import all, array, arange, asarray, reshape, shape, transpose # Chaco imports -from chaco.plot_factory import (create_line_plot, create_scatter_plot) +from chaco.plot_factory import create_line_plot, create_scatter_plot from chaco.array_data_source import ArrayDataSource from chaco.image_data import ImageData from chaco.tools.highlight_tool import HighlightTool - # Local relative imports from .chaco_shell_error import ChacoShellError @@ -26,42 +25,54 @@ # Normally I don't define an __all__, but this lets us distinguish # the top level plot-producing functions from the various helper # functions. -__all__ = ["do_plot", "do_imshow", "do_pcolor", "do_contour", "do_plotv", - "SizeMismatch", ] +__all__ = [ + "do_plot", + "do_imshow", + "do_pcolor", + "do_contour", + "do_plotv", + "SizeMismatch", +] -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Exceptions -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- + class SizeMismatch(ChacoShellError): pass -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Utility functions -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- -def is1D (a): + +def is1D(a): s = shape(a) - return ((len(s) == 1) or (s[0] == 1) or (s[1] == 1)) + return (len(s) == 1) or (s[0] == 1) or (s[1] == 1) + -def is2D (a): - return (len(shape(a)) == 2) +def is2D(a): + return len(shape(a)) == 2 -def row ( a ): - return reshape( asarray( a ), [1,-1] ) -def col ( a ): - return reshape( asarray( a ), [-1,1] ) +def row(a): + return reshape(asarray(a), [1, -1]) -#----------------------------------------------------------------------------- +def col(a): + return reshape(asarray(a), [-1, 1]) + + +# ----------------------------------------------------------------------------- # Plot commands for chaco-style plotv() -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- + def do_plotv(session, *args, **kw): - """ Creates a list of plots from the data in ``*args`` and options in + """Creates a list of plots from the data in ``*args`` and options in ``**kw``, according to the docstring on commands.plot(). """ @@ -79,11 +90,11 @@ def do_plotv(session, *args, **kw): for plot in plots: plot.orientation = kw.get("orientation", "h") - return plots + def make_data_sources(session, index_sort="none", *args): - """ Given a list of arguments, returns a list of (index, value) datasources + """Given a list of arguments, returns a list of (index, value) datasources to create plots from. """ # Make sure everything is a numpy array @@ -122,62 +133,65 @@ def make_data_sources(session, index_sort="none", *args): index_ary = ary[0] value_arrays = transpose(ary[1:]) index_ds = ArrayDataSource(index_ary, sort_order=index_sort) - sources.extend([(index_ds, ArrayDataSource(v, sort_order="none")) for v in value_arrays]) + sources.extend( + [ + (index_ds, ArrayDataSource(v, sort_order="none")) + for v in value_arrays + ] + ) return sources # Not a two-dimensional array, error. else: raise ChacoShellError( - "Unable to create plot data sources from array of shape " + - str(data[1].shape) + ".") + "Unable to create plot data sources from array of shape " + + str(data[1].shape) + + "." + ) -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Plot commands for matlab-compatible plot() function -#----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- # Regular expressions for parsing the format string -color_re = re.compile('[ymcrgbwk]') +color_re = re.compile("[ymcrgbwk]") color_trans = { - 'y': 'yellow', - 'm': 'magenta', - 'c': 'cyan', - 'r': 'red', - 'g': 'green', - 'b': 'blue', - 'w': 'white', - 'k': 'black' + "y": "yellow", + "m": "magenta", + "c": "cyan", + "r": "red", + "g": "green", + "b": "blue", + "w": "white", + "k": "black", } # This one isn't quite right: -marker_re = re.compile('[ox+s^v]|(?:[^-])[.]') +marker_re = re.compile("[ox+s^v]|(?:[^-])[.]") marker_trans = { - '.': 'dot', - 'o': 'circle', - 'x': 'cross', - '+': 'plus', - 's': 'square', - '^': 'triangle', - 'v': 'inverted_triangle' + ".": "dot", + "o": "circle", + "x": "cross", + "+": "plus", + "s": "square", + "^": "triangle", + "v": "inverted_triangle", } -line_re = re.compile('--|-\.|[-:]') -line_trans = { - '-': 'solid', - ':': 'dot', - '-.': 'dot dash', - '--': 'dash' -} +line_re = re.compile("--|-\.|[-:]") +line_trans = {"-": "solid", ":": "dot", "-.": "dot dash", "--": "dash"} + def _process_format(format): """ Converts a format string into a (color, line, marker, marker_color) tuple. """ - if format == '': - return ('black', 'solid', None, None) - color, line, marker, marker_color = 'black', None, None, None + if format == "": + return ("black", "solid", None, None) + color, line, marker, marker_color = "black", None, None, None m = color_re.findall(format) if len(m) > 0: color = marker_color = color_trans[m[0]] @@ -192,8 +206,9 @@ def _process_format(format): line = line_trans[m[0]] return (color, line, marker, marker_color) + def _process_group(group, plot_data=None): - """ Returns a (x_1D, y_1D, format_str) tuple from an input tuple + """Returns a (x_1D, y_1D, format_str) tuple from an input tuple of 1 to 3 elements: (x,y,format_str). A PlotData object can be optionally provided to disambiguate the cases @@ -204,7 +219,7 @@ def _process_group(group, plot_data=None): to be. """ # Interpret and split the 'group' tuple into x, y, and plotinfo - plotinfo = '' + plotinfo = "" if len(group) == 1: y = group[0] y_data = plot_data.get_data(y) @@ -228,8 +243,9 @@ def _process_group(group, plot_data=None): elif len(group) == 3: x, y, plotinfo = group else: - raise ChacoShellError("Found too many elements in group while" \ - " constructing plot.") + raise ChacoShellError( + "Found too many elements in group while" " constructing plot." + ) return x, y, plotinfo @@ -244,7 +260,7 @@ def _check_sort_order(data): def do_plot(plotdata, active_plot, *data_and_formats, **kwtraits): - """ Takes a list of data (arrays or names) and format string arguments + """Takes a list of data (arrays or names) and format string arguments and creates new plots on the active_plot. Returns a list of plot names on the active plot. """ @@ -275,7 +291,7 @@ def do_plot(plotdata, active_plot, *data_and_formats, **kwtraits): plots = [] for group in groups: - x, y, format_str = _process_group(group, plot_data = plotdata) + x, y, format_str = _process_group(group, plot_data=plotdata) linecolor, line, marker, markercolor = _process_format(format_str) plot_type = [] format = kwtraits.copy() @@ -289,7 +305,7 @@ def do_plot(plotdata, active_plot, *data_and_formats, **kwtraits): format["color"] = markercolor x_sort_order = _check_sort_order(plotdata.get_data(x)) - plots.extend(active_plot.plot((x,y), type=",".join(plot_type), **format)) + plots.extend(active_plot.plot((x, y), type=",".join(plot_type), **format)) # Set the sort order x_ds = active_plot.datasources[x] @@ -306,6 +322,7 @@ def do_plot(plotdata, active_plot, *data_and_formats, **kwtraits): return plots + def do_imread(*data, **kwargs): """ Returns image file as array. """ @@ -316,9 +333,8 @@ def do_imread(*data, **kwargs): raise ValueError("do_imread takes a string filename") - def do_imshow(plotdata, active_plot, *data, **kwargs): - """ Creates an image plot on the active plot, given either + """Creates an image plot on the active plot, given either a filename or data. """ @@ -340,8 +356,8 @@ def do_imshow(plotdata, active_plot, *data, **kwargs): return plot_list -def do_pcolor(plotdata, colormap, active_plot, *data, **kwargs ): - """ Creates a pseudocolor image plot on the active plot, given a 2-D +def do_pcolor(plotdata, colormap, active_plot, *data, **kwargs): + """Creates a pseudocolor image plot on the active plot, given a 2-D scalar data and a colormap. """ @@ -359,13 +375,14 @@ def do_pcolor(plotdata, colormap, active_plot, *data, **kwargs ): else: raise ValueError("do_pcolor takes one or three data sources") - plot_list = [active_plot.img_plot(z, xbounds=x, ybounds=y, - colormap=colormap, **kwargs)] + plot_list = [ + active_plot.img_plot(z, xbounds=x, ybounds=y, colormap=colormap, **kwargs) + ] return plot_list -def do_contour(plotdata, colormap, active_plot, type, *data, **kwargs ): - """ Creates a contour plot on the active plot, given a 2-D +def do_contour(plotdata, colormap, active_plot, type, *data, **kwargs): + """Creates a contour plot on the active plot, given a 2-D scalar data and a colormap. """ @@ -386,28 +403,31 @@ def do_contour(plotdata, colormap, active_plot, type, *data, **kwargs ): # we have to do slightly different calls here because of the different # handling of colormaps - if type is 'poly': - plot_list = [active_plot.contour_plot(z, type, xbounds=x, ybounds=y, - poly_cmap=colormap, - **kwargs)] + if type is "poly": + plot_list = [ + active_plot.contour_plot( + z, type, xbounds=x, ybounds=y, poly_cmap=colormap, **kwargs + ) + ] else: - plot_list = [active_plot.contour_plot(z, type, xbounds=x, ybounds=y, - colors=colormap, - **kwargs)] + plot_list = [ + active_plot.contour_plot( + z, type, xbounds=x, ybounds=y, colors=colormap, **kwargs + ) + ] return plot_list def _get_or_create_plot_data(data, plotdata): - """Create a new name for `data` if necessary, or check it is a valid name. - """ + """Create a new name for `data` if necessary, or check it is a valid name.""" valid_names = plotdata.list_data() if not isinstance(data, str): name = plotdata.set_data("", data, generate_name=True) else: if data not in valid_names: - msg = '{} is not an existing name for plot data' + msg = "{} is not an existing name for plot data" raise ValueError(msg.format(data)) name = data diff --git a/chaco/shell/plot_window.py b/chaco/shell/plot_window.py index 5b20f2305..05034de62 100644 --- a/chaco/shell/plot_window.py +++ b/chaco/shell/plot_window.py @@ -9,18 +9,25 @@ if ETSConfig.toolkit == "wx": import wx + class PlotWindow(wx.Frame): - """ A window for holding top-level plot containers. + """A window for holding top-level plot containers. Contains many utility methods for controlling the appearance of the window, which mostly pass through to underlying WX calls. """ - def __init__(self, is_image=False, bgcolor="white", - image_default_origin="top left", *args, **kw): + def __init__( + self, + is_image=False, + bgcolor="white", + image_default_origin="top left", + *args, + **kw + ): - kw.setdefault("size", (600,600)) - wx.Frame.__init__(self, None, *args, **kw ) + kw.setdefault("size", (600, 600)) + wx.Frame.__init__(self, None, *args, **kw) # Some defaults which should be overridden by preferences. self.bgcolor = bgcolor @@ -36,7 +43,6 @@ def __init__(self, is_image=False, bgcolor="white", # to notify it of our being closed, etc. self.session = None - # Create the Enable Window object, and store a reference to it. # (This will be handy later.) The Window requires a WX parent object # as its first argument, so we just pass 'self'. @@ -64,13 +70,11 @@ def set_container(self, container): self.plot_window.component = container def iconize(self, iconize): - """Iconizes the window if *iconize* is True. - """ + """Iconizes the window if *iconize* is True.""" self.Iconize(iconize) def maximize(self, maximize): - """ If *maximize* is True, maximizes the window size; restores if False. - """ + """If *maximize* is True, maximizes the window size; restores if False.""" self.Maximize(maximize) def set_size(self, width, height): @@ -80,8 +84,7 @@ def set_title(self, title): self.SetTitle(title) def raise_window(self): - """Raises this window to the top of the window hierarchy. - """ + """Raises this window to the top of the window hierarchy.""" self.Raise() def close(self): @@ -90,9 +93,9 @@ def close(self): # This is a Python property because this is not a HasTraits subclass. container = property(get_container, set_container) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _create_top_container(self): plot = ScalyPlot( @@ -113,7 +116,6 @@ def _create_top_img_container(self): ) return plot - def _on_window_close(self, event): if self.session: try: @@ -122,25 +124,32 @@ def _on_window_close(self, event): except ValueError: pass + elif ETSConfig.toolkit == "qt4": from pyface.qt import QtCore, QtGui class PlotWindow(QtGui.QFrame): - """ A window for holding top-level plot containers. + """A window for holding top-level plot containers. Contains many utility methods for controlling the appearance of the window, which mostly pass through to underlying Qt calls. """ - def __init__(self, is_image=False, bgcolor="white", - image_default_origin="top left", *args, **kw): + def __init__( + self, + is_image=False, + bgcolor="white", + image_default_origin="top left", + *args, + **kw + ): size = kw.pop("size", None) if isinstance(size, tuple): size = QtCore.QSize(*size) - - super(PlotWindow, self).__init__(None, *args, **kw ) + + super(PlotWindow, self).__init__(None, *args, **kw) if size is not None: self.resize(size) @@ -169,7 +178,7 @@ def __init__(self, is_image=False, bgcolor="white", layout.addWidget(self.plot_window.control) self.setLayout(layout) - size = kw.get("size", QtCore.QSize(600,600)) + size = kw.get("size", QtCore.QSize(600, 600)) self.set_size(size.width(), size.height()) self.show() @@ -181,16 +190,14 @@ def set_container(self, container): self.plot_window.component = container def iconize(self, iconize): - """Iconizes the window if *iconize* is True. - """ + """Iconizes the window if *iconize* is True.""" if iconize: self.showMinimized() else: self.showNormal() def maximize(self, maximize): - """ If *maximize* is True, maximizes the window size; restores if False. - """ + """If *maximize* is True, maximizes the window size; restores if False.""" if maximize: self.showMaximized() else: @@ -203,16 +210,15 @@ def set_title(self, title): self.setWindowTitle(title) def raise_window(self): - """Raises this window to the top of the window hierarchy. - """ + """Raises this window to the top of the window hierarchy.""" self.raise_() # This is a Python property because this is not a HasTraits subclass. container = property(get_container, set_container) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _create_top_container(self): plot = ScalyPlot( @@ -241,10 +247,9 @@ def closeEvent(self, event): except ValueError: pass + else: class PlotWindow(object): - def __init__(self, *args, **kwargs): - raise NotImplementedError( - 'PlotWindow not implemented for `null` toolkit') + raise NotImplementedError("PlotWindow not implemented for `null` toolkit") diff --git a/chaco/shell/preferences.py b/chaco/shell/preferences.py index 7ce6194b1..ca676e958 100644 --- a/chaco/shell/preferences.py +++ b/chaco/shell/preferences.py @@ -6,8 +6,7 @@ class Preferences(HasTraits): - """ Contains all the preferences that configure the Chaco shell session. - """ + """Contains all the preferences that configure the Chaco shell session.""" # Width of the plot window, in pixels. window_width = Int(600) @@ -25,25 +24,19 @@ class Preferences(HasTraits): bgcolor = white_color_trait # The default location of the origin for new image plots - image_default_origin = Enum("top left", "bottom left", - "bottom right", "top right") + image_default_origin = Enum("top left", "bottom left", "bottom right", "top right") @classmethod def from_file(cls, filename): - """ Creates a new preferences object from a file on disk. - """ + """Creates a new preferences object from a file on disk.""" prefs = cls() prefs.load(filename) return prefs - def load(self, filename): - """ Loads a preferences file; existing settings are overwritten. - """ + """Loads a preferences file; existing settings are overwritten.""" pass - def save(self, filename): - """ Saves the preferences to *filename*. - """ + """Saves the preferences to *filename*.""" pass diff --git a/chaco/shell/scaly_plot.py b/chaco/shell/scaly_plot.py index 43457c06f..816ffeac1 100644 --- a/chaco/shell/scaly_plot.py +++ b/chaco/shell/scaly_plot.py @@ -28,7 +28,7 @@ def add_default_axes(plot, orientation="normal", vtitle="", htitle=""): yticks = ScalesTickGenerator() left = PlotAxis( - orientation='left', + orientation="left", title=vtitle, mapper=v_mapper, component=plot, @@ -37,7 +37,7 @@ def add_default_axes(plot, orientation="normal", vtitle="", htitle=""): xticks = ScalesTickGenerator() bottom = PlotAxis( - orientation='bottom', + orientation="bottom", title=htitle, mapper=h_mapper, component=plot, @@ -104,19 +104,37 @@ def _init_components(self): self.y_ticks = ScalesTickGenerator(scale=self._make_scale(self.value_scale)) if self.x_grid is None: - self.x_grid = PlotGrid(mapper=self.x_mapper, orientation="vertical", - line_color="lightgray", line_style="dot", - component=self, tick_generator=self.x_ticks) + self.x_grid = PlotGrid( + mapper=self.x_mapper, + orientation="vertical", + line_color="lightgray", + line_style="dot", + component=self, + tick_generator=self.x_ticks, + ) if self.y_grid is None: - self.y_grid = PlotGrid(mapper=self.y_mapper, orientation="horizontal", - line_color="lightgray", line_style="dot", - component=self, tick_generator=self.y_ticks) + self.y_grid = PlotGrid( + mapper=self.y_mapper, + orientation="horizontal", + line_color="lightgray", + line_style="dot", + component=self, + tick_generator=self.y_ticks, + ) if self.x_axis is None: - self.x_axis = PlotAxis(mapper=self.x_mapper, orientation="bottom", - component=self, tick_generator=self.x_ticks) + self.x_axis = PlotAxis( + mapper=self.x_mapper, + orientation="bottom", + component=self, + tick_generator=self.x_ticks, + ) if self.y_axis is None: - self.y_axis = PlotAxis(mapper=self.y_mapper, orientation="left", - component=self, tick_generator=self.y_ticks) + self.y_axis = PlotAxis( + mapper=self.y_mapper, + orientation="left", + component=self, + tick_generator=self.y_ticks, + ) def _index_scale_changed(self, old, new): Plot._index_scale_changed(self, old, new) diff --git a/chaco/shell/session.py b/chaco/shell/session.py index cbe5dfefa..3a006345e 100644 --- a/chaco/shell/session.py +++ b/chaco/shell/session.py @@ -2,12 +2,21 @@ """ - # Enthoght library imports from chaco.array_plot_data import ArrayPlotData from chaco.default_colormaps import * -from traits.api import Any, Bool, Dict, HasTraits, Instance, Int, \ - List, Property, Trait, Str +from traits.api import ( + Any, + Bool, + Dict, + HasTraits, + Instance, + Int, + List, + Property, + Trait, + Str, +) # Local, relative imports @@ -37,10 +46,9 @@ class PlotSession(HasTraits): # arrays that are provided to various plotting commands. data = Instance(ArrayPlotData, args=()) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # "active" pointers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The index of the active window. active_window_index = Trait(None, None, Int) @@ -51,7 +59,6 @@ class PlotSession(HasTraits): # The active colormap. colormap = Trait(jet, Any) - def new_window(self, name=None, title=None, is_image=False): """Creates a new window and returns the index into the **windows** list for the new window. @@ -76,7 +83,7 @@ def new_window(self, name=None, title=None, is_image=False): self.windows.append(new_win) if name != None: self.window_map[name] = new_win - return len(self.windows)-1 + return len(self.windows) - 1 def get_window(self, ident): """ Retrieves a window either by index or by name """ @@ -88,7 +95,7 @@ def get_window(self, ident): return None def del_window(self, ident): - """ Deletes the specified window. + """Deletes the specified window. Parameters ---------- @@ -147,6 +154,5 @@ def _colormap_changed(self): p.invalidate_draw() p.request_redraw() elif hasattr(p, "colors"): - if isinstance(p.colors, str) or \ - isinstance(p.colors, AbstractColormap): + if isinstance(p.colors, str) or isinstance(p.colors, AbstractColormap): p.colors = color_map_dict[self.colormap] diff --git a/chaco/shell/tests/test_make_data_sources.py b/chaco/shell/tests/test_make_data_sources.py index 263d76a87..c02224d53 100644 --- a/chaco/shell/tests/test_make_data_sources.py +++ b/chaco/shell/tests/test_make_data_sources.py @@ -6,7 +6,6 @@ class MakeDataSourcesTestCase(unittest.TestCase): - def test_1D_single(self): session = None ary = np.array([3.0, 2.1, 1.3, 1.8, 5.7]) @@ -16,7 +15,7 @@ def test_1D_single(self): def test_1d_multiple(self): session = None - index = np.arange(-np.pi, np.pi, np.pi/30.0) + index = np.arange(-np.pi, np.pi, np.pi / 30.0) s = np.sin(index) c = np.cos(index) t = np.tan(index) @@ -27,4 +26,3 @@ def test_1d_multiple(self): assert_almost_equal(sources[0][1].get_data(), s) assert_almost_equal(sources[1][1].get_data(), c) assert_almost_equal(sources[2][1].get_data(), t) - diff --git a/chaco/shell/tests/test_tutorial_example.py b/chaco/shell/tests/test_tutorial_example.py index 19f4c864c..b50507f7e 100644 --- a/chaco/shell/tests/test_tutorial_example.py +++ b/chaco/shell/tests/test_tutorial_example.py @@ -11,12 +11,10 @@ from chaco.shell import plot, title, ytitle -@unittest.skipIf( - ETSConfig.toolkit=='null', "Skip on 'null' toolkit") +@unittest.skipIf(ETSConfig.toolkit == "null", "Skip on 'null' toolkit") class InteractiveTestCase(unittest.TestCase): - def test_script(self): - x = linspace(-2*pi, 2*pi, 100) + x = linspace(-2 * pi, 2 * pi, 100) y = sin(x) plot(x, y, "r-") title("First plot") diff --git a/chaco/simple_plot_frame.py b/chaco/simple_plot_frame.py index 98b890787..2ebc6a2a9 100644 --- a/chaco/simple_plot_frame.py +++ b/chaco/simple_plot_frame.py @@ -9,7 +9,6 @@ ################################################################################# - # Enthought library imports from traits.api import Bool @@ -17,6 +16,7 @@ from .base_plot_frame import BasePlotFrame from .plot_containers import OverlayPlotContainer + class SimplePlotFrame(BasePlotFrame): """ A plot frame with just a single, center container that takes up the entire @@ -28,7 +28,7 @@ class SimplePlotFrame(BasePlotFrame): #: This frame has only one position for plot components. Overrides #: PlotFrame. - slot_names = ("center") + slot_names = "center" #: Default width and height. Class attribute. default_bounds = (500, 500) @@ -40,14 +40,13 @@ class SimplePlotFrame(BasePlotFrame): #: component. Overrides Enable Container. fit_window = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Does the component need to do a layout call? _layout_needed = Bool(True) - def __init__(self, **kwtraits): # Delay setting the bounds until after base class initialization bounds = kwtraits.pop("bounds", list(self.default_bounds)) @@ -56,12 +55,12 @@ def __init__(self, **kwtraits): self.set_slot("center", OverlayPlotContainer(resizable="hv")) self.bounds = bounds - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Protected methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _draw_component(self, gc, view_bounds=None, mode="normal"): - """ Draws the component. + """Draws the component. This method is preserved for backwards compatibility with _old_draw(). Overrides PlotComponent. @@ -75,11 +74,11 @@ def _draw_component(self, gc, view_bounds=None, mode="normal"): self.center.draw(gc, view_bounds, mode) def get_preferred_size(self): - """ Returns the size (width,height) that is preferred for this component. + """Returns the size (width,height) that is preferred for this component. Overrides PlotComponent. """ - size = [0,0] + size = [0, 0] component_pref_size = None if "h" not in self.resizable: if "h" in self.fit_components: @@ -127,15 +126,15 @@ def _do_layout(self): # auto-size to our bounds, so do nothing. pass - component.outer_position = [0,0] + component.outer_position = [0, 0] component.do_layout() ### Persistence ########################################################### - #_pickles = () + # _pickles = () def __getstate__(self): - state = super(SimplePlotFrame,self).__getstate__() - for key in ['_layout_needed']: + state = super(SimplePlotFrame, self).__getstate__() + for key in ["_layout_needed"]: if key in state: del state[key] diff --git a/chaco/speedups.py b/chaco/speedups.py index bd4a2dd25..0263e303e 100644 --- a/chaco/speedups.py +++ b/chaco/speedups.py @@ -1,4 +1,3 @@ - # This contains python implementations of all the speedups from ._speedups_fallback import * diff --git a/chaco/svg_graphics_context.py b/chaco/svg_graphics_context.py index b287098e4..3443ecd99 100644 --- a/chaco/svg_graphics_context.py +++ b/chaco/svg_graphics_context.py @@ -4,8 +4,9 @@ from kiva.svg import GraphicsContext + class SVGGraphicsContext(GraphicsContext): - """ A Kiva graphics context, which facilitates rendering plots and plot + """A Kiva graphics context, which facilitates rendering plots and plot components into an offscreen or memory buffer. Its only real difference from a Kiva graphics context is that this @@ -14,20 +15,21 @@ class correctly offsets the coordinate frame by (0.5, 0.5) and increases into on-screen windows through Enable, this transformation step is handled by Enable. """ + # FIXME: Right now this does not resize correctly. (But you shouldn't # resize your GC, anyway!) def __init__(self, size_or_ary, dpi=72.0, *args, **kw): scale = dpi / 72.0 if type(size_or_ary) in (list, tuple) and len(size_or_ary) == 2: - size_or_ary = (size_or_ary[0]*scale + 1, size_or_ary[1]*scale + 1) + size_or_ary = (size_or_ary[0] * scale + 1, size_or_ary[1] * scale + 1) super(SVGGraphicsContext, self).__init__(size_or_ary, *args, **kw) self.translate_ctm(0.5, 0.5) self.scale_ctm(scale, scale) def render_component(self, component, container_coords=False): - """ Renders the given component. + """Renders the given component. Parameters ---------- @@ -62,9 +64,9 @@ def render_component(self, component, container_coords=False): component.draw(self, view_bounds=(0, 0, width, height)) def clip_to_rect(self, x, y, width, height): - """ Offsets the coordinate frame by (0.5, 0.5) and increases the actual + """Offsets the coordinate frame by (0.5, 0.5) and increases the actual size of the image by 1 pixel in each dimension. Overrides Kiva GraphicsContext. """ - GraphicsContext.clip_to_rect(self, x-0.5, y-0.5, width+1, height+1) + GraphicsContext.clip_to_rect(self, x - 0.5, y - 0.5, width + 1, height + 1) diff --git a/chaco/tests/_tools.py b/chaco/tests/_tools.py index 36599a098..03e5d07d0 100644 --- a/chaco/tests/_tools.py +++ b/chaco/tests/_tools.py @@ -6,6 +6,7 @@ # ######### Testing tools + @contextmanager def store_exceptions_on_all_threads(): """Context manager that captures all exceptions, even those coming from @@ -16,8 +17,8 @@ def store_exceptions_on_all_threads(): def excepthook(type, value, tb): exceptions.append(value) - message = 'Uncaught exception:\n' - message += ''.join(traceback.format_exception(type, value, tb)) + message = "Uncaught exception:\n" + message += "".join(traceback.format_exception(type, value, tb)) sys.stderr.write(message) try: @@ -36,5 +37,5 @@ def assert_raises(ExceptionClass): except ExceptionClass: pass else: - msg = 'Test should have failed with {}.' + msg = "Test should have failed with {}." raise Exception(msg.format(ExceptionClass.__name__)) diff --git a/chaco/tests/segment_plot_test_case.py b/chaco/tests/segment_plot_test_case.py index 43ef8174b..af90e1354 100644 --- a/chaco/tests/segment_plot_test_case.py +++ b/chaco/tests/segment_plot_test_case.py @@ -4,9 +4,7 @@ from numpy.testing import assert_array_equal # Chaco imports -from chaco.api import ( - ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext -) +from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext from chaco.base import rgba_dtype from chaco.segment_plot import SegmentPlot from chaco.default_colormaps import viridis @@ -55,13 +53,9 @@ def set_width_data(self): self.segment_plot.width_mapper = width_mapper def test_segment(self): - self.assertEqual(self.segment_plot.origin, 'bottom left') - self.assertIs( - self.segment_plot.x_mapper, self.segment_plot.index_mapper - ) - self.assertIs( - self.segment_plot.y_mapper, self.segment_plot.value_mapper - ) + self.assertEqual(self.segment_plot.origin, "bottom left") + self.assertIs(self.segment_plot.x_mapper, self.segment_plot.index_mapper) + self.assertIs(self.segment_plot.y_mapper, self.segment_plot.value_mapper) gc = PlotGraphicsContext(self.size) gc.render_component(self.segment_plot) @@ -69,15 +63,11 @@ def test_segment(self): self.assertFalse(alltrue(actual == 255)) def test_segment_orthogonal(self): - self.segment_plot.render_style = 'orthogonal' + self.segment_plot.render_style = "orthogonal" - self.assertEqual(self.segment_plot.origin, 'bottom left') - self.assertIs( - self.segment_plot.x_mapper, self.segment_plot.index_mapper - ) - self.assertIs( - self.segment_plot.y_mapper, self.segment_plot.value_mapper - ) + self.assertEqual(self.segment_plot.origin, "bottom left") + self.assertIs(self.segment_plot.x_mapper, self.segment_plot.index_mapper) + self.assertIs(self.segment_plot.y_mapper, self.segment_plot.value_mapper) gc = PlotGraphicsContext(self.size) gc.render_component(self.segment_plot) @@ -85,15 +75,11 @@ def test_segment_orthogonal(self): self.assertFalse(alltrue(actual == 255)) def test_segment_quad(self): - self.segment_plot.render_style = 'quad' + self.segment_plot.render_style = "quad" - self.assertEqual(self.segment_plot.origin, 'bottom left') - self.assertIs( - self.segment_plot.x_mapper, self.segment_plot.index_mapper - ) - self.assertIs( - self.segment_plot.y_mapper, self.segment_plot.value_mapper - ) + self.assertEqual(self.segment_plot.origin, "bottom left") + self.assertIs(self.segment_plot.x_mapper, self.segment_plot.index_mapper) + self.assertIs(self.segment_plot.y_mapper, self.segment_plot.value_mapper) gc = PlotGraphicsContext(self.size) gc.render_component(self.segment_plot) @@ -101,15 +87,11 @@ def test_segment_quad(self): self.assertFalse(alltrue(actual == 255)) def test_segment_cubic(self): - self.segment_plot.render_style = 'cubic' + self.segment_plot.render_style = "cubic" - self.assertEqual(self.segment_plot.origin, 'bottom left') - self.assertIs( - self.segment_plot.x_mapper, self.segment_plot.index_mapper - ) - self.assertIs( - self.segment_plot.y_mapper, self.segment_plot.value_mapper - ) + self.assertEqual(self.segment_plot.origin, "bottom left") + self.assertIs(self.segment_plot.x_mapper, self.segment_plot.index_mapper) + self.assertIs(self.segment_plot.y_mapper, self.segment_plot.value_mapper) gc = PlotGraphicsContext(self.size) gc.render_component(self.segment_plot) @@ -125,7 +107,7 @@ def test_segment_color(self): self.assertFalse(alltrue(actual == 255)) def test_segment_color_orthogonal(self): - self.segment_plot.render_style = 'orthogonal' + self.segment_plot.render_style = "orthogonal" self.set_color_data() gc = PlotGraphicsContext(self.size) @@ -134,7 +116,7 @@ def test_segment_color_orthogonal(self): self.assertFalse(alltrue(actual == 255)) def test_segment_color_quad(self): - self.segment_plot.render_style = 'quad' + self.segment_plot.render_style = "quad" self.set_color_data() gc = PlotGraphicsContext(self.size) @@ -143,7 +125,7 @@ def test_segment_color_quad(self): self.assertFalse(alltrue(actual == 255)) def test_segment_color_cubic(self): - self.segment_plot.render_style = 'cubic' + self.segment_plot.render_style = "cubic" self.set_color_data() gc = PlotGraphicsContext(self.size) @@ -160,7 +142,7 @@ def test_segment_width(self): self.assertFalse(alltrue(actual == 255)) def test_segment_width_orthogonal(self): - self.segment_plot.render_style = 'orthogonal' + self.segment_plot.render_style = "orthogonal" self.set_width_data() gc = PlotGraphicsContext(self.size) @@ -169,7 +151,7 @@ def test_segment_width_orthogonal(self): self.assertFalse(alltrue(actual == 255)) def test_segment_width_quad(self): - self.segment_plot.render_style = 'quad' + self.segment_plot.render_style = "quad" self.set_width_data() gc = PlotGraphicsContext(self.size) @@ -178,7 +160,7 @@ def test_segment_width_quad(self): self.assertFalse(alltrue(actual == 255)) def test_segment_width_cubic(self): - self.segment_plot.render_style = 'cubic' + self.segment_plot.render_style = "cubic" self.set_width_data() gc = PlotGraphicsContext(self.size) @@ -196,7 +178,7 @@ def test_segment_width_color(self): self.assertFalse(alltrue(actual == 255)) def test_segment_width_orthogonal_color(self): - self.segment_plot.render_style = 'orthogonal' + self.segment_plot.render_style = "orthogonal" self.set_width_data() self.set_color_data() @@ -206,7 +188,7 @@ def test_segment_width_orthogonal_color(self): self.assertFalse(alltrue(actual == 255)) def test_segment_width_quad_color(self): - self.segment_plot.render_style = 'quad' + self.segment_plot.render_style = "quad" self.set_width_data() self.set_color_data() @@ -216,7 +198,7 @@ def test_segment_width_quad_color(self): self.assertFalse(alltrue(actual == 255)) def test_segment_width_cubic_color(self): - self.segment_plot.render_style = 'cubic' + self.segment_plot.render_style = "cubic" self.set_width_data() self.set_color_data() @@ -234,7 +216,7 @@ def test_segment_alpha(self): self.assertFalse(alltrue(actual == 255)) def test_segment_orthogonal_alpha(self): - self.segment_plot.render_style = 'orthogonal' + self.segment_plot.render_style = "orthogonal" self.segment_plot.alpha = 0.5 gc = PlotGraphicsContext(self.size) @@ -243,7 +225,7 @@ def test_segment_orthogonal_alpha(self): self.assertFalse(alltrue(actual == 255)) def test_segment_quad_alpha(self): - self.segment_plot.render_style = 'quad' + self.segment_plot.render_style = "quad" self.segment_plot.alpha = 0.5 gc = PlotGraphicsContext(self.size) @@ -252,7 +234,7 @@ def test_segment_quad_alpha(self): self.assertFalse(alltrue(actual == 255)) def test_segment_cubic_alpha(self): - self.segment_plot.render_style = 'cubic' + self.segment_plot.render_style = "cubic" self.segment_plot.alpha = 0.5 gc = PlotGraphicsContext(self.size) @@ -262,14 +244,14 @@ def test_segment_cubic_alpha(self): def test_segment_selection(self): mask = array([True, True, False, False, True]) - self.segment_plot.index.metadata['selections'] = [mask] + self.segment_plot.index.metadata["selections"] = [mask] black = self.segment_plot.color_ yellow = self.segment_plot.selection_color_ expected_colors = array([yellow, yellow, black, black, yellow]) - expected_colors = expected_colors.astype('float32').view(rgba_dtype) - expected_colors.shape = (5, ) - expected_colors['a'][~mask] *= 0.3 + expected_colors = expected_colors.astype("float32").view(rgba_dtype) + expected_colors.shape = (5,) + expected_colors["a"][~mask] *= 0.3 assert_array_equal(mask, self.segment_plot.selected_mask) assert_array_equal(expected_colors, self.segment_plot.effective_colors) @@ -281,14 +263,14 @@ def test_segment_selection(self): def test_segment_selection_color(self): mask = array([True, True, False, False, True]) - self.segment_plot.index.metadata['selections'] = [mask] + self.segment_plot.index.metadata["selections"] = [mask] self.set_color_data() color_data = self.segment_plot.color_data.get_data() colors = self.segment_plot.color_mapper.map_screen(color_data) - expected_colors = colors.astype('float32').view(rgba_dtype) - expected_colors.shape = (5, ) - expected_colors['a'][~mask] *= 0.3 + expected_colors = colors.astype("float32").view(rgba_dtype) + expected_colors.shape = (5,) + expected_colors["a"][~mask] *= 0.3 assert_array_equal(mask, self.segment_plot.selected_mask) assert_array_equal(expected_colors, self.segment_plot.effective_colors) diff --git a/chaco/tests/serializable_base.py b/chaco/tests/serializable_base.py index 7f752b62a..f52b58e53 100644 --- a/chaco/tests/serializable_base.py +++ b/chaco/tests/serializable_base.py @@ -1,23 +1,25 @@ - - from traits.api import Bool, HasTraits, Str, Float, Enum, List, Int from chaco.serializable import Serializable + class Root(HasTraits): name = Str x = Float(0.0) y = Float(0.0) + class Shape(Serializable, Root): color = Enum("red", "green", "blue") filled = Bool(True) tools = List _pickles = ("tools", "filled", "color", "x") + class Circle(Shape): radius = Float(10.0) _pickles = ("radius",) + class Poly(Shape): numsides = Int(5) length = Float(5.0) diff --git a/chaco/tests/test_array_or_none.py b/chaco/tests/test_array_or_none.py index 78aef8a4f..5bb9f93ef 100644 --- a/chaco/tests/test_array_or_none.py +++ b/chaco/tests/test_array_or_none.py @@ -14,7 +14,7 @@ class TestArrayOrNone(unittest.TestCase): - """ Test that the FutureWarning from numpy concerning comparison of arrays + """Test that the FutureWarning from numpy concerning comparison of arrays against None are not issued. These warnings began with numpy 1.9. @@ -59,4 +59,3 @@ def test_label_axis(self): with warnings.catch_warnings(record=True) as w: axis.positions = np.arange(10) self.assertEqual(w, []) - diff --git a/chaco/tests/test_array_plot_data.py b/chaco/tests/test_array_plot_data.py index 9a2b6c9f4..0153c58ed 100644 --- a/chaco/tests/test_array_plot_data.py +++ b/chaco/tests/test_array_plot_data.py @@ -12,7 +12,7 @@ class ArrayPlotDataEventsCollector(HasTraits): data_changed_events = List - @observe('plot_data:data_changed') + @observe("plot_data:data_changed") def _got_data_changed_event(self, event): self.data_changed_events.append(event.new) @@ -35,17 +35,17 @@ def test_data_changed_events(self): plot_data = ArrayPlotData() with self.monitor_events(plot_data) as events: - plot_data.set_data('Grumpy', grumpy) - self.assertEqual(events, [{'added': ['Grumpy']}]) + plot_data.set_data("Grumpy", grumpy) + self.assertEqual(events, [{"added": ["Grumpy"]}]) # While we're here, check that get_data works as advertised. - grumpy_out = plot_data.get_data('Grumpy') + grumpy_out = plot_data.get_data("Grumpy") self.assertIs(grumpy_out, grumpy) with self.monitor_events(plot_data) as events: - plot_data.set_data('Grumpy', grumpy_too) - self.assertEqual(events, [{'changed': ['Grumpy']}]) + plot_data.set_data("Grumpy", grumpy_too) + self.assertEqual(events, [{"changed": ["Grumpy"]}]) with self.monitor_events(plot_data) as events: - plot_data.del_data('Grumpy') - self.assertEqual(events, [{'removed': ['Grumpy']}]) + plot_data.del_data("Grumpy") + self.assertEqual(events, [{"removed": ["Grumpy"]}]) diff --git a/chaco/tests/test_arraydatasource.py b/chaco/tests/test_arraydatasource.py index ee9abd169..f6480755a 100644 --- a/chaco/tests/test_arraydatasource.py +++ b/chaco/tests/test_arraydatasource.py @@ -15,7 +15,6 @@ class ArrayDataSourceTestCase(UnittestTools, unittest.TestCase): - def setUp(self): self.myarray = arange(10) self.mymask = array([i % 2 for i in self.myarray], dtype=bool) @@ -39,8 +38,7 @@ def test_basic_setup(self): def test_set_data(self): new_array = arange(0, 20, 2) - with self.assertTraitChanges(self.data_source, 'data_changed', - count=1): + with self.assertTraitChanges(self.data_source, "data_changed", count=1): self.data_source.set_data(new_array) assert_array_equal(new_array, self.data_source._data) @@ -50,17 +48,15 @@ def test_set_data(self): def test_set_data_ordered(self): new_array = arange(20, 0, -2) - with self.assertTraitChanges(self.data_source, 'data_changed', - count=1): - self.data_source.set_data(new_array, sort_order='descending') + with self.assertTraitChanges(self.data_source, "data_changed", count=1): + self.data_source.set_data(new_array, sort_order="descending") assert_array_equal(new_array, self.data_source._data) self.assertEqual(self.data_source.get_bounds(), (2, 20)) self.assertEqual(self.data_source.sort_order, "descending") def test_set_mask(self): - with self.assertTraitChanges(self.data_source, 'data_changed', - count=1): + with self.assertTraitChanges(self.data_source, "data_changed", count=1): self.data_source.set_mask(self.mymask) assert_array_equal(self.myarray, self.data_source._data) @@ -72,8 +68,7 @@ def test_remove_mask(self): self.data_source.set_mask(self.mymask) self.assertTrue(self.data_source.is_masked()) - with self.assertTraitChanges(self.data_source, 'data_changed', - count=1): + with self.assertTraitChanges(self.data_source, "data_changed", count=1): self.data_source.remove_mask() assert_array_equal(self.myarray, self.data_source._data) @@ -96,7 +91,7 @@ def test_get_data_mask(self): assert_array_equal(data, self.myarray) assert_array_equal(mask, self.mymask) - @unittest.skip('get_data_mask() fails in this case') + @unittest.skip("get_data_mask() fails in this case") def test_get_data_mask_no_data(self): data_source = ArrayDataSource(None) @@ -174,11 +169,10 @@ def test_bounds_negative_positive_inf(self): self.assertEqual(bounds, (-np.inf, np.inf)) def test_bounds_non_numeric(self): - myarray = np.array([u'abc', u'foo', - u'bar', u'def'], dtype=str) + myarray = np.array([u"abc", u"foo", u"bar", u"def"], dtype=str) data_source = ArrayDataSource(myarray) bounds = data_source.get_bounds() - self.assertEqual(bounds, (u'abc', u'def')) + self.assertEqual(bounds, (u"abc", u"def")) def test_data_size(self): # We know that ArrayDataTestCase always returns the exact length of @@ -190,53 +184,57 @@ def test_data_size(self): def test_reverse_map(self): # sort_order ascending myarray = arange(10) - data_source = ArrayDataSource(myarray, sort_order='ascending') + data_source = ArrayDataSource(myarray, sort_order="ascending") self.assertEqual(data_source.reverse_map(4.0), 4) # sort_order descending myarray = arange(10)[::-1] - data_source = ArrayDataSource(myarray, sort_order='descending') + data_source = ArrayDataSource(myarray, sort_order="descending") self.assertEqual(data_source.reverse_map(4.0), 5) # sort_order none myarray = array([12, 3, 0, 9, 2, 18, 3]) - data_source = ArrayDataSource(myarray, sort_order='none') + data_source = ArrayDataSource(myarray, sort_order="none") with self.assertRaises(NotImplementedError): data_source.reverse_map(3) def test_metadata(self): - self.assertEqual(self.data_source.metadata, - {'annotations': [], 'selections': []}) + self.assertEqual( + self.data_source.metadata, {"annotations": [], "selections": []} + ) def test_metadata_changed(self): - with self.assertTraitChanges(self.data_source, 'metadata_changed', - count=1): - self.data_source.metadata = {'new_metadata': True} + with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + self.data_source.metadata = {"new_metadata": True} def test_metadata_items_changed(self): - with self.assertTraitChanges(self.data_source, 'metadata_changed', - count=1): - self.data_source.metadata['new_metadata'] = True + with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + self.data_source.metadata["new_metadata"] = True def test_serialization_state(self): state = self.data_source.__getstate__() - self.assertNotIn('value_dimension', state) - self.assertNotIn('index_dimension', state) - self.assertNotIn('persist_data', state) + self.assertNotIn("value_dimension", state) + self.assertNotIn("index_dimension", state) + self.assertNotIn("persist_data", state) @unittest.skip("persist_data probably shouldn't be persisted") def test_serialization_state_no_persist(self): self.data_source.persist_data = False state = self.data_source.__getstate__() - self.assertNotIn('value_dimension', state) - self.assertNotIn('index_dimension', state) - self.assertNotIn('persist_data', state) - for key in ["_data", "_cached_mask", "_cached_bounds", "_min_index", - "_max_index"]: + self.assertNotIn("value_dimension", state) + self.assertNotIn("index_dimension", state) + self.assertNotIn("persist_data", state) + for key in [ + "_data", + "_cached_mask", + "_cached_bounds", + "_min_index", + "_max_index", + ]: self.assertIn(key, state) @unittest.skip("I think this is just broken") @@ -250,8 +248,9 @@ def test_serialization_post_load(self): self.assertEqual(unpickled_data_source._cached_bounds, ()) self.assertEqual(unpickled_data_source._cached_mask, None) - assert_array_equal(self.data_source.get_data(), - unpickled_data_source.get_data()) + assert_array_equal( + self.data_source.get_data(), unpickled_data_source.get_data() + ) mask = unpickled_data_source.get_data_mask()[1] assert_array_equal(mask, ones(10)) diff --git a/chaco/tests/test_base_utils.py b/chaco/tests/test_base_utils.py index 972e0b874..96be014b7 100644 --- a/chaco/tests/test_base_utils.py +++ b/chaco/tests/test_base_utils.py @@ -6,8 +6,15 @@ from numpy import arange, array, linspace, nan, ones from numpy.testing import assert_equal, assert_almost_equal, assert_array_equal -from chaco.base import (arg_find_runs, arg_true_runs, bin_search, find_runs, - intersect_range, reverse_map_1d, point_line_distance) +from chaco.base import ( + arg_find_runs, + arg_true_runs, + bin_search, + find_runs, + intersect_range, + reverse_map_1d, + point_line_distance, +) class BinSearchTestCase(unittest.TestCase): @@ -45,11 +52,11 @@ def test_descending_data(self): self.assertEqual(bin_search(ary, 5.1, -1), 4) self.assertEqual(bin_search(ary, 4.9, -1), 5) -class ReverseMap1DTestCase(unittest.TestCase): +class ReverseMap1DTestCase(unittest.TestCase): def test_ascending(self): ary = arange(10.0) - rmap = lambda x: reverse_map_1d(ary, x, 'ascending') + rmap = lambda x: reverse_map_1d(ary, x, "ascending") # inside bounds self.assertEqual(rmap(0.0), 0) @@ -67,7 +74,7 @@ def test_ascending(self): def test_ascending_floor(self): ary = arange(10.0) - rmap = lambda x: reverse_map_1d(ary, x, 'ascending', floor_only=True) + rmap = lambda x: reverse_map_1d(ary, x, "ascending", floor_only=True) # test rounding self.assertEqual(rmap(3.4), 3) @@ -76,7 +83,7 @@ def test_ascending_floor(self): def test_descending(self): ary = arange(10.0, 0.0, -1.0) - rmap = lambda x: reverse_map_1d(ary, x, 'descending') + rmap = lambda x: reverse_map_1d(ary, x, "descending") # inside bounds self.assertEqual(rmap(10.0), 0) @@ -94,7 +101,7 @@ def test_descending(self): def test_descending_floor(self): ary = arange(10.0, 0.0, -1.0) - rmap = lambda x: reverse_map_1d(ary, x, 'descending', floor_only=True) + rmap = lambda x: reverse_map_1d(ary, x, "descending", floor_only=True) # test rounding self.assertEqual(rmap(8.6), 1) @@ -113,7 +120,7 @@ def test_find_runs_start(self): def test_find_runs_end(self): x = array([18, 23, 24, 25]) - assert_equal(find_runs(x) , [[18], [23, 24, 25]]) + assert_equal(find_runs(x), [[18], [23, 24, 25]]) def test_find_runs_offset(self): # because of the nature of the find_runs algorithm, there may be @@ -131,80 +138,76 @@ def test_find_runs_none(self): def test_find_runs_descending(self): x = array([30, 41, 40, 39, 38, 37, 12]) - assert_equal(find_runs(x, order='descending'), \ - [[30], [41, 40, 39, 38, 37], [12]]) + assert_equal( + find_runs(x, order="descending"), [[30], [41, 40, 39, 38, 37], [12]] + ) def test_find_runs_flat(self): x = array([0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0]) - assert_equal(find_runs(x, order='flat'), \ - [[0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]]) + assert_equal( + find_runs(x, order="flat"), [[0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]] + ) class ArgFindRunsTestCase(unittest.TestCase): def test_arg_find_runs_middle(self): x = array([0, 8, 7, 8, 9, 2, 3, 4, 10]) - assert_equal(arg_find_runs(x), - [[0, 1], [1, 2], [2, 5], [5, 8], [8, 9]]) + assert_equal(arg_find_runs(x), [[0, 1], [1, 2], [2, 5], [5, 8], [8, 9]]) def test_arg_find_runs_start(self): x = array([3, 4, 5, 12, 9, 17]) - assert_equal(arg_find_runs(x) , [[0, 3], [3, 4], [4, 5], [5, 6]]) + assert_equal(arg_find_runs(x), [[0, 3], [3, 4], [4, 5], [5, 6]]) def test_arg_find_runs_end(self): x = array([18, 23, 24, 25]) - assert_equal(arg_find_runs(x) , [[0, 1], [1, 4]]) + assert_equal(arg_find_runs(x), [[0, 1], [1, 4]]) def test_arg_find_runs_offset(self): # because of the nature of the find_runs algorithm, there may be # fencepost errors with runs that start at x[1] or x[-2] x = array([10, 12, 13, 14, 28, 16]) - assert_equal(arg_find_runs(x) , [[0, 1], [1, 4], [4, 5], [5, 6]]) + assert_equal(arg_find_runs(x), [[0, 1], [1, 4], [4, 5], [5, 6]]) x = array([10, 15, 16, 17, 34]) - assert_equal(arg_find_runs(x) , [[0, 1], [1, 4], [4, 5]]) + assert_equal(arg_find_runs(x), [[0, 1], [1, 4], [4, 5]]) def test_arg_find_runs_none(self): x = array([]) - assert_equal(arg_find_runs(x) , []) + assert_equal(arg_find_runs(x), []) x = array([12, 15, 27]) - assert_equal(arg_find_runs(x) , [[0, 1], [1, 2], [2, 3]]) + assert_equal(arg_find_runs(x), [[0, 1], [1, 2], [2, 3]]) def test_arg_find_runs_descending(self): x = array([30, 41, 40, 39, 38, 37, 12]) - assert_equal(arg_find_runs(x, order='descending'), \ - [[0, 1], [1, 6], [6, 7]]) + assert_equal(arg_find_runs(x, order="descending"), [[0, 1], [1, 6], [6, 7]]) def test_arg_find_runs_flat(self): x = array([0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0]) - assert_equal(arg_find_runs(x, order='flat'), \ - [[0, 3], [3, 7], [7, 11]]) + assert_equal(arg_find_runs(x, order="flat"), [[0, 3], [3, 7], [7, 11]]) class TestArgTrueRuns(unittest.TestCase): - - def test_none(self): + def test_none(self): x = array([], dtype=bool) assert_equal(arg_true_runs(x), []) - def test_even(self): + def test_even(self): x = array([1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0], dtype=bool) assert_equal(arg_true_runs(x), [[0, 3], [7, 9]]) - def test_odd(self): + def test_odd(self): x = array([0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1], dtype=bool) assert_equal(arg_true_runs(x), [[3, 7], [9, 11]]) - def test_all_true(self): + def test_all_true(self): x = array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], dtype=bool) assert_equal(arg_true_runs(x), [[0, 11]]) - def test_all_false(self): + def test_all_false(self): x = array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=bool) assert_equal(arg_true_runs(x), []) - class PointLineDistanceTestCase(unittest.TestCase): - def test_horizontal_line(self): p1 = (10.0, 10.0) p2 = (60.0, 10.0) @@ -275,49 +278,49 @@ def test_high(self): def test_low_low(self): x = array([-2.0, -1.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [False]*2) + assert_array_equal(result, [False] * 2) def test_low_in(self): x = array([-1.0, 0.5]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*2) + assert_array_equal(result, [True] * 2) def test_low_lower_bound(self): x = array([-1.0, 0.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*2) + assert_array_equal(result, [True] * 2) def test_low_high(self): x = array([-2.0, 2.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*2) + assert_array_equal(result, [True] * 2) def test_in_in(self): x = array([0.75, 0.5]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*2) + assert_array_equal(result, [True] * 2) def test_in_high(self): x = array([-0.5, 2.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*2) + assert_array_equal(result, [True] * 2) def test_high_low(self): x = array([2.0, -2.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*2) + assert_array_equal(result, [True] * 2) def test_high_high(self): x = array([3.0, 2.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [False]*2) + assert_array_equal(result, [False] * 2) # three point tests def test_low_low_low(self): x = array([-3.0, -2.0, -1.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [False]*3) + assert_array_equal(result, [False] * 3) def test_in_low_low(self): x = array([0.5, -2.0, -1.0]) @@ -332,27 +335,27 @@ def test_high_low_low(self): def test_low_in_low(self): x = array([-3.0, 0.5, -1.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_in_in_low(self): x = array([0.75, 0.5, -1.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_high_in_low(self): x = array([2.0, 0.5, -1.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_low_high_low(self): x = array([-3.0, 2, -1.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_in_high_low(self): x = array([0.5, 2, -1.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_high_high_low(self): x = array([2.5, 2, -1.0]) @@ -377,27 +380,27 @@ def test_high_low_in(self): def test_low_in_in(self): x = array([-3.0, 0.5, 0.75]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_in_in_in(self): x = array([0.75, 0.5, 0.25]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_high_in_in(self): x = array([2.0, 0.5, 0.75]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_low_high_in(self): x = array([-3.0, 2, 0.5]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_in_high_in(self): x = array([0.5, 2, -1.0]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_high_high_in(self): x = array([2.5, 2, 0.5]) @@ -422,17 +425,17 @@ def test_high_low_high(self): def test_low_in_high(self): x = array([-3.0, 0.5, 2]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_in_in_high(self): x = array([0.75, 0.5, 2]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_high_in_high(self): x = array([2.0, 0.5, 2]) result = intersect_range(x, 0.0, 1.0) - assert_array_equal(result, [True]*3) + assert_array_equal(result, [True] * 3) def test_low_high_high(self): x = array([-3.0, 2, 3]) diff --git a/chaco/tests/test_border.py b/chaco/tests/test_border.py index 460b546ef..157aa5bda 100644 --- a/chaco/tests/test_border.py +++ b/chaco/tests/test_border.py @@ -18,20 +18,23 @@ def assertRavelEqual(self, x, y): self.assertTrue(alltrue(ravel(x) == ravel(y)), "\n%s\n !=\n%s" % (x, y)) def test_draw_border_simple(self): - """ Borders should have the correct height and width. - """ - size = (5,5) + """Borders should have the correct height and width.""" + size = (5, 5) container = Plot(padding=1, border_visible=True) container.outer_bounds = list(size) gc = PlotGraphicsContext(size) gc.render_component(container) - desired = array(((255, 255, 255, 255, 255, 255), - (255, 0, 0, 0, 0, 255), - (255, 0, 255, 255, 0, 255), - (255, 0, 255, 255, 0, 255), - (255, 0, 0, 0, 0, 255), - (255, 255, 255, 255, 255, 255))) - - actual = gc.bmp_array[:,:,0] + desired = array( + ( + (255, 255, 255, 255, 255, 255), + (255, 0, 0, 0, 0, 255), + (255, 0, 255, 255, 0, 255), + (255, 0, 255, 255, 0, 255), + (255, 0, 0, 0, 0, 255), + (255, 255, 255, 255, 255, 255), + ) + ) + + actual = gc.bmp_array[:, :, 0] self.assertRavelEqual(actual, desired) diff --git a/chaco/tests/test_cmap_image_plot.py b/chaco/tests/test_cmap_image_plot.py index 25681dea4..8afa3bca9 100644 --- a/chaco/tests/test_cmap_image_plot.py +++ b/chaco/tests/test_cmap_image_plot.py @@ -6,18 +6,23 @@ from enable.api import AbstractWindow from chaco.api import ( - CMapImagePlot, DataRange1D, DataRange2D, GridDataSource, GridMapper, - ImageData) + CMapImagePlot, + DataRange1D, + DataRange2D, + GridDataSource, + GridMapper, + ImageData, +) from chaco.default_colormaps import Spectral -class TestCMapImagePlot(unittest.TestCase): +class TestCMapImagePlot(unittest.TestCase): def test_redraw_on_color_mapper_update(self): # regression check for https://github.com/enthought/chaco/issues/220 npoints = 200 xs = numpy.linspace(-2 * numpy.pi, +2 * numpy.pi, npoints) - ys = numpy.linspace(-1.5*numpy.pi, +1.5*numpy.pi, npoints) + ys = numpy.linspace(-1.5 * numpy.pi, +1.5 * numpy.pi, npoints) x, y = numpy.meshgrid(xs, ys) z = y * x @@ -35,7 +40,7 @@ def test_redraw_on_color_mapper_update(self): ) cmap_plot._window = window = mock.Mock(spec=AbstractWindow) - #when + # when cmap_plot.color_mapper.updated = True # Then diff --git a/chaco/tests/test_colormapped_scatterplot.py b/chaco/tests/test_colormapped_scatterplot.py index 2618cf0e4..63fe1599c 100644 --- a/chaco/tests/test_colormapped_scatterplot.py +++ b/chaco/tests/test_colormapped_scatterplot.py @@ -4,12 +4,17 @@ from enable.compiled_path import CompiledPath # Chaco imports -from chaco.api import (ArrayDataSource, ColormappedScatterPlot, DataRange1D, - LinearMapper, PlotGraphicsContext, jet) +from chaco.api import ( + ArrayDataSource, + ColormappedScatterPlot, + DataRange1D, + LinearMapper, + PlotGraphicsContext, + jet, +) class TestColormappedScatterplot(unittest.TestCase): - def setUp(self): self.index = ArrayDataSource(arange(10)) self.value = ArrayDataSource(arange(10)) @@ -48,7 +53,7 @@ def test_scatter_render(self): def test_scatter_circle(self): """ Coverage test to check circles work """ - self.scatterplot.marker = 'circle' + self.scatterplot.marker = "circle" self.gc.render_component(self.scatterplot) actual = self.gc.bmp_array[:, :, :] @@ -56,7 +61,7 @@ def test_scatter_circle(self): @unittest.skip("Broken; see GH #232.") def test_scatter_custom(self): - """ Coverage test to check custom markers work... + """Coverage test to check custom markers work... XXX ...which apparently they currently don't. See #232. """ @@ -70,7 +75,7 @@ def test_scatter_custom(self): path.line_to(5, -5) path.line_to(-5, -5) - self.scatterplot.marker = 'custom' + self.scatterplot.marker = "custom" self.scatterplot.custom_symbol = path self.gc.render_component(self.scatterplot) diff --git a/chaco/tests/test_colormapper.py b/chaco/tests/test_colormapper.py index f09cfd88c..8fd8f31fd 100644 --- a/chaco/tests/test_colormapper.py +++ b/chaco/tests/test_colormapper.py @@ -6,13 +6,14 @@ class LinearSegmentedColormapTestCase(unittest.TestCase): - def setUp(self): """ Set up called before each test case. """ - _gray_data = {'red': [(0., 0, 0), (1., 1.0, 1.0)], - 'green': [(0., 0, 0), (1., 1.0, 1.0)], - 'blue': [(0., 0, 0), (1., 1.0, 1.0)]} + _gray_data = { + "red": [(0.0, 0, 0), (1.0, 1.0, 1.0)], + "green": [(0.0, 0, 0), (1.0, 1.0, 1.0)], + "blue": [(0.0, 0, 0), (1.0, 1.0, 1.0)], + } self.colormap = ColorMapper.from_segment_map(_gray_data) self.colormap.range = DataRange1D() @@ -26,9 +27,10 @@ def test_simple_map(self): expected = array([0.0, 0.5, 1.0]) - close = allclose(ravel(b[:,:1]), expected, atol=0.02) - self.assertTrue(close, - "Simple map failed. Expected %s. Got %s" % (expected, b[:,:1])) + close = allclose(ravel(b[:, :1]), expected, atol=0.02) + self.assertTrue( + close, "Simple map failed. Expected %s. Got %s" % (expected, b[:, :1]) + ) def test_change_min_max(self): """ Test that changing min_value and max_value does not break map. """ @@ -51,9 +53,12 @@ def test_change_min_max(self): datarange.remove(a) expected = array([0.0, 0.5, 1.0]) - close = allclose(ravel(b[:,:1]), expected, atol=0.02) - self.assertTrue(close, - "Changing min value broke map. Expected %s. Got %s" % (expected, b[:,:1])) + close = allclose(ravel(b[:, :1]), expected, atol=0.02) + self.assertTrue( + close, + "Changing min value broke map. Expected %s. Got %s" + % (expected, b[:, :1]), + ) # Update the max_value. datarange.high = 0.0 @@ -64,14 +69,17 @@ def test_change_min_max(self): datarange.remove(a) expected = array([0.0, 0.5, 1.0]) - close = allclose(ravel(b[:,:1]), expected, atol=0.02) - self.assertTrue(close, - "Changing min value broke map. Expected %s. Got %s" % (expected, b[:,:1])) + close = allclose(ravel(b[:, :1]), expected, atol=0.02) + self.assertTrue( + close, + "Changing min value broke map. Expected %s. Got %s" + % (expected, b[:, :1]), + ) def test_array_factory(self): """ Test that the array factory creates valid colormap. """ - colors = array([[0.0,0.0,0.0], [1.0,1.0,1.0]]) + colors = array([[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]]) cm = ColorMapper.from_palette_array(colors) cm.range = DataRange1D() @@ -82,36 +90,43 @@ def test_array_factory(self): expected = array([0.0, 0.5, 1.0]) - self.assertTrue(allclose(ravel(b[:,:1]), expected, atol=0.02), - "Array factory failed. Expected %s. Got %s" % (expected, b[:,:1])) + self.assertTrue( + allclose(ravel(b[:, :1]), expected, atol=0.02), + "Array factory failed. Expected %s. Got %s" % (expected, b[:, :1]), + ) def test_alpha_palette(self): - """ Create a colormap with a varying alpha channel from a palette array. - """ - cm = ColorMapper.from_palette_array([[0.0,0.0,0.0,0.5],[1.0,1.0,1.0,1.0]]) - sd = {'alpha': [(0.0, 0.5, 0.5), (1.0, 1.0, 1.0)], - 'blue': [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], - 'green': [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], - 'red': [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]} + """Create a colormap with a varying alpha channel from a palette array.""" + cm = ColorMapper.from_palette_array( + [[0.0, 0.0, 0.0, 0.5], [1.0, 1.0, 1.0, 1.0]] + ) + sd = { + "alpha": [(0.0, 0.5, 0.5), (1.0, 1.0, 1.0)], + "blue": [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], + "green": [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], + "red": [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], + } assert cm._segmentdata == sd def test_alpha_segment_data(self): - """ Create a colormap with a varying alpha channel from segment data. - """ - sd = {'alpha': [(0.0, 0.5, 0.5), (1.0, 1.0, 1.0)], - 'blue': [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], - 'green': [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], - 'red': [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]} + """Create a colormap with a varying alpha channel from segment data.""" + sd = { + "alpha": [(0.0, 0.5, 0.5), (1.0, 1.0, 1.0)], + "blue": [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], + "green": [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], + "red": [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], + } cm = ColorMapper.from_segment_map(sd) assert cm._segmentdata == sd def test_no_alpha(self): - """ Check that the defaults when no alpha is specified are correct. - """ - sd = {'alpha': [(0.0, 1.0, 1.0), (1.0, 1.0, 1.0)], - 'blue': [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], - 'green': [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], - 'red': [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)]} + """Check that the defaults when no alpha is specified are correct.""" + sd = { + "alpha": [(0.0, 1.0, 1.0), (1.0, 1.0, 1.0)], + "blue": [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], + "green": [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], + "red": [(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)], + } assert self.colormap._segmentdata == sd diff --git a/chaco/tests/test_contour.py b/chaco/tests/test_contour.py index cb68dbb93..228a3faea 100644 --- a/chaco/tests/test_contour.py +++ b/chaco/tests/test_contour.py @@ -7,18 +7,12 @@ class TestContour(unittest.TestCase): - def test_contour_trace_levels_no_mask(self): # Given xs = np.array([0, 1, 2, 3]) ys = np.array([10, 20, 30, 40]) xg, yg = np.meshgrid(xs, ys) - data = np.array([ - [0, 0, 1, 2], - [0, 1, 2, 3], - [1, 2, 0, 3], - [2, 3, 3, 3] - ]) + data = np.array([[0, 0, 1, 2], [0, 1, 2, 3], [1, 2, 0, 3], [2, 3, 3, 3]]) mask = np.ones(data.shape, dtype=bool) # When @@ -27,15 +21,9 @@ def test_contour_trace_levels_no_mask(self): # Then levels = c.trace(0.0) self.assertEqual(len(levels), 2) + self._check_level(levels[0], [1.0, 1.0, 0.0, 0.0], [10.0, 10.0, 20.0, 20.0]) self._check_level( - levels[0], - [1.0, 1.0, 0.0, 0.0], - [10.0, 10.0, 20.0, 20.0] - ) - self._check_level( - levels[1], - [2.0, 2.0, 2.0, 2.0, 2.0], - [30.0, 30.0, 30.0, 30.0, 30.0] + levels[1], [2.0, 2.0, 2.0, 2.0, 2.0], [30.0, 30.0, 30.0, 30.0, 30.0] ) levels = c.trace(1.0) @@ -43,21 +31,21 @@ def test_contour_trace_levels_no_mask(self): self._check_level( levels[0], [2.0, 2.0, 1.0, 1.0, 0.0, 0.0], - [10.0, 10.0, 20.0, 20.0, 30.0, 30.0] + [10.0, 10.0, 20.0, 20.0, 30.0, 30.0], ) self._check_level( levels[1], [2.0, 1.5, 2.0, 2.33333333, 2.0], - [25.0, 30.0, 33.33333333, 30.0, 25.0] + [25.0, 30.0, 33.33333333, 30.0, 25.0], ) levels = c.trace(2.0) self.assertEqual(len(levels), 1) self._check_level( levels[0], - [3.0, 2.0, 2.66666667, 2.0, 1.0, 0.0], - [10.0, 20.0, 30.0, 36.66666667, 30.0, 40.0] + [3.0, 2.0, 2.66666667, 2.0, 1.0, 0.0], + [10.0, 20.0, 30.0, 36.66666667, 30.0, 40.0], ) levels = c.trace(2.5) @@ -65,7 +53,7 @@ def test_contour_trace_levels_no_mask(self): self._check_level( levels[0], [3.0, 2.5, 2.83333333, 2.0, 1.0, 0.5], - [15.0, 20.0, 30.0, 38.33333333, 35.0, 40.0] + [15.0, 20.0, 30.0, 38.33333333, 35.0, 40.0], ) # Note: the level for z = 3.0 lies entirely on the boundary of the diff --git a/chaco/tests/test_data_frame_plot_data.py b/chaco/tests/test_data_frame_plot_data.py index a51e10a87..38664f6ab 100644 --- a/chaco/tests/test_data_frame_plot_data.py +++ b/chaco/tests/test_data_frame_plot_data.py @@ -9,6 +9,7 @@ try: from pandas import DataFrame + pandas_imported = True except ImportError: @@ -20,7 +21,7 @@ class DataFramePlotDataEventsCollector(HasTraits): data_changed_events = List - @observe('plot_data:data_changed') + @observe("plot_data:data_changed") def _got_data_changed_event(self, event): self.data_changed_events.append(event.new) @@ -45,26 +46,26 @@ def test_data_changed_events(self): df = DataFrame(index=np.arange(16)) plot_data = DataFramePlotData(data_frame=df) - assert_array_equal(plot_data.get_data('index'), df.index.values) + assert_array_equal(plot_data.get_data("index"), df.index.values) with monitor_events(plot_data) as events: - plot_data.set_data('arr', arr) - self.assertEqual(events, [{'added': ['arr']}]) + plot_data.set_data("arr", arr) + self.assertEqual(events, [{"added": ["arr"]}]) - assert_array_equal(df['arr'].values, arr) + assert_array_equal(df["arr"].values, arr) # While we're here, check that get_data works as advertised. - out = plot_data.get_data('arr') + out = plot_data.get_data("arr") assert_array_equal(arr, out) with monitor_events(plot_data) as events: - plot_data.set_data('arr', arr2) - self.assertEqual(events, [{'changed': ['arr']}]) - assert_array_equal(df['arr'].values, arr2) + plot_data.set_data("arr", arr2) + self.assertEqual(events, [{"changed": ["arr"]}]) + assert_array_equal(df["arr"].values, arr2) with monitor_events(plot_data) as events: - plot_data.del_data('arr') - self.assertEqual(events, [{'removed': ['arr']}]) + plot_data.del_data("arr") + self.assertEqual(events, [{"removed": ["arr"]}]) @unittest.skipUnless(pandas_imported, "Requires pandas") def test_no_index_column(self): @@ -74,18 +75,18 @@ def test_no_index_column(self): df = DataFrame(index=idx) plot_data = DataFramePlotData(data_frame=df) - assert_array_equal(plot_data.get_data('index'), df.index.values) + assert_array_equal(plot_data.get_data("index"), df.index.values) # Can set 'index' with monitor_events(plot_data) as events: - plot_data.set_data('index', arr) - self.assertEqual(events, [{'changed': ['index']}]) - self.assertNotIn('index', df.columns) + plot_data.set_data("index", arr) + self.assertEqual(events, [{"changed": ["index"]}]) + self.assertNotIn("index", df.columns) assert_array_equal(df.index.values, arr) # Cannot remove 'index' column with self.assertRaises(KeyError): - plot_data.del_data('index') + plot_data.del_data("index") @unittest.skipUnless(pandas_imported, "Requires pandas") def test_index_column(self): @@ -93,23 +94,23 @@ def test_index_column(self): idx = np.arange(16) arr = np.zeros(16) arr2 = np.ones(16) - data = {'index': arr} + data = {"index": arr} df = DataFrame(data, index=idx) plot_data = DataFramePlotData(data_frame=df) - assert_array_equal(plot_data.get_data('index'), df['index'].values) + assert_array_equal(plot_data.get_data("index"), df["index"].values) # Can set 'index' column with monitor_events(plot_data) as events: - plot_data.set_data('index', arr2) - self.assertEqual(events, [{'changed': ['index']}]) - assert_array_equal(df['index'].values, arr2) + plot_data.set_data("index", arr2) + self.assertEqual(events, [{"changed": ["index"]}]) + assert_array_equal(df["index"].values, arr2) # Can remove 'index' column with monitor_events(plot_data) as events: - plot_data.del_data('index') - self.assertNotIn('index', df.columns) + plot_data.del_data("index") + self.assertNotIn("index", df.columns) # Since there is always an index, this will register a 'changed' # event instead of a 'removed' event. - self.assertEqual(events, [{'changed': ['index']}]) - assert_array_equal(plot_data.get_data('index'), df.index.values) + self.assertEqual(events, [{"changed": ["index"]}]) + assert_array_equal(plot_data.get_data("index"), df.index.values) diff --git a/chaco/tests/test_data_label.py b/chaco/tests/test_data_label.py index 08a4c3728..9cfbc6c0e 100644 --- a/chaco/tests/test_data_label.py +++ b/chaco/tests/test_data_label.py @@ -4,24 +4,24 @@ class DataLabelTestCase(unittest.TestCase): - def test_data_label_arrow_not_visible(self): # Regression test for https://github.com/enthought/chaco/issues/281 # Before the problem was fixed, this test (specifically, using # arrow_visible=False in the DataLabel constructor) would raise an # exception because of an undefined reference. size = (50, 50) - plot = create_scatter_plot(data=[list(range(10)), - list(range(10))]) - label = DataLabel(component=plot, - data_point=(4, 4), - marker_color="red", - marker_size=3, - label_position=(20, 50), - label_style='bubble', - label_text="Something interesting", - label_format="at x=%(x).2f, y=%(y).2f", - arrow_visible=False) + plot = create_scatter_plot(data=[list(range(10)), list(range(10))]) + label = DataLabel( + component=plot, + data_point=(4, 4), + marker_color="red", + marker_size=3, + label_position=(20, 50), + label_style="bubble", + label_text="Something interesting", + label_format="at x=%(x).2f, y=%(y).2f", + arrow_visible=False, + ) plot.overlays.append(label) plot.outer_bounds = list(size) gc = PlotGraphicsContext(size) diff --git a/chaco/tests/test_data_view.py b/chaco/tests/test_data_view.py index 26c870901..0c0fc2e5a 100644 --- a/chaco/tests/test_data_view.py +++ b/chaco/tests/test_data_view.py @@ -1,20 +1,18 @@ - import unittest from chaco.api import DataRange2D, DataView, GridDataSource class DataViewTestCase(unittest.TestCase): - def test_empty(self): dv = DataView() - self.assertTrue(dv.orientation=="h") - self.assertTrue(dv.index_scale=="linear") - self.assertTrue(dv.bgcolor=="white") - self.assertTrue(dv.overlay_border==True) + self.assertTrue(dv.orientation == "h") + self.assertTrue(dv.index_scale == "linear") + self.assertTrue(dv.bgcolor == "white") + self.assertTrue(dv.overlay_border == True) - self.assertTrue(dv.range2d.x_range==dv.index_range) - self.assertTrue(dv.range2d.y_range==dv.value_range) + self.assertTrue(dv.range2d.x_range == dv.index_range) + self.assertTrue(dv.range2d.y_range == dv.value_range) def test_orientation(self): dv = DataView() @@ -31,9 +29,9 @@ def test_range2d_changed(self): old_range = dv.range2d r = DataRange2D() - self.assertTrue(dv.range2d.sources==[ds]) + self.assertTrue(dv.range2d.sources == [ds]) dv.range2d = r - self.assertTrue(dv.range2d.sources==[ds]) - self.assertTrue(old_range.sources==[]) + self.assertTrue(dv.range2d.sources == [ds]) + self.assertTrue(old_range.sources == []) self.assertTrue(dv.range2d.x_range is dv.index_mapper.range) self.assertTrue(dv.range2d.y_range is dv.value_mapper.range) diff --git a/chaco/tests/test_datarange_1d.py b/chaco/tests/test_datarange_1d.py index 7c528c97f..2a9d79926 100644 --- a/chaco/tests/test_datarange_1d.py +++ b/chaco/tests/test_datarange_1d.py @@ -17,13 +17,12 @@ class Foo(HasTraits): range_updated = Bool(False) - @observe('range.updated') + @observe("range.updated") def range_changed(self, event): self.range_updated = True class DataRangeTestCase(unittest.TestCase): - def test_empty_range(self): r = DataRange1D() self.assertEqual(r.low, -inf) @@ -86,13 +85,13 @@ def test_set_bounds4(self): """Set set_bounds() with high='track'.""" foo = Foo(range=DataRange1D(tracking_amount=1.0)) foo.range.low_setting = 0.0 - foo.range.high_setting = 'track' + foo.range.high_setting = "track" # Paranoid check first (not the main point of this test): self.assertEqual(foo.range.low, 0.0) self.assertEqual(foo.range.high, 1.0) # Now reset foo's range_updated flag and set the bounds with set_bounds(). foo.range_updated = False - foo.range.set_bounds(100.0, 'track') + foo.range.set_bounds(100.0, "track") # Verify the values. self.assertEqual(foo.range.low, 100.0) self.assertEqual(foo.range.high, 101.0) @@ -102,14 +101,14 @@ def test_set_bounds4(self): def test_set_bounds5(self): """Set set_bounds() with low='track'.""" foo = Foo(range=DataRange1D(tracking_amount=1.0)) - foo.range.low_setting = 'track' + foo.range.low_setting = "track" foo.range.high_setting = 1.0 # Paranoid check first (not the main point of this test): self.assertEqual(foo.range.low, 0.0) self.assertEqual(foo.range.high, 1.0) # Now reset foo's range_updated flag and set the bounds with set_bounds(). foo.range_updated = False - foo.range.set_bounds('track', 100.0) + foo.range.set_bounds("track", 100.0) # Verify the values. self.assertEqual(foo.range.low, 99.0) self.assertEqual(foo.range.high, 100.0) @@ -119,7 +118,7 @@ def test_set_bounds5(self): def test_set_tracking_amount(self): """Test setting the tracking amount using the set_tracking_amount() method.""" foo = Foo(range=DataRange1D(tracking_amount=1.0)) - foo.range.low_setting = 'track' + foo.range.low_setting = "track" foo.range.high_setting = 1.0 # Paranoid check first (not the main point of this test): self.assertEqual(foo.range.low, 0.0) @@ -136,7 +135,7 @@ def test_set_tracking_amount(self): def test_scale_tracking_amount(self): """Test setting the tracking amount using the scale_tracking_amount() method.""" foo = Foo(range=DataRange1D(tracking_amount=1.0)) - foo.range.low_setting = 'track' + foo.range.low_setting = "track" foo.range.high_setting = 1.0 # Paranoid check first (not the main point of this test): self.assertEqual(foo.range.low, 0.0) @@ -213,39 +212,39 @@ def test_multi_source(self): def test_clip_data(self): r = DataRange1D(low=2.0, high=10.0) ary = array([1, 3, 4, 9.8, 10.2, 12]) - assert_equal(r.clip_data(ary) , array([3.0,4.0,9.8])) + assert_equal(r.clip_data(ary), array([3.0, 4.0, 9.8])) r = DataRange1D(low=10, high=20) ary = array([5, 10, 15, 20, 25, 30]) - assert_equal(r.clip_data(ary) , array([10, 15, 20])) - assert_equal(r.clip_data(ary[::-1]) , array([20, 15, 10])) + assert_equal(r.clip_data(ary), array([10, 15, 20])) + assert_equal(r.clip_data(ary[::-1]), array([20, 15, 10])) r = DataRange1D(low=2.0, high=2.5) - assert_equal(len(r.clip_data(ary)) , 0) + assert_equal(len(r.clip_data(ary)), 0) def test_mask_data(self): r = DataRange1D(low=2.0, high=10.0) ary = array([1, 3, 4, 9.8, 10.2, 12]) - assert_equal(r.mask_data(ary) , array([0,1,1,1,0,0], 'b')) + assert_equal(r.mask_data(ary), array([0, 1, 1, 1, 0, 0], "b")) r = DataRange1D(low=10, high=20) ary = array([5, 10, 15, 20, 25, 30]) - target_mask = array([0,1,1,1,0,0], 'b') - assert_equal(r.mask_data(ary) , target_mask) - assert_equal(r.mask_data(ary[::-1]) , target_mask[::-1]) + target_mask = array([0, 1, 1, 1, 0, 0], "b") + assert_equal(r.mask_data(ary), target_mask) + assert_equal(r.mask_data(ary[::-1]), target_mask[::-1]) r = DataRange1D(low=2.0, high=2.5) - assert_equal(r.mask_data(ary) , zeros(len(ary))) + assert_equal(r.mask_data(ary), zeros(len(ary))) def test_bound_data(self): r = DataRange1D(low=2.9, high=6.1) ary = arange(10) - assert_equal(r.bound_data(ary) , (3,6)) + assert_equal(r.bound_data(ary), (3, 6)) # test non-monotonic data - ary = array([-5,-4,-7,-8,-2,1,2,3,4,5,4,3,8,9,10,9,8]) + ary = array([-5, -4, -7, -8, -2, 1, 2, 3, 4, 5, 4, 3, 8, 9, 10, 9, 8]) bounds = r.bound_data(ary) - assert_equal(bounds , (7,11)) + assert_equal(bounds, (7, 11)) def test_custom_bounds_func(self): def custom_func(low, high, margin, tight_bounds): @@ -253,14 +252,14 @@ def custom_func(low, high, margin, tight_bounds): assert_equal(high, 9.0) assert_equal(tight_bounds, False) assert_equal(margin, 1.0) - return -999., 999. + return -999.0, 999.0 r = DataRange1D(tight_bounds=False, margin=1.0, bounds_func=custom_func) ary = arange(10.0) ds = ArrayDataSource(ary) r.sources.append(ds) - assert_equal(r.low, -999.) - assert_equal(r.high, 999.) + assert_equal(r.low, -999.0) + assert_equal(r.high, 999.0) def test_inf_in_source(self): r = DataRange1D() @@ -270,7 +269,7 @@ def test_inf_in_source(self): self.assertEqual(r.low, 1.0) self.assertEqual(r.high, inf) data = array([-100.0, 0.0, 100.0]) - assert_equal(r.clip_data(data) , array([100.0])) + assert_equal(r.clip_data(data), array([100.0])) r = DataRange1D() ary2 = array([-inf, 1.0]) diff --git a/chaco/tests/test_datarange_2d.py b/chaco/tests/test_datarange_2d.py index 66337259f..721d7baf0 100644 --- a/chaco/tests/test_datarange_2d.py +++ b/chaco/tests/test_datarange_2d.py @@ -1,4 +1,3 @@ - import unittest from numpy import alltrue, arange, array, ravel, transpose, zeros, inf, isinf @@ -8,64 +7,63 @@ class DataRange2DTestCase(unittest.TestCase): - def test_empty_range(self): r = DataRange2D() - assert_ary_(r.low,array([-inf,-inf])) - assert_ary_(r.high,array([inf,inf])) - self.assertTrue(r.low_setting == ('auto','auto')) - self.assertTrue(r.high_setting == ('auto', 'auto')) - r.low = array([5.0,5.0]) - r.high = array([10.0,10.0]) - assert_ary_(r.low_setting, array([5.0,5.0])) - assert_ary_(r.high_setting, array([10.0,10.0])) - assert_ary_(r.low,array([5.0,5.0])) - assert_ary_(r.high, array([10.0,10.0])) + assert_ary_(r.low, array([-inf, -inf])) + assert_ary_(r.high, array([inf, inf])) + self.assertTrue(r.low_setting == ("auto", "auto")) + self.assertTrue(r.high_setting == ("auto", "auto")) + r.low = array([5.0, 5.0]) + r.high = array([10.0, 10.0]) + assert_ary_(r.low_setting, array([5.0, 5.0])) + assert_ary_(r.high_setting, array([10.0, 10.0])) + assert_ary_(r.low, array([5.0, 5.0])) + assert_ary_(r.high, array([10.0, 10.0])) def test_single_source(self): r = DataRange2D() - x = arange(10.) - y = arange(0.,100.,10.) - ds = PointDataSource(transpose(array([x,y])), sort_order="none") + x = arange(10.0) + y = arange(0.0, 100.0, 10.0) + ds = PointDataSource(transpose(array([x, y])), sort_order="none") r.add(ds) - assert_ary_(r.low, array([0.,0.])) - assert_ary_(r.high, array([9.0,90.0])) + assert_ary_(r.low, array([0.0, 0.0])) + assert_ary_(r.high, array([9.0, 90.0])) - r.low = [3.0,30.0] - r.high = [6.0,60.0] - assert_ary_(r.low_setting, array([3.0,30.0])) - assert_ary_(r.high_setting, array([6.0,60.0])) - assert_ary_(r.low, array([3.0,30.0])) - assert_ary_(r.high, array([6.0,60.0])) + r.low = [3.0, 30.0] + r.high = [6.0, 60.0] + assert_ary_(r.low_setting, array([3.0, 30.0])) + assert_ary_(r.high_setting, array([6.0, 60.0])) + assert_ary_(r.low, array([3.0, 30.0])) + assert_ary_(r.high, array([6.0, 60.0])) r.refresh() - assert_ary_(r.low_setting, array([3.0,30.0])) - assert_ary_(r.high_setting, array([6.0,60.0])) - assert_ary_(r.low, array([3.0,30.0])) - assert_ary_(r.high, array([6.0,60.0])) + assert_ary_(r.low_setting, array([3.0, 30.0])) + assert_ary_(r.high_setting, array([6.0, 60.0])) + assert_ary_(r.low, array([3.0, 30.0])) + assert_ary_(r.high, array([6.0, 60.0])) - r.low = ('auto', 'auto') - self.assertTrue(r.low_setting == ('auto', 'auto')) - assert_ary_(r.low, array([0.0,0.0])) + r.low = ("auto", "auto") + self.assertTrue(r.low_setting == ("auto", "auto")) + assert_ary_(r.low, array([0.0, 0.0])) def test_constant_values(self): r = DataRange2D() - ds = PointDataSource(array([[5.0,5.0]]), sort_order="none") + ds = PointDataSource(array([[5.0, 5.0]]), sort_order="none") r.add(ds) # A constant value > 1.0, by default, gets a range that brackets # it to the nearest power of ten above and below - assert_ary_(r.low, array([1.0,1.0])) - assert_ary_(r.high, array([10.0,10.0])) + assert_ary_(r.low, array([1.0, 1.0])) + assert_ary_(r.high, array([10.0, 10.0])) r.remove(ds) - ds = PointDataSource(array([[31.4,9.7]])) + ds = PointDataSource(array([[31.4, 9.7]])) r.add(ds) - assert_ary_(r.low, array([10.0,1.0])) - assert_ary_(r.high, array([100.0,10.0])) + assert_ary_(r.low, array([10.0, 1.0])) + assert_ary_(r.high, array([100.0, 10.0])) r.remove(ds) - ds = PointDataSource(array([[0.125,0.125]])) + ds = PointDataSource(array([[0.125, 0.125]])) r.add(ds) assert_ary_(r.low, array([0.0, 0.0])) assert_ary_(r.high, array([0.25, 0.25])) @@ -77,70 +75,70 @@ def test_constant_values(self): assert_ary_(r.high, array([0.0, 0.0])) def test_multi_source(self): - x = arange(10.) - y = arange(0.,100.,10.) - foo = transpose(array([x,y])) - bar = transpose(array([y,x])) + x = arange(10.0) + y = arange(0.0, 100.0, 10.0) + foo = transpose(array([x, y])) + bar = transpose(array([y, x])) ds1 = PointDataSource(foo) ds2 = PointDataSource(bar) r = DataRange2D(ds1, ds2) - assert_ary_(r.low, [0.0,0.0]) - assert_ary_(r.high, [90.,90.]) + assert_ary_(r.low, [0.0, 0.0]) + assert_ary_(r.high, [90.0, 90.0]) def test_grid_source(self): - test_xd1 = array([1,2,3]) + test_xd1 = array([1, 2, 3]) test_yd1 = array([1.5, 0.5, -0.5, -1.5]) - test_sort_order1 = ('ascending', 'descending') - test_xd2 = array([0,50,100]) + test_sort_order1 = ("ascending", "descending") + test_xd2 = array([0, 50, 100]) test_yd2 = array([0.5, 0.75, 1]) - ds1 = GridDataSource(xdata=test_xd1, ydata=test_yd1, - sort_order=test_sort_order1) + ds1 = GridDataSource( + xdata=test_xd1, ydata=test_yd1, sort_order=test_sort_order1 + ) ds2 = GridDataSource(xdata=test_xd2, ydata=test_yd2) r = DataRange2D() r.add(ds1) - assert_ary_(r.low, array([1,-1.5])) - assert_ary_(r.high, array([3,1.5])) + assert_ary_(r.low, array([1, -1.5])) + assert_ary_(r.high, array([3, 1.5])) r.add(ds2) - assert_ary_(r.low, array([0.0,-1.5])) - assert_ary_(r.high, array([100,1.5])) + assert_ary_(r.low, array([0.0, -1.5])) + assert_ary_(r.high, array([100, 1.5])) r.remove(ds1) - assert_ary_(r.low, array([0,0.5])) - assert_ary_(r.high, array([100,1])) + assert_ary_(r.low, array([0, 0.5])) + assert_ary_(r.high, array([100, 1])) r.remove(ds2) - assert_ary_(r.low, array([-inf,-inf])) - assert_ary_(r.high, array([inf,inf])) - + assert_ary_(r.low, array([-inf, -inf])) + assert_ary_(r.high, array([inf, inf])) def test_set_bounds(self): - test_xd = array([-10,10]) - test_yd = array([-10,10]) + test_xd = array([-10, 10]) + test_yd = array([-10, 10]) ds = GridDataSource(xdata=test_xd, ydata=test_yd) r = DataRange2D() - r.set_bounds((-1,-2), (3,4)) - assert_ary_(r.low, array([-1,-2])) - assert_ary_(r.high, array([3,4])) + r.set_bounds((-1, -2), (3, 4)) + assert_ary_(r.low, array([-1, -2])) + assert_ary_(r.high, array([3, 4])) r.add(ds) - assert_ary_(r.low, array([-1,-2])) + assert_ary_(r.low, array([-1, -2])) - r.low_setting = ('auto','auto') - assert_ary_(r.low, array([-10,-10])) - assert_ary_(r.high, array([3,4])) + r.low_setting = ("auto", "auto") + assert_ary_(r.low, array([-10, -10])) + assert_ary_(r.high, array([3, 4])) - r.high_setting = ('auto','auto') - assert_ary_(r.low, array([-10,-10])) - assert_ary_(r.high, array([10,10])) + r.high_setting = ("auto", "auto") + assert_ary_(r.low, array([-10, -10])) + assert_ary_(r.high, array([10, 10])) - r.set_bounds((-100,-100), (100,100)) - assert_ary_(r.low, array([-100,-100])) - assert_ary_(r.high, array([100,100])) + r.set_bounds((-100, -100), (100, 100)) + assert_ary_(r.low, array([-100, -100])) + assert_ary_(r.high, array([100, 100])) def test_reset_bounds(self): r = DataRange2D() @@ -154,48 +152,49 @@ def test_reset_bounds(self): r.reset() - self.assertEqual(r.low_setting, ('auto', 'auto')) - self.assertEqual(r.high_setting, ('auto', 'auto')) - self.assertEqual(r.x_range.low_setting, 'auto') - self.assertEqual(r.y_range.low_setting, 'auto') - self.assertEqual(r.x_range.high_setting, 'auto') - self.assertEqual(r.y_range.high_setting, 'auto') - + self.assertEqual(r.low_setting, ("auto", "auto")) + self.assertEqual(r.high_setting, ("auto", "auto")) + self.assertEqual(r.x_range.low_setting, "auto") + self.assertEqual(r.y_range.low_setting, "auto") + self.assertEqual(r.x_range.high_setting, "auto") + self.assertEqual(r.y_range.high_setting, "auto") def test_clip_data(self): - r = DataRange2D(low=[2.0,5.0], high=[10.0,8.0]) - x= arange(10.0) - y= arange(0.,20.,2.) - ary= transpose(array([x,y])) - assert_equal(r.clip_data(ary) , array([[3.,6.],[4.,8.]])) - - r = DataRange2D(low=[10.,10.], high=[20.,20.]) - x= arange(10.0,30.,2.) - y= arange(0.,40.,4.) - ary = transpose(array([x,y])) - assert_equal(r.clip_data(ary) , array([[16.,12.],[18.,16.],[20.,20.]])) - assert_equal(r.clip_data(ary[::-1]) , array([[20,20], [18,16], [16,12]])) + r = DataRange2D(low=[2.0, 5.0], high=[10.0, 8.0]) + x = arange(10.0) + y = arange(0.0, 20.0, 2.0) + ary = transpose(array([x, y])) + assert_equal(r.clip_data(ary), array([[3.0, 6.0], [4.0, 8.0]])) + + r = DataRange2D(low=[10.0, 10.0], high=[20.0, 20.0]) + x = arange(10.0, 30.0, 2.0) + y = arange(0.0, 40.0, 4.0) + ary = transpose(array([x, y])) + assert_equal( + r.clip_data(ary), array([[16.0, 12.0], [18.0, 16.0], [20.0, 20.0]]) + ) + assert_equal(r.clip_data(ary[::-1]), array([[20, 20], [18, 16], [16, 12]])) def test_mask_data(self): - r = DataRange2D(low=[2.0,5.0], high=[10.0,18.0]) + r = DataRange2D(low=[2.0, 5.0], high=[10.0, 18.0]) x = array([1, 3, 4, 9.8, 10.2, 12]) y = array([5, 3, 7, 12, 18, 6]) - ary = transpose(array([x,y])) - assert_equal(r.mask_data(ary) , array([0,0,1,1,0,0], 'b')) + ary = transpose(array([x, y])) + assert_equal(r.mask_data(ary), array([0, 0, 1, 1, 0, 0], "b")) - r = DataRange2D(low=[10.,15.], high=[20.,25.]) + r = DataRange2D(low=[10.0, 15.0], high=[20.0, 25.0]) x = array([5, 10, 15, 20, 25, 30]) y = array([5, 10, 15, 20, 25, 30]) - ary = transpose(array([x,y])) - target_mask = array([0,0,1,1,0,0], 'b') - assert_equal(r.mask_data(ary) , target_mask) - assert_equal(r.mask_data(ary[::-1]) , target_mask[::-1]) + ary = transpose(array([x, y])) + target_mask = array([0, 0, 1, 1, 0, 0], "b") + assert_equal(r.mask_data(ary), target_mask) + assert_equal(r.mask_data(ary[::-1]), target_mask[::-1]) - r = DataRange2D(low=[2.0,5.0], high=[2.5,9.0]) - assert_equal(r.mask_data(ary) , zeros(len(ary))) + r = DataRange2D(low=[2.0, 5.0], high=[2.5, 9.0]) + assert_equal(r.mask_data(ary), zeros(len(ary))) -def assert_close_(desired,actual): +def assert_close_(desired, actual): diff_allowed = 1e-5 diff = abs(ravel(actual) - ravel(desired)) for d in diff: @@ -203,8 +202,9 @@ def assert_close_(desired,actual): assert_(alltrue(d <= diff_allowed)) return + def assert_ary_(desired, actual): - if (desired == 'auto'): - assert_equal(actual, 'auto') + if desired == "auto": + assert_equal(actual, "auto") for d in range(len(desired)): assert_equal(desired[d], actual[d]) diff --git a/chaco/tests/test_default_colormaps.py b/chaco/tests/test_default_colormaps.py index 210cc0a83..52565683c 100644 --- a/chaco/tests/test_default_colormaps.py +++ b/chaco/tests/test_default_colormaps.py @@ -1,4 +1,4 @@ -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Copyright (c) 2014, Enthought, Inc. # All rights reserved. # @@ -8,7 +8,7 @@ # is also available online at http://www.enthought.com/licenses/BSD.txt # Thanks for using Enthought open source! # -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ import unittest import numpy as np @@ -19,7 +19,6 @@ class DefaultColormapsTestCase(unittest.TestCase): - def test_default_colormaps_smoke(self): # Runs some data through each of the default colormaps and do basic # sanity checks. @@ -42,8 +41,7 @@ def test_default_colormaps_smoke(self): c_cmapper = default_colormaps.center(cmap_func)(datarange) self.assertEqual(c_cmapper.range.low, -1.5) self.assertEqual(c_cmapper.range.high, 1.5) - f_cmapper = default_colormaps.fix(cmap_func, - (0.0, 1.0))(datarange) + f_cmapper = default_colormaps.fix(cmap_func, (0.0, 1.0))(datarange) self.assertEqual(f_cmapper.range.low, 0.0) self.assertEqual(f_cmapper.range.high, 1.0) @@ -63,7 +61,7 @@ def test_discrete_colormaps_smoke(self): assert_array_equal(rgba[:, -1], np.ones(3)) r_cmapper = default_colormaps.reverse(cmap_func)(datarange) - y = (len(cmapper.palette)-1-x[::-1]) + y = len(cmapper.palette) - 1 - x[::-1] r_rgba = r_cmapper.map_screen(y) assert_array_almost_equal(r_rgba, rgba[::-1]) diff --git a/chaco/tests/test_discrete_colormapper.py b/chaco/tests/test_discrete_colormapper.py index 67345b533..d7d844e52 100644 --- a/chaco/tests/test_discrete_colormapper.py +++ b/chaco/tests/test_discrete_colormapper.py @@ -7,7 +7,6 @@ class DiscreteColormapTestCase(unittest.TestCase): - def setUp(self): gray_data = empty(shape=(5, 3)) gray_data[:] = array([0.0, 0.25, 0.5, 0.75, 1.0]).reshape(5, 1) @@ -24,7 +23,7 @@ def test_simple_map(self): assert_array_almost_equal(b[:, 3], [1, 1, 1]) def test_color_space_rgb(self): - self.colormap.color_depth = 'rgb' + self.colormap.color_depth = "rgb" a = array([0, 2, 3]) b = self.colormap.map_screen(a) @@ -33,7 +32,7 @@ def test_color_space_rgb(self): assert_array_almost_equal(b[:, i], array([0.0, 0.5, 0.75])) def test_map_uint8(self): - self.colormap.color_depth = 'rgb' + self.colormap.color_depth = "rgb" a = array([0, 2, 3]) b = self.colormap.map_uint8(a) @@ -53,7 +52,7 @@ def test_map_uint8_rgb(self): assert_array_almost_equal(b[:, 3], [255, 255, 255]) def test_map_index(self): - self.colormap.color_depth = 'rgb' + self.colormap.color_depth = "rgb" a = array([0, 2, 3]) b = self.colormap.map_index(a) @@ -76,7 +75,8 @@ def test_alpha_palette_rgb(self): gray_data = empty(shape=(5, 4)) gray_data[:] = array([0.0, 0.25, 0.5, 0.75, 1.0]).reshape(5, 1) self.colormap = DiscreteColorMapper.from_palette_array( - gray_data, color_depth='rgb') + gray_data, color_depth="rgb" + ) a = array([0, 2, 3]) b = self.colormap.map_screen(a) @@ -100,7 +100,8 @@ def test_alpha_palette_map_uint8_rgb(self): gray_data = empty(shape=(5, 4)) gray_data[:] = array([0.0, 0.25, 0.5, 0.75, 1.0]).reshape(5, 1) self.colormap = DiscreteColorMapper.from_palette_array( - gray_data, color_depth='rgb') + gray_data, color_depth="rgb" + ) a = array([0, 2, 3]) b = self.colormap.map_uint8(a) @@ -114,13 +115,14 @@ def test_from_colormap(self): def colormap_function(range, **traits): """ Typical colormap generator """ - _gray_data = {'red': [(0., 0, 0), (1., 1.0, 1.0)], - 'green': [(0., 0, 0), (1., 1.0, 1.0)], - 'blue': [(0., 0, 0), (1., 1.0, 1.0)]} - return ColorMapper.from_segment_map(_gray_data, range=range, - **traits) - self.colormap = DiscreteColorMapper.from_colormap( - colormap_function, steps=5) + _gray_data = { + "red": [(0.0, 0, 0), (1.0, 1.0, 1.0)], + "green": [(0.0, 0, 0), (1.0, 1.0, 1.0)], + "blue": [(0.0, 0, 0), (1.0, 1.0, 1.0)], + } + return ColorMapper.from_segment_map(_gray_data, range=range, **traits) + + self.colormap = DiscreteColorMapper.from_colormap(colormap_function, steps=5) gray_data = empty(shape=(5, 4)) gray_data[:] = array([0.0, 0.25, 0.5, 0.75, 1.0]).reshape(5, 1) @@ -131,4 +133,3 @@ def colormap_function(range, **traits): self.assertEqual(b.shape, (3, 4)) for i in range(4): assert_array_almost_equal(b[:, i], array([0.0, 0.5, 0.75])) - diff --git a/chaco/tests/test_errorbarplot.py b/chaco/tests/test_errorbarplot.py index 70a7a0bc5..95ab932d8 100644 --- a/chaco/tests/test_errorbarplot.py +++ b/chaco/tests/test_errorbarplot.py @@ -5,8 +5,11 @@ # Chaco imports from chaco.api import ( - ArrayDataSource, DataRange1D, ErrorBarPlot, LinearMapper, - PlotGraphicsContext + ArrayDataSource, + DataRange1D, + ErrorBarPlot, + LinearMapper, + PlotGraphicsContext, ) @@ -26,7 +29,7 @@ def test_errorbarplot(self): value_mapper=LinearMapper(range=DataRange1D(low=0, high=15)), value_low=low, value_high=high, - color='blue', + color="blue", line_width=3.0, ) errorbar_plot.outer_bounds = list(size) diff --git a/chaco/tests/test_function_data_source.py b/chaco/tests/test_function_data_source.py index d739ffca7..35ce92e10 100644 --- a/chaco/tests/test_function_data_source.py +++ b/chaco/tests/test_function_data_source.py @@ -13,12 +13,10 @@ class FunctionDataSourceTestCase(UnittestTools, unittest.TestCase): - def setUp(self): - self.myfunc = lambda low, high: linspace(low, high, 101)**2 + self.myfunc = lambda low, high: linspace(low, high, 101) ** 2 self.data_source = FunctionDataSource(func=self.myfunc) - def test_init_defaults(self): data_source = FunctionDataSource() assert_array_equal(data_source._data, []) @@ -34,39 +32,33 @@ def test_basic_setup(self): def test_set_data(self): with self.assertRaises(RuntimeError): - self.data_source.set_data( - lambda low, high: linspace(low, high, 101)) + self.data_source.set_data(lambda low, high: linspace(low, high, 101)) def test_range_high_changed(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, - high_setting=1.0) + self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) - with self.assertTraitChanges(self.data_source, 'data_changed', count=1): + with self.assertTraitChanges(self.data_source, "data_changed", count=1): self.data_source.data_range.high_setting = 2.0 - assert_array_equal(linspace(0.0, 2.0, 101)**2, - self.data_source.get_data()) + assert_array_equal(linspace(0.0, 2.0, 101) ** 2, self.data_source.get_data()) def test_range_low_changed(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, - high_setting=1.0) + self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) - with self.assertTraitChanges(self.data_source, 'data_changed', count=1): + with self.assertTraitChanges(self.data_source, "data_changed", count=1): self.data_source.data_range.low_setting = -1.0 - assert_array_equal(linspace(-1.0, 1.0, 101)**2, - self.data_source.get_data()) + assert_array_equal(linspace(-1.0, 1.0, 101) ** 2, self.data_source.get_data()) def test_range_data_range_changed(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, - high_setting=1.0) + self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) - with self.assertTraitChanges(self.data_source, 'data_changed', count=1): - self.data_source.data_range = DataRange1D(low_setting=-2.0, - high_setting=2.0) + with self.assertTraitChanges(self.data_source, "data_changed", count=1): + self.data_source.data_range = DataRange1D( + low_setting=-2.0, high_setting=2.0 + ) - assert_array_equal(linspace(-2.0, 2.0, 101)**2, - self.data_source.get_data()) + assert_array_equal(linspace(-2.0, 2.0, 101) ** 2, self.data_source.get_data()) def test_set_mask(self): mymask = array([i % 2 for i in range(101)], dtype=bool) @@ -79,11 +71,9 @@ def test_remove_mask(self): self.data_source.remove_mask() def test_get_data(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, - high_setting=1.0) + self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) - assert_array_equal(linspace(0.0, 1.0, 101)**2, - self.data_source.get_data()) + assert_array_equal(linspace(0.0, 1.0, 101) ** 2, self.data_source.get_data()) def test_get_data_no_data(self): self.data_source = FunctionDataSource() @@ -91,30 +81,26 @@ def test_get_data_no_data(self): assert_array_equal(self.data_source.get_data(), array([], dtype=float)) def test_get_data_mask(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, - high_setting=1.0) + self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) data, mask = self.data_source.get_data_mask() - assert_array_equal(data, linspace(0.0, 1.0, 101)**2) + assert_array_equal(data, linspace(0.0, 1.0, 101) ** 2) assert_array_equal(mask, ones(shape=101, dtype=bool)) def test_bounds(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, - high_setting=2.0) + self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=2.0) bounds = self.data_source.get_bounds() self.assertEqual(bounds, (0.0, 4.0)) @unittest.skip("default sort_order is ascending, which isn't right") def test_bounds_non_monotone(self): - self.data_source.data_range = DataRange1D(low_setting=-2.0, - high_setting=2.0) + self.data_source.data_range = DataRange1D(low_setting=-2.0, high_setting=2.0) bounds = self.data_source.get_bounds() self.assertEqual(bounds, (0.0, 4.0)) def test_data_size(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, - high_setting=2.0) + self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=2.0) self.assertEqual(101, self.data_source.get_size()) diff --git a/chaco/tests/test_grid_data_source.py b/chaco/tests/test_grid_data_source.py index f73988ca2..42d269d3f 100644 --- a/chaco/tests/test_grid_data_source.py +++ b/chaco/tests/test_grid_data_source.py @@ -12,63 +12,66 @@ class GridDataSourceTestCase(UnittestTools, unittest.TestCase): - def setUp(self): self.data_source = GridDataSource( xdata=array([1, 2, 3]), ydata=array([1.5, 0.5, -0.5, -1.5]), - sort_order=('ascending', 'descending')) + sort_order=("ascending", "descending"), + ) def test_empty(self): data_source = GridDataSource() - self.assertEqual(data_source.sort_order, ('none', 'none')) - self.assertEqual(data_source.index_dimension, 'image') - self.assertEqual(data_source.value_dimension, 'scalar') - self.assertEqual(data_source.metadata, - {"selections":[], "annotations":[]}) + self.assertEqual(data_source.sort_order, ("none", "none")) + self.assertEqual(data_source.index_dimension, "image") + self.assertEqual(data_source.value_dimension, "scalar") + self.assertEqual(data_source.metadata, {"selections": [], "annotations": []}) xdata, ydata = data_source.get_data() assert_array_equal(xdata.get_data(), array([])) assert_array_equal(ydata.get_data(), array([])) - self.assertEqual(data_source.get_bounds(), ((0,0),(0,0))) + self.assertEqual(data_source.get_bounds(), ((0, 0), (0, 0))) def test_init(self): test_xd = array([1, 2, 3]) test_yd = array([1.5, 0.5, -0.5, -1.5]) - test_sort_order = ('ascending', 'descending') + test_sort_order = ("ascending", "descending") self.assertEqual(self.data_source.sort_order, test_sort_order) xd, yd = self.data_source.get_data() assert_array_equal(xd.get_data(), test_xd) assert_array_equal(yd.get_data(), test_yd) - self.assertEqual(self.data_source.get_bounds(), - ((min(test_xd),min(test_yd)), - (max(test_xd),max(test_yd)))) + self.assertEqual( + self.data_source.get_bounds(), + ((min(test_xd), min(test_yd)), (max(test_xd), max(test_yd))), + ) def test_set_data(self): - test_xd = array([0,2,4]) - test_yd = array([0,1,2,3,4,5]) - test_sort_order = ('none', 'none') + test_xd = array([0, 2, 4]) + test_yd = array([0, 1, 2, 3, 4, 5]) + test_sort_order = ("none", "none") - self.data_source.set_data(xdata=test_xd, ydata=test_yd, - sort_order=('none', 'none')) + self.data_source.set_data( + xdata=test_xd, ydata=test_yd, sort_order=("none", "none") + ) self.assertEqual(self.data_source.sort_order, test_sort_order) xd, yd = self.data_source.get_data() assert_array_equal(xd.get_data(), test_xd) assert_array_equal(yd.get_data(), test_yd) - self.assertEqual(self.data_source.get_bounds(), - ((min(test_xd),min(test_yd)), - (max(test_xd),max(test_yd)))) + self.assertEqual( + self.data_source.get_bounds(), + ((min(test_xd), min(test_yd)), (max(test_xd), max(test_yd))), + ) def test_metadata(self): - self.assertEqual(self.data_source.metadata, - {'annotations': [], 'selections': []}) + self.assertEqual( + self.data_source.metadata, {"annotations": [], "selections": []} + ) def test_metadata_changed(self): - with self.assertTraitChanges(self.data_source, 'metadata_changed', count=1): - self.data_source.metadata = {'new_metadata': True} + with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + self.data_source.metadata = {"new_metadata": True} def test_metadata_items_changed(self): - with self.assertTraitChanges(self.data_source, 'metadata_changed', count=1): - self.data_source.metadata['new_metadata'] = True + with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + self.data_source.metadata["new_metadata"] = True diff --git a/chaco/tests/test_grid_mapper.py b/chaco/tests/test_grid_mapper.py index a71acf28a..fbae180c1 100644 --- a/chaco/tests/test_grid_mapper.py +++ b/chaco/tests/test_grid_mapper.py @@ -1,12 +1,11 @@ - import unittest from numpy import array, transpose from numpy.testing import assert_equal from chaco.api import GridDataSource, DataRange2D, GridMapper -class GridMapperTestCase(unittest.TestCase): +class GridMapperTestCase(unittest.TestCase): def setUp(self): self.x_ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) self.y_ary = array([1.0, 1.0, 2.0, 2.0, 3.0, 3.0]) @@ -15,36 +14,35 @@ def setUp(self): self.mapper = GridMapper(range=r) def test_basic(self): - self.mapper.x_low_pos=50 - self.mapper.x_high_pos=100 - self.mapper.y_low_pos=0 - self.mapper.y_high_pos=10 + self.mapper.x_low_pos = 50 + self.mapper.x_high_pos = 100 + self.mapper.y_low_pos = 0 + self.mapper.y_high_pos = 10 result = self.mapper.map_screen(transpose((self.x_ary, self.y_ary))) - assert_equal(result, [(50,0), (60,0), (70,5), - (80,5), (90,10), (100,10)]) + assert_equal(result, [(50, 0), (60, 0), (70, 5), (80, 5), (90, 10), (100, 10)]) def test_map_screen_scalar(self): - self.mapper.x_low_pos=50 - self.mapper.x_high_pos=100 - self.mapper.y_low_pos=0 - self.mapper.y_high_pos=10 + self.mapper.x_low_pos = 50 + self.mapper.x_high_pos = 100 + self.mapper.y_low_pos = 0 + self.mapper.y_high_pos = 10 result = self.mapper.map_screen(transpose((6.0, 1.0))) assert_equal(result, [[60, 0]]) def test_map_data(self): - self.mapper.x_low_pos=50 - self.mapper.x_high_pos=100 - self.mapper.y_low_pos=0 - self.mapper.y_high_pos=10 - screen_ary = array([(50,0), (60,0), (70,5), (80,5), (90,10), (100,10)]) + self.mapper.x_low_pos = 50 + self.mapper.x_high_pos = 100 + self.mapper.y_low_pos = 0 + self.mapper.y_high_pos = 10 + screen_ary = array([(50, 0), (60, 0), (70, 5), (80, 5), (90, 10), (100, 10)]) result = self.mapper.map_data(screen_ary) assert_equal(result, transpose((self.x_ary, self.y_ary))) def test_map_data_scalar(self): - self.mapper.x_low_pos=50 - self.mapper.x_high_pos=100 - self.mapper.y_low_pos=0 - self.mapper.y_high_pos=10 + self.mapper.x_low_pos = 50 + self.mapper.x_high_pos = 100 + self.mapper.y_low_pos = 0 + self.mapper.y_high_pos = 10 screen_ary = (60, 0) result = self.mapper.map_data(screen_ary) assert_equal(result, [[6.0, 1.0]]) diff --git a/chaco/tests/test_hittest.py b/chaco/tests/test_hittest.py index 56678b98c..579bac2de 100644 --- a/chaco/tests/test_hittest.py +++ b/chaco/tests/test_hittest.py @@ -4,15 +4,15 @@ import unittest from numpy import arange, array, linalg -from chaco.api import (ArrayDataSource, ArrayPlotData, - Plot, LinearMapper, DataRange1D) +from chaco.api import ArrayDataSource, ArrayPlotData, Plot, LinearMapper, DataRange1D + class HittestTestCase(unittest.TestCase): def make_plot(self, orientation): # make some data points x = arange(3) x = ArrayDataSource(x, sort_order="ascending") - y = array([2,0,1]) + y = array([2, 0, 1]) # Plot the data pd = ArrayPlotData(x=x, y=y) @@ -22,31 +22,33 @@ def make_plot(self, orientation): # Construct a fake screen space for the plots # otherwise would need to actually display the plots to get this - index_mapper = LinearMapper(data_range=DataRange1D(low=0,high=2), - high_pos=380, low_pos=20) - value_mapper = LinearMapper(data_range=DataRange1D(low=0,high=2), - high_pos=380, low_pos=20) + index_mapper = LinearMapper( + data_range=DataRange1D(low=0, high=2), high_pos=380, low_pos=20 + ) + value_mapper = LinearMapper( + data_range=DataRange1D(low=0, high=2), high_pos=380, low_pos=20 + ) plot.index_mapper = index_mapper plot.value_mapper = value_mapper line_plot.index_mapper = index_mapper line_plot.value_mapper = value_mapper - return plot, line_plot + return plot, line_plot def test_horizontal(self): plot, line_plot = self.make_plot("h") - self._test_plot(plot, line_plot, point=[0.5,1]) - self._test_plot(plot, line_plot, point=[1,0]) + self._test_plot(plot, line_plot, point=[0.5, 1]) + self._test_plot(plot, line_plot, point=[1, 0]) def test_vertical(self): plot, line_plot = self.make_plot("v") - self._test_plot(plot, line_plot, point=[0.5,1]) - self._test_plot(plot, line_plot, point=[1,0]) + self._test_plot(plot, line_plot, point=[0.5, 1]) + self._test_plot(plot, line_plot, point=[1, 0]) def _test_plot(self, plot, line_plot, point): - threshold = 2 # In pixels + threshold = 2 # In pixels screen_pt = plot.map_screen(point).flatten() result = line_plot.hittest(screen_pt, threshold=threshold) @@ -59,8 +61,9 @@ def _test_plot(self, plot, line_plot, point): self.assertTrue(linalg.norm(screen_pt - screen_result) < threshold) # check the return_distance = True case: - x, y, d = line_plot.hittest(screen_pt, threshold=threshold, - return_distance=True) + x, y, d = line_plot.hittest( + screen_pt, threshold=threshold, return_distance=True + ) self.assertEqual(x, result[0]) self.assertEqual(y, result[1]) self.assertTrue(d < threshold) diff --git a/chaco/tests/test_image_data.py b/chaco/tests/test_image_data.py index d34a9f239..2f1b442d4 100644 --- a/chaco/tests/test_image_data.py +++ b/chaco/tests/test_image_data.py @@ -13,11 +13,10 @@ from traits.testing.unittest_tools import UnittestTools -data_dir = resource_filename('chaco.tests', 'data') +data_dir = resource_filename("chaco.tests", "data") class ImageDataTestCase(UnittestTools, unittest.TestCase): - def setUp(self): self.myarray = arange(15).reshape(5, 3, 1) self.data_source = ImageData(data=self.myarray) @@ -27,18 +26,18 @@ def test_init_defaults(self): assert_array_equal(data_source.data, []) # this isn't right - - #self.assertEqual(data_source.value_dimension, "scalar") - #self.assertEqual(data_source.image_dimension, "image") + # self.assertEqual(data_source.value_dimension, "scalar") + # self.assertEqual(data_source.image_dimension, "image") def test_basic_setup(self): assert_array_equal(self.myarray, self.data_source.data) - #self.assertEqual(self.data_source.value_dimension, "scalar") + # self.assertEqual(self.data_source.value_dimension, "scalar") self.assertFalse(self.data_source.is_masked()) def test_set_data(self): new_array = arange(0, 30, 2).reshape(5, 3, 1) - with self.assertTraitChanges(self.data_source, 'data_changed', count=1): + with self.assertTraitChanges(self.data_source, "data_changed", count=1): self.data_source.set_data(new_array) assert_array_equal(new_array, self.data_source.data) @@ -74,7 +73,7 @@ def test_bounds(self): bounds = self.data_source.get_bounds() self.assertEqual(bounds, (0, 14)) - @unittest.skip('test_bounds_empty() fails in this case') + @unittest.skip("test_bounds_empty() fails in this case") def test_bounds_empty(self): data_source = ImageData() bounds = data_source.get_bounds() @@ -116,26 +115,27 @@ def test_array_bounds_transposed(self): def test_fromfile_png_rgb(self): # basic smoke test - assume that kiva.image does the right thing - path = os.path.join(data_dir, 'PngSuite', 'basn2c08.png') + path = os.path.join(data_dir, "PngSuite", "basn2c08.png") data_source = ImageData.fromfile(path) self.assertEqual(data_source.value_depth, 3) def test_fromfile_png_rgba(self): # basic smoke test - assume that kiva.image does the right thing - path = os.path.join(data_dir, 'PngSuite', 'basi6a08.png') + path = os.path.join(data_dir, "PngSuite", "basi6a08.png") data_source = ImageData.fromfile(path) self.assertEqual(data_source.value_depth, 4) def test_metadata(self): - self.assertEqual(self.data_source.metadata, - {'annotations': [], 'selections': []}) + self.assertEqual( + self.data_source.metadata, {"annotations": [], "selections": []} + ) def test_metadata_changed(self): - with self.assertTraitChanges(self.data_source, 'metadata_changed', count=1): - self.data_source.metadata = {'new_metadata': True} + with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + self.data_source.metadata = {"new_metadata": True} def test_metadata_items_changed(self): - with self.assertTraitChanges(self.data_source, 'metadata_changed', count=1): - self.data_source.metadata['new_metadata'] = True + with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + self.data_source.metadata["new_metadata"] = True diff --git a/chaco/tests/test_image_plot.py b/chaco/tests/test_image_plot.py index 3e896d449..b1a56225c 100644 --- a/chaco/tests/test_image_plot.py +++ b/chaco/tests/test_image_plot.py @@ -20,12 +20,12 @@ DataRange2D, ImageData, ImagePlot, - Plot + Plot, ) # The Quartz backend rescales pixel values, so use a higher threshold. -MAX_RMS_ERROR = 16 if ETSConfig.kiva_backend == 'quartz' else 1 +MAX_RMS_ERROR = 16 if ETSConfig.kiva_backend == "quartz" else 1 IMAGE = np.random.random_integers(0, 255, size=(100, 200)).astype(np.uint8) RGB = np.dstack([IMAGE] * 3) @@ -34,7 +34,7 @@ @contextmanager -def temp_image_file(suffix='.tif', prefix='test', dir=None): +def temp_image_file(suffix=".tif", prefix="test", dir=None): fd, filename = tempfile.mkstemp(suffix=suffix, prefix=prefix, dir=dir) try: yield filename @@ -45,7 +45,7 @@ def temp_image_file(suffix='.tif', prefix='test', dir=None): def get_image_index_and_mapper(image): h, w = image.shape[:2] - index = GridDataSource(np.arange(h+1), np.arange(w+1)) + index = GridDataSource(np.arange(h + 1), np.arange(w + 1)) index_mapper = GridMapper(range=DataRange2D(low=(0, 0), high=(h, w))) return index, index_mapper @@ -62,7 +62,7 @@ def image_from_renderer(renderer, orientation): data = renderer.value # Set bounding box size and origin to align rendered image with array renderer.bounds = (data.get_width() + 1, data.get_height() + 1) - if orientation == 'v': + if orientation == "v": renderer.bounds = renderer.bounds[::-1] renderer.position = 0, 0 @@ -75,10 +75,10 @@ def image_from_renderer(renderer, orientation): def rendered_image_result(image, filename=None, **plot_kwargs): data_source = ImageData(data=image) index, index_mapper = get_image_index_and_mapper(image) - renderer = ImagePlot(value=data_source, index=index, - index_mapper=index_mapper, - **plot_kwargs) - orientation = plot_kwargs.get('orientation', 'h') + renderer = ImagePlot( + value=data_source, index=index, index_mapper=index_mapper, **plot_kwargs + ) + orientation = plot_kwargs.get("orientation", "h") return image_from_renderer(renderer, orientation) @@ -94,7 +94,7 @@ def calculate_rms(image_result, expected_image): abs_diff_image = abs(np.int_(expected_image) - np.int_(image_result)) histogram = np.bincount(abs_diff_image.ravel(), minlength=256) - sum_of_squares = np.sum(np.int64(histogram) * np.arange(len(histogram))**2) + sum_of_squares = np.sum(np.int64(histogram) * np.arange(len(histogram)) ** 2) rms = np.sqrt(float(sum_of_squares) / num_values) return rms @@ -106,7 +106,7 @@ def plot_comparison(input_image, expected_image, **plot_kwargs): diff = np.int64(expected_image) - np.int64(image_result) max_diff = max(abs(diff.min()), abs(diff.max()), 1) - fig, (ax0, ax1, ax2) = plt.subplots(ncols=3, sharex='all', sharey='all') + fig, (ax0, ax1, ax2) = plt.subplots(ncols=3, sharex="all", sharey="all") ax0.imshow(expected_image) ax1.imshow(image_result) im_plot = ax2.imshow(diff, vmin=-max_diff, vmax=max_diff, cmap=plt.cm.bwr) @@ -115,7 +115,6 @@ def plot_comparison(input_image, expected_image, **plot_kwargs): class TestResultImage(unittest.TestCase): - def verify_result_image(self, input_image, expected_image, **plot_kwargs): # These tests were written assuming uint8 inputs. self.assertEqual(input_image.dtype, np.uint8) @@ -126,47 +125,50 @@ def verify_result_image(self, input_image, expected_image, **plot_kwargs): def test_horizontal_top_left(self): # Horizontal orientation with top left origin renders original image. - self.verify_result_image(RGB, IMAGE, origin='top left') + self.verify_result_image(RGB, IMAGE, origin="top left") def test_horizontal_bottom_left(self): # Horizontal orientation with bottom left origin renders a vertically # flipped image. - self.verify_result_image(RGB, IMAGE[::-1], origin='bottom left') + self.verify_result_image(RGB, IMAGE[::-1], origin="bottom left") def test_horizontal_top_right(self): # Horizontal orientation with top right origin renders a horizontally # flipped image. - self.verify_result_image(RGB, IMAGE[:, ::-1], origin='top right') + self.verify_result_image(RGB, IMAGE[:, ::-1], origin="top right") def test_horizontal_bottom_right(self): # Horizontal orientation with top right origin renders an image flipped # horizontally and vertically. - self.verify_result_image(RGB, IMAGE[::-1, ::-1], origin='bottom right') + self.verify_result_image(RGB, IMAGE[::-1, ::-1], origin="bottom right") def test_vertical_top_left(self): # Vertical orientation with top left origin renders transposed image. - self.verify_result_image(RGB, IMAGE.T, origin='top left', orientation='v') + self.verify_result_image(RGB, IMAGE.T, origin="top left", orientation="v") def test_vertical_bottom_left(self): # Vertical orientation with bottom left origin renders transposed image # that is vertically flipped. - self.verify_result_image(RGB, (IMAGE.T)[::-1], - origin='bottom left', orientation='v') + self.verify_result_image( + RGB, (IMAGE.T)[::-1], origin="bottom left", orientation="v" + ) def test_vertical_top_right(self): # Vertical orientation with top right origin renders transposed image # that is horizontally flipped. - self.verify_result_image(RGB, (IMAGE.T)[:, ::-1], - origin='top right', orientation='v') + self.verify_result_image( + RGB, (IMAGE.T)[:, ::-1], origin="top right", orientation="v" + ) def test_vertical_bottom_right(self): # Vertical orientation with bottom right origin renders transposed image # that is flipped vertically and horizontally. - self.verify_result_image(RGB, (IMAGE.T)[::-1, ::-1], - origin='bottom right', orientation='v') + self.verify_result_image( + RGB, (IMAGE.T)[::-1, ::-1], origin="bottom right", orientation="v" + ) # regression test for enthought/chaco#528 - @unittest.skipIf(ETSConfig.toolkit=='null', "Skip on 'null' toolkit") + @unittest.skipIf(ETSConfig.toolkit == "null", "Skip on 'null' toolkit") def test_resize_to_zero(self): class TestResize(HasTraits): plot = Instance(Component) @@ -175,7 +177,7 @@ class TestResize(HasTraits): # image is 0x0 on the screen and the failure was triggered traits_view = View( Group( - UItem('plot', editor=ComponentEditor(size=(101, 101))), + UItem("plot", editor=ComponentEditor(size=(101, 101))), ), resizable=True, ) @@ -183,13 +185,13 @@ class TestResize(HasTraits): def _plot_default(self): pd = ArrayPlotData(image=RGB) plot = Plot(pd) - plot.img_plot('image') + plot.img_plot("image") return plot - + test_obj = TestResize() tester = UITester() - # should not fail + # should not fail with tester.create_ui(test_obj) as ui: pass diff --git a/chaco/tests/test_image_utils.py b/chaco/tests/test_image_utils.py index c8a33e22f..53a8e967a 100644 --- a/chaco/tests/test_image_utils.py +++ b/chaco/tests/test_image_utils.py @@ -21,7 +21,6 @@ def assert_midpoints_equal(bounds_list): class TestImageUtils(unittest.TestCase): - def test_viewer_zoomed_into_single_pixel(self): screen_rect = [0, 0, 100, 100] view_rect = [10, 11, 1, 2] @@ -31,23 +30,25 @@ def test_viewer_zoomed_into_single_pixel(self): def test_viewer_at_corner_of_single_image(self): offset = 0.2 screen_rect = [1, 1, 1, 1] - new_size = [1-offset, 1-offset] + new_size = [1 - offset, 1 - offset] - down_right = [1+offset, 1+offset, 1, 1] + down_right = [1 + offset, 1 + offset, 1, 1] new_rect = trim_screen_rect(screen_rect, down_right, SINGLE_PIXEL) expected_rect = down_right[:2] + new_size assert_midpoints_equal((new_rect, expected_rect)) - up_left = [1-offset, 1-offset, 1, 1] + up_left = [1 - offset, 1 - offset, 1, 1] new_rect = trim_screen_rect(screen_rect, up_left, SINGLE_PIXEL) expected_rect = [1, 1] + new_size assert_midpoints_equal((new_rect, expected_rect)) def test_viewer_zoomed_into_four_pixel_intersection(self): screen_rect = [0, 0, 100, 100] # 4-pixel intersection at (50, 50) - view_rectangles = ([49, 49, 2, 2], # Centered pixel intersection - [49, 49, 3, 3], # Intersection at 1/3 of view - [49, 49, 2, 3]) # Intersection at 1/2, 1/3 of view + view_rectangles = ( + [49, 49, 2, 2], # Centered pixel intersection + [49, 49, 3, 3], # Intersection at 1/3 of view + [49, 49, 2, 3], + ) # Intersection at 1/2, 1/3 of view for view_rect in view_rectangles: new_rect = trim_screen_rect(screen_rect, view_rect, FOUR_PIXELS) assert_midpoints_equal((new_rect, screen_rect)) @@ -55,8 +56,10 @@ def test_viewer_zoomed_into_four_pixel_intersection(self): def test_viewer_at_corner_of_four_pixel_image(self): offset = 0.2 screen_rect = [1, 1, 1, 1] - view_rectangles = ([1+offset, 1+offset, 1, 1], # Shifted down and right - [1-offset, 1-offset, 1, 1]) # Shifted up and left + view_rectangles = ( + [1 + offset, 1 + offset, 1, 1], # Shifted down and right + [1 - offset, 1 - offset, 1, 1], + ) # Shifted up and left for view_rect in view_rectangles: new_rect = trim_screen_rect(screen_rect, view_rect, FOUR_PIXELS) assert_equal(new_rect, screen_rect) diff --git a/chaco/tests/test_instantiation_order.py b/chaco/tests/test_instantiation_order.py index eb4da3ecb..cc3530bea 100644 --- a/chaco/tests/test_instantiation_order.py +++ b/chaco/tests/test_instantiation_order.py @@ -6,12 +6,12 @@ import unittest from numpy import array -from chaco.api import ArrayDataSource, DataRange1D, \ - LinearMapper +from chaco.api import ArrayDataSource, DataRange1D, LinearMapper + class DataPipelineTestCase(unittest.TestCase): def test_piecewise_construction(self): - ary = array([1,2,3,4,5,6,7]) + ary = array([1, 2, 3, 4, 5, 6, 7]) ds = ArrayDataSource() ds.set_data(ary) r = DataRange1D() @@ -25,14 +25,14 @@ def test_piecewise_construction(self): mapper.range = r mapper.low_pos = 1.0 mapper.high_pos = 7.0 - screen_pts = mapper.map_screen(array([1,3,7])) + screen_pts = mapper.map_screen(array([1, 3, 7])) self.assertTrue(tuple(screen_pts) == (1.0, 3.0, 7.0)) def test_reverse_construction(self): mapper = LinearMapper() r = DataRange1D() ds = ArrayDataSource() - ary = array([1,2,3,4,5,6,7]) + ary = array([1, 2, 3, 4, 5, 6, 7]) mapper.range = r mapper.low_pos = 1.0 @@ -42,5 +42,5 @@ def test_reverse_construction(self): self.assertTrue(r.low == 1) self.assertTrue(r.high == 7) - screen_pts = mapper.map_screen(array([1,3,7])) + screen_pts = mapper.map_screen(array([1, 3, 7])) self.assertTrue(tuple(screen_pts) == (1.0, 3.0, 7.0)) diff --git a/chaco/tests/test_jitterplot.py b/chaco/tests/test_jitterplot.py index 44cb63d8d..206e397d3 100644 --- a/chaco/tests/test_jitterplot.py +++ b/chaco/tests/test_jitterplot.py @@ -5,13 +5,11 @@ from enable.compiled_path import CompiledPath # Chaco imports -from chaco.api import (ArrayDataSource, DataRange1D, LinearMapper, - PlotGraphicsContext) +from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext from chaco.jitterplot import JitterPlot class Jitterplot1DTest(unittest.TestCase): - def setUp(self): self.size = (250, 250) data_source = ArrayDataSource(arange(10)) @@ -26,10 +24,9 @@ def setUp(self): self.scatterplot.outer_bounds = list(self.size) def test_scatter_1d(self): - self.assertEqual(self.scatterplot.origin, 'bottom left') + self.assertEqual(self.scatterplot.origin, "bottom left") self.assertIsNone(self.scatterplot.x_mapper) - self.assertEqual(self.scatterplot.y_mapper, - self.scatterplot.index_mapper) + self.assertEqual(self.scatterplot.y_mapper, self.scatterplot.index_mapper) gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -37,11 +34,10 @@ def test_scatter_1d(self): self.assertFalse(alltrue(actual == 255)) def test_scatter_1d_horizontal(self): - self.scatterplot.orientation = 'h' + self.scatterplot.orientation = "h" - self.assertEqual(self.scatterplot.origin, 'bottom left') - self.assertEqual(self.scatterplot.x_mapper, - self.scatterplot.index_mapper) + self.assertEqual(self.scatterplot.origin, "bottom left") + self.assertEqual(self.scatterplot.x_mapper, self.scatterplot.index_mapper) self.assertIsNone(self.scatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -50,12 +46,11 @@ def test_scatter_1d_horizontal(self): self.assertFalse(alltrue(actual == 255)) def test_scatter_1d_flipped(self): - self.scatterplot.direction = 'flipped' + self.scatterplot.direction = "flipped" - self.assertEqual(self.scatterplot.origin, 'top left') + self.assertEqual(self.scatterplot.origin, "top left") self.assertIsNone(self.scatterplot.x_mapper) - self.assertEqual(self.scatterplot.y_mapper, - self.scatterplot.index_mapper) + self.assertEqual(self.scatterplot.y_mapper, self.scatterplot.index_mapper) gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -63,12 +58,11 @@ def test_scatter_1d_flipped(self): self.assertFalse(alltrue(actual == 255)) def test_scatter_1d_horizontal_flipped(self): - self.scatterplot.direction = 'flipped' - self.scatterplot.orientation = 'h' + self.scatterplot.direction = "flipped" + self.scatterplot.orientation = "h" - self.assertEqual(self.scatterplot.origin, 'bottom right') - self.assertEqual(self.scatterplot.x_mapper, - self.scatterplot.index_mapper) + self.assertEqual(self.scatterplot.origin, "bottom right") + self.assertEqual(self.scatterplot.x_mapper, self.scatterplot.index_mapper) self.assertIsNone(self.scatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -77,7 +71,7 @@ def test_scatter_1d_horizontal_flipped(self): self.assertFalse(alltrue(actual == 255)) def test_scatter_1d_circle(self): - self.scatterplot.marker = 'circle' + self.scatterplot.marker = "circle" gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) actual = gc.bmp_array[:, :, :] @@ -91,7 +85,7 @@ def test_scatter_1d_custom(self): path.line_to(-5, 5) path.line_to(-5, -5) - self.scatterplot.marker = 'custom' + self.scatterplot.marker = "custom" self.scatterplot.custom_symbol = path gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -100,24 +94,20 @@ def test_scatter_1d_custom(self): def test_scatter_1d_map_data(self): points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), - array([4.5, 0])) + assert_almost_equal(self.scatterplot.map_data(points), array([4.5, 0])) def test_scatter_1d_map_data_horizontal(self): - self.scatterplot.orientation = 'h' + self.scatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), - array([0, 4.5])) + assert_almost_equal(self.scatterplot.map_data(points), array([0, 4.5])) def test_scatter_1d_map_data_flipped(self): - self.scatterplot.direction = 'flipped' + self.scatterplot.direction = "flipped" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), - array([4.5, 9.0])) + assert_almost_equal(self.scatterplot.map_data(points), array([4.5, 9.0])) def test_scatter_1d_map_data_horizontal_flipped(self): - self.scatterplot.direction = 'flipped' - self.scatterplot.orientation = 'h' + self.scatterplot.direction = "flipped" + self.scatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), - array([9.0, 4.5])) + assert_almost_equal(self.scatterplot.map_data(points), array([9.0, 4.5])) diff --git a/chaco/tests/test_line_scatterplot.py b/chaco/tests/test_line_scatterplot.py index 24f45aae9..02e00d7de 100644 --- a/chaco/tests/test_line_scatterplot.py +++ b/chaco/tests/test_line_scatterplot.py @@ -6,13 +6,11 @@ from traits.testing.unittest_tools import UnittestTools # Chaco imports -from chaco.api import (ArrayDataSource, DataRange1D, LinearMapper, - PlotGraphicsContext) +from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext from chaco.line_scatterplot_1d import LineScatterPlot1D class LineScatterPlot1DTest(UnittestTools, unittest.TestCase): - def setUp(self): self.size = (250, 250) data_source = ArrayDataSource(arange(10)) @@ -27,12 +25,14 @@ def setUp(self): self.linescatterplot.outer_bounds = list(self.size) def test_linescatter_1d(self): - self.assertEqual(self.linescatterplot.origin, 'bottom left') + self.assertEqual(self.linescatterplot.origin, "bottom left") self.assertIsNone(self.linescatterplot.x_mapper) - self.assertEqual(self.linescatterplot.y_mapper, - self.linescatterplot.index_mapper) - self.assertIs(self.linescatterplot.index_range, - self.linescatterplot.index_mapper.range) + self.assertEqual( + self.linescatterplot.y_mapper, self.linescatterplot.index_mapper + ) + self.assertIs( + self.linescatterplot.index_range, self.linescatterplot.index_mapper.range + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.linescatterplot) @@ -40,11 +40,12 @@ def test_linescatter_1d(self): self.assertFalse(alltrue(actual == 255)) def test_linescatter_1d_horizontal(self): - self.linescatterplot.orientation = 'h' + self.linescatterplot.orientation = "h" - self.assertEqual(self.linescatterplot.origin, 'bottom left') - self.assertEqual(self.linescatterplot.x_mapper, - self.linescatterplot.index_mapper) + self.assertEqual(self.linescatterplot.origin, "bottom left") + self.assertEqual( + self.linescatterplot.x_mapper, self.linescatterplot.index_mapper + ) self.assertIsNone(self.linescatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -53,12 +54,13 @@ def test_linescatter_1d_horizontal(self): self.assertFalse(alltrue(actual == 255)) def test_linescatter_1d_flipped(self): - self.linescatterplot.direction = 'flipped' + self.linescatterplot.direction = "flipped" - self.assertEqual(self.linescatterplot.origin, 'top left') + self.assertEqual(self.linescatterplot.origin, "top left") self.assertIsNone(self.linescatterplot.x_mapper) - self.assertEqual(self.linescatterplot.y_mapper, - self.linescatterplot.index_mapper) + self.assertEqual( + self.linescatterplot.y_mapper, self.linescatterplot.index_mapper + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.linescatterplot) @@ -66,12 +68,13 @@ def test_linescatter_1d_flipped(self): self.assertFalse(alltrue(actual == 255)) def test_linescatter_1d_horizontal_flipped(self): - self.linescatterplot.direction = 'flipped' - self.linescatterplot.orientation = 'h' + self.linescatterplot.direction = "flipped" + self.linescatterplot.orientation = "h" - self.assertEqual(self.linescatterplot.origin, 'bottom right') - self.assertEqual(self.linescatterplot.x_mapper, - self.linescatterplot.index_mapper) + self.assertEqual(self.linescatterplot.origin, "bottom right") + self.assertEqual( + self.linescatterplot.x_mapper, self.linescatterplot.index_mapper + ) self.assertIsNone(self.linescatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -87,14 +90,14 @@ def test_linescatter_1d_thicker(self): self.assertFalse(alltrue(actual == 255)) def test_linescatter_1d_color(self): - self.linescatterplot.color = 'orange' + self.linescatterplot.color = "orange" gc = PlotGraphicsContext(self.size) gc.render_component(self.linescatterplot) actual = gc.bmp_array[:, :, :] self.assertFalse(alltrue(actual == 255)) def test_linescatter_1d_line_style(self): - self.linescatterplot.line_style = 'dash' + self.linescatterplot.line_style = "dash" gc = PlotGraphicsContext(self.size) gc.render_component(self.linescatterplot) actual = gc.bmp_array[:, :, :] @@ -102,30 +105,26 @@ def test_linescatter_1d_line_style(self): def test_linescatter_1d_map_data(self): points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.linescatterplot.map_data(points), - array([4.5, 0])) + assert_almost_equal(self.linescatterplot.map_data(points), array([4.5, 0])) def test_linescatter_1d_map_data_horizontal(self): - self.linescatterplot.orientation = 'h' + self.linescatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.linescatterplot.map_data(points), - array([0, 4.5])) + assert_almost_equal(self.linescatterplot.map_data(points), array([0, 4.5])) def test_linescatter_1d_map_data_flipped(self): - self.linescatterplot.direction = 'flipped' + self.linescatterplot.direction = "flipped" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.linescatterplot.map_data(points), - array([4.5, 9.0])) + assert_almost_equal(self.linescatterplot.map_data(points), array([4.5, 9.0])) def test_linescatter_1d_map_data_horizontal_flipped(self): - self.linescatterplot.direction = 'flipped' - self.linescatterplot.orientation = 'h' + self.linescatterplot.direction = "flipped" + self.linescatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.linescatterplot.map_data(points), - array([9.0, 4.5])) + assert_almost_equal(self.linescatterplot.map_data(points), array([9.0, 4.5])) def test_linescatter_1d_selection(self): - self.linescatterplot.index.metadata['selections'] = [ + self.linescatterplot.index.metadata["selections"] = [ (arange(10) % 2 == 0), ] @@ -136,8 +135,8 @@ def test_linescatter_1d_selection(self): def test_linescatter_1d_selection_mask_name(self): # select with a mask - self.linescatterplot.selection_metadata_name = 'highlight_masks' - self.linescatterplot.index.metadata['highlight_masks'] = [ + self.linescatterplot.selection_metadata_name = "highlight_masks" + self.linescatterplot.index.metadata["highlight_masks"] = [ (arange(10) % 2 == 0), ] @@ -149,7 +148,7 @@ def test_linescatter_1d_selection_mask_name(self): def test_linescatter_1d_selection_alpha(self): # test with different alpha self.linescatterplot.unselected_alpha = 0.4 - self.linescatterplot.index.metadata['selections'] = [ + self.linescatterplot.index.metadata["selections"] = [ (arange(10) % 2 == 0), ] @@ -166,8 +165,7 @@ def test_linescatter_1d_set_index_range(self): def test_linescatter_1d_set_index_mapper_notifies_index_range(self): new_range = DataRange1D(low=0.42, high=1.42) - with self.assertTraitChanges( - self.linescatterplot, "index_range", count=1): + with self.assertTraitChanges(self.linescatterplot, "index_range", count=1): self.linescatterplot.index_mapper = LinearMapper(range=new_range) self.assertIs(self.linescatterplot.index_range, new_range) diff --git a/chaco/tests/test_linearmapper.py b/chaco/tests/test_linearmapper.py index 63c6e1c48..60a4166e3 100644 --- a/chaco/tests/test_linearmapper.py +++ b/chaco/tests/test_linearmapper.py @@ -1,4 +1,3 @@ - import unittest from numpy import array, ndarray from numpy.testing import assert_array_almost_equal, assert_equal @@ -6,8 +5,8 @@ from chaco.api import ArrayDataSource, DataRange1D, LinearMapper -class LinearMapperTestCase(unittest.TestCase): +class LinearMapperTestCase(unittest.TestCase): def test_basic(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) ds = ArrayDataSource(ary) @@ -15,12 +14,12 @@ def test_basic(self): mapper = LinearMapper(range=r) self.assertFalse(mapper._low_bound_initialized) self.assertFalse(mapper._high_bound_initialized) - mapper.low_pos=50 + mapper.low_pos = 50 self.assertTrue(mapper._low_bound_initialized) - mapper.high_pos=100 + mapper.high_pos = 100 self.assertTrue(mapper._high_bound_initialized) result = mapper.map_screen(ary) - assert_equal(result , array([50, 60, 70, 80, 90, 100])) + assert_equal(result, array([50, 60, 70, 80, 90, 100])) def test_reversed(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -29,12 +28,12 @@ def test_reversed(self): mapper = LinearMapper(range=r) self.assertFalse(mapper._low_bound_initialized) self.assertFalse(mapper._high_bound_initialized) - mapper.low_pos=100 + mapper.low_pos = 100 self.assertTrue(mapper._low_bound_initialized) - mapper.high_pos=0 + mapper.high_pos = 0 self.assertTrue(mapper._high_bound_initialized) result = mapper.map_screen(ary) - assert_equal(result , array([100, 80, 60, 40, 20, 0])) + assert_equal(result, array([100, 80, 60, 40, 20, 0])) def test_set_screen_bounds(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -47,7 +46,7 @@ def test_set_screen_bounds(self): self.assertTrue(mapper._low_bound_initialized) self.assertTrue(mapper._high_bound_initialized) result = mapper.map_screen(ary) - assert_equal(result , array([50, 60, 70, 80, 90, 100])) + assert_equal(result, array([50, 60, 70, 80, 90, 100])) def test_reversed_set_screen_bounds(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -60,7 +59,7 @@ def test_reversed_set_screen_bounds(self): self.assertTrue(mapper._low_bound_initialized) self.assertTrue(mapper._high_bound_initialized) result = mapper.map_screen(ary) - assert_equal(result , array([100, 80, 60, 40, 20, 0])) + assert_equal(result, array([100, 80, 60, 40, 20, 0])) def test_update_screen_bounds_stretch_data(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -71,8 +70,7 @@ def test_update_screen_bounds_stretch_data(self): mapper.screen_bounds = (50.0, 100.0) mapper.screen_bounds = (40.0, 120.0) result = mapper.map_screen(ary) - assert_array_almost_equal( - result, array([40.0, 56.0, 72.0, 88.0, 104.0, 120.0])) + assert_array_almost_equal(result, array([40.0, 56.0, 72.0, 88.0, 104.0, 120.0])) def test_update_screen_bounds_dont_stretch_data(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -83,8 +81,7 @@ def test_update_screen_bounds_dont_stretch_data(self): mapper.screen_bounds = (50.0, 100.0) mapper.screen_bounds = (40.0, 120.0) result = mapper.map_screen(ary) - assert_array_almost_equal( - result, array([40.0, 50.0, 60.0, 70.0, 80.0, 90.0])) + assert_array_almost_equal(result, array([40.0, 50.0, 60.0, 70.0, 80.0, 90.0])) def test_reversed_update_screen_bounds_stretch_data(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -95,8 +92,7 @@ def test_reversed_update_screen_bounds_stretch_data(self): mapper.screen_bounds = (100.0, 0.0) mapper.screen_bounds = (120.0, -10.0) result = mapper.map_screen(ary) - assert_array_almost_equal( - result, array([120.0, 94.0, 68.0, 42.0, 16.0, -10.0])) + assert_array_almost_equal(result, array([120.0, 94.0, 68.0, 42.0, 16.0, -10.0])) def test_reversed_update_screen_bounds_dont_stretch_data(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -107,8 +103,7 @@ def test_reversed_update_screen_bounds_dont_stretch_data(self): mapper.screen_bounds = (100.0, 0.0) mapper.screen_bounds = (120.0, -10.0) result = mapper.map_screen(ary) - assert_array_almost_equal( - result, array([120.0, 100.0, 80.0, 60.0, 40.0, 20.0])) + assert_array_almost_equal(result, array([120.0, 100.0, 80.0, 60.0, 40.0, 20.0])) def test_update_low_pos_stretch_data(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) diff --git a/chaco/tests/test_logmapper.py b/chaco/tests/test_logmapper.py index 8255fc754..39634da44 100644 --- a/chaco/tests/test_logmapper.py +++ b/chaco/tests/test_logmapper.py @@ -1,12 +1,11 @@ - import unittest from numpy import array, nan from numpy.testing import assert_array_almost_equal, assert_equal from chaco.api import ArrayDataSource, DataRange1D, LogMapper -class LogMapperTestCase(unittest.TestCase): +class LogMapperTestCase(unittest.TestCase): def test_basic(self): ary = array([1.0, 10.0, 100.0, 1000.0, 10000.0]) ds = ArrayDataSource(ary) diff --git a/chaco/tests/test_multi_array_data_source.py b/chaco/tests/test_multi_array_data_source.py index ac8ffbcc4..c6a441152 100644 --- a/chaco/tests/test_multi_array_data_source.py +++ b/chaco/tests/test_multi_array_data_source.py @@ -12,7 +12,6 @@ class MultiArrayDataTestCase(UnittestTools, unittest.TestCase): - def setUp(self): self.myarray = arange(20).reshape(10, 2) self.data_source = MultiArrayDataSource(self.myarray) @@ -36,7 +35,7 @@ def test_basic_setup(self): def test_set_data(self): new_array = arange(0, 40, 2).reshape(10, 2) - with self.assertTraitChanges(self.data_source, 'data_changed', count=1): + with self.assertTraitChanges(self.data_source, "data_changed", count=1): self.data_source.set_data(new_array) assert_array_equal(new_array, self.data_source._data) @@ -52,8 +51,7 @@ def test_get_data_axes(self): def test_get_data_no_data(self): data_source = MultiArrayDataSource() - assert_array_equal(data_source.get_data(), - empty(shape=(0, 1), dtype=float)) + assert_array_equal(data_source.get_data(), empty(shape=(0, 1), dtype=float)) def test_get_data_mask(self): data, mask = self.data_source.get_data_mask() @@ -67,7 +65,7 @@ def test_bounds(self): # descending myarray = arange(20)[::-1].reshape(10, 2) - data_source = MultiArrayDataSource(myarray, sort_order='descending') + data_source = MultiArrayDataSource(myarray, sort_order="descending") bounds = data_source.get_bounds() self.assertEqual(bounds, (0, 19)) @@ -84,7 +82,7 @@ def test_bounds_value(self): # descending myarray = arange(20)[::-1].reshape(10, 2) - data_source = MultiArrayDataSource(myarray, sort_order='descending') + data_source = MultiArrayDataSource(myarray, sort_order="descending") bounds = data_source.get_bounds(value=0) self.assertEqual(bounds, (1, 19)) @@ -101,7 +99,7 @@ def test_bounds_index(self): # descending myarray = arange(20)[::-1].reshape(10, 2) - data_source = MultiArrayDataSource(myarray, sort_order='descending') + data_source = MultiArrayDataSource(myarray, sort_order="descending") bounds = data_source.get_bounds(index=0) self.assertEqual(bounds, (18, 19)) @@ -126,15 +124,16 @@ def test_bounds_all_nans(self): self.assertTrue(isnan(bounds[1])) def test_metadata(self): - self.assertEqual(self.data_source.metadata, - {'annotations': [], 'selections': []}) + self.assertEqual( + self.data_source.metadata, {"annotations": [], "selections": []} + ) - @unittest.skip('change handler missing from class') + @unittest.skip("change handler missing from class") def test_metadata_changed(self): - with self.assertTraitChanges(self.data_source, 'metadata_changed', count=1): - self.data_source.metadata = {'new_metadata': True} + with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + self.data_source.metadata = {"new_metadata": True} - @unittest.skip('change handler missing from class') + @unittest.skip("change handler missing from class") def test_metadata_items_changed(self): - with self.assertTraitChanges(self.data_source, 'metadata_changed', count=1): - self.data_source.metadata['new_metadata'] = True + with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + self.data_source.metadata["new_metadata"] = True diff --git a/chaco/tests/test_plot.py b/chaco/tests/test_plot.py index a9c182b6b..704441065 100644 --- a/chaco/tests/test_plot.py +++ b/chaco/tests/test_plot.py @@ -22,8 +22,8 @@ def test_range_change(self): arr = arange(10) data = ArrayPlotData(x=arr, y=arr) plot = Plot(data) - renderer_2d = plot.plot(('x', 'y'))[0] - renderer_1d = plot.plot_1d(('x'))[0] + renderer_2d = plot.plot(("x", "y"))[0] + renderer_1d = plot.plot_1d(("x"))[0] new_range = DataRange1D() old_range = plot.index_range self.assertIsNot(old_range, new_range) @@ -39,7 +39,7 @@ def test_segment_plot(self): y = arange(1, 11) data = ArrayPlotData(x=x, y=y) plot = Plot(data) - plot.plot(('x', 'y'), "segment")[0] + plot.plot(("x", "y"), "segment")[0] plot.do_layout((250, 250)) gc = PlotGraphicsContext((250, 250)) @@ -53,7 +53,7 @@ def test_segment_plot_color(self): c = arange(2, 7) data = ArrayPlotData(x=x, y=y, c=c) plot = Plot(data) - plot.plot(('x', 'y', 'c'), "cmap_segment", color_mapper=viridis)[0] + plot.plot(("x", "y", "c"), "cmap_segment", color_mapper=viridis)[0] plot.do_layout((250, 250)) gc = PlotGraphicsContext((250, 250)) @@ -68,8 +68,7 @@ def test_segment_plot_color_width(self): w = arange(3, 8) data = ArrayPlotData(x=x, y=y, c=c, w=w) plot = Plot(data) - plot.plot(('x', 'y', 'c', 'w'), "cmap_segment", - color_mapper=viridis)[0] + plot.plot(("x", "y", "c", "w"), "cmap_segment", color_mapper=viridis)[0] plot.do_layout((250, 250)) gc = PlotGraphicsContext((250, 250)) @@ -83,7 +82,7 @@ def test_text_plot(self): t = array(["one", "two", "three", "four", "five"]) data = ArrayPlotData(x=x, y=y, t=t) plot = Plot(data) - plot.plot(('x', 'y', 't'), "text")[0] + plot.plot(("x", "y", "t"), "text")[0] plot.do_layout((250, 250)) gc = PlotGraphicsContext((250, 250)) diff --git a/chaco/tests/test_plot_factory.py b/chaco/tests/test_plot_factory.py index 072ee1825..a55b78275 100644 --- a/chaco/tests/test_plot_factory.py +++ b/chaco/tests/test_plot_factory.py @@ -1,9 +1,12 @@ - from unittest import TestCase import numpy as np -from chaco.plot_factory import create_bar_plot, create_line_plot, \ - create_polar_plot, create_scatter_plot +from chaco.plot_factory import ( + create_bar_plot, + create_line_plot, + create_polar_plot, + create_scatter_plot, +) from chaco.api import BarPlot, LinePlot, PlotAxis, PlotGrid, ScatterPlot from chaco.polar_line_renderer import PolarLineRenderer diff --git a/chaco/tests/test_plotcontainer.py b/chaco/tests/test_plotcontainer.py index f1cb3bb8b..bb39267bb 100644 --- a/chaco/tests/test_plotcontainer.py +++ b/chaco/tests/test_plotcontainer.py @@ -1,8 +1,13 @@ import sys import unittest -from chaco.api import HPlotContainer, OverlayPlotContainer, \ - PlotComponent, VPlotContainer, GridContainer +from chaco.api import ( + HPlotContainer, + OverlayPlotContainer, + PlotComponent, + VPlotContainer, + GridContainer, +) from traits.api import Any, Tuple SizePrefs = GridContainer.SizePrefs @@ -24,6 +29,7 @@ def __init__(self, bounds, *args, **kw): kw["resizable"] = "" PlotComponent.__init__(self, *args, **kw) + class ResizablePlotComponent(PlotComponent): """ A resizable PlotComponent with a fixed preferred size. """ @@ -47,18 +53,19 @@ def get_preferred_size(self): class OverlayPlotContainerTestCase(ContainerTestCase): - def test_basics(self): - container = OverlayPlotContainer(resizable='', bounds=[100.0,200.0]) - self.assert_tuple(container.get_preferred_size(), (100.0,200.0)) + container = OverlayPlotContainer(resizable="", bounds=[100.0, 200.0]) + self.assert_tuple(container.get_preferred_size(), (100.0, 200.0)) self.assertEqual(container._layout_needed, True) container.do_layout() self.assertEqual(container._layout_needed, False) def test_fixed_size_component(self): - container = OverlayPlotContainer(resizable='', bounds=[200.0,300.0]) + container = OverlayPlotContainer(resizable="", bounds=[200.0, 300.0]) # non-resizable component - component = PlotComponent(resizable='', position=[50.0,60.0], bounds=[100.0,110.0]) + component = PlotComponent( + resizable="", position=[50.0, 60.0], bounds=[100.0, 110.0] + ) self.assertEqual(container._layout_needed, True) container.do_layout() container.add(component) @@ -67,155 +74,156 @@ def test_fixed_size_component(self): self.assertEqual(container._layout_needed, False) # check the results of the layout - self.assert_tuple(container.get_preferred_size(), (200.0,300.0)) - self.assert_tuple(component.position, (50.0,60.0)) - self.assert_tuple(component.bounds, (100.0,110.0)) + self.assert_tuple(container.get_preferred_size(), (200.0, 300.0)) + self.assert_tuple(component.position, (50.0, 60.0)) + self.assert_tuple(component.bounds, (100.0, 110.0)) def test_resizable_component(self): - container = OverlayPlotContainer(resizable='', bounds=[200.0,300.0]) - component = PlotComponent(resizable='hv', position=[50.0,56.0], bounds=[100.0,110.0]) + container = OverlayPlotContainer(resizable="", bounds=[200.0, 300.0]) + component = PlotComponent( + resizable="hv", position=[50.0, 56.0], bounds=[100.0, 110.0] + ) container.add(component) container.do_layout() - self.assert_tuple(component.position, (0.0,0.0)) - self.assert_tuple(component.bounds, (200.0,300.0)) + self.assert_tuple(component.position, (0.0, 0.0)) + self.assert_tuple(component.bounds, (200.0, 300.0)) - comp2 = PlotComponent(resizable="h", position=[10,20], bounds=[100,150]) + comp2 = PlotComponent(resizable="h", position=[10, 20], bounds=[100, 150]) container.add(comp2) container.do_layout() self.assert_tuple(comp2.position, (0.0, 20.0)) self.assert_tuple(comp2.bounds, (200.0, 150.0)) - comp3 = PlotComponent(resizable="v", position=[30,40], bounds=[100,150]) + comp3 = PlotComponent(resizable="v", position=[30, 40], bounds=[100, 150]) container.add(comp3) container.do_layout() self.assert_tuple(comp3.position, (30.0, 0.0)) - self.assert_tuple(comp3.bounds, (100,300)) + self.assert_tuple(comp3.bounds, (100, 300)) def test_min_size(self): - container = OverlayPlotContainer(resizable='', bounds=[50.0,50.0]) - component = PlotComponent(resizable='', position=[50.0,60.0], - bounds=[100.0, 110.0]) + container = OverlayPlotContainer(resizable="", bounds=[50.0, 50.0]) + component = PlotComponent( + resizable="", position=[50.0, 60.0], bounds=[100.0, 110.0] + ) container.add(component) container.do_layout() - self.assert_tuple(component.position, (50.0,60.0)) - self.assert_tuple(component.bounds, (100.0,110.0)) + self.assert_tuple(component.position, (50.0, 60.0)) + self.assert_tuple(component.bounds, (100.0, 110.0)) def test_multiple_min_size(self): comp1 = StaticPlotComponent([200, 50]) comp2 = StaticPlotComponent([60, 300]) - container = OverlayPlotContainer(resizable='hv', bounds=[30,30]) + container = OverlayPlotContainer(resizable="hv", bounds=[30, 30]) container.fit_components = "hv" container.add(comp1, comp2) container.do_layout() - self.assert_tuple(container.get_preferred_size(), (200,300)) - self.assert_tuple(comp1.bounds, (200,50)) - self.assert_tuple(comp2.bounds, (60,300)) + self.assert_tuple(container.get_preferred_size(), (200, 300)) + self.assert_tuple(comp1.bounds, (200, 50)) + self.assert_tuple(comp2.bounds, (60, 300)) class HPlotContainerTestCase(ContainerTestCase): - def test_stack_nonresize(self): # Assuming resizable='' for all plot containers and components - container = HPlotContainer(bounds=[300,100]) - comp1 = StaticPlotComponent([100,70]) - comp2 = StaticPlotComponent([90,80]) - comp3 = StaticPlotComponent([80,90]) + container = HPlotContainer(bounds=[300, 100]) + comp1 = StaticPlotComponent([100, 70]) + comp2 = StaticPlotComponent([90, 80]) + comp3 = StaticPlotComponent([80, 90]) container.add(comp1, comp2, comp3) container.do_layout() - self.assert_tuple(container.get_preferred_size(), (270,90)) - self.assert_tuple(container.bounds, (300,100)) - self.assert_tuple(comp1.position, (0,0)) - self.assert_tuple(comp2.position, (100,0)) - self.assert_tuple(comp3.position, (190,0)) + self.assert_tuple(container.get_preferred_size(), (270, 90)) + self.assert_tuple(container.bounds, (300, 100)) + self.assert_tuple(comp1.position, (0, 0)) + self.assert_tuple(comp2.position, (100, 0)) + self.assert_tuple(comp3.position, (190, 0)) def test_stack_one_resize(self): "Checks stacking with 1 resizable component thrown in" - container = HPlotContainer(bounds=[300,100]) - comp1 = StaticPlotComponent([100,70]) - comp2 = StaticPlotComponent([90,80]) - comp3 = StaticPlotComponent([80,90], resizable='hv') - comp4 = StaticPlotComponent([40,50]) + container = HPlotContainer(bounds=[300, 100]) + comp1 = StaticPlotComponent([100, 70]) + comp2 = StaticPlotComponent([90, 80]) + comp3 = StaticPlotComponent([80, 90], resizable="hv") + comp4 = StaticPlotComponent([40, 50]) container.add(comp1, comp2, comp3, comp4) container.do_layout() - self.assert_tuple(container.get_preferred_size(), (230,80)) - self.assert_tuple(container.bounds, (300,100)) - self.assert_tuple(comp1.position, (0,0)) - self.assert_tuple(comp2.position, (100,0)) - self.assert_tuple(comp3.position, (190,0)) - self.assert_tuple(comp4.position, (260,0)) + self.assert_tuple(container.get_preferred_size(), (230, 80)) + self.assert_tuple(container.bounds, (300, 100)) + self.assert_tuple(comp1.position, (0, 0)) + self.assert_tuple(comp2.position, (100, 0)) + self.assert_tuple(comp3.position, (190, 0)) + self.assert_tuple(comp4.position, (260, 0)) def test_valign(self): - container = HPlotContainer(bounds=[300,200], valign="center") - comp1 = StaticPlotComponent([200,100]) + container = HPlotContainer(bounds=[300, 200], valign="center") + comp1 = StaticPlotComponent([200, 100]) container.add(comp1) container.do_layout() - self.assertEqual(comp1.position, [0,50]) - container.valign="top" + self.assertEqual(comp1.position, [0, 50]) + container.valign = "top" container.do_layout(force=True) - self.assertEqual(comp1.position, [0,100]) + self.assertEqual(comp1.position, [0, 100]) class VPlotContainerTestCase(ContainerTestCase): # These tests are mostly transposes of the values in HPlotContainer def test_stack_nonresize(self): - container = VPlotContainer(bounds=[100,300]) - comp1 = StaticPlotComponent([70,100]) - comp2 = StaticPlotComponent([80,90]) - comp3 = StaticPlotComponent([90,80]) + container = VPlotContainer(bounds=[100, 300]) + comp1 = StaticPlotComponent([70, 100]) + comp2 = StaticPlotComponent([80, 90]) + comp3 = StaticPlotComponent([90, 80]) container.add(comp1, comp2, comp3) container.do_layout() self.assert_tuple(container.get_preferred_size(), (90, 270)) - self.assert_tuple(container.bounds, (100,300)) - self.assert_tuple(comp1.position, (0,0)) - self.assert_tuple(comp2.position, (0,100)) - self.assert_tuple(comp3.position, (0,190)) + self.assert_tuple(container.bounds, (100, 300)) + self.assert_tuple(comp1.position, (0, 0)) + self.assert_tuple(comp2.position, (0, 100)) + self.assert_tuple(comp3.position, (0, 190)) def test_stack_one_resize(self): "Checks stacking with 1 resizable component thrown in" - container = VPlotContainer(bounds=[100,300]) - comp1 = StaticPlotComponent([70,100]) - comp2 = StaticPlotComponent([80,90]) - comp3 = StaticPlotComponent([90,80], resizable='hv') - comp4 = StaticPlotComponent([50,40]) + container = VPlotContainer(bounds=[100, 300]) + comp1 = StaticPlotComponent([70, 100]) + comp2 = StaticPlotComponent([80, 90]) + comp3 = StaticPlotComponent([90, 80], resizable="hv") + comp4 = StaticPlotComponent([50, 40]) container.add(comp1, comp2, comp3, comp4) container.do_layout() - self.assert_tuple(container.get_preferred_size(), (80,230)) - self.assert_tuple(container.bounds, (100,300)) - self.assert_tuple(comp1.position, (0,0)) - self.assert_tuple(comp2.position, (0,100)) - self.assert_tuple(comp3.position, (0,190)) - self.assert_tuple(comp4.position, (0,260)) + self.assert_tuple(container.get_preferred_size(), (80, 230)) + self.assert_tuple(container.bounds, (100, 300)) + self.assert_tuple(comp1.position, (0, 0)) + self.assert_tuple(comp2.position, (0, 100)) + self.assert_tuple(comp3.position, (0, 190)) + self.assert_tuple(comp4.position, (0, 260)) def test_halign(self): - container = VPlotContainer(bounds=[200,300], halign="center") - comp1 = StaticPlotComponent([100,200]) + container = VPlotContainer(bounds=[200, 300], halign="center") + comp1 = StaticPlotComponent([100, 200]) container.add(comp1) container.do_layout() - self.assertEqual(comp1.position, [50,0]) - container.halign="right" + self.assertEqual(comp1.position, [50, 0]) + container.halign = "right" container.do_layout(force=True) - self.assertEqual(comp1.position, [100,0]) + self.assertEqual(comp1.position, [100, 0]) def test_fit_components(self): - container = VPlotContainer(bounds=[200,300], resizable="v", fit_components="v") - comp1 = StaticPlotComponent([50,100], padding=5) - comp2 = StaticPlotComponent([50,120], padding=5) + container = VPlotContainer(bounds=[200, 300], resizable="v", fit_components="v") + comp1 = StaticPlotComponent([50, 100], padding=5) + comp2 = StaticPlotComponent([50, 120], padding=5) container.add(comp1) container.add(comp2) - self.assert_tuple(container.get_preferred_size(), (200,240)) + self.assert_tuple(container.get_preferred_size(), (200, 240)) # The container should not change its size as a result of its fit_components # being set. - self.assert_tuple(container.bounds, (200,300)) + self.assert_tuple(container.bounds, (200, 300)) container.bounds = container.get_preferred_size() container.do_layout() container.padding = 8 - self.assert_tuple(container.get_preferred_size(), (216,256)) + self.assert_tuple(container.get_preferred_size(), (216, 256)) container.do_layout() - self.assert_tuple(comp1.outer_position, (0,0)) - self.assert_tuple(comp2.outer_position, (0,110)) - + self.assert_tuple(comp1.outer_position, (0, 0)) + self.assert_tuple(comp2.outer_position, (0, 110)) class SizePrefsTestCase(unittest.TestCase): @@ -225,21 +233,21 @@ def assert_tuple(self, t1, t2): def test_sequential_non_resizable(self): prefs = SizePrefs(4, "h") - components = [StaticPlotComponent([100,100]) for i in range(4)] + components = [StaticPlotComponent([100, 100]) for i in range(4)] for i, c in enumerate(components): prefs.update_from_component(c, i) pref_size = prefs.get_preferred_size() - self.assert_tuple(pref_size, (100,100,100,100)) + self.assert_tuple(pref_size, (100, 100, 100, 100)) sizes = prefs.compute_size_array(400) - self.assert_tuple(sizes, (100,100,100,100)) + self.assert_tuple(sizes, (100, 100, 100, 100)) sizes2 = prefs.compute_size_array(500) - self.assert_tuple(sizes, (100,100,100,100)) + self.assert_tuple(sizes, (100, 100, 100, 100)) def test_overlapping_non_resizable(self): prefs = SizePrefs(1, "h") - prefs.update_from_component(StaticPlotComponent([100,10]), 0) - prefs.update_from_component(StaticPlotComponent([200,10]), 0) - prefs.update_from_component(StaticPlotComponent([300,10]), 0) + prefs.update_from_component(StaticPlotComponent([100, 10]), 0) + prefs.update_from_component(StaticPlotComponent([200, 10]), 0) + prefs.update_from_component(StaticPlotComponent([300, 10]), 0) pref_size = prefs.get_preferred_size() self.assertEqual(pref_size[0], 300) sizes = prefs.compute_size_array(400) @@ -247,11 +255,11 @@ def test_overlapping_non_resizable(self): def test_sequential_resizable(self): prefs = SizePrefs(3, "v") - prefs.update_from_component(ResizablePlotComponent([10,100]), 0) - prefs.update_from_component(ResizablePlotComponent([10,200]), 1) - prefs.update_from_component(ResizablePlotComponent([10,300]), 2) + prefs.update_from_component(ResizablePlotComponent([10, 100]), 0) + prefs.update_from_component(ResizablePlotComponent([10, 200]), 1) + prefs.update_from_component(ResizablePlotComponent([10, 300]), 2) pref_size = prefs.get_preferred_size() - self.assert_tuple(pref_size, (100,200,300)) + self.assert_tuple(pref_size, (100, 200, 300)) sizes = prefs.compute_size_array(600) self.assert_tuple(sizes, [100, 200, 300]) sizes2 = prefs.compute_size_array(60) @@ -265,7 +273,7 @@ def test_overlapping_resizable(self): prefs.update_from_component(ResizablePlotComponent([100, 10]), 0) prefs.update_from_component(ResizablePlotComponent([80, 10]), 1) pref_size = prefs.get_preferred_size() - self.assert_tuple(pref_size, (100,80)) + self.assert_tuple(pref_size, (100, 80)) sizes = prefs.compute_size_array(180) self.assert_tuple(sizes, (100, 80)) sizes2 = prefs.compute_size_array(360) @@ -276,7 +284,7 @@ def test_sequential_fully_resizable(self): for i in range(3): prefs.update_from_component(ResizablePlotComponent(), i) pref_size = prefs.get_preferred_size() - self.assert_tuple(pref_size, (0,0,0)) + self.assert_tuple(pref_size, (0, 0, 0)) sizes = prefs.compute_size_array(60) self.assert_tuple(sizes, (20, 20, 20)) @@ -293,7 +301,7 @@ def test_sequential_mixed_resizable(self): # Tests a sequence of resizable and fully resizable components. prefs = SizePrefs(3, "h") prefs.update_from_component(ResizablePlotComponent(), 0) - prefs.update_from_component(ResizablePlotComponent([100,10]), 1) + prefs.update_from_component(ResizablePlotComponent([100, 10]), 1) prefs.update_from_component(ResizablePlotComponent(), 2) pref_size = prefs.get_preferred_size() self.assert_tuple(pref_size, (0, 100, 0)) @@ -308,14 +316,14 @@ def test_overlapping_mixed_resizable(self): # Tests a sequence of overlapping resizable and fully resizable components. prefs = SizePrefs(4, "h") # Slot 1 - prefs.update_from_component(ResizablePlotComponent([100,10]), 0) + prefs.update_from_component(ResizablePlotComponent([100, 10]), 0) prefs.update_from_component(ResizablePlotComponent(), 0) # Slot 2 prefs.update_from_component(ResizablePlotComponent(), 1) - prefs.update_from_component(ResizablePlotComponent([50,10]), 1) + prefs.update_from_component(ResizablePlotComponent([50, 10]), 1) # Slot 3 prefs.update_from_component(ResizablePlotComponent(), 2) - prefs.update_from_component(ResizablePlotComponent([40,10]), 2) + prefs.update_from_component(ResizablePlotComponent([40, 10]), 2) # Slot 4 prefs.update_from_component(ResizablePlotComponent(), 3) prefs.update_from_component(ResizablePlotComponent(), 3) @@ -329,42 +337,42 @@ def test_overlapping_mixed_resizable(self): def test_sequential_mixed_resizable_static(self): # Tests a sequence of static and resizable components. prefs = SizePrefs(3, "h") - prefs.update_from_component(StaticPlotComponent([100,10]), 0) - prefs.update_from_component(ResizablePlotComponent([50,10]), 1) - prefs.update_from_component(ResizablePlotComponent([75,10]), 2) + prefs.update_from_component(StaticPlotComponent([100, 10]), 0) + prefs.update_from_component(ResizablePlotComponent([50, 10]), 1) + prefs.update_from_component(ResizablePlotComponent([75, 10]), 2) pref_size = prefs.get_preferred_size() - self.assert_tuple(pref_size, (100,50,75)) + self.assert_tuple(pref_size, (100, 50, 75)) sizes = prefs.compute_size_array(225) - self.assert_tuple(sizes, (100,50,75)) + self.assert_tuple(sizes, (100, 50, 75)) sizes2 = prefs.compute_size_array(350) - self.assert_tuple(sizes2, (100,100,150)) + self.assert_tuple(sizes2, (100, 100, 150)) def test_sequential_mixed_resizable_static2(self): # Tests a sequence of non-overlapping static, resizable, and fully # resizable components. prefs = SizePrefs(4, "h") - prefs.update_from_component(StaticPlotComponent([100,10]), 0) - prefs.update_from_component(ResizablePlotComponent([50,10]), 1) - prefs.update_from_component(ResizablePlotComponent([75,10]), 2) + prefs.update_from_component(StaticPlotComponent([100, 10]), 0) + prefs.update_from_component(ResizablePlotComponent([50, 10]), 1) + prefs.update_from_component(ResizablePlotComponent([75, 10]), 2) prefs.update_from_component(ResizablePlotComponent(), 3) pref_size = prefs.get_preferred_size() - self.assert_tuple(pref_size, (100,50,75,0)) + self.assert_tuple(pref_size, (100, 50, 75, 0)) sizes = prefs.compute_size_array(300) - self.assert_tuple(sizes, (100,50,75,75)) + self.assert_tuple(sizes, (100, 50, 75, 75)) def test_overlapping_mixed_resizable_static(self): prefs = SizePrefs(5, "h") # Slot 1 - static and smaller resizable - prefs.update_from_component(StaticPlotComponent([100,10]), 0) - prefs.update_from_component(ResizablePlotComponent([50,10]), 0) + prefs.update_from_component(StaticPlotComponent([100, 10]), 0) + prefs.update_from_component(ResizablePlotComponent([50, 10]), 0) # Slot 2 - static and larger resizable - prefs.update_from_component(StaticPlotComponent([30,10]), 1) - prefs.update_from_component(ResizablePlotComponent([60,10]), 1) + prefs.update_from_component(StaticPlotComponent([30, 10]), 1) + prefs.update_from_component(ResizablePlotComponent([60, 10]), 1) # Slot 3 - static and fully resizable - prefs.update_from_component(StaticPlotComponent([50,10]), 2) + prefs.update_from_component(StaticPlotComponent([50, 10]), 2) prefs.update_from_component(ResizablePlotComponent(), 2) # Slot 4 - resizable and fully resizable - prefs.update_from_component(ResizablePlotComponent([90,10]), 3) + prefs.update_from_component(ResizablePlotComponent([90, 10]), 3) prefs.update_from_component(ResizablePlotComponent(), 3) # Slot 5 - fully resizable prefs.update_from_component(ResizablePlotComponent(), 4) @@ -374,7 +382,7 @@ def test_overlapping_mixed_resizable_static(self): # Test scaling down of resizable components in slots 2 and 4 sizes = prefs.compute_size_array(180 + 60) - self.assert_tuple(sizes, (100, 30+15, 50, 45, 0)) + self.assert_tuple(sizes, (100, 30 + 15, 50, 45, 0)) # Test scaling up of fully resizable component in slot 5, and proper # allocation of slot 2's resizable component's full preferred size. @@ -382,26 +390,24 @@ def test_overlapping_mixed_resizable_static(self): self.assert_tuple(sizes2, (100, 60, 50, 90, 35)) - class GridContainerTestCase(ContainerTestCase): - def test_empty_container(self): - cont = GridContainer(shape=(1,1)) - cont.bounds = [100,100] + cont = GridContainer(shape=(1, 1)) + cont.bounds = [100, 100] cont.do_layout() def test_all_empty_cells(self): - cont = GridContainer(shape=(2,2), spacing=(0,0)) + cont = GridContainer(shape=(2, 2), spacing=(0, 0)) cont.component_grid = [[None, None], [None, None]] size = cont.get_preferred_size() - self.assert_tuple(size, (0,0)) - cont.bounds = (100,100) + self.assert_tuple(size, (0, 0)) + cont.bounds = (100, 100) cont.do_layout() def test_some_empty_cells(self): - cont = GridContainer(shape=(2,2), spacing=(0,0)) - a = StaticPlotComponent([100,30]) - b = StaticPlotComponent([50,40]) + cont = GridContainer(shape=(2, 2), spacing=(0, 0)) + a = StaticPlotComponent([100, 30]) + b = StaticPlotComponent([50, 40]) cont.component_grid = [[a, None], [None, b]] size = cont.get_preferred_size() self.assert_tuple(size, (150, 70)) @@ -409,216 +415,223 @@ def test_some_empty_cells(self): cont.do_layout() self.assert_tuple(a.outer_position, (0, 40)) self.assert_tuple(a.outer_bounds, (100, 30)) - self.assert_tuple(b.outer_position, (100,0)) + self.assert_tuple(b.outer_position, (100, 0)) self.assert_tuple(b.outer_bounds, (50, 40)) def test_single_cell(self): - cont = GridContainer(shape=(1,1)) - comp1 = StaticPlotComponent([200,300]) + cont = GridContainer(shape=(1, 1)) + comp1 = StaticPlotComponent([200, 300]) cont.add(comp1) cont.do_layout() # it would be nice to make all boolean tests here trigger # assert failures, maybe using Pypy? - self.assert_tuple(comp1.position, (0,0)) - self.assert_tuple(comp1.bounds, (200,300)) + self.assert_tuple(comp1.position, (0, 0)) + self.assert_tuple(comp1.bounds, (200, 300)) def test_nonresizable_container(self): - cont = GridContainer(shape=(1,1), resizable="") - comp1 = StaticPlotComponent([200,300]) + cont = GridContainer(shape=(1, 1), resizable="") + comp1 = StaticPlotComponent([200, 300]) cont.add(comp1) cont.do_layout() - self.assert_tuple(comp1.position, (0,0)) - self.assert_tuple(comp1.bounds, (200,300)) + self.assert_tuple(comp1.position, (0, 0)) + self.assert_tuple(comp1.bounds, (200, 300)) def test_row(self): - cont = GridContainer(shape=(1,3), halign="center", valign="center") - c1 = StaticPlotComponent([50,50]) - c2 = StaticPlotComponent([30,30]) - c3 = StaticPlotComponent([0,0], resizable="hv") + cont = GridContainer(shape=(1, 3), halign="center", valign="center") + c1 = StaticPlotComponent([50, 50]) + c2 = StaticPlotComponent([30, 30]) + c3 = StaticPlotComponent([0, 0], resizable="hv") cont.add(c1, c2, c3) cont.bounds = list(cont.get_preferred_size()) cont.do_layout() - self.assert_tuple(c1.position, (0,0)) - self.assert_tuple(c1.bounds, (50,50)) - self.assert_tuple(c2.position, (50,10)) - self.assert_tuple(c2.bounds, (30,30)) - self.assert_tuple(c3.position, (80,0)) - self.assert_tuple(c3.bounds, (0,50)) + self.assert_tuple(c1.position, (0, 0)) + self.assert_tuple(c1.bounds, (50, 50)) + self.assert_tuple(c2.position, (50, 10)) + self.assert_tuple(c2.bounds, (30, 30)) + self.assert_tuple(c3.position, (80, 0)) + self.assert_tuple(c3.bounds, (0, 50)) cont.bounds = [100, 50] cont.do_layout() - self.assert_tuple(c1.position, (0,0)) - self.assert_tuple(c1.bounds, (50,50)) - self.assert_tuple(c2.position, (50,10)) - self.assert_tuple(c2.bounds, (30,30)) - self.assert_tuple(c3.position, (80,0)) - self.assert_tuple(c3.bounds, (20,50)) + self.assert_tuple(c1.position, (0, 0)) + self.assert_tuple(c1.bounds, (50, 50)) + self.assert_tuple(c2.position, (50, 10)) + self.assert_tuple(c2.bounds, (30, 30)) + self.assert_tuple(c3.position, (80, 0)) + self.assert_tuple(c3.bounds, (20, 50)) def test_two_by_two(self): """ Tests a 2x2 grid of components """ - cont = GridContainer(shape=(2,2), halign="center", valign="center") - ul = StaticPlotComponent([50,50]) # upper-left component - lr = StaticPlotComponent([100,100]) # lower-right component - top = StaticPlotComponent([0,0], resizable="hv") - left = StaticPlotComponent([0,0], resizable="hv") + cont = GridContainer(shape=(2, 2), halign="center", valign="center") + ul = StaticPlotComponent([50, 50]) # upper-left component + lr = StaticPlotComponent([100, 100]) # lower-right component + top = StaticPlotComponent([0, 0], resizable="hv") + left = StaticPlotComponent([0, 0], resizable="hv") cont.component_grid = [[ul, top], [left, lr]] cont.bounds = [150, 150] cont.do_layout() - self.assert_tuple(ul.position, (0,100)) - self.assert_tuple(ul.bounds, (50,50)) - self.assert_tuple(top.position, (50,100)) + self.assert_tuple(ul.position, (0, 100)) + self.assert_tuple(ul.bounds, (50, 50)) + self.assert_tuple(top.position, (50, 100)) self.assert_tuple(top.bounds, (100, 50)) - self.assert_tuple(left.position, (0,0)) - self.assert_tuple(left.bounds, (50,100)) - self.assert_tuple(lr.position, (50,0)) - self.assert_tuple(lr.bounds, (100,100)) + self.assert_tuple(left.position, (0, 0)) + self.assert_tuple(left.bounds, (50, 100)) + self.assert_tuple(lr.position, (50, 0)) + self.assert_tuple(lr.bounds, (100, 100)) def test_spacing(self): - cont = GridContainer(shape=(2,2), spacing=(10,10), - halign="center", valign="center") - ul = StaticPlotComponent([50,50]) # upper-left component - lr = StaticPlotComponent([100,100]) # lower-right component - top = StaticPlotComponent([0,0], resizable="hv") - left = StaticPlotComponent([0,0], resizable="hv") + cont = GridContainer( + shape=(2, 2), spacing=(10, 10), halign="center", valign="center" + ) + ul = StaticPlotComponent([50, 50]) # upper-left component + lr = StaticPlotComponent([100, 100]) # lower-right component + top = StaticPlotComponent([0, 0], resizable="hv") + left = StaticPlotComponent([0, 0], resizable="hv") cont.component_grid = [[ul, top], [left, lr]] cont.bounds = [190, 190] cont.do_layout() - self.assert_tuple(ul.position, (10,130)) - self.assert_tuple(ul.bounds, (50,50)) - self.assert_tuple(top.position, (80,130)) + self.assert_tuple(ul.position, (10, 130)) + self.assert_tuple(ul.bounds, (50, 50)) + self.assert_tuple(top.position, (80, 130)) self.assert_tuple(top.bounds, (100, 50)) - self.assert_tuple(left.position, (10,10)) - self.assert_tuple(left.bounds, (50,100)) - self.assert_tuple(lr.position, (80,10)) - self.assert_tuple(lr.bounds, (100,100)) + self.assert_tuple(left.position, (10, 10)) + self.assert_tuple(left.bounds, (50, 100)) + self.assert_tuple(lr.position, (80, 10)) + self.assert_tuple(lr.bounds, (100, 100)) def test_resizable(self): - cont = GridContainer(shape=(2,2), spacing=(0,0), - halign="center", valign="center") - ul = StaticPlotComponent([0,0], resizable="hv") - lr = StaticPlotComponent([0,0], resizable="hv") - top = StaticPlotComponent([0,0], resizable="hv") - left = StaticPlotComponent([0,0], resizable="hv") + cont = GridContainer( + shape=(2, 2), spacing=(0, 0), halign="center", valign="center" + ) + ul = StaticPlotComponent([0, 0], resizable="hv") + lr = StaticPlotComponent([0, 0], resizable="hv") + top = StaticPlotComponent([0, 0], resizable="hv") + left = StaticPlotComponent([0, 0], resizable="hv") cont.component_grid = [[ul, top], [left, lr]] cont.bounds = [200, 200] cont.do_layout() - self.assert_tuple(ul.position, (0,100)) - self.assert_tuple(ul.bounds, (100,100)) - self.assert_tuple(top.position, (100,100)) + self.assert_tuple(ul.position, (0, 100)) + self.assert_tuple(ul.bounds, (100, 100)) + self.assert_tuple(top.position, (100, 100)) self.assert_tuple(top.bounds, (100, 100)) - self.assert_tuple(left.position, (0,0)) - self.assert_tuple(left.bounds, (100,100)) - self.assert_tuple(lr.position, (100,0)) - self.assert_tuple(lr.bounds, (100,100)) + self.assert_tuple(left.position, (0, 0)) + self.assert_tuple(left.bounds, (100, 100)) + self.assert_tuple(lr.position, (100, 0)) + self.assert_tuple(lr.bounds, (100, 100)) def test_resizable2(self): # Tests a resizable component that also has a preferred size - cont = GridContainer(shape=(2,2), spacing=(0,0), - halign="center", valign="center") - ul = StaticPlotComponent([150,150], resizable="hv") - lr = StaticPlotComponent([0,0], resizable="hv") - top = StaticPlotComponent([0,0], resizable="hv") - left = StaticPlotComponent([0,0], resizable="hv") + cont = GridContainer( + shape=(2, 2), spacing=(0, 0), halign="center", valign="center" + ) + ul = StaticPlotComponent([150, 150], resizable="hv") + lr = StaticPlotComponent([0, 0], resizable="hv") + top = StaticPlotComponent([0, 0], resizable="hv") + left = StaticPlotComponent([0, 0], resizable="hv") cont.component_grid = [[ul, top], [left, lr]] cont.bounds = [200, 200] cont.do_layout() - self.assert_tuple(ul.position, (0,100)) - self.assert_tuple(ul.bounds, (100,100)) - self.assert_tuple(top.position, (100,100)) - self.assert_tuple(top.bounds, (100,100)) - self.assert_tuple(left.position, (0,0)) - self.assert_tuple(left.bounds, (100,100)) - self.assert_tuple(lr.position, (100,0)) - self.assert_tuple(lr.bounds, (100,100)) + self.assert_tuple(ul.position, (0, 100)) + self.assert_tuple(ul.bounds, (100, 100)) + self.assert_tuple(top.position, (100, 100)) + self.assert_tuple(top.bounds, (100, 100)) + self.assert_tuple(left.position, (0, 0)) + self.assert_tuple(left.bounds, (100, 100)) + self.assert_tuple(lr.position, (100, 0)) + self.assert_tuple(lr.bounds, (100, 100)) def test_resizable_mixed(self): """ Tests mixing resizable and non-resizable components """ - cont = GridContainer(shape=(2,2), spacing=(10,10), - halign="center", valign="center") - ul = StaticPlotComponent([0,0], resizable="hv") - lr = StaticPlotComponent([0,0], resizable="hv") - top = StaticPlotComponent([0,0], resizable="hv") - left = StaticPlotComponent([100,100], resizable="") + cont = GridContainer( + shape=(2, 2), spacing=(10, 10), halign="center", valign="center" + ) + ul = StaticPlotComponent([0, 0], resizable="hv") + lr = StaticPlotComponent([0, 0], resizable="hv") + top = StaticPlotComponent([0, 0], resizable="hv") + left = StaticPlotComponent([100, 100], resizable="") cont.component_grid = [[ul, top], [left, lr]] cont.bounds = [240, 240] cont.do_layout() - self.assert_tuple(ul.position, (10,130)) - self.assert_tuple(ul.bounds, (100,100)) - self.assert_tuple(top.position, (130,130)) + self.assert_tuple(ul.position, (10, 130)) + self.assert_tuple(ul.bounds, (100, 100)) + self.assert_tuple(top.position, (130, 130)) self.assert_tuple(top.bounds, (100, 100)) - self.assert_tuple(left.position, (10,10)) - self.assert_tuple(left.bounds, (100,100)) - self.assert_tuple(lr.position, (130,10)) - self.assert_tuple(lr.bounds, (100,100)) + self.assert_tuple(left.position, (10, 10)) + self.assert_tuple(left.bounds, (100, 100)) + self.assert_tuple(lr.position, (130, 10)) + self.assert_tuple(lr.bounds, (100, 100)) def test_resizable_mixed2(self): # Tests laying out resizable components with preferred # sized alongside non-resizable components. - cont = GridContainer(shape=(2,2), spacing=(0,0), - halign="center", valign="center") - ul = ResizablePlotComponent([150,150]) - lr = StaticPlotComponent([50,50], resizable="") - top = StaticPlotComponent([0,0], resizable="hv") - left = StaticPlotComponent([0,0], resizable="hv") + cont = GridContainer( + shape=(2, 2), spacing=(0, 0), halign="center", valign="center" + ) + ul = ResizablePlotComponent([150, 150]) + lr = StaticPlotComponent([50, 50], resizable="") + top = StaticPlotComponent([0, 0], resizable="hv") + left = StaticPlotComponent([0, 0], resizable="hv") cont.component_grid = [[ul, top], [left, lr]] cont.bounds = [200, 200] cont.do_layout() - self.assert_tuple(ul.position, (0,50)) - self.assert_tuple(ul.bounds, (150,150)) - self.assert_tuple(top.position, (150,50)) - self.assert_tuple(top.bounds, (50,150)) - self.assert_tuple(left.position, (0,0)) - self.assert_tuple(left.bounds, (150,50)) - self.assert_tuple(lr.position, (150,0)) - self.assert_tuple(lr.bounds, (50,50)) + self.assert_tuple(ul.position, (0, 50)) + self.assert_tuple(ul.bounds, (150, 150)) + self.assert_tuple(top.position, (150, 50)) + self.assert_tuple(top.bounds, (50, 150)) + self.assert_tuple(left.position, (0, 0)) + self.assert_tuple(left.bounds, (150, 50)) + self.assert_tuple(lr.position, (150, 0)) + self.assert_tuple(lr.bounds, (50, 50)) def test_resizable_mixed_h(self): # Tests the layout of a non-resizable component, a resizable with a # preferred size, and a fully resizable component in a horizontal # GridContainer - cont = GridContainer(shape=(3,1), spacing=(0,0), - halign="center", valign="center") - left = StaticPlotComponent([50,10], resizable="") - middle = ResizablePlotComponent([100,10]) - right = StaticPlotComponent([0,0], resizable="hv") + cont = GridContainer( + shape=(3, 1), spacing=(0, 0), halign="center", valign="center" + ) + left = StaticPlotComponent([50, 10], resizable="") + middle = ResizablePlotComponent([100, 10]) + right = StaticPlotComponent([0, 0], resizable="hv") cont.component_grid = [[left, middle, right]] cont.bounds = [200, 10] cont.do_layout() - self.assert_tuple(left.position, (0,0)) - self.assert_tuple(left.bounds, (50,10)) - self.assert_tuple(middle.position, (50,0)) - self.assert_tuple(middle.bounds, (100,10)) - self.assert_tuple(right.position, (150,0)) - self.assert_tuple(right.bounds, (50,10)) + self.assert_tuple(left.position, (0, 0)) + self.assert_tuple(left.bounds, (50, 10)) + self.assert_tuple(middle.position, (50, 0)) + self.assert_tuple(middle.bounds, (100, 10)) + self.assert_tuple(right.position, (150, 0)) + self.assert_tuple(right.bounds, (50, 10)) def test_non_resizable(self): - cont = GridContainer(shape=(2,2), spacing=(10,10), - halign="center", valign="center") - ul = StaticPlotComponent([100,100], resizable="") - ur = StaticPlotComponent([100,100], resizable="") - ll = StaticPlotComponent([100,100], resizable="") - lr = StaticPlotComponent([100,100], resizable="") + cont = GridContainer( + shape=(2, 2), spacing=(10, 10), halign="center", valign="center" + ) + ul = StaticPlotComponent([100, 100], resizable="") + ur = StaticPlotComponent([100, 100], resizable="") + ll = StaticPlotComponent([100, 100], resizable="") + lr = StaticPlotComponent([100, 100], resizable="") cont.component_grid = [[ul, ur], [ll, lr]] cont.bounds = [240, 240] cont.do_layout() - self.assert_tuple(ul.position, (10,130)) - self.assert_tuple(ul.bounds, (100,100)) - self.assert_tuple(ur.position, (130,130)) + self.assert_tuple(ul.position, (10, 130)) + self.assert_tuple(ul.bounds, (100, 100)) + self.assert_tuple(ur.position, (130, 130)) self.assert_tuple(ur.bounds, (100, 100)) - self.assert_tuple(ll.position, (10,10)) - self.assert_tuple(ll.bounds, (100,100)) - self.assert_tuple(lr.position, (130,10)) - self.assert_tuple(lr.bounds, (100,100)) + self.assert_tuple(ll.position, (10, 10)) + self.assert_tuple(ll.bounds, (100, 100)) + self.assert_tuple(lr.position, (130, 10)) + self.assert_tuple(lr.bounds, (100, 100)) cont.bounds = [280, 280] cont.do_layout() - self.assert_tuple(ul.position, (20,160)) - self.assert_tuple(ul.bounds, (100,100)) - self.assert_tuple(ur.position, (160,160)) + self.assert_tuple(ul.position, (20, 160)) + self.assert_tuple(ul.bounds, (100, 100)) + self.assert_tuple(ur.position, (160, 160)) self.assert_tuple(ur.bounds, (100, 100)) - self.assert_tuple(ll.position, (20,20)) - self.assert_tuple(ll.bounds, (100,100)) - self.assert_tuple(lr.position, (160,20)) - self.assert_tuple(lr.bounds, (100,100)) + self.assert_tuple(ll.position, (20, 20)) + self.assert_tuple(ll.bounds, (100, 100)) + self.assert_tuple(lr.position, (160, 20)) + self.assert_tuple(lr.bounds, (100, 100)) diff --git a/chaco/tests/test_scatterplot_1d.py b/chaco/tests/test_scatterplot_1d.py index df3deb9cd..6b9e6db56 100644 --- a/chaco/tests/test_scatterplot_1d.py +++ b/chaco/tests/test_scatterplot_1d.py @@ -7,13 +7,11 @@ from traits.testing.unittest_tools import UnittestTools # Chaco imports -from chaco.api import (ArrayDataSource, DataRange1D, LinearMapper, - PlotGraphicsContext) +from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext from chaco.scatterplot_1d import ScatterPlot1D class Scatterplot1DTest(UnittestTools, unittest.TestCase): - def setUp(self): self.size = (250, 250) data_source = ArrayDataSource(arange(10)) @@ -28,12 +26,10 @@ def setUp(self): self.scatterplot.outer_bounds = list(self.size) def test_scatter_1d(self): - self.assertEqual(self.scatterplot.origin, 'bottom left') + self.assertEqual(self.scatterplot.origin, "bottom left") self.assertIsNone(self.scatterplot.x_mapper) - self.assertEqual(self.scatterplot.y_mapper, - self.scatterplot.index_mapper) - self.assertIs(self.scatterplot.index_range, - self.scatterplot.index_mapper.range) + self.assertEqual(self.scatterplot.y_mapper, self.scatterplot.index_mapper) + self.assertIs(self.scatterplot.index_range, self.scatterplot.index_mapper.range) gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -41,11 +37,10 @@ def test_scatter_1d(self): self.assertFalse(alltrue(actual == 255)) def test_scatter_1d_horizontal(self): - self.scatterplot.orientation = 'h' + self.scatterplot.orientation = "h" - self.assertEqual(self.scatterplot.origin, 'bottom left') - self.assertEqual(self.scatterplot.x_mapper, - self.scatterplot.index_mapper) + self.assertEqual(self.scatterplot.origin, "bottom left") + self.assertEqual(self.scatterplot.x_mapper, self.scatterplot.index_mapper) self.assertIsNone(self.scatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -54,12 +49,11 @@ def test_scatter_1d_horizontal(self): self.assertFalse(alltrue(actual == 255)) def test_scatter_1d_flipped(self): - self.scatterplot.direction = 'flipped' + self.scatterplot.direction = "flipped" - self.assertEqual(self.scatterplot.origin, 'top left') + self.assertEqual(self.scatterplot.origin, "top left") self.assertIsNone(self.scatterplot.x_mapper) - self.assertEqual(self.scatterplot.y_mapper, - self.scatterplot.index_mapper) + self.assertEqual(self.scatterplot.y_mapper, self.scatterplot.index_mapper) gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -67,12 +61,11 @@ def test_scatter_1d_flipped(self): self.assertFalse(alltrue(actual == 255)) def test_scatter_1d_horizontal_flipped(self): - self.scatterplot.direction = 'flipped' - self.scatterplot.orientation = 'h' + self.scatterplot.direction = "flipped" + self.scatterplot.orientation = "h" - self.assertEqual(self.scatterplot.origin, 'bottom right') - self.assertEqual(self.scatterplot.x_mapper, - self.scatterplot.index_mapper) + self.assertEqual(self.scatterplot.origin, "bottom right") + self.assertEqual(self.scatterplot.x_mapper, self.scatterplot.index_mapper) self.assertIsNone(self.scatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -81,7 +74,7 @@ def test_scatter_1d_horizontal_flipped(self): self.assertFalse(alltrue(actual == 255)) def test_scatter_1d_circle(self): - self.scatterplot.marker = 'circle' + self.scatterplot.marker = "circle" gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) actual = gc.bmp_array[:, :, :] @@ -95,7 +88,7 @@ def test_scatter_1d_custom(self): path.line_to(-5, 5) path.line_to(-5, -5) - self.scatterplot.marker = 'custom' + self.scatterplot.marker = "custom" self.scatterplot.custom_symbol = path gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -104,31 +97,27 @@ def test_scatter_1d_custom(self): def test_scatter_1d_map_data(self): points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), - array([4.5, 0])) + assert_almost_equal(self.scatterplot.map_data(points), array([4.5, 0])) def test_scatter_1d_map_data_horizontal(self): - self.scatterplot.orientation = 'h' + self.scatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), - array([0, 4.5])) + assert_almost_equal(self.scatterplot.map_data(points), array([0, 4.5])) def test_scatter_1d_map_data_flipped(self): - self.scatterplot.direction = 'flipped' + self.scatterplot.direction = "flipped" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), - array([4.5, 9.0])) + assert_almost_equal(self.scatterplot.map_data(points), array([4.5, 9.0])) def test_scatter_1d_map_data_horizontal_flipped(self): - self.scatterplot.direction = 'flipped' - self.scatterplot.orientation = 'h' + self.scatterplot.direction = "flipped" + self.scatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), - array([9.0, 4.5])) + assert_almost_equal(self.scatterplot.map_data(points), array([9.0, 4.5])) def test_scatter_1d_selection(self): # select a single point - self.scatterplot.index.metadata['selections'] = [ + self.scatterplot.index.metadata["selections"] = [ (arange(10) % 2 == 0), ] @@ -139,8 +128,8 @@ def test_scatter_1d_selection(self): def test_scatter_1d_selection_mask_name(self): # select with a mask - self.scatterplot.selection_metadata_name = 'highlight_masks' - self.scatterplot.index.metadata['highlight_masks'] = [ + self.scatterplot.selection_metadata_name = "highlight_masks" + self.scatterplot.index.metadata["highlight_masks"] = [ (arange(10) % 2 == 0), ] @@ -152,7 +141,7 @@ def test_scatter_1d_selection_mask_name(self): def test_scatter_1d_selection_alpha(self): # test with different alpha self.scatterplot.unselected_alpha = 0.4 - self.scatterplot.index.metadata['selections'] = [ + self.scatterplot.index.metadata["selections"] = [ (arange(10) % 2 == 0), ] diff --git a/chaco/tests/test_scatterplot_renderers.py b/chaco/tests/test_scatterplot_renderers.py index cc2e2fe1f..12ddc60a6 100644 --- a/chaco/tests/test_scatterplot_renderers.py +++ b/chaco/tests/test_scatterplot_renderers.py @@ -48,7 +48,7 @@ def test_scatter_custom(self): size = (50, 50) scatterplot = create_scatter_plot( data=[list(range(10)), list(range(10))], - marker='custom', + marker="custom", border_visible=False, ) scatterplot.custom_symbol = path diff --git a/chaco/tests/test_serializable.py b/chaco/tests/test_serializable.py index 3602ef3a9..af17f38e5 100644 --- a/chaco/tests/test_serializable.py +++ b/chaco/tests/test_serializable.py @@ -7,8 +7,8 @@ # the classes to be pickled are in a different file from .serializable_base import Circle, Poly -class SimpleSerializationTestCase(unittest.TestCase): +class SimpleSerializationTestCase(unittest.TestCase): def compare_traits(self, a, b, trait_names=None): "Checks the traits of objects 'a' and 'b' and makes sure they all match." if trait_names is None: @@ -16,12 +16,10 @@ def compare_traits(self, a, b, trait_names=None): for name in trait_names: if name in ("trait_added", "trait_modified"): continue - o1 = getattr(a,name) - o2 = getattr(b,name) + o1 = getattr(a, name) + o2 = getattr(b, name) if isinstance(o1, list) or isinstance(o1, tuple): - raise RuntimeError( - "Warning: Cowardly refusing to do deep compares" - ) + raise RuntimeError("Warning: Cowardly refusing to do deep compares") else: self.assertTrue(o1 == o2) diff --git a/chaco/tests/test_speedups.py b/chaco/tests/test_speedups.py index 1fb5eb8be..76114d421 100644 --- a/chaco/tests/test_speedups.py +++ b/chaco/tests/test_speedups.py @@ -1,10 +1,9 @@ - import unittest from numpy import alltrue, array, ravel, zeros, isinf, linspace -def assert_close(desired,actual): +def assert_close(desired, actual): diff_allowed = 1e-5 diff = abs(ravel(actual) - ravel(desired)) for d in diff: @@ -12,6 +11,7 @@ def assert_close(desired,actual): assert alltrue(d <= diff_allowed) return + class GatherPointsBase(object): # The module to look for the gather_points function in; subclasses @@ -22,8 +22,12 @@ def test_basic(self): index = linspace(0.0, 20.0, 21) value = linspace(0.0, 1.0, 21) points, selection = self.func(index, 4.5, 14.5, value, -1.0, 2.4) - desired = array([[5, 6, 7, 8, 9, 10, 11, 12, 13, 14], - [0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.8]]).T + desired = array( + [ + [5, 6, 7, 8, 9, 10, 11, 12, 13, 14], + [0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.8], + ] + ).T self.assertTrue(selection == None) assert_close(desired, points) @@ -35,18 +39,16 @@ def test_masked(self): value_mask = zeros(11, dtype=bool) value_mask[4:8] = 1 - points, selection = self.func(index, 0, 10, value, 0, 1, - index_mask = index_mask) + points, selection = self.func(index, 0, 10, value, 0, 1, index_mask=index_mask) desired = array([[2, 3, 4, 5], [0.2, 0.3, 0.4, 0.5]]).T assert_close(desired, points) - points, selection = self.func(index, 0, 10, value, 0, 1, - index_mask = index_mask, - value_mask = value_mask) + points, selection = self.func( + index, 0, 10, value, 0, 1, index_mask=index_mask, value_mask=value_mask + ) desired = array([[4, 0.4], [5, 0.5]]) assert_close(desired, points) - def test_selection(self): pass @@ -55,6 +57,5 @@ def test_selection_range(self): def _get_func(self): return self.module.scatterplot_gather_points - func = property(_get_func) - + func = property(_get_func) diff --git a/chaco/tests/test_text_plot_1d.py b/chaco/tests/test_text_plot_1d.py index d42836643..06d768d85 100644 --- a/chaco/tests/test_text_plot_1d.py +++ b/chaco/tests/test_text_plot_1d.py @@ -6,18 +6,28 @@ from traits.testing.unittest_tools import UnittestTools # Chaco imports -from chaco.api import (ArrayDataSource, DataRange1D, LinearMapper, - PlotGraphicsContext) +from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext from chaco.text_plot_1d import TextPlot1D class TextPlot1DTest(UnittestTools, unittest.TestCase): - def setUp(self): self.size = (250, 250) data_source = ArrayDataSource(arange(10)) - text_data = ArrayDataSource(['one', 'two', 'three', 'four', 'five', - 'six', 'seven', 'eight', 'nine', 'ten']) + text_data = ArrayDataSource( + [ + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "ten", + ] + ) index_range = DataRange1D() index_range.add(data_source) index_mapper = LinearMapper(range=index_range) @@ -30,12 +40,10 @@ def setUp(self): self.textplot.outer_bounds = list(self.size) def test_text_1d(self): - self.assertEqual(self.textplot.origin, 'bottom left') + self.assertEqual(self.textplot.origin, "bottom left") self.assertIsNone(self.textplot.x_mapper) - self.assertEqual(self.textplot.y_mapper, - self.textplot.index_mapper) - self.assertIs(self.textplot.index_range, - self.textplot.index_mapper.range) + self.assertEqual(self.textplot.y_mapper, self.textplot.index_mapper) + self.assertIs(self.textplot.index_range, self.textplot.index_mapper.range) gc = PlotGraphicsContext(self.size) gc.render_component(self.textplot) @@ -43,11 +51,10 @@ def test_text_1d(self): self.assertFalse(alltrue(actual == 255)) def test_text_1d_horizontal(self): - self.textplot.orientation = 'h' + self.textplot.orientation = "h" - self.assertEqual(self.textplot.origin, 'bottom left') - self.assertEqual(self.textplot.x_mapper, - self.textplot.index_mapper) + self.assertEqual(self.textplot.origin, "bottom left") + self.assertEqual(self.textplot.x_mapper, self.textplot.index_mapper) self.assertIsNone(self.textplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -56,12 +63,11 @@ def test_text_1d_horizontal(self): self.assertFalse(alltrue(actual == 255)) def test_text_1d_flipped(self): - self.textplot.direction = 'flipped' + self.textplot.direction = "flipped" - self.assertEqual(self.textplot.origin, 'top left') + self.assertEqual(self.textplot.origin, "top left") self.assertIsNone(self.textplot.x_mapper) - self.assertEqual(self.textplot.y_mapper, - self.textplot.index_mapper) + self.assertEqual(self.textplot.y_mapper, self.textplot.index_mapper) gc = PlotGraphicsContext(self.size) gc.render_component(self.textplot) @@ -69,12 +75,11 @@ def test_text_1d_flipped(self): self.assertFalse(alltrue(actual == 255)) def test_text_1d_horizontal_flipped(self): - self.textplot.direction = 'flipped' - self.textplot.orientation = 'h' + self.textplot.direction = "flipped" + self.textplot.orientation = "h" - self.assertEqual(self.textplot.origin, 'bottom right') - self.assertEqual(self.textplot.x_mapper, - self.textplot.index_mapper) + self.assertEqual(self.textplot.origin, "bottom right") + self.assertEqual(self.textplot.x_mapper, self.textplot.index_mapper) self.assertIsNone(self.textplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -91,27 +96,23 @@ def test_text_1d_rotated(self): def test_text_1d_map_data(self): points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.textplot.map_data(points), - array([4.5, 0])) + assert_almost_equal(self.textplot.map_data(points), array([4.5, 0])) def test_text_1d_map_data_horizontal(self): - self.textplot.orientation = 'h' + self.textplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.textplot.map_data(points), - array([0, 4.5])) + assert_almost_equal(self.textplot.map_data(points), array([0, 4.5])) def test_text_1d_map_data_flipped(self): - self.textplot.direction = 'flipped' + self.textplot.direction = "flipped" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.textplot.map_data(points), - array([4.5, 9.0])) + assert_almost_equal(self.textplot.map_data(points), array([4.5, 9.0])) def test_text_1d_map_data_horizontal_flipped(self): - self.textplot.direction = 'flipped' - self.textplot.orientation = 'h' + self.textplot.direction = "flipped" + self.textplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.textplot.map_data(points), - array([9.0, 4.5])) + assert_almost_equal(self.textplot.map_data(points), array([9.0, 4.5])) def test_text_1d_set_index_range(self): new_range = DataRange1D(low=0.42, high=1.42) diff --git a/chaco/tests/test_ticks.py b/chaco/tests/test_ticks.py index f72141d0e..5f3bc1c8b 100644 --- a/chaco/tests/test_ticks.py +++ b/chaco/tests/test_ticks.py @@ -4,14 +4,13 @@ class TestDefaultTickGenerator(unittest.TestCase): - def setUp(self): self.tick_generator = DefaultTickGenerator() def test_default_tick_generator(self): - high = 1. - low = 0. + high = 1.0 + low = 0.0 interval = 0.1 ticks = self.tick_generator.get_ticks( data_low=0, @@ -25,7 +24,6 @@ def test_default_tick_generator(self): class TestMinorTickGenerator(unittest.TestCase): - def setUp(self): self.tick_generator = MinorTickGenerator() @@ -71,14 +69,14 @@ def test_minor_tick_generator_without_interval(self): data_high=1, bounds_low=low, bounds_high=high, - interval='auto', + interval="auto", ) ticksDefault = self.default_tick_generator.get_ticks( data_low=0, data_high=1, bounds_low=low, bounds_high=high, - interval='auto', + interval="auto", ) self.assertGreater(len(ticksMinor), len(ticksDefault)) @@ -91,20 +89,21 @@ def test_default_auto_interval(self): By default, the interval tries to pick eye-friendly intervals so that there are between 2 and 8 tick marks. """ - data_low = 0. + data_low = 0.0 for i in range(30): - data_high = 10. ** (i / 10.) + data_high = 10.0 ** (i / 10.0) interval = auto_interval(data_low=data_low, data_high=data_high) num_ticks = int((data_high - data_low) / interval) self.assertGreaterEqual(num_ticks, 3) self.assertLessEqual(num_ticks, 8) def test_auto_interval_max_ticks(self): - data_low = 0. - data_high = 100. + data_low = 0.0 + data_high = 100.0 for max_ticks in range(4, 11): - interval = auto_interval(data_low=data_low, data_high=data_high, - max_ticks=max_ticks) + interval = auto_interval( + data_low=data_low, data_high=data_high, max_ticks=max_ticks + ) num_ticks = int((data_high - data_low) / interval) self.assertGreaterEqual(num_ticks, 3) self.assertLessEqual(num_ticks, max_ticks) diff --git a/chaco/tests/text_plot_test_case.py b/chaco/tests/text_plot_test_case.py index b05c19880..6ba414c3f 100644 --- a/chaco/tests/text_plot_test_case.py +++ b/chaco/tests/text_plot_test_case.py @@ -3,9 +3,7 @@ from numpy import alltrue, arange, array # Chaco imports -from chaco.api import ( - ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext -) +from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext from chaco.text_plot import TextPlot @@ -37,13 +35,11 @@ def setUp(self): self.text_plot.outer_bounds = list(self.size) def test_text(self): - self.assertEqual(self.text_plot.origin, 'bottom left') + self.assertEqual(self.text_plot.origin, "bottom left") self.assertEqual(self.text_plot.x_mapper, self.text_plot.index_mapper) self.assertEqual(self.text_plot.y_mapper, self.text_plot.value_mapper) - self.assertIs(self.text_plot.index_range, - self.text_plot.index_mapper.range) - self.assertIs(self.text_plot.value_range, - self.text_plot.value_mapper.range) + self.assertIs(self.text_plot.index_range, self.text_plot.index_mapper.range) + self.assertIs(self.text_plot.value_range, self.text_plot.value_mapper.range) gc = PlotGraphicsContext(self.size) gc.render_component(self.text_plot) diff --git a/chaco/tests_with_backend/test_2d_case.py b/chaco/tests_with_backend/test_2d_case.py index 4beee0d96..8977b6dd0 100644 --- a/chaco/tests_with_backend/test_2d_case.py +++ b/chaco/tests_with_backend/test_2d_case.py @@ -14,20 +14,18 @@ class PlotViewer(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor())) + traits_view = View(Item("plot", editor=ComponentEditor())) -@unittest.skipIf( - ETSConfig.toolkit=='null', "Skip on 'null' toolkit") +@unittest.skipIf(ETSConfig.toolkit == "null", "Skip on 'null' toolkit") class Test2DCase(unittest.TestCase): - def test_bounds_2d_case(self): # test for bug: contour and image plots should support the case where # xbounds and ybounds are 2d arrays resulting from meshgrids - xs = np.linspace(-10,10,200) - ys = np.linspace(-10,10,400) - x, y = np.meshgrid(xs,ys) + xs = np.linspace(-10, 10, 200) + ys = np.linspace(-10, 10, 400) + x, y = np.meshgrid(xs, ys) z = x + y plotdata = ArrayPlotData() @@ -68,33 +66,33 @@ def test_process_2d_bounds_cell_plot(self): # bounds is a 1D array: the first and last elements are used to create # equally spaced intervals. Bounds must be of one element larger than the # corresponding axis in array_data, or it will raise a Value error - bounds = np.zeros((height+1, )) + bounds = np.zeros((height + 1,)) bounds[0], bounds[-1] = 0.2, 21.3 ys = plot._process_2d_bounds(bounds, array_data, 0, cell_plot=True) self.assertEqual(ys.shape[0], height + 1) self.assertEqual(ys[0], bounds[0]) self.assertEqual(ys[-1], bounds[-1]) with assert_raises(ValueError): - bounds = np.zeros((width // 2, )) + bounds = np.zeros((width // 2,)) plot._process_2d_bounds(bounds, array_data, 0, cell_plot=True) # bounds is a 2D array: the first and last elements along the appropriate # axis are used to create equally spaced intervals. # The size of the bounds must be the same as the data array, or this # sill raise a ValueError - xbounds, ybounds = np.meshgrid(np.arange(width+1), np.arange(height+1)) + xbounds, ybounds = np.meshgrid(np.arange(width + 1), np.arange(height + 1)) xs = plot._process_2d_bounds(xbounds, array_data, 1, cell_plot=True) self.assertEqual(xs.shape[0], width + 1) - self.assertEqual(xs[0], xbounds[0,0]) - self.assertEqual(xs[-1], xbounds[0,-1]) + self.assertEqual(xs[0], xbounds[0, 0]) + self.assertEqual(xs[-1], xbounds[0, -1]) with assert_raises(ValueError): plot._process_2d_bounds(xbounds[:, :5], array_data, 1, cell_plot=True) ys = plot._process_2d_bounds(ybounds, array_data, 0, cell_plot=True) self.assertEqual(ys.shape[0], height + 1) - self.assertEqual(ys[0], ybounds[0,0]) - self.assertEqual(ys[-1], ybounds[-1,0]) + self.assertEqual(ys[0], ybounds[0, 0]) + self.assertEqual(ys[-1], ybounds[-1, 0]) with assert_raises(ValueError): plot._process_2d_bounds(ybounds[:5, :], array_data, 0, cell_plot=True) @@ -125,14 +123,14 @@ def test_process_2d_bounds_vertex_data(self): # bounds is a 1D array: the first and last elements are used to create # equally spaced intervals. Bounds must be of one element larger than the # corresponding axis in array_data, or it will raise a Value error - bounds = np.zeros((height, )) + bounds = np.zeros((height,)) bounds[0], bounds[-1] = 0.2, 21.3 ys = plot._process_2d_bounds(bounds, array_data, 0, cell_plot=False) self.assertEqual(ys.shape[0], height) self.assertEqual(ys[0], bounds[0]) self.assertEqual(ys[-1], bounds[-1]) with assert_raises(ValueError): - bounds = np.zeros((width // 2, )) + bounds = np.zeros((width // 2,)) plot._process_2d_bounds(bounds, array_data, 0, cell_plot=False) # bounds is a 2D array: the first and last elements along the appropriate @@ -143,14 +141,14 @@ def test_process_2d_bounds_vertex_data(self): xs = plot._process_2d_bounds(xbounds, array_data, 1, cell_plot=False) self.assertEqual(xs.shape[0], width) - self.assertEqual(xs[0], xbounds[0,0]) - self.assertEqual(xs[-1], xbounds[0,-1]) + self.assertEqual(xs[0], xbounds[0, 0]) + self.assertEqual(xs[-1], xbounds[0, -1]) with assert_raises(ValueError): plot._process_2d_bounds(xbounds[:, :5], array_data, 1, cell_plot=False) ys = plot._process_2d_bounds(ybounds, array_data, 0, cell_plot=False) self.assertEqual(ys.shape[0], height) - self.assertEqual(ys[0], ybounds[0,0]) - self.assertEqual(ys[-1], ybounds[-1,0]) + self.assertEqual(ys[0], ybounds[0, 0]) + self.assertEqual(ys[-1], ybounds[-1, 0]) with assert_raises(ValueError): plot._process_2d_bounds(ybounds[:5, :], array_data, 0, cell_plot=False) diff --git a/chaco/tests_with_backend/test_highlight_tool.py b/chaco/tests_with_backend/test_highlight_tool.py index 3a40f4098..8de1c8c5f 100644 --- a/chaco/tests_with_backend/test_highlight_tool.py +++ b/chaco/tests_with_backend/test_highlight_tool.py @@ -13,17 +13,15 @@ class PlotViewer(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor())) + traits_view = View(Item("plot", editor=ComponentEditor())) class MockEvent(HasTraits): pass -@unittest.skipIf( - ETSConfig.toolkit=='null', "Skip on 'null' toolkit") +@unittest.skipIf(ETSConfig.toolkit == "null", "Skip on 'null' toolkit") class TestHighlightTool(unittest.TestCase): - def test_highlight_on_log_plot(self): # test for bug: the highlight tool raises an exception when used on # a loglog plot @@ -32,17 +30,17 @@ def test_highlight_on_log_plot(self): plotdata = ArrayPlotData() plotdata.set_data("x", x) - plotdata.set_data("y", x*x) + plotdata.set_data("y", x * x) plot = Plot(plotdata) - plot.plot(("x", "y"), index_scale='log', value_scale='log') + plot.plot(("x", "y"), index_scale="log", value_scale="log") # necessary for the machinery involved in _find_curve - plot.datasources["x"].sort_order = 'ascending' - plot.datasources["y"].sort_order = 'ascending' + plot.datasources["x"].sort_order = "ascending" + plot.datasources["y"].sort_order = "ascending" # add the highlight tool - htool = HighlightTool(plot, threshold=20.) + htool = HighlightTool(plot, threshold=20.0) plot.tools.append(htool) # we create a view of the plot so that the screen bounds are set @@ -50,5 +48,5 @@ def test_highlight_on_log_plot(self): pv.edit_traits() # this should not raise an exception - event = MockEvent(x=170., y=60.) - htool._find_curve(plot.plots['plot0'], event) + event = MockEvent(x=170.0, y=60.0) + htool._find_curve(plot.plots["plot0"], event) diff --git a/chaco/text_box_overlay.py b/chaco/text_box_overlay.py index b849293f9..5d5bffe21 100644 --- a/chaco/text_box_overlay.py +++ b/chaco/text_box_overlay.py @@ -13,8 +13,7 @@ class TextBoxOverlay(AbstractOverlay): - """ Draws a box with text in it. - """ + """Draws a box with text in it.""" #### Configuration traits ################################################# @@ -66,7 +65,7 @@ class TextBoxOverlay(AbstractOverlay): #### Public 'AbstractOverlay' interface ################################### def overlay(self, component, gc, view_bounds=None, mode="normal"): - """ Draws the box overlaid on another component. + """Draws the box overlaid on another component. Overrides AbstractOverlay. """ @@ -77,9 +76,14 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): # draw the label on a transparent box. This allows us to draw # different shapes and put the text inside it without the label # filling a rectangle on top of it - label = Label(text=self.text, font=self.font, bgcolor="transparent", - color=self.text_color, max_width=self.max_text_width, - margin=5) + label = Label( + text=self.text, + font=self.font, + bgcolor="transparent", + color=self.text_color, + max_width=self.max_text_width, + margin=5, + ) width, height = label.get_width_height(gc) valign, halign = self.align @@ -107,10 +111,12 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): x = component.x + self.padding # attempt to get the box entirely within the component - x_min, y_min, x_max, y_max = (component.x, - component.y, - component.x + component.width, - component.y + component.height) + x_min, y_min, x_max, y_max = ( + component.x, + component.y, + component.x + component.width, + component.y + component.height, + ) if x + width > x_max: x = max(x_min, x_max - width) if y + height > y_max: @@ -141,19 +147,16 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): end_radius = 8.0 gc.begin_path() gc.move_to(x + end_radius, y) - gc.arc_to(x + width, y, - x + width, - y + end_radius, end_radius) - gc.arc_to(x + width, - y + height, - x + width - end_radius, - y + height, end_radius) - gc.arc_to(x, y + height, - x, y, - end_radius) - gc.arc_to(x, y, - x + width + end_radius, - y, end_radius) + gc.arc_to(x + width, y, x + width, y + end_radius, end_radius) + gc.arc_to( + x + width, + y + height, + x + width - end_radius, + y + height, + end_radius, + ) + gc.arc_to(x, y + height, x, y, end_radius) + gc.arc_to(x, y, x + width + end_radius, y, end_radius) gc.draw_path() label.draw(gc) diff --git a/chaco/text_plot.py b/chaco/text_plot.py index b40a95fca..6aae72642 100644 --- a/chaco/text_plot.py +++ b/chaco/text_plot.py @@ -4,15 +4,12 @@ """ - from numpy import array, column_stack, empty, isfinite # Enthought library imports from enable.api import black_color_trait from kiva.trait_defs.kiva_font_trait import KivaFont -from traits.api import ( - Bool, Enum, Float, Int, Instance, List, Tuple, observe -) +from traits.api import Bool, Enum, Float, Int, Instance, List, Tuple, observe # local imports from .array_data_source import ArrayDataSource @@ -27,7 +24,7 @@ class TextPlot(BaseXYPlot): text = Instance(ArrayDataSource) #: The font of the tick labels. - text_font = KivaFont('modern 10') + text_font = KivaFont("modern 10") #: The color of the tick labels. text_color = black_color_trait @@ -47,9 +44,9 @@ class TextPlot(BaseXYPlot): #: offset of text relative to non-index direction in pixels text_offset = Tuple(Float, Float) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: flag for whether the cache of Label instances is valid _label_cache_valid = Bool(False) @@ -60,9 +57,9 @@ class TextPlot(BaseXYPlot): #: cache of bounding boxes of labels _label_box_cache = List - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _compute_labels(self, gc): """Generate the Label instances for the plot. """ @@ -72,17 +69,17 @@ def _compute_labels(self, gc): font=self.text_font, color=self.text_color, rotate_angle=self.text_rotate_angle, - margin=self.text_margin - ) for text in self.text.get_data() + margin=self.text_margin, + ) + for text in self.text.get_data() ] self._label_box_cache = [ - array(label.get_bounding_box(gc), float) - for label in self._label_cache + array(label.get_bounding_box(gc), float) for label in self._label_cache ] self._label_cache_valid = True def _gather_points(self): - """ Abstract method to collect data points that are within the range of + """Abstract method to collect data points that are within the range of the plot, and cache them. """ if self._cache_valid: @@ -103,9 +100,7 @@ def _gather_points(self): index_range_mask = self.index_mapper.range.mask_data(index) value_range_mask = self.value_mapper.range.mask_data(value) - nan_mask = ( - isfinite(index) & index_mask & isfinite(value) & value_mask - ) + nan_mask = isfinite(index) & index_mask & isfinite(value) & value_mask point_mask = nan_mask & index_range_mask & value_range_mask if not self._cache_valid: @@ -128,10 +123,10 @@ def _render(self, gc, pts): ] boxes = [ label - for label, mask in - zip(self._label_box_cache, self._cached_point_mask) if mask + for label, mask in zip(self._label_box_cache, self._cached_point_mask) + if mask ] - offset = empty((2, ), float) + offset = empty((2,), float) with gc: gc.clip_to_rect(self.x, self.y, self.width, self.height) @@ -155,9 +150,9 @@ def _render(self, gc, pts): label.draw(gc) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait events - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @observe("index.data_changed") def _invalidate(self, event): diff --git a/chaco/text_plot_1d.py b/chaco/text_plot_1d.py index 9f8fe784a..bd4c5ffc2 100644 --- a/chaco/text_plot_1d.py +++ b/chaco/text_plot_1d.py @@ -4,8 +4,6 @@ """ - - from numpy import array, empty # Enthought library imports @@ -26,7 +24,7 @@ class TextPlot1D(Base1DPlot): value = Instance(ArrayDataSource) #: The font of the tick labels. - text_font = KivaFont('modern 10') + text_font = KivaFont("modern 10") #: The color of the tick labels. text_color = black_color_trait @@ -38,7 +36,7 @@ class TextPlot1D(Base1DPlot): text_margin = Int(2) #: the anchor point of the text (corner is better for 45 degree rotation) - text_alignment = Enum('edge', 'corner') + text_alignment = Enum("edge", "corner") #: alignment of text relative to non-index direction alignment = Enum("center", "left", "right", "top", "bottom") @@ -50,9 +48,9 @@ class TextPlot1D(Base1DPlot): #: offset of text relative to non-index direction in pixels text_offset = Float - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: private trait holding position of text relative to non-index direction _text_position = Float @@ -66,9 +64,9 @@ class TextPlot1D(Base1DPlot): #: cache of bounding boxes of labels _label_box_cache = List - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _compute_labels(self, gc): """Generate the Label instances for the plot. """ @@ -78,10 +76,13 @@ def _compute_labels(self, gc): font=self.text_font, color=self.text_color, rotate_angle=self.text_rotate_angle, - margin=self.text_margin - ) for text in self.value.get_data()] - self._label_box_cache = [array(label.get_bounding_box(gc), float) - for label in self._label_cache] + margin=self.text_margin, + ) + for text in self.value.get_data() + ] + self._label_box_cache = [ + array(label.get_bounding_box(gc), float) for label in self._label_cache + ] self._label_cache_valid = True def _draw_plot(self, gc, view_bounds=None, mode="normal"): @@ -95,7 +96,7 @@ def _draw_plot(self, gc, view_bounds=None, mode="normal"): coord = self._compute_screen_coord() pts = empty(shape=(len(coord), 2)) - if self.orientation == 'v': + if self.orientation == "v": pts[:, 1] = coord pts[:, 0] = self._text_position else: @@ -118,19 +119,19 @@ def _get_index_text_position(self, gc, pt, label): x, y = pt width, height = label.get_bounding_box(gc) - if self.orientation == 'v': + if self.orientation == "v": position, width = y, height else: position = x - if self.index_alignment == 'center': - position -= width/2.0 - elif self.index_alignment in ['left', 'bottom']: + if self.index_alignment == "center": + position -= width / 2.0 + elif self.index_alignment in ["left", "bottom"]: position -= width # If alignment is 'right' or 'top' we do nothing as that already # matches the default behavior - if self.orientation == 'v': + if self.orientation == "v": return x, position else: return position, y @@ -140,29 +141,29 @@ def _get_text_position(self): x, y = self.position w, h = self.bounds - if self.orientation == 'v': + if self.orientation == "v": y, h = x, w - if self.alignment == 'center': - position = y + h/2.0 - elif self.alignment in ['left', 'bottom']: + if self.alignment == "center": + position = y + h / 2.0 + elif self.alignment in ["left", "bottom"]: position = y - elif self.alignment in ['right', 'top']: + elif self.alignment in ["right", "top"]: position = y + h position += self.text_offset return position - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __text_position_default(self): return self._get_text_position() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait events - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @observe("index.data_changed") def _invalidate(self, event): diff --git a/chaco/ticks.py b/chaco/ticks.py index 2ef9aac90..021bbcf36 100644 --- a/chaco/ticks.py +++ b/chaco/ticks.py @@ -1,4 +1,4 @@ -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # # # Written by: David C. Morrill (based on similar routines written by Eric Jones) @@ -7,26 +7,50 @@ # # (c) Copyright 2002-7 by Enthought, Inc. # -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- """ Tick generator classes and helper functions for calculating axis tick-related values (i.e., bounds and intervals). """ # Major library imports -from numpy import arange, argsort, array, ceil, concatenate, equal, finfo, \ - float64, floor, linspace, log10, minimum, ndarray, newaxis, \ - putmask, shape +from numpy import ( + arange, + argsort, + array, + ceil, + concatenate, + equal, + finfo, + float64, + floor, + linspace, + log10, + minimum, + ndarray, + newaxis, + putmask, + shape, +) # Enthought library imports from traits.api import HasTraits, Any + class AbstractTickGenerator(HasTraits): - """ Abstract class for tick generators. - """ - def get_ticks(self, data_low, data_high, bounds_low, bounds_high, interval, - use_endpoints=False, scale='linear'): - """ Returns a list of ticks points in data space. + """Abstract class for tick generators.""" + + def get_ticks( + self, + data_low, + data_high, + bounds_low, + bounds_high, + interval, + use_endpoints=False, + scale="linear", + ): + """Returns a list of ticks points in data space. Parameters ---------- @@ -72,121 +96,171 @@ def get_ticks(self, data_low, data_high, bounds_low, bounds_high, interval, class DefaultTickGenerator(AbstractTickGenerator): - """ An implementation of AbstractTickGenerator that simply uses the + """An implementation of AbstractTickGenerator that simply uses the auto_ticks() and log_auto_ticks() functions. """ - def get_ticks(self, data_low, data_high, bounds_low, - bounds_high, interval, use_endpoints=False, - scale='linear'): - if scale == 'linear': - return array(auto_ticks(data_low, data_high, bounds_low, bounds_high, - interval, use_endpoints=False), float64) - elif scale == 'log': - return array(log_auto_ticks(data_low, data_high, bounds_low, bounds_high, - interval, use_endpoints=False), float64) + + def get_ticks( + self, + data_low, + data_high, + bounds_low, + bounds_high, + interval, + use_endpoints=False, + scale="linear", + ): + if scale == "linear": + return array( + auto_ticks( + data_low, + data_high, + bounds_low, + bounds_high, + interval, + use_endpoints=False, + ), + float64, + ) + elif scale == "log": + return array( + log_auto_ticks( + data_low, + data_high, + bounds_low, + bounds_high, + interval, + use_endpoints=False, + ), + float64, + ) + class ShowAllTickGenerator(AbstractTickGenerator): - """ Uses the abstract interface, but returns all "positions" instead - of decimating the ticks. + """Uses the abstract interface, but returns all "positions" instead + of decimating the ticks. - You must provide a sequence of values as a *positions* keyword argument - to the constructor. + You must provide a sequence of values as a *positions* keyword argument + to the constructor. """ + # A sequence of positions for ticks. positions = Any - def get_ticks(self, data_low, data_high, bounds_low, bounds_high, interval, - use_endpoints=False, scale='linear'): - """ Returns an array based on **positions**. - """ + def get_ticks( + self, + data_low, + data_high, + bounds_low, + bounds_high, + interval, + use_endpoints=False, + scale="linear", + ): + """Returns an array based on **positions**.""" # ignore all the high, low, etc. data and just return every position return array(self.positions, float64) + class MinorTickGenerator(DefaultTickGenerator): - """ An implementation of AbstractTickGenerator that extends DefaultTickGenerator, - but sets the tick interval to a smaller length. + """An implementation of AbstractTickGenerator that extends DefaultTickGenerator, + but sets the tick interval to a smaller length. """ - def get_ticks(self, data_low, data_high, bounds_low, bounds_high, - interval, use_endpoints=False, scale='linear'): - if interval == 'auto': + + def get_ticks( + self, + data_low, + data_high, + bounds_low, + bounds_high, + interval, + use_endpoints=False, + scale="linear", + ): + if interval == "auto": # for the default interval, generate a smaller tick interval interval = auto_interval(0, auto_interval(data_low, data_high), max_ticks=5) - - return super(MinorTickGenerator, self).get_ticks(data_low, data_high, - bounds_low, bounds_high, interval, use_endpoints, scale) -#------------------------------------------------------------------------------- + return super(MinorTickGenerator, self).get_ticks( + data_low, data_high, bounds_low, bounds_high, interval, use_endpoints, scale + ) + + +# ------------------------------------------------------------------------------- # Code imported from plt/plot_utility.py: -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- -def auto_ticks ( data_low, data_high, bound_low, bound_high, tick_interval, - use_endpoints = True): - """ Finds locations for axis tick marks. - Calculates the locations for tick marks on an axis. The *bound_low*, - *bound_high*, and *tick_interval* parameters specify how the axis end - points and tick interval are calculated. +def auto_ticks( + data_low, data_high, bound_low, bound_high, tick_interval, use_endpoints=True +): + """Finds locations for axis tick marks. - Parameters - ---------- + Calculates the locations for tick marks on an axis. The *bound_low*, + *bound_high*, and *tick_interval* parameters specify how the axis end + points and tick interval are calculated. - data_low, data_high : number - The minimum and maximum values of the data along this axis. - If any of the bound settings are 'auto' or 'fit', the axis - traits are calculated automatically from these values. - bound_low, bound_high : 'auto', 'fit', or a number. - The lower and upper bounds of the axis. If the value is a number, - that value is used for the corresponding end point. If the value is - 'auto', then the end point is calculated automatically. If the - value is 'fit', then the axis bound is set to the corresponding - *data_low* or *data_high* value. - tick_interval : can be 'auto' or a number - If the value is a positive number, it specifies the length - of the tick interval; a negative integer specifies the - number of tick intervals; 'auto' specifies that the number and - length of the tick intervals are automatically calculated, based - on the range of the axis. - use_endpoints : Boolean - If True, the lower and upper bounds of the data are used as the - lower and upper end points of the axis. If False, the end points - might not fall exactly on the bounds. + Parameters + ---------- - Returns - ------- - An array of tick mark locations. The first and last tick entries are the - axis end points. + data_low, data_high : number + The minimum and maximum values of the data along this axis. + If any of the bound settings are 'auto' or 'fit', the axis + traits are calculated automatically from these values. + bound_low, bound_high : 'auto', 'fit', or a number. + The lower and upper bounds of the axis. If the value is a number, + that value is used for the corresponding end point. If the value is + 'auto', then the end point is calculated automatically. If the + value is 'fit', then the axis bound is set to the corresponding + *data_low* or *data_high* value. + tick_interval : can be 'auto' or a number + If the value is a positive number, it specifies the length + of the tick interval; a negative integer specifies the + number of tick intervals; 'auto' specifies that the number and + length of the tick intervals are automatically calculated, based + on the range of the axis. + use_endpoints : Boolean + If True, the lower and upper bounds of the data are used as the + lower and upper end points of the axis. If False, the end points + might not fall exactly on the bounds. + + Returns + ------- + An array of tick mark locations. The first and last tick entries are the + axis end points. """ - is_auto_low = (bound_low == 'auto') - is_auto_high = (bound_high == 'auto') + is_auto_low = bound_low == "auto" + is_auto_high = bound_high == "auto" if isinstance(bound_low, str): lower = data_low else: - lower = float( bound_low ) + lower = float(bound_low) if isinstance(bound_high, str): upper = data_high else: - upper = float( bound_high ) + upper = float(bound_high) - if (tick_interval == 'auto') or (tick_interval == 0.0): - rng = abs( upper - lower ) + if (tick_interval == "auto") or (tick_interval == 0.0): + rng = abs(upper - lower) if rng == 0.0: tick_interval = 0.5 - lower = data_low - 0.5 - upper = data_high + 0.5 + lower = data_low - 0.5 + upper = data_high + 0.5 else: - tick_interval = auto_interval( lower, upper ) + tick_interval = auto_interval(lower, upper) elif tick_interval < 0: - intervals = -tick_interval - tick_interval = tick_intervals( lower, upper, intervals ) + intervals = -tick_interval + tick_interval = tick_intervals(lower, upper, intervals) if is_auto_low and is_auto_high: is_auto_low = is_auto_high = False - lower = tick_interval * floor( lower / tick_interval ) - while ((abs( lower ) >= tick_interval) and - ((lower + tick_interval * (intervals - 1)) >= upper)): + lower = tick_interval * floor(lower / tick_interval) + while (abs(lower) >= tick_interval) and ( + (lower + tick_interval * (intervals - 1)) >= upper + ): lower -= tick_interval upper = lower + tick_interval * intervals @@ -194,16 +268,17 @@ def auto_ticks ( data_low, data_high, bound_low, bound_high, tick_interval, # calculate them based on the newly chosen tick_interval: if is_auto_low or is_auto_high: delta = 0.01 * tick_interval * (data_low == data_high) - auto_lower, auto_upper = auto_bounds( data_low - delta, - data_high + delta, tick_interval ) + auto_lower, auto_upper = auto_bounds( + data_low - delta, data_high + delta, tick_interval + ) if is_auto_low: lower = auto_lower if is_auto_high: upper = auto_upper # Compute the range of ticks values: - start = floor( lower / tick_interval ) * tick_interval - end = floor( upper / tick_interval ) * tick_interval + start = floor(lower / tick_interval) * tick_interval + end = floor(upper / tick_interval) * tick_interval # If we return the same value for the upper bound and lower bound, the # layout code will not be able to lay out the tick marks (divide by zero). if start == end: @@ -212,10 +287,10 @@ def auto_ticks ( data_low, data_high, bound_low, bound_high, tick_interval, if upper > end: end += tick_interval - ticks = arange( start, end + (tick_interval / 2.0), tick_interval ) + ticks = arange(start, end + (tick_interval / 2.0), tick_interval) - if len( ticks ) < 2: - ticks = array( ( ( lower - lower * 1.0e-7 ), lower ) ) + if len(ticks) < 2: + ticks = array(((lower - lower * 1.0e-7), lower)) if (not is_auto_low) and use_endpoints: ticks[0] = lower if (not is_auto_high) and use_endpoints: @@ -224,9 +299,10 @@ def auto_ticks ( data_low, data_high, bound_low, bound_high, tick_interval, return [tick for tick in ticks if tick >= bound_low and tick <= bound_high] -#-------------------------------------------------------------------------------- +# -------------------------------------------------------------------------------- # Compute the best tick interval for a specified data range: -#-------------------------------------------------------------------------------- +# -------------------------------------------------------------------------------- + def heckbert_interval(data_low, data_high, numticks=8): """ @@ -234,10 +310,10 @@ def heckbert_interval(data_low, data_high, numticks=8): number of ticks. From Paul Heckbert's algorithm in Graphics Gems. """ range = _nice(data_high - data_low) - d = _nice(range / (numticks-1), round=True) + d = _nice(range / (numticks - 1), round=True) graphmin = floor(data_low / d) * d graphmax = ceil(data_high / d) * d - #nfrac = max(-floor(log10(d)), 0) + # nfrac = max(-floor(log10(d)), 0) return graphmin, graphmax, d @@ -251,7 +327,7 @@ def _nice(x, round=False): elif f < 3.0: nf = 2.0 elif f < 7.0: - nf = 5.0; + nf = 5.0 else: nf = 10.0 else: @@ -266,43 +342,43 @@ def _nice(x, round=False): return nf * pow(10, expv) -def auto_interval ( data_low, data_high, max_ticks=9 ): - """ Calculates the tick interval for a range. +def auto_interval(data_low, data_high, max_ticks=9): + """Calculates the tick interval for a range. - The boundaries for the data to be plotted on the axis are:: + The boundaries for the data to be plotted on the axis are:: - data_bounds = (data_low,data_high) + data_bounds = (data_low,data_high) - The function chooses the number of tick marks, which can be between - 3 and max_ticks marks (including end points), and chooses tick intervals at - 1, 2, 2.5, 5, 10, 20, ... + The function chooses the number of tick marks, which can be between + 3 and max_ticks marks (including end points), and chooses tick intervals at + 1, 2, 2.5, 5, 10, 20, ... - Returns - ------- - interval : float - tick mark interval for axis + Returns + ------- + interval : float + tick mark interval for axis """ - range = float( data_high ) - float( data_low ) + range = float(data_high) - float(data_low) # We'll choose from between 2 and 8 tick marks. # Preference is given to more ticks: # Note reverse order and see kludge below... - divisions = arange( max_ticks-1, 2.0, -1.0 ) # for max_ticks=9, ( 7, 6, ..., 3 ) + divisions = arange(max_ticks - 1, 2.0, -1.0) # for max_ticks=9, ( 7, 6, ..., 3 ) # Calculate the intervals for the divisions: candidate_intervals = range / divisions # Get magnitudes and mantissas for each candidate: - magnitudes = 10.0 ** floor( log10( candidate_intervals ) ) - mantissas = candidate_intervals / magnitudes + magnitudes = 10.0 ** floor(log10(candidate_intervals)) + mantissas = candidate_intervals / magnitudes # List of "pleasing" intervals between ticks on graph. # Only the first magnitude are listed, higher mags others are inferred: - magic_intervals = array( ( 1.0, 2.0, 2.5, 5.0, 10.0 ) ) + magic_intervals = array((1.0, 2.0, 2.5, 5.0, 10.0)) # Calculate the absolute differences between the candidates # (with magnitude removed) and the magic intervals: - differences = abs( magic_intervals[:,newaxis] - mantissas ) + differences = abs(magic_intervals[:, newaxis] - mantissas) # Find the division and magic interval combo that produce the # smallest differences: @@ -310,35 +386,37 @@ def auto_interval ( data_low, data_high, max_ticks=9 ): # KLUDGE: 'argsort' doesn't preserve the order of equal values, # so we subtract a small, index dependent amount from each difference # to force correct ordering. - sh = shape( differences ) - small = 2.2e-16 * arange( sh[1] ) * arange( sh[0] )[:,newaxis] - small = small[::-1,::-1] #reverse the order + sh = shape(differences) + small = 2.2e-16 * arange(sh[1]) * arange(sh[0])[:, newaxis] + small = small[::-1, ::-1] # reverse the order differences = differences - small # ? Numeric should allow keyword "axis" ? comment out for now - #best_mantissa = minimum.reduce(differences,axis=0) - #best_magic = minimum.reduce(differences,axis=-1) - best_mantissa = minimum.reduce( differences, 0 ) - best_magic = minimum.reduce( differences, -1 ) - magic_index = argsort( best_magic )[0] - mantissa_index = argsort( best_mantissa )[0] + # best_mantissa = minimum.reduce(differences,axis=0) + # best_magic = minimum.reduce(differences,axis=-1) + best_mantissa = minimum.reduce(differences, 0) + best_magic = minimum.reduce(differences, -1) + magic_index = argsort(best_magic)[0] + mantissa_index = argsort(best_mantissa)[0] # The best interval is the magic_interval multiplied by the magnitude # of the best mantissa: - interval = magic_intervals[ magic_index ] - magnitude = magnitudes[ mantissa_index ] - result = interval * magnitude + interval = magic_intervals[magic_index] + magnitude = magnitudes[mantissa_index] + result = interval * magnitude if result == 0.0: result = finfo(float).eps return result -#-------------------------------------------------------------------------------- + +# -------------------------------------------------------------------------------- # Compute the best tick interval length to achieve a specified number of tick # intervals: -#-------------------------------------------------------------------------------- +# -------------------------------------------------------------------------------- + -def tick_intervals ( data_low, data_high, intervals ): - """ Computes the best tick interval length to achieve a specified number of +def tick_intervals(data_low, data_high, intervals): + """Computes the best tick interval length to achieve a specified number of tick intervals. Parameters @@ -354,70 +432,72 @@ def tick_intervals ( data_low, data_high, intervals ): ------- Returns a float indicating the tick interval length. """ - range = float( data_high - data_low ) + range = float(data_high - data_low) if range == 0.0: range = 1.0 - interval = range / intervals - factor = 10.0 ** floor( log10( interval ) ) + interval = range / intervals + factor = 10.0 ** floor(log10(interval)) interval /= factor if interval < 2.0: interval = 2.0 - index = 0 + index = 0 elif interval < 2.5: interval = 2.5 - index = 1 + index = 1 elif interval < 5.0: interval = 5.0 - index = 2 + index = 2 else: interval = 10.0 - index = 3 + index = 3 while True: result = interval * factor - if ((floor( data_low / result ) * result) + (intervals * result) >= - data_high): + if (floor(data_low / result) * result) + (intervals * result) >= data_high: return result - index = (index + 1) % 4 - interval *= ( 2.0, 1.25, 2.0, 2.0 )[ index ] + index = (index + 1) % 4 + interval *= (2.0, 1.25, 2.0, 2.0)[index] - -def log_auto_ticks(data_low, data_high, - bound_low, bound_high, - tick_interval, use_endpoints = True): +def log_auto_ticks( + data_low, data_high, bound_low, bound_high, tick_interval, use_endpoints=True +): """Like auto_ticks(), but for log scales.""" tick_goal = 15 magic_numbers = [1, 2, 5] explicit_ticks = False - if data_low<=0.0: + if data_low <= 0.0: return [] - if tick_interval != 'auto': + if tick_interval != "auto": if tick_interval < 0: tick_goal = -tick_interval else: magic_numbers = [tick_interval] explicit_ticks = True - if data_low>data_high: + if data_low > data_high: data_low, data_high = data_high, data_low log_low = log10(data_low) log_high = log10(data_high) - log_interval = log_high-log_low + log_interval = log_high - log_low if log_interval < 1.0: # If less than a factor of 10 separates the data, just use the normal # linear approach - return auto_ticks(data_low, data_high, - bound_low, bound_high, - tick_interval, - use_endpoints = False) - - elif log_interval < (tick_goal+1)/2 or explicit_ticks: + return auto_ticks( + data_low, + data_high, + bound_low, + bound_high, + tick_interval, + use_endpoints=False, + ) + + elif log_interval < (tick_goal + 1) / 2 or explicit_ticks: # If there's enough space, try to put lines at the magic number multipliers # inside each power of ten @@ -425,46 +505,52 @@ def log_auto_ticks(data_low, data_high, for interval in magic_numbers: ticklist = [] for exp in range(int(floor(log_low)), int(ceil(log_high))): - for multiplier in linspace(interval, 10.0, round(10.0/interval), - endpoint=1): - tick = 10**exp*multiplier + for multiplier in linspace( + interval, 10.0, round(10.0 / interval), endpoint=1 + ): + tick = 10 ** exp * multiplier if tick >= data_low and tick <= data_high: ticklist.append(tick) - if len(ticklist) self.max_zoom_out_factor or \ - (orig_bounds / new_bounds) > self.max_zoom_in_factor: + if (new_bounds / orig_bounds) > self.max_zoom_out_factor or ( + orig_bounds / new_bounds + ) > self.max_zoom_in_factor: return True return False - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Utility methods for computing axes, coordinates, etc. - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_mapper(self): - """ Returns the mapper for the component associated with this tool. + """Returns the mapper for the component associated with this tool. The zoom tool really only cares about this, so subclasses can easily customize SimpleZoom to work with all sorts of components just by @@ -67,19 +72,18 @@ def _get_mapper(self): else: return None - def _get_axis_coord(self, event, axis="index"): - """ Returns the coordinate of the event along the axis of interest + """Returns the coordinate of the event along the axis of interest to the tool (or along the orthogonal axis, if axis="value"). """ event_pos = (event.x, event.y) if axis == "index": - return event_pos[ self._determine_axis() ] + return event_pos[self._determine_axis()] else: - return event_pos[ 1 - self._determine_axis() ] + return event_pos[1 - self._determine_axis()] def _determine_axis(self): - """ Determines whether the index of the coordinate along the axis of + """Determines whether the index of the coordinate along the axis of interest is the first or second element of an (x,y) coordinate tuple. """ if self.axis == "index": @@ -87,20 +91,22 @@ def _determine_axis(self): return 0 else: return 1 - else: # self.axis == "value" + else: # self.axis == "value" if self.component.orientation == "h": return 1 else: return 0 def _map_coordinate_box(self, start, end): - """ Given start and end points in screen space, returns corresponding + """Given start and end points in screen space, returns corresponding low and high points in data space. """ - low = [0,0] - high = [0,0] - for axis_index, mapper in [(0, self.component.x_mapper), \ - (1, self.component.y_mapper)]: + low = [0, 0] + high = [0, 0] + for axis_index, mapper in [ + (0, self.component.x_mapper), + (1, self.component.y_mapper), + ]: low_val = mapper.map_data(start[axis_index]) high_val = mapper.map_data(end[axis_index]) @@ -109,4 +115,3 @@ def _map_coordinate_box(self, start, end): low[axis_index] = low_val high[axis_index] = high_val return low, high - diff --git a/chaco/tools/better_selecting_zoom.py b/chaco/tools/better_selecting_zoom.py index 9ffba0356..813fb6fe9 100644 --- a/chaco/tools/better_selecting_zoom.py +++ b/chaco/tools/better_selecting_zoom.py @@ -1,5 +1,3 @@ - - import numpy from chaco.abstract_overlay import AbstractOverlay @@ -10,9 +8,10 @@ from .better_zoom import BetterZoom from .tool_states import SelectedZoomState + class BetterSelectingZoom(AbstractOverlay, BetterZoom): - """ Zooming tool which allows the user to draw a box which defines the - desired region to zoom in to + """Zooming tool which allows the user to draw a box which defines the + desired region to zoom in to """ #: The selection mode: @@ -29,7 +28,7 @@ class BetterSelectingZoom(AbstractOverlay, BetterZoom): #: Defines a meta-key, that works with always_on to set the zoom mode. This #: is useful when the zoom tool is used in conjunction with the pan tool. - always_on_modifier = Enum('control', 'shift', 'alt') + always_on_modifier = Enum("control", "shift", "alt") #: The mouse button that initiates the drag. If "None", then the tool #: will not respond to drag. (It can still respond to mousewheel events.) @@ -39,14 +38,13 @@ class BetterSelectingZoom(AbstractOverlay, BetterZoom): #: the tool to actually take effect. minimum_screen_delta = Int(10) - - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # deprecated interaction controls, used for API compatability with # SimpleZoom - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- #: Conversion ratio from wheel steps to zoom factors. - wheel_zoom_step = Property(Float, depends_on='zoom_factor') + wheel_zoom_step = Property(Float, depends_on="zoom_factor") #: The key press to enter zoom mode, if **always_on** is False. Has no effect #: if **always_on** is True. @@ -59,10 +57,9 @@ class BetterSelectingZoom(AbstractOverlay, BetterZoom): #: Disable the tool after the zoom is completed? disable_on_complete = Property() - - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Appearance properties (for Box mode) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- #: The pointer to use when drawing a zoom box. pointer = "magnifier" @@ -97,9 +94,9 @@ class BetterSelectingZoom(AbstractOverlay, BetterZoom): # is currently enabled. _enabled = Bool(False) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Private traits - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # the original numerical screen ranges _orig_low_setting = Tuple @@ -117,29 +114,28 @@ def __init__(self, component=None, *args, **kw): self._orig_high_setting = (x_range.high_setting, y_range.high_setting) def reset(self, event=None): - """ Resets the tool to normal state, with no start or end position. - """ + """Resets the tool to normal state, with no start or end position.""" self.event_state = "normal" self._screen_start = None self._screen_end = None - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- # BetterZoom interface - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def normal_key_pressed(self, event): - """ Handles a key being pressed when the tool is in the 'normal' + """Handles a key being pressed when the tool is in the 'normal' state. """ if not self.always_on: if self.enter_zoom_key.match(event) and not self._enabled: - self.event_state = 'pre_selecting' + self.event_state = "pre_selecting" event.window.set_pointer(self.pointer) event.window.set_mouse_owner(self, event.net_transform()) self._enabled = True event.handled = True elif self.exit_zoom_key.match(event) and self._enabled: - self.state = 'normal' + self.state = "normal" self._end_select(event) event.handled = True @@ -147,7 +143,7 @@ def normal_key_pressed(self, event): super(BetterSelectingZoom, self).normal_key_pressed(event) def normal_left_down(self, event): - """ Handles the left mouse button being pressed while the tool is + """Handles the left mouse button being pressed while the tool is in the 'normal' state. If the tool is enabled or always on, it starts selecting. @@ -157,7 +153,7 @@ def normal_left_down(self, event): event.handled = True def normal_right_down(self, event): - """ Handles the right mouse button being pressed while the tool is + """Handles the right mouse button being pressed while the tool is in the 'normal' state. If the tool is enabled or always on, it starts selecting. @@ -167,26 +163,24 @@ def normal_right_down(self, event): event.handled = True def pre_selecting_left_down(self, event): - """ The user pressed the key to turn on the zoom mode, - now handle the click to start the select mode + """The user pressed the key to turn on the zoom mode, + now handle the click to start the select mode """ self._start_select(event) event.handled = True def pre_selecting_key_pressed(self, event): - """ Handle key presses, specifically the exit zoom key - """ + """Handle key presses, specifically the exit zoom key""" if self.exit_zoom_key.match(event) and self._enabled: self._end_selecting(event) def selecting_key_pressed(self, event): - """ Handle key presses, specifically the exit zoom key - """ + """Handle key presses, specifically the exit zoom key""" if self.exit_zoom_key.match(event) and self._enabled: self._end_selecting(event) def selecting_mouse_move(self, event): - """ Handles the mouse moving when the tool is in the 'selecting' state. + """Handles the mouse moving when the tool is in the 'selecting' state. The selection is extended to the current mouse position. """ @@ -220,7 +214,7 @@ def selecting_mouse_move(self, event): event.handled = True def selecting_left_up(self, event): - """ Handles the left mouse button being released when the tool is in + """Handles the left mouse button being released when the tool is in the 'selecting' state. Finishes selecting and does the zoom. @@ -229,7 +223,7 @@ def selecting_left_up(self, event): self._end_select(event) def selecting_right_up(self, event): - """ Handles the right mouse button being released when the tool is in + """Handles the right mouse button being released when the tool is in the 'selecting' state. Finishes selecting and does the zoom. @@ -238,19 +232,19 @@ def selecting_right_up(self, event): self._end_select(event) def selecting_mouse_leave(self, event): - """ Handles the mouse leaving the plot when the tool is in the + """Handles the mouse leaving the plot when the tool is in the 'selecting' state. Ends the selection operation without zooming. """ self._end_selecting(event) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- # AbstractOverlay interface - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def overlay(self, component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Overrides AbstractOverlay. """ @@ -260,9 +254,9 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): else: self._overlay_box(component, gc) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- # private interface - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- @deprecated def _get_disable_on_complete(self): @@ -284,24 +278,23 @@ def _is_enabling_event(self, event): if self.always_on: enabled = True else: - if self.always_on_modifier == 'shift': + if self.always_on_modifier == "shift": enabled = event.shift_down - elif self.always_on_modifier == 'control': + elif self.always_on_modifier == "control": enabled = event.control_down - elif self.always_on_modifier == 'alt': + elif self.always_on_modifier == "alt": enabled = event.alt_down if enabled: - if event.right_down and self.drag_button == 'right': + if event.right_down and self.drag_button == "right": return True - if event.left_down and self.drag_button == 'left': + if event.left_down and self.drag_button == "left": return True return False def _start_select(self, event): - """ Starts selecting the zoom region - """ + """Starts selecting the zoom region""" if self.component.active_tool in (None, self): self.component.active_tool = self else: @@ -314,7 +307,7 @@ def _start_select(self, event): self.selecting_mouse_move(event) def _end_select(self, event): - """ Ends selection of the zoom region, adds the new zoom range to + """Ends selection of the zoom region, adds the new zoom range to the zoom stack, and does the zoom. """ self._screen_end = (event.x, event.y) @@ -334,7 +327,7 @@ def _end_select(self, event): prev = (x_range.low, x_range.high, y_range.low, y_range.high) - if self.tool_mode == 'range': + if self.tool_mode == "range": axis = self._determine_axis() if axis == 1: # vertical @@ -354,8 +347,7 @@ def _end_select(self, event): event.handled = True def _end_selecting(self, event=None): - """ Ends selection of zoom region, without zooming. - """ + """Ends selection of zoom region, without zooming.""" self.reset() self._enabled = False if self.component.active_tool == self: @@ -368,17 +360,18 @@ def _end_selecting(self, event=None): event.window.set_mouse_owner(None) def _overlay_box(self, component, gc): - """ Draws the overlay as a box. - """ + """Draws the overlay as a box.""" if self._screen_start and self._screen_end: with gc: gc.set_antialias(0) gc.set_line_width(self.border_size) gc.set_stroke_color(self.border_color_) - gc.clip_to_rect(component.x, component.y, component.width, component.height) + gc.clip_to_rect( + component.x, component.y, component.width, component.height + ) x, y = self._screen_start x2, y2 = self._screen_end - rect = (x, y, x2-x+1, y2-y+1) + rect = (x, y, x2 - x + 1, y2 - y + 1) if self.color != "transparent": color = self._get_fill_color() gc.set_fill_color(color) @@ -388,15 +381,16 @@ def _overlay_box(self, component, gc): gc.stroke_path() def _overlay_range(self, component, gc): - """ Draws the overlay as a range. - """ + """Draws the overlay as a range.""" axis_ndx = self._determine_axis() - lower_left = [0,0] - upper_right = [0,0] + lower_left = [0, 0] + upper_right = [0, 0] lower_left[axis_ndx] = self._screen_start[axis_ndx] - lower_left[1-axis_ndx] = self.component.position[1-axis_ndx] - upper_right[axis_ndx] = self._screen_end[axis_ndx] - self._screen_start[axis_ndx] - upper_right[1-axis_ndx] = self.component.bounds[1-axis_ndx] + lower_left[1 - axis_ndx] = self.component.position[1 - axis_ndx] + upper_right[axis_ndx] = ( + self._screen_end[axis_ndx] - self._screen_start[axis_ndx] + ) + upper_right[1 - axis_ndx] = self.component.bounds[1 - axis_ndx] with gc: gc.set_antialias(0) @@ -407,8 +401,7 @@ def _overlay_range(self, component, gc): gc.draw_rect((lower_left[0], lower_left[1], upper_right[0], upper_right[1])) def _get_fill_color(self): - """Get the fill color based on the alpha and the color property - """ + """Get the fill color based on the alpha and the color property""" if self.alpha: color = list(self.color_) if len(color) == 4: @@ -420,7 +413,7 @@ def _get_fill_color(self): return color def _determine_axis(self): - """ Determines whether the index of the coordinate along the axis of + """Determines whether the index of the coordinate along the axis of interest is the first or second element of an (x,y) coordinate tuple. """ if self.axis == "index": @@ -435,13 +428,15 @@ def _determine_axis(self): return 0 def _map_coordinate_box(self, start, end): - """ Given start and end points in screen space, returns corresponding + """Given start and end points in screen space, returns corresponding low and high points in data space. """ - low = [0,0] - high = [0,0] - for axis_index, mapper in [(0, self.component.x_mapper), \ - (1, self.component.y_mapper)]: + low = [0, 0] + high = [0, 0] + for axis_index, mapper in [ + (0, self.component.x_mapper), + (1, self.component.y_mapper), + ]: # Ignore missing axis mappers (ColorBar instances only have one). if not mapper: continue @@ -461,9 +456,9 @@ def _reset_range_settings(self): x_range.low_setting, y_range.low_setting = self._orig_low_setting x_range.high_setting, y_range.high_setting = self._orig_high_setting - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- # overloaded - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _prev_state_pressed(self): super(BetterSelectingZoom, self)._prev_state_pressed() diff --git a/chaco/tools/better_zoom.py b/chaco/tools/better_zoom.py index b759785ef..24474c7be 100644 --- a/chaco/tools/better_zoom.py +++ b/chaco/tools/better_zoom.py @@ -20,7 +20,7 @@ class BetterZoom(BaseTool, ToolHistoryMixin): #: Keys to zoom in/out - zoom_in_key = Instance(KeySpec, args=("+",), kw={'ignore': ['shift']}) + zoom_in_key = Instance(KeySpec, args=("+",), kw={"ignore": ["shift"]}) zoom_out_key = Instance(KeySpec, args=("-",)) #: Keys to zoom in/out in x direction only @@ -81,23 +81,25 @@ def _do_zoom(self, new_index_factor, new_value_factor): x_map = self._get_x_mapper() y_map = self._get_y_mapper() - cx = (x_map.range.high + x_map.range.low)/2 + cx = (x_map.range.high + x_map.range.low) / 2 if self._index_factor == new_index_factor: nextx = cx else: x = x_map.map_data(location[0]) - nextx = x + (cx - x)*(self._index_factor/new_index_factor) + nextx = x + (cx - x) * (self._index_factor / new_index_factor) - cy = (y_map.range.high + y_map.range.low)/2 + cy = (y_map.range.high + y_map.range.low) / 2 if self._value_factor == new_value_factor: nexty = cy else: y = y_map.map_data(location[1]) - nexty = y + (cy - y)*(self._value_factor/new_value_factor) + nexty = y + (cy - y) * (self._value_factor / new_value_factor) pan_state = PanState((cx, cy), (nextx, nexty)) - zoom_state = ZoomState((self._index_factor, self._value_factor), - (new_index_factor, new_value_factor)) + zoom_state = ZoomState( + (self._index_factor, self._value_factor), + (new_index_factor, new_value_factor), + ) states = GroupedToolState([pan_state, zoom_state]) states.apply(self) @@ -105,15 +107,17 @@ def _do_zoom(self, new_index_factor, new_value_factor): else: - zoom_state = ZoomState((self._index_factor, self._value_factor), - (new_index_factor, new_value_factor)) + zoom_state = ZoomState( + (self._index_factor, self._value_factor), + (new_index_factor, new_value_factor), + ) zoom_state.apply(self) self._append_state(zoom_state) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- # public interface - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def zoom_in(self, factor=0): if factor == 0: @@ -122,20 +126,20 @@ def zoom_in(self, factor=0): new_index_factor = self._index_factor * factor new_value_factor = self._value_factor * factor - if self.axis == 'value': + if self.axis == "value": new_index_factor = self._index_factor - elif self.axis == 'index': + elif self.axis == "index": new_value_factor = self._value_factor - if self.component.orientation == 'h': - if self._zoom_limit_reached(new_index_factor, 'x'): + if self.component.orientation == "h": + if self._zoom_limit_reached(new_index_factor, "x"): return - if self._zoom_limit_reached(new_value_factor, 'y'): + if self._zoom_limit_reached(new_value_factor, "y"): return else: - if self._zoom_limit_reached(new_index_factor, 'y'): + if self._zoom_limit_reached(new_index_factor, "y"): return - if self._zoom_limit_reached(new_value_factor, 'x'): + if self._zoom_limit_reached(new_value_factor, "x"): return self._do_zoom(new_index_factor, new_value_factor) @@ -146,20 +150,20 @@ def zoom_out(self, factor=0): new_index_factor = self._index_factor / factor new_value_factor = self._value_factor / factor - if self.axis == 'value': + if self.axis == "value": new_index_factor = self._index_factor - elif self.axis == 'index': + elif self.axis == "index": new_value_factor = self._value_factor - if self.component.orientation == 'h': - if self._zoom_limit_reached(new_index_factor, 'x'): + if self.component.orientation == "h": + if self._zoom_limit_reached(new_index_factor, "x"): return - if self._zoom_limit_reached(new_value_factor, 'y'): + if self._zoom_limit_reached(new_value_factor, "y"): return else: - if self._zoom_limit_reached(new_index_factor, 'y'): + if self._zoom_limit_reached(new_index_factor, "y"): return - if self._zoom_limit_reached(new_value_factor, 'x'): + if self._zoom_limit_reached(new_value_factor, "x"): return self._do_zoom(new_index_factor, new_value_factor) @@ -168,15 +172,15 @@ def zoom_in_x(self, factor=0): if factor == 0: factor = self.zoom_factor - if self.component.orientation == 'h': + if self.component.orientation == "h": new_index_factor = self._index_factor * factor new_value_factor = self._value_factor - if self._zoom_limit_reached(new_index_factor, 'x'): + if self._zoom_limit_reached(new_index_factor, "x"): return else: new_index_factor = self._index_factor new_value_factor = self._value_factor * factor - if self._zoom_limit_reached(new_value_factor, 'x'): + if self._zoom_limit_reached(new_value_factor, "x"): return self._do_zoom(new_index_factor, new_value_factor) @@ -185,15 +189,15 @@ def zoom_out_x(self, factor=0): if factor == 0: factor = self.zoom_factor - if self.component.orientation == 'h': + if self.component.orientation == "h": new_index_factor = self._index_factor / factor new_value_factor = self._value_factor - if self._zoom_limit_reached(new_index_factor, 'x'): + if self._zoom_limit_reached(new_index_factor, "x"): return else: new_index_factor = self._index_factor new_value_factor = self._value_factor / factor - if self._zoom_limit_reached(new_value_factor, 'x'): + if self._zoom_limit_reached(new_value_factor, "x"): return self._do_zoom(new_index_factor, new_value_factor) @@ -201,15 +205,15 @@ def zoom_in_y(self, factor=0): if factor == 0: factor = self.zoom_factor - if self.component.orientation == 'v': + if self.component.orientation == "v": new_index_factor = self._index_factor * factor new_value_factor = self._value_factor - if self._zoom_limit_reached(new_index_factor, 'y'): + if self._zoom_limit_reached(new_index_factor, "y"): return else: new_index_factor = self._index_factor new_value_factor = self._value_factor * factor - if self._zoom_limit_reached(new_value_factor, 'y'): + if self._zoom_limit_reached(new_value_factor, "y"): return self._do_zoom(new_index_factor, new_value_factor) @@ -218,25 +222,25 @@ def zoom_out_y(self, factor=0): if factor == 0: factor = self.zoom_factor - if self.component.orientation == 'v': + if self.component.orientation == "v": new_index_factor = self._index_factor / factor new_value_factor = self._value_factor - if self._zoom_limit_reached(new_index_factor, 'y'): + if self._zoom_limit_reached(new_index_factor, "y"): return else: new_index_factor = self._index_factor new_value_factor = self._value_factor / factor - if self._zoom_limit_reached(new_value_factor, 'y'): + if self._zoom_limit_reached(new_value_factor, "y"): return self._do_zoom(new_index_factor, new_value_factor) - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- # BaseTool interface - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def normal_key_pressed(self, event): - """ Handles a key being pressed when the tool is in the 'normal' + """Handles a key being pressed when the tool is in the 'normal' state. """ if not self.keys_zoom_to_mouse: @@ -277,42 +281,39 @@ def normal_mouse_move(self, event): self.position = (event.x, event.y) def normal_mouse_enter(self, event): - """ Try to set the focus to the window when the mouse enters, otherwise - the keypress events will not be triggered. + """Try to set the focus to the window when the mouse enters, otherwise + the keypress events will not be triggered. """ if self.component._window is not None: self.component._window._set_focus() - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- # private interface - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _center_screen(self): - return self.component.bounds[0]/2, self.component.bounds[1]/2 + return self.component.bounds[0] / 2, self.component.bounds[1] / 2 def _zoom_limit_reached(self, factor, xy_axis): - """ Returns True if the new low and high exceed the maximum zoom + """Returns True if the new low and high exceed the maximum zoom limits """ - if xy_axis == 'x': - return not (self.x_min_zoom_factor <= - factor <= self.x_max_zoom_factor) + if xy_axis == "x": + return not (self.x_min_zoom_factor <= factor <= self.x_max_zoom_factor) else: - return not (self.y_min_zoom_factor <= - factor <= self.y_max_zoom_factor) + return not (self.y_min_zoom_factor <= factor <= self.y_max_zoom_factor) def _zoom_in_mapper(self, mapper, factor): high = mapper.range.high low = mapper.range.low - range = high-low + range = high - low - center = (low + high)/2.0 + center = (low + high) / 2.0 - new_range = range/factor - mapper.range.set_bounds(low=center - new_range/2, - high=center + new_range/2) + new_range = range / factor + mapper.range.set_bounds(low=center - new_range / 2, high=center + new_range / 2) def _get_x_mapper(self): if isinstance(self.component.index_mapper, GridMapper): @@ -334,12 +335,12 @@ def _get_y_mapper(self): return self.component.value_mapper return self.component.index_mapper - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- # ToolHistoryMixin interface - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _next_state_pressed(self): - """ Called when the tool needs to advance to the next state in the + """Called when the tool needs to advance to the next state in the stack. The **_history_index** will have already been set to the index @@ -349,16 +350,16 @@ def _next_state_pressed(self): self._current_state().apply(self) def _prev_state_pressed(self): - """ Called when the tool needs to advance to the previous state in the + """Called when the tool needs to advance to the previous state in the stack. The **_history_index** will have already been set to the index corresponding to the previous state. """ - self._history[self._history_index+1].revert(self) + self._history[self._history_index + 1].revert(self) def _reset_state_pressed(self): - """ Called when the tool needs to reset its history. + """Called when the tool needs to reset its history. The history index will have already been set to 0. """ @@ -366,9 +367,9 @@ def _reset_state_pressed(self): state.revert(self) self._history = [] - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- # Traits defaults - #-------------------------------------------------------------------------- + # -------------------------------------------------------------------------- def _position_default(self): # center of the component is a sensible default diff --git a/chaco/tools/broadcaster.py b/chaco/tools/broadcaster.py index 53ebc0065..92af2ed52 100644 --- a/chaco/tools/broadcaster.py +++ b/chaco/tools/broadcaster.py @@ -3,8 +3,9 @@ from enable.api import BaseTool from traits.api import Dict, List + class BroadcasterTool(BaseTool): - """ A simple tool that keeps a list of other tools, and broadcasts events it + """A simple tool that keeps a list of other tools, and broadcasts events it receives to all of the tools. """ @@ -16,11 +17,11 @@ class BroadcasterTool(BaseTool): mouse_owners = Dict def dispatch(self, event, suffix): - """ Dispatches a mouse event based on the current event state. + """Dispatches a mouse event based on the current event state. Overrides BaseTool. """ - handled = False # keeps track of whether any tool handled this event + handled = False # keeps track of whether any tool handled this event if event.window.mouse_owner == self: tools = list(self.mouse_owners.keys()) diff --git a/chaco/tools/cursor_tool.py b/chaco/tools/cursor_tool.py index 7dc66e2e0..deac85221 100644 --- a/chaco/tools/cursor_tool.py +++ b/chaco/tools/cursor_tool.py @@ -20,8 +20,16 @@ # Enthought library imports from enable.tools.drag_tool import DragTool -from traits.api import Int, Property, cached_property, Float,\ - Bool, Instance, Tuple, Disallow +from traits.api import ( + Int, + Property, + cached_property, + Float, + Bool, + Instance, + Tuple, + Disallow, +) # Chaco imports from chaco.scatter_markers import CircleMarker @@ -40,7 +48,9 @@ def CursorTool(component, *args, **kwds): elif isinstance(component, Base2DPlot): return CursorTool2D(component, *args, **kwds) else: - raise NotImplementedError("cursors available for BaseXYPlot and Base2DPlot only") + raise NotImplementedError( + "cursors available for BaseXYPlot and Base2DPlot only" + ) class BaseCursorTool(LineInspector, DragTool): @@ -48,25 +58,25 @@ class BaseCursorTool(LineInspector, DragTool): Abstract base class for CursorTool objects """ - #if true, draw a small circle at the cursor/line intersection + # if true, draw a small circle at the cursor/line intersection show_marker = Bool(True) - #the radius of the marker in pixels + # the radius of the marker in pixels marker_size = Float(3.0) - #the marker object. this should probably be private + # the marker object. this should probably be private marker = Instance(CircleMarker, ()) - #pick threshold, in screen units (pixels) + # pick threshold, in screen units (pixels) threshold = Float(5.0) - #The current index-value of the cursor. Over-ridden in subclasses + # The current index-value of the cursor. Over-ridden in subclasses current_index = Disallow - #The current position of the cursor in data units - current_position = Property(depends_on=['current_index']) + # The current position of the cursor in data units + current_position = Property(depends_on=["current_index"]) - #Stuff from line_inspector which is not required + # Stuff from line_inspector which is not required axis = Disallow inspect_mode = Disallow is_interactive = Disallow @@ -79,13 +89,17 @@ def _draw_marker(self, gc, sx, sy): Ruthlessly hijacked from the scatterplot.py class. This design is silly; the choice of rendering path should be encapsulated within the GC. """ - if sx < self.component.x or sx > self.component.x2 or \ - sy < self.component.y or sy > self.component.y2: + if ( + sx < self.component.x + or sx > self.component.x2 + or sy < self.component.y + or sy > self.component.y2 + ): return marker = self.marker marker_size = self.marker_size - points = [(sx,sy)] + points = [(sx, sy)] with gc: gc.set_fill_color(self.color_) @@ -93,15 +107,14 @@ def _draw_marker(self, gc, sx, sy): gc.begin_path() # This is the fastest method - use one of the kiva built-in markers - if hasattr(gc, "draw_marker_at_points") \ - and (gc.draw_marker_at_points(points, - marker_size, - marker.kiva_marker) != 0): - pass + if hasattr(gc, "draw_marker_at_points") and ( + gc.draw_marker_at_points(points, marker_size, marker.kiva_marker) != 0 + ): + pass # The second fastest method - draw the path into a compiled path, then # draw the compiled path at each point - elif hasattr(gc, 'draw_path_at_points'): + elif hasattr(gc, "draw_path_at_points"): path = gc.get_empty_path() marker.add_to_path(path, marker_size) mode = marker.draw_mode @@ -113,7 +126,7 @@ def _draw_marker(self, gc, sx, sy): else: if not marker.antialias: gc.set_antialias(False) - for sx,sy in points: + for sx, sy in points: with gc: gc.translate_ctm(sx, sy) # Kiva GCs have a path-drawing interface @@ -121,13 +134,11 @@ def _draw_marker(self, gc, sx, sy): gc.draw_path(marker.draw_mode) def normal_mouse_move(self, event): - """ Handles the mouse being moved. - """ + """Handles the mouse being moved.""" return def normal_mouse_leave(self, event): - """ Handles the mouse leaving the plot. - """ + """Handles the mouse leaving the plot.""" return @@ -140,12 +151,11 @@ class CursorTool1D(BaseCursorTool): """ - #The current index-value of the cursor + # The current index-value of the cursor current_index = Int(0) - - #if true, draws a line parallel to the index-axis - #through the cursor intersection point + # if true, draws a line parallel to the index-axis + # through the cursor intersection point show_value_line = Bool(True) def _current_index_changed(self): @@ -157,7 +167,7 @@ def _get_current_position(self): ndx = self.current_index x = plot.index.get_data()[ndx] y = plot.value.get_data()[ndx] - return x,y + return x, y def _set_current_position(self, traitname, args): plot = self.component @@ -166,7 +176,7 @@ def _set_current_position(self, traitname, args): self.current_index = ndx def draw(self, gc, view_bounds=None): - """ Draws this tool on a graphics context. + """Draws this tool on a graphics context. Overrides LineInspector, BaseTool. """ @@ -199,14 +209,14 @@ def is_draggable(self, x, y): if plot is not None: orientation = plot.orientation sx, sy = plot.map_screen(self.current_position) - if orientation=='h' and numpy.abs(sx-x) <= self.threshold: + if orientation == "h" and numpy.abs(sx - x) <= self.threshold: return True - elif orientation=='v' and numpy.abs(sy-y) <= self.threshold: + elif orientation == "v" and numpy.abs(sy - y) <= self.threshold: return True return False def dragging(self, event): - x,y = event.x, event.y + x, y = event.x, event.y plot = self.component ndx = plot.map_index((x, y), threshold=0.0, index_only=True) if ndx is None: @@ -219,7 +229,7 @@ class CursorTool2D(BaseCursorTool): _dragV = Bool(False) _dragH = Bool(False) - current_index = Tuple(0,0) + current_index = Tuple(0, 0) def _current_index_changed(self): self.component.request_redraw() @@ -231,7 +241,7 @@ def _get_current_position(self): xdata, ydata = plot.index.get_data() x = xdata.get_data()[ndx] y = ydata.get_data()[ndy] - return x,y + return x, y def _set_current_position(self, traitname, args): plot = self.component @@ -247,21 +257,21 @@ def is_draggable(self, x, y): orientation = plot.orientation sx, sy = plot.map_screen([self.current_position])[0] self._dragV = self._dragH = False - if orientation=='h': - if numpy.abs(sx-x) <= self.threshold: + if orientation == "h": + if numpy.abs(sx - x) <= self.threshold: self._dragH = True - if numpy.abs(sy-y) <= self.threshold: + if numpy.abs(sy - y) <= self.threshold: self._dragV = True else: - if numpy.abs(sx-x) <= self.threshold: + if numpy.abs(sx - x) <= self.threshold: self._dragV = True - if numpy.abs(sy-y) <= self.threshold: + if numpy.abs(sy - y) <= self.threshold: self._dragH = True return self._dragV or self._dragH return False def draw(self, gc, view_bounds=None): - """ Draws this tool on a graphics context. + """Draws this tool on a graphics context. Overrides LineInspector, BaseTool. """ @@ -289,7 +299,7 @@ def draw(self, gc, view_bounds=None): self._draw_marker(gc, sx, sy) def dragging(self, event): - x,y = event.x, event.y + x, y = event.x, event.y plot = self.component ndx = plot.map_index((x, y), threshold=0.0, index_only=True) if ndx is None: diff --git a/chaco/tools/data_label_tool.py b/chaco/tools/data_label_tool.py index 064987592..eabbe53b1 100644 --- a/chaco/tools/data_label_tool.py +++ b/chaco/tools/data_label_tool.py @@ -9,7 +9,7 @@ class DataLabelTool(DragTool): - """ A tool for dragging a data label. + """A tool for dragging a data label. Attach this tool to a DataLabel object by setting the tool's **component** to the DataLabel. @@ -26,25 +26,31 @@ class DataLabelTool(DragTool): _original_offset = Any # This is used in the auto_arrow_root = 'corners' case. - _corner_names = ("bottom left", "bottom right", "top right", "top left", - "top center", "bottom center", "left center", "right center") + _corner_names = ( + "bottom left", + "bottom right", + "top right", + "top left", + "top center", + "bottom center", + "left center", + "right center", + ) def is_draggable(self, x, y): - """ Returns whether the (x,y) position is in a region that is OK to + """Returns whether the (x,y) position is in a region that is OK to drag. Overrides DragTool. """ if self.component: label = self.component - return (x >= label.x and x <= label.x2 and \ - y >= label.y and y <= label.y2) + return x >= label.x and x <= label.x2 and y >= label.y and y <= label.y2 else: return False - def drag_start(self, event): - """ Called when the drag operation starts. + """Called when the drag operation starts. Implements DragTool. """ @@ -56,7 +62,7 @@ def drag_start(self, event): event.handled = True def dragging(self, event): - """ This method is called for every mouse_move event that the tool + """This method is called for every mouse_move event that the tool receives while the user is dragging the mouse. Implements DragTool. Moves and redraws the label. @@ -66,8 +72,10 @@ def dragging(self, event): dx = int(event.x - self.mouse_down_position[0]) dy = int(event.y - self.mouse_down_position[1]) - label.label_position = (self._original_offset[0] + dx, - self._original_offset[1] + dy) + label.label_position = ( + self._original_offset[0] + dx, + self._original_offset[1] + dy, + ) if self.auto_arrow_root: # Determine which corner is closest to the point @@ -75,10 +83,20 @@ def dragging(self, event): x, y = label.position x2 = label.x2 y2 = label.y2 - xmid = (x+x2)/2 - ymid = (y+y2)/2 - anchors = array(((x, y), (x2, y), (x2, y2), (x, y2), - (xmid, y2), (xmid, y), (x, ymid), (x2, ymid))) + xmid = (x + x2) / 2 + ymid = (y + y2) / 2 + anchors = array( + ( + (x, y), + (x2, y), + (x2, y2), + (x, y2), + (xmid, y2), + (xmid, y), + (x, ymid), + (x2, ymid), + ) + ) diff = anchors - p closest = argmin((diff ** 2).sum(axis=-1)) label.arrow_root = self._corner_names[closest] @@ -87,7 +105,7 @@ def dragging(self, event): label.request_redraw() def drag_end(self, event): - """ Called when a mouse event causes the drag operation to end. + """Called when a mouse event causes the drag operation to end. Implements DragTool. """ diff --git a/chaco/tools/dataprinter.py b/chaco/tools/dataprinter.py index 18e342f81..0c5ffedfb 100644 --- a/chaco/tools/dataprinter.py +++ b/chaco/tools/dataprinter.py @@ -2,7 +2,6 @@ """ - # Enthought library imports from traits.api import Str from enable.api import BaseTool @@ -12,7 +11,7 @@ class DataPrinter(BaseTool): - """ Simple listener tool that prints the (x,y) data space position of the + """Simple listener tool that prints the (x,y) data space position of the point under the cursor. """ @@ -26,7 +25,7 @@ class DataPrinter(BaseTool): format = Str("(%.3f, %.3f)") def normal_mouse_move(self, event): - """ Handles the mouse being moved in the 'normal' state. + """Handles the mouse being moved in the 'normal' state. Prints the data space position of the current mouse position. """ @@ -40,8 +39,7 @@ def normal_mouse_move(self, event): print(msg.format(plot.__class__.__name__)) def _build_text_from_event(self, event): - """ Build the text to display from the mouse event. - """ + """Build the text to display from the mouse event.""" plot = self.component ndx = plot.map_index((event.x, event.y), index_only=True) x = plot.index.get_data()[ndx] diff --git a/chaco/tools/drag_tool.py b/chaco/tools/drag_tool.py index fd093a876..dfbfe72d1 100644 --- a/chaco/tools/drag_tool.py +++ b/chaco/tools/drag_tool.py @@ -1,11 +1,12 @@ - # This is a duplicate of the enable.DragTool class and will be # removed in future versions. Please import DragTool directly # from enable. import warnings -warnings.warn("chaco.tools.DragTool has been removed." - "Use enable.tools.DragTool instead.", DeprecationWarning) -from enable.tools.drag_tool import DragTool +warnings.warn( + "chaco.tools.DragTool has been removed." "Use enable.tools.DragTool instead.", + DeprecationWarning, +) +from enable.tools.drag_tool import DragTool diff --git a/chaco/tools/drag_zoom.py b/chaco/tools/drag_zoom.py index cb73490a1..a2d94372e 100644 --- a/chaco/tools/drag_zoom.py +++ b/chaco/tools/drag_zoom.py @@ -10,7 +10,7 @@ class DragZoom(DragTool, BetterZoom): - """ A zoom tool that zooms continuously with a mouse drag movement, instead + """A zoom tool that zooms continuously with a mouse drag movement, instead of using a zoom box or range. By default, the tool maintains aspect ratio and zooms the plot's X and Y @@ -50,9 +50,9 @@ class DragZoom(DragTool, BetterZoom): zoom_to_mouse = Bool(False) - #------------------------------------------------------------------------------ + # ------------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------------ + # ------------------------------------------------------------------------------ # (x,y) of the point where the mouse button was pressed. _original_xy = Tuple() @@ -88,8 +88,8 @@ def dragging(self, event): zoom_y = self._calc_zoom(self._prev_y, event.y) # invert the zoom so scrolling up zooms in - zoom_x = 1.0/zoom_x - zoom_y = 1.0/zoom_y + zoom_x = 1.0 / zoom_x + zoom_y = 1.0 / zoom_y self.zoom_in_x(zoom_x) self.zoom_in_y(zoom_y) @@ -97,8 +97,11 @@ def dragging(self, event): def drag_start(self, event, capture_mouse=True): self._original_xy = (event.x, event.y) c = self.component - self._orig_screen_bounds = ((c.x,c.y), (c.x2,c.y2)) - self._original_data = (c.x_mapper.map_data(event.x), c.y_mapper.map_data(event.y)) + self._orig_screen_bounds = ((c.x, c.y), (c.x2, c.y2)) + self._original_data = ( + c.x_mapper.map_data(event.x), + c.y_mapper.map_data(event.y), + ) self._prev_x = event.x self._prev_y = event.y if capture_mouse: @@ -113,9 +116,9 @@ def drag_end(self, event): event.handled = True def _calc_zoom(self, original, clicked): - """ Returns the amount to scale the range based on the original + """Returns the amount to scale the range based on the original cursor position and a new, updated position. """ # We express the built-in zoom scaling as 0.05/10 to indicate a scaling # of 5% every 10 pixels, per the docstring for the 'speed' trait. - return 1.0 - self.speed * (clicked - original) * (0.05/10) + return 1.0 - self.speed * (clicked - original) * (0.05 / 10) diff --git a/chaco/tools/draw_points_tool.py b/chaco/tools/draw_points_tool.py index dd1072aae..27382bb88 100644 --- a/chaco/tools/draw_points_tool.py +++ b/chaco/tools/draw_points_tool.py @@ -12,8 +12,7 @@ class DrawPointsTool(BaseTool): - """ A tool that draws points onto a rectangular plot as they are clicked. - """ + """A tool that draws points onto a rectangular plot as they are clicked.""" #: A data source for the x-dimension of the drawn points. xdata = Instance(ArrayDataSource) @@ -22,7 +21,7 @@ class DrawPointsTool(BaseTool): #: Is this the active tool? activated = Bool(True) - #It would be nice to set the pointer to a cross + # It would be nice to set the pointer to a cross def __init__(self, **kwtraits): BaseTool.__init__(self, **kwtraits) @@ -30,14 +29,14 @@ def __init__(self, **kwtraits): self.ydata = self.component.value2 def normal_left_down(self, event): - """ Handles the left mouse button being clicked when the tool is in the + """Handles the left mouse button being clicked when the tool is in the 'normal' state. Maps the event position into data space, adds the point to the points for this tool, and redraws. """ - x,y = event.x, event.y - data_x, data_y = self.component.map_data((x,y)) + x, y = event.x, event.y + data_x, data_y = self.component.map_data((x, y)) self._append_data(self.xdata, data_x) self._append_data(self.ydata, data_y) self.component.request_redraw() diff --git a/chaco/tools/highlight_tool.py b/chaco/tools/highlight_tool.py index 505827753..a2dbe96bd 100644 --- a/chaco/tools/highlight_tool.py +++ b/chaco/tools/highlight_tool.py @@ -12,12 +12,12 @@ class HighlightTool(BaseTool): - """ A tool that enables the user to select a plot to be highlighted on the + """A tool that enables the user to select a plot to be highlighted on the graph by clicking on it. """ #: The name of the data source metadata which controls selections. - metadata_name = Str('selections') + metadata_name = Str("selections") #: The mouse button that initiates the selection. drag_button = Enum("left", "right") @@ -25,9 +25,9 @@ class HighlightTool(BaseTool): #: Threshold distance for hit-testing. threshold = Float(20.0) - #--------------------------------------------------------------------- + # --------------------------------------------------------------------- # Inherited BaseTool traits - #--------------------------------------------------------------------- + # --------------------------------------------------------------------- #: This tool is not drawn. Overrides BaseTool. draw_mode = "none" @@ -36,7 +36,7 @@ class HighlightTool(BaseTool): visible = False def normal_left_down(self, event): - """ Handles the left mouse button being pressed. + """Handles the left mouse button being pressed. If the left mouse button initiates the selection, this method does so. """ @@ -44,7 +44,7 @@ def normal_left_down(self, event): self._highlight(event) def normal_right_down(self, event): - """ Handles the right mouse button being pressed. + """Handles the right mouse button being pressed. If the right mouse button initiates the selection, this method does so. """ @@ -57,7 +57,9 @@ def _highlight(self, event): closest_plot = self._find_curve(self.component.components, event) if closest_plot: index = closest_plot.index - index.metadata[self.metadata_name] = ones(len(index.get_data()), dtype=bool) + index.metadata[self.metadata_name] = ones( + len(index.get_data()), dtype=bool + ) closest_plot.request_redraw() else: # If we are attached to a plot container, then we can deselect @@ -72,7 +74,9 @@ def _highlight(self, event): hit_point = self.component.hittest((event.x, event.y), self.threshold) index = self.component.index if hit_point is not None: - index.metadata[self.metadata_name] = ones(len(index.get_data()), dtype=bool) + index.metadata[self.metadata_name] = ones( + len(index.get_data()), dtype=bool + ) self.component.request_redraw() elif self.metadata_name in index.metadata: del index.metadata[self.metadata_name] @@ -80,12 +84,11 @@ def _highlight(self, event): event.handled = True - def _find_curve(self, plots, event): # need to change to use distance - not just return first plot within threshold for p in plots: if hasattr(p, "hittest"): - cpoint = p.hittest((event.x,event.y), self.threshold) + cpoint = p.hittest((event.x, event.y), self.threshold) if cpoint is not None: return p return None diff --git a/chaco/tools/image_inspector_tool.py b/chaco/tools/image_inspector_tool.py index e76d4de11..7aec63dfa 100644 --- a/chaco/tools/image_inspector_tool.py +++ b/chaco/tools/image_inspector_tool.py @@ -12,8 +12,7 @@ class ImageInspectorTool(BaseTool): - """ A tool that captures the color and underlying values of an image plot. - """ + """A tool that captures the color and underlying values of an image plot.""" #: This event fires whenever the mouse moves over a new image point. #: Its value is a dict with a key "color_value", and possibly a key @@ -29,11 +28,11 @@ class ImageInspectorTool(BaseTool): #: This key will show and hide any ImageInspectorOverlays associated #: with this tool. - inspector_key = KeySpec('p') + inspector_key = KeySpec("p") # Stores the value of self.visible when the mouse leaves the tool, # so that it can be restored when the mouse enters again. - _old_visible = Enum(None, True, False) #Trait(None, Bool(True)) + _old_visible = Enum(None, True, False) # Trait(None, Bool(True)) def normal_key_pressed(self, event): if self.inspector_key.match(event): @@ -51,7 +50,7 @@ def normal_mouse_enter(self, event): self._old_visible = None def normal_mouse_move(self, event): - """ Handles the mouse being moved. + """Handles the mouse being moved. Fires the **new_value** event with the data (if any) from the event's position. @@ -66,26 +65,30 @@ def normal_mouse_move(self, event): x_index, y_index = ndx image_data = plot.value - if hasattr(plot, "_cached_mapped_image") and \ - plot._cached_mapped_image is not None: - self.new_value = \ - {"indices": ndx, - "data_value": image_data.data[y_index, x_index], - "color_value": plot._cached_mapped_image[y_index, - x_index]} + if ( + hasattr(plot, "_cached_mapped_image") + and plot._cached_mapped_image is not None + ): + self.new_value = { + "indices": ndx, + "data_value": image_data.data[y_index, x_index], + "color_value": plot._cached_mapped_image[y_index, x_index], + } else: - self.new_value = \ - {"indices": ndx, - "color_value": image_data.data[y_index, x_index]} + self.new_value = { + "indices": ndx, + "color_value": image_data.data[y_index, x_index], + } self.last_mouse_position = (event.x, event.y) class ImageInspectorOverlay(TextBoxOverlay): - """ An overlay that displays a box containing values from an + """An overlay that displays a box containing values from an ImageInspectorTool instance. """ + #: An instance of ImageInspectorTool; this overlay listens to the tool #: for changes, and updates its displayed text accordingly. image_inspector = Any @@ -104,21 +107,21 @@ class ImageInspectorOverlay(TextBoxOverlay): # Private interface ------------------------------------------------------- def _build_text_from_event(self, event): - """ Create a formatted string to display from the mouse event data. - """ + """Create a formatted string to display from the mouse event data.""" newstring = "" - if 'indices' in event: - newstring += '(%d, %d)' % event['indices'] - if 'color_value' in event: + if "indices" in event: + newstring += "(%d, %d)" % event["indices"] + if "color_value" in event: try: newstring += "\n(%d, %d, %d)" % tuple( - map(int, event['color_value'][:3])) + map(int, event["color_value"][:3]) + ) except IndexError: # color value is an integer, for example if gray scale image - newstring += "\n%d" % event['color_value'] + newstring += "\n%d" % event["color_value"] - if 'data_value' in event: - newstring += "\n{}".format(event['data_value']) + if "data_value" in event: + newstring += "\n{}".format(event["data_value"]) return newstring @@ -126,12 +129,10 @@ def _build_text_from_event(self, event): def _image_inspector_changed(self, old, new): if old: - old.observe(self._new_value_updated, 'new_value', - remove=True) - old.observe(self._tool_visible_updated, "visible", - remove=True) + old.observe(self._new_value_updated, "new_value", remove=True) + old.observe(self._tool_visible_updated, "visible", remove=True) if new: - new.observe(self._new_value_updated, 'new_value') + new.observe(self._new_value_updated, "new_value") new.observe(self._tool_visible_updated, "visible") self._tool_visible_updated() diff --git a/chaco/tools/lasso_selection.py b/chaco/tools/lasso_selection.py index 956d27184..6629c0f38 100644 --- a/chaco/tools/lasso_selection.py +++ b/chaco/tools/lasso_selection.py @@ -5,8 +5,18 @@ from numpy import array, column_stack, empty, sometrue, vstack, zeros # Enthought library imports -from traits.api import Any, Array, Enum, Event, Bool, Instance, \ - Property, Str, Trait, List +from traits.api import ( + Any, + Array, + Enum, + Event, + Bool, + Instance, + Property, + Str, + Trait, + List, +) from kiva.api import points_in_polygon # Chaco imports @@ -17,12 +27,13 @@ class LassoSelection(AbstractController): - """ A controller that represents the interaction of "lassoing" a set of + """A controller that represents the interaction of "lassoing" a set of points. "Lassoing" means drawing an arbitrary selection region around the points by dragging the mouse along the outline of the region. """ + #: An Nx2 array of points in data space representing all selected points. dataspace_points = Property(Array) @@ -75,11 +86,11 @@ class LassoSelection(AbstractController): #: selecting: #: The user is dragging the mouse and is actively changing the #: selection region. - event_state = Enum('normal', 'selecting') + event_state = Enum("normal", "selecting") - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Private Traits - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # The PlotComponent associated with this tool. _plot = Trait(None, Any) @@ -91,18 +102,18 @@ class LassoSelection(AbstractController): _active_selection = Array _previous_selections = List(Array) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Properties - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _get_dataspace_points(self): - """ Returns a complete list of all selected points. + """Returns a complete list of all selected points. - This property exists for backwards compatibility, as the - disjoint_selections property is almost always the preferred - method of accessingselected points + This property exists for backwards compatibility, as the + disjoint_selections property is almost always the preferred + method of accessingselected points """ - composite = empty((0,2)) + composite = empty((0, 2)) for region in self.disjoint_selections: if len(region) > 0: composite = vstack((composite, region)) @@ -110,17 +121,17 @@ def _get_dataspace_points(self): return composite def _get_disjoint_selections(self): - """ Returns a list of all disjoint selections composed of - the previous selections and the active selection + """Returns a list of all disjoint selections composed of + the previous selections and the active selection """ if len(self._active_selection) == 0: return self._previous_selections else: return self._previous_selections + [self._active_selection] - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Event Handlers - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def normal_left_down(self, event): if self.drag_button == "left": @@ -131,19 +142,21 @@ def normal_right_down(self, event): return self.normal_mouse_down(event) def normal_mouse_down(self, event): - """ Handles the left mouse button being pressed while the tool is + """Handles the left mouse button being pressed while the tool is in the 'normal' state. Puts the tool into 'selecting' mode, and starts defining the selection. """ # We may want to generalize this for the n-dimensional case... - self._active_selection = empty((0,2), dtype=numpy.bool) + self._active_selection = empty((0, 2), dtype=numpy.bool) if self.selection_datasource is not None: - self.selection_datasource.metadata[self.metadata_name] = zeros(len(self.selection_datasource.get_data()), dtype=numpy.bool) + self.selection_datasource.metadata[self.metadata_name] = zeros( + len(self.selection_datasource.get_data()), dtype=numpy.bool + ) self.selection_mode = "include" - self.event_state = 'selecting' + self.event_state = "selecting" self.selecting_mouse_move(event) if (not event.shift_down) and (not event.control_down): @@ -164,19 +177,19 @@ def selecting_right_up(self, event): return self.selecting_mouse_up(event) def selecting_mouse_up(self, event): - """ Handles the mouse button coming up in the 'selecting' state. + """Handles the mouse button coming up in the 'selecting' state. Completes the selection and switches to the 'normal' state. """ - self.event_state = 'normal' + self.event_state = "normal" self.selection_completed = True self._update_selection() self._previous_selections.append(self._active_selection) - self._active_selection = empty((0,2), dtype=numpy.bool) + self._active_selection = empty((0, 2), dtype=numpy.bool) def selecting_mouse_move(self, event): - """ Handles the mouse moving when the tool is in the 'selecting' state. + """Handles the mouse moving when the tool is in the 'selecting' state. The selection is extended to the current mouse position. """ @@ -192,7 +205,7 @@ def selecting_mouse_move(self, event): self.trait_property_changed("disjoint_selections", None) def selecting_mouse_leave(self, event): - """ Handles the mouse leaving the plot when the tool is in the + """Handles the mouse leaving the plot when the tool is in the 'selecting' state. Ends the selection operation. @@ -201,59 +214,58 @@ def selecting_mouse_leave(self, event): return self.selecting_mouse_up(event) def normal_key_pressed(self, event): - """ Handles the user pressing a key in the 'normal' state. + """Handles the user pressing a key in the 'normal' state. If the user presses the Escape key, the tool is reset. """ if event.character == "Esc": self._reset() - elif event.character == 'a' and event.control_down: + elif event.character == "a" and event.control_down: self._reset() self._select_all() - elif event.character == 'i' and event.control_down: + elif event.character == "i" and event.control_down: self.selecting_mouse_up(None) - self.selection_mode = 'invert' + self.selection_mode = "invert" self._select_all() - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Protected Methods - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _dataspace_points_default(self): - return empty((0,2), dtype=numpy.bool) + return empty((0, 2), dtype=numpy.bool) def _reset(self): - """ Resets the selection - """ - self.event_state='normal' - self._active_selection = empty((0,2), dtype=numpy.bool) + """Resets the selection""" + self.event_state = "normal" + self._active_selection = empty((0, 2), dtype=numpy.bool) self._previous_selections = [] self._update_selection() def _select_all(self): - """ Selects all points in the plot. This is done by making a rectangle - using the corners of the plot, which is simple but effective. A - much cooler, but more time-intensive solution would be to make - a selection polygon representing the convex hull. + """Selects all points in the plot. This is done by making a rectangle + using the corners of the plot, which is simple but effective. A + much cooler, but more time-intensive solution would be to make + a selection polygon representing the convex hull. """ - points = [self._map_data(array((self.plot.x, self.plot.y2))), - self._map_data(array((self.plot.x2, self.plot.y2))), - self._map_data(array((self.plot.x2, self.plot.y))), - self._map_data(array((self.plot.x, self.plot.y)))] + points = [ + self._map_data(array((self.plot.x, self.plot.y2))), + self._map_data(array((self.plot.x2, self.plot.y2))), + self._map_data(array((self.plot.x2, self.plot.y))), + self._map_data(array((self.plot.x, self.plot.y))), + ] self._active_selection = numpy.array(points) self._update_selection() - def _update_selection(self): - """ Sets the selection datasource's metadata to a mask of all + """Sets the selection datasource's metadata to a mask of all the points selected """ if self.selection_datasource is None: return - selected_mask = zeros(self.selection_datasource._data.shape, - dtype=numpy.bool) + selected_mask = zeros(self.selection_datasource._data.shape, dtype=numpy.bool) data = self._get_data() # Compose the selection mask from the cached selections first, then @@ -261,36 +273,40 @@ def _update_selection(self): # for the active selection for selection in self._previous_selections: - selected_mask |= points_in_polygon( - data, selection, False).astype(bool, copy=False) + selected_mask |= points_in_polygon(data, selection, False).astype( + bool, copy=False + ) active_selection = points_in_polygon( - data, self._active_selection, False).astype(bool, copy=False) + data, self._active_selection, False + ).astype(bool, copy=False) - if self.selection_mode == 'exclude': + if self.selection_mode == "exclude": # XXX I think this should be "set difference"? - CJW selected_mask |= active_selection selected_mask = ~selected_mask - elif self.selection_mode == 'invert': + elif self.selection_mode == "invert": selected_mask ^= active_selection else: selected_mask |= active_selection - if sometrue(selected_mask != self.selection_datasource.metadata[self.metadata_name]): + if sometrue( + selected_mask != self.selection_datasource.metadata[self.metadata_name] + ): self.selection_datasource.metadata[self.metadata_name] = selected_mask self.selection_changed = True def _map_screen(self, points): - """ Maps a point in data space to a point in screen space on the plot. + """Maps a point in data space to a point in screen space on the plot. Normally this method is a pass-through, but it may do more in specialized plots. """ - return self.plot.map_screen(points)[:,:2] + return self.plot.map_screen(points)[:, :2] def _map_data(self, point): - """ Maps a point in screen space to data space. + """Maps a point in screen space to data space. Normally this method is a pass-through, but for plots that have more data than just (x,y), proper transformations need to happen here. @@ -304,14 +320,12 @@ def _map_data(self, point): raise RuntimeError("LassoSelection only supports BaseXY and Base2D plots") def _get_data(self): - """ Returns the datapoints in the plot, as an Nx2 array of (x,y). - """ - return column_stack((self.plot.index.get_data(), - self.plot.value.get_data())) + """Returns the datapoints in the plot, as an Nx2 array of (x,y).""" + return column_stack((self.plot.index.get_data(), self.plot.value.get_data())) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property getter/setters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_plot(self): if self._plot is not None: diff --git a/chaco/tools/legend_highlighter.py b/chaco/tools/legend_highlighter.py index 62ebc2606..9eafb65cb 100644 --- a/chaco/tools/legend_highlighter.py +++ b/chaco/tools/legend_highlighter.py @@ -8,7 +8,7 @@ def _ensure_list(obj): - """ NOTE: The Legend stores plots in a dictionary with either single + """NOTE: The Legend stores plots in a dictionary with either single renderers as values, or lists of renderers. This function helps us assume we're always working with lists """ @@ -40,7 +40,7 @@ def get_hit_plots(legend, event): class LegendHighlighter(LegendTool): - """ A tool for legends that allows clicking on the legend to show + """A tool for legends that allows clicking on the legend to show or hide certain plots. """ @@ -57,8 +57,7 @@ class LegendHighlighter(LegendTool): _selected_renderers = List def normal_left_down(self, event): - if (not self.component.visible or - not self.component.is_in(event.x, event.y)): + if not self.component.visible or not self.component.is_in(event.x, event.y): return plots = get_hit_plots(self.component, event) @@ -71,8 +70,7 @@ def normal_left_down(self, event): self._selected_renderers.append(plot) elif plots: # User in single-select mode. - add_plot = any(plot not in self._selected_renderers - for plot in plots) + add_plot = any(plot not in self._selected_renderers for plot in plots) self._selected_renderers = [] if add_plot: self._selected_renderers.extend(plots) @@ -90,7 +88,7 @@ def normal_left_down(self, event): def _reset_selects(self, plots): """ Set all renderers to their default values. """ for plot in concat(_ensure_list(p) for p in plots.values()): - if not hasattr(plot, '_orig_alpha'): + if not hasattr(plot, "_orig_alpha"): plot._orig_alpha = plot.alpha plot._orig_line_width = plot.line_width plot.alpha = plot._orig_alpha @@ -99,7 +97,7 @@ def _reset_selects(self, plots): def _set_states(self, plots): """ Decorates a plot to indicate it is selected """ for plot in concat(_ensure_list(p) for p in plots.values()): - if not hasattr(plot, '_orig_alpha'): + if not hasattr(plot, "_orig_alpha"): # FIXME: These attributes should be put into the class def. plot._orig_alpha = plot.alpha plot._orig_line_width = plot.line_width diff --git a/chaco/tools/legend_tool.py b/chaco/tools/legend_tool.py index 99cdd14d6..aa1af4e91 100644 --- a/chaco/tools/legend_tool.py +++ b/chaco/tools/legend_tool.py @@ -7,7 +7,7 @@ class LegendTool(DragTool): - """ A tool for interacting with legends. + """A tool for interacting with legends. Attach this tool to a legend by setting the tool's **component** to the legend. @@ -20,23 +20,20 @@ class LegendTool(DragTool): #: the quadrant into which it is dropped. auto_align = Bool(True) - def is_draggable(self, x, y): - """ Returns whether the (x,y) position is in a region that is OK to + """Returns whether the (x,y) position is in a region that is OK to drag. Overrides DragTool. """ if self.component: legend = self.component - return (x >= legend.x and x <= legend.x2 and \ - y >= legend.y and y <= legend.y2) + return x >= legend.x and x <= legend.x2 and y >= legend.y and y <= legend.y2 else: return False - def drag_start(self, event): - """ Called when the drag operation starts. + """Called when the drag operation starts. Implements DragTool. """ @@ -46,7 +43,7 @@ def drag_start(self, event): event.handled = True def dragging(self, event): - """ This method is called for every mouse_move event that the tool + """This method is called for every mouse_move event that the tool receives while the user is dragging the mouse. Implements DragTool. Moves the legend by aligning it to a corner of its @@ -78,7 +75,7 @@ def dragging(self, event): legend.request_redraw() def drag_end(self, event): - """ Called when a mouse event causes the drag operation to end. + """Called when a mouse event causes the drag operation to end. Implements DragTool. """ diff --git a/chaco/tools/line_inspector.py b/chaco/tools/line_inspector.py index 8d7c51aef..d3a438e35 100644 --- a/chaco/tools/line_inspector.py +++ b/chaco/tools/line_inspector.py @@ -12,7 +12,7 @@ class LineInspector(BaseTool): - """ A simple tool to draw a line parallel to the index or the value axis of + """A simple tool to draw a line parallel to the index or the value axis of an X-Y plot. This tool supports only plots with a 1-D index. @@ -43,9 +43,9 @@ class LineInspector(BaseTool): #: The name of the metadata field to listen or write to. metadata_name = Str("selections") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Override default values of inherited traits in BaseTool - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: This tool is visible (overrides BaseTool). visible = True @@ -65,7 +65,7 @@ class LineInspector(BaseTool): _last_position = Trait(None, Any) def draw(self, gc, view_bounds=None): - """ Draws this tool on a graphics context. + """Draws this tool on a graphics context. Overrides BaseTool. """ @@ -91,7 +91,7 @@ def draw(self, gc, view_bounds=None): self._draw_vertical_line(gc, sx) elif sy is not None: self._draw_horizontal_line(gc, sy) - else: # self.axis == "value" + else: # self.axis == "value" if plot.orientation == "h" and sy is not None: self._draw_horizontal_line(gc, sy) elif sx is not None: @@ -101,13 +101,11 @@ def do_layout(self, *args, **kw): pass def overlay(self, component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on a graphics context. - """ + """Draws this component overlaid on a graphics context.""" self.draw(gc, view_bounds) def normal_mouse_move(self, event): - """ Handles the mouse being moved. - """ + """Handles the mouse being moved.""" if not self.is_interactive: return plot = self.component @@ -116,31 +114,28 @@ def normal_mouse_move(self, event): if isinstance(plot, BaseXYPlot): if self.write_metadata: if self.inspect_mode == "space": - index_coord, value_coord = \ - self._map_to_data(event.x, event.y) + index_coord, value_coord = self._map_to_data(event.x, event.y) plot.index.metadata[self.metadata_name] = index_coord plot.value.metadata[self.metadata_name] = value_coord else: - ndx = plot.map_index((event.x, event.y), - threshold=5.0, index_only=True) + ndx = plot.map_index( + (event.x, event.y), threshold=5.0, index_only=True + ) if ndx: plot.index.metadata[self.metadata_name] = ndx plot.value.metadata[self.metadata_name] = ndx elif isinstance(plot, Base2DPlot): if self.write_metadata: try: - old_x_data, old_y_data = \ - plot.index.metadata[self.metadata_name] + old_x_data, old_y_data = plot.index.metadata[self.metadata_name] except: old_x_data, old_y_data = (None, None) if self.inspect_mode == "space": if plot.orientation == "h": - x_coord, y_coord = \ - plot.map_data([(event.x, event.y)])[0] + x_coord, y_coord = plot.map_data([(event.x, event.y)])[0] else: - y_coord, x_coord = \ - plot.map_data([(event.x, event.y)])[0] + y_coord, x_coord = plot.map_data([(event.x, event.y)])[0] if self.axis == "index_x": metadata = x_coord, old_y_data elif self.axis == "index_y": @@ -149,11 +144,13 @@ def normal_mouse_move(self, event): raise ValueError(self.axis) else: if plot.orientation == "h": - x_ndx, y_ndx = plot.map_index((event.x, event.y), - threshold=5.0) + x_ndx, y_ndx = plot.map_index( + (event.x, event.y), threshold=5.0 + ) else: - y_ndx, x_ndx = plot.map_index((event.x, event.y), - threshold=5.0) + y_ndx, x_ndx = plot.map_index( + (event.x, event.y), threshold=5.0 + ) if self.axis == "index_x": metadata = x_ndx, old_y_data elif self.axis == "index_y": @@ -163,8 +160,7 @@ def normal_mouse_move(self, event): plot.request_redraw() def normal_mouse_leave(self, event): - """ Handles the mouse leaving the plot. - """ + """Handles the mouse leaving the plot.""" if not self.is_interactive: return self._last_position = None @@ -178,12 +174,12 @@ def normal_mouse_leave(self, event): plot.index.metadata.pop(self.metadata_name, None) plot.request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_screen_pts(self): - """ Returns the screen-space coordinates of the selected point on + """Returns the screen-space coordinates of the selected point on the plot component as a tuple (x, y). A dimension that doesn't have a selected point has the value None at @@ -231,7 +227,7 @@ def _get_screen_pts(self): return retval[1], retval[0] def _map_to_data(self, x, y): - """ Returns the data space coordinates of the given x and y. + """Returns the data space coordinates of the given x and y. Takes into account orientation of the plot and the axis setting. """ @@ -246,7 +242,7 @@ def _map_to_data(self, x, y): return index, value def _draw_vertical_line(self, gc, sx): - """ Draws a vertical line through screen point (sx,sy) having the height + """Draws a vertical line through screen point (sx,sy) having the height of the tool's component. """ if sx < self.component.x or sx > self.component.x2: @@ -261,7 +257,7 @@ def _draw_vertical_line(self, gc, sx): gc.stroke_path() def _draw_horizontal_line(self, gc, sy): - """ Draws a horizontal line through screen point (sx,sy) having the + """Draws a horizontal line through screen point (sx,sy) having the width of the tool's component. """ if sy < self.component.y or sy > self.component.y2: diff --git a/chaco/tools/line_segment_tool.py b/chaco/tools/line_segment_tool.py index 1be5eb29b..6c3eef1ff 100644 --- a/chaco/tools/line_segment_tool.py +++ b/chaco/tools/line_segment_tool.py @@ -13,9 +13,8 @@ from chaco.abstract_overlay import AbstractOverlay - class LineSegmentTool(AbstractOverlay): - """ The base class for tools that allow the user to draw a + """The base class for tools that allow the user to draw a series of points connected by lines. """ @@ -72,17 +71,16 @@ class LineSegmentTool(AbstractOverlay): #: Cursor shape for moving points. move_cursor = Pointer("sizing") - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Traits inherited from Component - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The tool is initially invisible, because there is nothing to draw. visible = Bool(False) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def __init__(self, component=None, **kwtraits): if "component" in kwtraits: @@ -92,12 +90,12 @@ def __init__(self, component=None, **kwtraits): self.reset() self.line.line_dash = (4.0, 2.0) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Drawing tool methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def reset(self): - """ Resets the tool, throwing away any points, and making the tool + """Resets the tool, throwing away any points, and making the tool invisible. """ self.points = [] @@ -117,38 +115,36 @@ def _deactivate(self, component=None): """ self.reset() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # PointLine methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def add_point(self, point): - """ Given a screen-space *point* (x,y), adds the corresponding data + """Given a screen-space *point* (x,y), adds the corresponding data space point to the list for this tool. """ self.points.append(self._map_data(point)) def get_point(self, index): - """ Retrieves the indexed point and returns its screen space value. - """ + """Retrieves the indexed point and returns its screen space value.""" return self._map_screen(self.points[index]) def set_point(self, index, point): - """ Sets the data-space *index* for a screen-space *point*. - """ + """Sets the data-space *index* for a screen-space *point*.""" self.points[index] = self._map_data(point) def remove_point(self, index): - """ Removes the point for a given *index* from this tool's list of + """Removes the point for a given *index* from this tool's list of points. """ del self.points[index] - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # "normal" state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def normal_left_down(self, event): - """ Handles the left mouse button being pressed while the tool is + """Handles the left mouse button being pressed while the tool is in the 'normal' state. For an existing point, if the user is pressing the Control key, the @@ -179,7 +175,7 @@ def normal_left_down(self, event): self.dragging_mouse_move(event) def normal_mouse_move(self, event): - """ Handles the user moving the mouse in the 'normal' state. + """Handles the user moving the mouse in the 'normal' state. When the user moves the cursor over an existing point, if the Control key is pressed, the cursor changes to the **delete_cursor**, indicating @@ -203,13 +199,12 @@ def normal_mouse_move(self, event): self.request_redraw() def normal_draw(self, gc): - """ Draws the line. - """ + """Draws the line.""" self.line.points = list(self.component.map_screen(array(self.points))) self.line._draw(gc) def normal_key_pressed(self, event): - """ Handles the user pressing a key in the 'normal' state. + """Handles the user pressing a key in the 'normal' state. If the user presses the Enter key, the tool is reset. """ @@ -218,15 +213,14 @@ def normal_key_pressed(self, event): self.reset() def normal_mouse_leave(self, event): - """ Handles the user moving the cursor away from the tool area. - """ + """Handles the user moving the cursor away from the tool area.""" event.window.set_pointer("arrow") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # "dragging" state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def dragging_mouse_move(self, event): - """ Handles the user moving the mouse while in the 'dragging' state. + """Handles the user moving the mouse while in the 'dragging' state. The screen is updated to show the new mouse position as the end of the line segment being drawn. @@ -237,12 +231,11 @@ def dragging_mouse_move(self, event): self.request_redraw() def dragging_draw(self, gc): - """ Draws the polygon in the 'dragging' state. - """ + """Draws the polygon in the 'dragging' state.""" self.line._draw(gc) def dragging_left_up(self, event): - """ Handles the left mouse coming up in the 'dragging' state. + """Handles the left mouse coming up in the 'dragging' state. Switches to 'normal' state. """ @@ -251,7 +244,7 @@ def dragging_left_up(self, event): self.updated = self def dragging_key_pressed(self, event): - """ Handles a key being pressed in the 'dragging' state. + """Handles a key being pressed in the 'dragging' state. If the key is "Esc", the drag operation is canceled. """ @@ -259,7 +252,7 @@ def dragging_key_pressed(self, event): self._cancel_drag() def dragging_mouse_leave(self, event): - """ Handles the mouse leaving the tool area in the 'dragging' state. + """Handles the mouse leaving the tool area in the 'dragging' state. The drag is canceled and the cursor changes to an arrow. """ @@ -267,8 +260,7 @@ def dragging_mouse_leave(self, event): event.window.set_pointer("arrow") def _cancel_drag(self): - """ Cancels a drag operation. - """ + """Cancels a drag operation.""" if self._dragged != None: if self._drag_new_point: # Only remove the point if it was a newly-placed point @@ -278,39 +270,40 @@ def _cancel_drag(self): self.event_state = "normal" self.request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # override AbstractOverlay methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def overlay(self, component, gc, view_bounds, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Implements AbstractOverlay. """ draw_func = getattr(self, self.event_state + "_draw", None) if draw_func: with gc: - gc.clip_to_rect(component.x, component.y, component.width-1, component.height-1) + gc.clip_to_rect( + component.x, component.y, component.width - 1, component.height - 1 + ) draw_func(gc) def request_redraw(self): - """ Requests that the component redraw itself. + """Requests that the component redraw itself. Overrides Enable Component. """ self.component.invalidate_draw() self.component.request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _map_data(self, point): - """ Maps values from screen space into data space. - """ + """Maps values from screen space into data space.""" x_mapper = self.component.x_mapper y_mapper = self.component.y_mapper - if self.component.orientation == 'h': + if self.component.orientation == "h": ndx = x_mapper.map_data(point[0]) val = y_mapper.map_data(point[1]) else: @@ -319,11 +312,10 @@ def _map_data(self, point): return (ndx, val) def _map_screen(self, point): - """ Maps values from data space into screen space. - """ + """Maps values from data space into screen space.""" x_mapper = self.component.x_mapper y_mapper = self.component.y_mapper - if self.component.orientation == 'h': + if self.component.orientation == "h": x = x_mapper.map_screen(point[0]) y = y_mapper.map_screen(point[1]) else: @@ -331,17 +323,16 @@ def _map_screen(self, point): y = y_mapper.map_screen(point[0]) return (x, y) - def _is_near_point(self, point, event): - """ Determines if the pointer is near a specified point. - """ + """Determines if the pointer is near a specified point.""" event_point = (event.x, event.y) - return ((abs( point[0] - event_point[0] ) + \ - abs( point[1] - event_point[1] )) <= self.proximity_distance) + return ( + abs(point[0] - event_point[0]) + abs(point[1] - event_point[1]) + ) <= self.proximity_distance def _over_point(self, event, points): - """ Return the index of a point in *points* that *event* is 'over'. + """Return the index of a point in *points* that *event* is 'over'. Returns None if there is no such point. """ @@ -359,9 +350,9 @@ def _finalize_selection(self): """ pass - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _component_changed(self, old, new): if new: diff --git a/chaco/tools/move_tool.py b/chaco/tools/move_tool.py index 5dfe0ed72..ba97184c0 100644 --- a/chaco/tools/move_tool.py +++ b/chaco/tools/move_tool.py @@ -6,14 +6,13 @@ class MoveTool(DragTool): - """ A tool for moving a plot component. - """ + """A tool for moving a plot component.""" # The (x,y) offset of the start of the drag relative to the component. - _offset = Tuple((0,0)) + _offset = Tuple((0, 0)) def drag_start(self, event): - """ Called when the drag operation starts. + """Called when the drag operation starts. Implements DragTool. """ @@ -21,7 +20,7 @@ def drag_start(self, event): event.handled = True def dragging(self, event): - """ This method is called for every mouse_move event that the tool + """This method is called for every mouse_move event that the tool receives while the user is dragging the mouse. Implements DragTool. Moves the component. @@ -38,4 +37,3 @@ def dragging(self, event): c.hgrid.invalidate() event.handled = True c.request_redraw() - diff --git a/chaco/tools/pan_tool.py b/chaco/tools/pan_tool.py index 559b56a0a..3cbbb9d46 100644 --- a/chaco/tools/pan_tool.py +++ b/chaco/tools/pan_tool.py @@ -9,7 +9,7 @@ class PanTool(BaseTool): - """ A tool that enables the user to pan a plot by clicking a mouse + """A tool that enables the user to pan a plot by clicking a mouse button and dragging. """ @@ -62,10 +62,9 @@ class PanTool(BaseTool): # set programmatically. _auto_constrain = Bool(False) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Inherited BaseTool traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The tool does not have a visual representation (overrides #: BaseTool). @@ -78,25 +77,21 @@ class PanTool(BaseTool): event_state = Enum("normal", "panning") def normal_key_pressed(self, event): - """ Handles a key being pressed when the tool is in the 'normal' + """Handles a key being pressed when the tool is in the 'normal' state. """ if self.pan_keys_step == 0.0: return - src = self.component.bounds[0]/2, self.component.bounds[1]/2 + src = self.component.bounds[0] / 2, self.component.bounds[1] / 2 dest = src if self.pan_left_key.match(event): - dest = (src[0] - self.pan_keys_step, - src[1]) + dest = (src[0] - self.pan_keys_step, src[1]) elif self.pan_right_key.match(event): - dest = (src[0] + self.pan_keys_step, - src[1]) + dest = (src[0] + self.pan_keys_step, src[1]) elif self.pan_down_key.match(event): - dest = (src[0], - src[1] - self.pan_keys_step) + dest = (src[0], src[1] - self.pan_keys_step) elif self.pan_up_key.match(event): - dest = (src[0], - src[1] + self.pan_keys_step) + dest = (src[0], src[1] + self.pan_keys_step) if src != dest: self._original_xy = src event.x = dest[0] @@ -104,7 +99,7 @@ def normal_key_pressed(self, event): self.panning_mouse_move(event) def normal_left_down(self, event): - """ Handles the left mouse button being pressed when the tool is in + """Handles the left mouse button being pressed when the tool is in the 'normal' state. Starts panning if the left mouse button is the drag button. @@ -113,7 +108,7 @@ def normal_left_down(self, event): self._start_pan(event) def normal_right_down(self, event): - """ Handles the right mouse button being pressed when the tool is in + """Handles the right mouse button being pressed when the tool is in the 'normal' state. Starts panning if the right mouse button is the drag button. @@ -122,7 +117,7 @@ def normal_right_down(self, event): self._start_pan(event) def normal_middle_down(self, event): - """ Handles the middle mouse button being pressed when the tool is in + """Handles the middle mouse button being pressed when the tool is in the 'normal' state. Starts panning if the middle mouse button is the drag button. @@ -131,7 +126,7 @@ def normal_middle_down(self, event): self._start_pan(event) def panning_left_up(self, event): - """ Handles the left mouse button coming up when the tool is in the + """Handles the left mouse button coming up when the tool is in the 'panning' state. Stops panning if the left mouse button is the drag button. @@ -140,7 +135,7 @@ def panning_left_up(self, event): self._end_pan(event) def panning_right_up(self, event): - """ Handles the right mouse button coming up when the tool is in the + """Handles the right mouse button coming up when the tool is in the 'panning' state. Stops panning if the right mouse button is the drag button. @@ -149,7 +144,7 @@ def panning_right_up(self, event): self._end_pan(event) def panning_middle_up(self, event): - """ Handles the middle mouse button coming up when the tool is in the + """Handles the middle mouse button coming up when the tool is in the 'panning' state. Stops panning if the middle mouse button is the drag button. @@ -158,7 +153,7 @@ def panning_middle_up(self, event): self._end_pan(event) def panning_mouse_move(self, event): - """ Handles the mouse being moved when the tool is in the 'panning' + """Handles the mouse being moved when the tool is in the 'panning' state. """ plot = self.component @@ -192,9 +187,11 @@ def panning_mouse_move(self, event): # values. As a first approximation, we're just going to # use a linear approximation, which works perfectly for # linear mappers (which is used 99% of the time). - data = [arr for arr in - (source.get_data() for source in mapper.range.sources) - if arr.size > 0] + data = [ + arr + for arr in (source.get_data() for source in mapper.range.sources) + if arr.size > 0 + ] if domain_min is None: if self.restrict_to_data: domain_min = min([arr.min() for arr in data]) @@ -231,7 +228,7 @@ def panning_mouse_move(self, event): plot.request_redraw() def panning_mouse_leave(self, event): - """ Handles the mouse leaving the plot when the tool is in the 'panning' + """Handles the mouse leaving the plot when the tool is in the 'panning' state. Ends panning. diff --git a/chaco/tools/pan_tool2.py b/chaco/tools/pan_tool2.py index 34c4941a9..02ab7caf3 100644 --- a/chaco/tools/pan_tool2.py +++ b/chaco/tools/pan_tool2.py @@ -1,4 +1,3 @@ - from numpy import inf from enable.api import Pointer @@ -7,7 +6,7 @@ class PanTool(DragTool): - """ An implementation of a pan tool based on the DragTool instead of + """An implementation of a pan tool based on the DragTool instead of a bare BaseTool """ @@ -47,9 +46,9 @@ class PanTool(DragTool): # set programmatically. _auto_constrain = Bool(False) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Inherited BaseTool traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The tool does not have a visual representation (overrides # BaseTool). @@ -58,7 +57,6 @@ class PanTool(DragTool): # The tool is not visible (overrides BaseTool). visible = False - def drag_start(self, event): """ Called when the drag operation starts """ self._start_pan(event) @@ -68,12 +66,14 @@ def dragging(self, event): if self._auto_constrain and self.constrain_direction is None: # Determine the constraint direction - if abs(event.x - self._original_xy[0]) > abs(event.y - self._original_xy[1]): + if abs(event.x - self._original_xy[0]) > abs( + event.y - self._original_xy[1] + ): self.constrain_direction = "x" else: self.constrain_direction = "y" - for direction, bound_name, ndx in [("x","width",0), ("y","height",1)]: + for direction, bound_name, ndx in [("x", "width", 0), ("y", "height", 1)]: if not self.constrain or self.constrain_direction == direction: mapper = getattr(plot, direction + "_mapper") range = mapper.range @@ -83,7 +83,7 @@ def dragging(self, event): screenlow, screenhigh = mapper.screen_bounds screendelta = self.speed * (eventpos - origpos) - #if getattr(plot, direction + "_direction", None) == "flipped": + # if getattr(plot, direction + "_direction", None) == "flipped": # screendelta = -screendelta newlow = mapper.map_data(screenlow - screendelta) @@ -98,12 +98,16 @@ def dragging(self, event): # linear mappers (which is used 99% of the time). if domain_min is None: if self.restrict_to_data: - domain_min = min([source.get_data().min() for source in range.sources]) + domain_min = min( + [source.get_data().min() for source in range.sources] + ) else: domain_min = -inf if domain_max is None: if self.restrict_to_data: - domain_max = max([source.get_data().max() for source in range.sources]) + domain_max = max( + [source.get_data().max() for source in range.sources] + ) else: domain_max = inf if (newlow <= domain_min) and (newhigh >= domain_max): diff --git a/chaco/tools/point_marker.py b/chaco/tools/point_marker.py index e50db9c4a..7e5d3733b 100755 --- a/chaco/tools/point_marker.py +++ b/chaco/tools/point_marker.py @@ -11,7 +11,7 @@ class PointMarker(BaseTool): - """ This tool looks at an XY plot's index data source and draws a + """This tool looks at an XY plot's index data source and draws a line corresponding to the index indicated by the "selections" metadata. """ @@ -31,7 +31,7 @@ class PointMarker(BaseTool): line_width = Float(1.0) def draw(self, gc, view_bounds=None): - """ Draws this tool on a graphics context. + """Draws this tool on a graphics context. Implements BaseTool. """ @@ -54,28 +54,28 @@ def draw(self, gc, view_bounds=None): self._draw_vertical_lines(gc, screen_pts) else: self._draw_horizontal_lines(gc, screen_pts) - else: # self.axis == "value" + else: # self.axis == "value" if plot.orientation == "h": self._draw_horizontal_lines(gc, screen_pts) else: self._draw_vertical_lines(gc, screen_pts) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _draw_vertical_lines(self, gc, points): with gc: gc.set_stroke_color(self.color_) for pt in points: - gc.move_to(int(pt[0])+0.5, self.component.y) - gc.line_to(int(pt[0])+0.5, self.component.y2) + gc.move_to(int(pt[0]) + 0.5, self.component.y) + gc.line_to(int(pt[0]) + 0.5, self.component.y2) gc.stroke_path() def _draw_horizontal_lines(self, gc, points): with gc: gc.set_stroke_color(self.color_) for pt in points: - gc.move_to(self.component.x, int(pt[1])+0.5) - gc.line_to(self.component.x2, int(pt[1])+0.5) + gc.move_to(self.component.x, int(pt[1]) + 0.5) + gc.line_to(self.component.x2, int(pt[1]) + 0.5) gc.stroke_path() diff --git a/chaco/tools/range_selection.py b/chaco/tools/range_selection.py index 113ad8d8d..590388077 100644 --- a/chaco/tools/range_selection.py +++ b/chaco/tools/range_selection.py @@ -4,8 +4,21 @@ from numpy import array # Enthought library imports -from traits.api import Any, Array, ArrayOrNone, Bool, Enum, Event, Float, \ - Instance, Int, List, Property, Str, Trait +from traits.api import ( + Any, + Array, + ArrayOrNone, + Bool, + Enum, + Event, + Float, + Instance, + Int, + List, + Property, + Str, + Trait, +) from enable.api import KeySpec # Chaco imports @@ -13,7 +26,7 @@ class RangeSelection(AbstractController): - """ Selects a range along the index or value axis. + """Selects a range along the index or value axis. The user right-click-drags to select a region, which stays selected until the user left-clicks to deselect. @@ -62,7 +75,7 @@ class RangeSelection(AbstractController): #: The user moving (not resizing) the selection range. event_state = Enum("normal", "selecting", "selected", "moving") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Traits for overriding default object relationships # # By default, the RangeSelection assumes that self.component is a plot @@ -70,7 +83,7 @@ class RangeSelection(AbstractController): # case, then any (or all) three of these can be overriden by directly # assigning values to them. To unset them and have them revert to default # behavior, assign "None" to them. - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The plot associated with this tool By default, this is just #: self.component. @@ -87,9 +100,9 @@ class RangeSelection(AbstractController): #: List of listeners that listen to selection events. listeners = List - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Configuring interaction control - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: Can the user resize the selection once it has been drawn? enable_resize = Bool(True) @@ -116,9 +129,9 @@ class RangeSelection(AbstractController): #: as opposed to overwriting it. append_key = Instance(KeySpec, args=(None, "control")) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The value of the override plot to use, if any. If None, then uses # self.component. @@ -141,10 +154,10 @@ class RangeSelection(AbstractController): # The end of the selection that is being actively modified by the mouse. _drag_edge = Enum("high", "low") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # These record the mouse position when the user is moving (not resizing) # the selection - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The position of the initial user click for moving the selection. _down_point = Array # (x,y) @@ -155,12 +168,12 @@ class RangeSelection(AbstractController): # The original selection when the mouse went down to move the selection. _original_selection = Any - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Public methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def deselect(self, event=None): - """ Deselects the highlighted region. + """Deselects the highlighted region. This method essentially resets the tool. It takes the event causing the deselection as an optional argument. @@ -173,12 +186,12 @@ def deselect(self, event=None): event.window.set_pointer("arrow") event.handled = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers for the "selected" event state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def selected_left_down(self, event): - """ Handles the left mouse button being pressed when the tool is in + """Handles the left mouse button being pressed when the tool is in the 'selected' state. If the user is allowed to resize the selection, and the event occurred @@ -204,15 +217,15 @@ def selected_left_down(self, event): mouse_coord = tmp[ndx] if self.enable_resize: - if (abs(mouse_coord - high) <= self.resize_margin) or \ - (abs(mouse_coord - low) <= self.resize_margin): + if (abs(mouse_coord - high) <= self.resize_margin) or ( + abs(mouse_coord - low) <= self.resize_margin + ): return self.selected_right_down(event) if low <= tmp[ndx] <= high: self.event_state = "moving" self._down_point = array([event.x, event.y]) - self._down_data_coord = \ - self.mapper.map_data(self._down_point)[ndx] + self._down_data_coord = self.mapper.map_data(self._down_point)[ndx] self._original_selection = array(self.selection) elif self.allow_deselection: self.deselect(event) @@ -223,7 +236,7 @@ def selected_left_down(self, event): event.handled = True def selected_right_down(self, event): - """ Handles the right mouse button being pressed when the tool is in + """Handles the right mouse button being pressed when the tool is in the 'selected' state. If the user is allowed to resize the selection, and the event occurred @@ -252,7 +265,7 @@ def selected_right_down(self, event): self.event_state = "selecting" self._drag_edge = "low" self.selecting_mouse_move(event) - #elif self.allow_deselection: + # elif self.allow_deselection: # self.deselect(event) else: # Treat this as a combination deselect + right down @@ -265,7 +278,7 @@ def selected_right_down(self, event): event.handled = True def selected_mouse_move(self, event): - """ Handles the mouse moving when the tool is in the 'selected' srate. + """Handles the mouse moving when the tool is in the 'selected' srate. If the user is allowed to resize the selection, and the event occurred within the resize margin of an endpoint, then the cursor @@ -282,27 +295,29 @@ def selected_mouse_move(self, event): tmp = (event.x, event.y) ndx = self.axis_index mouse_coord = tmp[ndx] - if abs(mouse_coord - end) <= self.resize_margin or \ - abs(mouse_coord - start) <= self.resize_margin: + if ( + abs(mouse_coord - end) <= self.resize_margin + or abs(mouse_coord - start) <= self.resize_margin + ): self._set_sizing_cursor(event) return event.window.set_pointer("arrow") event.handled = True def selected_mouse_leave(self, event): - """ Handles the mouse leaving the plot when the tool is in the + """Handles the mouse leaving the plot when the tool is in the 'selected' state. Sets the cursor to an arrow. """ event.window.set_pointer("arrow") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers for the "moving" event state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def moving_left_up(self, event): - """ Handles the left mouse button coming up when the tool is in the + """Handles the left mouse button coming up when the tool is in the 'moving' state. Switches the tool to the 'selected' state. @@ -316,7 +331,7 @@ def moving_left_up(self, event): event.handled = True def moving_mouse_move(self, event): - """ Handles the mouse moving when the tool is in the 'moving' state. + """Handles the mouse moving when the tool is in the 'moving' state. Moves the selection range by an amount corresponding to the amount that the mouse has moved since its button was pressed. If the new @@ -326,8 +341,7 @@ def moving_mouse_move(self, event): cur_point = array([event.x, event.y]) cur_data_point = self.mapper.map_data(cur_point)[self.axis_index] original_selection = self._original_selection - new_selection = original_selection + (cur_data_point - - self._down_data_coord) + new_selection = original_selection + (cur_data_point - self._down_data_coord) selection_data_width = original_selection[1] - original_selection[0] range = self.mapper.range @@ -342,7 +356,7 @@ def moving_mouse_move(self, event): event.handled = True def moving_mouse_leave(self, event): - """ Handles the mouse leaving the plot while the tool is in the + """Handles the mouse leaving the plot while the tool is in the 'moving' state. If the mouse was within the selection region when it left, the method @@ -369,12 +383,12 @@ def moving_mouse_enter(self, event): if not event.left_down: return self.moving_left_up(event) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers for the "normal" event state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def normal_left_down(self, event): - """ Handles the left mouse button being pressed when the tool is in + """Handles the left mouse button being pressed when the tool is in the 'normal' state. If the tool allows the left mouse button to start a selection, then @@ -384,7 +398,7 @@ def normal_left_down(self, event): return self.normal_right_down(event) def normal_right_down(self, event): - """ Handles the right mouse button being pressed when the tool is in + """Handles the right mouse button being pressed when the tool is in the 'normal' state. Puts the tool into 'selecting' mode, changes the cursor to show that it @@ -403,12 +417,12 @@ def normal_right_down(self, event): self.selection_mode = "set" self.selecting_mouse_move(event) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers for the "selecting" event state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def selecting_mouse_move(self, event): - """ Handles the mouse being moved when the tool is in the 'selecting' + """Handles the mouse being moved when the tool is in the 'selecting' state. Expands the selection range at the appropriate end, based on the new @@ -463,7 +477,7 @@ def selecting_button_up(self, event): event.handled = True def selecting_right_up(self, event): - """ Handles the right mouse button coming up when the tool is in the + """Handles the right mouse button coming up when the tool is in the 'selecting' state. Switches the tool to the 'selected' state and completes the selection. @@ -471,7 +485,7 @@ def selecting_right_up(self, event): self.selecting_button_up(event) def selecting_left_up(self, event): - """ Handles the left mouse button coming up when the tool is in the + """Handles the left mouse button coming up when the tool is in the 'selecting' state. Switches the tool to the 'selected' state. @@ -481,7 +495,7 @@ def selecting_left_up(self, event): self.selecting_button_up(event) def selecting_mouse_leave(self, event): - """ Handles the mouse leaving the plot when the tool is in the + """Handles the mouse leaving the plot when the tool is in the 'selecting' state. Determines whether the event's position is outside the component's @@ -513,7 +527,7 @@ def selecting_mouse_leave(self, event): self.component.request_redraw() def selecting_mouse_enter(self, event): - """ Handles the mouse entering the plot when the tool is in the + """Handles the mouse entering the plot when the tool is in the 'selecting' state. If the mouse does not have the right mouse button down, this event @@ -528,9 +542,9 @@ def selecting_mouse_enter(self, event): else: self._set_sizing_cursor(event) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property getter/setters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_plot(self): if self._plot is not None: @@ -578,16 +592,16 @@ def _set_selection(self, val): datasource.metadata_changed = {mdname: val} # Set the selection mask on the datasource - selection_masks = \ - datasource.metadata.setdefault(self.mask_metadata_name, []) + selection_masks = datasource.metadata.setdefault( + self.mask_metadata_name, [] + ) for index in range(len(selection_masks)): if id(selection_masks[index]) == id(self._selection_mask): del selection_masks[index] break # Set the selection mode on the datasource - datasource.metadata[self.selection_mode_metadata_name] = \ - self.selection_mode + datasource.metadata[self.selection_mode_metadata_name] = self.selection_mode if val is not None: low, high = val @@ -603,13 +617,12 @@ def _set_selection(self, val): if hasattr(l, "set_value_selection"): l.set_value_selection(val) - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_selection_screencoords(self): - """ Returns a tuple of (x1, x2) screen space coordinates of the start + """Returns a tuple of (x1, x2) screen space coordinates of the start and end selection points. If there is no current selection, then it returns None. @@ -621,7 +634,7 @@ def _get_selection_screencoords(self): return None def _set_sizing_cursor(self, event): - """ Sets the correct cursor shape on the window of the event, given the + """Sets the correct cursor shape on the window of the event, given the tool's orientation and axis. """ if self.axis_index == 0: @@ -632,7 +645,7 @@ def _set_sizing_cursor(self, event): event.window.set_pointer("size top") def _get_axis_coord(self, event, axis="index"): - """ Returns the coordinate of the event along the axis of interest + """Returns the coordinate of the event along the axis of interest to this tool (or along the orthogonal axis, if axis="value"). """ event_pos = (event.x, event.y) @@ -642,7 +655,7 @@ def _get_axis_coord(self, event, axis="index"): return event_pos[1 - self.axis_index] def _determine_axis(self): - """ Determines whether the index of the coordinate along this tool's + """Determines whether the index of the coordinate along this tool's axis of interest is the first or second element of an (x,y) coordinate tuple. @@ -654,7 +667,7 @@ def _determine_axis(self): return 0 else: return 1 - else: # self.axis == "value" + else: # self.axis == "value" if self.plot.orientation == "h": return 1 else: @@ -665,8 +678,6 @@ def __mapper_changed(self, event): def _axis_changed(self, old, new): if old is not None: - self.plot.observe( - self.__mapper_changed, old + "_mapper", remove=True - ) + self.plot.observe(self.__mapper_changed, old + "_mapper", remove=True) if new is not None: self.plot.observe(self.__mapper_changed, new + "_mapper") diff --git a/chaco/tools/range_selection_2d.py b/chaco/tools/range_selection_2d.py index 6a2a74b06..9068afbf7 100644 --- a/chaco/tools/range_selection_2d.py +++ b/chaco/tools/range_selection_2d.py @@ -8,20 +8,19 @@ class RangeSelection2D(RangeSelection): - """ Selects a range along the index or value axis for plots on 2D data, + """Selects a range along the index or value axis for plots on 2D data, such as image plots The user right-click-drags to select a region, which stays selected until the user left-clicks to deselect. """ - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers for the "selected" event state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def selected_left_down(self, event): - """ Handles the left mouse button being pressed when the tool is in + """Handles the left mouse button being pressed when the tool is in the 'selected' state. If the user is allowed to resize the selection, and the event occurred @@ -44,14 +43,17 @@ def selected_left_down(self, event): mouse_coord = tmp[ndx] if self.enable_resize: - if (abs(mouse_coord - high) <= self.resize_margin) or \ - (abs(mouse_coord - low) <= self.resize_margin): + if (abs(mouse_coord - high) <= self.resize_margin) or ( + abs(mouse_coord - low) <= self.resize_margin + ): return self.selected_right_down(event) if tmp[self.axis_index] >= low and tmp[self.axis_index] <= high: self.event_state = "moving" self._down_point = numpy.array([event.x, event.y]) - self._down_data_coord = self._map_data([self._down_point])[0][self.axis_index] + self._down_data_coord = self._map_data([self._down_point])[0][ + self.axis_index + ] self._original_selection = numpy.array(self.selection) elif self.allow_deselection: @@ -63,7 +65,7 @@ def selected_left_down(self, event): event.handled = True def selected_right_down(self, event): - """ Handles the right mouse button being pressed when the tool is in + """Handles the right mouse button being pressed when the tool is in the 'selected' state. If the user is allowed to resize the selection, and the event occurred @@ -105,7 +107,7 @@ def selected_right_down(self, event): event.handled = True def selected_mouse_move(self, event): - """ Handles the mouse moving when the tool is in the 'selected' state. + """Handles the mouse moving when the tool is in the 'selected' state. If the user is allowed to resize the selection, and the event occurred within the resize margin of an endpoint, then the cursor @@ -121,19 +123,21 @@ def selected_mouse_move(self, event): tmp = (event.x, event.y) ndx = self._determine_axis() mouse_coord = tmp[ndx] - if abs(mouse_coord - end) <= self.resize_margin or \ - abs(mouse_coord - start) <= self.resize_margin: + if ( + abs(mouse_coord - end) <= self.resize_margin + or abs(mouse_coord - start) <= self.resize_margin + ): self._set_sizing_cursor(event) return event.window.set_pointer("arrow") event.handled = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers for the "moving" event state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def moving_mouse_move(self, event): - """ Handles the mouse moving when the tool is in the 'moving' state. + """Handles the mouse moving when the tool is in the 'moving' state. Moves the selection range by an amount corresponding to the amount that the mouse has moved since its button was pressed. If the new @@ -143,8 +147,9 @@ def moving_mouse_move(self, event): cur_point = numpy.array([event.x, event.y]) cur_data_point = self._map_data([cur_point])[0] original_selection = self._original_selection - new_selection = original_selection + (cur_data_point[self.axis_index] \ - - self._down_data_coord) + new_selection = original_selection + ( + cur_data_point[self.axis_index] - self._down_data_coord + ) selection_data_width = original_selection[1] - original_selection[0] range = self.mapper.range @@ -160,12 +165,12 @@ def moving_mouse_move(self, event): self.component.request_redraw() event.handled = True - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers for the "normal" event state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def normal_right_down(self, event): - """ Handles the right mouse button being pressed when the tool is in + """Handles the right mouse button being pressed when the tool is in the 'normal' state. Puts the tool into 'selecting' mode, changes the cursor to show that it @@ -175,7 +180,7 @@ def normal_right_down(self, event): x_pos = self._get_axis_coord(event, "index") y_pos = self._get_axis_coord(event, "value") self._down_point = numpy.array([x_pos, y_pos]) - mapped_pos = self._map_data([(x_pos,y_pos)])[0][self.axis_index] + mapped_pos = self._map_data([(x_pos, y_pos)])[0][self.axis_index] self.selection = (mapped_pos, mapped_pos) @@ -183,12 +188,12 @@ def normal_right_down(self, event): self.event_state = "selecting" self.selecting_mouse_move(event) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Event handlers for the "selecting" event state - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def selecting_mouse_move(self, event): - """ Handles the mouse being moved when the tool is in the 'selecting' + """Handles the mouse being moved when the tool is in the 'selecting' state. Expands the selection range at the appropriate end, based on the new @@ -202,7 +207,7 @@ def selecting_mouse_move(self, event): if tmp >= low and tmp <= high: x_pos = self._get_axis_coord(event, "index") y_pos = self._get_axis_coord(event, "value") - new_edge = self._map_data([(x_pos,y_pos)])[0][self.axis_index] + new_edge = self._map_data([(x_pos, y_pos)])[0][self.axis_index] if self._drag_edge == "high": low_val = self.selection[0] @@ -211,7 +216,9 @@ def selecting_mouse_move(self, event): # if it appears that only 1 point is selected, move one # edge over a pixel if new_edge == low_val: - new_edge = self._map_data([(x_pos+1,y_pos+1)])[0][self.axis_index] + new_edge = self._map_data([(x_pos + 1, y_pos + 1)])[0][ + self.axis_index + ] if new_edge > low_val: self.selection = (low_val, new_edge) @@ -225,7 +232,9 @@ def selecting_mouse_move(self, event): # if it appears that only 1 point is selected, move one # edge over a pixel if new_edge == high_val: - new_edge = self._map_data([(x_pos-1,y_pos-1)])[0][self.axis_index] + new_edge = self._map_data([(x_pos - 1, y_pos - 1)])[0][ + self.axis_index + ] if new_edge < high_val: self.selection = (new_edge, high_val) @@ -237,7 +246,7 @@ def selecting_mouse_move(self, event): event.handled = True def selecting_mouse_leave(self, event): - """ Handles the mouse leaving the plot when the tool is in the + """Handles the mouse leaving the plot when the tool is in the 'selecting' state. Determines whether the event's position is outside the component's @@ -253,12 +262,12 @@ def selecting_mouse_leave(self, event): pos = self._get_axis_coord(event) if pos >= high: - if self.axis == 'index': + if self.axis == "index": selection_high = self._map_data([(high, 0)])[0][self.axis_index] else: selection_high = self._map_data([(0, high)])[0][self.axis_index] elif pos <= low: - if self.axis == 'index': + if self.axis == "index": selection_low = self._map_data([(low, 0)])[0][self.axis_index] else: selection_low = self._map_data([(0, low)])[0][self.axis_index] @@ -267,9 +276,9 @@ def selecting_mouse_leave(self, event): event.window.set_pointer("arrow") self.component.request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _map_data(self, screen_pts): return self.mapper.map_data(screen_pts) @@ -278,17 +287,21 @@ def _map_screen(self, data_pts): return self.mapper.map_screen(data_pts) def _get_selection_screencoords(self): - """ Returns a tuple of (x1, x2) screen space coordinates of the start + """Returns a tuple of (x1, x2) screen space coordinates of the start and end selection points. If there is no current selection, then it returns None. """ selection = self.selection if selection is not None and len(selection) == 2: - if self.axis == 'index': - return [x for x,y in self._map_screen([(x,0) for x in self.selection])] + if self.axis == "index": + return [ + x for x, y in self._map_screen([(x, 0) for x in self.selection]) + ] else: - return [y for x,y in self._map_screen([(0,y) for y in self.selection])] + return [ + y for x, y in self._map_screen([(0, y) for y in self.selection]) + ] else: return None diff --git a/chaco/tools/range_selection_overlay.py b/chaco/tools/range_selection_overlay.py index 9cf161557..00b36bb2c 100644 --- a/chaco/tools/range_selection_overlay.py +++ b/chaco/tools/range_selection_overlay.py @@ -7,8 +7,7 @@ # Enthought library imports from enable.api import ColorTrait, LineStyle -from traits.api import Enum, Float, Property, Str, Instance, \ - cached_property +from traits.api import Enum, Float, Property, Str, Instance, cached_property from chaco.abstract_overlay import AbstractOverlay from chaco.base import arg_find_runs from chaco.grid_mapper import GridMapper @@ -16,7 +15,7 @@ class RangeSelectionOverlay(AbstractOverlay): - """ Highlights the selection region on a component. + """Highlights the selection region on a component. Looks at a given metadata field of self.component for regions to draw as selected. @@ -27,7 +26,7 @@ class RangeSelectionOverlay(AbstractOverlay): #: Mapping from screen space to data space. By default, it is just #: self.component. - plot = Property(depends_on='component') + plot = Property(depends_on="component") #: The mapper (and associated range) that drive this RangeSelectionOverlay. #: By default, this is the mapper on self.plot that corresponds to self.axis. @@ -43,9 +42,9 @@ class RangeSelectionOverlay(AbstractOverlay): #: a boolean array mask of seleted dataspace points with any other name metadata_name = Str("selections") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Appearance traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ #: The color of the selection border line. border_color = ColorTrait("dodgerblue") @@ -58,44 +57,47 @@ class RangeSelectionOverlay(AbstractOverlay): #: The transparency of the fill color. alpha = Float(0.3) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # AbstractOverlay interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def overlay(self, component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Overrides AbstractOverlay. """ axis_ndx = self.axis_index - lower_left = [0,0] - upper_right = [0,0] + lower_left = [0, 0] + upper_right = [0, 0] # Draw the selection coords = self._get_selection_screencoords() for coord in coords: start, end = coord lower_left[axis_ndx] = start - lower_left[1-axis_ndx] = component.position[1-axis_ndx] + lower_left[1 - axis_ndx] = component.position[1 - axis_ndx] upper_right[axis_ndx] = end - start - upper_right[1-axis_ndx] = component.bounds[1-axis_ndx] + upper_right[1 - axis_ndx] = component.bounds[1 - axis_ndx] with gc: - gc.clip_to_rect(component.x, component.y, component.width, component.height) + gc.clip_to_rect( + component.x, component.y, component.width, component.height + ) gc.set_alpha(self.alpha) gc.set_fill_color(self.fill_color_) gc.set_stroke_color(self.border_color_) gc.set_line_width(self.border_width) gc.set_line_dash(self.border_style_) - gc.draw_rect((lower_left[0], lower_left[1], - upper_right[0], upper_right[1])) + gc.draw_rect( + (lower_left[0], lower_left[1], upper_right[0], upper_right[1]) + ) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _get_selection_screencoords(self): - """ Returns a tuple of (x1, x2) screen space coordinates of the start + """Returns a tuple of (x1, x2) screen space coordinates of the start and end selection points. If there is no current selection, then returns an empty list. @@ -106,25 +108,26 @@ def _get_selection_screencoords(self): return [] # "selections" metadata must be a tuple - if self.metadata_name == "selections" or \ - (selection is not None and isinstance(selection, tuple)): + if self.metadata_name == "selections" or ( + selection is not None and isinstance(selection, tuple) + ): if selection is not None and len(selection) == 2: return [self.mapper.map_screen(array(selection))] else: return [] # All other metadata is interpreted as a mask on dataspace else: - ar = arange(0,len(selection), 1) + ar = arange(0, len(selection), 1) runs = arg_find_runs(ar[selection]) coords = [] for inds in runs: start = ds._data[ar[selection][inds[0]]] - end = ds._data[ar[selection][inds[1]-1]] + end = ds._data[ar[selection][inds[1] - 1]] coords.append(self.mapper.map_screen(array((start, end)))) return coords def _determine_axis(self): - """ Determines which element of an (x,y) coordinate tuple corresponds + """Determines which element of an (x,y) coordinate tuple corresponds to the tool's axis of interest. This method is only called if self._axis_index hasn't been set (or is @@ -135,15 +138,15 @@ def _determine_axis(self): return 0 else: return 1 - else: # self.axis == "value" + else: # self.axis == "value" if self.plot.orientation == "h": return 1 else: return 0 - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _component_changed(self, old, new): self._attach_metadata_handler(old, new) @@ -168,9 +171,9 @@ def _attach_metadata_handler(self, old, new): def _metadata_change_handler(self, event): self.component.request_redraw() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Default initializers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _mapper_default(self): # If the plot's mapper is a GridMapper, return either its @@ -179,16 +182,16 @@ def _mapper_default(self): mapper = getattr(self.plot, self.axis + "_mapper") if isinstance(mapper, GridMapper): - if self.axis == 'index': + if self.axis == "index": return mapper._xmapper else: return mapper._ymapper else: return mapper - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Property getter/setters - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ @cached_property def _get_plot(self): diff --git a/chaco/tools/rect_zoom.py b/chaco/tools/rect_zoom.py index 295b33367..fc70bf2c1 100644 --- a/chaco/tools/rect_zoom.py +++ b/chaco/tools/rect_zoom.py @@ -2,6 +2,7 @@ """ from .zoom_tool import ZoomTool + class RectZoomTool(ZoomTool): """ Allows the user to drag a zoom box around a region of the plot. @@ -16,4 +17,3 @@ class RectZoomTool(ZoomTool): # The tool is always on; left-clicking initiates a zoom (overrides # SimpleZoom). always_on = True - diff --git a/chaco/tools/rectangular_selection.py b/chaco/tools/rectangular_selection.py index fdd9dbc5e..77bb7eb73 100644 --- a/chaco/tools/rectangular_selection.py +++ b/chaco/tools/rectangular_selection.py @@ -7,14 +7,13 @@ class RectangularSelection(LassoSelection): - """ A lasso selection tool whose selection shape is rectangular - """ + """A lasso selection tool whose selection shape is rectangular""" #: The first click. This represents a corner of the rectangle. first_corner = ArrayOrNone(shape=(2,)) def selecting_mouse_move(self, event): - """ This function is the same as the super except that it injects + """This function is the same as the super except that it injects `_make_rectangle` as the `_active_selection` assignment. """ # Translate the event's location to be relative to this container @@ -23,8 +22,7 @@ def selecting_mouse_move(self, event): new_point = self._map_data(np.array((event.x, event.y))) if self.first_corner is None: self.first_corner = new_point - self._active_selection = self._make_rectangle( - self.first_corner, new_point) + self._active_selection = self._make_rectangle(self.first_corner, new_point) self.updated = True if self.incremental_select: self._update_selection() @@ -37,15 +35,10 @@ def selecting_mouse_up(self, event): self.first_corner = None def _make_rectangle(self, p1, p2): - """ Makes an array that represents that path that follows the + """Makes an array that represents that path that follows the corner points of the rectangle with two corners p1 and p2: *-----p2 | | p1----* """ - return np.array([ - p1, - [p1[0], p2[1]], - p2, - [p2[0], p1[1]] - ]) + return np.array([p1, [p1[0], p2[1]], p2, [p2[0], p1[1]]]) diff --git a/chaco/tools/regression_lasso.py b/chaco/tools/regression_lasso.py index 2f5fbb783..a555eb142 100644 --- a/chaco/tools/regression_lasso.py +++ b/chaco/tools/regression_lasso.py @@ -17,8 +17,8 @@ class RegressionLasso(LassoSelection): - """ A controller for "lassoing" a selection of points in a regression plot. - """ + """A controller for "lassoing" a selection of points in a regression plot.""" + #: The regression updates as more points are added (overrides LassoSelection). incremental_select = True @@ -37,8 +37,8 @@ def _selection_changed_fired(self, event): self.fit_params = None self.centroid = None else: - self.fit_params = tuple(polyfit(x,y,1)) - self.centroid = (sum(x)/len(x)), (sum(y)/len(y)) + self.fit_params = tuple(polyfit(x, y, 1)) + self.centroid = (sum(x) / len(x)), (sum(y) / len(y)) else: self.fit_params = None self.centroid = None @@ -50,8 +50,12 @@ class RegressionOverlay(LassoOverlay): line_style = LineStyle("dash") line_width = Float(2.0) - _label = Instance(Label, kw=dict(bgcolor="white", border_color="black", - font="modern 14", border_width=1)) + _label = Instance( + Label, + kw=dict( + bgcolor="white", border_color="black", font="modern 14", border_width=1 + ), + ) def _draw_component(self, gc, view_bounds=None, mode="normal"): LassoOverlay._draw_component(self, gc, view_bounds, mode) @@ -66,10 +70,13 @@ def _draw_component(self, gc, view_bounds=None, mode="normal"): operator = "-" else: operator = "+" - self._label.text = "%.2fx "%selection.fit_params[0] + operator + \ - " %.2f" % fabs(selection.fit_params[1]) + self._label.text = ( + "%.2fx " % selection.fit_params[0] + + operator + + " %.2f" % fabs(selection.fit_params[1]) + ) w, h = self._label.get_width_height(gc) - x = (c.x+c.x2)/2 - w/2 + x = (c.x + c.x2) / 2 - w / 2 y = c.y + 5 # add some padding on the bottom with gc: gc.translate_ctm(x, y) @@ -77,7 +84,7 @@ def _draw_component(self, gc, view_bounds=None, mode="normal"): # draw the line slope, y0 = selection.fit_params - f = lambda x: slope*x + y0 + f = lambda x: slope * x + y0 cx, cy = c.map_screen([selection.centroid])[0] left = c.x right = c.x2 diff --git a/chaco/tools/save_tool.py b/chaco/tools/save_tool.py index aa6345a75..d5c67ada4 100755 --- a/chaco/tools/save_tool.py +++ b/chaco/tools/save_tool.py @@ -10,7 +10,7 @@ class SaveTool(BaseTool): - """ This tool allows the user to press Ctrl+S to save a snapshot image of + """This tool allows the user to press Ctrl+S to save a snapshot image of the plot component. """ @@ -27,9 +27,9 @@ class SaveTool(BaseTool): dest_box = Tuple((0.5, 0.5, -0.5, -0.5)) dest_box_units = Enum("inch", "cm", "mm", "pica") - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Override default trait values inherited from BaseTool - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- #: This tool does not have a visual representation (overrides BaseTool). draw_mode = "none" @@ -38,7 +38,7 @@ class SaveTool(BaseTool): visible = False def normal_key_pressed(self, event): - """ Handles a key-press when the tool is in the 'normal' state. + """Handles a key-press when the tool is in the 'normal' state. Saves an image of the plot if the keys pressed are Control and S. """ @@ -53,18 +53,23 @@ def normal_key_pressed(self, event): event.handled = True def _save_raster(self): - """ Saves an image of the component. - """ + """Saves an image of the component.""" from chaco.plot_graphics_context import PlotGraphicsContext - gc = PlotGraphicsContext((int(self.component.outer_width), int(self.component.outer_height))) + + gc = PlotGraphicsContext( + (int(self.component.outer_width), int(self.component.outer_height)) + ) self.component.draw(gc, mode="normal") gc.save(self.filename) def _save_pdf(self): from chaco.pdf_graphics_context import PdfPlotGraphicsContext - gc = PdfPlotGraphicsContext(filename=self.filename, - pagesize = self.pagesize, - dest_box = self.dest_box, - dest_box_units = self.dest_box_units) + + gc = PdfPlotGraphicsContext( + filename=self.filename, + pagesize=self.pagesize, + dest_box=self.dest_box, + dest_box_units=self.dest_box_units, + ) gc.render_component(self.component) gc.save() diff --git a/chaco/tools/scatter_inspector.py b/chaco/tools/scatter_inspector.py index e643700a5..880119b59 100644 --- a/chaco/tools/scatter_inspector.py +++ b/chaco/tools/scatter_inspector.py @@ -23,7 +23,7 @@ class ScatterInspectorEvent(HasStrictTraits): class ScatterInspector(SelectTool): - """ A tool for inspecting scatter plots. + """A tool for inspecting scatter plots. It writes the index of the point under the cursor to the metadata of the index and value data sources, and allows clicking to select the point. @@ -39,8 +39,8 @@ class ScatterInspector(SelectTool): persistent_hover = Bool(False) #: The names of the data source metadata for hover and selection events. - hover_metadata_name = Str('hover') - selection_metadata_name = Str('selections') + hover_metadata_name = Str("hover") + selection_metadata_name = Str("selections") #: This tool emits events when hover or selection changes inspector_event = Event(ScatterInspectorEvent) @@ -56,7 +56,7 @@ class ScatterInspector(SelectTool): draw_mode = "none" def normal_mouse_move(self, event): - """ Handles the mouse moving when the tool is in the 'normal' state. + """Handles the mouse moving when the tool is in the 'normal' state. If the cursor is within **threshold** of a data point, the method writes the index to the plot's data sources' "hover" metadata. @@ -66,8 +66,7 @@ def normal_mouse_move(self, event): """ plot = self.component index = plot.map_index((event.x, event.y), threshold=self.threshold) - insp_event = ScatterInspectorEvent(event_type=HOVER_EVENT, - event_index=index) + insp_event = ScatterInspectorEvent(event_type=HOVER_EVENT, event_index=index) if index is not None: old = plot.index.metadata.get(self.hover_metadata_name, None) plot.index.metadata[self.hover_metadata_name] = [index] @@ -87,7 +86,7 @@ def _get_selection_state(self, event): index = plot.map_index((event.x, event.y), threshold=self.threshold) already_selected = False - for name in ('index', 'value'): + for name in ("index", "value"): if not hasattr(plot, name): continue md = getattr(plot, name).metadata @@ -104,13 +103,12 @@ def _get_selection_token(self, event): return index def _deselect(self, index=None): - """ Deselects a particular index. If no index is given, then + """Deselects a particular index. If no index is given, then deselects all points. """ plot = self.component - insp_event = ScatterInspectorEvent(event_type=DESELECT_EVENT, - event_index=index) - for name in ('index', 'value'): + insp_event = ScatterInspectorEvent(event_type=DESELECT_EVENT, event_index=index) + for name in ("index", "value"): if not hasattr(plot, name): continue md = getattr(plot, name).metadata @@ -121,19 +119,18 @@ def _deselect(self, index=None): new_list.remove(index) md[self.selection_metadata_name] = new_list # Only issue 1 event: - if name == 'index': + if name == "index": self.inspector_event = insp_event elif index is None: md[self.selection_metadata_name] = [] # Only issue 1 event: - if name == 'index': + if name == "index": self.inspector_event = insp_event def _select(self, index, append=True): plot = self.component - insp_event = ScatterInspectorEvent(event_type=SELECT_EVENT, - event_index=index) - for name in ('index', 'value'): + insp_event = ScatterInspectorEvent(event_type=SELECT_EVENT, event_index=index) + for name in ("index", "value"): if not hasattr(plot, name): continue md = getattr(plot, name).metadata @@ -159,5 +156,5 @@ def _select(self, index, append=True): md[self.selection_metadata_name] = [index] # Test to only issue 1 event per selection, not 1 per axis: - if name == 'index': + if name == "index": self.inspector_event = insp_event diff --git a/chaco/tools/select_tool.py b/chaco/tools/select_tool.py index 4abb9bb1f..d1de1d60a 100644 --- a/chaco/tools/select_tool.py +++ b/chaco/tools/select_tool.py @@ -1,12 +1,10 @@ - - # Enthought library imports from enable.api import BaseTool, KeySpec from traits.api import Enum, Float, Instance class SelectTool(BaseTool): - """ Base class for tools that handle some level of click-to-select + """Base class for tools that handle some level of click-to-select interaction. Handles the logic of different kinds of selection modes. Subclasses only need to implement a few concrete methods to handle actual selection/deselection. @@ -37,9 +35,8 @@ class SelectTool(BaseTool): #: and **multi** selection modes. multiselect_modifier = Instance(KeySpec, args=(None, "control"), allow_none=True) - def _get_selection_state(self, event): - """ Returns a tuple reflecting the current selection state + """Returns a tuple reflecting the current selection state Parameters ---------- @@ -57,24 +54,22 @@ def _get_selection_state(self, event): raise NotImplementedError def _get_selection_token(self, event): - """ Returns a token corresponding to the selection event. This token + """Returns a token corresponding to the selection event. This token is passed in to the select and deselect methods. By default, this just returns the event itself. """ return event def _select(self, token, append=True): - """ Selects the given token. - """ + """Selects the given token.""" raise NotImplementedError def _deselect(self, token, append=True): - """ Deselects the given token. - """ + """Deselects the given token.""" raise NotImplementedError def normal_left_down(self, event): - """ Handles the left mouse button being pressed when the tool is in the + """Handles the left mouse button being pressed when the tool is in the 'normal' state. If selecting is enabled and the cursor is within **threshold** of a @@ -87,8 +82,9 @@ def normal_left_down(self, event): modifier_down = self.multiselect_modifier.match(event) token = self._get_selection_token(event) - if (self.selection_mode == "single") or\ - (self.selection_mode == "multi" and not modifier_down): + if (self.selection_mode == "single") or ( + self.selection_mode == "multi" and not modifier_down + ): if clicked and not already_selected: if self.selection_mode == "single" or not modifier_down: self._select(token, append=False) @@ -106,6 +102,3 @@ def normal_left_down(self, event): self._select(token) event.handled = True return - - - diff --git a/chaco/tools/simple_inspector.py b/chaco/tools/simple_inspector.py index b7deddf56..64972dd43 100644 --- a/chaco/tools/simple_inspector.py +++ b/chaco/tools/simple_inspector.py @@ -9,8 +9,9 @@ from enable.api import BaseTool, KeySpec from traits.api import Bool, Event, Tuple, Enum, Callable + class SimpleInspectorTool(BaseTool): - """ Simple inspector tool for plots + """Simple inspector tool for plots This is a simple tool that reports the data-space coordinates of the current mouse cursor position in a plot. @@ -41,7 +42,7 @@ class SimpleInspectorTool(BaseTool): last_mouse_position = Tuple #: This key will show and hide any overlays listening to this tool. - inspector_key = KeySpec('p') + inspector_key = KeySpec("p") #: A callable that computes other values for the new_value event #: this takes a dictionary as an argument, and returns a dictionary @@ -51,14 +52,14 @@ class SimpleInspectorTool(BaseTool): # Stores the value of self.visible when the mouse leaves the tool, # so that it can be restored when the mouse enters again. - _old_visible = Enum(None, True, False) #Trait(None, Bool(True)) + _old_visible = Enum(None, True, False) # Trait(None, Bool(True)) ######################################################################### # SimpleInspectorTool API ######################################################################### def gather_values(self, event): - """ Generate the values for the new_value dictionary. + """Generate the values for the new_value dictionary. By default this returns a dictionary with keys "x", "y", "index" and "value". If there is a value_generator callable, this will be called @@ -76,11 +77,12 @@ def gather_values(self, event): A dictionary. """ x, y, index, value = self.map_to_data(event.x, event.y) - d = {'index': index, 'value': value, 'x': x, 'y': y} + d = {"index": index, "value": value, "x": x, "y": y} if isinstance(self.component, ImagePlot): - x_ndx, y_ndx = self.component.map_index((event.x, event.y), - outside_returns_none=False) + x_ndx, y_ndx = self.component.map_index( + (event.x, event.y), outside_returns_none=False + ) # FIXME: off-by-one error. The size of the index is +1 to the size of # the image array @@ -89,16 +91,16 @@ def gather_values(self, event): if x_ndx == self.component.value.data.shape[1]: x_ndx += 1 - z = self.component.value.data[y_ndx, x_ndx] - d['z'] = z - d['color'] = z + z = self.component.value.data[y_ndx, x_ndx] + d["z"] = z + d["color"] = z if self.value_generator is not None: d = self.value_generator(d) return d def map_to_data(self, x, y): - """ Returns the data space coordinates of the given x and y. + """Returns the data space coordinates of the given x and y. Takes into account orientation of the plot and the axis setting. """ diff --git a/chaco/tools/simple_zoom.py b/chaco/tools/simple_zoom.py index 7d8b01b08..7f68398a2 100644 --- a/chaco/tools/simple_zoom.py +++ b/chaco/tools/simple_zoom.py @@ -3,22 +3,23 @@ import warnings + warnings.warn("SimpleZoom has been deprecated, use ZoomTool", DeprecationWarning) from numpy import array # Enthought library imports from enable.api import ColorTrait, KeySpec -from traits.api \ - import Bool, Enum, Float, Instance, Int, Str, Trait, Tuple +from traits.api import Bool, Enum, Float, Instance, Int, Str, Trait, Tuple # Chaco imports from chaco.abstract_overlay import AbstractOverlay from .base_zoom_tool import BaseZoomTool from .tool_history_mixin import ToolHistoryMixin + class SimpleZoom(AbstractOverlay, ToolHistoryMixin, BaseZoomTool): - """ Selects a range along the index or value axis. + """Selects a range along the index or value axis. The user left-click-drags to select a region to zoom in. Certain keyboard keys are mapped to performing zoom actions as well. @@ -41,19 +42,19 @@ class SimpleZoom(AbstractOverlay, ToolHistoryMixin, BaseZoomTool): # Defines a meta-key, that works with always_on to set the zoom mode. This # is useful when the zoom tool is used in conjunction with the pan tool. - always_on_modifier = Enum(None, 'shift', 'control', 'alt') + always_on_modifier = Enum(None, "shift", "control", "alt") - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Zoom control - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # The axis to which the selection made by this tool is perpendicular. This # only applies in 'range' mode. axis = Enum("index", "value") - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Interaction control - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Enable the mousewheel for zooming? enable_wheel = Bool(True) @@ -80,9 +81,9 @@ class SimpleZoom(AbstractOverlay, ToolHistoryMixin, BaseZoomTool): # the tool to actually take effect. minimum_screen_delta = Int(10) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # Appearance properties (for Box mode) - #------------------------------------------------------------------------- + # ------------------------------------------------------------------------- # The pointer to use when drawing a zoom box. pointer = "magnifier" @@ -107,16 +108,16 @@ class SimpleZoom(AbstractOverlay, ToolHistoryMixin, BaseZoomTool): # The possible event states of this zoom tool. event_state = Enum("normal", "selecting") - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Key mappings - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # The key that cancels the zoom and resets the view to the original defaults. cancel_zoom_key = Instance(KeySpec, args=("Esc",)) - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private traits - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # If **always_on** is False, this attribute indicates whether the tool # is currently enabled. @@ -147,13 +148,11 @@ def __init__(self, component=None, *args, **kw): x_range = self.component.x_mapper.range y_range = self.component.y_mapper.range self._orig_low_setting = (x_range.low_setting, y_range.low_setting) - self._orig_high_setting = \ - (x_range.high_setting, y_range.high_setting) - component.observe(self._reset_state_to_current, - "index_data_changed") + self._orig_high_setting = (x_range.high_setting, y_range.high_setting) + component.observe(self._reset_state_to_current, "index_data_changed") def enable(self, event=None): - """ Provides a programmatic way to enable this tool, if + """Provides a programmatic way to enable this tool, if **always_on** is False. Calling this method has the same effect as if the user pressed the @@ -166,7 +165,7 @@ def enable(self, event=None): event.window.set_pointer(self.pointer) def disable(self, event=None): - """ Provides a programmatic way to enable this tool, if **always_on** + """Provides a programmatic way to enable this tool, if **always_on** is False. Calling this method has the same effect as if the user pressed the @@ -180,20 +179,18 @@ def disable(self, event=None): event.window.set_pointer("arrow") def reset(self, event=None): - """ Resets the tool to normal state, with no start or end position. - """ + """Resets the tool to normal state, with no start or end position.""" self.event_state = "normal" self._screen_start = None self._screen_end = None def deactivate(self, component): - """ Called when this is no longer the active tool. - """ + """Called when this is no longer the active tool.""" # Required as part of the AbstractController interface. return self.disable() def overlay(self, component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. + """Draws this component overlaid on another component. Overrides AbstractOverlay. """ @@ -204,17 +201,18 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): self.overlay_box(component, gc) def overlay_box(self, component, gc): - """ Draws the overlay as a box. - """ + """Draws the overlay as a box.""" if self._screen_start and self._screen_end: with gc: gc.set_antialias(0) gc.set_line_width(self.border_size) gc.set_stroke_color(self.border_color_) - gc.clip_to_rect(component.x, component.y, component.width, component.height) + gc.clip_to_rect( + component.x, component.y, component.width, component.height + ) x, y = self._screen_start x2, y2 = self._screen_end - rect = (x, y, x2-x+1, y2-y+1) + rect = (x, y, x2 - x + 1, y2 - y + 1) if self.color != "transparent": if self.alpha: color = list(self.color_) @@ -232,15 +230,16 @@ def overlay_box(self, component, gc): gc.stroke_path() def overlay_range(self, component, gc): - """ Draws the overlay as a range. - """ + """Draws the overlay as a range.""" axis_ndx = self._determine_axis() - lower_left = [0,0] - upper_right = [0,0] + lower_left = [0, 0] + upper_right = [0, 0] lower_left[axis_ndx] = self._screen_start[axis_ndx] - lower_left[1-axis_ndx] = self.component.position[1-axis_ndx] - upper_right[axis_ndx] = self._screen_end[axis_ndx] - self._screen_start[axis_ndx] - upper_right[1-axis_ndx] = self.component.bounds[1-axis_ndx] + lower_left[1 - axis_ndx] = self.component.position[1 - axis_ndx] + upper_right[axis_ndx] = ( + self._screen_end[axis_ndx] - self._screen_start[axis_ndx] + ) + upper_right[1 - axis_ndx] = self.component.bounds[1 - axis_ndx] with gc: gc.set_antialias(0) @@ -252,7 +251,7 @@ def overlay_range(self, component, gc): gc.draw_path() def normal_left_down(self, event): - """ Handles the left mouse button being pressed while the tool is + """Handles the left mouse button being pressed while the tool is in the 'normal' state. If the tool is enabled or always on, it starts selecting. @@ -262,7 +261,7 @@ def normal_left_down(self, event): event.handled = True def normal_right_down(self, event): - """ Handles the right mouse button being pressed while the tool is + """Handles the right mouse button being pressed while the tool is in the 'normal' state. If the tool is enabled or always on, it starts selecting. @@ -272,7 +271,7 @@ def normal_right_down(self, event): event.handled = True def selecting_mouse_move(self, event): - """ Handles the mouse moving when the tool is in the 'selecting' state. + """Handles the mouse moving when the tool is in the 'selecting' state. The selection is extended to the current mouse position. """ @@ -281,7 +280,7 @@ def selecting_mouse_move(self, event): event.handled = True def selecting_left_up(self, event): - """ Handles the left mouse button being released when the tool is in + """Handles the left mouse button being released when the tool is in the 'selecting' state. Finishes selecting and does the zoom. @@ -290,7 +289,7 @@ def selecting_left_up(self, event): self._end_select(event) def selecting_right_up(self, event): - """ Handles the right mouse button being released when the tool is in + """Handles the right mouse button being released when the tool is in the 'selecting' state. Finishes selecting and does the zoom. @@ -299,7 +298,7 @@ def selecting_right_up(self, event): self._end_select(event) def selecting_mouse_leave(self, event): - """ Handles the mouse leaving the plot when the tool is in the + """Handles the mouse leaving the plot when the tool is in the 'selecting' state. Ends the selection operation without zooming. @@ -307,7 +306,7 @@ def selecting_mouse_leave(self, event): self._end_selecting(event) def selecting_key_pressed(self, event): - """ Handles a key being pressed when the tool is in the 'selecting' + """Handles a key being pressed when the tool is in the 'selecting' state. If the key pressed is the **cancel_zoom_key**, then selecting is @@ -318,8 +317,7 @@ def selecting_key_pressed(self, event): event.handled = True def _start_select(self, event): - """ Starts selecting the zoom region - """ + """Starts selecting the zoom region""" if self.component.active_tool in (None, self): self.component.active_tool = self else: @@ -332,7 +330,7 @@ def _start_select(self, event): self.selecting_mouse_move(event) def _end_select(self, event): - """ Ends selection of the zoom region, adds the new zoom range to + """Ends selection of the zoom region, adds the new zoom range to the zoom stack, and does the zoom. """ self._screen_end = (event.x, event.y) @@ -363,8 +361,7 @@ def _end_select(self, event): event.handled = True def _end_selecting(self, event=None): - """ Ends selection of zoom region, without zooming. - """ + """Ends selection of zoom region, without zooming.""" if self.disable_on_complete: self.disable(event) else: @@ -374,7 +371,7 @@ def _end_selecting(self, event=None): event.window.set_mouse_owner(None) def _do_zoom(self): - """ Does the zoom operation. + """Does the zoom operation. This method does not handle zooms triggered by scrolling the mouse wheel. Those are handled by `normal_mouse_wheel()`. @@ -394,10 +391,8 @@ def _do_zoom(self): # "box" mode; reset both axes. x_range = self.component.x_mapper.range y_range = self.component.y_mapper.range - x_range.low_setting, y_range.low_setting = \ - self._orig_low_setting - x_range.high_setting, y_range.high_setting = \ - self._orig_high_setting + x_range.low_setting, y_range.low_setting = self._orig_low_setting + x_range.high_setting, y_range.high_setting = self._orig_high_setting # resetting the ranges will allow 'auto' to pick the values x_range.reset() @@ -417,8 +412,9 @@ def _do_zoom(self): # "box" mode; zoom both axes. for ndx in (0, 1): mapper = (self.component.x_mapper, self.component.y_mapper)[ndx] - if self._zoom_limit_reached(orig_low[ndx], orig_high[ndx], - low[ndx], high[ndx], mapper): + if self._zoom_limit_reached( + orig_low[ndx], orig_high[ndx], low[ndx], high[ndx], mapper + ): # pop _current_state off the stack and leave the actual # bounds unmodified. self._pop_state() @@ -431,7 +427,7 @@ def _do_zoom(self): self.component.request_redraw() def normal_key_pressed(self, event): - """ Handles a key being pressed when the tool is in 'normal' state. + """Handles a key being pressed when the tool is in 'normal' state. If the tool is not always on, this method handles turning it on and off when the appropriate keys are pressed. Also handles keys to @@ -457,7 +453,7 @@ def normal_key_pressed(self, event): self.component.request_redraw() def normal_mouse_wheel(self, event): - """ Handles the mouse wheel being used when the tool is in the 'normal' + """Handles the mouse wheel being used when the tool is in the 'normal' state. Scrolling the wheel "up" zooms in; scrolling it "down" zooms out. @@ -496,7 +492,7 @@ def normal_mouse_wheel(self, event): newlow = mapper.map_data(newscreenlow) newhigh = mapper.map_data(newscreenhigh) - if type(orig_high) in (tuple,list): + if type(orig_high) in (tuple, list): ol, oh = orig_low[ndx], orig_high[ndx] else: ol, oh = orig_low, orig_high @@ -505,7 +501,7 @@ def normal_mouse_wheel(self, event): # Ignore other axes, we're done. event.handled = True return - todo_list.append((mapper,newlow,newhigh)) + todo_list.append((mapper, newlow, newhigh)) # Check the domain limits on each dimension, and rescale the zoom # amount if necessary. @@ -513,7 +509,7 @@ def normal_mouse_wheel(self, event): if newlow > newhigh: # This happens when the orientation of the axis is reversed. newlow, newhigh = newhigh, newlow - domain_min, domain_max = getattr(mapper, "domain_limits", (None,None)) + domain_min, domain_max = getattr(mapper, "domain_limits", (None, None)) if domain_min is not None and newlow < domain_min: newlow = domain_min if domain_max is not None and newhigh > domain_max: @@ -531,17 +527,17 @@ def normal_mouse_wheel(self, event): def _is_enabling_event(self, event): always_on = self.always_on - if self.always_on_modifier == 'shift': + if self.always_on_modifier == "shift": always_on = always_on and event.shift_down - elif self.always_on_modifier == 'control': + elif self.always_on_modifier == "control": always_on = always_on and event.control_down - elif self.always_on_modifier == 'alt': + elif self.always_on_modifier == "alt": always_on = always_on and event.alt_down if always_on or self._enabled: - if event.right_down and self.drag_button == 'right': + if event.right_down and self.drag_button == "right": return True - if event.left_down and self.drag_button == 'left': + if event.left_down and self.drag_button == "left": return True return False @@ -558,28 +554,26 @@ def _tool_mode_changed(self, old, new): # different state types in the history self._reset_state_to_current() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Implementation of PlotComponent interface - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _activate(self): - """ Called by PlotComponent to set this as the active tool. - """ + """Called by PlotComponent to set this as the active tool.""" self.enable() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # implementations of abstract methods on ToolHistoryMixin - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _reset_state_to_current(self, event=None): - """ Clears the tool history, and sets the current state to be the + """Clears the tool history, and sets the current state to be the first state in the history. """ if self.tool_mode == "range": mapper = self._get_mapper() if mapper is not None: - self._reset_state((mapper.range.low, - mapper.range.high)) + self._reset_state((mapper.range.low, mapper.range.high)) else: if self.component.x_mapper is not None: x_range = self.component.x_mapper.range @@ -597,11 +591,10 @@ def _reset_state_to_current(self, event=None): ylow = "auto" yhigh = "auto" - self._reset_state(((xlow, ylow), - (xhigh, yhigh))) + self._reset_state(((xlow, ylow), (xhigh, yhigh))) def _reset_state_pressed(self): - """ Called when the tool needs to reset its history. + """Called when the tool needs to reset its history. The history index will have already been set to 0. Implements ToolHistoryMixin. @@ -613,7 +606,7 @@ def _reset_state_pressed(self): self._reset_state_to_current() def _prev_state_pressed(self): - """ Called when the tool needs to advance to the previous state in the + """Called when the tool needs to advance to the previous state in the stack. The history index will have already been set to the index corresponding @@ -622,7 +615,7 @@ def _prev_state_pressed(self): self._do_zoom() def _next_state_pressed(self): - """ Called when the tool needs to advance to the next state in the stack. + """Called when the tool needs to advance to the next state in the stack. The history index will have already been set to the index corresponding to the next state. Implements ToolHistoryMixin. @@ -633,23 +626,23 @@ def _next_state_pressed(self): def __getstate__(self): dont_pickle = [ - 'always_on', - 'always_on_modifier', - 'enter_zoom_key', - 'exit_zoom_key', - 'minimum_screen_delta', - 'event_state', - 'reset_zoom_key', - 'prev_zoom_key', - 'next_zoom_key', - 'pointer', - '_enabled', - '_screen_start', - '_screen_end'] - state = super(SimpleZoom,self).__getstate__() + "always_on", + "always_on_modifier", + "enter_zoom_key", + "exit_zoom_key", + "minimum_screen_delta", + "event_state", + "reset_zoom_key", + "prev_zoom_key", + "next_zoom_key", + "pointer", + "_enabled", + "_screen_start", + "_screen_end", + ] + state = super(SimpleZoom, self).__getstate__() for key in dont_pickle: if key in state: del state[key] return state - diff --git a/chaco/tools/tests/test_better_zoom_tool.py b/chaco/tools/tests/test_better_zoom_tool.py index bd1dceac4..23d1f3758 100644 --- a/chaco/tools/tests/test_better_zoom_tool.py +++ b/chaco/tools/tests/test_better_zoom_tool.py @@ -40,7 +40,7 @@ def test_default_position(self): tool = self.tool # this doesn't throw an exception - self.send_key(tool, '+') + self.send_key(tool, "+") self.assertEqual(tool.position, (50, 50)) diff --git a/chaco/tools/tests/test_image_inspector.py b/chaco/tools/tests/test_image_inspector.py index 4544b7151..5df6ce75f 100644 --- a/chaco/tools/tests/test_image_inspector.py +++ b/chaco/tools/tests/test_image_inspector.py @@ -20,7 +20,7 @@ def create_image_plot(img_values, **kwargs): class CustomImageInspectorOverlay(ImageInspectorOverlay): def _build_text_from_event(self, event): - return 'Position: ({}, {})'.format(*event['indices']) + return "Position: ({}, {})".format(*event["indices"]) class BaseImageInspectorTool(EnableTestAssistant, UnittestTools): @@ -30,10 +30,12 @@ def setUp(self): self.plot._window = self.create_mock_window() renderer = self.plot.plots["plot0"][0] self.tool = ImageInspectorTool(component=renderer) - self.overlay = ImageInspectorOverlay(component=renderer, - image_inspector=self.tool) - self.overlay2 = CustomImageInspectorOverlay(component=renderer, - image_inspector=self.tool) + self.overlay = ImageInspectorOverlay( + component=renderer, image_inspector=self.tool + ) + self.overlay2 = CustomImageInspectorOverlay( + component=renderer, image_inspector=self.tool + ) self.plot.active_tool = self.tool self.plot.do_layout() @@ -65,10 +67,9 @@ def test_mouse_move_custom_overlay(self): with self.assertTraitChanges(self.overlay2, "text", 1): self.mouse_move(tool, 0, 0) - self.assertEqual(self.overlay2.text, 'Position: (0, 0)') + self.assertEqual(self.overlay2.text, "Position: (0, 0)") finally: - tool.observe(self.store_inspector_event, "new_value", - remove=True) + tool.observe(self.store_inspector_event, "new_value", remove=True) # Helper methods ---------------------------------------------------------- @@ -77,8 +78,7 @@ def store_inspector_event(self, event): class TestImageInspectorToolGray(BaseImageInspectorTool, TestCase): - """ Tests for the ImageInspector tool with a gray scale image - """ + """Tests for the ImageInspector tool with a gray scale image""" def setUp(self): values = np.arange(4).reshape(2, 2) @@ -99,7 +99,7 @@ def test_mouse_move_collect_image_info(self): self.assertEqual(self.insp_event["color_value"], 0) self.assertEqual(self.insp_event["indices"], (0, 0)) - self.assertEqual(self.overlay.text, '(0, 0)\n0') + self.assertEqual(self.overlay.text, "(0, 0)\n0") with self.assertTraitChanges(tool, "new_value", 1): with self.assertTraitChanges(self.overlay, "text", 1): @@ -108,7 +108,7 @@ def test_mouse_move_collect_image_info(self): self.assertEqual(self.insp_event["color_value"], 1) self.assertEqual(self.insp_event["indices"], (1, 0)) - self.assertEqual(self.overlay.text, '(1, 0)\n1') + self.assertEqual(self.overlay.text, "(1, 0)\n1") with self.assertTraitChanges(tool, "new_value", 1): with self.assertTraitDoesNotChange(self.overlay, "text"): @@ -124,7 +124,7 @@ def test_mouse_move_collect_image_info(self): self.assertEqual(self.insp_event["color_value"], 2) self.assertEqual(self.insp_event["indices"], (0, 1)) - self.assertEqual(self.overlay.text, '(0, 1)\n2') + self.assertEqual(self.overlay.text, "(0, 1)\n2") with self.assertTraitChanges(tool, "new_value", 1): with self.assertTraitChanges(self.overlay, "text", 1): @@ -133,16 +133,14 @@ def test_mouse_move_collect_image_info(self): self.assertEqual(self.insp_event["color_value"], 3) self.assertEqual(self.insp_event["indices"], (1, 1)) - self.assertEqual(self.overlay.text, '(1, 1)\n3') + self.assertEqual(self.overlay.text, "(1, 1)\n3") finally: - tool.observe(self.store_inspector_event, "new_value", - remove=True) + tool.observe(self.store_inspector_event, "new_value", remove=True) class TestImageInspectorToolRGB(BaseImageInspectorTool, TestCase): - """ Tests for the ImageInspector tool with an RGB image. - """ + """Tests for the ImageInspector tool with an RGB image.""" def setUp(self): values = np.arange(12).reshape(2, 2, 3) @@ -160,50 +158,54 @@ def test_mouse_move_collect_image_info(self): with self.assertTraitChanges(tool, "new_value", 1): with self.assertTraitChanges(self.overlay, "text", 1): self.mouse_move(tool, 0, 0) - assert_array_equal(self.insp_event["color_value"], - np.array([0, 1, 2])) + assert_array_equal( + self.insp_event["color_value"], np.array([0, 1, 2]) + ) self.assertEqual(self.insp_event["indices"], (0, 0)) - self.assertEqual(self.overlay.text, '(0, 0)\n(0, 1, 2)') + self.assertEqual(self.overlay.text, "(0, 0)\n(0, 1, 2)") with self.assertTraitChanges(tool, "new_value", 1): with self.assertTraitChanges(self.overlay, "text", 1): # Move within the same tile: self.mouse_move(tool, 90, 0) - assert_array_equal(self.insp_event["color_value"], - np.array([3, 4, 5])) + assert_array_equal( + self.insp_event["color_value"], np.array([3, 4, 5]) + ) self.assertEqual(self.insp_event["indices"], (1, 0)) - self.assertEqual(self.overlay.text, '(1, 0)\n(3, 4, 5)') + self.assertEqual(self.overlay.text, "(1, 0)\n(3, 4, 5)") with self.assertTraitChanges(tool, "new_value", 1): with self.assertTraitDoesNotChange(self.overlay, "text"): # Move within the same tile: self.mouse_move(tool, 91, 0) - assert_array_equal(self.insp_event["color_value"], - np.array([3, 4, 5])) + assert_array_equal( + self.insp_event["color_value"], np.array([3, 4, 5]) + ) self.assertEqual(self.insp_event["indices"], (1, 0)) with self.assertTraitChanges(tool, "new_value", 1): with self.assertTraitChanges(self.overlay, "text", 1): # Move to another value in the image: self.mouse_move(tool, 0, 90) - assert_array_equal(self.insp_event["color_value"], - np.array([6, 7, 8])) + assert_array_equal( + self.insp_event["color_value"], np.array([6, 7, 8]) + ) self.assertEqual(self.insp_event["indices"], (0, 1)) - self.assertEqual(self.overlay.text, '(0, 1)\n(6, 7, 8)') + self.assertEqual(self.overlay.text, "(0, 1)\n(6, 7, 8)") with self.assertTraitChanges(tool, "new_value", 1): with self.assertTraitChanges(self.overlay, "text", 1): # Move within the same tile: self.mouse_move(tool, 90, 90) - assert_array_equal(self.insp_event["color_value"], - np.array([9, 10, 11])) + assert_array_equal( + self.insp_event["color_value"], np.array([9, 10, 11]) + ) self.assertEqual(self.insp_event["indices"], (1, 1)) - self.assertEqual(self.overlay.text, '(1, 1)\n(9, 10, 11)') + self.assertEqual(self.overlay.text, "(1, 1)\n(9, 10, 11)") finally: - tool.observe(self.store_inspector_event, "new_value", - remove=True) + tool.observe(self.store_inspector_event, "new_value", remove=True) diff --git a/chaco/tools/tests/test_pan_tool.py b/chaco/tools/tests/test_pan_tool.py index f3244f306..ec29ab30b 100644 --- a/chaco/tools/tests/test_pan_tool.py +++ b/chaco/tools/tests/test_pan_tool.py @@ -9,7 +9,6 @@ class PanToolTestCase(EnableTestAssistant, unittest.TestCase): - def test_restrict_to_data_with_empty_source(self): # Regression test for #214. plot_data = ArrayPlotData() @@ -18,8 +17,8 @@ def test_restrict_to_data_with_empty_source(self): plot_data.set_data("x", arr) plot_data.set_data("y", arr) plot_data.set_data("z", np.array([], np.float64)) - plot.plot(('x', 'y')) - plot.plot(('z', 'z')) + plot.plot(("x", "y")) + plot.plot(("z", "z")) tool = PanTool(plot, restrict_to_data=True) plot.tools.append(tool) diff --git a/chaco/tools/tests/test_range_selection.py b/chaco/tools/tests/test_range_selection.py index bb9c7f45d..cdd579932 100644 --- a/chaco/tools/tests/test_range_selection.py +++ b/chaco/tools/tests/test_range_selection.py @@ -10,7 +10,6 @@ class RangeSelectionTestCase(EnableTestAssistant, unittest.TestCase): - def test_selecting_mouse_leave_clipping(self): # Regression test for #216. plot_data = ArrayPlotData() @@ -18,17 +17,17 @@ def test_selecting_mouse_leave_clipping(self): plot_data.set_data("x", arr) plot_data.set_data("y", arr) - for origin in ('bottom left', 'top left', 'bottom right', 'top right'): - for orientation in ('h', 'v'): - for axis in ('index', 'value'): - plot = Plot( - plot_data, orientation=orientation, origin='top right' - ) + for origin in ("bottom left", "top left", "bottom right", "top right"): + for orientation in ("h", "v"): + for axis in ("index", "value"): + plot = Plot(plot_data, orientation=orientation, origin="top right") - renderer = plot.plot(('x', 'y'))[0] + renderer = plot.plot(("x", "y"))[0] renderer.bounds = [10, 20] tool = RangeSelection( - renderer, left_button_selects=True, axis=axis, + renderer, + left_button_selects=True, + axis=axis, ) renderer.tools.append(tool) @@ -58,7 +57,7 @@ def test_selection_no_warning(self): plot_data.set_data("x", arr) plot_data.set_data("y", arr) plot = Plot(plot_data) - renderer = plot.plot(('x', 'y'))[0] + renderer = plot.plot(("x", "y"))[0] tool = RangeSelection(renderer) with warnings.catch_warnings(record=True) as w: # Ignore warnings coming from any package other than Chaco diff --git a/chaco/tools/tests/test_range_zoom.py b/chaco/tools/tests/test_range_zoom.py index 518cd4755..b4eca97c3 100644 --- a/chaco/tools/tests/test_range_zoom.py +++ b/chaco/tools/tests/test_range_zoom.py @@ -16,6 +16,7 @@ class BackgroundColorTestCase(EnableTestAssistant, TestCase): appear completely opaque. This issue was reported (and fixed) in GH #309. """ + def setUp(self): values = numpy.arange(10) self.plot = create_line_plot((values, values)) @@ -31,36 +32,30 @@ def tearDown(self): def test_rgba_background_box(self): tool = self.tool - tool.tool_mode = 'box' + tool.tool_mode = "box" tool.alpha = 0.3 - tool.color = 'red' - gc = self.create_mock_gc(100, 100, methods=('set_fill_color',)) + tool.color = "red" + gc = self.create_mock_gc(100, 100, methods=("set_fill_color",)) - kwargs = { - 'window': self.plot._window, 'control_down': True - } + kwargs = {"window": self.plot._window, "control_down": True} self.mouse_down(self.tool, 0.0, 0.0, **kwargs) self.mouse_move(self.tool, 10.0, 10.0, **kwargs) tool.overlay(self.plot, gc) - self.assertEqual(gc.set_fill_color.call_args, - mock.call([1.0, 0.0, 0.0, 0.3])) + self.assertEqual(gc.set_fill_color.call_args, mock.call([1.0, 0.0, 0.0, 0.3])) def test_rgba_background_range(self): tool = self.tool - tool.tool_mode = 'range' + tool.tool_mode = "range" tool.alpha = 0.3 - tool.color = 'red' - gc = self.create_mock_gc(100, 100, methods=('set_fill_color',)) + tool.color = "red" + gc = self.create_mock_gc(100, 100, methods=("set_fill_color",)) - kwargs = { - 'window': self.plot._window, 'control_down': True - } + kwargs = {"window": self.plot._window, "control_down": True} self.mouse_down(self.tool, 0.0, 0.0, **kwargs) self.mouse_move(self.tool, 10.0, 10.0, **kwargs) tool.overlay(self.plot, gc) - self.assertEqual(gc.set_fill_color.call_args, - mock.call([1.0, 0.0, 0.0, 0.3])) + self.assertEqual(gc.set_fill_color.call_args, mock.call([1.0, 0.0, 0.0, 0.3])) diff --git a/chaco/tools/tests/test_rectangular_selection_tool.py b/chaco/tools/tests/test_rectangular_selection_tool.py index 954913724..8888041e5 100644 --- a/chaco/tools/tests/test_rectangular_selection_tool.py +++ b/chaco/tools/tests/test_rectangular_selection_tool.py @@ -9,7 +9,6 @@ class RectangularSelectionTestCase(EnableTestAssistant, unittest.TestCase): - def test_selection_mask(self): plot_data = ArrayPlotData() @@ -17,11 +16,11 @@ def test_selection_mask(self): arr = np.array([-2, -1, 1, 2]) plot_data.set_data("x", arr) plot_data.set_data("y", arr) - splot = plot.plot(('x', 'y'), type='scatter')[0] + splot = plot.plot(("x", "y"), type="scatter")[0] tool = RectangularSelection( component=splot, selection_datasource=splot.index, - metadata_name='selections', + metadata_name="selections", ) splot.tools.append(tool) @@ -30,24 +29,12 @@ def test_selection_mask(self): cursor_start = splot.map_screen([-1.5, -1.5])[0] cursor_stop = splot.map_screen([1.5, 1.5])[0] - self.mouse_down( - interactor=tool, - x=cursor_start[0], - y=cursor_start[1] - ) + self.mouse_down(interactor=tool, x=cursor_start[0], y=cursor_start[1]) - self.mouse_move( - interactor=tool, - x=cursor_stop[0], - y=cursor_stop[1] - ) + self.mouse_move(interactor=tool, x=cursor_stop[0], y=cursor_stop[1]) - self.mouse_up( - interactor=tool, - x=cursor_stop[0], - y=cursor_stop[1] - ) + self.mouse_up(interactor=tool, x=cursor_stop[0], y=cursor_stop[1]) expected_mask = [False, True, True, False] - selection_mask = list(splot.index.metadata['selections']) + selection_mask = list(splot.index.metadata["selections"]) self.assertEqual(expected_mask, selection_mask) diff --git a/chaco/tools/tests/test_scatter_inspector.py b/chaco/tools/tests/test_scatter_inspector.py index 5d1c4ab24..7b6245bd2 100644 --- a/chaco/tools/tests/test_scatter_inspector.py +++ b/chaco/tools/tests/test_scatter_inspector.py @@ -131,8 +131,7 @@ def test_hover_triggers_event(self): self.assertEqual(self.insp_event.event_type, "hover") self.assertEqual(self.insp_event.event_index, 1) finally: - tool.observe(self.store_inspector_event, "inspector_event", - remove=True) + tool.observe(self.store_inspector_event, "inspector_event", remove=True) def test_select_triggers_event(self): tool = self.tool @@ -162,9 +161,7 @@ def test_select_triggers_event(self): self.assertEqual(self.insp_event.event_type, "deselect") self.assertEqual(self.insp_event.event_index, 1) finally: - tool.observe( - self.store_inspector_event, "inspector_event", remove=True - ) + tool.observe(self.store_inspector_event, "inspector_event", remove=True) # Helper methods ---------------------------------------------------------- diff --git a/chaco/tools/tool_history_mixin.py b/chaco/tools/tool_history_mixin.py index 3f573f6fa..1dfcc934f 100644 --- a/chaco/tools/tool_history_mixin.py +++ b/chaco/tools/tool_history_mixin.py @@ -5,7 +5,7 @@ class ToolHistoryMixin(HasTraits): - """ A mix-in class for tools to maintain a tool state history and to move + """A mix-in class for tools to maintain a tool state history and to move backwards and forwards through that history stack. This mix-in listens for keypressed events; to handle keypresses in a @@ -28,12 +28,12 @@ class ToolHistoryMixin(HasTraits): # The current index into _history _history_index = Int - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Abstract methods that subclasses must implement to handle keypresses - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _next_state_pressed(self): - """ Called when the tool needs to advance to the next state in the + """Called when the tool needs to advance to the next state in the stack. The **_history_index** will have already been set to the index @@ -42,7 +42,7 @@ def _next_state_pressed(self): pass def _prev_state_pressed(self): - """ Called when the tool needs to advance to the previous state in the + """Called when the tool needs to advance to the previous state in the stack. The **_history_index** will have already been set to the index @@ -51,44 +51,42 @@ def _prev_state_pressed(self): pass def _reset_state_pressed(self): - """ Called when the tool needs to reset its history. + """Called when the tool needs to reset its history. The history index will have already been set to 0. """ pass - - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Protected methods for subclasses to use - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _current_state(self): - """ Returns the current history state. - """ + """Returns the current history state.""" return self._history[self._history_index] def _reset_state(self, state): - """ Clears the history stack and sets the first or original state in + """Clears the history stack and sets the first or original state in the history to *state*. """ self._history = [state] self._history_index = 0 def _append_state(self, state, set_index=True): - """ Clears the history after the current **_history_index**, and + """Clears the history after the current **_history_index**, and appends the given state to the history. If *set_index* is True, the method sets the **_history_index** to match the new, truncated history. If it is False, the history index is unchanged. """ - new_history = self._history[:self._history_index+1] + [state] + new_history = self._history[: self._history_index + 1] + [state] self._history = new_history if set_index: self._history_index = len(self._history) - 1 def _pop_state(self): - """ Pops the most last state off the history stack. + """Pops the most last state off the history stack. If the history index points to the end of the stack, then it is adjusted; otherwise, the index is unaffected. If the stack is empty, @@ -104,12 +102,12 @@ def _pop_state(self): return self._history.pop() - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Private methods / event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def normal_key_pressed(self, event): - """ Handles a key being pressed, and takes appropriate action if it is + """Handles a key being pressed, and takes appropriate action if it is one of the history keys defined for this class. """ self._history_handle_key(event) diff --git a/chaco/tools/tool_states.py b/chaco/tools/tool_states.py index 6e990f3f7..70e70647c 100644 --- a/chaco/tools/tool_states.py +++ b/chaco/tools/tool_states.py @@ -3,7 +3,6 @@ class ToolState(HasTraits): - def __init__(self, prev, next): self.prev = prev self.next = next @@ -16,7 +15,6 @@ def revert(self, tool): class GroupedToolState(ToolState): - def __init__(self, states): self.states = states @@ -30,7 +28,6 @@ def revert(self, tool): class PanState(ToolState): - def apply(self, tool): if isinstance(tool.component.index_mapper, GridMapper): index_mapper = tool.component.index_mapper._xmapper @@ -41,18 +38,20 @@ def apply(self, tool): if self.next[0] != self.prev[0]: high = index_mapper.range.high low = index_mapper.range.low - range = high-low + range = high - low - index_mapper.range.set_bounds(low=self.next[0] - range/2, - high=self.next[0] + range/2) + index_mapper.range.set_bounds( + low=self.next[0] - range / 2, high=self.next[0] + range / 2 + ) if self.next[1] != self.prev[1]: high = value_mapper.range.high low = value_mapper.range.low - range = high-low + range = high - low - value_mapper.range.set_bounds(low=self.next[1] - range/2, - high=self.next[1] + range/2) + value_mapper.range.set_bounds( + low=self.next[1] - range / 2, high=self.next[1] + range / 2 + ) def revert(self, tool): if isinstance(tool.component.index_mapper, GridMapper): @@ -65,31 +64,33 @@ def revert(self, tool): if self.next[0] != self.prev[0]: high = index_mapper.range.high low = index_mapper.range.low - range = high-low + range = high - low - index_mapper.range.set_bounds(low=self.prev[0] - range/2, - high=self.prev[0] + range/2) + index_mapper.range.set_bounds( + low=self.prev[0] - range / 2, high=self.prev[0] + range / 2 + ) if self.next[1] != self.prev[1]: high = value_mapper.range.high low = value_mapper.range.low - range = high-low + range = high - low - index_mapper.range.set_bounds(low=self.prev[1] - range/2, - high=self.prev[1] + range/2) + index_mapper.range.set_bounds( + low=self.prev[1] - range / 2, high=self.prev[1] + range / 2 + ) class ZoomState(ToolState): - """ A zoom state which can be applied and reverted. + """A zoom state which can be applied and reverted. - This class exists so that subclasses can introduce new types - of events which can be applied and reverted in the same manner. - This greatly eases the code for managing history + This class exists so that subclasses can introduce new types + of events which can be applied and reverted in the same manner. + This greatly eases the code for managing history """ def apply(self, zoom_tool): - index_factor = self.next[0]/self.prev[0] - value_factor = self.next[1]/self.prev[1] + index_factor = self.next[0] / self.prev[0] + value_factor = self.next[1] / self.prev[1] if isinstance(zoom_tool.component.index_mapper, GridMapper): index_mapper = zoom_tool.component.index_mapper._xmapper @@ -117,17 +118,14 @@ def revert(self, zoom_tool): index_mapper = zoom_tool.component.index_mapper value_mapper = zoom_tool.component.value_mapper - zoom_tool._zoom_in_mapper(index_mapper, - self.prev[0]/self.next[0]) - zoom_tool._zoom_in_mapper(value_mapper, - self.prev[1]/self.next[1]) + zoom_tool._zoom_in_mapper(index_mapper, self.prev[0] / self.next[0]) + zoom_tool._zoom_in_mapper(value_mapper, self.prev[1] / self.next[1]) zoom_tool._index_factor = self.prev[0] zoom_tool._value_factor = self.prev[1] class SelectedZoomState(ZoomState): - def apply(self, zoom_tool): x_mapper = zoom_tool._get_x_mapper() y_mapper = zoom_tool._get_y_mapper() diff --git a/chaco/tools/toolbars/plot_toolbar.py b/chaco/tools/toolbars/plot_toolbar.py index 0dc5d8094..12ed2bcbc 100644 --- a/chaco/tools/toolbars/plot_toolbar.py +++ b/chaco/tools/toolbars/plot_toolbar.py @@ -1,11 +1,15 @@ - - import numpy from chaco.abstract_overlay import AbstractOverlay -from chaco.tools.toolbars.toolbar_buttons import ToolbarButton, \ - IndexAxisLogButton, ValueAxisLogButton, SaveAsButton, \ - CopyToClipboardButton, ZoomResetButton, ExportDataToClipboardButton +from chaco.tools.toolbars.toolbar_buttons import ( + ToolbarButton, + IndexAxisLogButton, + ValueAxisLogButton, + SaveAsButton, + CopyToClipboardButton, + ZoomResetButton, + ExportDataToClipboardButton, +) from enable.api import Container from enable.tools.api import HoverTool from traits.api import Bool, Float, observe, List, Tuple, Type, Enum @@ -22,7 +26,7 @@ def normal_mouse_move(self, event): super(PlotToolbarHover, self).normal_mouse_move(event) def on_hover(self): - """ This gets called when all the conditions of the hover action have + """This gets called when all the conditions of the hover action have been met, and the tool determines that the mouse is, in fact, hovering over a target region on the component. @@ -33,12 +37,11 @@ def on_hover(self): self.callback(component.label) return - self.callback('') + self.callback("") class PlotToolbar(Container, AbstractOverlay): - """ A toolbar for embedding buttons in - """ + """A toolbar for embedding buttons in""" buttons = List(Type(ToolbarButton)) @@ -63,7 +66,7 @@ class PlotToolbar(Container, AbstractOverlay): vertical_padding = Float(5.0) # The edge against which the toolbar is placed. - location = Enum('top', 'right', 'bottom', 'left') + location = Enum("top", "right", "bottom", "left") # Should tooltips be shown? show_tooltips = Bool(False) @@ -76,7 +79,7 @@ def __init__(self, component=None, *args, **kw): super(PlotToolbar, self).__init__(*args, **kw) self.component = component - if component is not None and hasattr(component, 'toolbar_location'): + if component is not None and hasattr(component, "toolbar_location"): self.location = component.toolbar_location for buttontype in self.buttons: @@ -85,27 +88,30 @@ def __init__(self, component=None, *args, **kw): hover_tool = PlotToolbarHover(component=self, callback=self.on_hover) self.tools.append(hover_tool) - if self.location in ['top', 'bottom']: + if self.location in ["top", "bottom"]: self._calculate_width() else: self._calculate_height() def _buttons_default(self): - return [IndexAxisLogButton, ValueAxisLogButton, - SaveAsButton, CopyToClipboardButton, - ExportDataToClipboardButton, ZoomResetButton] + return [ + IndexAxisLogButton, + ValueAxisLogButton, + SaveAsButton, + CopyToClipboardButton, + ExportDataToClipboardButton, + ZoomResetButton, + ] def add_button(self, button): - """ adds a button to the toolbar - """ + """adds a button to the toolbar""" self.add(button) button.toolbar_overlay = self self._layout_needed = True def normal_mouse_move(self, event): - """ handler for normal mouse move - """ - self.on_hover('') + """handler for normal mouse move""" + self.on_hover("") if self.hiding: self.hiding = False @@ -114,8 +120,7 @@ def on_hover(self, tooltip): self.component.window.set_tooltip(tooltip) def normal_left_down(self, event): - """ handler for a left mouse click - """ + """handler for a left mouse click""" if self.hiding: return else: @@ -130,8 +135,7 @@ def normal_left_down(self, event): ############################################################ def overlay(self, other_component, gc, view_bounds=None, mode="normal"): - """ Draws this component overlaid on another component. - """ + """Draws this component overlaid on another component.""" starting_color = numpy.array([0.0, 1.0, 1.0, 1.0, 0.5]) ending_color = numpy.array([1.0, 0.0, 0.0, 0.0, 0.5]) @@ -143,27 +147,27 @@ def overlay(self, other_component, gc, view_bounds=None, mode="normal"): with gc: gc.begin_path() gc.move_to(x + self.end_radius, y) - gc.arc_to(x + self.width, y, - x + self.width, y + self.end_radius, - self.end_radius) - gc.arc_to(x + self.width, y + height, - x + self.width - self.end_radius, y + height, - self.end_radius) - gc.arc_to(x, y + height, - x, y + height - self.end_radius, - self.end_radius) - gc.arc_to(x, y, - x + self.end_radius, y, - self.end_radius) - - if self.location in ['top', 'bottom']: - gc.linear_gradient(x, y, x, y + 100, - numpy.array([starting_color, ending_color]), - "pad") + gc.arc_to( + x + self.width, y, x + self.width, y + self.end_radius, self.end_radius + ) + gc.arc_to( + x + self.width, + y + height, + x + self.width - self.end_radius, + y + height, + self.end_radius, + ) + gc.arc_to(x, y + height, x, y + height - self.end_radius, self.end_radius) + gc.arc_to(x, y, x + self.end_radius, y, self.end_radius) + + if self.location in ["top", "bottom"]: + gc.linear_gradient( + x, y, x, y + 100, numpy.array([starting_color, ending_color]), "pad" + ) else: - gc.linear_gradient(x, y, x + 100, y, - numpy.array([starting_color, ending_color]), - "pad") + gc.linear_gradient( + x, y, x + 100, y, numpy.array([starting_color, ending_color]), "pad" + ) gc.draw_path() @@ -180,51 +184,50 @@ def _do_layout(self, component=None): if component is None: component = self.component - if self.location in ['top', 'bottom']: + if self.location in ["top", "bottom"]: if self.hiding: self.height = height = 10 else: - tallest_button = max([button.height - for button in self.components]) - self.height = height = (tallest_button + - self.vertical_padding * 2) + tallest_button = max([button.height for button in self.components]) + self.height = height = tallest_button + self.vertical_padding * 2 else: if self.hiding: self.width = width = 10 else: - widest_button = max([button.width - for button in self.components]) - self.width = width = (widest_button + - self.horizontal_padding * 2) + widest_button = max([button.width for button in self.components]) + self.width = width = widest_button + self.horizontal_padding * 2 if component is not None: # Overlay positions are not relative to the component's position, # so we have to add in the component's position cx, cy = component.outer_position - if self.location is 'top': - self.x = (cx + (component.width - self.width) / 2 - + component.padding_left) - self.y = (cy + component.height + component.padding_bottom - - height - 2) - elif self.location is 'bottom': - self.x = (cx + (component.width - self.width) / 2 - + component.padding_left) + if self.location is "top": + self.x = ( + cx + (component.width - self.width) / 2 + component.padding_left + ) + self.y = cy + component.height + component.padding_bottom - height - 2 + elif self.location is "bottom": + self.x = ( + cx + (component.width - self.width) / 2 + component.padding_left + ) self.y = cy + component.padding_bottom + 2 - elif self.location is 'left': + elif self.location is "left": self.x = cx + component.padding_left + 2 - self.y = (cy + (component.height - self.height) / 2 - + component.padding_bottom) + self.y = ( + cy + (component.height - self.height) / 2 + component.padding_bottom + ) else: # 'right' - self.x = (cx + component.width + component.padding_left - - width - 2) - self.y = (cy + (component.height - self.height) / 2 - + component.padding_bottom) + self.x = cx + component.width + component.padding_left - width - 2 + self.y = ( + cy + (component.height - self.height) / 2 + component.padding_bottom + ) - if self.location in ['top', 'bottom']: + if self.location in ["top", "bottom"]: v_position = self.y + self.vertical_padding * 2 - last_button_position = (self.x + self.horizontal_padding - + self.button_spacing) + last_button_position = ( + self.x + self.horizontal_padding + self.button_spacing + ) for button in self.components: button.x = last_button_position button.y = v_position @@ -233,8 +236,7 @@ def _do_layout(self, component=None): # location is 'left' or 'right' h_position = self.x + self.horizontal_padding - last_button_position = (self.y + self.vertical_padding - + self.button_spacing) + last_button_position = self.y + self.vertical_padding + self.button_spacing for button in reversed(self.components): h_offset = (self.width - button.width) / 2 button.y = last_button_position @@ -243,9 +245,9 @@ def _do_layout(self, component=None): def _dispatch_stateful_event(self, event, suffix): if self.is_in(event.x, event.y): - if suffix == 'mouse_move': + if suffix == "mouse_move": self.normal_mouse_move(event) - elif suffix == 'left_down': + elif suffix == "left_down": self.normal_left_down(event) event.handled = True else: @@ -256,9 +258,9 @@ def _dispatch_stateful_event(self, event, suffix): # Trait handlers ############################################################ - @observe('components, location') + @observe("components, location") def _calculate_width(self, event=None): - if self.location in ['top', 'bottom']: + if self.location in ["top", "bottom"]: width = self.horizontal_padding * 2 for button in self.components: width += button.width + self.button_spacing * 2 @@ -267,9 +269,9 @@ def _calculate_width(self, event=None): self._layout_needed = True self.request_redraw() - @observe('components, location') + @observe("components, location") def _calculate_height(self, event=None): - if self.location in ['left', 'right']: + if self.location in ["left", "right"]: height = self.vertical_padding * 2 for button in self.components: height += button.height + self.button_spacing * 2 @@ -278,12 +280,12 @@ def _calculate_height(self, event=None): self._layout_needed = True self.request_redraw() - @observe('hiding') + @observe("hiding") def _set_layout_needed_and_redraw(self, event): self._layout_needed = True self.request_redraw() - @observe('auto_hide') + @observe("auto_hide") def _set_hiding_and_redraw(self, event): self.hiding = self.auto_hide self.request_redraw() diff --git a/chaco/tools/toolbars/toolbar_buttons.py b/chaco/tools/toolbars/toolbar_buttons.py index 981870be4..5f46ff49c 100644 --- a/chaco/tools/toolbars/toolbar_buttons.py +++ b/chaco/tools/toolbars/toolbar_buttons.py @@ -7,21 +7,20 @@ from kiva.image import Image from pyface.image_resource import ImageResource from pyface.api import FileDialog, OK, error -from traits.api import Instance, Str, Property, cached_property, \ - List, Int, Enum +from traits.api import Instance, Str, Property, cached_property, List, Int, Enum class ToolbarButton(Button): image = Str() _image = Instance(Image) - color = 'black' + color = "black" - width = Property(Int, depends_on='label, image') - height = Property(Int, depends_on='label, image') + width = Property(Int, depends_on="label, image") + height = Property(Int, depends_on="label, image") # bounds are used for hit testing - bounds = Property(List, depends_on='label, image') + bounds = Property(List, depends_on="label, image") def __init__(self, *args, **kw): super(ToolbarButton, self).__init__(*args, **kw) @@ -49,9 +48,10 @@ def _get_bounds(self): def _draw_actual_button(self, gc): x_offset = self.x + (self.width - self._image.width()) / 2 - gc.draw_image(self._image, - (x_offset, self.y + 2, self._image.width(), - self._image.height())) + gc.draw_image( + self._image, + (x_offset, self.y + 2, self._image.width(), self._image.height()), + ) if self.label is not None and len(self.label) > 0: gc.set_font(self.label_font) @@ -67,35 +67,35 @@ def _draw_actual_button(self, gc): class IndexAxisLogButton(ToolbarButton): - label = 'X Log Scale' - tooltip = 'Change index axis scale' - image = 'zoom-fit-width' + label = "X Log Scale" + tooltip = "Change index axis scale" + image = "zoom-fit-width" def perform(self, event): - if self.container.component.index_scale == 'linear': - self.container.component.index_scale = 'log' + if self.container.component.index_scale == "linear": + self.container.component.index_scale = "log" else: - self.container.component.index_scale = 'linear' + self.container.component.index_scale = "linear" self.container.request_redraw() class ValueAxisLogButton(ToolbarButton): - label = 'Y Log Scale' - tooltip = 'Change value axis scale' - image = 'zoom-fit-height' + label = "Y Log Scale" + tooltip = "Change value axis scale" + image = "zoom-fit-height" def perform(self, event): - if self.container.component.value_scale == 'linear': - self.container.component.value_scale = 'log' + if self.container.component.value_scale == "linear": + self.container.component.value_scale = "log" else: - self.container.component.value_scale = 'linear' + self.container.component.value_scale = "linear" self.container.request_redraw() class ZoomResetButton(ToolbarButton): - label = 'Zoom Reset' - tooltip = 'Zoom Reset' - image = 'zoom-original' + label = "Zoom Reset" + tooltip = "Zoom Reset" + image = "zoom-original" def perform(self, event): plot_component = self.container.component @@ -108,16 +108,16 @@ def perform(self, event): class SaveAsButton(ToolbarButton): - label = 'Save As' - tooltip = 'Save As' - image = 'document-save' + label = "Save As" + tooltip = "Save As" + image = "document-save" def perform(self, event): plot_component = self.container.component - filter = 'PNG file (*.png)|*.png|\nTIFF file (*.tiff)|*.tiff|' - dialog = FileDialog(action='save as', wildcard=filter) + filter = "PNG file (*.png)|*.png|\nTIFF file (*.tiff)|*.tiff|" + dialog = FileDialog(action="save as", wildcard=filter) if dialog.open() != OK: return @@ -135,11 +135,14 @@ def perform(self, event): try: gc.save(filename) except KeyError as e: - errmsg = ("The filename must have an extension that matches " - "a graphics format, such as '.png' or '.tiff'.") - if str(e.message) != '': - errmsg = ("Unknown filename extension: '%s'\n" % - str(e.message)) + errmsg + errmsg = ( + "The filename must have an extension that matches " + "a graphics format, such as '.png' or '.tiff'." + ) + if str(e.message) != "": + errmsg = ( + "Unknown filename extension: '%s'\n" % str(e.message) + ) + errmsg error(None, errmsg, title="Invalid Filename Extension") @@ -149,8 +152,8 @@ def perform(self, event): class CopyToClipboardButton(ToolbarButton): label = "Copy Image" - tooltip = 'Copy to the clipboard' - image = 'edit-copy' + tooltip = "Copy to the clipboard" + image = "edit-copy" def perform(self, event): plot_component = self.container.component @@ -164,7 +167,7 @@ def perform(self, event): gc = PlotGraphicsContext((width, height), dpi=72) gc.render_component(plot_component) - if ETSConfig.toolkit == 'wx': + if ETSConfig.toolkit == "wx": self._perform_wx(width, height, gc) else: pass @@ -175,8 +178,7 @@ def perform(self, event): def _perform_wx(self, width, height, gc): import wx - bitmap = wx.BitmapFromBufferRGBA(width + 1, height + 1, - gc.bmp_array.flatten()) + bitmap = wx.BitmapFromBufferRGBA(width + 1, height + 1, gc.bmp_array.flatten()) data = wx.BitmapDataObject() data.SetBitmap(bitmap) if wx.TheClipboard.Open(): @@ -188,15 +190,15 @@ def _perform_wx(self, width, height, gc): class ExportDataToClipboardButton(ToolbarButton): label = "Copy Data" - tooltip = 'Copy data to the clipboard' - image = 'application-vnd-ms-excel' + tooltip = "Copy data to the clipboard" + image = "application-vnd-ms-excel" - orientation = Enum('v', 'h') + orientation = Enum("v", "h") def perform(self, event): - if ETSConfig.toolkit == 'wx': + if ETSConfig.toolkit == "wx": self._perform_wx() - elif ETSConfig.toolkit == 'qt4': + elif ETSConfig.toolkit == "qt4": self._perform_qt() else: pass @@ -216,12 +218,12 @@ def _serialize_data(self, indices, values): # otherwise go element by element adding the necessary empty strings if len(set([len(l) for l in values])) == 1: data = [indices[0]] + values - if self.orientation == 'v': + if self.orientation == "v": data = numpy.array(data).T.tolist() - data_str = '' + data_str = "" for row in data: - data_str += ','.join(['%f' % v for v in row]) + '\n' + data_str += ",".join(["%f" % v for v in row]) + "\n" return data_str else: @@ -248,4 +250,4 @@ def _perform_qt(self): indices, values = self._get_data_from_plots() data_str = self._serialize_data(indices, values) - QtGui.QApplication.clipboard().setText(data_str) \ No newline at end of file + QtGui.QApplication.clipboard().setText(data_str) diff --git a/chaco/tools/tracking_pan_tool.py b/chaco/tools/tracking_pan_tool.py index 17e6eaf5e..8054ae0bc 100644 --- a/chaco/tools/tracking_pan_tool.py +++ b/chaco/tools/tracking_pan_tool.py @@ -3,8 +3,9 @@ # Chaco imports from .pan_tool import PanTool + class TrackingPanTool(PanTool): - """ Allows the user to pan around a plot. + """Allows the user to pan around a plot. The user clicks a mouse button and drags to pan; the tool then returns to a tracking state. @@ -18,26 +19,26 @@ def _end_pan(self, event): if not self.constrain or self.constrain_direction == "x": high = xrange.high low = xrange.low - if xrange.default_state == 'low_track': + if xrange.default_state == "low_track": hi_val = max([source.get_bounds()[1] for source in xrange.sources]) if hi_val >= low and hi_val <= high: - xrange.set_bounds('track','auto') - elif xrange.default_state == 'high_track': + xrange.set_bounds("track", "auto") + elif xrange.default_state == "high_track": lo_val = min([source.get_bounds()[0] for source in xrange.sources]) if lo_val >= low and lo_val <= high: - xrange.set_bounds('auto','track') + xrange.set_bounds("auto", "track") if not self.constrain or self.constrain_direction == "y": high = yrange.high low = yrange.low - if yrange.default_state == 'low_track': + if yrange.default_state == "low_track": hi_val = max([source.get_bounds()[1] for source in yrange.sources]) if hi_val >= low and hi_val <= high: - yrange.set_bounds('track','auto') - elif yrange.default_state == 'high_track': + yrange.set_bounds("track", "auto") + elif yrange.default_state == "high_track": lo_val = min([source.get_bounds()[0] for source in yrange.sources]) if lo_val >= low and lo_val <= high: - yrange.set_bounds('auto','track') + yrange.set_bounds("auto", "track") if self._auto_constrain: self.constrain = False @@ -47,5 +48,4 @@ def _end_pan(self, event): if event.window.mouse_owner == self: event.window.set_mouse_owner(None) - event.handled = True diff --git a/chaco/tools/tracking_zoom.py b/chaco/tools/tracking_zoom.py index c17376bab..05d4ba4b9 100644 --- a/chaco/tools/tracking_zoom.py +++ b/chaco/tools/tracking_zoom.py @@ -4,8 +4,9 @@ # Chaco imports from .zoom_tool import ZoomTool + class TrackingZoom(ZoomTool): - """ Allows the user to zoom in or out on a plot that is using tracking. + """Allows the user to zoom in or out on a plot that is using tracking. The **default_state** of the data range determines the tracking behavior. For example, if the data range's **default_state** is "low_track", @@ -14,9 +15,8 @@ class TrackingZoom(ZoomTool): for "high_track"). """ - def normal_mouse_wheel(self, event): - """ Handles the mouse wheel being used when the tool is in the 'normal' + """Handles the mouse wheel being used when the tool is in the 'normal' state. Overrides ZoomTool @@ -47,7 +47,7 @@ def normal_mouse_wheel(self, event): newlow = mouse_val - zoom * (mouse_val - low_pt[ndx]) newhigh = mouse_val + zoom * (high_pt[ndx] - mouse_val) - if type(orig_high) in (tuple,list): + if type(orig_high) in (tuple, list): ol, oh = orig_low[ndx], orig_high[ndx] else: ol, oh = orig_low, orig_high @@ -56,21 +56,21 @@ def normal_mouse_wheel(self, event): event.handled = True return - if datarange.default_state == 'low_track': + if datarange.default_state == "low_track": hi = max([source.get_bounds()[1] for source in datarange.sources]) - #is hi in the current view? + # is hi in the current view? if hi >= low_pt[ndx] and hi <= high_pt[ndx]: datarange.scale_tracking_amount(zoom) - newhigh = 'auto' - newlow = 'track' + newhigh = "auto" + newlow = "track" - elif datarange.default_state == 'high_track': + elif datarange.default_state == "high_track": lo = min([source.get_bounds()[0] for source in datarange.sources]) - #is lo in the current view? + # is lo in the current view? if lo >= low_pt[ndx] and lo <= high_pt[ndx]: datarange.scale_tracking_amount(zoom) - newlow = 'auto' - newhigh = 'track' + newlow = "auto" + newhigh = "track" datarange.set_bounds(newlow, newhigh) event.handled = True diff --git a/chaco/tools/traits_tool.py b/chaco/tools/traits_tool.py index a363e9ea5..9c1a86091 100755 --- a/chaco/tools/traits_tool.py +++ b/chaco/tools/traits_tool.py @@ -11,23 +11,28 @@ class Fifo(object): - """ Slightly-modified version of the Fifo class from the Python cookbook: - http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68436 + """Slightly-modified version of the Fifo class from the Python cookbook: + http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68436 """ + def __init__(self): self.nextin = 0 self.nextout = 0 self.data = {} + def append(self, value): self.data[self.nextin] = value self.nextin += 1 + def extend(self, values): if len(values) > 0: - for i,val in enumerate(values): - self.data[i+self.nextin] = val - self.nextin += i+1 + for i, val in enumerate(values): + self.data[i + self.nextin] = val + self.nextin += i + 1 + def isempty(self): return self.nextout >= self.nextin + def pop(self): value = self.data[self.nextout] del self.data[self.nextout] @@ -36,7 +41,7 @@ def pop(self): def get_nested_components(container, classes): - """ Returns a list of fundamental plotting components from a container + """Returns a list of fundamental plotting components from a container with nested containers. Performs a breadth-first search of the containment hierarchy. Each element @@ -45,11 +50,11 @@ def get_nested_components(container, classes): """ components = [] worklist = Fifo() - worklist.append((container, (0,0))) + worklist.append((container, (0, 0))) while 1: item, offset = worklist.pop() if isinstance(item, Container): - new_offset = (offset[0]+item.x, offset[1]+item.y) + new_offset = (offset[0] + item.x, offset[1] + item.y) for c in item.components: worklist.append((c, new_offset)) for overlay in item.overlays + item.underlays: @@ -64,8 +69,7 @@ def get_nested_components(container, classes): class TraitsTool(BaseTool): - """ Tool to edit the traits of plots, grids, and axes. - """ + """Tool to edit the traits of plots, grids, and axes.""" #: This tool does not have a visual representation (overrides BaseTool). draw_mode = "none" @@ -79,12 +83,12 @@ class TraitsTool(BaseTool): views = Dict #: The event to trigger the edit on - event = Str('left_dclick') + event = Str("left_dclick") def _dispatch_stateful_event(self, event, suffix): """If the event type matches the specification in *event*, look for a component that - matches one of the classes in *classes* in our containment hierarchy. If one is found, - edit it using either the default editor, or an alternate editor specified in *views* + matches one of the classes in *classes* in our containment hierarchy. If one is found, + edit it using either the default editor, or an alternate editor specified in *views* """ if suffix != self.event: return @@ -102,19 +106,20 @@ def _dispatch_stateful_event(self, event, suffix): # Hittest against all the candidate and take the first one item = None for candidate, offset in candidates: - if candidate.is_in(x-offset[0], y-offset[1]): - item=candidate + if candidate.is_in(x - offset[0], y - offset[1]): + item = candidate break if item is not None: self.component.active_tool = self if item.__class__ in self.views: - item.edit_traits(kind="livemodal", - view=self.views[item.__class__], - parent=event.window.control) + item.edit_traits( + kind="livemodal", + view=self.views[item.__class__], + parent=event.window.control, + ) else: - item.edit_traits(kind="livemodal", - parent=event.window.control) + item.edit_traits(kind="livemodal", parent=event.window.control) event.handled = True self.component.active_tool = None item.request_redraw() diff --git a/chaco/tooltip.py b/chaco/tooltip.py index 555baa4be..61192b929 100644 --- a/chaco/tooltip.py +++ b/chaco/tooltip.py @@ -2,7 +2,6 @@ """ - from numpy import array # Enthought library imports @@ -19,10 +18,10 @@ class ToolTip(AbstractOverlay): - """ An overlay that is a toolip. - """ + """An overlay that is a toolip.""" + #: The font to render the tooltip. - font = KivaFont('modern 10') + font = KivaFont("modern 10") #: The color of the text in the tooltip text_color = black_color_trait @@ -54,9 +53,9 @@ class ToolTip(AbstractOverlay): #: Use a white background color (overrides AbstractOverlay). bgcolor = white_color_trait - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Private Traits - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- _font_metrics_provider = Any() @@ -66,23 +65,23 @@ class ToolTip(AbstractOverlay): _total_line_height = Float(0.0) - def draw(self, gc, view_bounds=None, mode='normal'): - """ Draws the plot component. + def draw(self, gc, view_bounds=None, mode="normal"): + """Draws the plot component. Overrides PlotComponent. """ - self.overlay(self, gc, view_bounds=view_bounds, mode='normal') + self.overlay(self, gc, view_bounds=view_bounds, mode="normal") - def overlay(self, component, gc, view_bounds=None, mode='normal'): - """ Draws the tooltip overlaid on another component. + def overlay(self, component, gc, view_bounds=None, mode="normal"): + """Draws the tooltip overlaid on another component. Overrides AbstractOverlay. """ self.do_layout() PlotComponent._draw(self, gc, view_bounds, mode) - def _draw_overlay(self, gc, view_bounds=None, mode='normal'): - """ Draws the overlay layer of a component. + def _draw_overlay(self, gc, view_bounds=None, mode="normal"): + """Draws the overlay layer of a component. Overrides PlotComponent. """ @@ -93,9 +92,9 @@ def _draw_overlay(self, gc, view_bounds=None, mode='normal'): for i, label in enumerate(self._cached_labels): label_height = self._cached_line_sizes[i][1] y -= label_height - gc.translate_ctm(0,y) + gc.translate_ctm(0, y) label.draw(gc) - gc.translate_ctm(0,-y) + gc.translate_ctm(0, -y) y -= self.line_spacing def _do_layout(self): @@ -107,14 +106,16 @@ def _do_layout(self): if not self._text_props_valid: self._recompute_text() - outer_bounds = [self._max_line_width + 2*self.border_padding + self.hpadding, - self._total_line_height + 2*self.border_padding + self.vpadding] + outer_bounds = [ + self._max_line_width + 2 * self.border_padding + self.hpadding, + self._total_line_height + 2 * self.border_padding + self.vpadding, + ] self.outer_bounds = outer_bounds if self.auto_adjust and self.component is not None: new_pos = list(self.outer_position) - for dimindex in (0,1): + for dimindex in (0, 1): pos = self.position[dimindex] extent = outer_bounds[dimindex] c_min = self.component.position[dimindex] @@ -137,18 +138,26 @@ def _do_layout(self): self._layout_needed = False def _recompute_text(self): - labels = [Label(text=line, font=self.font, margin=0, - bgcolor='transparent', border_width=0, - color=self.text_color, rotate_angle=self.rotate_angle) - for line in self.lines] + labels = [ + Label( + text=line, + font=self.font, + margin=0, + bgcolor="transparent", + border_width=0, + color=self.text_color, + rotate_angle=self.rotate_angle, + ) + for line in self.lines + ] dummy_gc = self._font_metrics_provider - line_sizes = array([label.get_width_height(dummy_gc) - for label in labels]) + line_sizes = array([label.get_width_height(dummy_gc) for label in labels]) self._cached_labels = labels self._cached_line_sizes = line_sizes - self._max_line_width = max(line_sizes[:,0]) - self._total_line_height = sum(line_sizes[:,1]) + \ - len(line_sizes-1)*self.line_spacing + self._max_line_width = max(line_sizes[:, 0]) + self._total_line_height = ( + sum(line_sizes[:, 1]) + len(line_sizes - 1) * self.line_spacing + ) self._layout_needed = True def __font_metrics_provider_default(self): diff --git a/chaco/transform_color_mapper.py b/chaco/transform_color_mapper.py index b5403dc21..e229baf7b 100644 --- a/chaco/transform_color_mapper.py +++ b/chaco/transform_color_mapper.py @@ -5,17 +5,18 @@ from .speedups import map_colors, map_colors_uint8 + class TransformColorMapper(ColorMapper): """This class adds arbitrary data transformations to a ColorMapper. - + The default ColorMapper is basically a linear mapper from data space to color space. A TransformColorMapper allows a nonlinear mapper to be created. - + A ColorMapper works by linearly transforming the data from data space to the unit interval [0,1], and then linearly mapping that interval to the color space. - + A TransformColorMapper allows an arbitrary transform to be inserted at two places in this process. First, an initial transformation, `data_func` can be applied to the data *before* is it mapped to [0,1]. Then another @@ -25,17 +26,16 @@ class TransformColorMapper(ColorMapper): """ data_func = Trait(None, None, Callable) - + unit_func = Trait(None, None, Callable) - - transformed_bounds = Tuple(Trait(None, None, Float), - Trait(None, None, Float)) - - #------------------------------------------------------------------- + + transformed_bounds = Tuple(Trait(None, None, Float), Trait(None, None, Float)) + + # ------------------------------------------------------------------- # Trait handlers - #------------------------------------------------------------------- + # ------------------------------------------------------------------- - @observe('data_func, range.updated') + @observe("data_func, range.updated") def _update_transformed_bounds(self, event): if self.range is None: @@ -55,25 +55,26 @@ def _update_transformed_bounds(self, event): def _unit_func_changed(self): self.updated = True - #------------------------------------------------------------------- + # ------------------------------------------------------------------- # Class methods - #------------------------------------------------------------------- + # ------------------------------------------------------------------- @classmethod - def from_color_mapper(cls, color_mapper, data_func=None, unit_func=None, - **traits): - """ Create a TransformColorMapper from an existing ColorMapper instance. - """ + def from_color_mapper(cls, color_mapper, data_func=None, unit_func=None, **traits): + """Create a TransformColorMapper from an existing ColorMapper instance.""" segdata = color_mapper._segmentdata - return cls.from_segment_map(segdata, range=color_mapper.range, - data_func=data_func, unit_func=unit_func, - **traits) + return cls.from_segment_map( + segdata, + range=color_mapper.range, + data_func=data_func, + unit_func=unit_func, + **traits + ) @classmethod - def from_color_map(cls, color_map, data_func=None, unit_func=None, - **traits): + def from_color_map(cls, color_map, data_func=None, unit_func=None, **traits): """Create a TransformColorMapper from a colormap generator function. - + The return value is an instance of TransformColorMapper, *not* a factory function, so this does not provide a direct replacement for a standard colormap factory function. For that, use the class method @@ -83,17 +84,22 @@ def from_color_map(cls, color_map, data_func=None, unit_func=None, # ColorMapper. color_mapper = color_map(None, **traits) segdata = color_mapper._segmentdata - return cls.from_segment_map(segdata, range=color_mapper.range, - data_func=data_func, unit_func=unit_func, - **traits) + return cls.from_segment_map( + segdata, + range=color_mapper.range, + data_func=data_func, + unit_func=unit_func, + **traits + ) @classmethod - def factory_from_color_map(cls, color_map, data_func=None, unit_func=None, - **traits): + def factory_from_color_map( + cls, color_map, data_func=None, unit_func=None, **traits + ): """ Create a TransformColorMapper factory function from a standard colormap factory function. - + WARNING: This function is untested; I realized I didn't need it shortly after writing it, so I haven't tried it yet. --WW """ @@ -102,54 +108,66 @@ def factory_from_color_map(cls, color_map, data_func=None, unit_func=None, color_mapper = color_map(None, **traits) def factory(range, **traits): - tcm = cls.from_color_mapper(color_mapper, - data_func=data_func, unit_func=unit_func, **traits) + tcm = cls.from_color_mapper( + color_mapper, data_func=data_func, unit_func=unit_func, **traits + ) return tcm return factory - #------------------------------------------------------------------- + # ------------------------------------------------------------------- # ColorMapper interface (these override methods from ColorMapper) - #------------------------------------------------------------------- + # ------------------------------------------------------------------- def map_screen(self, data_array): - """ Maps an array of data values to an array of colors. - """ + """Maps an array of data values to an array of colors.""" norm_data = self._compute_normalized_data(data_array) # The data are normalized, so we can pass low = 0, high = 1 - rgba = map_colors(norm_data, self.steps, 0, 1, self._red_lut, - self._green_lut, self._blue_lut, self._alpha_lut) + rgba = map_colors( + norm_data, + self.steps, + 0, + 1, + self._red_lut, + self._green_lut, + self._blue_lut, + self._alpha_lut, + ) return rgba - def map_index(self, data_array): - """ Maps an array of values to their corresponding color band index. - """ + """Maps an array of values to their corresponding color band index.""" norm_data = self._compute_normalized_data(data_array) - indices = (norm_data * (self.steps-1)).astype(int) + indices = (norm_data * (self.steps - 1)).astype(int) return indices def map_uint8(self, data_array): - """ Maps an array of data values to an array of colors. - """ + """Maps an array of data values to an array of colors.""" norm_data = self._compute_normalized_data(data_array) - rgba = map_colors_uint8(norm_data, self.steps, 0.0, 1.0, - self._red_lut_uint8, self._green_lut_uint8, - self._blue_lut_uint8, self._alpha_lut_uint8) + rgba = map_colors_uint8( + norm_data, + self.steps, + 0.0, + 1.0, + self._red_lut_uint8, + self._green_lut_uint8, + self._blue_lut_uint8, + self._alpha_lut_uint8, + ) return rgba - #------------------------------------------------------------------- + # ------------------------------------------------------------------- # Private methods - #------------------------------------------------------------------- + # ------------------------------------------------------------------- def _compute_normalized_data(self, data_array): """ Apply `data_func`, then linearly scale to the unit interval, and then apply `unit_func`. """ - + # FIXME: Deal with nans? if self._dirty: @@ -162,14 +180,14 @@ def _compute_normalized_data(self, data_array): low, high = self.range.low, self.range.high range_diff = high - low - # Linearly transform the values to the unit interval. + # Linearly transform the values to the unit interval. if range_diff == 0.0 or isinf(range_diff): - # Handle null range, or infinite range (which can happen during + # Handle null range, or infinite range (which can happen during # initialization before range is connected to a data source). - norm_data = 0.5*ones_like(data_array) + norm_data = 0.5 * ones_like(data_array) else: - norm_data = empty(data_array.shape, dtype='float32') + norm_data = empty(data_array.shape, dtype="float32") norm_data[:] = data_array norm_data -= low norm_data /= range_diff diff --git a/chaco/ui/axis_ui.py b/chaco/ui/axis_ui.py index e097e09ca..45f6c2755 100644 --- a/chaco/ui/axis_ui.py +++ b/chaco/ui/axis_ui.py @@ -9,80 +9,83 @@ from traitsui.api import View, Group, VGroup, HGroup, Item, TextEditor title_group = Group( - Item("title", label="Text", editor=TextEditor()), - # Fix me: We really don't have an reasonable font editor. - #Item("title_font", label="Font", style="custom"), - Item("title_color", label="Color", style="simple"), - ) + Item("title", label="Text", editor=TextEditor()), + # Fix me: We really don't have an reasonable font editor. + # Item("title_font", label="Font", style="custom"), + Item("title_color", label="Color", style="simple"), +) axis_line_group = Group( - Item("axis_line_visible", label="Visible"), - Group( - Item("axis_line_color", label="Color", style="simple"), - Item("axis_line_weight", label="Thickness"), - # Line Style - enabled_when='object.axis_line_visible==True', - ), - ) + Item("axis_line_visible", label="Visible"), + Group( + Item("axis_line_color", label="Color", style="simple"), + Item("axis_line_weight", label="Thickness"), + # Line Style + enabled_when="object.axis_line_visible==True", + ), +) tick_labels_group = Group( - # fix me: We need a 'Visible' trait on that determines - # whether tick labels are visible or not. - # Visible -- The rest should be in a group that is enabled - # by this. - # Fix me: Need an reasonable font editor. - #Item("tick_label_font", label="Font"), - Item("tick_label_color", label="Color", style="simple"), - # Fix me: set the rotation of the label. - # Rotation - # Fix me: Set the offset (in pixels?) of the label to - # allow people to "bump" them up or down. - # Offset - # Fix me: Are labels next to the axis or off the side of the - # plot? - # relative_to: axis|plot_min|plot_max - ) + # fix me: We need a 'Visible' trait on that determines + # whether tick labels are visible or not. + # Visible -- The rest should be in a group that is enabled + # by this. + # Fix me: Need an reasonable font editor. + # Item("tick_label_font", label="Font"), + Item("tick_label_color", label="Color", style="simple"), + # Fix me: set the rotation of the label. + # Rotation + # Fix me: Set the offset (in pixels?) of the label to + # allow people to "bump" them up or down. + # Offset + # Fix me: Are labels next to the axis or off the side of the + # plot? + # relative_to: axis|plot_min|plot_max +) tick_lines_group = Group( - Item("tick_visible", label="Visible"), - Group( - # These are the only non-axis part of the view... - HGroup( - # fix me: THe enabled_when is not working - # correctly. This failure began - # when we switched to using context. - Item("tick_interval_ui", label="Interval", - enabled_when = "object.tick_interval_auto_ui == False"), - Item("tick_interval_auto_ui", label="Auto"), - ), - Item("tick_color", label="Color", style="simple"), - Item("tick_weight", label="Thickness"), - #HGroup( - Item("tick_in", label="Tick in (pixels)"), - Item("tick_out", label="Tick out (pixels)"), - #), - enabled_when="object.tick_visible==True", - ), - ) + Item("tick_visible", label="Visible"), + Group( + # These are the only non-axis part of the view... + HGroup( + # fix me: THe enabled_when is not working + # correctly. This failure began + # when we switched to using context. + Item( + "tick_interval_ui", + label="Interval", + enabled_when="object.tick_interval_auto_ui == False", + ), + Item("tick_interval_auto_ui", label="Auto"), + ), + Item("tick_color", label="Color", style="simple"), + Item("tick_weight", label="Thickness"), + # HGroup( + Item("tick_in", label="Tick in (pixels)"), + Item("tick_out", label="Tick out (pixels)"), + # ), + enabled_when="object.tick_visible==True", + ), +) tick_lines_group = Group( - Item("tick_visible", label="Visible"), - Group( - Item("tick_color", label="Color", style="simple"), - Item("tick_weight", label="Thickness"), - Item("tick_in", label="Tick in (pixels)"), - Item("tick_out", label="Tick out (pixels)"), - # Fix me: We really need to split out the tick interval - # into a UI like this. - #HGroup( - # Item("tick_interval_ui", label="Interval", - # enabled_when = "object.tick_interval_auto_ui == False"), - # Item("tick_interval_auto_ui", label="Auto"), - #), - Item(label="Note: Tick Interval not currently settable."), - enabled_when="object.tick_visible==True", - ), - ) + Item("tick_visible", label="Visible"), + Group( + Item("tick_color", label="Color", style="simple"), + Item("tick_weight", label="Thickness"), + Item("tick_in", label="Tick in (pixels)"), + Item("tick_out", label="Tick out (pixels)"), + # Fix me: We really need to split out the tick interval + # into a UI like this. + # HGroup( + # Item("tick_interval_ui", label="Interval", + # enabled_when = "object.tick_interval_auto_ui == False"), + # Item("tick_interval_auto_ui", label="Auto"), + # ), + Item(label="Note: Tick Interval not currently settable."), + enabled_when="object.tick_visible==True", + ), +) # We are missing a group to specify the "scale" or "range" setting @@ -90,18 +93,17 @@ # The main view for an axis... default_view = View( - VGroup(Group(title_group, label='Title', show_border=True), - Group(axis_line_group, label='Axis Line', show_border=True), - HGroup( - Group(tick_lines_group, - label='Tick Lines', show_border=True), - Group(tick_labels_group, - label='Labels', show_border=True), - label='Ticks', - ), - layout="tabbed", - ), - buttons = ["OK", "Cancel"], - ) + VGroup( + Group(title_group, label="Title", show_border=True), + Group(axis_line_group, label="Axis Line", show_border=True), + HGroup( + Group(tick_lines_group, label="Tick Lines", show_border=True), + Group(tick_labels_group, label="Labels", show_border=True), + label="Ticks", + ), + layout="tabbed", + ), + buttons=["OK", "Cancel"], +) # Fix me: Should we do something here where we register this with the Axis object? diff --git a/chaco/ui/plot_window.py b/chaco/ui/plot_window.py index ff1619f3f..6c41bfb7b 100644 --- a/chaco/ui/plot_window.py +++ b/chaco/ui/plot_window.py @@ -4,15 +4,18 @@ from enable.api import Container from enable.component_editor import ComponentEditor + class PlotWindow(HasTraits): plot = Instance(Container) - traits_view = View(Item('plot', - editor=ComponentEditor(), - height=300, - width=500, - show_label=False, - ), - title='Chaco Plot', - resizable=True - ) + traits_view = View( + Item( + "plot", + editor=ComponentEditor(), + height=300, + width=500, + show_label=False, + ), + title="Chaco Plot", + resizable=True, + ) diff --git a/chaco/ui/popupable_plot.py b/chaco/ui/popupable_plot.py index 1b1a199be..4e08e6fe0 100644 --- a/chaco/ui/popupable_plot.py +++ b/chaco/ui/popupable_plot.py @@ -8,8 +8,10 @@ from traitsui.wx.constants import WindowColor + class PopupablePlot(Plot): """A Plot class that pops up in a new window on double click""" + # FIXME: It would be nice to queue up other types of commands and settings command_queue = List() @@ -25,7 +27,7 @@ def normal_left_dclick(self, event): plot.tools.append(PanTool(plot)) plot.overlays.append(ZoomTool(plot)) window = PlotWindow(plot=container) - window.edit_traits(kind='live', parent=event.window.control) + window.edit_traits(kind="live", parent=event.window.control) def plot(self, data, **kw): """Queue up the plot commands""" From f3a64667859df08989fe34af51aad83f4f4a8ed6 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Fri, 2 Apr 2021 10:40:50 -0500 Subject: [PATCH 2/7] black examples --- .../demo/advanced/asynchronous_updates.py | 104 ++-- .../advanced/cmap_variable_sized_scatter.py | 66 ++- examples/demo/advanced/data_cube.py | 221 +++++--- examples/demo/advanced/data_stream.py | 88 +-- .../demo/advanced/javascript_hover_tools.py | 162 +++--- .../scalar_image_function_inspector.py | 532 ++++++++++-------- .../scalar_image_function_inspector_old.py | 458 +++++++++------ examples/demo/advanced/spec_waterfall.py | 115 ++-- examples/demo/advanced/spectrum.py | 109 ++-- examples/demo/aspect_ratio.py | 39 +- examples/demo/basic/bar_plot_configurable.py | 61 +- examples/demo/basic/bar_plot_stacked.py | 51 +- examples/demo/basic/bounded_grids.py | 36 +- examples/demo/basic/candle.py | 55 +- .../demo/basic/cmap_image_aspect_ratio.py | 42 +- examples/demo/basic/cmap_image_plot.py | 43 +- examples/demo/basic/cmap_image_select.py | 98 ++-- examples/demo/basic/cmap_scatter.py | 106 ++-- examples/demo/basic/cmap_segment_plot.py | 98 ++-- examples/demo/basic/contour_cmap_plot.py | 122 ++-- examples/demo/basic/contour_plot.py | 50 +- .../demo/basic/discrete_cmap_image_plot.py | 42 +- examples/demo/basic/discrete_cmap_scatter.py | 102 ++-- examples/demo/basic/draw_layers.py | 37 +- examples/demo/basic/grid_container.py | 79 +-- .../demo/basic/grid_container_aspect_ratio.py | 61 +- examples/demo/basic/hittest_tool.py | 63 ++- examples/demo/basic/horizon_plot.py | 161 +++--- examples/demo/basic/image_from_file.py | 88 +-- examples/demo/basic/image_inspector.py | 57 +- examples/demo/basic/image_lasso.py | 49 +- examples/demo/basic/image_plot.py | 57 +- examples/demo/basic/inset_plot.py | 39 +- examples/demo/basic/line_drawing.py | 59 +- examples/demo/basic/line_plot1.py | 42 +- examples/demo/basic/line_plot_hold.py | 56 +- examples/demo/basic/log_plot.py | 39 +- examples/demo/basic/minard_napoleon.py | 237 ++++---- examples/demo/basic/minor_ticks_axis.py | 22 +- examples/demo/basic/nans_plot.py | 34 +- examples/demo/basic/pandas_data.py | 13 +- examples/demo/basic/polygon_move.py | 62 +- examples/demo/basic/polygon_plot_demo.py | 65 ++- examples/demo/basic/regression.py | 38 +- examples/demo/basic/scatter.py | 50 +- examples/demo/basic/scatter_1d.py | 85 ++- examples/demo/basic/scatter_alpha.py | 58 +- examples/demo/basic/scatter_custom_marker.py | 55 +- examples/demo/basic/scatter_inspector.py | 50 +- examples/demo/basic/scatter_inspector2.py | 44 +- examples/demo/basic/scatter_rect_select.py | 48 +- examples/demo/basic/scatter_select.py | 80 +-- examples/demo/basic/scatter_toggle.py | 91 +-- examples/demo/basic/scatter_variable_size.py | 50 +- examples/demo/basic/scrollbar.py | 41 +- examples/demo/basic/segment_plot.py | 50 +- examples/demo/basic/tabbed_plots.py | 27 +- examples/demo/basic/traits_editor.py | 66 +-- examples/demo/basic/zoomable_colorbar.py | 85 +-- examples/demo/bigdata.py | 47 +- examples/demo/canvas/axis_tool.py | 16 +- examples/demo/canvas/canvas.py | 261 ++++++--- examples/demo/canvas/cliptest.py | 29 +- examples/demo/canvas/data_source_button.py | 51 +- examples/demo/canvas/mp_move_tool.py | 5 +- examples/demo/canvas/mp_viewport_pan_tool.py | 8 +- examples/demo/canvas/mptools.py | 98 ++-- examples/demo/canvas/plot_clone_tool.py | 38 +- .../demo/canvas/transient_plot_overlay.py | 20 +- examples/demo/chaco_trait_editor.py | 59 +- examples/demo/coordinate_line_overlay_demo.py | 64 ++- examples/demo/cursor_tool_demo.py | 125 ++-- examples/demo/data_labels.py | 137 +++-- examples/demo/data_view.py | 51 +- examples/demo/demo.py | 10 +- examples/demo/depth.py | 20 +- examples/demo/domain_limits.py | 23 +- examples/demo/edit_line.py | 86 +-- examples/demo/financial/correlations.py | 141 +++-- examples/demo/financial/stock_prices.py | 148 +++-- examples/demo/financial_plot.py | 145 +++-- examples/demo/financial_plot_dates.py | 172 +++--- examples/demo/functionplotter.py | 107 ++-- .../demo/image_plot_origin_and_orientation.py | 44 +- examples/demo/logo.py | 36 +- examples/demo/multi_line_plot.py | 39 +- examples/demo/multi_line_plot_demo.py | 92 +-- examples/demo/multiaxis.py | 56 +- examples/demo/multiaxis_using_Plot.py | 41 +- examples/demo/noninteractive.py | 36 +- examples/demo/nonlinear_color_mapping.py | 194 ++++--- examples/demo/qt_example.py | 7 +- examples/demo/quiver.py | 24 +- examples/demo/range_selection_demo.py | 42 +- examples/demo/scales_test.py | 121 ++-- examples/demo/shell/add_tool.py | 17 +- examples/demo/shell/contour.py | 10 +- examples/demo/shell/contourf.py | 8 +- examples/demo/shell/dates.py | 8 +- examples/demo/shell/imshow.py | 8 +- examples/demo/shell/lines.py | 2 +- examples/demo/shell/loglog.py | 4 +- examples/demo/shell/pcolor.py | 10 +- examples/demo/shell/scatter.py | 2 +- examples/demo/shell/semilog.py | 3 +- examples/demo/simple_line.py | 59 +- examples/demo/simple_polar.py | 42 +- examples/demo/stacked_axis.py | 78 +-- examples/demo/status_overlay.py | 55 +- examples/demo/toolbar_plot.py | 25 +- examples/demo/tornado.py | 118 ++-- examples/demo/two_plots.py | 52 +- examples/demo/updating_plot/updating_plot1.py | 23 +- examples/demo/updating_plot/updating_plot2.py | 39 +- examples/demo/updating_plot/updating_plot3.py | 52 +- examples/demo/updating_plot/updating_plot4.py | 57 +- examples/demo/updating_plot/updating_plot5.py | 56 +- examples/demo/vertical_plot.py | 70 ++- examples/demo/vtk/cmap_scatter.py | 108 ++-- examples/demo/vtk/spectrum.py | 107 ++-- examples/demo/vtk/vtk_example.py | 49 +- examples/demo/vtk_example.py | 48 +- examples/demo/world_map.py | 49 +- examples/demo/xray_plot.py | 67 +-- .../demo/zoomed_plot/grid_plot_factory.py | 236 ++++---- examples/demo/zoomed_plot/wav_to_numeric.py | 49 +- examples/demo/zoomed_plot/zoom_overlay.py | 14 +- examples/demo/zoomed_plot/zoom_plot.py | 148 ++--- .../scipy2008/connected_orientation.py | 21 +- .../tutorials/scipy2008/connected_range.py | 22 +- .../scipy2008/connected_single_range.py | 23 +- .../tutorials/scipy2008/connected_widgets.py | 24 +- examples/tutorials/scipy2008/container.py | 24 +- .../tutorials/scipy2008/container_nospace.py | 21 +- .../tutorials/scipy2008/container_vertical.py | 23 +- .../tutorials/scipy2008/custom_overlay.py | 52 +- .../scipy2008/custom_overlay_dataspace.py | 60 +- .../scipy2008/custom_overlay_movetool.py | 60 +- examples/tutorials/scipy2008/custom_tool.py | 24 +- .../tutorials/scipy2008/custom_tool_click.py | 26 +- .../tutorials/scipy2008/custom_tool_screen.py | 26 +- examples/tutorials/scipy2008/data_chooser.py | 25 +- examples/tutorials/scipy2008/first_plot.py | 25 +- examples/tutorials/scipy2008/image.py | 23 +- examples/tutorials/scipy2008/overlapping.py | 20 +- examples/tutorials/scipy2008/ploteditor.py | 39 +- examples/tutorials/scipy2008/scatter.py | 23 +- examples/tutorials/scipy2008/tool_chooser.py | 25 +- examples/tutorials/scipy2008/tools.py | 22 +- .../tutorials/scipy2008/traits_example.py | 32 +- examples/tutorials/scipy2008/traits_image.py | 34 +- examples/tutorials/tutor.py | 10 +- examples/tutorials/tutorial1.py | 23 +- examples/tutorials/tutorial10.py | 11 +- examples/tutorials/tutorial10b.py | 11 +- examples/tutorials/tutorial11.py | 45 +- examples/tutorials/tutorial2.py | 7 +- examples/tutorials/tutorial2_ipython.py | 6 +- examples/tutorials/tutorial6.py | 2 + examples/tutorials/tutorial7.py | 2 + examples/tutorials/tutorial8.py | 34 +- examples/tutorials/tutorial9.py | 7 +- examples/tutorials/tutorial9b.py | 5 +- examples/user_guide/grid_plot_container.py | 29 +- examples/user_guide/h_plot_container.py | 15 +- .../h_plot_container_add_multiple_times.py | 17 +- .../user_guide/h_plot_container_colorbar.py | 31 +- .../user_guide/overlay_container_inset.py | 22 +- .../plot_types/create_plot_snapshots.py | 377 +++++++------ examples/user_guide/plot_types/plot_window.py | 19 +- examples/user_guide/power_function_example.py | 35 +- 171 files changed, 6080 insertions(+), 4606 deletions(-) diff --git a/examples/demo/advanced/asynchronous_updates.py b/examples/demo/advanced/asynchronous_updates.py index b63c50f28..0a3a6208b 100644 --- a/examples/demo/advanced/asynchronous_updates.py +++ b/examples/demo/advanced/asynchronous_updates.py @@ -13,19 +13,19 @@ # Enthought library imports from enable.api import Component, ComponentEditor -from traits.api import ( - Array, Bool, DelegatesTo, HasTraits, Instance, Range, observe -) +from traits.api import Array, Bool, DelegatesTo, HasTraits, Instance, Range, observe from traits.trait_notifiers import ui_dispatch from traitsui.api import Item, Group, View try: - from encore.concurrent.futures.enhanced_thread_pool_executor import \ - EnhancedThreadPoolExecutor + from encore.concurrent.futures.enhanced_thread_pool_executor import ( + EnhancedThreadPoolExecutor, + ) from encore.concurrent.futures.asynchronizer import Asynchronizer except ImportError: import sys - sys.exit('You need futures and encore installed to run this demo.') + + sys.exit("You need futures and encore installed to run this demo.") # Chaco imports from chaco.api import ArrayPlotData, Plot, VPlotContainer, gray @@ -34,9 +34,9 @@ class BlurPlotController(HasTraits): """ Plot controller class for an image plot and its blurred output """ - #========================================================================== + # ========================================================================== # Synchronization logic - #========================================================================== + # ========================================================================== # Flag indicating whether updates are asynchronous. asynchronous = Bool(True) @@ -60,7 +60,7 @@ def __asynchronizer_default(self): # its own asynchronizer. return Asynchronizer(self._executor) - @observe('blur_level, image', post_init=True) + @observe("blur_level, image", post_init=True) def _recalculate_blurred_image(self, event): """ Blur the image either synchronously or with the asynchronizer """ image = self.image @@ -74,8 +74,7 @@ def _recalculate_blurred_image(self, event): # the asynchronizer's current job (if any) is complete. If another # job (presumably with a different blur_level) comes in before this # happens, this job will never be executed. - self._asynchronizer.submit(self._blur_and_notify_plot, image, - blur_level) + self._asynchronizer.submit(self._blur_and_notify_plot, image, blur_level) else: # This happens on the calling thread, which is the GUI thread when # a change in 'blur_level' comes from the GUI (as in this demo). @@ -94,12 +93,11 @@ def _blur_and_notify_plot(self, image, blur_level): # thread. Since this call is being executed on one of the executor's # worker threads, we must re-dispatch the data update to the UI thread # or suffer undefined consequences (possibly crashes). - ui_dispatch(self.plot_data.set_data, "blurred_image", - self.blurred_image) + ui_dispatch(self.plot_data.set_data, "blurred_image", self.blurred_image) - #========================================================================== + # ========================================================================== # Visualization logic - useful, but not the point of the demo - #========================================================================== + # ========================================================================== # An image array to display image = Array @@ -117,8 +115,8 @@ def _blur_and_notify_plot(self, image, blur_level): component = Instance(Component) def _image_default(self): - x, y = ogrid[-pi:pi:1024j, 0:2*pi:1024j] - z = (sin(11*x**2)**2 * sin(5*y**2))**2 + x, y = ogrid[-pi:pi:1024j, 0 : 2 * pi : 1024j] + z = (sin(11 * x ** 2) ** 2 * sin(5 * y ** 2)) ** 2 return z def _blurred_image_default(self): @@ -133,18 +131,22 @@ def _plot_data_default(self): def _component_default(self): padding = (25, 5, 5, 25) image_plot = Plot(self.plot_data, padding=padding) - image_plot.img_plot("image", - origin="top left", - xbounds=(-pi, pi), - ybounds=(-pi, pi), - colormap=gray) + image_plot.img_plot( + "image", + origin="top left", + xbounds=(-pi, pi), + ybounds=(-pi, pi), + colormap=gray, + ) blurred_image_plot = Plot(self.plot_data, padding=padding) - blurred_image_plot.img_plot("blurred_image", - origin="top left", - xbounds=(-pi, pi), - ybounds=(-pi, pi), - colormap=gray) + blurred_image_plot.img_plot( + "blurred_image", + origin="top left", + xbounds=(-pi, pi), + ybounds=(-pi, pi), + colormap=gray, + ) container = VPlotContainer() container.add(blurred_image_plot) @@ -156,58 +158,50 @@ def blur_image(image, blur_level): """ Blur the image using a potentially time-consuming algorithm """ blurred_image = image.copy() - for _ in range(blur_level**2): + for _ in range(blur_level ** 2): blurred_image[1:-1, 1:-1] += ( - blurred_image[:-2, 1:-1] + # top - blurred_image[2:, 1:-1] + # bottom - blurred_image[1:-1, :-2] + # left - blurred_image[1:-1, 2:] + # right - blurred_image[:-2, :-2] + # top-left - blurred_image[:-2, 2:] + # top-right - blurred_image[2:, :-2] + # bottom-left - blurred_image[2:, 2:] # bottom-right + blurred_image[:-2, 1:-1] + + blurred_image[2:, 1:-1] # top + + blurred_image[1:-1, :-2] # bottom + + blurred_image[1:-1, 2:] # left + + blurred_image[:-2, :-2] # right + + blurred_image[:-2, 2:] # top-left + + blurred_image[2:, :-2] # top-right + + blurred_image[2:, 2:] # bottom-left # bottom-right ) blurred_image /= 9 return blurred_image -#============================================================================== +# ============================================================================== # Attributes to use for the plot view. -#============================================================================== +# ============================================================================== size = (800, 600) title = "Image with asynchronous blurring" -#============================================================================== +# ============================================================================== # Demo class that is used by the demo.py application. -#============================================================================== +# ============================================================================== class Demo(HasTraits): plot_controller = Instance(BlurPlotController, ()) - component = DelegatesTo('plot_controller') + component = DelegatesTo("plot_controller") - blur_level = DelegatesTo('plot_controller') + blur_level = DelegatesTo("plot_controller") - asynchronous = DelegatesTo('plot_controller') + asynchronous = DelegatesTo("plot_controller") traits_view = View( Group( - Item( - 'component', - editor=ComponentEditor(size=size), - show_label=False - ), - Group( - Item('asynchronous'), - Item('blur_level'), - orientation="horizontal" - ), - orientation="vertical" + Item("component", editor=ComponentEditor(size=size), show_label=False), + Group(Item("asynchronous"), Item("blur_level"), orientation="horizontal"), + orientation="vertical", ), resizable=True, - title=title + title=title, ) diff --git a/examples/demo/advanced/cmap_variable_sized_scatter.py b/examples/demo/advanced/cmap_variable_sized_scatter.py index 7e323f2af..0d3451339 100644 --- a/examples/demo/advanced/cmap_variable_sized_scatter.py +++ b/examples/demo/advanced/cmap_variable_sized_scatter.py @@ -18,13 +18,20 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ArrayPlotData, Plot, ColormappedScatterPlot, \ - LinearMapper, ArrayDataSource, viridis, DataRange1D +from chaco.api import ( + ArrayPlotData, + Plot, + ColormappedScatterPlot, + LinearMapper, + ArrayDataSource, + viridis, + DataRange1D, +) from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -58,19 +65,20 @@ def _create_plot_component(): # Create the scatter renderer scatter = ColormappedScatterPlot( - index=index_ds, - value=value_ds, - color_data=color_ds, - color_mapper=viridis(range=DataRange1D(low=0.0, high=1.0)), - fill_alpha=0.4, - index_mapper = imapper, - value_mapper = vmapper, - marker='circle', - marker_size=marker_size) + index=index_ds, + value=value_ds, + color_data=color_ds, + color_mapper=viridis(range=DataRange1D(low=0.0, high=1.0)), + fill_alpha=0.4, + index_mapper=imapper, + value_mapper=vmapper, + marker="circle", + marker_size=marker_size, + ) # Append the renderer to the list of the plot's plots plot.add(scatter) - plot.plots['var_size_scatter'] = [scatter] + plot.plots["var_size_scatter"] = [scatter] # Tweak some of the plot properties plot.title = "Variable Size and Color Scatter Plot" @@ -84,29 +92,35 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (650, 650) title = "Variable size and color scatter plot" -bg_color="lightgray" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/advanced/data_cube.py b/examples/demo/advanced/data_cube.py index 36691494a..eec1ccd28 100644 --- a/examples/demo/advanced/data_cube.py +++ b/examples/demo/advanced/data_cube.py @@ -22,19 +22,30 @@ from numpy import arange, linspace, nanmin, nanmax, newaxis, pi, sin, cos # Enthought library imports -from chaco.api import ArrayPlotData, Plot, GridPlotContainer, \ - BaseTool, DataRange1D +from chaco.api import ArrayPlotData, Plot, GridPlotContainer, BaseTool, DataRange1D from chaco.default_colormaps import * from chaco.tools.api import LineInspector, ZoomTool from enable.example_support import DemoFrame, demo_main from enable.api import Window -from traits.api import Any, Array, Bool, Callable, CFloat, CInt, \ - Event, Float, HasTraits, Int, Trait, observe +from traits.api import ( + Any, + Array, + Bool, + Callable, + CFloat, + CInt, + Event, + Float, + HasTraits, + Int, + Trait, + observe, +) from traits.observation.api import match # Will hold the path that the user chooses to download to. Will be an empty # string if the user decides to download to the current directory. -dl_path = '' +dl_path = "" # Determines if the script should ask the user if they would like to remove the # downloaded data. This defaults to False, because data deletion is @@ -42,15 +53,16 @@ # manually themselves. run_cleanup = False + class Model(HasTraits): npts_x = CInt(256) npts_y = CInt(256) npts_z = CInt(109) - min_x = CFloat(-2*pi) - max_x = CFloat(2*pi) - min_y = CFloat(-2*pi) - max_y = CFloat(2*pi) + min_x = CFloat(-2 * pi) + max_x = CFloat(2 * pi) + min_y = CFloat(-2 * pi) + max_y = CFloat(2 * pi) min_z = CFloat(-pi) max_z = CFloat(pi) @@ -70,15 +82,15 @@ def __init__(self, *args, **kwargs): @observe( match( lambda name, trait: ( - name.startswith("npts_") or - name.startswith("min_") or - name.startswith("max_") - ) + name.startswith("npts_") + or name.startswith("min_") + or name.startswith("max_") ) + ) ) def compute_model(self, event=None): def vfunc(x, y, z): - return sin(x*z) * cos(y)*sin(z) + sin(0.5*z) + return sin(x * z) * cos(y) * sin(z) + sin(0.5 * z) # Create the axes self.xs = linspace(self.min_x, self.max_x, self.npts_x) @@ -86,9 +98,11 @@ def vfunc(x, y, z): self.zs = linspace(self.min_z, self.max_z, self.npts_z) # Generate a cube of values by using newaxis to span new dimensions - self.vals = vfunc(self.xs[:, newaxis, newaxis], - self.ys[newaxis, :, newaxis], - self.zs[newaxis, newaxis, :]) + self.vals = vfunc( + self.xs[:, newaxis, newaxis], + self.ys[newaxis, :, newaxis], + self.zs[newaxis, newaxis, :], + ) self.minval = nanmin(self.vals) self.maxval = nanmax(self.vals) @@ -102,15 +116,15 @@ def __init__(self, *args, **kwargs): def compute_model(self): global dl_path - mrbrain_path = os.path.join(dl_path, 'voldata', 'MRbrain.') + mrbrain_path = os.path.join(dl_path, "voldata", "MRbrain.") nx = 256 ny = 256 nz = 109 - full_arr = zeros((nx, ny, nz), dtype='f') + full_arr = zeros((nx, ny, nz), dtype="f") for i in range(1, 110): - arr = fromfile(mrbrain_path + str(i), dtype='>u2') - arr.shape = (256,256) - full_arr[:,:,i-1] = arr + arr = fromfile(mrbrain_path + str(i), dtype=">u2") + arr.shape = (256, 256) + full_arr[:, :, i - 1] = arr self.vals = full_arr # Create the axes @@ -125,7 +139,7 @@ def compute_model(self): class ImageIndexTool(BaseTool): - """ A tool to set the slice of a cube based on the user's mouse movements + """A tool to set the slice of a cube based on the user's mouse movements or clicks. """ @@ -142,7 +156,7 @@ class ImageIndexTool(BaseTool): # This token can be used by the callback to decide how to process # the event. - token = Any() + token = Any() # Whether or not to update the slice info; we enter select mode when # the left mouse button is pressed and exit it when the mouse button @@ -161,11 +175,10 @@ def normal_mouse_move(self, event): self._update_slices(event) def _update_slices(self, event): - plot = self.component - ndx = plot.map_index((event.x, event.y), - threshold=5.0, index_only=True) - if ndx: - self.callback(self, *ndx) + plot = self.component + ndx = plot.map_index((event.x, event.y), threshold=5.0, index_only=True) + if ndx: + self.callback(self, *ndx) def normal_mouse_wheel(self, event): if self.wheel_cb is not None: @@ -185,9 +198,9 @@ class PlotFrame(DemoFrame): colormap = Any colorcube = Any - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Private Traits - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- _cmap = Trait(viridis, Callable) @@ -211,14 +224,16 @@ def _index_callback(self, tool, x_index, y_index): self.bottom.invalidate_and_redraw() def _wheel_callback(self, tool, wheelamt): - plane_slice_dict = {"xy": ("slice_z", 2), - "yz": ("slice_x", 0), - "xz": ("slice_y", 1)} + plane_slice_dict = { + "xy": ("slice_z", 2), + "yz": ("slice_x", 0), + "xz": ("slice_y", 1), + } attr, shape_ndx = plane_slice_dict[tool.token] val = getattr(self, attr) max = self.model.vals.shape[shape_ndx] if val + wheelamt > max: - setattr(self, attr, max-1) + setattr(self, attr, max - 1) elif val + wheelamt < 0: setattr(self, attr, 0) else: @@ -243,37 +258,48 @@ def _create_component(self): # Center Plot centerplot = Plot(self.plotdata, padding=0) - imgplot = centerplot.img_plot("xy", - xbounds=(model.xs[0], model.xs[-1]), - ybounds=(model.ys[0], model.ys[-1]), - colormap=cmap)[0] + imgplot = centerplot.img_plot( + "xy", + xbounds=(model.xs[0], model.xs[-1]), + ybounds=(model.ys[0], model.ys[-1]), + colormap=cmap, + )[0] self._add_plot_tools(imgplot, "xy") self.center = imgplot # Right Plot rightplot = Plot(self.plotdata, width=150, resizable="v", padding=0) rightplot.value_range = centerplot.value_range - imgplot = rightplot.img_plot("yz", - xbounds=(model.zs[0], model.zs[-1]), - ybounds=(model.ys[0], model.ys[-1]), - colormap=cmap)[0] + imgplot = rightplot.img_plot( + "yz", + xbounds=(model.zs[0], model.zs[-1]), + ybounds=(model.ys[0], model.ys[-1]), + colormap=cmap, + )[0] self._add_plot_tools(imgplot, "yz") self.right = imgplot # Bottom Plot bottomplot = Plot(self.plotdata, height=150, resizable="h", padding=0) bottomplot.index_range = centerplot.index_range - imgplot = bottomplot.img_plot("xz", - xbounds=(model.xs[0], model.xs[-1]), - ybounds=(model.zs[0], model.zs[-1]), - colormap=cmap)[0] + imgplot = bottomplot.img_plot( + "xz", + xbounds=(model.xs[0], model.xs[-1]), + ybounds=(model.zs[0], model.zs[-1]), + colormap=cmap, + )[0] self._add_plot_tools(imgplot, "xz") self.bottom = imgplot # Create Container and add all Plots - container = GridPlotContainer(padding=20, fill_padding=True, - bgcolor="white", use_backbuffer=True, - shape=(2,2), spacing=(12,12)) + container = GridPlotContainer( + padding=20, + fill_padding=True, + bgcolor="white", + use_backbuffer=True, + shape=(2, 2), + spacing=(12, 12), + ) container.add(centerplot) container.add(rightplot) container.add(bottomplot) @@ -284,50 +310,75 @@ def _create_component(self): def _add_plot_tools(self, imgplot, token): """ Add LineInspectors, ImageIndexTool, and ZoomTool to the image plots. """ - imgplot.overlays.append(ZoomTool(component=imgplot, tool_mode="box", - enable_wheel=False, always_on=False)) - imgplot.overlays.append(LineInspector(imgplot, axis="index_y", color="white", - inspect_mode="indexed", write_metadata=True, is_listener=True)) - imgplot.overlays.append(LineInspector(imgplot, axis="index_x", color="white", - inspect_mode="indexed", write_metadata=True, is_listener=True)) - imgplot.tools.append(ImageIndexTool(imgplot, token=token, - callback=self._index_callback, wheel_cb=self._wheel_callback)) + imgplot.overlays.append( + ZoomTool( + component=imgplot, tool_mode="box", enable_wheel=False, always_on=False + ) + ) + imgplot.overlays.append( + LineInspector( + imgplot, + axis="index_y", + color="white", + inspect_mode="indexed", + write_metadata=True, + is_listener=True, + ) + ) + imgplot.overlays.append( + LineInspector( + imgplot, + axis="index_x", + color="white", + inspect_mode="indexed", + write_metadata=True, + is_listener=True, + ) + ) + imgplot.tools.append( + ImageIndexTool( + imgplot, + token=token, + callback=self._index_callback, + wheel_cb=self._wheel_callback, + ) + ) def _update_model(self, cmap): - range = DataRange1D(low=amin(self.model.vals), - high=amax(self.model.vals)) + range = DataRange1D(low=amin(self.model.vals), high=amax(self.model.vals)) self.colormap = cmap(range) self.colorcube = (self.colormap.map_screen(self.model.vals) * 255).astype(uint8) def _update_images(self): - """ Updates the image data in self.plotdata to correspond to the + """Updates the image data in self.plotdata to correspond to the slices given. """ cube = self.colorcube pd = self.plotdata # These are transposed because img_plot() expects its data to be in # row-major order - pd.set_data("xy", transpose(cube[:, :, self.slice_z], (1,0,2))) - pd.set_data("xz", transpose(cube[:, self.slice_y, :], (1,0,2))) + pd.set_data("xy", transpose(cube[:, :, self.slice_z], (1, 0, 2))) + pd.set_data("xz", transpose(cube[:, self.slice_y, :], (1, 0, 2))) pd.set_data("yz", cube[self.slice_x, :, :]) + def download_data(): global dl_path, run_cleanup print('Please enter the location of the "voldata" subdirectory containing') - print('the data files for this demo, or enter a path to download to (7.8MB).') - print('Press to download to the current directory.') - dl_path = input('Path: ').strip().rstrip("/").rstrip("\\") + print("the data files for this demo, or enter a path to download to (7.8MB).") + print("Press to download to the current directory.") + dl_path = input("Path: ").strip().rstrip("/").rstrip("\\") if not dl_path.endswith("voldata"): - voldata_path = os.path.join(dl_path, 'voldata') + voldata_path = os.path.join(dl_path, "voldata") else: voldata_path = dl_path - tar_path = os.path.join(dl_path, 'MRbrain.tar.gz') + tar_path = os.path.join(dl_path, "MRbrain.tar.gz") data_good = True try: - for i in range(1,110): + for i in range(1, 110): if not os.path.isfile(os.path.join(voldata_path, "MRbrain.%d" % i)): data_good = False break @@ -341,29 +392,33 @@ def download_data(): import tarfile if len(dl_path) > 0 and not os.path.exists(dl_path): - print('The given path does not exist.') + print("The given path does not exist.") run_cleanup = False sys.exit() if not os.path.isabs(dl_path): - print('Downloading to: ' + os.path.join(os.getcwd(), dl_path)) + print("Downloading to: " + os.path.join(os.getcwd(), dl_path)) else: - print('Downloading to: ' + dl_path) + print("Downloading to: " + dl_path) try: # download and extract the file print("Downloading data, Please Wait (7.8MB)") - opener = urllib.request.urlopen('http://www-graphics.stanford.edu/data/voldata/MRbrain.tar.gz') + opener = urllib.request.urlopen( + "http://www-graphics.stanford.edu/data/voldata/MRbrain.tar.gz" + ) except: - print('Download error. Opening backup data.') + print("Download error. Opening backup data.") run_cleanup = False raise try: - open(tar_path, 'wb').write(opener.read()) + open(tar_path, "wb").write(opener.read()) except: - print('Cannot write to the destination directory specified. ' - 'Opening backup data.') + print( + "Cannot write to the destination directory specified. " + "Opening backup data." + ) run_cleanup = False raise @@ -376,21 +431,23 @@ def download_data(): tar_file.close() os.unlink(tar_path) else: - print('Previously downloaded data detected.') + print("Previously downloaded data detected.") + def cleanup_data(): global dl_path - answer = input('Remove downloaded files? [Y/N]: ') - if answer.lower() == 'y': + answer = input("Remove downloaded files? [Y/N]: ") + if answer.lower() == "y": try: - shutil.rmtree(os.path.join(dl_path, 'voldata')) + shutil.rmtree(os.path.join(dl_path, "voldata")) except: pass + if __name__ == "__main__": # Save demo so that it doesn't get garbage collected when run within # existing event loop (i.e. from ipython). - demo = demo_main(PlotFrame, size=(800,700), title="Cube analyzer") + demo = demo_main(PlotFrame, size=(800, 700), title="Cube analyzer") if run_cleanup: cleanup_data() diff --git a/examples/demo/advanced/data_stream.py b/examples/demo/advanced/data_stream.py index fb2856b67..6cec0f23c 100644 --- a/examples/demo/advanced/data_stream.py +++ b/examples/demo/advanced/data_stream.py @@ -15,8 +15,7 @@ import numpy as np # Enthought imports -from traits.api import (Array, Callable, Enum, Float, HasTraits, Instance, Int, - Trait) +from traits.api import Array, Callable, Enum, Float, HasTraits, Instance, Int, Trait from traitsui.api import Group, HGroup, Item, View, spring, Handler from pyface.timer.api import Timer @@ -25,34 +24,41 @@ class Viewer(HasTraits): - """ This class just contains the two data arrays that will be updated + """This class just contains the two data arrays that will be updated by the Controller. The visualization/editor for this class is a Chaco plot. """ + index = Array data = Array plot_type = Enum("line", "scatter") - view = View(ChacoPlotItem("index", "data", - type_trait="plot_type", - resizable=True, - x_label="Time", - y_label="Signal", - color="blue", - bgcolor="white", - border_visible=True, - border_width=1, - padding_bg_color="lightgray", - width=800, - height=380, - marker_size=2, - show_label=False), - HGroup(spring, Item("plot_type", style='custom'), spring), - resizable = True, - buttons = ["OK"], - width=800, height=500) + view = View( + ChacoPlotItem( + "index", + "data", + type_trait="plot_type", + resizable=True, + x_label="Time", + y_label="Signal", + color="blue", + bgcolor="white", + border_visible=True, + border_width=1, + padding_bg_color="lightgray", + width=800, + height=380, + marker_size=2, + show_label=False, + ), + HGroup(spring, Item("plot_type", style="custom"), spring), + resizable=True, + buttons=["OK"], + width=800, + height=500, + ) class Controller(HasTraits): @@ -78,12 +84,16 @@ class Controller(HasTraits): # it can be set to any callable object. _generator = Trait(np.random.normal, Callable) - view = View(Group('distribution_type', - 'mean', - 'stddev', - 'max_num_points', - orientation="vertical"), - buttons=["OK", "Cancel"]) + view = View( + Group( + "distribution_type", + "mean", + "stddev", + "max_num_points", + orientation="vertical", + ), + buttons=["OK", "Cancel"], + ) def timer_tick(self, *args): """ @@ -98,9 +108,8 @@ def timer_tick(self, *args): # grab the existing data, truncate it, and append the new point. # This isn't the most efficient thing in the world but it works. cur_data = self.viewer.data - new_data = np.hstack((cur_data[-self.max_num_points+1:], [new_val])) - new_index = np.arange(self.num_ticks - len(new_data) + 1, - self.num_ticks + 0.01) + new_data = np.hstack((cur_data[-self.max_num_points + 1 :], [new_val])) + new_index = np.arange(self.num_ticks - len(new_data) + 1, self.num_ticks + 0.01) self.viewer.index = new_index self.viewer.data = new_data @@ -114,9 +123,8 @@ def _distribution_type_changed(self): class DemoHandler(Handler): - def closed(self, info, is_ok): - """ Handles a dialog-based user interface being closed by the user. + """Handles a dialog-based user interface being closed by the user. Overridden here to stop the timer once the window is destroyed. """ @@ -127,21 +135,23 @@ class Demo(HasTraits): controller = Instance(Controller) viewer = Instance(Viewer, ()) timer = Instance(Timer) - view = View(Item('controller', style='custom', show_label=False), - Item('viewer', style='custom', show_label=False), - handler=DemoHandler, - resizable=True) + view = View( + Item("controller", style="custom", show_label=False), + Item("viewer", style="custom", show_label=False), + handler=DemoHandler, + resizable=True, + ) def edit_traits(self, *args, **kws): # Start up the timer! We should do this only when the demo actually # starts and not when the demo object is created. - self.timer=Timer(100, self.controller.timer_tick) + self.timer = Timer(100, self.controller.timer_tick) return super(Demo, self).edit_traits(*args, **kws) def configure_traits(self, *args, **kws): # Start up the timer! We should do this only when the demo actually # starts and not when the demo object is created. - self.timer=Timer(100, self.controller.timer_tick) + self.timer = Timer(100, self.controller.timer_tick) return super(Demo, self).configure_traits(*args, **kws) def _controller_default(self): @@ -150,7 +160,7 @@ def _controller_default(self): # NOTE: examples/demo/demo.py looks for a 'demo' or 'popup' or 'modal popup' # keyword when it executes this file, and displays a view for it. -popup=Demo() +popup = Demo() if __name__ == "__main__": diff --git a/examples/demo/advanced/javascript_hover_tools.py b/examples/demo/advanced/javascript_hover_tools.py index ca5f6b97c..dc1b20004 100644 --- a/examples/demo/advanced/javascript_hover_tools.py +++ b/examples/demo/advanced/javascript_hover_tools.py @@ -34,27 +34,28 @@ from scipy.special import jn # Chaco imports -from chaco.api \ - import ArrayPlotData, Plot, PlotGraphicsContext, LinePlot +from chaco.api import ArrayPlotData, Plot, PlotGraphicsContext, LinePlot from chaco.example_support import COLOR_PALETTE -#-- Constants ----------------------------------------------------------------- +# -- Constants ----------------------------------------------------------------- DPI = 72.0 -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # File templates: # In a real application, these templates should be their own files, # and a real templating engine (ex. Mako) would make things more flexible. -#------------------------------------------------------------------------------ -html_template_keys = {'filename1' : 'plot_hover_coords.png', - 'filename2' : 'plot_hover2_coords.png', - 'file1_src' : 'plot_hover_coords.png', - 'file2_src' : 'plot_hover2_coords.png', - 'hover_coords' :'src="hover_coords.js">', - 'data1' :'src="plot_hover_coords_png_hover_data.js">', - 'data2' :'src="plot_hover2_coords_png_hover_data.js">' } +# ------------------------------------------------------------------------------ +html_template_keys = { + "filename1": "plot_hover_coords.png", + "filename2": "plot_hover2_coords.png", + "file1_src": "plot_hover_coords.png", + "file2_src": "plot_hover2_coords.png", + "hover_coords": 'src="hover_coords.js">', + "data1": 'src="plot_hover_coords_png_hover_data.js">', + "data2": 'src="plot_hover2_coords_png_hover_data.js">', +} # Turns into index.html. @@ -357,9 +358,10 @@ """ -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Data generation functions for *_hover_data.js files. -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ + def get_pixel_data(segment, renderer, screen_width): """ @@ -375,13 +377,13 @@ def get_pixel_data(segment, renderer, screen_width): if len(screen_points) == 0: return array([]) - s_index = screen_points[:,0].astype(int) - d_value = segment[:,1] + s_index = screen_points[:, 0].astype(int) + d_value = segment[:, 1] if len(s_index) != len(d_value): - raise ValueError('Data-to-screen mapping not 1-to-1.') + raise ValueError("Data-to-screen mapping not 1-to-1.") indices = searchsorted(s_index, arange(0, screen_width)) indices[where(indices == 0)] = 1 - return d_value[indices-1] + return d_value[indices - 1] def write_hover_coords(container, array_id, script_filename=None): @@ -443,40 +445,42 @@ def write_hover_coords(container, array_id, script_filename=None): else: alpha = 1 r, g, b = [int(component * alpha * 255) for component in color[:3]] - colstrings.append('"#%02x%02x%02x"' % (r,g,b)) - colors = ",".join(colstrings); + colstrings.append('"#%02x%02x%02x"' % (r, g, b)) + colors = ",".join(colstrings) line_template = ",".join(['"%1.2f"'] * pixel_data.shape[1]) - data_s = '' + data_s = "" for row in pixel_data[:-1]: - data_s += '[' + line_template % tuple(row) + '],' + data_s += "[" + line_template % tuple(row) + "]," if len(pixel_data) > 0: - data_s += '[' + line_template % tuple(row) + ']' - - template_keys = dict(height = container.height, - padding_top = container.padding_top, - padding_left = container.padding_left, - padding_bottom = container.padding_bottom, - border_width = container.border_width, - array_id = array_id, - pixel_data = pixel_data, - colors = colors, - data_s = data_s) + data_s += "[" + line_template % tuple(row) + "]" + + template_keys = dict( + height=container.height, + padding_top=container.padding_top, + padding_left=container.padding_left, + padding_bottom=container.padding_bottom, + border_width=container.border_width, + array_id=array_id, + pixel_data=pixel_data, + colors=colors, + data_s=data_s, + ) # Write out and return the result. output = javascript_data_template % template_keys if script_filename: - f = open(script_filename, 'wt') + f = open(script_filename, "wt") f.write(output) f.close() return output -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Plot and renderer generation functions. -#------------------------------------------------------------------------------ -def create_plot(num_plots=8, type='line'): +# ------------------------------------------------------------------------------ +def create_plot(num_plots=8, type="line"): """ Create a single plot object, with multiple renderers. """ # This is a bit of a hack to work around that line widths don't scale # with the GraphicsContext's CTM. @@ -487,10 +491,14 @@ def create_plot(num_plots=8, type='line'): x = linspace(low, high, numpoints) pd = ArrayPlotData(index=x) p = Plot(pd, bgcolor="white", padding=50, border_visible=True) - for i in range(1,num_plots+2): - pd.set_data("y" + str(i), jn(i,x)) - p.plot(("index", "y" + str(i)), color=tuple(COLOR_PALETTE[i]), - width = 2.0 * dpi_scale, type=type) + for i in range(1, num_plots + 2): + pd.set_data("y" + str(i), jn(i, x)) + p.plot( + ("index", "y" + str(i)), + color=tuple(COLOR_PALETTE[i]), + width=2.0 * dpi_scale, + type=type, + ) p.x_grid.visible = True p.x_grid.line_width *= dpi_scale p.y_grid.visible = True @@ -499,7 +507,7 @@ def create_plot(num_plots=8, type='line'): return p -def draw_plot(filename, size=(800,600), num_plots=8, type='line', key=''): +def draw_plot(filename, size=(800, 600), num_plots=8, type="line", key=""): """ Save the plot, and generate the hover_data file. """ container = create_plot(num_plots, type) container.outer_bounds = list(size) @@ -521,58 +529,61 @@ def make_palettized_png_str(gc): format = gc.format()[:-2].upper() if format != "RGBA": gc = gc.convert_pixel_format("rgba32") - img = Image.fromstring("RGBA", - (gc.width(), gc.height()), gc.bmp_array.tostring()) + img = Image.fromstring("RGBA", (gc.width(), gc.height()), gc.bmp_array.tostring()) img2 = img.convert("P") output_buf = io.StringIO() - img2.save(output_buf, 'png') + img2.save(output_buf, "png") output = encodestring(output_buf.getvalue()) output_buf.close() return output -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ # Main -#------------------------------------------------------------------------------ +# ------------------------------------------------------------------------------ def main(embedded=False): """ Create the files and load the output in a webbrowser. """ # 1. Create the JavaScript hover tool file. # Only doing this to keep the demo file self-contained. - target_path = os.path.join(os.getcwd(), 'hover_coords.js') + target_path = os.path.join(os.getcwd(), "hover_coords.js") if embedded: - html_template_keys['hover_coords'] = '>\n%s\n' % hover_coords_js_file + html_template_keys["hover_coords"] = ">\n%s\n" % hover_coords_js_file else: - f = open(target_path, 'wt') + f = open(target_path, "wt") f.write(hover_coords_js_file) f.close() # 2. Create the dynamically generated JavaScript data files. if embedded: - html_template_keys['file1_src'] = None - html_template_keys['file2_src'] = None - file1_strs = draw_plot(html_template_keys['file1_src'], - size=(800, 600), - key=html_template_keys['filename1']) - file2_strs = draw_plot(html_template_keys['file2_src'], - size=(600, 400), - num_plots = 4, - type='scatter', - key=html_template_keys['filename2']) + html_template_keys["file1_src"] = None + html_template_keys["file2_src"] = None + file1_strs = draw_plot( + html_template_keys["file1_src"], + size=(800, 600), + key=html_template_keys["filename1"], + ) + file2_strs = draw_plot( + html_template_keys["file2_src"], + size=(600, 400), + num_plots=4, + type="scatter", + key=html_template_keys["filename2"], + ) # 3. Choose the correct src type for the HTML file if embedded. if embedded: - src1 = 'data:image/png;base64,' + file1_strs[0] - html_template_keys['file1_src'] = src1 - src2 = 'data:image/png;base64,' + file2_strs[0] - html_template_keys['file2_src'] = src2 - html_template_keys['data1'] = '>\n%s\n' % file1_strs[1] - html_template_keys['data2'] = '>\n%s\n' % file2_strs[1] + src1 = "data:image/png;base64," + file1_strs[0] + html_template_keys["file1_src"] = src1 + src2 = "data:image/png;base64," + file2_strs[0] + html_template_keys["file2_src"] = src2 + html_template_keys["data1"] = ">\n%s\n" % file1_strs[1] + html_template_keys["data2"] = ">\n%s\n" % file2_strs[1] # 4. Create the HTML file. - out_html = os.path.join(os.getcwd(), 'plot_hover_coords.html') - f = open(out_html, 'wt') + out_html = os.path.join(os.getcwd(), "plot_hover_coords.html") + f = open(out_html, "wt") f.write(html_template % html_template_keys) f.close() @@ -580,14 +591,16 @@ def main(embedded=False): try: webbrowser.open(out_html) except Exception as e: - print('Browser did not open properly. Exception %s. The results' \ - 'can be viewed with the file plot_hover_coords.html.' % str(e)) + print( + "Browser did not open properly. Exception %s. The results" + "can be viewed with the file plot_hover_coords.html." % str(e) + ) raise -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== # NOTE: The Demo class is being created for the purpose of running this # example using a TraitsDemo-like app (see examples/demo/demo.py in Traits3). # The demo.py file looks for a 'demo' or 'popup' or 'modal popup' keyword @@ -600,8 +613,8 @@ def main(embedded=False): from traits.api import HasTraits from traitsui.api import UI, Handler -class Demo(HasTraits): +class Demo(HasTraits): def configure_traits(self, *args, **kws): main(embedded=True) return True @@ -610,10 +623,11 @@ def edit_traits(self, *args, **kws): main(embedded=True) return UI(handler=Handler()) + popup = Demo() if __name__ == "__main__": - if '-e' in sys.argv or '--embedded' in sys.argv: + if "-e" in sys.argv or "--embedded" in sys.argv: main(embedded=True) else: main(embedded=False) diff --git a/examples/demo/advanced/scalar_image_function_inspector.py b/examples/demo/advanced/scalar_image_function_inspector.py index adeb05044..c7de5dba0 100644 --- a/examples/demo/advanced/scalar_image_function_inspector.py +++ b/examples/demo/advanced/scalar_image_function_inspector.py @@ -11,58 +11,92 @@ """ - # Standard library imports from optparse import OptionParser import sys import random # Major library imports -from numpy import array, linspace, meshgrid, nanmin, nanmax, pi, errstate +from numpy import array, linspace, meshgrid, nanmin, nanmax, pi, errstate # Enthought library imports -from chaco.api import ArrayPlotData, ColorBar, ContourLinePlot, \ - ContourPolyPlot, DataRange1D, VPlotContainer, \ - DataRange2D, GridMapper, GridDataSource, \ - HPlotContainer, ImageData, LinearMapper, \ - OverlayPlotContainer, Plot, PlotAxis +from chaco.api import ( + ArrayPlotData, + ColorBar, + ContourLinePlot, + ContourPolyPlot, + DataRange1D, + VPlotContainer, + DataRange2D, + GridMapper, + GridDataSource, + HPlotContainer, + ImageData, + LinearMapper, + OverlayPlotContainer, + Plot, + PlotAxis, +) from chaco import default_colormaps from enable.component_editor import ComponentEditor from chaco.tools.api import LineInspector, PanTool, ZoomTool -from traits.api import Array, Callable, CFloat, CInt, Enum, Event, Float, \ - HasTraits, Int, Instance, Str, Trait, observe, Button, Bool, \ - DelegatesTo +from traits.api import ( + Array, + Callable, + CFloat, + CInt, + Enum, + Event, + Float, + HasTraits, + Int, + Instance, + Str, + Trait, + observe, + Button, + Bool, + DelegatesTo, +) from traitsui.api import Group, HGroup, Item, View, UItem, spring from pyface.timer.api import Timer # Remove the most boring colormaps from consideration: colormaps = list(default_colormaps.color_map_name_dict.keys()) -for boring in 'bone gray yarg gist_gray gist_yarg Greys'.split(): +for boring in "bone gray yarg gist_gray gist_yarg Greys".split(): colormaps.remove(boring) + class Model(HasTraits): - #Traits view definitions: + # Traits view definitions: traits_view = View( - Group(Item('function'), - HGroup(Item('npts_x', label="Number X Points"), - Item('npts_y', label="Number Y Points")), - HGroup(Item('min_x', label="Min X value"), - Item('max_x', label="Max X value")), - HGroup(Item('min_y', label="Min Y value"), - Item('max_y', label="Max Y value"))), - buttons=["OK", "Cancel"]) + Group( + Item("function"), + HGroup( + Item("npts_x", label="Number X Points"), + Item("npts_y", label="Number Y Points"), + ), + HGroup( + Item("min_x", label="Min X value"), Item("max_x", label="Max X value") + ), + HGroup( + Item("min_y", label="Min Y value"), Item("max_y", label="Max Y value") + ), + ), + buttons=["OK", "Cancel"], + ) function = Str("tanh(x**2+y)*cos(y)*jn(0,x+y*2)") npts_x = CInt(400) npts_y = CInt(200) - min_x = CFloat(-2*pi) - max_x = CFloat(2*pi) - min_y = CFloat(-1.5*pi) - max_y = CFloat(1.5*pi) + min_x = CFloat(-2 * pi) + max_x = CFloat(2 * pi) + min_y = CFloat(-1.5 * pi) + max_y = CFloat(1.5 * pi) xs = Array ys = Array @@ -80,16 +114,20 @@ def __init__(self, *args, **kwargs): def compute_model(self): # The xs and ys used for the image plot range need to be the # edges of the cells. - self.xs = linspace(self.min_x, self.max_x, self.npts_x+1) - self.ys = linspace(self.min_y, self.max_y, self.npts_y+1) + self.xs = linspace(self.min_x, self.max_x, self.npts_x + 1) + self.ys = linspace(self.min_y, self.max_y, self.npts_y + 1) # The grid of points at which we will evaluate the 2D function # is located at cell centers, so use halfsteps from the # min/max values (which are edges) xstep = (self.max_x - self.min_x) / self.npts_x ystep = (self.max_y - self.min_y) / self.npts_y - gridx = linspace(self.min_x+xstep/2, self.max_x-xstep/2, self.npts_x+1) - gridy = linspace(self.min_y+ystep/2, self.max_y-ystep/2, self.npts_y+1) + gridx = linspace( + self.min_x + xstep / 2, self.max_x - xstep / 2, self.npts_x + 1 + ) + gridy = linspace( + self.min_y + ystep / 2, self.max_y - ystep / 2, self.npts_y + 1 + ) x, y = meshgrid(gridx, gridy) d = dict(x=x, y=y) @@ -115,160 +153,171 @@ def compute_model(self): self._function = self.function def _anytrait_changed(self, name, value): - if name in ['function', 'npts_x', 'npts_y', - 'min_x', 'max_x', 'min_y', 'max_y']: + if name in ["function", "npts_x", "npts_y", "min_x", "max_x", "min_y", "max_y"]: self.compute_model() class PlotUI(HasTraits): - + # container for all plots container = Instance(HPlotContainer) - + # Plot components within this container: polyplot = Instance(ContourPolyPlot) lineplot = Instance(ContourLinePlot) cross_plot = Instance(Plot) cross_plot2 = Instance(Plot) colorbar = Instance(ColorBar) - + # plot data pd = Instance(ArrayPlotData) # view options num_levels = Int(15) colormap = Enum(colormaps) - - #Traits view definitions: + + # Traits view definitions: traits_view = View( - Group(UItem('container', editor=ComponentEditor(size=(800,600)))), - resizable=True) + Group(UItem("container", editor=ComponentEditor(size=(800, 600)))), + resizable=True, + ) plot_edit_view = View( - Group(Item('num_levels'), - Item('colormap')), - buttons=["OK","Cancel"]) + Group(Item("num_levels"), Item("colormap")), buttons=["OK", "Cancel"] + ) - - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Private Traits - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- _image_index = Instance(GridDataSource) _image_value = Instance(ImageData) _cmap = Trait(default_colormaps.viridis, Callable) - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Public View interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def __init__(self, *args, **kwargs): super(PlotUI, self).__init__(*args, **kwargs) - # FIXME: 'with' wrapping is temporary fix for infinite range in initial + # FIXME: 'with' wrapping is temporary fix for infinite range in initial # color map, which can cause a distracting warning print. This 'with' # wrapping should be unnecessary after fix in color_mapper.py. - with errstate(invalid='ignore'): + with errstate(invalid="ignore"): self.create_plot() def create_plot(self): # Create the mapper, etc - self._image_index = GridDataSource(array([]), - array([]), - sort_order=("ascending","ascending")) + self._image_index = GridDataSource( + array([]), array([]), sort_order=("ascending", "ascending") + ) image_index_range = DataRange2D(self._image_index) self._image_index.observe(self._metadata_changed, "metadata_changed") self._image_value = ImageData(data=array([]), value_depth=1) image_value_range = DataRange1D(self._image_value) - - # Create the contour plots - self.polyplot = ContourPolyPlot(index=self._image_index, - value=self._image_value, - index_mapper=GridMapper(range= - image_index_range), - color_mapper=\ - self._cmap(image_value_range), - levels=self.num_levels) - - self.lineplot = ContourLinePlot(index=self._image_index, - value=self._image_value, - index_mapper=GridMapper(range= - self.polyplot.index_mapper.range), - levels=self.num_levels) - + self.polyplot = ContourPolyPlot( + index=self._image_index, + value=self._image_value, + index_mapper=GridMapper(range=image_index_range), + color_mapper=self._cmap(image_value_range), + levels=self.num_levels, + ) + + self.lineplot = ContourLinePlot( + index=self._image_index, + value=self._image_value, + index_mapper=GridMapper(range=self.polyplot.index_mapper.range), + levels=self.num_levels, + ) # Add a left axis to the plot - left = PlotAxis(orientation='left', - title= "y", - mapper=self.polyplot.index_mapper._ymapper, - component=self.polyplot) + left = PlotAxis( + orientation="left", + title="y", + mapper=self.polyplot.index_mapper._ymapper, + component=self.polyplot, + ) self.polyplot.overlays.append(left) # Add a bottom axis to the plot - bottom = PlotAxis(orientation='bottom', - title= "x", - mapper=self.polyplot.index_mapper._xmapper, - component=self.polyplot) + bottom = PlotAxis( + orientation="bottom", + title="x", + mapper=self.polyplot.index_mapper._xmapper, + component=self.polyplot, + ) self.polyplot.overlays.append(bottom) - # Add some tools to the plot - self.polyplot.tools.append(PanTool(self.polyplot, - constrain_key="shift")) - self.polyplot.overlays.append(ZoomTool(component=self.polyplot, - tool_mode="box", always_on=False)) - self.polyplot.overlays.append(LineInspector(component=self.polyplot, - axis='index_x', - inspect_mode="indexed", - write_metadata=True, - is_listener=True, - color="white")) - self.polyplot.overlays.append(LineInspector(component=self.polyplot, - axis='index_y', - inspect_mode="indexed", - write_metadata=True, - color="white", - is_listener=True)) + self.polyplot.tools.append(PanTool(self.polyplot, constrain_key="shift")) + self.polyplot.overlays.append( + ZoomTool(component=self.polyplot, tool_mode="box", always_on=False) + ) + self.polyplot.overlays.append( + LineInspector( + component=self.polyplot, + axis="index_x", + inspect_mode="indexed", + write_metadata=True, + is_listener=True, + color="white", + ) + ) + self.polyplot.overlays.append( + LineInspector( + component=self.polyplot, + axis="index_y", + inspect_mode="indexed", + write_metadata=True, + color="white", + is_listener=True, + ) + ) # Add these two plots to one container - contour_container = OverlayPlotContainer(padding=20, - use_backbuffer=True, - unified_draw=True) + contour_container = OverlayPlotContainer( + padding=20, use_backbuffer=True, unified_draw=True + ) contour_container.add(self.polyplot) contour_container.add(self.lineplot) - # Create a colorbar cbar_index_mapper = LinearMapper(range=image_value_range) - self.colorbar = ColorBar(index_mapper=cbar_index_mapper, - plot=self.polyplot, - padding_top=self.polyplot.padding_top, - padding_bottom=self.polyplot.padding_bottom, - padding_right=40, - resizable='v', - width=30) - - self.pd = ArrayPlotData(line_index = array([]), - line_value = array([]), - scatter_index = array([]), - scatter_value = array([]), - scatter_color = array([])) + self.colorbar = ColorBar( + index_mapper=cbar_index_mapper, + plot=self.polyplot, + padding_top=self.polyplot.padding_top, + padding_bottom=self.polyplot.padding_bottom, + padding_right=40, + resizable="v", + width=30, + ) + + self.pd = ArrayPlotData( + line_index=array([]), + line_value=array([]), + scatter_index=array([]), + scatter_value=array([]), + scatter_color=array([]), + ) self.cross_plot = Plot(self.pd, resizable="h") self.cross_plot.height = 100 self.cross_plot.padding = 20 - self.cross_plot.plot(("line_index", "line_value"), - line_style="dot") - self.cross_plot.plot(("scatter_index","scatter_value","scatter_color"), - type="cmap_scatter", - name="dot", - color_mapper=self._cmap(image_value_range), - marker="circle", - marker_size=8) + self.cross_plot.plot(("line_index", "line_value"), line_style="dot") + self.cross_plot.plot( + ("scatter_index", "scatter_value", "scatter_color"), + type="cmap_scatter", + name="dot", + color_mapper=self._cmap(image_value_range), + marker="circle", + marker_size=8, + ) self.cross_plot.index_range = self.polyplot.index_range.x_range @@ -278,26 +327,30 @@ def create_plot(self): self.pd.set_data("scatter_value2", array([])) self.pd.set_data("scatter_color2", array([])) - self.cross_plot2 = Plot(self.pd, width = 140, orientation="v", - resizable="v", padding=20, padding_bottom=160) - self.cross_plot2.plot(("line_index2", "line_value2"), - line_style="dot") - self.cross_plot2.plot(("scatter_index2", - "scatter_value2", - "scatter_color2"), - type="cmap_scatter", - name="dot", - color_mapper=self._cmap(image_value_range), - marker="circle", - marker_size=8) + self.cross_plot2 = Plot( + self.pd, + width=140, + orientation="v", + resizable="v", + padding=20, + padding_bottom=160, + ) + self.cross_plot2.plot(("line_index2", "line_value2"), line_style="dot") + self.cross_plot2.plot( + ("scatter_index2", "scatter_value2", "scatter_color2"), + type="cmap_scatter", + name="dot", + color_mapper=self._cmap(image_value_range), + marker="circle", + marker_size=8, + ) self.cross_plot2.index_range = self.polyplot.index_range.y_range - - # Create a container and add components - self.container = HPlotContainer(padding=40, fill_padding=True, - bgcolor = "white", use_backbuffer=False) + self.container = HPlotContainer( + padding=40, fill_padding=True, bgcolor="white", use_backbuffer=False + ) inner_cont = VPlotContainer(padding=0, use_backbuffer=True) inner_cont.add(self.cross_plot) inner_cont.add(contour_container) @@ -305,7 +358,6 @@ def create_plot(self): self.container.add(inner_cont) self.container.add(self.cross_plot2) - def update(self, model): self.minz = model.minz self.maxz = model.maxz @@ -317,10 +369,9 @@ def update(self, model): self.container.invalidate_draw() self.container.request_redraw() - - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Event handlers - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def _metadata_changed(self, event): old, new = event.old, event.new @@ -338,19 +389,24 @@ def _metadata_changed(self, event): xdata, ydata = self._image_index.get_data() xdata, ydata = xdata.get_data(), ydata.get_data() self.pd.update_data( - line_value=self._image_value.data[y_ndx,:], - line_value2=self._image_value.data[:,x_ndx], + line_value=self._image_value.data[y_ndx, :], + line_value2=self._image_value.data[:, x_ndx], scatter_index=array([xdata[x_ndx]]), scatter_index2=array([ydata[y_ndx]]), scatter_value=array([self._image_value.data[y_ndx, x_ndx]]), scatter_value2=array([self._image_value.data[y_ndx, x_ndx]]), scatter_color=array([self._image_value.data[y_ndx, x_ndx]]), - scatter_color2=array([self._image_value.data[y_ndx, x_ndx]]) + scatter_color2=array([self._image_value.data[y_ndx, x_ndx]]), ) else: - self.pd.update_data({"scatter_value": array([]), - "scatter_value2": array([]), "line_value": array([]), - "line_value2": array([])}) + self.pd.update_data( + { + "scatter_value": array([]), + "scatter_value2": array([]), + "line_value": array([]), + "line_value2": array([]), + } + ) def _colormap_changed(self): self._cmap = default_colormaps.color_map_name_dict[self.colormap] @@ -361,10 +417,8 @@ def _colormap_changed(self): self.cross_plot.color_mapper = self._cmap(value_range) # FIXME: change when we decide how best to update plots using # the shared colormap in plot object - self.cross_plot.plots["dot" - ][0].color_mapper = self._cmap(value_range) - self.cross_plot2.plots["dot" - ][0].color_mapper = self._cmap(value_range) + self.cross_plot.plots["dot"][0].color_mapper = self._cmap(value_range) + self.cross_plot2.plots["dot"][0].color_mapper = self._cmap(value_range) self.container.request_redraw() def _num_levels_changed(self): @@ -373,41 +427,52 @@ def _num_levels_changed(self): self.lineplot.levels = self.num_levels - - # HasTraits class that supplies the callable for the timer event. class TimerController(HasTraits): # The plot view which will be affected by timed animation view = Instance(PlotUI) - + # The ModelView instance that contains the animation options: - model_view = Instance('ModelView') - + model_view = Instance("ModelView") + # Whether the view is animated: - animated = DelegatesTo('model_view') - + animated = DelegatesTo("model_view") + # whether color change is animated on each boundary: - animate_left = DelegatesTo('model_view') - animate_right = DelegatesTo('model_view') - animate_top = DelegatesTo('model_view') - animate_bottom = DelegatesTo('model_view') - + animate_left = DelegatesTo("model_view") + animate_right = DelegatesTo("model_view") + animate_top = DelegatesTo("model_view") + animate_bottom = DelegatesTo("model_view") + # current increments of selected point, for animation x_delta = Int y_delta = Int - + # Possible directions for 2D animated motion. # One tuple will be selected randomly from these on each bounce. # In each tuple, the first integer is the absolute value of # the new delta of the component that reached a boundary. # The second integer is the new delta of the other component. - motions = ((1,1), (1,2), (1,3), (2,1), (3,1), (3,2), (2,3), - (1,-1),(1,-2),(1,-3),(2,-1),(3,-1),(3,-2),(2,-2) - ) + motions = ( + (1, 1), + (1, 2), + (1, 3), + (2, 1), + (3, 1), + (3, 2), + (2, 3), + (1, -1), + (1, -2), + (1, -3), + (2, -1), + (3, -1), + (3, -2), + (2, -2), + ) def onTimer(self, *args): - """ + """ Callback function which responds to each timer tick and animates the moving selection point and colors. """ @@ -416,23 +481,22 @@ def randomize(new_direction=1, color_change=False): """ Randomize 2D motion, and colors if desired. Parameters: - + * new_direction is the sign of the new motion delta for - the component that reached the boundary (the primary bounce + the component that reached the boundary (the primary bounce direction.) - + * color_change is whether to change the colormap if allowed. - + Returns a pair of integers, which are the new motion deltas, respectively, for primary bounce direction and the other. - + """ if color_change: self.view.colormap = random.choice(colormaps) result0, result1 = random.choice(self.motions) return result0 * new_direction, result1 - - + if self.animated: metadata = self.view._image_index.metadata indices = metadata.get("selections", ()) @@ -443,29 +507,25 @@ def randomize(new_direction=1, color_change=False): y += self.y_delta if y < 0: y = 0 - self.y_delta, self.x_delta = randomize(1, - self.animate_bottom) + self.y_delta, self.x_delta = randomize(1, self.animate_bottom) elif y >= ylim: - y = ylim-1 - self.y_delta, self.x_delta = randomize(-1, - self.animate_top) + y = ylim - 1 + self.y_delta, self.x_delta = randomize(-1, self.animate_top) else: x += self.x_delta if x < 0: x = 0 - self.x_delta, self.y_delta = randomize(1, - self.animate_left) + self.x_delta, self.y_delta = randomize(1, self.animate_left) elif x >= xlim: - x = xlim-1 - self.x_delta, self.y_delta = randomize(-1, - self.animate_right) - + x = xlim - 1 + self.x_delta, self.y_delta = randomize(-1, self.animate_right) + else: - x,y = 0,0 + x, y = 0, 0 self.x_delta, self.y_delta = random.choice(self.motions) self.y_delta = 1 - metadata['selections'] = x,y - + metadata["selections"] = x, y + class ModelView(HasTraits): @@ -473,44 +533,46 @@ class ModelView(HasTraits): view = Instance(PlotUI) timer = Instance(Timer) timer_controller = Instance(TimerController, ()) - + edit_model = Button edit_view = Button animated = Bool(False) - + # Whether to animate colors on a bounce of each side: animate_left = Bool(False) animate_right = Bool(False) animate_top = Bool(False) animate_bottom = Bool(False) - - traits_view = View(UItem('@view'), - HGroup(UItem('edit_model', enabled_when='not animated'), - UItem('edit_view'), - Item('animated'), - Item('animate_left', enabled_when='animated', - label='Change colors at: Left'), - Item('animate_right', enabled_when='animated', - label='Right'), - Item('animate_top', enabled_when='animated', - label='Top'), - Item('animate_bottom', enabled_when='animated', - label='Bottom'), - spring), - title = "Function Inspector", - resizable=True) - - @observe('model, model.model_changed, view') + + traits_view = View( + UItem("@view"), + HGroup( + UItem("edit_model", enabled_when="not animated"), + UItem("edit_view"), + Item("animated"), + Item( + "animate_left", enabled_when="animated", label="Change colors at: Left" + ), + Item("animate_right", enabled_when="animated", label="Right"), + Item("animate_top", enabled_when="animated", label="Top"), + Item("animate_bottom", enabled_when="animated", label="Bottom"), + spring, + ), + title="Function Inspector", + resizable=True, + ) + + @observe("model, model.model_changed, view") def update_view(self, event): if self.model is not None and self.view is not None: self.view.update(self.model) - + def _edit_model_fired(self): self.model.configure_traits() - + def _edit_view_fired(self): self.view.configure_traits(view="plot_edit_view") - + def _start_timer(self): # Start up the timer! We should do this only when the demo actually # starts and not when the demo object is created. @@ -518,7 +580,7 @@ def _start_timer(self): self.timer_controller.view = self.view self.timer_controller.model_view = self self.timer = Timer(40, self.timer_controller.onTimer) - + def edit_traits(self, *args, **kws): self._start_timer() return super(ModelView, self).edit_traits(*args, **kws) @@ -526,13 +588,15 @@ def edit_traits(self, *args, **kws): def configure_traits(self, *args, **kws): self._start_timer() return super(ModelView, self).configure_traits(*args, **kws) - + + def show_plot(**kwargs): model = Model(**kwargs) view = PlotUI(**kwargs) - modelview=ModelView(model=model, view=view) + modelview = ModelView(model=model, view=view) modelview.configure_traits() + def main(argv=None): if argv is None: @@ -541,26 +605,46 @@ def main(argv=None): usage = "usage: %prog [options]" parser = OptionParser(usage=usage, version="%prog 1.0") - parser.add_option("-c", "--colormap", - action="store", type="string", dest="colormap", default="viridis", - metavar="CMAP", help="choose a default colormapper") - - parser.add_option("-n", "--nlevels", - action="store", type="int", dest="num_levels", default=15, - help="number countour levels to plot [default: %default]") - - parser.add_option("-f", "--function", - action="store", type="string", dest="function", - default="tanh(x**2+y)*cos(y)*jn(0,x+y*2)", - help="function of x and y [default: %default]") + parser.add_option( + "-c", + "--colormap", + action="store", + type="string", + dest="colormap", + default="viridis", + metavar="CMAP", + help="choose a default colormapper", + ) + + parser.add_option( + "-n", + "--nlevels", + action="store", + type="int", + dest="num_levels", + default=15, + help="number countour levels to plot [default: %default]", + ) + + parser.add_option( + "-f", + "--function", + action="store", + type="string", + dest="function", + default="tanh(x**2+y)*cos(y)*jn(0,x+y*2)", + help="function of x and y [default: %default]", + ) opts, args = parser.parse_args(argv[1:]) if len(args) > 0: parser.error("Incorrect number of arguments") - show_plot(colormap=opts.colormap, num_levels=opts.num_levels, - function=opts.function) + show_plot( + colormap=opts.colormap, num_levels=opts.num_levels, function=opts.function + ) + if __name__ == "__main__": sys.exit(main()) diff --git a/examples/demo/advanced/scalar_image_function_inspector_old.py b/examples/demo/advanced/scalar_image_function_inspector_old.py index 6f19ecc67..9def269b8 100644 --- a/examples/demo/advanced/scalar_image_function_inspector_old.py +++ b/examples/demo/advanced/scalar_image_function_inspector_old.py @@ -8,49 +8,89 @@ import sys # Major library imports -from numpy import array, linspace, meshgrid, nanmin, nanmax, pi, zeros +from numpy import array, linspace, meshgrid, nanmin, nanmax, pi, zeros # Enthought library imports -from chaco.api import ArrayDataSource, ArrayPlotData, ColorBar, ContourLinePlot, \ - ColormappedScatterPlot, CMapImagePlot, \ - ContourPolyPlot, DataRange1D, VPlotContainer, \ - DataRange2D, GridMapper, GridDataSource, \ - HPlotContainer, ImageData, LinearMapper, \ - LinePlot, OverlayPlotContainer, Plot, PlotAxis +from chaco.api import ( + ArrayDataSource, + ArrayPlotData, + ColorBar, + ContourLinePlot, + ColormappedScatterPlot, + CMapImagePlot, + ContourPolyPlot, + DataRange1D, + VPlotContainer, + DataRange2D, + GridMapper, + GridDataSource, + HPlotContainer, + ImageData, + LinearMapper, + LinePlot, + OverlayPlotContainer, + Plot, + PlotAxis, +) from chaco.default_colormaps import * from enable.component_editor import ComponentEditor -from chaco.tools.api import LineInspector, PanTool, RangeSelection, \ - RangeSelectionOverlay, ZoomTool +from chaco.tools.api import ( + LineInspector, + PanTool, + RangeSelection, + RangeSelectionOverlay, + ZoomTool, +) from enable.api import Window -from traits.api import Any, Array, Callable, CFloat, CInt, Enum, Event, Float, HasTraits, \ - Int, Instance, Str, Trait, observe +from traits.api import ( + Any, + Array, + Callable, + CFloat, + CInt, + Enum, + Event, + Float, + HasTraits, + Int, + Instance, + Str, + Trait, + observe, +) from traitsui.api import Group, Handler, HGroup, Item, View -from traitsui.menu import Action, CloseAction, Menu, \ - MenuBar, NoButtons, Separator +from traitsui.menu import Action, CloseAction, Menu, MenuBar, NoButtons, Separator class Model(HasTraits): - #Traits view definitions: + # Traits view definitions: traits_view = View( - Group(Item('function'), - HGroup(Item('npts_x', label="Number X Points"), - Item('npts_y', label="Number Y Points")), - HGroup(Item('min_x', label="Min X value"), - Item('max_x', label="Max X value")), - HGroup(Item('min_y', label="Min Y value"), - Item('max_y', label="Max Y value"))), - buttons=["OK", "Cancel"]) + Group( + Item("function"), + HGroup( + Item("npts_x", label="Number X Points"), + Item("npts_y", label="Number Y Points"), + ), + HGroup( + Item("min_x", label="Min X value"), Item("max_x", label="Max X value") + ), + HGroup( + Item("min_y", label="Min Y value"), Item("max_y", label="Max Y value") + ), + ), + buttons=["OK", "Cancel"], + ) function = Str("tanh(x**2+y)*cos(y)*jn(0,x+y*2)") npts_x = CInt(400) npts_y = CInt(200) - min_x = CFloat(-2*pi) - max_x = CFloat(2*pi) - min_y = CFloat(-1.5*pi) - max_y = CFloat(1.5*pi) + min_x = CFloat(-2 * pi) + max_x = CFloat(2 * pi) + min_y = CFloat(-1.5 * pi) + max_y = CFloat(1.5 * pi) xs = Array ys = Array @@ -68,16 +108,16 @@ def __init__(self, *args, **kwargs): def compute_model(self): # The xs and ys used for the image plot range need to be the # edges of the cells. - self.xs = linspace(self.min_x, self.max_x, self.npts_x+1) - self.ys = linspace(self.min_y, self.max_y, self.npts_y+1) + self.xs = linspace(self.min_x, self.max_x, self.npts_x + 1) + self.ys = linspace(self.min_y, self.max_y, self.npts_y + 1) # The grid of points at which we will evaluate the 2D function # is located at cell centers, so use halfsteps from the # min/max values (which are edges) xstep = (self.max_x - self.min_x) / self.npts_x ystep = (self.max_y - self.min_y) / self.npts_y - gridx = linspace(self.min_x+xstep/2, self.max_x-xstep/2, self.npts_x) - gridy = linspace(self.min_y+xstep/2, self.max_y-xstep/2, self.npts_y) + gridx = linspace(self.min_x + xstep / 2, self.max_x - xstep / 2, self.npts_x) + gridy = linspace(self.min_y + xstep / 2, self.max_y - xstep / 2, self.npts_y) x, y = meshgrid(gridx, gridy) try: d = dict(x=x, y=y) @@ -92,42 +132,40 @@ def compute_model(self): self.trait_setq(function=self._function) def _anytrait_changed(self, name, value): - if name in ['function', 'npts_x', 'npts_y', - 'min_x', 'max_x', 'min_y', 'max_y']: + if name in ["function", "npts_x", "npts_y", "min_x", "max_x", "min_y", "max_y"]: self.compute_model() class PlotUI(HasTraits): - #Traits view definitions: + # Traits view definitions: traits_view = View( - Group(Item('container', - editor=ComponentEditor(size=(800,600)), - show_label=False)), + Group( + Item("container", editor=ComponentEditor(size=(800, 600)), show_label=False) + ), buttons=NoButtons, - resizable=True) + resizable=True, + ) plot_edit_view = View( - Group(Item('num_levels'), - Item('colormap')), - buttons=["OK","Cancel"]) - + Group(Item("num_levels"), Item("colormap")), buttons=["OK", "Cancel"] + ) num_levels = Int(15) colormap = Enum(list(color_map_name_dict.keys())) - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Private Traits - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- _image_index = Instance(GridDataSource) _image_value = Instance(ImageData) _cmap = Trait(viridis, Callable) - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Public View interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def __init__(self, *args, **kwargs): super(PlotUI, self).__init__(*args, **kwargs) @@ -136,101 +174,114 @@ def __init__(self, *args, **kwargs): def create_plot(self): # Create the mapper, etc - self._image_index = GridDataSource(array([]), - array([]), - sort_order=("ascending","ascending")) + self._image_index = GridDataSource( + array([]), array([]), sort_order=("ascending", "ascending") + ) image_index_range = DataRange2D(self._image_index) self._image_index.observe(self._metadata_changed, "metadata_changed") self._image_value = ImageData(data=array([]), value_depth=1) image_value_range = DataRange1D(self._image_value) - - # Create the contour plots - self.polyplot = ContourPolyPlot(index=self._image_index, - value=self._image_value, - index_mapper=GridMapper(range= - image_index_range), - color_mapper=\ - self._cmap(image_value_range), - levels=self.num_levels) - - self.lineplot = ContourLinePlot(index=self._image_index, - value=self._image_value, - index_mapper=GridMapper(range= - self.polyplot.index_mapper.range), - levels=self.num_levels) - + self.polyplot = ContourPolyPlot( + index=self._image_index, + value=self._image_value, + index_mapper=GridMapper(range=image_index_range), + color_mapper=self._cmap(image_value_range), + levels=self.num_levels, + ) + + self.lineplot = ContourLinePlot( + index=self._image_index, + value=self._image_value, + index_mapper=GridMapper(range=self.polyplot.index_mapper.range), + levels=self.num_levels, + ) # Add a left axis to the plot - left = PlotAxis(orientation='left', - title= "y", - mapper=self.polyplot.index_mapper._ymapper, - component=self.polyplot) + left = PlotAxis( + orientation="left", + title="y", + mapper=self.polyplot.index_mapper._ymapper, + component=self.polyplot, + ) self.polyplot.overlays.append(left) # Add a bottom axis to the plot - bottom = PlotAxis(orientation='bottom', - title= "x", - mapper=self.polyplot.index_mapper._xmapper, - component=self.polyplot) + bottom = PlotAxis( + orientation="bottom", + title="x", + mapper=self.polyplot.index_mapper._xmapper, + component=self.polyplot, + ) self.polyplot.overlays.append(bottom) - # Add some tools to the plot - self.polyplot.tools.append(PanTool(self.polyplot, - constrain_key="shift")) - self.polyplot.overlays.append(ZoomTool(component=self.polyplot, - tool_mode="box", always_on=False)) - self.polyplot.overlays.append(LineInspector(component=self.polyplot, - axis='index_x', - inspect_mode="indexed", - write_metadata=True, - is_listener=False, - color="white")) - self.polyplot.overlays.append(LineInspector(component=self.polyplot, - axis='index_y', - inspect_mode="indexed", - write_metadata=True, - color="white", - is_listener=False)) + self.polyplot.tools.append(PanTool(self.polyplot, constrain_key="shift")) + self.polyplot.overlays.append( + ZoomTool(component=self.polyplot, tool_mode="box", always_on=False) + ) + self.polyplot.overlays.append( + LineInspector( + component=self.polyplot, + axis="index_x", + inspect_mode="indexed", + write_metadata=True, + is_listener=False, + color="white", + ) + ) + self.polyplot.overlays.append( + LineInspector( + component=self.polyplot, + axis="index_y", + inspect_mode="indexed", + write_metadata=True, + color="white", + is_listener=False, + ) + ) # Add these two plots to one container - contour_container = OverlayPlotContainer(padding=20, - use_backbuffer=True, - unified_draw=True) + contour_container = OverlayPlotContainer( + padding=20, use_backbuffer=True, unified_draw=True + ) contour_container.add(self.polyplot) contour_container.add(self.lineplot) - # Create a colorbar cbar_index_mapper = LinearMapper(range=image_value_range) - self.colorbar = ColorBar(index_mapper=cbar_index_mapper, - plot=self.polyplot, - padding_top=self.polyplot.padding_top, - padding_bottom=self.polyplot.padding_bottom, - padding_right=40, - resizable='v', - width=30) - - self.pd = ArrayPlotData(line_index = array([]), - line_value = array([]), - scatter_index = array([]), - scatter_value = array([]), - scatter_color = array([])) + self.colorbar = ColorBar( + index_mapper=cbar_index_mapper, + plot=self.polyplot, + padding_top=self.polyplot.padding_top, + padding_bottom=self.polyplot.padding_bottom, + padding_right=40, + resizable="v", + width=30, + ) + + self.pd = ArrayPlotData( + line_index=array([]), + line_value=array([]), + scatter_index=array([]), + scatter_value=array([]), + scatter_color=array([]), + ) self.cross_plot = Plot(self.pd, resizable="h") self.cross_plot.height = 100 self.cross_plot.padding = 20 - self.cross_plot.plot(("line_index", "line_value"), - line_style="dot") - self.cross_plot.plot(("scatter_index","scatter_value","scatter_color"), - type="cmap_scatter", - name="dot", - color_mapper=self._cmap(image_value_range), - marker="circle", - marker_size=8) + self.cross_plot.plot(("line_index", "line_value"), line_style="dot") + self.cross_plot.plot( + ("scatter_index", "scatter_value", "scatter_color"), + type="cmap_scatter", + name="dot", + color_mapper=self._cmap(image_value_range), + marker="circle", + marker_size=8, + ) self.cross_plot.index_range = self.polyplot.index_range.x_range @@ -240,23 +291,30 @@ def create_plot(self): self.pd.set_data("scatter_value2", array([])) self.pd.set_data("scatter_color2", array([])) - self.cross_plot2 = Plot(self.pd, width = 140, orientation="v", resizable="v", padding=20, padding_bottom=160) - self.cross_plot2.plot(("line_index2", "line_value2"), - line_style="dot") - self.cross_plot2.plot(("scatter_index2","scatter_value2","scatter_color2"), - type="cmap_scatter", - name="dot", - color_mapper=self._cmap(image_value_range), - marker="circle", - marker_size=8) + self.cross_plot2 = Plot( + self.pd, + width=140, + orientation="v", + resizable="v", + padding=20, + padding_bottom=160, + ) + self.cross_plot2.plot(("line_index2", "line_value2"), line_style="dot") + self.cross_plot2.plot( + ("scatter_index2", "scatter_value2", "scatter_color2"), + type="cmap_scatter", + name="dot", + color_mapper=self._cmap(image_value_range), + marker="circle", + marker_size=8, + ) self.cross_plot2.index_range = self.polyplot.index_range.y_range - - # Create a container and add components - self.container = HPlotContainer(padding=40, fill_padding=True, - bgcolor = "white", use_backbuffer=False) + self.container = HPlotContainer( + padding=40, fill_padding=True, bgcolor="white", use_backbuffer=False + ) inner_cont = VPlotContainer(padding=0, use_backbuffer=True) inner_cont.add(self.cross_plot) inner_cont.add(contour_container) @@ -264,7 +322,6 @@ def create_plot(self): self.container.add(inner_cont) self.container.add(self.cross_plot2) - def update(self, model): self.minz = model.minz self.maxz = model.maxz @@ -277,10 +334,9 @@ def update(self, model): self.container.invalidate_draw() self.container.request_redraw() - - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Event handlers - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def _metadata_changed(self, event): old, new = event.old, event.new @@ -295,22 +351,24 @@ def _metadata_changed(self, event): if "selections" in self._image_index.metadata: x_ndx, y_ndx = self._image_index.metadata["selections"] if y_ndx and x_ndx: - self.pd.set_data("line_value", - self._image_value.data[y_ndx,:]) - self.pd.set_data("line_value2", - self._image_value.data[:,x_ndx]) + self.pd.set_data("line_value", self._image_value.data[y_ndx, :]) + self.pd.set_data("line_value2", self._image_value.data[:, x_ndx]) xdata, ydata = self._image_index.get_data() xdata, ydata = xdata.get_data(), ydata.get_data() self.pd.set_data("scatter_index", array([xdata[x_ndx]])) self.pd.set_data("scatter_index2", array([ydata[y_ndx]])) - self.pd.set_data("scatter_value", - array([self._image_value.data[y_ndx, x_ndx]])) - self.pd.set_data("scatter_value2", - array([self._image_value.data[y_ndx, x_ndx]])) - self.pd.set_data("scatter_color", - array([self._image_value.data[y_ndx, x_ndx]])) - self.pd.set_data("scatter_color2", - array([self._image_value.data[y_ndx, x_ndx]])) + self.pd.set_data( + "scatter_value", array([self._image_value.data[y_ndx, x_ndx]]) + ) + self.pd.set_data( + "scatter_value2", array([self._image_value.data[y_ndx, x_ndx]]) + ) + self.pd.set_data( + "scatter_color", array([self._image_value.data[y_ndx, x_ndx]]) + ) + self.pd.set_data( + "scatter_color2", array([self._image_value.data[y_ndx, x_ndx]]) + ) else: self.pd.set_data("scatter_value", array([])) self.pd.set_data("scatter_value2", array([])) @@ -336,29 +394,27 @@ def _num_levels_changed(self): self.lineplot.levels = self.num_levels - class Controller(Handler): - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # State traits - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- model = Instance(Model) view = Instance(PlotUI) - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Handler interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def init(self, info): self.model = info.object.model self.view = info.object.view self.model.observe(self._model_changed, "model_changed") - - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Public Controller interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def edit_model(self, ui_info): self.model.configure_traits() @@ -366,49 +422,57 @@ def edit_model(self, ui_info): def edit_plot(self, ui_info): self.view.configure_traits(view="plot_edit_view") - - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Private Controller interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def _model_changed(self, event): if self.view is not None: self.view.update(self.model) + class ModelView(HasTraits): model = Instance(Model) view = Instance(PlotUI) - traits_view = View(Item('@view', - show_label=False), - menubar=MenuBar(Menu(Action(name="Edit Model", - action="edit_model"), - Action(name="Edit Plot", - action="edit_plot"), - CloseAction, - name="File")), - handler = Controller, - title = "Function Inspector", - resizable=True) - - @observe('model, view') + traits_view = View( + Item("@view", show_label=False), + menubar=MenuBar( + Menu( + Action(name="Edit Model", action="edit_model"), + Action(name="Edit Plot", action="edit_plot"), + CloseAction, + name="File", + ) + ), + handler=Controller, + title="Function Inspector", + resizable=True, + ) + + @observe("model, view") def update_view(self, event): if self.model is not None and self.view is not None: self.view.update(self.model) -options_dict = {'colormap' : "viridis", - 'num_levels' : 15, - 'function' : "tanh(x**2+y)*cos(y)*jn(0,x+y*2)"} -model=Model(**options_dict) -view=PlotUI(**options_dict) + +options_dict = { + "colormap": "viridis", + "num_levels": 15, + "function": "tanh(x**2+y)*cos(y)*jn(0,x+y*2)", +} +model = Model(**options_dict) +view = PlotUI(**options_dict) popup = ModelView(model=model, view=view) + def show_plot(**kwargs): model = Model(**kwargs) view = PlotUI(**kwargs) - modelview=ModelView(model=model, view=view) + modelview = ModelView(model=model, view=view) modelview.configure_traits() + def main(argv=None): if argv is None: @@ -417,26 +481,46 @@ def main(argv=None): usage = "usage: %prog [options]" parser = OptionParser(usage=usage, version="%prog 1.0") - parser.add_option("-c", "--colormap", - action="store", type="string", dest="colormap", default="viridis", - metavar="CMAP", help="choose a default colormapper") - - parser.add_option("-n", "--nlevels", - action="store", type="int", dest="num_levels", default=15, - help="number countour levels to plot [default: %default]") - - parser.add_option("-f", "--function", - action="store", type="string", dest="function", - default="tanh(x**2+y)*cos(y)*jn(0,x+y*2)", - help="function of x and y [default: %default]") + parser.add_option( + "-c", + "--colormap", + action="store", + type="string", + dest="colormap", + default="viridis", + metavar="CMAP", + help="choose a default colormapper", + ) + + parser.add_option( + "-n", + "--nlevels", + action="store", + type="int", + dest="num_levels", + default=15, + help="number countour levels to plot [default: %default]", + ) + + parser.add_option( + "-f", + "--function", + action="store", + type="string", + dest="function", + default="tanh(x**2+y)*cos(y)*jn(0,x+y*2)", + help="function of x and y [default: %default]", + ) opts, args = parser.parse_args(argv[1:]) if len(args) > 0: parser.error("Incorrect number of arguments") - show_plot(colormap=opts.colormap, num_levels=opts.num_levels, - function=opts.function) + show_plot( + colormap=opts.colormap, num_levels=opts.num_levels, function=opts.function + ) + if __name__ == "__main__": sys.exit(main()) diff --git a/examples/demo/advanced/spec_waterfall.py b/examples/demo/advanced/spec_waterfall.py index 051b35a0f..dcdf2c047 100644 --- a/examples/demo/advanced/spec_waterfall.py +++ b/examples/demo/advanced/spec_waterfall.py @@ -15,13 +15,22 @@ from pyface.timer.api import Timer # Chaco imports -from chaco.api import (Plot, ArrayPlotData, HPlotContainer, VPlotContainer, - AbstractMapper, LinePlot, LinearMapper, DataRange1D) +from chaco.api import ( + Plot, + ArrayPlotData, + HPlotContainer, + VPlotContainer, + AbstractMapper, + LinePlot, + LinearMapper, + DataRange1D, +) NUM_SAMPLES = 1024 SAMPLING_RATE = 11025 SPECTROGRAM_LENGTH = 50 + class WaterfallRenderer(LinePlot): # numpy arrays of the same length @@ -42,7 +51,11 @@ def _gather_points(self): values = self.values numindex = len(index) - if numindex == 0 or all(len(v)==0 for v in values) or all(numindex != len(v) for v in values): + if ( + numindex == 0 + or all(len(v) == 0 for v in values) + or all(numindex != len(v) for v in values) + ): self._cached_data_pts = [] self._cache_valid = True @@ -54,7 +67,7 @@ def get_screen_points(self): return [self.map_screen(pts, i) for i, pts in enumerate(self._cached_data_pts)] def map_screen(self, data_array, data_offset=None): - """ data_offset, if provided, is a float that will be mapped + """data_offset, if provided, is a float that will be mapped into screen space using self.value_mapper and then added to mapping data_array with y2_mapper. If data_offset is not provided, then y2_mapper is used. @@ -74,52 +87,58 @@ def map_screen(self, data_array, data_offset=None): else: return transpose(array((sy, sx))) -#============================================================================ + +# ============================================================================ # Create the Chaco plot. -#============================================================================ +# ============================================================================ + def _create_plot_component(obj): # Setup the spectrum plot - frequencies = linspace(0.0, float(SAMPLING_RATE)/2, num=NUM_SAMPLES/2) + frequencies = linspace(0.0, float(SAMPLING_RATE) / 2, num=NUM_SAMPLES / 2) obj.spectrum_data = ArrayPlotData(frequency=frequencies) - empty_amplitude = zeros(NUM_SAMPLES/2) - obj.spectrum_data.set_data('amplitude', empty_amplitude) + empty_amplitude = zeros(NUM_SAMPLES / 2) + obj.spectrum_data.set_data("amplitude", empty_amplitude) obj.spectrum_plot = Plot(obj.spectrum_data) - spec_renderer = obj.spectrum_plot.plot(("frequency", "amplitude"), name="Spectrum", - color="red")[0] + spec_renderer = obj.spectrum_plot.plot( + ("frequency", "amplitude"), name="Spectrum", color="red" + )[0] obj.spectrum_plot.padding = 50 obj.spectrum_plot.title = "Spectrum" spec_range = list(obj.spectrum_plot.plots.values())[0][0].value_mapper.range spec_range.low = 0.0 spec_range.high = 5.0 - obj.spectrum_plot.index_axis.title = 'Frequency (hz)' - obj.spectrum_plot.value_axis.title = 'Amplitude' + obj.spectrum_plot.index_axis.title = "Frequency (hz)" + obj.spectrum_plot.value_axis.title = "Amplitude" # Time Series plot - times = linspace(0.0, float(NUM_SAMPLES)/SAMPLING_RATE, num=NUM_SAMPLES) + times = linspace(0.0, float(NUM_SAMPLES) / SAMPLING_RATE, num=NUM_SAMPLES) obj.time_data = ArrayPlotData(time=times) empty_amplitude = zeros(NUM_SAMPLES) - obj.time_data.set_data('amplitude', empty_amplitude) + obj.time_data.set_data("amplitude", empty_amplitude) obj.time_plot = Plot(obj.time_data) obj.time_plot.plot(("time", "amplitude"), name="Time", color="blue") obj.time_plot.padding = 50 obj.time_plot.title = "Time" - obj.time_plot.index_axis.title = 'Time (seconds)' - obj.time_plot.value_axis.title = 'Amplitude' + obj.time_plot.index_axis.title = "Time (seconds)" + obj.time_plot.value_axis.title = "Amplitude" time_range = list(obj.time_plot.plots.values())[0][0].value_mapper.range time_range.low = -0.2 time_range.high = 0.2 # Spectrogram plot - values = [zeros(NUM_SAMPLES/2) for i in range(SPECTROGRAM_LENGTH)] - p = WaterfallRenderer(index = spec_renderer.index, values = values, - index_mapper = LinearMapper(range = obj.spectrum_plot.index_mapper.range), - value_mapper = LinearMapper(range = DataRange1D(low=0, high=SPECTROGRAM_LENGTH)), - y2_mapper = LinearMapper(low_pos=0, high_pos=8, - range=DataRange1D(low=0, high=15)), - ) + values = [zeros(NUM_SAMPLES / 2) for i in range(SPECTROGRAM_LENGTH)] + p = WaterfallRenderer( + index=spec_renderer.index, + values=values, + index_mapper=LinearMapper(range=obj.spectrum_plot.index_mapper.range), + value_mapper=LinearMapper(range=DataRange1D(low=0, high=SPECTROGRAM_LENGTH)), + y2_mapper=LinearMapper( + low_pos=0, high_pos=8, range=DataRange1D(low=0, high=15) + ), + ) spectrogram_plot = p obj.spectrogram_plot = p dummy = Plot() @@ -141,39 +160,43 @@ def _create_plot_component(obj): def get_audio_data(): pa = pyaudio.PyAudio() - stream = pa.open(format=pyaudio.paInt16, channels=1, rate=SAMPLING_RATE, - input=True, frames_per_buffer=NUM_SAMPLES) - audio_data = fromstring(stream.read(NUM_SAMPLES), dtype=short) + stream = pa.open( + format=pyaudio.paInt16, + channels=1, + rate=SAMPLING_RATE, + input=True, + frames_per_buffer=NUM_SAMPLES, + ) + audio_data = fromstring(stream.read(NUM_SAMPLES), dtype=short) stream.close() normalized_data = audio_data / 32768.0 - return (abs(fft(normalized_data))[:NUM_SAMPLES/2], normalized_data) + return (abs(fft(normalized_data))[: NUM_SAMPLES / 2], normalized_data) # HasTraits class that supplies the callable for the timer event. class TimerController(HasTraits): - def onTimer(self, *args): spectrum, time = get_audio_data() - self.spectrum_data.set_data('amplitude', spectrum) - self.time_data.set_data('amplitude', time) + self.spectrum_data.set_data("amplitude", spectrum) + self.time_data.set_data("amplitude", time) spec_data = self.spectrogram_plot.values[1:] + [spectrum] self.spectrogram_plot.values = spec_data self.spectrum_plot.request_redraw() -#============================================================================ +# ============================================================================ # Attributes to use for the plot view. -size = (900,850) +size = (900, 850) title = "Audio Spectrum Waterfall" -#============================================================================ +# ============================================================================ # Demo class that is used by the demo.py application. -#============================================================================ +# ============================================================================ -class DemoHandler(Handler): +class DemoHandler(Handler): def closed(self, info, is_ok): - """ Handles a dialog-based user interface being closed by the user. + """Handles a dialog-based user interface being closed by the user. Overridden here to stop the timer once the window is destroyed. """ @@ -189,14 +212,16 @@ class Demo(HasTraits): timer = Instance(Timer) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1]+25, - handler=DemoHandler - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1] + 25, + handler=DemoHandler, + ) def __init__(self, **traits): super(Demo, self).__init__(**traits) diff --git a/examples/demo/advanced/spectrum.py b/examples/demo/advanced/spectrum.py index db1d02273..7b09f5a14 100644 --- a/examples/demo/advanced/spectrum.py +++ b/examples/demo/advanced/spectrum.py @@ -11,7 +11,7 @@ try: import pyaudio except ImportError: - sys.exit('You need pyaudio installed to run this demo.') + sys.exit("You need pyaudio installed to run this demo.") from numpy import zeros, linspace, short, fromstring, hstack, transpose from scipy import fft @@ -30,61 +30,62 @@ SAMPLING_RATE = 11025 SPECTROGRAM_LENGTH = 100 -#============================================================================ +# ============================================================================ # Create the Chaco plot. -#============================================================================ +# ============================================================================ + def _create_plot_component(obj): # Setup the spectrum plot - frequencies = linspace(0.0, float(SAMPLING_RATE)/2, num=NUM_SAMPLES/2) + frequencies = linspace(0.0, float(SAMPLING_RATE) / 2, num=NUM_SAMPLES / 2) obj.spectrum_data = ArrayPlotData(frequency=frequencies) - empty_amplitude = zeros(NUM_SAMPLES//2) - obj.spectrum_data.set_data('amplitude', empty_amplitude) + empty_amplitude = zeros(NUM_SAMPLES // 2) + obj.spectrum_data.set_data("amplitude", empty_amplitude) obj.spectrum_plot = Plot(obj.spectrum_data) - obj.spectrum_plot.plot(("frequency", "amplitude"), name="Spectrum", - color="red") + obj.spectrum_plot.plot(("frequency", "amplitude"), name="Spectrum", color="red") obj.spectrum_plot.padding = 50 obj.spectrum_plot.title = "Spectrum" spec_range = list(obj.spectrum_plot.plots.values())[0][0].value_mapper.range spec_range.low = 0.0 spec_range.high = 5.0 - obj.spectrum_plot.index_axis.title = 'Frequency (Hz)' - obj.spectrum_plot.value_axis.title = 'Amplitude' + obj.spectrum_plot.index_axis.title = "Frequency (Hz)" + obj.spectrum_plot.value_axis.title = "Amplitude" # Time Series plot - times = linspace(0.0, float(NUM_SAMPLES)/SAMPLING_RATE, num=NUM_SAMPLES) + times = linspace(0.0, float(NUM_SAMPLES) / SAMPLING_RATE, num=NUM_SAMPLES) obj.time_data = ArrayPlotData(time=times) empty_amplitude = zeros(NUM_SAMPLES) - obj.time_data.set_data('amplitude', empty_amplitude) + obj.time_data.set_data("amplitude", empty_amplitude) obj.time_plot = Plot(obj.time_data) obj.time_plot.plot(("time", "amplitude"), name="Time", color="blue") obj.time_plot.padding = 50 obj.time_plot.title = "Time" - obj.time_plot.index_axis.title = 'Time (seconds)' - obj.time_plot.value_axis.title = 'Amplitude' + obj.time_plot.index_axis.title = "Time (seconds)" + obj.time_plot.value_axis.title = "Amplitude" time_range = list(obj.time_plot.plots.values())[0][0].value_mapper.range time_range.low = -0.2 time_range.high = 0.2 # Spectrogram plot - spectrogram_data = zeros(( NUM_SAMPLES//2, SPECTROGRAM_LENGTH)) + spectrogram_data = zeros((NUM_SAMPLES // 2, SPECTROGRAM_LENGTH)) obj.spectrogram_plotdata = ArrayPlotData() - obj.spectrogram_plotdata.set_data('imagedata', spectrogram_data) + obj.spectrogram_plotdata.set_data("imagedata", spectrogram_data) spectrogram_plot = Plot(obj.spectrogram_plotdata) max_time = float(SPECTROGRAM_LENGTH * NUM_SAMPLES) / SAMPLING_RATE max_freq = float(SAMPLING_RATE / 2) - spectrogram_plot.img_plot('imagedata', - name='Spectrogram', - xbounds=(0, max_time), - ybounds=(0, max_freq), - colormap=hot, - ) - range_obj = spectrogram_plot.plots['Spectrogram'][0].value_mapper.range + spectrogram_plot.img_plot( + "imagedata", + name="Spectrogram", + xbounds=(0, max_time), + ybounds=(0, max_freq), + colormap=hot, + ) + range_obj = spectrogram_plot.plots["Spectrogram"][0].value_mapper.range range_obj.high = 5 range_obj.low = 0.0 - spectrogram_plot.title = 'Spectrogram' + spectrogram_plot.title = "Spectrogram" obj.spectrogram_plot = spectrogram_plot container = HPlotContainer() @@ -94,15 +95,23 @@ def _create_plot_component(obj): return container + _stream = None + + def get_audio_data(): global _stream if _stream is None: pa = pyaudio.PyAudio() - _stream = pa.open(format=pyaudio.paInt16, channels=1, rate=SAMPLING_RATE, - input=True, frames_per_buffer=NUM_SAMPLES) + _stream = pa.open( + format=pyaudio.paInt16, + channels=1, + rate=SAMPLING_RATE, + input=True, + frames_per_buffer=NUM_SAMPLES, + ) try: - audio_data = fromstring(_stream.read(NUM_SAMPLES), dtype=short) + audio_data = fromstring(_stream.read(NUM_SAMPLES), dtype=short) except IOError as e: # Workaround "Input overflowed" issue on OS X, by restarting stream if e.errno != "Input overflowed": @@ -112,36 +121,35 @@ def get_audio_data(): _stream.close() _stream = None normalized_data = audio_data / 32768.0 - return (abs(fft(normalized_data))[:NUM_SAMPLES//2], normalized_data) + return (abs(fft(normalized_data))[: NUM_SAMPLES // 2], normalized_data) # HasTraits class that supplies the callable for the timer event. class TimerController(HasTraits): - def onTimer(self, *args): spectrum, time = get_audio_data() - self.spectrum_data.set_data('amplitude', spectrum) - self.time_data.set_data('amplitude', time) - spectrogram_data = self.spectrogram_plotdata.get_data('imagedata') - spectrogram_data = hstack((spectrogram_data[:,1:], - transpose([spectrum]))) + self.spectrum_data.set_data("amplitude", spectrum) + self.time_data.set_data("amplitude", time) + spectrogram_data = self.spectrogram_plotdata.get_data("imagedata") + spectrogram_data = hstack((spectrogram_data[:, 1:], transpose([spectrum]))) - self.spectrogram_plotdata.set_data('imagedata', spectrogram_data) + self.spectrogram_plotdata.set_data("imagedata", spectrogram_data) self.spectrum_plot.request_redraw() -#============================================================================ + +# ============================================================================ # Attributes to use for the plot view. -size = (900,500) +size = (900, 500) title = "Audio Spectrum" -#============================================================================ +# ============================================================================ # Demo class that is used by the demo.py application. -#============================================================================ +# ============================================================================ -class DemoHandler(Handler): +class DemoHandler(Handler): def closed(self, info, is_ok): - """ Handles a dialog-based user interface being closed by the user. + """Handles a dialog-based user interface being closed by the user. Overridden here to stop the timer once the window is destroyed. """ @@ -157,14 +165,16 @@ class Demo(HasTraits): timer = Instance(Timer) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1], - handler=DemoHandler - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + handler=DemoHandler, + ) def __init__(self, **traits): super(Demo, self).__init__(**traits) @@ -182,6 +192,7 @@ def configure_traits(self, *args, **kws): self.timer = Timer(20, self.controller.onTimer) return super(Demo, self).configure_traits(*args, **kws) + popup = Demo() if __name__ == "__main__": diff --git a/examples/demo/aspect_ratio.py b/examples/demo/aspect_ratio.py index 7f590c803..9163c6ba8 100644 --- a/examples/demo/aspect_ratio.py +++ b/examples/demo/aspect_ratio.py @@ -23,6 +23,7 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool + class AspectRatio(BaseFloat): "A new Trait for defining aspect ratios" @@ -46,21 +47,22 @@ class MyPlot(HasTraits): fixed_x = Bool(False) fixed_y = Bool(False) traits_view = View( - VGroup( - HGroup( - Item("screen_enabled", label="Screen"), - Item("screen_aspect", label="aspect ratio (w/h)") - ), - HGroup( - Item("fixed_x", label="Data X fixed"), - Item("fixed_y", label="Data Y fixed") - ), - Item("plot", editor=ComponentEditor(size=(100,100)), - show_label=False) - ), - width=600, height=600, resizable=True, - title="Aspect Ratio Example") - + VGroup( + HGroup( + Item("screen_enabled", label="Screen"), + Item("screen_aspect", label="aspect ratio (w/h)"), + ), + HGroup( + Item("fixed_x", label="Data X fixed"), + Item("fixed_y", label="Data Y fixed"), + ), + Item("plot", editor=ComponentEditor(size=(100, 100)), show_label=False), + ), + width=600, + height=600, + resizable=True, + title="Aspect Ratio Example", + ) def __init__(self, *args, **kw): HasTraits.__init__(self, *args, **kw) @@ -97,10 +99,11 @@ def _fixed_y_changed(self): renderer.value_mapper.stretch_data = not self.fixed_y self.plot.request_redraw() -#=============================================================================== + +# =============================================================================== # # Create the demo object to be used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = myplot = MyPlot() if __name__ == "__main__": - myplot.configure_traits() \ No newline at end of file + myplot.configure_traits() diff --git a/examples/demo/basic/bar_plot_configurable.py b/examples/demo/basic/bar_plot_configurable.py index cd60d11fd..0b775d320 100644 --- a/examples/demo/basic/bar_plot_configurable.py +++ b/examples/demo/basic/bar_plot_configurable.py @@ -15,35 +15,32 @@ class BarPlotDemo(HasTraits): # The bar plot renderer. bar_plot = Instance(BarPlot) - # Assorted styles that will be set on `bar_plot`. + # Assorted styles that will be set on `bar_plot`. bar_width = Range(0.0, 1.0, 0.8) line_width = Range(0.0, 10.0, 5.0) alpha = Range(0.0, 1.0, 1.0) line_color_alpha = Range(0.0, 1.0, 1.0) fill_color_alpha = Range(0.0, 1.0, 1.0) - traits_view = \ - View( + traits_view = View( + VGroup( + Group( + UItem("bar_plot", editor=ComponentEditor(), style="custom"), + ), VGroup( - Group( - UItem('bar_plot', - editor=ComponentEditor(), - style='custom'), - ), - VGroup( - Item('bar_width'), - Item('line_width'), - Item('line_color_alpha'), - Item('fill_color_alpha'), - Item('alpha'), - ), + Item("bar_width"), + Item("line_width"), + Item("line_color_alpha"), + Item("fill_color_alpha"), + Item("alpha"), ), - resizable=True, - ) + ), + resizable=True, + ) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Default values - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _bar_plot_default(self): @@ -61,21 +58,22 @@ def _bar_plot_default(self): value_mapper = LinearMapper(range=value_range) # The bar plot - plot = BarPlot(index=index, value=value, - value_mapper=value_mapper, - index_mapper=index_mapper, - line_color="black", - fill_color="cornflowerblue", - bgcolor="white", - bar_width=self.bar_width, - line_width=self.line_width, - ) + plot = BarPlot( + index=index, + value=value, + value_mapper=value_mapper, + index_mapper=index_mapper, + line_color="black", + fill_color="cornflowerblue", + bgcolor="white", + bar_width=self.bar_width, + line_width=self.line_width, + ) return plot - - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Trait change handlers - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _line_color_alpha_changed(self): alpha = self.line_color_alpha @@ -96,6 +94,7 @@ def _bar_width_changed(self): def _line_width_changed(self): self.bar_plot.line_width = self.line_width + demo = BarPlotDemo() if __name__ == "__main__": diff --git a/examples/demo/basic/bar_plot_stacked.py b/examples/demo/basic/bar_plot_stacked.py index 95ef61943..d036b4a61 100644 --- a/examples/demo/basic/bar_plot_stacked.py +++ b/examples/demo/basic/bar_plot_stacked.py @@ -13,11 +13,15 @@ # Chaco imports from chaco.api import LabelAxis, Plot, ArrayPlotData, ArrayDataSource + class PlotExample(HasTraits): plot = Instance(Plot) - traits_view = View(UItem('plot', editor=ComponentEditor()), - width=400, height=400, resizable=True, - ) + traits_view = View( + UItem("plot", editor=ComponentEditor()), + width=400, + height=400, + resizable=True, + ) def __init__(self, index, series_a, series_b, series_c, **kw): super(PlotExample, self).__init__(**kw) @@ -27,31 +31,46 @@ def __init__(self, index, series_a, series_b, series_c, **kw): series_b = series_b + series_a plot_data = ArrayPlotData(index=index) - plot_data.set_data('series_a', series_a) - plot_data.set_data('series_b', series_b) - plot_data.set_data('series_c', series_c) + plot_data.set_data("series_a", series_a) + plot_data.set_data("series_b", series_b) + plot_data.set_data("series_c", series_c) self.plot = Plot(plot_data) - self.plot.plot(('index', 'series_a'), type='bar', bar_width=0.8, color='auto') - self.plot.plot(('index', 'series_b'), type='bar', bar_width=0.8, color='auto', starting_value=ArrayDataSource(series_a)) - self.plot.plot(('index', 'series_c'), type='bar', bar_width=0.8, color='auto', starting_value=ArrayDataSource(series_b)) + self.plot.plot(("index", "series_a"), type="bar", bar_width=0.8, color="auto") + self.plot.plot( + ("index", "series_b"), + type="bar", + bar_width=0.8, + color="auto", + starting_value=ArrayDataSource(series_a), + ) + self.plot.plot( + ("index", "series_c"), + type="bar", + bar_width=0.8, + color="auto", + starting_value=ArrayDataSource(series_b), + ) # set the plot's value range to 0, otherwise it may pad too much self.plot.value_range.low = 0 # replace the index values with some nicer labels - label_axis = LabelAxis(self.plot, orientation='bottom', - title='Months', - positions = list(range(1, 10)), - labels = ['jan', 'feb', 'march', 'april', 'may'], - small_haxis_style=True) + label_axis = LabelAxis( + self.plot, + orientation="bottom", + title="Months", + positions=list(range(1, 10)), + labels=["jan", "feb", "march", "april", "may"], + small_haxis_style=True, + ) self.plot.underlays.remove(self.plot.index_axis) self.plot.index_axis = label_axis self.plot.underlays.append(label_axis) -index = numpy.array([1,2,3,4,5]) -demo = PlotExample(index, index*10, index*5, index*2) +index = numpy.array([1, 2, 3, 4, 5]) +demo = PlotExample(index, index * 10, index * 5, index * 2) if __name__ == "__main__": demo.configure_traits() diff --git a/examples/demo/basic/bounded_grids.py b/examples/demo/basic/bounded_grids.py index c7be93a1f..6e2ae04cd 100644 --- a/examples/demo/basic/bounded_grids.py +++ b/examples/demo/basic/bounded_grids.py @@ -16,16 +16,16 @@ from chaco.api import ArrayPlotData, HPlotContainer, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some x-y data series to plot x = linspace(-2.0, 10.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) for i in range(5): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) # Create some line plots of some of the data plot = Plot(pd, title="Line Plot", padding=50, border_visible=True) @@ -55,7 +55,7 @@ def _create_plot_component(): # A second plot whose vertical grid lines are clipped to the jn(3) function def my_bounds_func(ticks): """ Returns y_low and y_high for each grid tick in the array **ticks** """ - tmp = array([zeros(len(ticks)),jn(3, ticks)]).T + tmp = array([zeros(len(ticks)), jn(3, ticks)]).T return tmp func_plot = Plot(pd, padding=50, border_visible=True) @@ -71,27 +71,31 @@ def my_bounds_func(ticks): return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Grids with bounded extents" +size = (900, 500) +title = "Grids with bounded extents" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) - traits_view = View(UItem('plot', editor=ComponentEditor()), - width=size[0], height=size[1], resizable=True, - title=title - ) + traits_view = View( + UItem("plot", editor=ComponentEditor()), + width=size[0], + height=size[1], + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/demo/basic/candle.py b/examples/demo/basic/candle.py index 2b34423b5..1d127743e 100644 --- a/examples/demo/basic/candle.py +++ b/examples/demo/basic/candle.py @@ -21,9 +21,10 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== + def _create_data(numpoints): index = arange(numpoints) @@ -39,27 +40,32 @@ def _create_data(numpoints): sorted_vals.sort(0) return index, sorted_vals + def _create_plot_component(): # Create some data index, sorted_vals = _create_data(200) # Create a plot data obect and give it this data - pd = ArrayPlotData(index = index, - min = sorted_vals[0], - bar_min = sorted_vals[1], - average = sorted_vals[2], - bar_max = sorted_vals[3], - max = sorted_vals[4]) + pd = ArrayPlotData( + index=index, + min=sorted_vals[0], + bar_min=sorted_vals[1], + average=sorted_vals[2], + bar_max=sorted_vals[3], + max=sorted_vals[4], + ) # Create the plot plot = Plot(pd) - plot.candle_plot(("index", "min", "bar_min", "average", "bar_max", "max"), - color = "lightgray", - bar_line_color = "black", - stem_color = "blue", - center_color = "red", - center_width = 2) + plot.candle_plot( + ("index", "min", "bar_min", "average", "bar_max", "max"), + color="lightgray", + bar_line_color="black", + stem_color="blue", + center_color="red", + center_width=2, + ) # Tweak some of the plot properties plot.title = "Candlestick Plot" @@ -73,24 +79,29 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (650, 650) title = "Candlestick plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) - traits_view = View(UItem('plot', editor=ComponentEditor()), - width=size[0], height=size[1], resizable=True, - title=title - ) + traits_view = View( + UItem("plot", editor=ComponentEditor()), + width=size[0], + height=size[1], + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/cmap_image_aspect_ratio.py b/examples/demo/basic/cmap_image_aspect_ratio.py index eb7971438..c8e5d7b74 100644 --- a/examples/demo/basic/cmap_image_aspect_ratio.py +++ b/examples/demo/basic/cmap_image_aspect_ratio.py @@ -21,15 +21,15 @@ from chaco.api import ArrayPlotData, viridis, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create a scalar field to colormap xs = linspace(0, 10, 600) ys = linspace(0, 5, 600) - x, y = meshgrid(xs,ys) - z = exp(-(x**2+y**2)/100) + x, y = meshgrid(xs, ys) + z = exp(-(x ** 2 + y ** 2) / 100) # Create a plot data object and give it this data pd = ArrayPlotData() @@ -37,10 +37,9 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - img_plot = plot.img_plot("imagedata", - xbounds=(0, 10), - ybounds=(0, 5), - colormap=viridis)[0] + img_plot = plot.img_plot( + "imagedata", xbounds=(0, 10), ybounds=(0, 5), colormap=viridis + )[0] img_plot.index_mapper.aspect_ratio = 0.5 img_plot.index_mapper.maintain_aspect_ratio = True @@ -55,26 +54,29 @@ def _create_plot_component(): return plot -#=============================================================================== +# =============================================================================== # Attributes to use for the plot view. -size=(800,600) -title="Basic Colormapped Image Plot" +size = (800, 600) +title = "Basic Colormapped Image Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) + def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/cmap_image_plot.py b/examples/demo/basic/cmap_image_plot.py index 32f0c06ef..da2004ba6 100644 --- a/examples/demo/basic/cmap_image_plot.py +++ b/examples/demo/basic/cmap_image_plot.py @@ -21,15 +21,15 @@ from chaco.api import ArrayPlotData, viridis, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create a scalar field to colormap xs = linspace(0, 10, 600) ys = linspace(0, 5, 600) - x, y = meshgrid(xs,ys) - z = exp(-(x**2+y**2)/100) + x, y = meshgrid(xs, ys) + z = exp(-(x ** 2 + y ** 2) / 100) # Create a plot data object and give it this data pd = ArrayPlotData() @@ -37,10 +37,9 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - img_plot = plot.img_plot("imagedata", - xbounds=(0, 10), - ybounds=(0, 5), - colormap=viridis)[0] + img_plot = plot.img_plot( + "imagedata", xbounds=(0, 10), ybounds=(0, 5), colormap=viridis + )[0] # Tweak some of the plot properties plot.title = "My First Image Plot" @@ -53,29 +52,31 @@ def _create_plot_component(): return plot -#=============================================================================== +# =============================================================================== # Attributes to use for the plot view. -size=(800,600) -title="Basic Colormapped Image Plot" +size = (800, 600) +title = "Basic Colormapped Image Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) + def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/demo/basic/cmap_image_select.py b/examples/demo/basic/cmap_image_select.py index 3336bee71..46e7a1264 100644 --- a/examples/demo/basic/cmap_image_select.py +++ b/examples/demo/basic/cmap_image_select.py @@ -19,22 +19,27 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ArrayPlotData, ColorBar, HPlotContainer, viridis, \ - LinearMapper, Plot -from chaco.tools.api import PanTool, RangeSelection, \ - RangeSelectionOverlay, ZoomTool - -#=============================================================================== +from chaco.api import ( + ArrayPlotData, + ColorBar, + HPlotContainer, + viridis, + LinearMapper, + Plot, +) +from chaco.tools.api import PanTool, RangeSelection, RangeSelectionOverlay, ZoomTool + +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create a scalar field to colormap# Create a scalar field to colormap - xbounds = (-2*pi, 2*pi, 600) - ybounds = (-1.5*pi, 1.5*pi, 300) + xbounds = (-2 * pi, 2 * pi, 600) + ybounds = (-1.5 * pi, 1.5 * pi, 300) xs = linspace(*xbounds) ys = linspace(*ybounds) - x, y = meshgrid(xs,ys) - z = jn(2, x)*y*x + x, y = meshgrid(xs, ys) + z = jn(2, x) * y * x # Create a plot data obect and give it this data pd = ArrayPlotData() @@ -42,11 +47,13 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.img_plot("imagedata", - name="my_plot", - xbounds=xbounds[:2], - ybounds=ybounds[:2], - colormap=viridis) + plot.img_plot( + "imagedata", + name="my_plot", + xbounds=xbounds[:2], + ybounds=ybounds[:2], + colormap=viridis, + ) # Tweak some of the plot properties plot.title = "Selectable Image Plot" @@ -63,60 +70,67 @@ def _create_plot_component(): # Create the colorbar, handing in the appropriate range and colormap colormap = my_plot.color_mapper - colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), - color_mapper=colormap, - plot=my_plot, - orientation='v', - resizable='v', - width=30, - padding=20) + colorbar = ColorBar( + index_mapper=LinearMapper(range=colormap.range), + color_mapper=colormap, + plot=my_plot, + orientation="v", + resizable="v", + width=30, + padding=20, + ) colorbar.padding_top = plot.padding_top colorbar.padding_bottom = plot.padding_bottom # create a range selection for the colorbar range_selection = RangeSelection(component=colorbar) colorbar.tools.append(range_selection) - colorbar.overlays.append(RangeSelectionOverlay(component=colorbar, - border_color="white", - alpha=0.8, - fill_color="lightgray")) + colorbar.overlays.append( + RangeSelectionOverlay( + component=colorbar, border_color="white", alpha=0.8, fill_color="lightgray" + ) + ) # we also want to the range selection to inform the cmap plot of # the selection, so set that up as well range_selection.listeners.append(my_plot) # Create a container to position the plot and the colorbar side-by-side - container = HPlotContainer(use_backbuffer = True) + container = HPlotContainer(use_backbuffer=True) container.add(plot) container.add(colorbar) container.bgcolor = "lightgray" - #my_plot.set_value_selection((-1.3, 6.9)) + # my_plot.set_value_selection((-1.3, 6.9)) return container -#=============================================================================== + + +# =============================================================================== # Attributes to use for the plot view. -size=(800,600) -title="Colormapped Image Plot" +size = (800, 600) +title = "Colormapped Image Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) + def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/demo/basic/cmap_scatter.py b/examples/demo/basic/cmap_scatter.py index 85e662221..920d5039a 100644 --- a/examples/demo/basic/cmap_scatter.py +++ b/examples/demo/basic/cmap_scatter.py @@ -19,22 +19,27 @@ from traitsui.api import Item, VGroup, View, Label # Chaco imports -from chaco.api import ArrayPlotData, ColorBar, \ - ColormappedSelectionOverlay, HPlotContainer, \ - viridis, LinearMapper, Plot -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, \ - RangeSelectionOverlay - -#=============================================================================== +from chaco.api import ( + ArrayPlotData, + ColorBar, + ColormappedSelectionOverlay, + HPlotContainer, + viridis, + LinearMapper, + Plot, +) +from chaco.tools.api import PanTool, ZoomTool, RangeSelection, RangeSelectionOverlay + +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data numpts = 1000 x = sort(random(numpts)) y = random(numpts) - color = exp(-(x**2 + y**2)) + color = exp(-(x ** 2 + y ** 2)) # Create a plot data obect and give it this data pd = ArrayPlotData() @@ -44,16 +49,18 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value", "color"), - type="cmap_scatter", - name="my_plot", - color_mapper=viridis, - marker = "square", - fill_alpha = 0.5, - marker_size = 6, - outline_color = "black", - border_visible = True, - bgcolor = "white") + plot.plot( + ("index", "value", "color"), + type="cmap_scatter", + name="my_plot", + color_mapper=viridis, + marker="square", + fill_alpha=0.5, + marker_size=6, + outline_color="black", + border_visible=True, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Colormapped Scatter Plot with Range-selectable Data Points" @@ -71,8 +78,9 @@ def _create_plot_component(): plot.tools.append(PanTool(plot, constrain_key="shift")) zoom = ZoomTool(component=plot, tool_mode="box", always_on=False) plot.overlays.append(zoom) - selection = ColormappedSelectionOverlay(cmap_renderer, fade_alpha=0.35, - selection_type="mask") + selection = ColormappedSelectionOverlay( + cmap_renderer, fade_alpha=0.35, selection_type="mask" + ) cmap_renderer.overlays.append(selection) # Create the colorbar, handing in the appropriate range and colormap @@ -82,48 +90,54 @@ def _create_plot_component(): colorbar.padding_bottom = plot.padding_bottom # Create a container to position the plot and the colorbar side-by-side - container = HPlotContainer(use_backbuffer = True) + container = HPlotContainer(use_backbuffer=True) container.add(plot) container.add(colorbar) container.bgcolor = "lightgray" return container + def create_colorbar(colormap): - colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), - color_mapper=colormap, - orientation='v', - resizable='v', - width=30, - padding=20) + colorbar = ColorBar( + index_mapper=LinearMapper(range=colormap.range), + color_mapper=colormap, + orientation="v", + resizable="v", + width=30, + padding=20, + ) colorbar.tools.append(RangeSelection(component=colorbar)) - colorbar.overlays.append(RangeSelectionOverlay(component=colorbar, - border_color="white", - alpha=0.8, - fill_color="lightgray")) + colorbar.overlays.append( + RangeSelectionOverlay( + component=colorbar, border_color="white", alpha=0.8, fill_color="lightgray" + ) + ) return colorbar -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(650,650) -title="Colormapped scatter plot" +size = (650, 650) +title = "Colormapped scatter plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - VGroup( - Label('Right-drag on colorbar to select data range'), - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - ), - resizable=True, - title=title - ) + VGroup( + Label("Right-drag on colorbar to select data range"), + Item("plot", editor=ComponentEditor(size=size), show_label=False), + ), + resizable=True, + title=title, + ) + def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/cmap_segment_plot.py b/examples/demo/basic/cmap_segment_plot.py index 8004056da..f56a4bee8 100644 --- a/examples/demo/basic/cmap_segment_plot.py +++ b/examples/demo/basic/cmap_segment_plot.py @@ -19,15 +19,20 @@ from traitsui.api import Item, VGroup, View, Label # Chaco imports -from chaco.api import ArrayPlotData, ColorBar, \ - ColormappedSelectionOverlay, HPlotContainer, \ - viridis, LinearMapper, Plot -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, \ - RangeSelectionOverlay - -#=============================================================================== +from chaco.api import ( + ArrayPlotData, + ColorBar, + ColormappedSelectionOverlay, + HPlotContainer, + viridis, + LinearMapper, + Plot, +) +from chaco.tools.api import PanTool, ZoomTool, RangeSelection, RangeSelectionOverlay + +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -36,7 +41,7 @@ def _create_plot_component(): y1 = random(numpts) x2 = x1 + standard_normal(numpts) * 0.05 y2 = y1 + standard_normal(numpts) * 0.05 - color = exp(-(x1**2 + y2**2)) + color = exp(-(x1 ** 2 + y2 ** 2)) widths = random(numpts) # Create a plot data obect and give it this data @@ -48,15 +53,17 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value", "color", "widths"), - type="cmap_segment", - name="my_plot", - color_mapper=viridis, - border_visible=True, - render_style='cubic', - bgcolor="white", - size_min=0.5, - size_max=5.0) + plot.plot( + ("index", "value", "color", "widths"), + type="cmap_segment", + name="my_plot", + color_mapper=viridis, + border_visible=True, + render_style="cubic", + bgcolor="white", + size_min=0.5, + size_max=5.0, + ) # Tweak some of the plot properties plot.title = "Colormapped Segment Plot with variable widths" @@ -76,51 +83,58 @@ def _create_plot_component(): plot.overlays.append(zoom) # Create the colorbar, handing in the appropriate range and colormap - colorbar = ColorBar(index_mapper=LinearMapper(range=plot.color_mapper.range), - color_mapper=plot.color_mapper, - orientation='v', - resizable='v', - width=30, - padding=20) + colorbar = ColorBar( + index_mapper=LinearMapper(range=plot.color_mapper.range), + color_mapper=plot.color_mapper, + orientation="v", + resizable="v", + width=30, + padding=20, + ) colorbar.plot = cmap_renderer colorbar.padding_top = plot.padding_top colorbar.padding_bottom = plot.padding_bottom # Create a container to position the plot and the colorbar side-by-side - container = HPlotContainer(use_backbuffer = True) + container = HPlotContainer(use_backbuffer=True) container.add(plot) container.add(colorbar) container.bgcolor = "lightgray" return container + def create_colorbar(colormap): - colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), - color_mapper=colormap, - orientation='v', - resizable='v', - width=30, - padding=20) + colorbar = ColorBar( + index_mapper=LinearMapper(range=colormap.range), + color_mapper=colormap, + orientation="v", + resizable="v", + width=30, + padding=20, + ) return colorbar -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(650,650) -title="Colormapped segment plot" +size = (650, 650) +title = "Colormapped segment plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - resizable=True, - title=title - ) + Item("plot", editor=ComponentEditor(size=size), show_label=False), + resizable=True, + title=title, + ) + def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/contour_cmap_plot.py b/examples/demo/basic/contour_cmap_plot.py index 288c730ae..345d8e97f 100644 --- a/examples/demo/basic/contour_cmap_plot.py +++ b/examples/demo/basic/contour_cmap_plot.py @@ -16,24 +16,31 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ArrayPlotData, ColorBar, gmt_drywet, \ - HPlotContainer, LinearMapper, Plot +from chaco.api import ( + ArrayPlotData, + ColorBar, + gmt_drywet, + HPlotContainer, + LinearMapper, + Plot, +) from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create a scalar field to colormap - x_extents = (-2*pi, 2*pi) - y_extents = (-1.5*pi, 1.5*pi) - xs = linspace(-2*pi, 2*pi, 200) - ys = linspace(-1.5*pi, 1.5*pi, 100) - x, y = meshgrid(xs,ys) - zs = sin(log(abs((x+1)**4)+0.05))*cos(y)*1.1*(-y) + \ - sin(((x+1)**2 + y**2)/4) + x_extents = (-2 * pi, 2 * pi) + y_extents = (-1.5 * pi, 1.5 * pi) + xs = linspace(-2 * pi, 2 * pi, 200) + ys = linspace(-1.5 * pi, 1.5 * pi, 100) + x, y = meshgrid(xs, ys) + zs = sin(log(abs((x + 1) ** 4) + 0.05)) * cos(y) * 1.1 * (-y) + sin( + ((x + 1) ** 2 + y ** 2) / 4 + ) # Create a plot data obect and give it this data pd = ArrayPlotData() @@ -41,15 +48,14 @@ def _create_plot_component(): # Create the left plot, a colormap and simple contours lplot = Plot(pd) - lplot.img_plot("imagedata", - name="cm_plot", - xbounds=x_extents, - ybounds=y_extents, - colormap=gmt_drywet) - lplot.contour_plot("imagedata", - type="line", - xbounds=x_extents, - ybounds=y_extents) + lplot.img_plot( + "imagedata", + name="cm_plot", + xbounds=x_extents, + ybounds=y_extents, + colormap=gmt_drywet, + ) + lplot.contour_plot("imagedata", type="line", xbounds=x_extents, ybounds=y_extents) # Tweak some of the plot properties lplot.title = "Colormap and contours" @@ -68,27 +74,31 @@ def _create_plot_component(): # Create the colorbar, handing in the appropriate range and colormap colormap = cm_plot.color_mapper - colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), - color_mapper=colormap, - plot=cm_plot, - orientation='v', - resizable='v', - width=30, - padding=20) + colorbar = ColorBar( + index_mapper=LinearMapper(range=colormap.range), + color_mapper=colormap, + plot=cm_plot, + orientation="v", + resizable="v", + width=30, + padding=20, + ) colorbar.padding_top = lplot.padding_top colorbar.padding_bottom = lplot.padding_bottom # Create the left plot, contours of varying color and width rplot = Plot(pd, range2d=lplot.range2d) - rplot.contour_plot("imagedata", - type="line", - xbounds=x_extents, - ybounds=y_extents, - bgcolor="black", - levels=15, - styles="solid", - widths=list(linspace(4.0, 0.1, 15)), - colors=gmt_drywet) + rplot.contour_plot( + "imagedata", + type="line", + xbounds=x_extents, + ybounds=y_extents, + bgcolor="black", + levels=15, + styles="solid", + widths=list(linspace(4.0, 0.1, 15)), + colors=gmt_drywet, + ) # Add some tools to the plot zoom = ZoomTool(rplot, tool_mode="box", always_on=False) @@ -102,35 +112,43 @@ def _create_plot_component(): rplot.fill_padding = True # Create a container and add our plots - container = HPlotContainer(padding=40, fill_padding=True, - bgcolor = "white", use_backbuffer=True) + container = HPlotContainer( + padding=40, fill_padding=True, bgcolor="white", use_backbuffer=True + ) container.add(colorbar) container.add(lplot) container.add(rplot) return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(950,650) -title="Some contour plots" -bg_color="lightgray" +size = (950, 650) +title = "Some contour plots" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) + def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/contour_plot.py b/examples/demo/basic/contour_plot.py index 69f48532f..e013232ab 100644 --- a/examples/demo/basic/contour_plot.py +++ b/examples/demo/basic/contour_plot.py @@ -22,23 +22,23 @@ from chaco.api import ArrayPlotData, viridis, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create a scalar field to contour # uses a randomly sampled, non-uniform grid - xs = uniform(-2*pi, 2*pi, 600) + xs = uniform(-2 * pi, 2 * pi, 600) xs.sort() - ys = uniform(-1.5*pi, 1.5*pi, 300) + ys = uniform(-1.5 * pi, 1.5 * pi, 300) ys.sort() - x, y = meshgrid(xs,ys) - z = tanh(x*y/6)*cosh(exp(-y**2)*x/3) - z = x*y + x, y = meshgrid(xs, ys) + z = tanh(x * y / 6) * cosh(exp(-(y ** 2)) * x / 3) + z = x * y # mask out a region with nan values - mask = ((abs(x-5) <= 1) & (abs(y-2) <= 2)) + mask = (abs(x - 5) <= 1) & (abs(y - 2) <= 2) z[mask] = nan # Create a plot data object and give it this data @@ -47,17 +47,10 @@ def _create_plot_component(): # Create a contour polygon plot of the data plot = Plot(pd, default_origin="bottom left") - plot.contour_plot("imagedata", - type="poly", - poly_cmap=viridis, - xbounds=x, - ybounds=y) + plot.contour_plot("imagedata", type="poly", poly_cmap=viridis, xbounds=x, ybounds=y) # Create a contour line plot for the data, too - plot.contour_plot("imagedata", - type="line", - xbounds=x, - ybounds=y) + plot.contour_plot("imagedata", type="line", xbounds=x, ybounds=y) # Tweak some of the plot properties plot.title = "My First Contour Plot" @@ -71,27 +64,30 @@ def _create_plot_component(): plot.overlays.append(zoom) return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (800, 600) title = "Basic Contour Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/discrete_cmap_image_plot.py b/examples/demo/basic/discrete_cmap_image_plot.py index 31cfcc91b..25db780e2 100644 --- a/examples/demo/basic/discrete_cmap_image_plot.py +++ b/examples/demo/basic/discrete_cmap_image_plot.py @@ -21,15 +21,15 @@ from chaco.api import ArrayPlotData, viridis, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create a scalar field to colormap xs = linspace(0, 10, 600) ys = linspace(0, 5, 600) - x, y = meshgrid(xs,ys) - z = (exp(-(x**2+y**2)/100)*7).round() + x, y = meshgrid(xs, ys) + z = (exp(-(x ** 2 + y ** 2) / 100) * 7).round() # Create a plot data object and give it this data pd = ArrayPlotData() @@ -37,10 +37,9 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - img_plot = plot.img_plot("imagedata", - xbounds=(0, 10), - ybounds=(0, 5), - colormap=viridis)[0] + img_plot = plot.img_plot( + "imagedata", xbounds=(0, 10), ybounds=(0, 5), colormap=viridis + )[0] # Tweak some of the plot properties plot.title = "My First Image Plot" @@ -53,26 +52,29 @@ def _create_plot_component(): return plot -#=============================================================================== +# =============================================================================== # Attributes to use for the plot view. -size=(800,600) -title="Basic Colormapped Image Plot" +size = (800, 600) +title = "Basic Colormapped Image Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) + def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/discrete_cmap_scatter.py b/examples/demo/basic/discrete_cmap_scatter.py index 96042a2a1..274d35e06 100644 --- a/examples/demo/basic/discrete_cmap_scatter.py +++ b/examples/demo/basic/discrete_cmap_scatter.py @@ -19,16 +19,21 @@ from traitsui.api import Item, VGroup, View, Label # Chaco imports -from chaco.api import ArrayPlotData, ColorBar, \ - ColormappedSelectionOverlay, HPlotContainer, \ - LabelAxis, LinearMapper, Plot +from chaco.api import ( + ArrayPlotData, + ColorBar, + ColormappedSelectionOverlay, + HPlotContainer, + LabelAxis, + LinearMapper, + Plot, +) from chaco.default_colormaps import accent -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, \ - RangeSelectionOverlay +from chaco.tools.api import PanTool, ZoomTool, RangeSelection, RangeSelectionOverlay -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -45,16 +50,18 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value", "color"), - type="cmap_scatter", - name="my_plot", - color_mapper=accent, - marker = "square", - fill_alpha = 0.5, - marker_size = 6, - outline_color = "black", - border_visible = True, - bgcolor = "white") + plot.plot( + ("index", "value", "color"), + type="cmap_scatter", + name="my_plot", + color_mapper=accent, + marker="square", + fill_alpha=0.5, + marker_size=6, + outline_color="black", + border_visible=True, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Colormapped Scatter Plot with Range-selectable Data Points" @@ -72,8 +79,9 @@ def _create_plot_component(): plot.tools.append(PanTool(plot, constrain_key="shift")) zoom = ZoomTool(component=plot, tool_mode="box", always_on=False) plot.overlays.append(zoom) - selection = ColormappedSelectionOverlay(cmap_renderer, fade_alpha=0.35, - selection_type="mask") + selection = ColormappedSelectionOverlay( + cmap_renderer, fade_alpha=0.35, selection_type="mask" + ) cmap_renderer.overlays.append(selection) # Create the colorbar, handing in the appropriate range and colormap @@ -83,50 +91,56 @@ def _create_plot_component(): colorbar.padding_bottom = plot.padding_bottom # Create a container to position the plot and the colorbar side-by-side - container = HPlotContainer(use_backbuffer = True) + container = HPlotContainer(use_backbuffer=True) container.add(plot) container.add(colorbar) container.bgcolor = "lightgray" return container + def create_colorbar(colormap): - colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), - color_mapper=colormap, - orientation='v', - resizable='v', - width=30, - padding=20) + colorbar = ColorBar( + index_mapper=LinearMapper(range=colormap.range), + color_mapper=colormap, + orientation="v", + resizable="v", + width=30, + padding=20, + ) colorbar.grid_visible = False colorbar._axis.tick_visible = False colorbar.tools.append(RangeSelection(component=colorbar)) - colorbar.overlays.append(RangeSelectionOverlay(component=colorbar, - border_color="white", - alpha=0.8, - fill_color="lightgray")) + colorbar.overlays.append( + RangeSelectionOverlay( + component=colorbar, border_color="white", alpha=0.8, fill_color="lightgray" + ) + ) return colorbar -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(650,650) -title="Discrete colormapped scatter plot" +size = (650, 650) +title = "Discrete colormapped scatter plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - VGroup( - Label('Right-drag on colorbar to select data range'), - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - ), - resizable=True, - title=title - ) + VGroup( + Label("Right-drag on colorbar to select data range"), + Item("plot", editor=ComponentEditor(size=size), show_label=False), + ), + resizable=True, + title=title, + ) + def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/draw_layers.py b/examples/demo/basic/draw_layers.py index 4fbb68c7e..9ad376d0b 100644 --- a/examples/demo/basic/draw_layers.py +++ b/examples/demo/basic/draw_layers.py @@ -19,13 +19,13 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): x = linspace(-2.0, 10.0, 100) - pd = ArrayPlotData(x = x) + pd = ArrayPlotData(x=x) # Create some line plots of some of the data plot = Plot(pd, padding=50, border_visible=True, overlay_border=True) @@ -46,7 +46,7 @@ def _create_plot_component(): # Draw bessels for i in range(3): y_name = "bessel" + str(i) - pd.set_data(y_name, jn(i,x)) + pd.set_data(y_name, jn(i, x)) renderer = plot.plot(("x", y_name), color="green", name=y_name, line_width=2)[0] renderer.draw_layer = "bessel" renderer.unified_draw = True @@ -54,7 +54,7 @@ def _create_plot_component(): # Draw sines for i in range(3): y_name = "sine" + str(i) - pd.set_data(y_name, sin(x * (i+1) / 1.5)) + pd.set_data(y_name, sin(x * (i + 1) / 1.5)) renderer = plot.plot(("x", y_name), color="red", name=y_name, line_width=2)[0] renderer.draw_layer = "sine" renderer.unified_draw = True @@ -66,27 +66,30 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Draw order demonstration" +size = (900, 500) +title = "Draw order demonstration" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/grid_container.py b/examples/demo/basic/grid_container.py index a056fbf21..ca57d0cd5 100644 --- a/examples/demo/basic/grid_container.py +++ b/examples/demo/basic/grid_container.py @@ -32,27 +32,35 @@ from chaco.tools.api import PanTool, ZoomTool - -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create a GridContainer to hold all of our plots: 2 rows, 3 columns: - container = GridContainer(padding=40, fill_padding=True, - bgcolor="lightgray", use_backbuffer=True, - shape=(2,3), spacing=(20,20)) + container = GridContainer( + padding=40, + fill_padding=True, + bgcolor="lightgray", + use_backbuffer=True, + shape=(2, 3), + spacing=(20, 20), + ) # Create the initial series of data x = linspace(-5, 15.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) # Plot some bessel functions and add the plots to our container for i in range(6): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) plot = Plot(pd) - plot.plot(("index", "y" + str(i)), - color=tuple(COLOR_PALETTE[i]), line_width=2.0, - bgcolor = "white", border_visible=True) + plot.plot( + ("index", "y" + str(i)), + color=tuple(COLOR_PALETTE[i]), + line_width=2.0, + bgcolor="white", + border_visible=True, + ) # Tweak some of the plot properties plot.border_width = 1 @@ -72,49 +80,52 @@ def _create_plot_component(): ul_plot = container.components[0] ul_plot.resizable = "v" ul_plot.width = 200 - ul_plot.overlays.append(PlotLabel("Not horizontally resizable", - component=ul_plot)) + ul_plot.overlays.append(PlotLabel("Not horizontally resizable", component=ul_plot)) # Set the bottom center plot to have a fixed width and height. # This also constrains the height of the bottom row and the width of # the middle column. cplot = container.components[4] cplot.resizable = "" - cplot.bounds = [400,400] + cplot.bounds = [400, 400] cplot.overlays.append(PlotLabel("Not resizable", component=cplot)) container.padding_top = 50 container.overlays.append( - PlotLabel('Resize the window - some plots resize, others cannot ' - '(see source code)', - component=container, - font = "swiss 16", - overlay_position = "top")) - + PlotLabel( + "Resize the window - some plots resize, others cannot " "(see source code)", + component=container, + font="swiss 16", + overlay_position="top", + ) + ) + return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(1000,800) -title="Resizable Grid Container" +size = (1000, 800) +title = "Resizable Grid Container" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) - traits_view = \ - View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical" - ), - resizable=True, title=title ) + traits_view = View( + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/grid_container_aspect_ratio.py b/examples/demo/basic/grid_container_aspect_ratio.py index da7bd1b4f..2776e0a5c 100644 --- a/examples/demo/basic/grid_container_aspect_ratio.py +++ b/examples/demo/basic/grid_container_aspect_ratio.py @@ -21,26 +21,35 @@ from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create a GridContainer to hold all of our plots - container = GridContainer(padding=20, fill_padding=True, - bgcolor="lightgray", use_backbuffer=True, - shape=(3,3), spacing=(12,12)) + container = GridContainer( + padding=20, + fill_padding=True, + bgcolor="lightgray", + use_backbuffer=True, + shape=(3, 3), + spacing=(12, 12), + ) # Create the initial series of data x = linspace(-5, 15.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) # Plot some bessel functions and add the plots to our container for i in range(9): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) plot = Plot(pd) - plot.plot(("index", "y" + str(i)), - color=tuple(COLOR_PALETTE[i]), line_width=2.0, - bgcolor = "white", border_visible=True) + plot.plot( + ("index", "y" + str(i)), + color=tuple(COLOR_PALETTE[i]), + line_width=2.0, + bgcolor="white", + border_visible=True, + ) # Tweak some of the plot properties plot.border_width = 1 @@ -48,8 +57,8 @@ def _create_plot_component(): # Set each plot's aspect ratio based on its position in the # 3x3 grid of plots. - n,m = divmod(i, 3) - plot.aspect_ratio = float(n+1) / (m+1) + n, m = divmod(i, 3) + plot.aspect_ratio = float(n + 1) / (m + 1) # Attach some tools to the plot plot.tools.append(PanTool(plot)) @@ -60,26 +69,30 @@ def _create_plot_component(): container.add(plot) return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(1000,800) -title="Grid Container with Fixed Aspect ratios" +size = (1000, 800) +title = "Grid Container with Fixed Aspect ratios" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) + def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/hittest_tool.py b/examples/demo/basic/hittest_tool.py index 58be41dd1..d2bd08cf7 100644 --- a/examples/demo/basic/hittest_tool.py +++ b/examples/demo/basic/hittest_tool.py @@ -3,61 +3,64 @@ Draws a random x-y lineplot and makes a tool which shows the closet point on the lineplot to the mouse position. """ -#Major library imports +# Major library imports from numpy.random import random_sample from numpy import arange -#Enthought library imports +# Enthought library imports from enable.api import Component, ComponentEditor, BaseTool from traits.api import HasTraits, Instance, Any, Int from traitsui.api import View, UItem -#Chaco imports +# Chaco imports from chaco.api import Plot, ArrayPlotData, AbstractOverlay, ArrayDataSource -#=============================================================================== +# =============================================================================== # # Create the Chaco custom tool -#=============================================================================== +# =============================================================================== class HittestTool(BaseTool, AbstractOverlay): - '''This tool uses LinePlot.hittest() to get the closest point + """This tool uses LinePlot.hittest() to get the closest point on the line to the mouse position and to draw it to the screen. Also implements an Overlay in order to draw the point. - ''' + """ + # A reference to the lineplot the tool acts on line_plot = Any() - + # Whether to draw the overlay - visible=True + visible = True # The point to draw on the plot, or None if no point pt = Any() - # How many pixels away we may be from the line in order to do + # How many pixels away we may be from the line in order to do threshold = Int(40) def normal_mouse_move(self, event): # Compute the nearest point and draw it whenever the mouse moves - x,y = event.x, event.y + x, y = event.x, event.y if self.line_plot.orientation == "h": - x,y = self.component.map_data((x,y)) + x, y = self.component.map_data((x, y)) else: - x,y = self.component.map_data((y,x)) + x, y = self.component.map_data((y, x)) - x,y = self.line_plot.map_screen((x,y)) - self.pt = self.line_plot.hittest((x,y), threshold=self.threshold) + x, y = self.line_plot.map_screen((x, y)) + self.pt = self.line_plot.hittest((x, y), threshold=self.threshold) self.request_redraw() def overlay(self, plot, gc, view_bounds=None, mode="normal"): # If we have a point, draw it to the screen as a small square if self.pt is not None: - x,y = plot.map_screen(self.pt) - gc.draw_rect((int(x)-2, int(y)-2, 4, 4)) + x, y = plot.map_screen(self.pt) + gc.draw_rect((int(x) - 2, int(y) - 2, 4, 4)) + -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== + def _create_plot_component(): # make 10 random points @@ -69,7 +72,7 @@ def _create_plot_component(): pd = ArrayPlotData(x=x, y=y) plot = Plot(pd) - plot.orientation = 'v' + plot.orientation = "v" line_plot = plot.plot(("x", "y"))[0] # Add the tool to the plot both as a tool and as an overlay @@ -79,28 +82,28 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -#=============================================================================== -size = (800,600) -title="LinePlot Hittest Demo" +# =============================================================================== +size = (800, 600) +title = "LinePlot Hittest Demo" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - UItem("plot", editor=ComponentEditor(size=size)), - resizable=True, - title=title + UItem("plot", editor=ComponentEditor(size=size)), resizable=True, title=title ) def _plot_default(self): return _create_plot_component() + demo = Demo() -if __name__ == '__main__': +if __name__ == "__main__": demo.configure_traits() diff --git a/examples/demo/basic/horizon_plot.py b/examples/demo/basic/horizon_plot.py index 6198c52bc..dcd2c4efd 100644 --- a/examples/demo/basic/horizon_plot.py +++ b/examples/demo/basic/horizon_plot.py @@ -13,129 +13,164 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ArrayDataSource, LinearMapper, DataRange1D, \ - HPlotContainer, OverlayPlotContainer, PlotGrid, PlotAxis, \ - FilledLinePlot, BandedMapper, HorizonPlot, \ - ColorBar, RdBu as cmap +from chaco.api import ( + ArrayDataSource, + LinearMapper, + DataRange1D, + HPlotContainer, + OverlayPlotContainer, + PlotGrid, + PlotAxis, + FilledLinePlot, + BandedMapper, + HorizonPlot, + ColorBar, + RdBu as cmap, +) from chaco.tools.api import PanTool from chaco.scales.api import CalendarScaleSystem from chaco.scales_tick_generator import ScalesTickGenerator + def create_dates(numpoints, units="days"): - """ Returns **numpoints** number of dates that evenly bracket the current + """Returns **numpoints** number of dates that evenly bracket the current date and time. **units** should be one of "weeks", "days", "hours" "minutes", or "seconds". """ - units_map = { "weeks" : 7*24*3600, - "days" : 24*3600, - "hours" : 3600, - "minutes" : 60, - "seconds" : 1 } + units_map = { + "weeks": 7 * 24 * 3600, + "days": 24 * 3600, + "hours": 3600, + "minutes": 60, + "seconds": 1, + } now = time.time() dt = units_map[units] - dates = linspace(now, now+numpoints*dt, numpoints) + dates = linspace(now, now + numpoints * dt, numpoints) return dates -#=============================================================================== + +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_components(): # Create the data and datasource objects # In order for the date axis to work, the index data points need to # be in units of seconds since the epoch. This is because we are using # the CalendarScaleSystem, whose formatters interpret the numerical values # as seconds since the epoch. - high = 1. + high = 1.0 numpoints = 5000 random.seed(1000) index = create_dates(numpoints) - price = 100*cumprod(random.lognormal(0.0, 0.04, size=numpoints)) - changes = price/price[0] - 1. + price = 100 * cumprod(random.lognormal(0.0, 0.04, size=numpoints)) + changes = price / price[0] - 1.0 index_ds = ArrayDataSource(index) value_ds = ArrayDataSource(changes, sort_order="none") value_range = DataRange1D(value_ds, low=-high, high=high) - + index_mapper = LinearMapper(range=DataRange1D(index_ds), stretch_data=False) - + horizon = HorizonPlot( - bands = 4, - index = index_ds, - value = value_ds, - index_mapper = index_mapper, - value_mapper = BandedMapper(range=DataRange1D(low=0, high=high)), - color_mapper = cmap(range=value_range), - ) + bands=4, + index=index_ds, + value=value_ds, + index_mapper=index_mapper, + value_mapper=BandedMapper(range=DataRange1D(low=0, high=high)), + color_mapper=cmap(range=value_range), + ) horizon.tools.append(PanTool(horizon, constrain=True, constrain_direction="x")) - axis = PlotAxis(mapper = horizon.value_mapper, component=horizon, orientation="left", - tick_label_position="outside") + axis = PlotAxis( + mapper=horizon.value_mapper, + component=horizon, + orientation="left", + tick_label_position="outside", + ) horizon.overlays.append(axis) - bottom_axis = PlotAxis(horizon, orientation="bottom", - tick_generator=ScalesTickGenerator(scale=CalendarScaleSystem())) + bottom_axis = PlotAxis( + horizon, + orientation="bottom", + tick_generator=ScalesTickGenerator(scale=CalendarScaleSystem()), + ) horizon.overlays.append(bottom_axis) - filled = FilledLinePlot( - index = index_ds, - value = value_ds, - index_mapper = index_mapper, - value_mapper = LinearMapper(range=value_range, stretch_data=False), - fill_color = (0.81960784, 0.89803922, 0.94117647), - edge_color = 'transparent', - ) + index=index_ds, + value=value_ds, + index_mapper=index_mapper, + value_mapper=LinearMapper(range=value_range, stretch_data=False), + fill_color=(0.81960784, 0.89803922, 0.94117647), + edge_color="transparent", + ) filled.tools.append(PanTool(filled, constrain=True, constrain_direction="x")) - axis = PlotAxis(mapper = filled.value_mapper, component=filled, orientation="left", - tick_label_position="outside") + axis = PlotAxis( + mapper=filled.value_mapper, + component=filled, + orientation="left", + tick_label_position="outside", + ) filled.overlays.append(axis) - grid = PlotGrid(mapper = filled.value_mapper, component=filled, orientation='horizontal', - line_color='lightgray', line_style="dot",) + grid = PlotGrid( + mapper=filled.value_mapper, + component=filled, + orientation="horizontal", + line_color="lightgray", + line_style="dot", + ) filled.underlays.append(grid) colormap = horizon.color_mapper - colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), - color_mapper=colormap, - orientation='v', - resizable='v', - width=20, - padding=20) - + colorbar = ColorBar( + index_mapper=LinearMapper(range=colormap.range), + color_mapper=colormap, + orientation="v", + resizable="v", + width=20, + padding=20, + ) + padding = (40, 20, 0, 0) over1 = HPlotContainer(use_backbuffer=True, padding=padding, padding_top=20) over1.add(filled) over1.add(colorbar) - over2 = OverlayPlotContainer(padding = padding, padding_bottom=40) + over2 = OverlayPlotContainer(padding=padding, padding_bottom=40) over2.add(horizon) return over1, over2 -filled_size=(800,220) -horizon_size=(800,70) -title="Horizon plot example" +filled_size = (800, 220) +horizon_size = (800, 70) +title = "Horizon plot example" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): filled = Instance(Component) horizon = Instance(Component) traits_view = View( - Group( - Item('filled', editor=ComponentEditor(size=filled_size), - show_label=False), - Item('horizon', editor=ComponentEditor(size=horizon_size), - show_label=False), - orientation = "vertical"), - resizable=False, title=title, - width=filled_size[0], height=filled_size[1]+horizon_size[1], - ) + Group( + Item("filled", editor=ComponentEditor(size=filled_size), show_label=False), + Item( + "horizon", editor=ComponentEditor(size=horizon_size), show_label=False + ), + orientation="vertical", + ), + resizable=False, + title=title, + width=filled_size[0], + height=filled_size[1] + horizon_size[1], + ) + demo = Demo() diff --git a/examples/demo/basic/image_from_file.py b/examples/demo/basic/image_from_file.py index 9eed76270..8e46f4911 100644 --- a/examples/demo/basic/image_from_file.py +++ b/examples/demo/basic/image_from_file.py @@ -18,19 +18,18 @@ from traits.util.resource import find_resource from traits.api import File, HasTraits, Instance from traitsui.api import Handler, Item, View -from traitsui.menu \ - import Action, CloseAction, Menu, MenuBar, OKCancelButtons, Separator +from traitsui.menu import Action, CloseAction, Menu, MenuBar, OKCancelButtons, Separator # Chaco imports -from chaco.api \ - import ArrayPlotData, ImageData, Plot, PlotGraphicsContext +from chaco.api import ArrayPlotData, ImageData, Plot, PlotGraphicsContext from enable.component_editor import ComponentEditor from chaco.tools.api import PanTool, ZoomTool -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # Class 'DemoView' -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- + class DemoView(HasTraits): @@ -42,43 +41,42 @@ class DemoView(HasTraits): # A Plot object to plot our image data plot = Instance(Plot) - ### Private Traits ######################################################### # File name to load image from - resource_path = os.path.join('examples','basic','capitol.jpg') - alt_path = 'capitol.jpg' - image_path = find_resource('Chaco', resource_path, alt_path=alt_path, - return_path=True) + resource_path = os.path.join("examples", "basic", "capitol.jpg") + alt_path = "capitol.jpg" + image_path = find_resource( + "Chaco", resource_path, alt_path=alt_path, return_path=True + ) _load_file = File(image_path) # File name to save image to _save_file = File - ### Traits Views ########################################################### # This view is for a file dialog to select the 'load' filename load_file_view = View( - Item('_load_file'), + Item("_load_file"), buttons=OKCancelButtons, - kind='livemodal', # NB must use livemodal, plot objects don't copy well + kind="livemodal", # NB must use livemodal, plot objects don't copy well width=400, resizable=True, ) # This view is for a file dialog to select the 'save' filename save_file_view = View( - Item('_save_file'), + Item("_save_file"), buttons=OKCancelButtons, - kind='livemodal', # NB must use livemodal, plot objects don't copy well + kind="livemodal", # NB must use livemodal, plot objects don't copy well width=400, resizable=True, ) - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Public 'DemoView' interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def __init__(self, *args, **kwargs): super(DemoView, self).__init__(*args, **kwargs) @@ -99,34 +97,35 @@ def __init__(self, *args, **kwargs): self.plot.img_plot("imagedata") def default_traits_view(self): - """ Returns the default view to use for this class. - """ + """Returns the default view to use for this class.""" # NOTE: I moved the view to this method so we can declare a handler # for the view. Alternatively, we could move the DemoController class # to the top and declare view=Instance(HasTraits) instead. traits_view = View( - Item('plot', - editor=ComponentEditor(), - show_label=False, + Item( + "plot", + editor=ComponentEditor(), + show_label=False, ), menubar=MenuBar( - Menu(Action(name="Save Plot", action="save"), # see Controller for - Action(name="Load Plot", action="load"), # these callbacks - Separator(), - CloseAction, - name="File", + Menu( + Action(name="Save Plot", action="save"), # see Controller for + Action(name="Load Plot", action="load"), # these callbacks + Separator(), + CloseAction, + name="File", ), ), width=600, height=600, resizable=True, - handler=DemoController + handler=DemoController, ) return traits_view - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Private 'DemoView' interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def _save(self): # Create a graphics context of the right size @@ -152,22 +151,22 @@ def _load(self): self.plot.request_redraw() - -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # Class 'DemoController' -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- + class DemoController(Handler): # The HasTraits object we are a controller for view = Instance(DemoView) - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Public 'DemoController' interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def init(self, info): - """ Initializes the controls of a user interface. + """Initializes the controls of a user interface. Overridden here to assign the 'view' trait. """ self.view = info.object @@ -176,7 +175,7 @@ def save(self, ui_info): """ Callback for the 'Save Image' menu option. """ - ui = self.view.edit_traits(view='save_file_view') + ui = self.view.edit_traits(view="save_file_view") if ui.result == True: self.view._save() @@ -184,28 +183,29 @@ def load(self, ui_info): """ Callback for the 'Load Image' menu option. """ - ui = self.view.edit_traits(view='load_file_view') + ui = self.view.edit_traits(view="load_file_view") if ui.result == True: self.view._load() -#=============================================================================== +# =============================================================================== # # popup object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== # Note: we declare a 'popup' rather than a 'demo' since the menubar doesn't seem # to show up in a 'panel' mode. popup = DemoView() -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # Function 'main' -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- + def main(argv=None): view = DemoView() view.configure_traits() -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- if __name__ == "__main__": sys.exit(main()) diff --git a/examples/demo/basic/image_inspector.py b/examples/demo/basic/image_inspector.py index bca1ed3c3..8f4d4f587 100644 --- a/examples/demo/basic/image_inspector.py +++ b/examples/demo/basic/image_inspector.py @@ -24,19 +24,18 @@ # Chaco imports from chaco.api import ArrayPlotData, viridis, Plot from chaco.tools.api import PanTool, ZoomTool -from chaco.tools.image_inspector_tool import ImageInspectorTool, \ - ImageInspectorOverlay +from chaco.tools.image_inspector_tool import ImageInspectorTool, ImageInspectorOverlay -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== -def _create_plot_component():# Create a scalar field to colormap - xbounds = (-2*pi, 2*pi, 600) - ybounds = (-1.5*pi, 1.5*pi, 300) +# =============================================================================== +def _create_plot_component(): # Create a scalar field to colormap + xbounds = (-2 * pi, 2 * pi, 600) + ybounds = (-1.5 * pi, 1.5 * pi, 300) xs = linspace(*xbounds) ys = linspace(*ybounds) - x, y = meshgrid(xs,ys) - z = sin(x)*y + x, y = meshgrid(xs, ys) + z = sin(x) * y # Create a plot data obect and give it this data pd = ArrayPlotData() @@ -44,10 +43,9 @@ def _create_plot_component():# Create a scalar field to colormap # Create the plot plot = Plot(pd) - img_plot = plot.img_plot("imagedata", - xbounds = xbounds[:2], - ybounds = ybounds[:2], - colormap=viridis)[0] + img_plot = plot.img_plot( + "imagedata", xbounds=xbounds[:2], ybounds=ybounds[:2], colormap=viridis + )[0] # Tweak some of the plot properties plot.title = "My First Image Plot" @@ -59,33 +57,40 @@ def _create_plot_component():# Create a scalar field to colormap plot.overlays.append(zoom) imgtool = ImageInspectorTool(component=img_plot) img_plot.tools.append(imgtool) - overlay = ImageInspectorOverlay(component=img_plot, image_inspector=imgtool, - bgcolor="white", border_visible=True) + overlay = ImageInspectorOverlay( + component=img_plot, + image_inspector=imgtool, + bgcolor="white", + border_visible=True, + ) img_plot.overlays.append(overlay) return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (800, 600) -title="Inspecting a Colormapped Image Plot" +title = "Inspecting a Colormapped Image Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/image_lasso.py b/examples/demo/basic/image_lasso.py index 32e416918..5ae3bfad4 100644 --- a/examples/demo/basic/image_lasso.py +++ b/examples/demo/basic/image_lasso.py @@ -19,9 +19,10 @@ from chaco.api import ArrayPlotData, viridis, Plot, LassoOverlay from chaco.tools.api import LassoSelection, LassoSelection -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== + def lasso_updated(event): lasso_tool = event.object @@ -42,13 +43,13 @@ def lasso_updated(event): print("\t", lasso_tool.plot.map_index((x, y))) -def _create_plot_component():# Create a scalar field to colormap - xbounds = (-2*pi, 2*pi, 600) - ybounds = (-1.5*pi, 1.5*pi, 300) +def _create_plot_component(): # Create a scalar field to colormap + xbounds = (-2 * pi, 2 * pi, 600) + ybounds = (-1.5 * pi, 1.5 * pi, 300) xs = linspace(*xbounds) ys = linspace(*ybounds) - x, y = meshgrid(xs,ys) - z = sin(x)*y + x, y = meshgrid(xs, ys) + z = sin(x) * y # Create a plot data obect and give it this data pd = ArrayPlotData() @@ -56,10 +57,9 @@ def _create_plot_component():# Create a scalar field to colormap # Create the plot plot = Plot(pd) - img_plot = plot.img_plot("imagedata", - xbounds=xbounds[:2], - ybounds=ybounds[:2], - colormap=viridis)[0] + img_plot = plot.img_plot( + "imagedata", xbounds=xbounds[:2], ybounds=ybounds[:2], colormap=viridis + )[0] # Tweak some of the plot properties plot.title = "Image Plot with Lasso" @@ -67,32 +67,35 @@ def _create_plot_component():# Create a scalar field to colormap lasso_selection = LassoSelection(component=img_plot) lasso_selection.observe(lasso_updated, "disjoint_selections") - lasso_overlay = LassoOverlay(lasso_selection = lasso_selection, component=img_plot) + lasso_overlay = LassoOverlay(lasso_selection=lasso_selection, component=img_plot) img_plot.tools.append(lasso_selection) img_plot.overlays.append(lasso_overlay) return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (800, 600) -title="Image Plot with Lasso" +title = "Image Plot with Lasso" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/image_plot.py b/examples/demo/basic/image_plot.py index 02323e0a2..f27e413d9 100644 --- a/examples/demo/basic/image_plot.py +++ b/examples/demo/basic/image_plot.py @@ -20,20 +20,19 @@ # Chaco imports from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -from chaco.tools.image_inspector_tool import ImageInspectorTool, \ - ImageInspectorOverlay +from chaco.tools.image_inspector_tool import ImageInspectorTool, ImageInspectorOverlay -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some RGBA image data - image = zeros((200,400,4), dtype=uint8) - image[:,0:40,0] += 255 # Vertical red stripe - image[0:25,:,1] += 255 # Horizontal green stripe; also yellow square - image[-80:,-160:,2] += 255 # Blue square - image[:,:,3] = 255 + image = zeros((200, 400, 4), dtype=uint8) + image[:, 0:40, 0] += 255 # Vertical red stripe + image[0:25, :, 1] += 255 # Horizontal green stripe; also yellow square + image[-80:, -160:, 2] += 255 # Blue square + image[:, :, 3] = 255 # Create a plot data obect and give it this data pd = ArrayPlotData() @@ -49,38 +48,44 @@ def _create_plot_component(): # Attach some tools to the plot plot.tools.append(PanTool(plot, constrain_key="shift")) - plot.overlays.append(ZoomTool(component=plot, - tool_mode="box", always_on=False)) + plot.overlays.append(ZoomTool(component=plot, tool_mode="box", always_on=False)) imgtool = ImageInspectorTool(img_plot) img_plot.tools.append(imgtool) - plot.overlays.append(ImageInspectorOverlay(component=img_plot, - image_inspector=imgtool)) + plot.overlays.append( + ImageInspectorOverlay(component=img_plot, image_inspector=imgtool) + ) return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (600, 600) -title="Simple image plot" -bg_color="lightgray" +title = "Simple image plot" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/inset_plot.py b/examples/demo/basic/inset_plot.py index 826975a50..e8661e112 100644 --- a/examples/demo/basic/inset_plot.py +++ b/examples/demo/basic/inset_plot.py @@ -19,15 +19,15 @@ from chaco.api import ArrayPlotData, OverlayPlotContainer, Plot from chaco.tools.api import PanTool, ZoomTool, MoveTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some x-y data series to plot x = linspace(-2.0, 10.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) for i in range(5): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) # Create some line plots of some of the data plot1 = Plot(pd) @@ -46,10 +46,10 @@ def _create_plot_component(): # Create a second scatter plot of one of the datasets, linking its # range to the first plot plot2 = Plot(pd, range2d=plot1.range2d, padding=50) - plot2.plot(('index', 'y3'), type="scatter", color="blue", marker="circle") + plot2.plot(("index", "y3"), type="scatter", color="blue", marker="circle") plot2.resizable = "" plot2.bounds = [250, 250] - plot2.position = [550,150] + plot2.position = [550, 150] plot2.bgcolor = "white" plot2.border_visible = True plot2.unified_draw = True @@ -65,27 +65,30 @@ def _create_plot_component(): container.add(plot2) return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Inset plots" +size = (900, 500) +title = "Inset plots" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/line_drawing.py b/examples/demo/basic/line_drawing.py index 8dce0d823..7c8882aae 100644 --- a/examples/demo/basic/line_drawing.py +++ b/examples/demo/basic/line_drawing.py @@ -43,9 +43,10 @@ def _finalize_selection(self): for point in self.points: print("\t", point) -#=============================================================================== + +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -60,15 +61,17 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value"), - type="scatter", - name="my_plot", - marker="square", - index_sort="ascending", - color="lightblue", - outline_color="none", - marker_size=3, - bgcolor="white") + plot.plot( + ("index", "value"), + type="scatter", + name="my_plot", + marker="square", + index_sort="ascending", + color="lightblue", + outline_color="none", + marker_size=3, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Click to add points, press Enter to finalize selection" @@ -83,29 +86,35 @@ def _create_plot_component(): plot.overlays.append(MyLineDrawer(plot)) return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(650,650) -title="Line drawing example" -bg_color="lightgray" +size = (650, 650) +title = "Line drawing example" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/line_plot1.py b/examples/demo/basic/line_plot1.py index a00cc9c36..d2d7af6d9 100644 --- a/examples/demo/basic/line_plot1.py +++ b/examples/demo/basic/line_plot1.py @@ -22,16 +22,16 @@ from chaco.api import ArrayPlotData, HPlotContainer, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some x-y data series to plot x = linspace(-2.0, 10.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) for i in range(5): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) # Create some line plots of some of the data plot1 = Plot(pd, title="Line Plot", padding=60, border_visible=True) @@ -47,9 +47,10 @@ def _create_plot_component(): # Create a second scatter plot of one of the datasets, linking its # range to the first plot - plot2 = Plot(pd, range2d=plot1.range2d, title="Scatter plot", padding=60, - border_visible=True) - plot2.plot(('index', 'y3'), type="scatter", color="blue", marker="circle") + plot2 = Plot( + pd, range2d=plot1.range2d, title="Scatter plot", padding=60, border_visible=True + ) + plot2.plot(("index", "y3"), type="scatter", color="blue", marker="circle") # Configure the vertical axis: plot2.value_axis.title = "J3" @@ -63,27 +64,30 @@ def _create_plot_component(): return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Basic x-y plots" +size = (900, 500) +title = "Basic x-y plots" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/line_plot_hold.py b/examples/demo/basic/line_plot_hold.py index d5a7c6c31..3b8cef479 100644 --- a/examples/demo/basic/line_plot_hold.py +++ b/examples/demo/basic/line_plot_hold.py @@ -16,23 +16,30 @@ from chaco.api import ArrayPlotData, HPlotContainer, Plot from chaco.tools.api import PanTool, ZoomTool + def attach_tools(plot): plot.tools.append(PanTool(plot)) zoom = ZoomTool(component=plot, tool_mode="box", always_on=False) plot.overlays.append(zoom) -#=============================================================================== + +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some x-y data series to plot x = linspace(-2.0, 10.0, 40) - pd = ArrayPlotData(index = x, y0=jn(0,x)) + pd = ArrayPlotData(index=x, y0=jn(0, x)) # Create some line plots of some of the data - plot1 = Plot(pd, title="render_style = hold", padding=50, border_visible=True, - overlay_border = True) + plot1 = Plot( + pd, + title="render_style = hold", + padding=50, + border_visible=True, + overlay_border=True, + ) plot1.legend.visible = True lineplot = plot1.plot(("index", "y0"), name="j_0", color="red", render_style="hold") @@ -41,9 +48,15 @@ def _create_plot_component(): # Create a second scatter plot of one of the datasets, linking its # range to the first plot - plot2 = Plot(pd, range2d=plot1.range2d, title="render_style = connectedhold", - padding=50, border_visible=True, overlay_border=True) - plot2.plot(('index', 'y0'), color="blue", render_style="connectedhold") + plot2 = Plot( + pd, + range2d=plot1.range2d, + title="render_style = connectedhold", + padding=50, + border_visible=True, + overlay_border=True, + ) + plot2.plot(("index", "y0"), color="blue", render_style="connectedhold") attach_tools(plot2) # Create a container and add our plots @@ -52,27 +65,30 @@ def _create_plot_component(): container.add(plot2) return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Line plots with hold" +size = (900, 500) +title = "Line plots with hold" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/log_plot.py b/examples/demo/basic/log_plot.py index ff91eecda..d2f153dc1 100644 --- a/examples/demo/basic/log_plot.py +++ b/examples/demo/basic/log_plot.py @@ -18,20 +18,20 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some x-y data series to plot x = linspace(1.0, 8.0, 200) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) pd.set_data("y0", sqrt(x)) pd.set_data("y1", x) - pd.set_data("y2", x**2) + pd.set_data("y2", x ** 2) pd.set_data("y3", exp(x)) pd.set_data("y4", gamma(x)) - pd.set_data("y5", x**x) + pd.set_data("y5", x ** x) # Create some line plots of some of the data plot = Plot(pd) @@ -39,7 +39,7 @@ def _create_plot_component(): plot.plot(("index", "y1"), line_width=2, name="x", color="blue") plot.plot(("index", "y2"), line_width=2, name="x**2", color="green") plot.plot(("index", "y3"), line_width=2, name="exp(x)", color="gold") - plot.plot(("index", "y4"), line_width=2, name="gamma(x)",color="orange") + plot.plot(("index", "y4"), line_width=2, name="gamma(x)", color="orange") plot.plot(("index", "y5"), line_width=2, name="x**x", color="red") # Set the value axis to display on a log scale @@ -57,27 +57,30 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Basic x-y log plots" +size = (900, 500) +title = "Basic x-y log plots" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/minard_napoleon.py b/examples/demo/basic/minard_napoleon.py index e0040c17d..9f21e4e02 100644 --- a/examples/demo/basic/minard_napoleon.py +++ b/examples/demo/basic/minard_napoleon.py @@ -21,123 +21,127 @@ # town locations -towns = np.array([ - (24.0, 55.0, u"Kowno"), - (25.3, 54.7, u"Wilna"), - (26.4, 54.4, u"Smorgoni"), - (26.8, 54.3, u"Molodexno"), - (27.7, 55.2, u"Gloubokoe"), - (27.6, 53.9, u"Minsk"), - (28.5, 54.3, u"Studienska"), - (28.7, 55.5, u"Polotzk"), - (29.2, 54.4, u"Bobr"), - (30.2, 55.3, u"Witebsk"), - (30.4, 54.5, u"Orscha"), - (30.4, 53.9, u"Mohilow"), - (32.0, 54.8, u"Smolensk"), - (33.2, 54.9, u"Dorogobouge"), - (34.3, 55.2, u"Wixma"), - (34.4, 55.5, u"Chjat"), - (36.0, 55.5, u"Mojaisk"), - (37.6, 55.8, u"Moscou"), - (36.6, 55.3, u"Tarantino"), - (36.5, 55.0, u"Malo-jarosewli")], - dtype=[('lon', 'f4'), ('lat', 'f4'), ('town', 'U12')] +towns = np.array( + [ + (24.0, 55.0, u"Kowno"), + (25.3, 54.7, u"Wilna"), + (26.4, 54.4, u"Smorgoni"), + (26.8, 54.3, u"Molodexno"), + (27.7, 55.2, u"Gloubokoe"), + (27.6, 53.9, u"Minsk"), + (28.5, 54.3, u"Studienska"), + (28.7, 55.5, u"Polotzk"), + (29.2, 54.4, u"Bobr"), + (30.2, 55.3, u"Witebsk"), + (30.4, 54.5, u"Orscha"), + (30.4, 53.9, u"Mohilow"), + (32.0, 54.8, u"Smolensk"), + (33.2, 54.9, u"Dorogobouge"), + (34.3, 55.2, u"Wixma"), + (34.4, 55.5, u"Chjat"), + (36.0, 55.5, u"Mojaisk"), + (37.6, 55.8, u"Moscou"), + (36.6, 55.3, u"Tarantino"), + (36.5, 55.0, u"Malo-jarosewli"), + ], + dtype=[("lon", "f4"), ("lat", "f4"), ("town", "U12")], ) # Temperature data for Napoleon's retreat. -temperatures = np.array([ - ("Oct 18", 37.6, 0), - ("Oct 24", 36.0, 0), - ("Nov 09", 33.2, -9), - ("Nov 14", 32.0, -21), - ("Nov 24", 29.2, -11), - ("Nov 28", 28.5, -20), - ("Dec 01", 27.2, -24), - ("Dec 06", 26.7, -30), - ("Dec 07", 25.3, -26)], - dtype=[('date', 'U6'), ('lon', float), ('temp', float)] +temperatures = np.array( + [ + ("Oct 18", 37.6, 0), + ("Oct 24", 36.0, 0), + ("Nov 09", 33.2, -9), + ("Nov 14", 32.0, -21), + ("Nov 24", 29.2, -11), + ("Nov 28", 28.5, -20), + ("Dec 01", 27.2, -24), + ("Dec 06", 26.7, -30), + ("Dec 07", 25.3, -26), + ], + dtype=[("date", "U6"), ("lon", float), ("temp", float)], ) # Army sizes -army = np.array([ - (24.5, 55.0, 24.6, 55.8, 22000, 1, 3), - - (25.5, 54.6, 26.6, 55.7, 60000, 1, 2), - (26.6, 55.7, 27.4, 55.6, 40000, 1, 2), - (27.4, 55.6, 28.7, 55.5, 33000, 1, 2), - - (24.0, 54.9, 24.5, 55.0, 422000, 1, 1), - (24.5, 55.0, 25.5, 54.6, 400000, 1, 1), - (25.5, 54.6, 26.0, 54.7, 340000, 1, 1), - (26.0, 54.7, 27.0, 54.8, 320000, 1, 1), - (27.0, 54.8, 28.0, 54.9, 300000, 1, 1), - (28.0, 54.9, 28.5, 55.0, 280000, 1, 1), - (28.5, 55.0, 29.0, 55.1, 240000, 1, 1), - (29.0, 55.1, 30.0, 55.2, 210000, 1, 1), - (30.0, 55.2, 30.3, 55.3, 180000, 1, 1), - (30.3, 55.3, 32.0, 54.8, 175000, 1, 1), - (32.0, 54.8, 33.2, 54.9, 145000, 1, 1), - (33.2, 54.9, 34.4, 55.5, 140000, 1, 1), - (34.4, 55.5, 35.5, 55.4, 127100, 1, 1), - (35.5, 55.4, 36.0, 55.5, 100000, 1, 1), - (36.0, 55.5, 37.6, 55.8, 100000, 1, 1), - - (37.6, 55.8, 37.0, 55.0, 98000, -1, 1), - (37.0, 55.0, 36.8, 55.0, 97000, -1, 1), - (36.8, 55.0, 35.4, 55.3, 96000, -1, 1), - (35.4, 55.3, 34.3, 55.2, 87000, -1, 1), - (34.3, 55.2, 33.2, 54.9, 55000, -1, 1), - (33.2, 54.9, 32.0, 54.8, 37000, -1, 1), - (32.0, 54.8, 30.4, 54.4, 24000, -1, 1), - (30.4, 54.4, 29.2, 54.4, 20000, -1, 1), - (29.2, 54.4, 28.5, 54.3, 50000, -1, 1), - (28.5, 54.3, 28.3, 54.3, 50000, -1, 1), - (28.3, 54.3, 27.5, 54.5, 48000, -1, 1), - (27.5, 54.5, 26.8, 54.3, 40000, -1, 1), - (26.8, 54.3, 26.4, 54.4, 12000, -1, 1), - (26.4, 54.4, 24.6, 54.5, 14000, -1, 1), - (24.6, 54.5, 24.4, 54.4, 8000, -1, 1), - (24.4, 54.4, 24.2, 54.4, 4000, -1, 1), - (24.2, 54.4, 24.1, 54.4, 10000, -1, 1), - - (28.7, 55.5, 29.2, 54.4, 30000, -1, 2), - - (24.6, 55.8, 24.2, 54.4, 6000, -1, 3), -], +army = np.array( + [ + (24.5, 55.0, 24.6, 55.8, 22000, 1, 3), + (25.5, 54.6, 26.6, 55.7, 60000, 1, 2), + (26.6, 55.7, 27.4, 55.6, 40000, 1, 2), + (27.4, 55.6, 28.7, 55.5, 33000, 1, 2), + (24.0, 54.9, 24.5, 55.0, 422000, 1, 1), + (24.5, 55.0, 25.5, 54.6, 400000, 1, 1), + (25.5, 54.6, 26.0, 54.7, 340000, 1, 1), + (26.0, 54.7, 27.0, 54.8, 320000, 1, 1), + (27.0, 54.8, 28.0, 54.9, 300000, 1, 1), + (28.0, 54.9, 28.5, 55.0, 280000, 1, 1), + (28.5, 55.0, 29.0, 55.1, 240000, 1, 1), + (29.0, 55.1, 30.0, 55.2, 210000, 1, 1), + (30.0, 55.2, 30.3, 55.3, 180000, 1, 1), + (30.3, 55.3, 32.0, 54.8, 175000, 1, 1), + (32.0, 54.8, 33.2, 54.9, 145000, 1, 1), + (33.2, 54.9, 34.4, 55.5, 140000, 1, 1), + (34.4, 55.5, 35.5, 55.4, 127100, 1, 1), + (35.5, 55.4, 36.0, 55.5, 100000, 1, 1), + (36.0, 55.5, 37.6, 55.8, 100000, 1, 1), + (37.6, 55.8, 37.0, 55.0, 98000, -1, 1), + (37.0, 55.0, 36.8, 55.0, 97000, -1, 1), + (36.8, 55.0, 35.4, 55.3, 96000, -1, 1), + (35.4, 55.3, 34.3, 55.2, 87000, -1, 1), + (34.3, 55.2, 33.2, 54.9, 55000, -1, 1), + (33.2, 54.9, 32.0, 54.8, 37000, -1, 1), + (32.0, 54.8, 30.4, 54.4, 24000, -1, 1), + (30.4, 54.4, 29.2, 54.4, 20000, -1, 1), + (29.2, 54.4, 28.5, 54.3, 50000, -1, 1), + (28.5, 54.3, 28.3, 54.3, 50000, -1, 1), + (28.3, 54.3, 27.5, 54.5, 48000, -1, 1), + (27.5, 54.5, 26.8, 54.3, 40000, -1, 1), + (26.8, 54.3, 26.4, 54.4, 12000, -1, 1), + (26.4, 54.4, 24.6, 54.5, 14000, -1, 1), + (24.6, 54.5, 24.4, 54.4, 8000, -1, 1), + (24.4, 54.4, 24.2, 54.4, 4000, -1, 1), + (24.2, 54.4, 24.1, 54.4, 10000, -1, 1), + (28.7, 55.5, 29.2, 54.4, 30000, -1, 2), + (24.6, 55.8, 24.2, 54.4, 6000, -1, 3), + ], dtype=[ - ('start_lon', float), ('start_lat', float), ('end_lon', float), - ('end_lat', float), ('size', float), ('direction', float), - ('group', float) + ("start_lon", float), + ("start_lat", float), + ("end_lon", float), + ("end_lat", float), + ("size", float), + ("direction", float), + ("group", float), ], ) def _create_plot_component(): - army_lat = np.column_stack([army['start_lat'], army['end_lat']]).reshape(-1) - army_lon = np.column_stack([army['start_lon'], army['end_lon']]).reshape(-1) + army_lat = np.column_stack([army["start_lat"], army["end_lat"]]).reshape(-1) + army_lon = np.column_stack([army["start_lon"], army["end_lon"]]).reshape(-1) plot_data = ArrayPlotData( army_lon=army_lon, army_lat=army_lat, - army_size=army['size'], - army_color=army['direction']*army["group"], - towns_lat=towns['lat'], - towns_lon=towns['lon'], - towns=towns['town'], - temp_lon=temperatures['lon'], - temp=temperatures['temp'], - temp_date=temperatures['date'], + army_size=army["size"], + army_color=army["direction"] * army["group"], + towns_lat=towns["lat"], + towns_lon=towns["lon"], + towns=towns["town"], + temp_lon=temperatures["lon"], + temp=temperatures["temp"], + temp_date=temperatures["date"], ) map_plot = Plot(plot_data) map_plot.x_grid = None map_plot.y_grid = None - map_plot.x_axis.orientation = 'top' - map_plot.x_axis.title = 'Longitude' - map_plot.y_axis.title = 'Latitude' + map_plot.x_axis.orientation = "top" + map_plot.x_axis.title = "Longitude" + map_plot.y_axis.title = "Latitude" map_plot.title = "Minard's Map of Napoleon's Russian Campaign" map_plot._title.overlay_position = "inside top" map_plot._title.hjustify = "left" @@ -160,46 +164,48 @@ def _create_plot_component(): ("towns_lon", "towns_lat", "towns"), type="text", text_margin=4, - h_position='right', + h_position="right", text_offset=(4, 0), ) map_plot.plot_1d( - ('temp_lon'), - type='line_scatter_1d', + ("temp_lon"), + type="line_scatter_1d", alpha=0.5, - line_style='dot', + line_style="dot", ) map_plot.index_range.high_setting = 38 map_plot.index_range.low_setting = 23 map_plot.value_range.high_setting = 56.0 map_plot.value_range.low_setting = 53.5 - map_plot.tools.extend([ - PanTool(map_plot), - ZoomTool(map_plot), - ]) + map_plot.tools.extend( + [ + PanTool(map_plot), + ZoomTool(map_plot), + ] + ) temp_plot = Plot(plot_data, height=100) temp_plot.index_range = map_plot.index_range temp_plot.x_grid = None temp_plot.x_axis = None - temp_plot.y_axis.orientation = 'right' - temp_plot.y_axis.title = u'Temp (°Re)' + temp_plot.y_axis.orientation = "right" + temp_plot.y_axis.title = u"Temp (°Re)" temp_plot.plot( - ('temp_lon', 'temp'), - type='line', + ("temp_lon", "temp"), + type="line", ) temp_plot.plot_1d( - ('temp_lon'), - type='line_scatter_1d', + ("temp_lon"), + type="line_scatter_1d", alpha=0.5, - line_style='dot', + line_style="dot", ) temp_plot.plot_1d( - ('temp_lon', 'temp_date'), - type='textplot_1d', + ("temp_lon", "temp_date"), + type="textplot_1d", alpha=0.5, - line_style='dot', - alignment='bottom', + line_style="dot", + alignment="bottom", ) temp_plot.value_range.high_setting = 5 temp_plot.value_range.low_setting = -35 @@ -215,7 +221,7 @@ def _create_plot_component(): temp_plot.padding_right = 70 temp_plot.padding_left = 70 temp_plot.height = 100 - temp_plot.resizable = 'h' + temp_plot.resizable = "h" return container @@ -233,13 +239,14 @@ def _plot_default(self): traits_view = View( Item( - 'plot', + "plot", editor=ComponentEditor(size=size), show_label=False, ), title=title, ) + demo = Demo() if __name__ == "__main__": diff --git a/examples/demo/basic/minor_ticks_axis.py b/examples/demo/basic/minor_ticks_axis.py index 2baa52ab7..06dc046df 100644 --- a/examples/demo/basic/minor_ticks_axis.py +++ b/examples/demo/basic/minor_ticks_axis.py @@ -8,28 +8,24 @@ class MinorTickDemo(HasTraits): - """ A plot with minor tick labels. - """ + """A plot with minor tick labels.""" plot = Instance(Plot) - view = View( - UItem('plot', editor=ComponentEditor()), - resizable=True - ) + view = View(UItem("plot", editor=ComponentEditor()), resizable=True) def _plot_default(self): - x = np.linspace(0, 2*np.pi) + x = np.linspace(0, 2 * np.pi) plotdata = ArrayPlotData(x=x, y=np.sin(x)) plot = Plot(plotdata) - plot.plot(('x', 'y'), type='line') + plot.plot(("x", "y"), type="line") plot.tools.append(ZoomTool(plot)) plot.tools.append(PanTool(plot)) # A standard minor plot axis. xminor = MinorPlotAxis( - orientation='bottom', + orientation="bottom", mapper=plot.x_mapper, component=plot, ) @@ -37,10 +33,10 @@ def _plot_default(self): # A customized minor plot axis. yminor = MinorPlotAxis( - orientation='left', + orientation="left", mapper=plot.y_mapper, component=plot, - tick_color='red', + tick_color="red", tick_weight=2, tick_in=4, tick_out=2, @@ -53,7 +49,7 @@ def _plot_default(self): # Customizations for the y-major axis to make it stand out a little. ymajor = plot.y_axis - ymajor.tick_color = 'blue' + ymajor.tick_color = "blue" ymajor.tick_weight = 3 ymajor.tick_in = 7 ymajor.tick_out = 3 @@ -61,6 +57,6 @@ def _plot_default(self): return plot -if __name__ == '__main__': +if __name__ == "__main__": demo = MinorTickDemo() demo.configure_traits() diff --git a/examples/demo/basic/nans_plot.py b/examples/demo/basic/nans_plot.py index 0eb434a1f..4b77a3ff9 100644 --- a/examples/demo/basic/nans_plot.py +++ b/examples/demo/basic/nans_plot.py @@ -23,9 +23,9 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some x-y data series (with NaNs) to plot @@ -33,15 +33,16 @@ def _create_plot_component(): x[75:125] = nan x[200:250] = nan x[300:330] = nan - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) pd.set_data("value1", jn(0, x)) pd.set_data("value2", jn(1, x)) # Create some line and scatter plots of the data plot = Plot(pd) plot.plot(("index", "value1"), name="j_0(x)", color="red", width=2.0) - plot.plot(("index", "value2"), type="scatter", marker_size=1, - name="j_1(x)", color="green") + plot.plot( + ("index", "value2"), type="scatter", marker_size=1, name="j_1(x)", color="green" + ) # Tweak some of the plot properties plot.title = "Plots with NaNs" @@ -55,27 +56,30 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (800, 700) title = "Nan Test" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/pandas_data.py b/examples/demo/basic/pandas_data.py index 4b113c5fa..e77a484bf 100644 --- a/examples/demo/basic/pandas_data.py +++ b/examples/demo/basic/pandas_data.py @@ -15,9 +15,10 @@ from chaco.api import DataFramePlotData, Plot -#============================================================================== +# ============================================================================== # # Demo class that is used by the demo.py application. -#============================================================================== +# ============================================================================== + class Demo(HasTraits): @@ -27,15 +28,11 @@ class Demo(HasTraits): traits_view = View( Group( - Item( - 'plot', - editor=ComponentEditor(size=(900, 500)), - show_label=False - ), + Item("plot", editor=ComponentEditor(size=(900, 500)), show_label=False), orientation="vertical", ), resizable=True, - title="pandas data example" + title="pandas data example", ) def _plot_data_default(self): diff --git a/examples/demo/basic/polygon_move.py b/examples/demo/basic/polygon_move.py index 41dee1270..cc2fefdb4 100644 --- a/examples/demo/basic/polygon_move.py +++ b/examples/demo/basic/polygon_move.py @@ -18,6 +18,7 @@ from chaco.base import n_gon from chaco.tools.api import PanTool, ZoomTool, DragTool + class DataspaceMoveTool(DragTool): """ Modifies the data values of a plot. Only works on instances @@ -28,7 +29,7 @@ class DataspaceMoveTool(DragTool): _prev_pt = CArray def is_draggable(self, x, y): - return self.component.hittest((x,y)) + return self.component.hittest((x, y)) def drag_start(self, event): data_pt = self.component.map_data((event.x, event.y), all_values=True) @@ -49,19 +50,27 @@ def dragging(self, event): plot.request_redraw() -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Use n_gon to compute center locations for our polygons - points = n_gon(center=(0,0), r=4, nsides=8) + points = n_gon(center=(0, 0), r=4, nsides=8) # Choose some colors for our polygons - colors = {3:0xaabbcc, 4:'orange', 5:'yellow', 6:'lightgreen', - 7:'green', 8:'blue', 9:'lavender', 10:'purple'} - - # Create a PlotData object to store the polygon data + colors = { + 3: 0xAABBCC, + 4: "orange", + 5: "yellow", + 6: "lightgreen", + 7: "green", + 8: "blue", + 9: "lavender", + 10: "purple", + } + + # Create a PlotData object to store the polygon data pd = ArrayPlotData() # Create a Polygon Plot to draw the regular polygons @@ -74,10 +83,12 @@ def _create_plot_component(): nxarray, nyarray = transpose(npoints) pd.set_data("x" + str(nsides), nxarray) pd.set_data("y" + str(nsides), nyarray) - plot = polyplot.plot(("x"+str(nsides), "y"+str(nsides)), - type="polygon", - face_color=colors[nsides], - hittest_type="poly")[0] + plot = polyplot.plot( + ("x" + str(nsides), "y" + str(nsides)), + type="polygon", + face_color=colors[nsides], + hittest_type="poly", + )[0] plot.tools.append(DataspaceMoveTool(plot, drag_button="right")) nsides = nsides + 1 @@ -92,27 +103,30 @@ def _create_plot_component(): return polyplot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(800,800) -title="Polygon Plot" +size = (800, 800) +title = "Polygon Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/polygon_plot_demo.py b/examples/demo/basic/polygon_plot_demo.py index 2c107274a..65319e9f5 100644 --- a/examples/demo/basic/polygon_plot_demo.py +++ b/examples/demo/basic/polygon_plot_demo.py @@ -23,36 +23,35 @@ class PolygonPlotDemo(HasTraits): # The polygon plot renderer. polygon_plot = Instance(PolygonPlot) - # Assorted styles that will be set on `polygon_plot`. + # Assorted styles that will be set on `polygon_plot`. edge_style = LineStyle edge_width = Range(value=1, low=0, high=8) edge_alpha = Range(value=1.0, low=0.0, high=1.0) face_alpha = Range(value=0.4, low=0.0, high=1.0) alpha = Range(value=1.0, low=0.0, high=1.0) - traits_view = \ - View( + traits_view = View( + VGroup( + Group( + UItem("plot", editor=ComponentEditor(), style="custom"), + ), VGroup( - Group( - UItem('plot', editor=ComponentEditor(), style='custom'), - ), - VGroup( - HGroup( - Item('edge_style'), - spring, - ), - Item('edge_width'), - Item('edge_alpha'), - Item('face_alpha'), - Item('alpha'), + HGroup( + Item("edge_style"), + spring, ), + Item("edge_width"), + Item("edge_alpha"), + Item("face_alpha"), + Item("alpha"), ), - resizable=True, - ) + ), + resizable=True, + ) - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Default values - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _apd_default(self): # Create the data to plot. @@ -64,21 +63,23 @@ def _apd_default(self): return apd def _plot_default(self): - plot = Plot(self.apd, title='PolygonPlot Demo') + plot = Plot(self.apd, title="PolygonPlot Demo") return plot def _polygon_plot_default(self): - p = self.plot.plot(('px', 'py'), - type='polygon', - face_color=(0,0.8,1) + (self.face_alpha,), - edge_color=(0,0,0) + (self.edge_alpha,), - edge_style=self.edge_style, - alpha=self.alpha) + p = self.plot.plot( + ("px", "py"), + type="polygon", + face_color=(0, 0.8, 1) + (self.face_alpha,), + edge_color=(0, 0, 0) + (self.edge_alpha,), + edge_style=self.edge_style, + alpha=self.alpha, + ) return p[0] - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- # Trait change handlers - #---------------------------------------------------------------------- + # ---------------------------------------------------------------------- def _edge_style_changed(self): self.polygon_plot.edge_style = self.edge_style @@ -87,10 +88,14 @@ def _edge_width_changed(self): self.polygon_plot.edge_width = self.edge_width def _edge_alpha_changed(self): - self.polygon_plot.edge_color = self.polygon_plot.edge_color[:3] + (self.edge_alpha,) + self.polygon_plot.edge_color = self.polygon_plot.edge_color[:3] + ( + self.edge_alpha, + ) def _face_alpha_changed(self): - self.polygon_plot.face_color = self.polygon_plot.face_color[:3] + (self.face_alpha,) + self.polygon_plot.face_color = self.polygon_plot.face_color[:3] + ( + self.face_alpha, + ) def _alpha_changed(self): self.polygon_plot.alpha = self.alpha diff --git a/examples/demo/basic/regression.py b/examples/demo/basic/regression.py index b10243c01..fef43e776 100644 --- a/examples/demo/basic/regression.py +++ b/examples/demo/basic/regression.py @@ -21,12 +21,11 @@ # Chaco imports from chaco.api import ArrayPlotData, Plot -from chaco.tools.api import PanTool, ZoomTool, RegressionLasso, \ - RegressionOverlay +from chaco.tools.api import PanTool, ZoomTool, RegressionLasso, RegressionOverlay -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): pd = ArrayPlotData(x=random(100), y=random(100)) @@ -46,34 +45,37 @@ def _create_plot_component(): # Add the regression tool and overlay. These need to be added # directly to the scatterplot instance (and not the Plot instance). - regression = RegressionLasso(scatterplot, - selection_datasource=scatterplot.index) + regression = RegressionLasso(scatterplot, selection_datasource=scatterplot.index) scatterplot.tools.append(regression) - scatterplot.overlays.append(RegressionOverlay(scatterplot, - lasso_selection=regression)) + scatterplot.overlays.append( + RegressionOverlay(scatterplot, lasso_selection=regression) + ) return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (600, 600) title = "Regression Selection" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/scatter.py b/examples/demo/basic/scatter.py index e707f8839..0b1973ec1 100644 --- a/examples/demo/basic/scatter.py +++ b/examples/demo/basic/scatter.py @@ -27,9 +27,9 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -44,13 +44,15 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value"), - type="scatter", - marker="circle", - index_sort="ascending", - color="orange", - marker_size=3, - bgcolor="white") + plot.plot( + ("index", "value"), + type="scatter", + marker="circle", + index_sort="ascending", + color="orange", + marker_size=3, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Scatter Plot" @@ -64,29 +66,35 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (650, 650) title = "Basic scatter plot" -bg_color="lightgray" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/scatter_1d.py b/examples/demo/basic/scatter_1d.py index 2ac2a9d72..eff9b6703 100644 --- a/examples/demo/basic/scatter_1d.py +++ b/examples/demo/basic/scatter_1d.py @@ -19,9 +19,9 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -38,46 +38,39 @@ def _create_plot_component(): plot = Plot(pd, use_backbuffer=True, auto_grid=False) plot.plot_1d( - 'index', - type='line_scatter_1d', - orientation='h', - color='lightgrey', - line_style='dot', + "index", + type="line_scatter_1d", + orientation="h", + color="lightgrey", + line_style="dot", ) plot.plot_1d( - 'index', - type='scatter_1d', - orientation='h', - marker='plus', - alignment='bottom' + "index", type="scatter_1d", orientation="h", marker="plus", alignment="bottom" ) plot.plot_1d( - 'value', - type='line_scatter_1d', - orientation='v', - color='lightgrey', - line_style='dot', + "value", + type="line_scatter_1d", + orientation="v", + color="lightgrey", + line_style="dot", ) plot.plot_1d( - 'value', - type='scatter_1d', - orientation='v', - marker='plus', - alignment='left' + "value", type="scatter_1d", orientation="v", marker="plus", alignment="left" ) - plot.plot(("index", "value"), - type="scatter", - marker="square", - index_sort="ascending", - color="orange", - marker_size=3, #randint(1,5, numpts), - bgcolor="white", - use_backbuffer=True) - + plot.plot( + ("index", "value"), + type="scatter", + marker="square", + index_sort="ascending", + color="orange", + marker_size=3, # randint(1,5, numpts), + bgcolor="white", + use_backbuffer=True, + ) # Tweak some of the plot properties plot.title = "1D Scatter Plots" @@ -91,29 +84,35 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (650, 650) title = "1D scatter plots" -bg_color="lightgray" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/scatter_alpha.py b/examples/demo/basic/scatter_alpha.py index a4853e0a9..6494800f7 100644 --- a/examples/demo/basic/scatter_alpha.py +++ b/examples/demo/basic/scatter_alpha.py @@ -20,9 +20,9 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -52,51 +52,59 @@ def _create_plot_component(): def _create_scatter_renderer(plot): - renderer = plot.plot(("index", "value"), - type="scatter", - marker="circle", - index_sort="ascending", - color="orange", - marker_size=3, - bgcolor="white")[0] + renderer = plot.plot( + ("index", "value"), + type="scatter", + marker="circle", + index_sort="ascending", + color="orange", + marker_size=3, + bgcolor="white", + )[0] return renderer -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (650, 650) title = "Basic scatter plot" -bg_color="lightgray" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) scatter_renderer = Instance(Component) - alpha = DelegatesTo('scatter_renderer') + alpha = DelegatesTo("scatter_renderer") traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - Group( - Item('alpha', editor=RangeEditor(low=0.0, high=1.0)), - ), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + Group( + Item("alpha", editor=RangeEditor(low=0.0, high=1.0)), + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() def _scatter_renderer_default(self): renderer = _create_scatter_renderer(self.plot) return renderer + demo = Demo() if __name__ == "__main__": diff --git a/examples/demo/basic/scatter_custom_marker.py b/examples/demo/basic/scatter_custom_marker.py index 6ca56f073..412a28a4e 100644 --- a/examples/demo/basic/scatter_custom_marker.py +++ b/examples/demo/basic/scatter_custom_marker.py @@ -30,16 +30,17 @@ def make_custom_marker(): path = CompiledPath() - path.move_to(-5,-5) + path.move_to(-5, -5) path.line_to(5, 5) path.line_to(5, -5) path.line_to(-5, 5) path.line_to(-5, -5) return path -#=============================================================================== + +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -57,14 +58,16 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value"), - type="scatter", - marker="custom", - custom_symbol=marker, - index_sort="ascending", - color="orange", - marker_size=3, - bgcolor="white") + plot.plot( + ("index", "value"), + type="scatter", + marker="custom", + custom_symbol=marker, + index_sort="ascending", + color="orange", + marker_size=3, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Scatter plot with custom markers" @@ -78,29 +81,35 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (650, 650) title = "Scatter plot w/ custom markers" -bg_color="lightgray" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/scatter_inspector.py b/examples/demo/basic/scatter_inspector.py index a8178fa07..30a56bb7e 100644 --- a/examples/demo/basic/scatter_inspector.py +++ b/examples/demo/basic/scatter_inspector.py @@ -19,15 +19,15 @@ from chaco.api import ArrayPlotData, Plot, ScatterInspectorOverlay from chaco.tools.api import PanTool, ZoomTool, ScatterInspector -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create a random scattering of XY pairs x = random.uniform(0.0, 10.0, 50) y = random.uniform(0.0, 5.0, 50) - pd = ArrayPlotData(x = x, y = y) + pd = ArrayPlotData(x=x, y=y) plot = Plot(pd, border_visible=True, overlay_border=True) scatter = plot.plot(("x", "y"), type="scatter", color="lightblue")[0] @@ -43,44 +43,50 @@ def _create_plot_component(): # Attach the inspector and its overlay inspector = ScatterInspector(scatter) scatter.tools.append(inspector) - overlay = ScatterInspectorOverlay(scatter, - hover_color="red", - hover_marker_size=6, - selection_marker_size=6, - selection_color="yellow", - selection_outline_color="purple", - selection_line_width=3) + overlay = ScatterInspectorOverlay( + scatter, + hover_color="red", + hover_marker_size=6, + selection_marker_size=6, + selection_color="yellow", + selection_outline_color="purple", + selection_line_width=3, + ) scatter.overlays.append(overlay) # Optional: add a listener on inspector events: def echo(event): new = event.new print("{} event on element {}".format(new.event_type, new.event_index)) + inspector.observe(echo, "inspector_event") return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Tooltip demo" +size = (900, 500) +title = "Tooltip demo" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/scatter_inspector2.py b/examples/demo/basic/scatter_inspector2.py index 819b18636..5d1befbd4 100644 --- a/examples/demo/basic/scatter_inspector2.py +++ b/examples/demo/basic/scatter_inspector2.py @@ -6,8 +6,7 @@ from traits.api import Callable, Enum, HasTraits, Instance, observe, Str from traitsui.api import View, Item from enable.api import ComponentEditor -from chaco.api import Plot, ArrayPlotData, ScatterInspectorOverlay, \ - TextBoxOverlay +from chaco.api import Plot, ArrayPlotData, ScatterInspectorOverlay, TextBoxOverlay from chaco.api import DataFramePlotData from chaco.tools.api import ScatterInspector @@ -18,17 +17,17 @@ class DataframeScatterInspector(ScatterInspector): class DataframeScatterOverlay(TextBoxOverlay): - """ Overlay for displaying hovered data point information. - """ + """Overlay for displaying hovered data point information.""" + #: The inspector tool which has hover information inspector = Instance(ScatterInspector) #: Function which takes and index and returns an info string. message_for_data = Callable - @observe('inspector:inspector_event') + @observe("inspector:inspector_event") def scatter_point_found(self, event): - inspector_event = event.new + inspector_event = event.new data_idx = inspector_event.event_index if data_idx is not None: self.text = self.message_for_data(data_idx) @@ -57,31 +56,33 @@ def _create_plot_component(): # scatter plot: x = np.random.uniform(0.0, 10.0, 50) y = np.random.uniform(0.0, 5.0, 50) - data = pd.DataFrame({"x": x, "y": y, - "dataset": np.random.choice(list("abcdefg"), 50)}) + data = pd.DataFrame( + {"x": x, "y": y, "dataset": np.random.choice(list("abcdefg"), 50)} + ) plot_data = ArrayPlotData(x=x, y=y) plot = Plot(plot_data) scatter = plot.plot(("x", "y"), type="scatter")[0] # Attach the inspector and its overlays - inspector = DataframeScatterInspector( - component=scatter, data=data - ) + inspector = DataframeScatterInspector(component=scatter, data=data) scatter.tools.append(inspector) - text_overlay = DataframeScatterOverlay(component=plot, - inspector=inspector, - bgcolor="black", alpha=0.6, - text_color="white", - border_color='none') + text_overlay = DataframeScatterOverlay( + component=plot, + inspector=inspector, + bgcolor="black", + alpha=0.6, + text_color="white", + border_color="none", + ) plot.overlays.append(text_overlay) # Optional: add an overlay on the point to confirm what is hovered over # Note that this overlay magically knows about hovered points by # listening to renderer events rather than inspector events: - point_overlay = ScatterInspectorOverlay(component=scatter, - hover_color="red", - hover_marker_size=6) + point_overlay = ScatterInspectorOverlay( + component=scatter, hover_color="red", hover_marker_size=6 + ) scatter.overlays.append(point_overlay) return plot @@ -98,8 +99,9 @@ class Demo(HasTraits): plot = Instance(Plot) traits_view = View( - Item('plot', editor=ComponentEditor(size=size), show_label=False), - resizable=True, title=title + Item("plot", editor=ComponentEditor(size=size), show_label=False), + resizable=True, + title=title, ) def _plot_default(self): diff --git a/examples/demo/basic/scatter_rect_select.py b/examples/demo/basic/scatter_rect_select.py index 29cc6c060..134c3a129 100644 --- a/examples/demo/basic/scatter_rect_select.py +++ b/examples/demo/basic/scatter_rect_select.py @@ -20,12 +20,10 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ( - ArrayPlotData, Plot, LassoOverlay, ScatterInspectorOverlay) +from chaco.api import ArrayPlotData, Plot, LassoOverlay, ScatterInspectorOverlay from chaco.tools.api import RectangularSelection, ScatterInspector - # =============================================================================== # # Create the Chaco plot. # =============================================================================== @@ -42,14 +40,16 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value"), - type="scatter", - name="my_plot", - marker="circle", - index_sort="ascending", - color="red", - marker_size=4, - bgcolor="white") + plot.plot( + ("index", "value"), + type="scatter", + name="my_plot", + marker="circle", + index_sort="ascending", + color="red", + marker_size=4, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Scatter Plot With Rectangular Selection" @@ -65,21 +65,20 @@ def _create_plot_component(): component=my_plot, selection_datasource=my_plot.index, drag_button="left", - metadata_name='selections', + metadata_name="selections", ) my_plot.tools.append(rect_selection) - my_plot.tools.append(ScatterInspector(my_plot, selection_mode='toggle')) + my_plot.tools.append(ScatterInspector(my_plot, selection_mode="toggle")) my_plot.active_tool = rect_selection - lasso_overlay = LassoOverlay(lasso_selection=rect_selection, - component=my_plot) + lasso_overlay = LassoOverlay(lasso_selection=rect_selection, component=my_plot) my_plot.overlays.append(lasso_overlay) scatter_overlay = ScatterInspectorOverlay( component=my_plot, - selection_color='cornflowerblue', - selection_marker_size=int(my_plot.marker_size)+3, - selection_marker='circle' + selection_color="cornflowerblue", + selection_marker_size=int(my_plot.marker_size) + 3, + selection_marker="circle", ) my_plot.overlays.append(scatter_overlay) @@ -101,14 +100,15 @@ class Demo(HasTraits): traits_view = View( Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation="vertical"), - resizable=True, title=title + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, ) def _selection_changed(self, event): - mask = self.index_datasource.metadata['selections'] + mask = self.index_datasource.metadata["selections"] print("New selection: ") print(compress(mask, arange(len(mask)))) # Ensure that the points are printed immediately: @@ -123,7 +123,7 @@ def _plot_default(self): # Set up the trait handler for the selection self.index_datasource = my_plot.index - rect_selection.observe(self._selection_changed, 'selection_changed') + rect_selection.observe(self._selection_changed, "selection_changed") return plot diff --git a/examples/demo/basic/scatter_select.py b/examples/demo/basic/scatter_select.py index 9e169eb38..4e7192f12 100644 --- a/examples/demo/basic/scatter_select.py +++ b/examples/demo/basic/scatter_select.py @@ -26,9 +26,9 @@ from chaco.api import ArrayPlotData, Plot, LassoOverlay from chaco.tools.api import LassoSelection, ScatterInspector -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -43,14 +43,16 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value"), - type="scatter", - name="my_plot", - marker="circle", - index_sort="ascending", - color="red", - marker_size=4, - bgcolor="white") + plot.plot( + ("index", "value"), + type="scatter", + name="my_plot", + marker="circle", + index_sort="ascending", + color="red", + marker_size=4, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Scatter Plot With Lasso Selection" @@ -62,62 +64,62 @@ def _create_plot_component(): my_plot = plot.plots["my_plot"][0] # Attach some tools to the plot - lasso_selection = LassoSelection(component=my_plot, - selection_datasource=my_plot.index, - drag_button="left") - #drag_button="right") + lasso_selection = LassoSelection( + component=my_plot, selection_datasource=my_plot.index, drag_button="left" + ) + # drag_button="right") my_plot.active_tool = lasso_selection my_plot.tools.append(ScatterInspector(my_plot)) - lasso_overlay = LassoOverlay(lasso_selection=lasso_selection, - component=my_plot) + lasso_overlay = LassoOverlay(lasso_selection=lasso_selection, component=my_plot) my_plot.overlays.append(lasso_overlay) # Uncomment this if you would like to see incremental updates: - #lasso_selection.incremental_select = True + # lasso_selection.incremental_select = True return plot -#=============================================================================== +# =============================================================================== # Attributes to use for the plot view. -size=(650,650) -title="Scatter plot with selection" -bg_color="lightgray" +size = (650, 650) +title = "Scatter plot with selection" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _selection_changed(self, event): - mask = self.index_datasource.metadata['selection'] + mask = self.index_datasource.metadata["selection"] print("New selection: ") print(compress(mask, arange(len(mask)))) # Ensure that the points are printed immediately: sys.stdout.flush() - def _plot_default(self): - plot = _create_plot_component() + plot = _create_plot_component() - # Retrieve the plot hooked to the LassoSelection tool. - my_plot = plot.plots["my_plot"][0] - lasso_selection = my_plot.active_tool + # Retrieve the plot hooked to the LassoSelection tool. + my_plot = plot.plots["my_plot"][0] + lasso_selection = my_plot.active_tool - # Set up the trait handler for the selection - self.index_datasource = my_plot.index - lasso_selection.observe(self._selection_changed, 'selection_changed') + # Set up the trait handler for the selection + self.index_datasource = my_plot.index + lasso_selection.observe(self._selection_changed, "selection_changed") + + return plot - return plot demo = Demo() diff --git a/examples/demo/basic/scatter_toggle.py b/examples/demo/basic/scatter_toggle.py index 6d580e0da..49ef4f433 100644 --- a/examples/demo/basic/scatter_toggle.py +++ b/examples/demo/basic/scatter_toggle.py @@ -24,13 +24,12 @@ from traitsui.api import Item, VGroup, View, Label, HGroup, spring # Chaco imports -from chaco.api import AbstractDataSource, ArrayPlotData, Plot, \ - ScatterInspectorOverlay +from chaco.api import AbstractDataSource, ArrayPlotData, Plot, ScatterInspectorOverlay from chaco.tools.api import ScatterInspector, PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -45,14 +44,16 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value"), - type="scatter", - name="my_plot", - marker="circle", - index_sort="ascending", - color="slategray", - marker_size=6, - bgcolor="white") + plot.plot( + ("index", "value"), + type="scatter", + name="my_plot", + marker="circle", + index_sort="ascending", + color="slategray", + marker_size=6, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Scatter Plot With Selection" @@ -64,51 +65,58 @@ def _create_plot_component(): my_plot = plot.plots["my_plot"][0] # Attach some tools to the plot - my_plot.tools.append(ScatterInspector(my_plot, selection_mode="toggle", - persistent_hover=False)) + my_plot.tools.append( + ScatterInspector(my_plot, selection_mode="toggle", persistent_hover=False) + ) my_plot.overlays.append( - ScatterInspectorOverlay(my_plot, - hover_color = "transparent", - hover_marker_size = 10, - hover_outline_color = "purple", - hover_line_width = 2, - selection_marker_size = 8, - selection_color = "lawngreen") - ) + ScatterInspectorOverlay( + my_plot, + hover_color="transparent", + hover_marker_size=10, + hover_outline_color="purple", + hover_line_width=2, + selection_marker_size=8, + selection_color="lawngreen", + ) + ) my_plot.tools.append(PanTool(my_plot)) my_plot.overlays.append(ZoomTool(my_plot, drag_button="right")) return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(650,650) -title="Scatter plot with selection" -bg_color="lightgray" +size = (650, 650) +title = "Scatter plot with selection" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - VGroup( - HGroup(spring, Label('Click point to select/unselect'), - spring), - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + VGroup( + HGroup(spring, Label("Click point to select/unselect"), spring), + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _metadata_handler(self, event): - sel_indices = self.index_datasource.metadata.get('selections', []) + sel_indices = self.index_datasource.metadata.get("selections", []) print("Selection indices:", sel_indices) - hover_indices = self.index_datasource.metadata.get('hover', []) + hover_indices = self.index_datasource.metadata.get("hover", []) print("Hover indices:", hover_indices) def _plot_default(self): @@ -119,12 +127,11 @@ def _plot_default(self): # Set up the trait handler for the selection self.index_datasource = my_plot.index - self.index_datasource.observe( - self._metadata_handler, "metadata_changed" - ) + self.index_datasource.observe(self._metadata_handler, "metadata_changed") return plot + demo = Demo() if __name__ == "__main__": diff --git a/examples/demo/basic/scatter_variable_size.py b/examples/demo/basic/scatter_variable_size.py index 3b8b95d0c..4672ba76a 100644 --- a/examples/demo/basic/scatter_variable_size.py +++ b/examples/demo/basic/scatter_variable_size.py @@ -20,9 +20,9 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -38,13 +38,15 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value"), - type="scatter", - marker="circle", - index_sort="ascending", - color=(1.0, 0.0, 0.74, 0.4), - marker_size=marker_size, - bgcolor="white") + plot.plot( + ("index", "value"), + type="scatter", + marker="circle", + index_sort="ascending", + color=(1.0, 0.0, 0.74, 0.4), + marker_size=marker_size, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Scatter Plot" @@ -58,29 +60,35 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (650, 650) title = "Basic scatter plot" -bg_color="lightgray" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/scrollbar.py b/examples/demo/basic/scrollbar.py index 8fed1a832..40670f12b 100644 --- a/examples/demo/basic/scrollbar.py +++ b/examples/demo/basic/scrollbar.py @@ -20,21 +20,20 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ArrayPlotData, VPlotContainer, \ - Plot +from chaco.api import ArrayPlotData, VPlotContainer, Plot from chaco.plotscrollbar import PlotScrollBar from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some x-y data series to plot x = linspace(-2.0, 10.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) for i in range(5): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) # Create some line plots of some of the data plot1 = Plot(pd, padding=50) @@ -47,8 +46,7 @@ def _create_plot_component(): plot1.overlays.append(zoom) # Add the scrollbar - hscrollbar = PlotScrollBar(component=plot1, axis="index", resizable="h", - height=15) + hscrollbar = PlotScrollBar(component=plot1, axis="index", resizable="h", height=15) plot1.padding_top = 0 hscrollbar.force_data_update() @@ -59,27 +57,30 @@ def _create_plot_component(): return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Scrollbar example" +size = (900, 500) +title = "Scrollbar example" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/segment_plot.py b/examples/demo/basic/segment_plot.py index 8a50d81d4..0106c7f1f 100644 --- a/examples/demo/basic/segment_plot.py +++ b/examples/demo/basic/segment_plot.py @@ -27,9 +27,9 @@ from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data @@ -46,13 +46,15 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value"), - type="segment", - color="forestgreen", - line_width=2, - line_style='dash', - alpha=0.7, - bgcolor="white") + plot.plot( + ("index", "value"), + type="segment", + color="forestgreen", + line_width=2, + line_style="dash", + alpha=0.7, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Segment Plot" @@ -66,29 +68,35 @@ def _create_plot_component(): return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (650, 650) title = "Basic scatter plot" -bg_color="lightgray" +bg_color = "lightgray" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size, - bgcolor=bg_color), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item( + "plot", + editor=ComponentEditor(size=size, bgcolor=bg_color), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/basic/tabbed_plots.py b/examples/demo/basic/tabbed_plots.py index 34fe9aad9..822ff2cc0 100644 --- a/examples/demo/basic/tabbed_plots.py +++ b/examples/demo/basic/tabbed_plots.py @@ -39,15 +39,16 @@ class TabbedPlots(HasTraits): view = View( VGroup( # UItem is an unlabeled item - UItem('plot_sin', editor=ComponentEditor(), dock='tab'), + UItem("plot_sin", editor=ComponentEditor(), dock="tab"), Tabbed( - UItem('plot_tan', editor=ComponentEditor(), dock='tab'), - UItem('plot_mixed', editor=ComponentEditor(), dock='tab')) + UItem("plot_tan", editor=ComponentEditor(), dock="tab"), + UItem("plot_mixed", editor=ComponentEditor(), dock="tab"), ), - title='Tabbed plots with shared data ranges', + ), + title="Tabbed plots with shared data ranges", width=0.67, height=0.4, - resizable=True + resizable=True, ) def create_plot(self, data, name, color): @@ -67,9 +68,9 @@ def create_plots(self): # initial value, we will use the range of the mixed plot, whose y-range # is auto-set to slightly larger than that of the sin plot. self.plot_sin.range2d = self.plot_mixed.range2d - + # The sin & mixed plots will share only their x range with the tan plot. - # Again, this x-axis range is a single object shared by all 3 plots. + # Again, this x-axis range is a single object shared by all 3 plots. # It is contained within the 2d range shared by the sin and mixed plots. # (The independent variable, in this case x, is called "index" in chaco. # The dependent variable is called "value".) @@ -79,15 +80,13 @@ def _data_changed(self): self.create_plots() -#=============================================================================== +# =============================================================================== # # demo object that is used by the demo.py application. -#=============================================================================== -x = linspace(-2*pi, 2*pi, 100) +# =============================================================================== +x = linspace(-2 * pi, 2 * pi, 100) demo = TabbedPlots( - data = ArrayPlotData(x=x, - ysin=sin(x), - ytan=tan(x), - ymix=sin(x)**2 + cos(x))) + data=ArrayPlotData(x=x, ysin=sin(x), ytan=tan(x), ymix=sin(x) ** 2 + cos(x)) +) if __name__ == "__main__": demo.configure_traits() diff --git a/examples/demo/basic/traits_editor.py b/examples/demo/basic/traits_editor.py index 455b8650d..5b650e34b 100644 --- a/examples/demo/basic/traits_editor.py +++ b/examples/demo/basic/traits_editor.py @@ -20,8 +20,7 @@ from traitsui.api import Item, View # Chaco imports -from chaco.chaco_plot_editor import ChacoPlotEditor, \ - ChacoPlotItem +from chaco.chaco_plot_editor import ChacoPlotEditor, ChacoPlotItem class Foo(HasTraits): @@ -33,34 +32,34 @@ class Foo(HasTraits): # Default TraitsUI view traits_view = View( - ChacoPlotItem("xdata", "_ydata", - type_trait="plot_type", - - # Basic axis and label properties - show_label=False, - resizable=True, - orientation="h", - x_label = "Index data", - y_label = "Value data", - - # Plot properties - color = "green", - bgcolor = "white", - - # Specific to scatter plot - marker = "circle", - marker_size = 2, - outline_color = "none", - - # Border, padding properties - border_visible=True, - border_width=1, - padding_bg_color = "lightgray"), - Item("plot_type"), - Item("eq"), - resizable=True, - width=500, height=500) - + ChacoPlotItem( + "xdata", + "_ydata", + type_trait="plot_type", + # Basic axis and label properties + show_label=False, + resizable=True, + orientation="h", + x_label="Index data", + y_label="Value data", + # Plot properties + color="green", + bgcolor="white", + # Specific to scatter plot + marker="circle", + marker_size=2, + outline_color="none", + # Border, padding properties + border_visible=True, + border_width=1, + padding_bg_color="lightgray", + ), + Item("plot_type"), + Item("eq"), + resizable=True, + width=500, + height=500, + ) # Private Traits _d = Dict @@ -79,10 +78,11 @@ def _eq_changed(self, old, new): except: pass -#=============================================================================== + +# =============================================================================== # # demo object that is used by the demo.py application. -#=============================================================================== -demo = Foo(xdata=linspace(-2*pi, 2*pi ,100), eq="sin(x)") +# =============================================================================== +demo = Foo(xdata=linspace(-2 * pi, 2 * pi, 100), eq="sin(x)") if __name__ == "__main__": demo.edit_traits(kind="modal") diff --git a/examples/demo/basic/zoomable_colorbar.py b/examples/demo/basic/zoomable_colorbar.py index 54b2d2cb8..fd7019a85 100644 --- a/examples/demo/basic/zoomable_colorbar.py +++ b/examples/demo/basic/zoomable_colorbar.py @@ -22,21 +22,26 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ArrayPlotData, ColorBar, \ - HPlotContainer, \ - LinearMapper, Plot, gist_earth +from chaco.api import ( + ArrayPlotData, + ColorBar, + HPlotContainer, + LinearMapper, + Plot, + gist_earth, +) from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some data numpts = 1000 x = sort(random(numpts)) y = random(numpts) - color = exp(-(x**2 + y**2)) + color = exp(-(x ** 2 + y ** 2)) # Create a plot data obect and give it this data pd = ArrayPlotData() @@ -46,16 +51,18 @@ def _create_plot_component(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value", "color"), - type="cmap_scatter", - name="my_plot", - color_mapper=gist_earth, - marker = "square", - fill_alpha = 0.5, - marker_size = 8, - outline_color = "black", - border_visible = True, - bgcolor = "white") + plot.plot( + ("index", "value", "color"), + type="cmap_scatter", + name="my_plot", + color_mapper=gist_earth, + marker="square", + fill_alpha=0.5, + marker_size=8, + outline_color="black", + border_visible=True, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Colormapped Scatter Plot with Pan/Zoom Color Bar" @@ -71,20 +78,23 @@ def _create_plot_component(): plot.overlays.append(zoom) # Create the colorbar, handing in the appropriate range and colormap - colorbar = ColorBar(index_mapper=LinearMapper(range=plot.color_mapper.range), - color_mapper=plot.color_mapper, - orientation='v', - resizable='v', - width=30, - padding=20) + colorbar = ColorBar( + index_mapper=LinearMapper(range=plot.color_mapper.range), + color_mapper=plot.color_mapper, + orientation="v", + resizable="v", + width=30, + padding=20, + ) colorbar.plot = plot colorbar.padding_top = plot.padding_top colorbar.padding_bottom = plot.padding_bottom # Add pan and zoom tools to the colorbar colorbar.tools.append(PanTool(colorbar, constrain_direction="y", constrain=True)) - zoom_overlay = ZoomTool(colorbar, axis="index", tool_mode="range", - always_on=True, drag_button="right") + zoom_overlay = ZoomTool( + colorbar, axis="index", tool_mode="range", always_on=True, drag_button="right" + ) colorbar.overlays.append(zoom_overlay) # Create a container to position the plot and the colorbar side-by-side @@ -92,27 +102,30 @@ def _create_plot_component(): return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(650,650) -title="Colormapped scatter plot" +size = (650, 650) +title = "Colormapped scatter plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/bigdata.py b/examples/demo/bigdata.py index 8d33ec063..8fa355cea 100644 --- a/examples/demo/bigdata.py +++ b/examples/demo/bigdata.py @@ -15,41 +15,50 @@ from numpy import arange from chaco.example_support import COLOR_PALETTE + # Enthought library imports from enable.api import Component, ComponentEditor from traits.api import Bool, HasTraits, Instance from traitsui.api import Group, Item, UItem, View # Chaco imports -from chaco.api import OverlayPlotContainer, create_line_plot, add_default_axes, \ - add_default_grids +from chaco.api import ( + OverlayPlotContainer, + create_line_plot, + add_default_axes, + add_default_grids, +) from chaco.tools.api import RangeSelection, RangeSelectionOverlay, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== # Do the plots use downsampling? use_downsampling = True + def _create_plot_component(use_downsampling=True): - container = OverlayPlotContainer(padding=40, bgcolor="lightgray", - use_backbuffer = True, - border_visible = True, - fill_padding = True) + container = OverlayPlotContainer( + padding=40, + bgcolor="lightgray", + use_backbuffer=True, + border_visible=True, + fill_padding=True, + ) numpoints = 100000 low = -5 high = 15.0 - x = arange(low, high+0.001, (high-low)/numpoints) + x = arange(low, high + 0.001, (high - low) / numpoints) # Plot some bessel functionsless ../en value_mapper = None index_mapper = None for i in range(10): y = jn(i, x) - plot = create_line_plot((x,y), color=tuple(COLOR_PALETTE[i]), width=2.0) + plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[i]), width=2.0) plot.use_downsampling = use_downsampling if value_mapper is None: @@ -62,12 +71,12 @@ def _create_plot_component(use_downsampling=True): value_mapper.range.add(plot.value) plot.index_mapper = index_mapper index_mapper.range.add(plot.index) - if i%2 == 1: + if i % 2 == 1: plot.line_style = "dash" plot.bgcolor = "white" container.add(plot) - selection_overlay = RangeSelectionOverlay(component = plot) + selection_overlay = RangeSelectionOverlay(component=plot) plot.tools.append(RangeSelection(plot)) zoom = ZoomTool(plot, tool_mode="box", always_on=False) plot.overlays.append(selection_overlay) @@ -75,26 +84,27 @@ def _create_plot_component(use_downsampling=True): return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. size = (600, 500) title = "Million Point Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) use_downsampling = Bool(True) traits_view = View( - UItem('plot', editor=ComponentEditor()), - Group(Item('use_downsampling')), + UItem("plot", editor=ComponentEditor()), + Group(Item("use_downsampling")), width=size[0], height=size[1], resizable=True, - title=title + title=title, ) def _plot_default(self): @@ -103,6 +113,7 @@ def _plot_default(self): def _use_downsampling_changed(self): self.plot = _create_plot_component(self.use_downsampling) + demo = Demo() if __name__ == "__main__": diff --git a/examples/demo/canvas/axis_tool.py b/examples/demo/canvas/axis_tool.py index 070b79e80..12fa84700 100644 --- a/examples/demo/canvas/axis_tool.py +++ b/examples/demo/canvas/axis_tool.py @@ -1,7 +1,7 @@ - from enable.api import BaseTool, ColorTrait from traits.api import Any, Bool, Dict, Enum, HasTraits, Int, List, Trait, Tuple + class RangeController(HasTraits): canvas = Any @@ -63,8 +63,14 @@ class AxisTool(BaseTool): _cached_border_visible = Bool(True) _cached_border_color = ColorTrait - attr_list = ("tick_color", "axis_line_color", "tick_label_color", "bgcolor", - "border_visible", "border_color") + attr_list = ( + "tick_color", + "axis_line_color", + "tick_label_color", + "bgcolor", + "border_visible", + "border_color", + ) def normal_left_down(self, event): if self.component is None: @@ -132,8 +138,7 @@ def normal_blob_down(self, event): if self.cur_bid == -1: self.cur_bid = event.bid if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, - event.net_transform()) + event.window.capture_blob(self, event.bid, event.net_transform()) self.normal_left_down(event) self._last_blob_pos = (event.x, event.y) @@ -145,4 +150,3 @@ def normal_blob_up(self, event): self.cur_bid = -1 event.x, event.y = self._last_blob_pos self.normal_left_up(event) - diff --git a/examples/demo/canvas/canvas.py b/examples/demo/canvas/canvas.py index 6f01be573..ccebbbc7b 100644 --- a/examples/demo/canvas/canvas.py +++ b/examples/demo/canvas/canvas.py @@ -19,14 +19,19 @@ from enable.api import Viewport, Window from enable.tools.api import MoveTool, ResizeTool, ViewportPanTool from enable.example_support import DemoFrame, demo_main -from traits.api import Any, Bool, Enum, Float, HasTraits, Instance, \ - List, Str +from traits.api import Any, Bool, Enum, Float, HasTraits, Instance, List, Str # Chaco imports -from chaco.api import AbstractOverlay, ArrayPlotData, \ - Plot, ScatterPlot, LinePlot, LinearMapper -from chaco.tools.api import PanTool, ZoomTool , LegendTool +from chaco.api import ( + AbstractOverlay, + ArrayPlotData, + Plot, + ScatterPlot, + LinePlot, + LinearMapper, +) +from chaco.tools.api import PanTool, ZoomTool, LegendTool # Canvas imports from chaco.plot_canvas import PlotCanvas @@ -37,13 +42,14 @@ from data_source_button import ButtonController, DataSourceButton from mp_move_tool import MPMoveTool from mp_viewport_pan_tool import MPViewportPanTool -#from canvas_grid import CanvasGrid + +# from canvas_grid import CanvasGrid # Multitouch imports if MULTITOUCH: - from mptools import MPPanTool, MPDragZoom, MPLegendTool, \ - MPPanZoom, MPRangeSelection - #AxisTool = MPAxisTool + from mptools import MPPanTool, MPDragZoom, MPLegendTool, MPPanZoom, MPRangeSelection + + # AxisTool = MPAxisTool PlotCloneTool = MPPlotCloneTool NUMPOINTS = 250 @@ -57,8 +63,7 @@ "ORCL": random.uniform(-2.0, 10.0, NUMPOINTS), "HPQ": random.uniform(-2.0, 10.0, NUMPOINTS), "DELL": random.uniform(-2.0, 10.0, NUMPOINTS), - } - +} def add_basic_tools(plot): @@ -67,41 +72,75 @@ def add_basic_tools(plot): zoom = ZoomTool(component=plot, tool_mode="box", always_on=False) plot.overlays.append(zoom) + def do_plot(name, pd): xname = name + "_x" yname = name + "_y" pd.set_data(xname, list(range(len(DATA[name])))) pd.set_data(yname, DATA[name]) - plot = Plot(pd, padding = 30, - unified_draw = True, - border_visible = True, - ) + plot = Plot( + pd, + padding=30, + unified_draw=True, + border_visible=True, + ) plot.x_axis.visible = False plot.title = name - plot.plot((xname, yname), name=name, type="line", color="blue",) + plot.plot( + (xname, yname), + name=name, + type="line", + color="blue", + ) return plot + def clone_renderer(r): """ Returns a clone of plot renderer r """ - basic_traits = ["orientation", "line_width", "color", "outline_color", - "bgcolor", "border_visible", "border_color", "visible", - "fill_padding", "resizable", "aspect_ratio", - "draw_layer", "draw_order", "border_width", "resizable", - "index", "value",] - - scatter_traits = ["custom_symbol", "marker", "marker_size", "selection_marker", - "selection_marker_size", "selection_line_width", - "selection_color"] - - line_traits = ["selected_color", "selected_line_style", "metadata_name", - "render_style"] + basic_traits = [ + "orientation", + "line_width", + "color", + "outline_color", + "bgcolor", + "border_visible", + "border_color", + "visible", + "fill_padding", + "resizable", + "aspect_ratio", + "draw_layer", + "draw_order", + "border_width", + "resizable", + "index", + "value", + ] + + scatter_traits = [ + "custom_symbol", + "marker", + "marker_size", + "selection_marker", + "selection_marker_size", + "selection_line_width", + "selection_color", + ] + + line_traits = [ + "selected_color", + "selected_line_style", + "metadata_name", + "render_style", + ] if isinstance(r, ScatterPlot): return r.clone_traits(basic_traits + scatter_traits) elif isinstance(r, LinePlot): return r.clone_traits(basic_traits + line_traits) + def clone_plot(clonetool, drop_position): # A little sketchy... canvas = clonetool.component.container.component.component @@ -109,10 +148,21 @@ def clone_plot(clonetool, drop_position): # Create a new Plot object oldplot = clonetool.component newplot = Plot(oldplot.data) - basic_traits = ["orientation", "default_origin", "bgcolor", "border_color", - "border_width", "border_visible", "draw_layer", "unified_draw", - "fit_components", "fill_padding", "visible", "aspect_ratio", - "title"] + basic_traits = [ + "orientation", + "default_origin", + "bgcolor", + "border_color", + "border_width", + "border_visible", + "draw_layer", + "unified_draw", + "fit_components", + "fill_padding", + "visible", + "aspect_ratio", + "title", + ] for attr in basic_traits: setattr(newplot, attr, getattr(oldplot, attr)) @@ -120,7 +170,7 @@ def clone_plot(clonetool, drop_position): # copy the ranges dst = newplot.range2d src = oldplot.range2d - #for attr in ('_low_setting', '_low_value', '_high_setting', '_high_value'): + # for attr in ('_low_setting', '_low_value', '_high_setting', '_high_value'): # setattr(dst, attr, getattr(src, attr)) dst._xrange.sources = copy(src._xrange.sources) dst._yrange.sources = copy(src._yrange.sources) @@ -143,7 +193,7 @@ def clone_plot(clonetool, drop_position): new_r.resizable = "hv" newrenderers.append(new_r) newplot.plots[name] = newrenderers - #newplot.plots = copy(oldplot.plots) + # newplot.plots = copy(oldplot.plots) for name, renderers in list(newplot.plots.items()): newplot.add(*renderers) @@ -154,18 +204,44 @@ def clone_plot(clonetool, drop_position): newplot.value_axis.unified_draw = True # Add new tools to the new plot - newplot.tools.append(AxisTool(component=newplot, - range_controller=canvas.range_controller)) + newplot.tools.append( + AxisTool(component=newplot, range_controller=canvas.range_controller) + ) # Add tools to the new plot - pan_traits = ["drag_button", "constrain", "constrain_key", "constrain_direction", - "speed"] - zoom_traits = ["tool_mode", "always_on", "axis", "enable_wheel", "drag_button", - "wheel_zoom_step", "enter_zoom_key", "exit_zoom_key", "pointer", - "color", "alpha", "border_color", "border_size", "disable_on_complete", - "minimum_screen_delta", "max_zoom_in_factor", "max_zoom_out_factor"] - move_traits = ["drag_button", "end_drag_on_leave", "cancel_keys", "capture_mouse", - "modifier_key"] + pan_traits = [ + "drag_button", + "constrain", + "constrain_key", + "constrain_direction", + "speed", + ] + zoom_traits = [ + "tool_mode", + "always_on", + "axis", + "enable_wheel", + "drag_button", + "wheel_zoom_step", + "enter_zoom_key", + "exit_zoom_key", + "pointer", + "color", + "alpha", + "border_color", + "border_size", + "disable_on_complete", + "minimum_screen_delta", + "max_zoom_in_factor", + "max_zoom_out_factor", + ] + move_traits = [ + "drag_button", + "end_drag_on_leave", + "cancel_keys", + "capture_mouse", + "modifier_key", + ] if not MULTITOUCH: for tool in oldplot.tools: @@ -200,12 +276,12 @@ def clone_plot(clonetool, drop_position): else: pz = MPPanZoom(newplot) - #pz.pan.constrain = True - #pz.pan.constrain_direction = "x" - #pz.zoom.mode = "range" - #pz.zoom.axis = "index" + # pz.pan.constrain = True + # pz.pan.constrain_direction = "x" + # pz.zoom.mode = "range" + # pz.zoom.axis = "index" newplot.tools.append(MPPanZoom(newplot)) - #newplot.tools.append(MTMoveTool( + # newplot.tools.append(MTMoveTool( newplot._layout_needed = True @@ -217,33 +293,37 @@ def clone_plot(clonetool, drop_position): def make_toolbar(canvas): # Create the toolbar - toolbar = PlotCanvasToolbar(bounds=[70, 200], - position=[50,350], - fill_padding=True, - bgcolor="lightgrey", - padding = 5, - align = "left", - ) + toolbar = PlotCanvasToolbar( + bounds=[70, 200], + position=[50, 350], + fill_padding=True, + bgcolor="lightgrey", + padding=5, + align="left", + ) # Create the scatterplot pd = ArrayPlotData() - scatterplot = Plot(pd, padding=15, bgcolor="white", unified_draw=True, - border_visible=True) + scatterplot = Plot( + pd, padding=15, bgcolor="white", unified_draw=True, border_visible=True + ) if not MULTITOUCH: scatterplot.tools.append(PanTool(scatterplot, drag_button="right")) scatterplot.tools.append(ZoomTool(scatterplot)) else: scatterplot.tools.append(MPPanZoom(scatterplot)) - scatterplot.overlays.append(PlotCloneTool(scatterplot, dest=canvas, - plot_cloner=clone_plot)) + scatterplot.overlays.append( + PlotCloneTool(scatterplot, dest=canvas, plot_cloner=clone_plot) + ) # Create the overlay - overlay = TransientPlotOverlay(component=toolbar, - overlay_component=scatterplot, - bounds=[350,350], - border_visible=True, - visible = False, # initially invisible - ) + overlay = TransientPlotOverlay( + component=toolbar, + overlay_component=scatterplot, + bounds=[350, 350], + border_visible=True, + visible=False, # initially invisible + ) scatterplot.container = overlay # Create buttons @@ -253,25 +333,31 @@ def make_toolbar(canvas): if MULTITOUCH: plot.tools.append(MPPanZoom(plot)) else: - plot.tools.append(PanTool(plot, drag_button="right", constrain=True, - constrain_direction="x")) - plot.tools.append(ZoomTool(plot, tool_mode="range", axis="index", - always_on=False)) - plot.overlays.append(PlotCloneTool(plot, dest=canvas, - plot_cloner=clone_plot)) - plot_overlay = TransientPlotOverlay(component=toolbar, - overlay_component=plot, - border_visible=True, - visible=False, - ) + plot.tools.append( + PanTool( + plot, drag_button="right", constrain=True, constrain_direction="x" + ) + ) + plot.tools.append( + ZoomTool(plot, tool_mode="range", axis="index", always_on=False) + ) + plot.overlays.append(PlotCloneTool(plot, dest=canvas, plot_cloner=clone_plot)) + plot_overlay = TransientPlotOverlay( + component=toolbar, + overlay_component=plot, + border_visible=True, + visible=False, + ) plot.container = plot_overlay - button = DataSourceButton(label=name, - bounds=[80,46], - padding = 5, - button_controller = controller, - #canvas = canvas, - plot_overlay = plot_overlay, - plotname = name) + button = DataSourceButton( + label=name, + bounds=[80, 46], + padding=5, + button_controller=controller, + # canvas = canvas, + plot_overlay=plot_overlay, + plotname=name, + ) toolbar.add(button) canvas.overlays.append(plot_overlay) controller.plot = scatterplot @@ -282,11 +368,10 @@ def make_toolbar(canvas): class PlotFrame(DemoFrame): - def _create_viewport(self): # Create a container and add our plots canvas = PlotCanvas() - canvas.range_controller = RangeController(cavas = canvas) + canvas.range_controller = RangeController(cavas=canvas) toolbar = make_toolbar(canvas) toolbar.component = canvas @@ -305,6 +390,7 @@ def _create_window_mt(self): from enactable.configuration import arg_parser, get_global_config from enactable.enable.enable_blob_listener import BlobWindow from enactable.enable.blobprovider import NetworkBlobProvider + parser = arg_parser() args = parser.parse_args() cfg = get_global_config() @@ -325,7 +411,8 @@ def _create_window(self): else: return self._create_window_simple() + if __name__ == "__main__": # Save demo so that it doesn't get garbage collected when run within # existing event loop (i.e. from ipython). - demo = demo_main(PlotFrame, size=(1000,700), title="PlotCanvas") + demo = demo_main(PlotFrame, size=(1000, 700), title="PlotCanvas") diff --git a/examples/demo/canvas/cliptest.py b/examples/demo/canvas/cliptest.py index 779b4a35c..9fc1163e1 100644 --- a/examples/demo/canvas/cliptest.py +++ b/examples/demo/canvas/cliptest.py @@ -4,7 +4,6 @@ """ - # Enthought library imports from traits.api import Float from enable.api import Window, Container, Component, Pointer @@ -16,6 +15,7 @@ class Box(Component): """ The box moves wherever the user clicks and drags. """ + normal_pointer = Pointer("arrow") moving_pointer = Pointer("hand") @@ -40,9 +40,9 @@ def _draw_mainlayer(self, gc, view_bounds=None, mode="default"): gc.fill_path() ## draw line around outer box - #gc.set_stroke_color((0,0,0,1)) - #gc.rect(self.outer_x, self.outer_y, self.outer_width, self.outer_height) - #gc.stroke_path() + # gc.set_stroke_color((0,0,0,1)) + # gc.rect(self.outer_x, self.outer_y, self.outer_width, self.outer_height) + # gc.stroke_path() def normal_left_down(self, event): self.event_state = "moving" @@ -53,7 +53,7 @@ def normal_left_down(self, event): event.handled = True def moving_mouse_move(self, event): - self.position = [event.x-self.offset_x, event.y-self.offset_y] + self.position = [event.x - self.offset_x, event.y - self.offset_y] event.handled = True self.request_redraw() @@ -71,13 +71,15 @@ def moving_mouse_leave(self, event): class MainFrame(DemoFrame): def _create_window(self): - a = Box(bounds=[75, 75], position=[50,50], fill_color=(1, 0, 0, 1)) - b = Box(bounds=[75, 75], position=[200,50], fill_color=(0, 1, 0, 1)) - c = Box(bounds=[75, 75], position=[50,200], fill_color=(0, 0, 1, 1)) - cont = Container(a, b, c, bounds=[400,400], border_visible=True, bgcolor="lightgray") - #cont.unified_draw = True - #cont.draw_layer = "background" - cont2 = Container(bounds=[300,300], border_visible=True, bgcolor="cyan") + a = Box(bounds=[75, 75], position=[50, 50], fill_color=(1, 0, 0, 1)) + b = Box(bounds=[75, 75], position=[200, 50], fill_color=(0, 1, 0, 1)) + c = Box(bounds=[75, 75], position=[50, 200], fill_color=(0, 0, 1, 1)) + cont = Container( + a, b, c, bounds=[400, 400], border_visible=True, bgcolor="lightgray" + ) + # cont.unified_draw = True + # cont.draw_layer = "background" + cont2 = Container(bounds=[300, 300], border_visible=True, bgcolor="cyan") cont.tools.append(MoveTool(cont, drag_button="left")) cont2.tools.append(MoveTool(cont2, drag_button="left")) outer = Container(cont, cont2, fit_window=True) @@ -87,5 +89,4 @@ def _create_window(self): if __name__ == "__main__": # Save demo so that it doesn't get garbage collected when run within # existing event loop (i.e. from ipython). - demo = demo_main(MainFrame, size=(800,800), title="ClipTest") - + demo = demo_main(MainFrame, size=(800, 800), title="ClipTest") diff --git a/examples/demo/canvas/data_source_button.py b/examples/demo/canvas/data_source_button.py index 669446d36..237b7cdbd 100644 --- a/examples/demo/canvas/data_source_button.py +++ b/examples/demo/canvas/data_source_button.py @@ -1,5 +1,3 @@ - - from random import choice from traits.api import Any, Enum, HasTraits, Instance, Int, List, Str from chaco.example_support import COLOR_PALETTE @@ -8,8 +6,9 @@ DEBUG = False + class ButtonController(HasTraits): - """ Tells buttons what to do + """Tells buttons what to do Buttons defer to this when they are activated. """ @@ -30,11 +29,11 @@ class ButtonController(HasTraits): _scatterplot_name = "ButtonControllerPlot" def notify(self, button, type, event): - """ Informs the controller that the particular **button** just + """Informs the controller that the particular **button** just got an event. **Type** is either "up" or "down". Event is the actual mouse event. """ - #control_down = getattr(event, self.modifier + "_down", False) + # control_down = getattr(event, self.modifier + "_down", False) control_down = True if DEBUG: print("[notify]", button.plotname, type, "control:", control_down) @@ -44,11 +43,14 @@ def notify(self, button, type, event): else: if not control_down: # Deselect all current buttons and select the new one - [self.button_deselected(b) for b in self.active_buttons \ - if b is not button] + [ + self.button_deselected(b) + for b in self.active_buttons + if b is not button + ] self.button_selected(button) else: # type == "up" - #if not control_down: + # if not control_down: if 1: self.button_deselected(button) @@ -102,15 +104,16 @@ def show_scatterplot(self, b1, b2): if len(self.plot.plots) > 0: self.plot.delplot(*list(self.plot.plots.keys())) - cur_plot = self.plot.plot((b1.plotname+"_y", b2.plotname+"_y"), - name=self._scatterplot_name, - type="scatter", - marker="square", - color=tuple(choice(COLOR_PALETTE)), - marker_size=8, - ) + cur_plot = self.plot.plot( + (b1.plotname + "_y", b2.plotname + "_y"), + name=self._scatterplot_name, + type="scatter", + marker="square", + color=tuple(choice(COLOR_PALETTE)), + marker_size=8, + ) self.plot.index_axis.title = b1.plotname - #self.plot.value_axis.title = b2.plotname + # self.plot.value_axis.title = b2.plotname self.plot.title = b1.plotname + " vs. " + b2.plotname self.plot_overlay.visible = True self.plot.request_redraw() @@ -123,7 +126,6 @@ def hide_scatterplot(self): self.plot_overlay.visible = False - class DataSourceButton(PlotToolbarButton): # A TransientPlotOverlay containing the timeseries plot of this datasource @@ -133,20 +135,20 @@ class DataSourceButton(PlotToolbarButton): canvas = Any - #overlay_bounds = List() + # overlay_bounds = List() # Can't call this "controller" because it conflicts with old tool dispatch button_controller = Instance(ButtonController) # Override inherited trait - label_color = (0,0,0,1) + label_color = (0, 0, 0, 1) resizable = "" cur_bid = Int(-1) # The overlay to display when the user holds the mouse down over us. - #_overlay = Instance(AbstractOverlay) + # _overlay = Instance(AbstractOverlay) def normal_left_down(self, event): self.button_state = "down" @@ -165,8 +167,7 @@ def normal_blob_down(self, event): self.cur_bid = event.bid self.normal_left_down(event) if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, - event.net_transform()) + event.window.capture_blob(self, event.bid, event.net_transform()) def normal_blob_up(self, event): if event.bid == self.cur_bid: @@ -197,6 +198,8 @@ def hide_overlay(self): def _do_layout(self): if self.canvas is not None: boff = self.canvas.bounds_offset - self.plot_overlay.offset = (boff[0], - boff[1] + self.y - self.container.y + self.height/2) + self.plot_overlay.offset = ( + boff[0], + boff[1] + self.y - self.container.y + self.height / 2, + ) self.plot_overlay.do_layout() diff --git a/examples/demo/canvas/mp_move_tool.py b/examples/demo/canvas/mp_move_tool.py index 6acae6006..4194975e2 100644 --- a/examples/demo/canvas/mp_move_tool.py +++ b/examples/demo/canvas/mp_move_tool.py @@ -1,7 +1,7 @@ - from traits.api import Int from enable.tools.api import MoveTool + class MPMoveTool(MoveTool): cur_bid = Int(-1) @@ -15,6 +15,3 @@ def dragging_blob_up(self, event): if event.bid == self.cur_bid: self.cur_bid = -1 self.normal_left_up(event) - - - diff --git a/examples/demo/canvas/mp_viewport_pan_tool.py b/examples/demo/canvas/mp_viewport_pan_tool.py index 8789a3bf7..b302f2d9e 100644 --- a/examples/demo/canvas/mp_viewport_pan_tool.py +++ b/examples/demo/canvas/mp_viewport_pan_tool.py @@ -1,7 +1,7 @@ - from traits.api import Int, Tuple from enable.tools.api import ViewportPanTool + class MPViewportPanTool(ViewportPanTool): cur_bid = Int(-1) @@ -27,12 +27,11 @@ def drag_start(self, event): if self.component: self.original_padding = self.component.padding if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, - event.net_transform()) + event.window.capture_blob(self, event.bid, event.net_transform()) else: event.window.set_mouse_owner(self, event.net_transform()) self._last_blob_pos = (event.x, event.y) - self.mouse_down_position = (event.x,event.y) + self.mouse_down_position = (event.x, event.y) self.event_state = "dragging" event.handled = True ViewportPanTool.drag_start(self, event) @@ -43,4 +42,3 @@ def drag_end(self, event): event.window.release_blob(event.bid) self.event_state = "normal" ViewportPanTool.drag_end(self, event) - diff --git a/examples/demo/canvas/mptools.py b/examples/demo/canvas/mptools.py index 4225ae0a9..c81dcef90 100644 --- a/examples/demo/canvas/mptools.py +++ b/examples/demo/canvas/mptools.py @@ -4,7 +4,17 @@ from numpy import asarray, dot, sqrt # Enthought library imports -from traits.api import Delegate, Dict, Enum, Instance, Int, Property, Trait, Tuple, CArray +from traits.api import ( + Delegate, + Dict, + Enum, + Instance, + Int, + Property, + Trait, + Tuple, + CArray, +) # Chaco imports from chaco.api import BaseTool @@ -13,8 +23,10 @@ BOGUS_BLOB_ID = -1 + def l2norm(v): - return sqrt(dot(v,v)) + return sqrt(dot(v, v)) + class MPPanTool(PanTool): cur_bid = Int(BOGUS_BLOB_ID) @@ -35,7 +47,7 @@ def panning_blob_move(self, event): self._dispatch_stateful_event(event, "mouse_move") def panning_mouse_leave(self, event): - """ Handles the mouse leaving the plot when the tool is in the 'panning' + """Handles the mouse leaving the plot when the tool is in the 'panning' state. Don't end panning. @@ -53,8 +65,8 @@ class MPDragZoom(DragZoom): speed = 1.0 # The original dataspace points where blobs 1 and 2 went down - _orig_low = CArray #Trait(None, None, Tuple) - _orig_high = CArray #Trait(None, None, Tuple) + _orig_low = CArray # Trait(None, None, Tuple) + _orig_high = CArray # Trait(None, None, Tuple) # Dataspace center of the zoom action _center_pt = Trait(None, None, Tuple) @@ -71,13 +83,13 @@ class MPDragZoom(DragZoom): _axis_moves = Property(Dict) def _convert_to_axis(self, d): - """ Convert a mapping of ID to (x,y) tuple to a mapping of ID to just + """Convert a mapping of ID to (x,y) tuple to a mapping of ID to just the coordinate appropriate for the selected axis. """ - if self.axis == 'index': + if self.axis == "index": idx = self.axis_index else: - idx = 1-self.axis_index + idx = 1 - self.axis_index d2 = {} for id, coords in list(d.items()): d2[id] = coords[idx] @@ -92,16 +104,20 @@ def _get__axis_moves(self): def drag_start(self, event, capture_mouse=False): bid1, bid2 = sorted(self._moves) xy01, xy02 = self._moves[bid1], self._moves[bid2] - self._orig_low, self._orig_high = list(map(asarray, - self._map_coordinate_box(xy01, xy02))) + self._orig_low, self._orig_high = list( + map(asarray, self._map_coordinate_box(xy01, xy02)) + ) self.orig_center = (self._orig_high + self._orig_low) / 2.0 self.orig_diag = l2norm(self._orig_high - self._orig_low) - #DragZoom.drag_start(self, event, capture_mouse) + # DragZoom.drag_start(self, event, capture_mouse) self._original_xy = xy02 c = self.component - self._orig_screen_bounds = ((c.x,c.y), (c.x2,c.y2)) - self._original_data = (c.x_mapper.map_data(xy02[0]), c.y_mapper.map_data(xy02[1])) + self._orig_screen_bounds = ((c.x, c.y), (c.x2, c.y2)) + self._original_data = ( + c.x_mapper.map_data(xy02[0]), + c.y_mapper.map_data(xy02[1]), + ) self._prev_y = xy02[1] if capture_mouse: event.window.set_pointer(self.drag_pointer) @@ -109,8 +125,7 @@ def drag_start(self, event, capture_mouse=False): def normal_blob_down(self, event): if len(self._blobs) < 2: self._blobs[event.bid] = (event.x, event.y) - event.window.capture_blob(self, event.bid, - transform=event.net_transform()) + event.window.capture_blob(self, event.bid, transform=event.net_transform()) event.handled = True def normal_blob_up(self, event): @@ -144,14 +159,16 @@ def dragging_blob_frame_end(self, event): zoom = self.speed * self.orig_diag / diag # The original screen bounds are used to test if we've reached max_zoom - orig_screen_low, orig_screen_high = \ - list(map(asarray, self._map_coordinate_box(*self._orig_screen_bounds))) + orig_screen_low, orig_screen_high = list( + map(asarray, self._map_coordinate_box(*self._orig_screen_bounds)) + ) new_low = center - zoom * (center - orig_screen_low) - translation new_high = center + zoom * (orig_screen_high - center) - translation - for ndx in (0,1): - if self._zoom_limit_reached(orig_screen_low[ndx], - orig_screen_high[ndx], new_low[ndx], new_high[ndx]): + for ndx in (0, 1): + if self._zoom_limit_reached( + orig_screen_low[ndx], orig_screen_high[ndx], new_low[ndx], new_high[ndx] + ): return c = self.component @@ -180,7 +197,7 @@ def _handle_blob_leave(self, event): class MPPanZoom(BaseTool): - """ This tool wraps a pan and a zoom tool, and automatically switches + """This tool wraps a pan and a zoom tool, and automatically switches behavior back and forth depending on how many blobs are tracked on screen. """ @@ -191,24 +208,24 @@ class MPPanZoom(BaseTool): event_state = Enum("normal", "pan", "zoom") - _blobs = Delegate('zoom') - _moves = Delegate('zoom') + _blobs = Delegate("zoom") + _moves = Delegate("zoom") def _dispatch_stateful_event(self, event, suffix): self.zoom.dispatch(event, suffix) event.handled = False self.pan.dispatch(event, suffix) if len(self._blobs) == 2: - self.event_state = 'zoom' + self.event_state = "zoom" elif len(self._blobs) == 1: - self.event_state = 'pan' + self.event_state = "pan" elif len(self._blobs) == 0: - self.event_state = 'normal' + self.event_state = "normal" else: assert len(self._blobs) <= 2 - if suffix == 'blob_up': + if suffix == "blob_up": event.window.release_blob(event.bid) - elif suffix == 'blob_down': + elif suffix == "blob_down": event.window.release_blob(event.bid) event.window.capture_blob(self, event.bid, event.net_transform()) event.handled = True @@ -248,11 +265,10 @@ def drag_start(self, event): if self.component: self.original_padding = self.component.padding if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, - event.net_transform()) + event.window.capture_blob(self, event.bid, event.net_transform()) else: event.window.set_mouse_owner(self, event.net_transform()) - self.mouse_down_position = (event.x,event.y) + self.mouse_down_position = (event.x, event.y) self.event_state = "dragging" event.handled = True @@ -263,7 +279,6 @@ def drag_end(self, event): LegendTool.drag_end(self, event) - class MPRangeSelection(RangeSelection): # Maps blob ID numbers to the (x,y) coordinates that came in. @@ -278,13 +293,13 @@ class MPRangeSelection(RangeSelection): _axis_moves = Property(Dict) def _convert_to_axis(self, d): - """ Convert a mapping of ID to (x,y) tuple to a mapping of ID to just + """Convert a mapping of ID to (x,y) tuple to a mapping of ID to just the coordinate appropriate for the selected axis. """ - if self.axis == 'index': + if self.axis == "index": idx = self.axis_index else: - idx = 1-self.axis_index + idx = 1 - self.axis_index d2 = {} for id, coords in list(d.items()): d2[id] = coords[idx] @@ -299,8 +314,7 @@ def _get__axis_moves(self): def normal_blob_down(self, event): if len(self._blobs) < 2: self._blobs[event.bid] = (event.x, event.y) - event.window.capture_blob(self, event.bid, - transform=event.net_transform()) + event.window.capture_blob(self, event.bid, transform=event.net_transform()) event.handled = True def normal_blob_up(self, event): @@ -309,8 +323,8 @@ def normal_blob_up(self, event): def normal_blob_frame_end(self, event): if len(self._blobs) == 2: self.event_state = "selecting" - #self.drag_start(event, capture_mouse=False) - #self.selecting_mouse_move(event) + # self.drag_start(event, capture_mouse=False) + # self.selecting_mouse_move(event) self._set_sizing_cursor(event) self.selection = sorted(self._axis_blobs.values()) @@ -344,13 +358,12 @@ def selecting_blob_frame_end(self, event): if low <= m0 <= high: m1 = self.mapper.map_data(self._axis_blobs[id]) dm = m1 - m0 - self.selection = (low+dm, high+dm) + self.selection = (low + dm, high + dm) def selected_blob_down(self, event): if len(self._blobs) < 2: self._blobs[event.bid] = (event.x, event.y) - event.window.capture_blob(self, event.bid, - transform=event.net_transform()) + event.window.capture_blob(self, event.bid, transform=event.net_transform()) event.handled = True def selected_blob_move(self, event): @@ -375,4 +388,3 @@ def _handle_blob_leave(self, event): if len(self._blobs) < 2: self.event_state = "selected" - diff --git a/examples/demo/canvas/plot_clone_tool.py b/examples/demo/canvas/plot_clone_tool.py index d28a693aa..a5371a869 100644 --- a/examples/demo/canvas/plot_clone_tool.py +++ b/examples/demo/canvas/plot_clone_tool.py @@ -3,7 +3,6 @@ """ - # Enthought library imports from traits.api import Bool, Callable, Enum, Float, Instance, Int, Trait, Tuple from enable.api import Container @@ -14,7 +13,7 @@ class PlotCloneTool(AbstractOverlay, DragTool): - """ On a drag operation, draws an overlay of self.component underneath + """On a drag operation, draws an overlay of self.component underneath the cursor. On drag_end, a copy of the plot is dropped onto the self.dest container. """ @@ -50,8 +49,9 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): if self._recursion_check: return else: - if self._offset is not None and (self._offset[0] > 10 or - self._offset[1] > 10): + if self._offset is not None and ( + self._offset[0] > 10 or self._offset[1] > 10 + ): with gc: gc.clear_clip_path() gc.translate_ctm(*self._offset) @@ -61,20 +61,26 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): self._recursion_check = False def drag_start(self, event): - """ Called when the drag operation starts. + """Called when the drag operation starts. Implements DragTool. """ - self._offset = (event.x - self.mouse_down_position[0], - event.y - self.mouse_down_position[1]) - self._offset_from_plot = (self.mouse_down_position[0] - self.component.x, - self.mouse_down_position[1] - self.component.y) + self._offset = ( + event.x - self.mouse_down_position[0], + event.y - self.mouse_down_position[1], + ) + self._offset_from_plot = ( + self.mouse_down_position[0] - self.component.x, + self.mouse_down_position[1] - self.component.y, + ) self.visible = True event.handled = True def dragging(self, event): - self._offset = (event.x - self.mouse_down_position[0], - event.y - self.mouse_down_position[1]) + self._offset = ( + event.x - self.mouse_down_position[0], + event.y - self.mouse_down_position[1], + ) self.component.request_redraw() def drag_end(self, event): @@ -114,11 +120,10 @@ def drag_start(self, event): if self.component: self.original_padding = self.component.padding if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, - event.net_transform()) + event.window.capture_blob(self, event.bid, event.net_transform()) else: event.window.set_mouse_owner(self, event.net_transform()) - self.mouse_down_position = (event.x,event.y) + self.mouse_down_position = (event.x, event.y) self.event_state = "dragging" event.handled = True PlotCloneTool.drag_start(self, event) @@ -131,6 +136,7 @@ def drag_end(self, event): offset = self._offset_from_plot drop_position = self._last_blob_pos if len(drop_position) == 2: - self.plot_cloner(self, (drop_position[0] - offset[0], - drop_position[1] - offset[1])) + self.plot_cloner( + self, (drop_position[0] - offset[0], drop_position[1] - offset[1]) + ) self._offset = None diff --git a/examples/demo/canvas/transient_plot_overlay.py b/examples/demo/canvas/transient_plot_overlay.py index 42abf7b23..4b8cf4012 100644 --- a/examples/demo/canvas/transient_plot_overlay.py +++ b/examples/demo/canvas/transient_plot_overlay.py @@ -1,6 +1,3 @@ - - - from enable.api import Component from traits.api import Enum, Float, Instance, Trait, Tuple @@ -8,8 +5,7 @@ class TransientPlotOverlay(BasePlotContainer, AbstractOverlay): - """ Allows an arbitrary plot component to be overlaid on top of another one. - """ + """Allows an arbitrary plot component to be overlaid on top of another one.""" # The PlotComponent to draw as an overlay overlay_component = Instance(Component) @@ -34,9 +30,9 @@ def _bounds_default(self): def _clear_bounds(self, gc, view_bounds): if view_bounds is None: - view_bounds = (0,0, self.width, self.height) + view_bounds = (0, 0, self.width, self.height) gc.clip_to_rect(*view_bounds) - gc.set_fill_color((1.0,1.0,1.0,1.0)) + gc.set_fill_color((1.0, 1.0, 1.0, 1.0)) gc.begin_path() gc.rect(*view_bounds) gc.fill_path() @@ -48,7 +44,7 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): self.overlay_component._draw(gc, view_bounds, mode) # TODO: Implement this more intelligently than the one in BasePlotContainer - #def get_preferred_size(self): + # def get_preferred_size(self): # pass def _do_layout(self): @@ -56,14 +52,14 @@ def _do_layout(self): bounds = self.outer_bounds if self.align in ("right", "left"): - y = component.outer_y -(bounds[1] - component.outer_height) / 2 + y = component.outer_y - (bounds[1] - component.outer_height) / 2 if self.align == "right": x = component.outer_x2 + self.margin else: x = component.outer_x - bounds[0] - self.margin - else: # "top", "bottom" - x = component.outer_x -(bounds[0] - component.outer_width) / 2 + else: # "top", "bottom" + x = component.outer_x - (bounds[0] - component.outer_width) / 2 if self.align == "top": y = component.outer_y2 + self.margin else: @@ -82,5 +78,3 @@ def _do_layout(self): def dispatch(self, event, suffix): if self.visible and self.overlay_component.is_in(event.x, event.y): return self.overlay_component.dispatch(event, suffix) - - diff --git a/examples/demo/chaco_trait_editor.py b/examples/demo/chaco_trait_editor.py index c417356a3..6eded502d 100644 --- a/examples/demo/chaco_trait_editor.py +++ b/examples/demo/chaco_trait_editor.py @@ -5,7 +5,8 @@ from traits.etsconfig.api import ETSConfig -if ETSConfig.toolkit == 'wx': + +if ETSConfig.toolkit == "wx": from traitsui.wx.editor import Editor else: from traitsui.qt4.editor import Editor @@ -15,8 +16,7 @@ from enable.window import Window from enable.api import ColorTrait -from chaco.api import OverlayPlotContainer, create_line_plot, \ - LinePlot +from chaco.api import OverlayPlotContainer, create_line_plot, LinePlot from chaco.tools.api import RangeSelection, RangeSelectionOverlay from traits.api import Int, TraitType, Instance, Float @@ -25,9 +25,8 @@ class Interval(TraitType): - """Trait that represents an interval. + """Trait that represents an interval.""" - """ info_text = "an interval (x,y) where x < y" def __init__(self, low=0, high=1, **metadata): @@ -54,11 +53,17 @@ class IntervalEditorFactory(EditorFactory): def simple_editor(self, ui, object, name, description, parent): trait = object.trait(name).trait_type low, high = trait.value - return IntervalEditorImpl(parent, factory=self, ui=ui, - object=object, name=name, - description=description, - low=low, - high=high) + return IntervalEditorImpl( + parent, + factory=self, + ui=ui, + object=object, + name=name, + description=description, + low=low, + high=high, + ) + class RangeKnobsOverlay(RangeSelectionOverlay): radius = Float(3) @@ -71,7 +76,7 @@ class RangeKnobsOverlay(RangeSelectionOverlay): border_color = ColorTrait("black") def overlay(self, component, gc, view_bounds=None, mode="normal"): - mid_y = component.position[1] + component.bounds[1]/2 + mid_y = component.position[1] + component.bounds[1] / 2 # Draw each of a possibly disjoint set of selections coords = self._get_selection_screencoords() for coord in coords: @@ -81,8 +86,9 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): gc.set_stroke_color(self.border_color_) gc.set_line_width(self.border_width) - gc.rect(start + self.radius, mid_y - 1, - (end - start - 2*self.radius), 2) + gc.rect( + start + self.radius, mid_y - 1, (end - start - 2 * self.radius), 2 + ) gc.draw_path() gc.set_fill_color(self.low_color_) @@ -98,7 +104,7 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): def _circle(self, gc, x, y, radius): with gc: gc.translate_ctm(x, y) - gc.arc(0, 0, 2*radius, 0, 2*pi) + gc.arc(0, 0, 2 * radius, 0, 2 * pi) class IntervalEditorImpl(Editor): @@ -108,16 +114,15 @@ class IntervalEditorImpl(Editor): def init(self, parent): factory = self.factory - container = OverlayPlotContainer(bgcolor='transparent', - padding=0, spacing=0) + container = OverlayPlotContainer(bgcolor="transparent", padding=0, spacing=0) window = Window(parent, component=container) interval = self.high - self.low - data = ([self.low, self.high], [0.5]*2) - plot = create_line_plot(data, color='black', bgcolor="sys_window") - plot.x_mapper.range.low = self.low - interval*0.1 - plot.x_mapper.range.high = self.high + interval*0.1 + data = ([self.low, self.high], [0.5] * 2) + plot = create_line_plot(data, color="black", bgcolor="sys_window") + plot.x_mapper.range.low = self.low - interval * 0.1 + plot.x_mapper.range.high = self.high + interval * 0.1 plot.y_mapper.range.high = 1.0 plot.y_mapper.range.low = 0.0 @@ -125,7 +130,7 @@ def init(self, parent): # Do not allow the user to reset the range range_selection.event_state = "selected" range_selection.deselect = lambda x: None - range_selection.observe(self.update_interval, 'selection') + range_selection.observe(self.update_interval, "selection") plot.tools.append(range_selection) plot.overlays.append(RangeKnobsOverlay(plot)) @@ -138,7 +143,7 @@ def init(self, parent): # Tell the editor what to display self.control = window.control - if ETSConfig.toolkit == 'wx': + if ETSConfig.toolkit == "wx": self.control.SetSize((factory.width, factory.height)) else: self.control.setMaximumSize(factory.width, factory.height) @@ -150,12 +155,13 @@ def update_interval(self, event): low = max(low, 0) high = min(high, 1) - self.plot.index.metadata['selections'] = (low, high) + self.plot.index.metadata["selections"] = (low, high) self.value = (low, high) def update_editor(self): pass + # The user normally uses the factory as if it were an editor, e.g.: # # View(Item('interval', editor=IntervalEditor())) @@ -163,19 +169,16 @@ def update_editor(self): IntervalEditor = IntervalEditorFactory - # --- Demonstration --- if __name__ == "__main__": from traits.api import HasTraits from traitsui.api import View, Item + class IntervalTest(HasTraits): interval = Interval(low=0, high=1) - traits_view = View(Item('interval', - editor=IntervalEditor() - ), - resizable=True) + traits_view = View(Item("interval", editor=IntervalEditor()), resizable=True) it = IntervalTest() it.configure_traits() diff --git a/examples/demo/coordinate_line_overlay_demo.py b/examples/demo/coordinate_line_overlay_demo.py index 73399ad18..debd059ca 100644 --- a/examples/demo/coordinate_line_overlay_demo.py +++ b/examples/demo/coordinate_line_overlay_demo.py @@ -39,18 +39,19 @@ class PlotExample(HasTraits): line_overlay1 = Instance(CoordinateLineOverlay) line_overlay2 = Instance(CoordinateLineOverlay) - traits_view = \ - View( - HGroup( - UItem('time_plot', editor=ComponentEditor(height=20)), - ), - title="Demo", - width=1000, height=640, resizable=True, - ) - - #------------------------------------------------------------------------ + traits_view = View( + HGroup( + UItem("time_plot", editor=ComponentEditor(height=20)), + ), + title="Demo", + width=1000, + height=640, + resizable=True, + ) + + # ------------------------------------------------------------------------ # Trait change handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _x1_changed(self): self.line_overlay1.index_data = self.x1 @@ -64,9 +65,9 @@ def _x2_changed(self): def _y2_changed(self): self.line_overlay2.value_data = self.y2 - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait defaults - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _x1_default(self): return np.array([1.8, 8.4]) @@ -79,37 +80,44 @@ def _y2_default(self): def _time_plot_data_default(self): t = np.linspace(0, 10, 201) - y = (0.5 * t + 0.1 * np.sin(0.4 * 2 * np.pi * t) + - 0.3 * (t + 2) * (8 - t) * np.cos(0.33 * 2 * np.pi * t)) + y = ( + 0.5 * t + + 0.1 * np.sin(0.4 * 2 * np.pi * t) + + 0.3 * (t + 2) * (8 - t) * np.cos(0.33 * 2 * np.pi * t) + ) data = ArrayPlotData(t=t, y=y) return data def _time_plot_default(self): time_plot = Plot(self.time_plot_data) - time_plot.plot(('t', 'y')) + time_plot.plot(("t", "y")) time_plot.index_axis.title = "Time" time_plot.tools.append(PanTool(time_plot)) - zoomtool = ZoomTool(time_plot, drag_button='right', - always_on=True) + zoomtool = ZoomTool(time_plot, drag_button="right", always_on=True) time_plot.overlays.append(zoomtool) - lines1 = CoordinateLineOverlay(component=time_plot, - index_data=self.x1, - value_data=self.y1, - color=(0.75, 0.25, 0.25, 0.75), - line_style='dash', line_width=1) + lines1 = CoordinateLineOverlay( + component=time_plot, + index_data=self.x1, + value_data=self.y1, + color=(0.75, 0.25, 0.25, 0.75), + line_style="dash", + line_width=1, + ) time_plot.underlays.append(lines1) self.line_overlay1 = lines1 - lines2 = CoordinateLineOverlay(component=time_plot, - index_data=self.x2, - value_data=self.y2, - color=(0.2, 0.5, 1.0, 0.75), - line_width=3) + lines2 = CoordinateLineOverlay( + component=time_plot, + index_data=self.x2, + value_data=self.y2, + color=(0.2, 0.5, 1.0, 0.75), + line_width=3, + ) time_plot.underlays.append(lines2) self.line_overlay2 = lines2 diff --git a/examples/demo/cursor_tool_demo.py b/examples/demo/cursor_tool_demo.py index aa54eb04a..9d65adcc5 100644 --- a/examples/demo/cursor_tool_demo.py +++ b/examples/demo/cursor_tool_demo.py @@ -13,8 +13,14 @@ import numpy # Enthought library imports -from chaco.api import create_line_plot, OverlayPlotContainer, \ - HPlotContainer, Plot, ArrayPlotData, viridis +from chaco.api import ( + create_line_plot, + OverlayPlotContainer, + HPlotContainer, + Plot, + ArrayPlotData, + viridis, +) from chaco.tools.api import PanTool, ZoomTool from chaco.tools.cursor_tool import CursorTool, BaseCursorTool from enable.component_editor import ComponentEditor @@ -27,100 +33,105 @@ class CursorTest(HasTraits): cursor1 = Instance(BaseCursorTool) cursor2 = Instance(BaseCursorTool) - cursor1pos = DelegatesTo('cursor1', prefix='current_position') - cursor2pos = DelegatesTo('cursor2', prefix='current_position') + cursor1pos = DelegatesTo("cursor1", prefix="current_position") + cursor2pos = DelegatesTo("cursor2", prefix="current_position") def __init__(self): - #The delegates views don't work unless we caller the superclass __init__ + # The delegates views don't work unless we caller the superclass __init__ super(CursorTest, self).__init__() container = HPlotContainer(padding=0, spacing=20) self.plot = container - #a subcontainer for the first plot. - #I'm not sure why this is required. Without it, the layout doesn't work right. + # a subcontainer for the first plot. + # I'm not sure why this is required. Without it, the layout doesn't work right. subcontainer = OverlayPlotContainer(padding=40) container.add(subcontainer) - #make some data - index = numpy.linspace(-10,10,512) + # make some data + index = numpy.linspace(-10, 10, 512) value = numpy.sin(index) - #create a LinePlot instance and add it to the subcontainer - line = create_line_plot([index, value], add_grid=True, - add_axis=True, index_sort='ascending', - orientation = 'h') + # create a LinePlot instance and add it to the subcontainer + line = create_line_plot( + [index, value], + add_grid=True, + add_axis=True, + index_sort="ascending", + orientation="h", + ) subcontainer.add(line) - #here's our first cursor. - csr = CursorTool(line, - drag_button="left", - color='blue') + # here's our first cursor. + csr = CursorTool(line, drag_button="left", color="blue") self.cursor1 = csr - #and set it's initial position (in data-space units) + # and set it's initial position (in data-space units) csr.current_position = 0.0, 0.0 - #this is a rendered component so it goes in the overlays list + # this is a rendered component so it goes in the overlays list line.overlays.append(csr) - #some other standard tools + # some other standard tools line.tools.append(PanTool(line, drag_button="right")) line.overlays.append(ZoomTool(line)) - #make some 2D data for a colourmap plot + # make some 2D data for a colourmap plot xy_range = (-5, 5) - x = numpy.linspace(xy_range[0], xy_range[1] ,100) - y = numpy.linspace(xy_range[0], xy_range[1] ,100) - X,Y = numpy.meshgrid(x, y) - Z = numpy.sin(X)*numpy.arctan2(Y,X) + x = numpy.linspace(xy_range[0], xy_range[1], 100) + y = numpy.linspace(xy_range[0], xy_range[1], 100) + X, Y = numpy.meshgrid(x, y) + Z = numpy.sin(X) * numpy.arctan2(Y, X) - #easiest way to get a CMapImagePlot is to use the Plot class + # easiest way to get a CMapImagePlot is to use the Plot class ds = ArrayPlotData() - ds.set_data('img', Z) + ds.set_data("img", Z) img = Plot(ds, padding=40) - cmapImgPlot = img.img_plot("img", - xbounds = xy_range, - ybounds = xy_range, - colormap = viridis)[0] + cmapImgPlot = img.img_plot( + "img", xbounds=xy_range, ybounds=xy_range, colormap=viridis + )[0] container.add(img) - #now make another cursor - csr2 = CursorTool(cmapImgPlot, - drag_button='left', - color='white', - line_width=2.0 - ) + # now make another cursor + csr2 = CursorTool( + cmapImgPlot, drag_button="left", color="white", line_width=2.0 + ) self.cursor2 = csr2 csr2.current_position = 1.0, 1.5 cmapImgPlot.overlays.append(csr2) - #add some standard tools. Note, I'm assigning the PanTool to the - #right mouse-button to avoid conflicting with the cursors + # add some standard tools. Note, I'm assigning the PanTool to the + # right mouse-button to avoid conflicting with the cursors cmapImgPlot.tools.append(PanTool(cmapImgPlot, drag_button="right")) cmapImgPlot.overlays.append(ZoomTool(cmapImgPlot)) - - traits_view = View(VGroup( - HGroup(Item('plot', - editor=ComponentEditor(), - resizable=True, springy=True, - show_label=False), - springy=True), - HGroup(Item('cursor1pos', width=300), - Item('cursor2pos', width=300))), - title="Cursor Tool Demo", - resizable=True, - width=800, - height=420) - -#=============================================================================== + traits_view = View( + VGroup( + HGroup( + Item( + "plot", + editor=ComponentEditor(), + resizable=True, + springy=True, + show_label=False, + ), + springy=True, + ), + HGroup(Item("cursor1pos", width=300), Item("cursor2pos", width=300)), + ), + title="Cursor Tool Demo", + resizable=True, + width=800, + height=420, + ) + + +# =============================================================================== # # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = CursorTest() -if __name__=='__main__': +if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/demo/data_labels.py b/examples/demo/data_labels.py index 6c5fe0b41..833fc29b9 100644 --- a/examples/demo/data_labels.py +++ b/examples/demo/data_labels.py @@ -25,8 +25,13 @@ from traitsui.api import Item, View # Chaco imports -from chaco.api import create_line_plot, add_default_axes, add_default_grids, \ - OverlayPlotContainer, DataLabel +from chaco.api import ( + create_line_plot, + add_default_axes, + add_default_grids, + OverlayPlotContainer, + DataLabel, +) from chaco.example_support import COLOR_PALETTE from chaco.tools.api import PanTool, ZoomTool, DataLabelTool @@ -37,16 +42,19 @@ class PlotExample(HasTraits): low = Float(-5.0) high = Float(15.0) - traits_view = View(Item('plot', editor=ComponentEditor(), - show_label=False), - width=800, height=700, resizable=True, - title="Data label example") + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=800, + height=700, + resizable=True, + title="Data label example", + ) def _plot_default(self): - container = OverlayPlotContainer(padding=50, fill_padding=True, - bgcolor="lightgray", - use_backbuffer=True) + container = OverlayPlotContainer( + padding=50, fill_padding=True, bgcolor="lightgray", use_backbuffer=True + ) # Create the initial X-series of data numpoints = self.numpoints @@ -54,8 +62,7 @@ def _plot_default(self): high = self.high x = linspace(low, high, numpoints + 1) y = jn(0, x) - plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[0]), - width=2.0) + plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[0]), width=2.0) plot.index.sort_order = "ascending" plot.bgcolor = "white" plot.border_visible = True @@ -70,75 +77,89 @@ def _plot_default(self): # Add a dynamic label. This can be dragged and moved around using the # right mouse button. Note the use of padding to offset the label # from its data point. - label = DataLabel(component=plot, data_point=(x[40], y[40]), - label_position="top left", padding=40, - bgcolor="lightgray", - border_visible=False) + label = DataLabel( + component=plot, + data_point=(x[40], y[40]), + label_position="top left", + padding=40, + bgcolor="lightgray", + border_visible=False, + ) plot.overlays.append(label) tool = DataLabelTool(label, drag_button="right", auto_arrow_root=True) label.tools.append(tool) # Add some static labels. - label2 = DataLabel(component=plot, data_point=(x[20], y[20]), - label_position="bottom right", - border_visible=False, - bgcolor="transparent", - marker_color="blue", - marker_line_color="transparent", - marker="diamond", - font='modern 14', - arrow_visible=False) + label2 = DataLabel( + component=plot, + data_point=(x[20], y[20]), + label_position="bottom right", + border_visible=False, + bgcolor="transparent", + marker_color="blue", + marker_line_color="transparent", + marker="diamond", + font="modern 14", + arrow_visible=False, + ) plot.overlays.append(label2) - label3 = DataLabel(component=plot, data_point=(x[80], y[80]), - label_position="top", padding_bottom=20, - marker_color="transparent", - marker_size=8, - marker="circle", - arrow_visible=False) + label3 = DataLabel( + component=plot, + data_point=(x[80], y[80]), + label_position="top", + padding_bottom=20, + marker_color="transparent", + marker_size=8, + marker="circle", + arrow_visible=False, + ) plot.overlays.append(label3) # This label uses label_style='bubble'. - label4 = DataLabel(component=plot, data_point=(x[60], y[60]), - border_padding=10, - marker_color="red", - marker_size=3, - label_position=(20, 50), - label_style='bubble', - label_text="Something interesting", - label_format="at x=%(x).2f, y=%(y).2f", - font='modern 18', - bgcolor=(1, 1, 0.75, 1), - ) + label4 = DataLabel( + component=plot, + data_point=(x[60], y[60]), + border_padding=10, + marker_color="red", + marker_size=3, + label_position=(20, 50), + label_style="bubble", + label_text="Something interesting", + label_format="at x=%(x).2f, y=%(y).2f", + font="modern 18", + bgcolor=(1, 1, 0.75, 1), + ) plot.overlays.append(label4) - tool4 = DataLabelTool(label4, drag_button="right", - auto_arrow_root=True) + tool4 = DataLabelTool(label4, drag_button="right", auto_arrow_root=True) label4.tools.append(tool4) # Another 'bubble' label. This one sets arrow_min_length=20, so # the arrow is not drawn when the label is close to the data point. - label5 = DataLabel(component=plot, data_point=(x[65], y[65]), - border_padding=10, - marker_color="green", - marker_size=4, - show_label_coords=False, - label_style='bubble', - label_position=(25, 5), - label_text="Label with\narrow_min_length=20", - border_visible=False, - arrow_min_length=20, - font='modern 14', - bgcolor=(0.75, 0.75, 0.75, 1), - ) + label5 = DataLabel( + component=plot, + data_point=(x[65], y[65]), + border_padding=10, + marker_color="green", + marker_size=4, + show_label_coords=False, + label_style="bubble", + label_position=(25, 5), + label_text="Label with\narrow_min_length=20", + border_visible=False, + arrow_min_length=20, + font="modern 14", + bgcolor=(0.75, 0.75, 0.75, 1), + ) plot.overlays.append(label5) - tool5 = DataLabelTool(label5, drag_button="right", - auto_arrow_root=True) + tool5 = DataLabelTool(label5, drag_button="right", auto_arrow_root=True) label5.tools.append(tool5) container.add(plot) return container + demo = PlotExample() if __name__ == "__main__": diff --git a/examples/demo/data_view.py b/examples/demo/data_view.py index 317c4ae45..b11150879 100644 --- a/examples/demo/data_view.py +++ b/examples/demo/data_view.py @@ -5,40 +5,47 @@ from numpy import linspace, sin, cos # Enthought library imports. -from chaco.api import DataView, ArrayDataSource, ScatterPlot, \ - LinePlot, LinearMapper +from chaco.api import DataView, ArrayDataSource, ScatterPlot, LinePlot, LinearMapper from chaco.tools.api import PanTool, ZoomTool from enable.api import Component, ComponentEditor from traits.api import HasTraits, Instance from traitsui.api import UItem, View + class PlotExample(HasTraits): plot = Instance(Component) - traits_view = View(UItem('plot', editor=ComponentEditor()), - width=700, height=600, resizable=True, - title="Dataview + renderer example" - ) + traits_view = View( + UItem("plot", editor=ComponentEditor()), + width=700, + height=600, + resizable=True, + title="Dataview + renderer example", + ) def _plot_default(self): x = linspace(-5, 10, 500) y = sin(x) - y2 = 0.5 * cos(2*x) - - view = DataView(border_visible = True) - scatter = ScatterPlot(index = ArrayDataSource(x), - value = ArrayDataSource(y), - marker = "square", - color = "red", - outline_color = "transparent", - index_mapper = LinearMapper(range=view.index_range), - value_mapper = LinearMapper(range=view.value_range)) - - line = LinePlot(index = scatter.index, - value = ArrayDataSource(y2), - color = "blue", - index_mapper = LinearMapper(range=view.index_range), - value_mapper = LinearMapper(range=view.value_range)) + y2 = 0.5 * cos(2 * x) + + view = DataView(border_visible=True) + scatter = ScatterPlot( + index=ArrayDataSource(x), + value=ArrayDataSource(y), + marker="square", + color="red", + outline_color="transparent", + index_mapper=LinearMapper(range=view.index_range), + value_mapper=LinearMapper(range=view.value_range), + ) + + line = LinePlot( + index=scatter.index, + value=ArrayDataSource(y2), + color="blue", + index_mapper=LinearMapper(range=view.index_range), + value_mapper=LinearMapper(range=view.value_range), + ) # Add the plot's index and value datasources to the dataview's # ranges so that it can auto-scale and fit appropriately diff --git a/examples/demo/demo.py b/examples/demo/demo.py index 1db4c9fbc..2ecf5b7c4 100644 --- a/examples/demo/demo.py +++ b/examples/demo/demo.py @@ -1,4 +1,4 @@ -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # # Copyright (c) 2009-2010, Enthought, Inc. # All rights reserved. @@ -13,15 +13,11 @@ # Author: Vibha Srinivasan # Date: 02/03/2009 # -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- """ Run the Chaco demo. """ from traitsui.extras.demo import demo -demo( - use_files=True, - title='Chaco Demos' -) - +demo(use_files=True, title="Chaco Demos") diff --git a/examples/demo/depth.py b/examples/demo/depth.py index 771522eb4..892523f37 100644 --- a/examples/demo/depth.py +++ b/examples/demo/depth.py @@ -9,23 +9,25 @@ from traits.api import HasTraits, Instance from traitsui.api import UItem, View + class MyPlot(HasTraits): - """ Plot where depth is the index such that the plot is vertical - and the origin is the upper left + """Plot where depth is the index such that the plot is vertical + and the origin is the upper left """ + plot = Instance(ToolbarPlot) - traits_view = View(UItem('plot', editor=ComponentEditor()), - width=600, height=600, resizable=True - ) + traits_view = View( + UItem("plot", editor=ComponentEditor()), width=600, height=600, resizable=True + ) def __init__(self, depth, data_series, **kw): super(MyPlot, self).__init__(**kw) plot_data = ArrayPlotData(index=depth) - plot_data.set_data('data_series', data_series) - self.plot = ToolbarPlot(plot_data, orientation='v', origin='top left') - line = self.plot.plot(('index', 'data_series'))[0] + plot_data.set_data("data_series", data_series) + self.plot = ToolbarPlot(plot_data, orientation="v", origin="top left") + line = self.plot.plot(("index", "data_series"))[0] line_inspector = LineInspector(component=line, write_metadata=True) line.tools.append(line_inspector) @@ -33,7 +35,7 @@ def __init__(self, depth, data_series, **kw): depth = numpy.arange(1.0, 100.0, 0.1) -data_series = numpy.sin(depth) + depth/10.0 +data_series = numpy.sin(depth) + depth / 10.0 my_plot = MyPlot(depth, data_series) my_plot.configure_traits() diff --git a/examples/demo/domain_limits.py b/examples/demo/domain_limits.py index 17fd3e0a4..2adc4139d 100644 --- a/examples/demo/domain_limits.py +++ b/examples/demo/domain_limits.py @@ -17,19 +17,19 @@ class ExamplePlotApp(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor(), - width = 600, height = 600, - show_label=False), - resizable=True) + traits_view = View( + Item("plot", editor=ComponentEditor(), width=600, height=600, show_label=False), + resizable=True, + ) def __init__(self, index, series1, series2, **kw): super(ExamplePlotApp, self).__init__(**kw) plot_data = ArrayPlotData(index=index) - plot_data.set_data('series1', series1) - plot_data.set_data('series2', series2) + plot_data.set_data("series1", series1) + plot_data.set_data("series2", series2) self.plot = ToolbarPlot(plot_data) - line_plot = self.plot.plot(('index', 'series1'), color='auto')[0] + line_plot = self.plot.plot(("index", "series1"), color="auto")[0] # Add pan and zoom tools line_plot.tools.append(PanTool(line_plot)) @@ -38,10 +38,11 @@ def __init__(self, index, series1, series2, **kw): # Set the domain_limits line_plot.index_mapper.domain_limits = (3.3, 6.6) -index = numpy.arange(1.0, 10., 0.01) -series1 = (100.0 + index) / (100.0 - 20*index**2 + 5.0*index**4) -series2 = (100.0 + index) / (100.0 - 20*index**2 + 5.0*index**3) + +index = numpy.arange(1.0, 10.0, 0.01) +series1 = (100.0 + index) / (100.0 - 20 * index ** 2 + 5.0 * index ** 4) +series2 = (100.0 + index) / (100.0 - 20 * index ** 2 + 5.0 * index ** 3) demo = ExamplePlotApp(index, series1, series2) -if __name__== '__main__': +if __name__ == "__main__": demo.configure_traits() diff --git a/examples/demo/edit_line.py b/examples/demo/edit_line.py index b739c826d..0614f9e49 100644 --- a/examples/demo/edit_line.py +++ b/examples/demo/edit_line.py @@ -27,12 +27,17 @@ from traitsui.api import UItem, View # Chaco imports -from chaco.api import add_default_axes, add_default_grids, \ - OverlayPlotContainer, PlotLabel, ScatterPlot, create_line_plot +from chaco.api import ( + add_default_axes, + add_default_grids, + OverlayPlotContainer, + PlotLabel, + ScatterPlot, + create_line_plot, +) from chaco.tools.api import PanTool, ZoomTool - class PointDraggingTool(DragTool): component = Instance(Component) @@ -60,15 +65,14 @@ def normal_mouse_move(self, event): ndx = plot.map_index((event.x, event.y), self.threshold) if ndx is None: - if 'selections' in plot.index.metadata: - del plot.index.metadata['selections'] + if "selections" in plot.index.metadata: + del plot.index.metadata["selections"] else: - plot.index.metadata['selections'] = [ndx] + plot.index.metadata["selections"] = [ndx] plot.invalidate_draw() plot.request_redraw() - def drag_start(self, event): plot = self.component ndx = plot.map_index((event.x, event.y), self.threshold) @@ -98,13 +102,13 @@ def drag_cancel(self, event): def drag_end(self, event): plot = self.component - if 'selections' in plot.index.metadata: - del plot.index.metadata['selections'] + if "selections" in plot.index.metadata: + del plot.index.metadata["selections"] plot.invalidate_draw() plot.request_redraw() def _lookup_point(self, x, y): - """ Finds the point closest to a screen point if it is within self.threshold + """Finds the point closest to a screen point if it is within self.threshold Parameters ========== @@ -119,20 +123,21 @@ def _lookup_point(self, x, y): If no data points are within *self.threshold* of *(x,y)*, returns None. """ - if hasattr(self.component, 'get_closest_point'): + if hasattr(self.component, "get_closest_point"): # This is on BaseXYPlots - return self.component.get_closest_point((x,y), threshold=self.threshold) + return self.component.get_closest_point((x, y), threshold=self.threshold) return None -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): - container = OverlayPlotContainer(padding = 50, fill_padding = True, - bgcolor = "lightgray", use_backbuffer=True) + container = OverlayPlotContainer( + padding=50, fill_padding=True, bgcolor="lightgray", use_backbuffer=True + ) # Create the initial X-series of data numpoints = 30 @@ -141,14 +146,16 @@ def _create_plot_component(): x = linspace(low, high, numpoints) y = jn(0, x) - lineplot = create_line_plot((x,y), color=tuple(COLOR_PALETTE[0]), width=2.0) + lineplot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[0]), width=2.0) lineplot.selected_color = "none" - scatter = ScatterPlot(index = lineplot.index, - value = lineplot.value, - index_mapper = lineplot.index_mapper, - value_mapper = lineplot.value_mapper, - color = tuple(COLOR_PALETTE[0]), - marker_size = 5) + scatter = ScatterPlot( + index=lineplot.index, + value=lineplot.value, + index_mapper=lineplot.index_mapper, + value_mapper=lineplot.value_mapper, + color=tuple(COLOR_PALETTE[0]), + marker_size=5, + ) scatter.index.sort_order = "ascending" scatter.bgcolor = "white" @@ -170,32 +177,37 @@ def _create_plot_component(): container.add(scatter) # Add the title at the top - container.overlays.append(PlotLabel("Line Editor", - component=container, - font = "swiss 16", - overlay_position="top")) + container.overlays.append( + PlotLabel( + "Line Editor", component=container, font="swiss 16", overlay_position="top" + ) + ) return container -#=============================================================================== +# =============================================================================== # Attributes to use for the plot view. -size=(800,700) -title="Simple line plot" +size = (800, 700) +title = "Simple line plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) - traits_view = View(UItem('plot', editor=ComponentEditor()), - width=size[0], height=size[1], resizable=True, - title=title - ) + traits_view = View( + UItem("plot", editor=ComponentEditor()), + width=size[0], + height=size[1], + resizable=True, + title=title, + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/financial/correlations.py b/examples/demo/financial/correlations.py index c0656220d..2ca7e45dc 100644 --- a/examples/demo/financial/correlations.py +++ b/examples/demo/financial/correlations.py @@ -1,38 +1,53 @@ - from numpy import linspace, random, zeros, arange, cumprod import time # ETS imports (non-chaco) from enable.component_editor import ComponentEditor -from traits.api import HasTraits, Instance, Int, List, Str, Enum, \ - observe, Any, DelegatesTo +from traits.api import ( + HasTraits, + Instance, + Int, + List, + Str, + Enum, + observe, + Any, + DelegatesTo, +) from traitsui.api import Item, View, HSplit, VGroup, EnumEditor # Chaco imports -from chaco.api import ArrayPlotData, Plot, PlotAxis, \ - ScatterInspectorOverlay +from chaco.api import ArrayPlotData, Plot, PlotAxis, ScatterInspectorOverlay from chaco.scales.api import CalendarScaleSystem from chaco.scales_tick_generator import ScalesTickGenerator from chaco.example_support import COLOR_PALETTE -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, \ - RangeSelectionOverlay, LegendTool +from chaco.tools.api import ( + PanTool, + ZoomTool, + RangeSelection, + RangeSelectionOverlay, + LegendTool, +) def create_dates(numpoints, units="days"): - """ Returns **numpoints** number of dates that evenly bracket the current + """Returns **numpoints** number of dates that evenly bracket the current date and time. **units** should be one of "weeks", "days", "hours" "minutes", or "seconds". """ - units_map = { "weeks" : 7*24*3600, - "days" : 24*3600, - "hours" : 3600, - "minutes" : 60, - "seconds" : 1 } + units_map = { + "weeks": 7 * 24 * 3600, + "days": 24 * 3600, + "hours": 3600, + "minutes": 60, + "seconds": 1, + } now = time.time() dt = units_map[units] - dates = linspace(now, now+numpoints*dt, numpoints) + dates = linspace(now, now + numpoints * dt, numpoints) return dates + class PlotApp(HasTraits): plotdata = Instance(ArrayPlotData) @@ -43,26 +58,28 @@ class PlotApp(HasTraits): sym2 = Enum(values="symbols") returns_plot = Instance(Plot) - times_ds = Any() # arraydatasource for the time axis data + times_ds = Any() # arraydatasource for the time axis data corr_plot = Instance(Plot) corr_renderer = Any() traits_view = View( - HSplit( - Item('returns_plot', editor=ComponentEditor(), - show_label = False), + HSplit( + Item("returns_plot", editor=ComponentEditor(), show_label=False), + VGroup( VGroup( - VGroup( - Item('sym1', width=-225), - Item('sym2', width=-225), - ), - Item('corr_plot', editor=ComponentEditor(), - show_label = False, width=-275), + Item("sym1", width=-225), + Item("sym2", width=-225), + ), + Item( + "corr_plot", editor=ComponentEditor(), show_label=False, width=-275 ), ), - width=1024, height=500, - resizable=True, - title = "Correlations of returns") + ), + width=1024, + height=500, + resizable=True, + title="Correlations of returns", + ) def __init__(self, *symbols, **kwtraits): super(PlotApp, self).__init__(symbols=list(symbols), **kwtraits) @@ -75,35 +92,52 @@ def __init__(self, *symbols, **kwtraits): def _create_returns_plot(self): plot = Plot(self.plotdata) plot.legend.visible = True - #FIXME: The legend move tool doesn't seem to quite work right now - #plot.legend.tools.append(LegendTool(plot.legend)) + # FIXME: The legend move tool doesn't seem to quite work right now + # plot.legend.tools.append(LegendTool(plot.legend)) plot.x_axis = None - x_axis = PlotAxis(plot, orientation="bottom", - tick_generator=ScalesTickGenerator(scale=CalendarScaleSystem())) + x_axis = PlotAxis( + plot, + orientation="bottom", + tick_generator=ScalesTickGenerator(scale=CalendarScaleSystem()), + ) plot.overlays.append(x_axis) plot.x_grid.tick_generator = x_axis.tick_generator for i, name in enumerate(self.plotdata.list_data()): if name == "times": continue - renderer = plot.plot(("times", name), type="line", name=name, - color=tuple(COLOR_PALETTE[i]))[0] + renderer = plot.plot( + ("times", name), type="line", name=name, color=tuple(COLOR_PALETTE[i]) + )[0] # Tricky: need to set auto_handle_event on the RangeSelection # so that it passes left-clicks to the PanTool # FIXME: The range selection is still getting the initial left down - renderer.tools.append(RangeSelection(renderer, left_button_selects = False, - auto_handle_event = False)) - plot.tools.append(PanTool(plot, drag_button="left", constrain=True, - constrain_direction="x", restrict_to_data=True)) - plot.overlays.append(ZoomTool(plot, tool_mode="range", max_zoom_out=1.0, x_min_zoom_factor=float(1e-3))) + renderer.tools.append( + RangeSelection(renderer, left_button_selects=False, auto_handle_event=False) + ) + plot.tools.append( + PanTool( + plot, + drag_button="left", + constrain=True, + constrain_direction="x", + restrict_to_data=True, + ) + ) + plot.overlays.append( + ZoomTool( + plot, tool_mode="range", max_zoom_out=1.0, x_min_zoom_factor=float(1e-3) + ) + ) # Attach the range selection to the last renderer; any one will do - self._range_selection_overlay = RangeSelectionOverlay(renderer, - metadata_name="selections") + self._range_selection_overlay = RangeSelectionOverlay( + renderer, metadata_name="selections" + ) renderer.overlays.append(self._range_selection_overlay) # Grab a reference to the Time axis datasource and add a listener to its # selections metadata self.times_ds = renderer.index - self.times_ds.observe(self._selections_updated, 'metadata_changed') + self.times_ds.observe(self._selections_updated, "metadata_changed") self.returns_plot = plot def _create_corr_plot(self): @@ -116,17 +150,21 @@ def _create_corr_plot(self): def _create_data(self, *names): numpoints = self.numpoints - plotdata = ArrayPlotData(times = create_dates(numpoints)) + plotdata = ArrayPlotData(times=create_dates(numpoints)) for name in names: - plotdata.set_data(name, cumprod(random.lognormal(0.0, 0.04, size=numpoints))) + plotdata.set_data( + name, cumprod(random.lognormal(0.0, 0.04, size=numpoints)) + ) self.plotdata = plotdata def _selections_updated(self, event): metadata_changed_event = event.new if self.corr_renderer is None: return - if not isinstance(metadata_changed_event, dict) \ - or "selections" not in metadata_changed_event: + if ( + not isinstance(metadata_changed_event, dict) + or "selections" not in metadata_changed_event + ): return corr_index = self.corr_renderer.index selections = metadata_changed_event["selections"] @@ -139,7 +177,7 @@ def _selections_updated(self, event): low_ndx = data.searchsorted(low) high_ndx = data.searchsorted(high) corr_index.metadata["selections"] = arange( - low_ndx, high_ndx+1, 1, dtype=int + low_ndx, high_ndx + 1, 1, dtype=int ) self.corr_plot.request_redraw() @@ -151,14 +189,15 @@ def _update_corr_symbols(self, event): plot.remove(self.corr_renderer) self.corr_renderer = None - self.corr_renderer = plot.plot((self.sym1, self.sym2), - type="scatter", color="blue")[0] - self.corr_renderer.overlays.append(ScatterInspectorOverlay(self.corr_renderer, - selection_color = "lightgreen")) + self.corr_renderer = plot.plot( + (self.sym1, self.sym2), type="scatter", color="blue" + )[0] + self.corr_renderer.overlays.append( + ScatterInspectorOverlay(self.corr_renderer, selection_color="lightgreen") + ) plot.request_redraw() demo = PlotApp("AAPL", "GOOG", "MSFT") if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/demo/financial/stock_prices.py b/examples/demo/financial/stock_prices.py index 6df06ee11..58ddec1d9 100644 --- a/examples/demo/financial/stock_prices.py +++ b/examples/demo/financial/stock_prices.py @@ -20,36 +20,44 @@ from enable.api import Window # Chaco imports -from chaco.api import ArrayDataSource, BarPlot, DataRange1D, \ - LinePlot, LinearMapper, VPlotContainer, PlotAxis, \ - FilledLinePlot, add_default_grids -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, \ - RangeSelectionOverlay +from chaco.api import ( + ArrayDataSource, + BarPlot, + DataRange1D, + LinePlot, + LinearMapper, + VPlotContainer, + PlotAxis, + FilledLinePlot, + add_default_grids, +) +from chaco.tools.api import PanTool, ZoomTool, RangeSelection, RangeSelectionOverlay from chaco.scales.api import CalendarScaleSystem from chaco.scales_tick_generator import ScalesTickGenerator def create_dates(numpoints, units="days"): - """ Returns **numpoints** number of dates that evenly bracket the current + """Returns **numpoints** number of dates that evenly bracket the current date and time. **units** should be one of "weeks", "days", "hours" "minutes", or "seconds". """ - units_map = { "weeks" : 7*24*3600, - "days" : 24*3600, - "hours" : 3600, - "minutes" : 60, - "seconds" : 1 } + units_map = { + "weeks": 7 * 24 * 3600, + "days": 24 * 3600, + "hours": 3600, + "minutes": 60, + "seconds": 1, + } now = time.time() dt = units_map[units] - dates = linspace(now, now+numpoints*dt, numpoints) + dates = linspace(now, now + numpoints * dt, numpoints) return dates class PlotFrame(DemoFrame): - def _create_price_plots(self, times, prices, mini_height=75): - """ Creates the two plots of prices and returns them. One of the + """Creates the two plots of prices and returns them. One of the plots can be zoomed and panned, and the other plot (smaller) always shows the full data. @@ -57,35 +65,50 @@ def _create_price_plots(self, times, prices, mini_height=75): """ # Create the price plot - price_plot = FilledLinePlot(index = times, value = prices, - index_mapper = LinearMapper(range=DataRange1D(times)), - value_mapper = LinearMapper(range=DataRange1D(prices)), - edge_color = "blue", - face_color = "paleturquoise", - bgcolor = "white", - border_visible = True) + price_plot = FilledLinePlot( + index=times, + value=prices, + index_mapper=LinearMapper(range=DataRange1D(times)), + value_mapper=LinearMapper(range=DataRange1D(prices)), + edge_color="blue", + face_color="paleturquoise", + bgcolor="white", + border_visible=True, + ) # Add pan and zoom - price_plot.tools.append(PanTool(price_plot, constrain=True, - constrain_direction="x", - restrict_to_data=True)) - price_plot.overlays.append(ZoomTool(price_plot, drag_button="right", - always_on=True, - tool_mode="range", - axis="index", - max_zoom_out_factor=1.0, - x_min_zoom_factor=float(1e-3) - )) + price_plot.tools.append( + PanTool( + price_plot, + constrain=True, + constrain_direction="x", + restrict_to_data=True, + ) + ) + price_plot.overlays.append( + ZoomTool( + price_plot, + drag_button="right", + always_on=True, + tool_mode="range", + axis="index", + max_zoom_out_factor=1.0, + x_min_zoom_factor=float(1e-3), + ) + ) # Create the miniplot - miniplot = LinePlot(index = times, value = prices, - index_mapper = LinearMapper(range=DataRange1D(times)), - value_mapper = LinearMapper(range=DataRange1D(prices)), - color = "black", - border_visible = True, - bgcolor = "white", - height = mini_height, - resizable = "h") + miniplot = LinePlot( + index=times, + value=prices, + index_mapper=LinearMapper(range=DataRange1D(times)), + value_mapper=LinearMapper(range=DataRange1D(prices)), + color="black", + border_visible=True, + bgcolor="white", + height=mini_height, + resizable="h", + ) # Add a range overlay to the miniplot that is hooked up to the range # of the main price_plot @@ -101,7 +124,6 @@ def _create_price_plots(self, times, prices, mini_height=75): return price_plot, miniplot - def _range_selection_handler(self, event): range_selection_event = event.new # The event obj should be a tuple (low, high) in data space @@ -122,20 +144,24 @@ def _plot_range_handler(self, event): def _create_vol_plot(self, times, volumes, height=100): "Creates and returns the volume plot" index_range = self.price_plot.index_range - vol_plot = BarPlot(index = times, value = volumes, - index_mapper = LinearMapper(range=index_range), - value_mapper = LinearMapper(range=DataRange1D(volumes)), - line_color = "transparent", - fill_color = "black", - bar_width = 1.0, - bar_width_type = "screen", - antialias = False, - height = 100, - resizable = "h", - bgcolor = "white", - border_visible = True) - vol_plot.tools.append(PanTool(vol_plot, constrain=True, - constrain_direction="x")) + vol_plot = BarPlot( + index=times, + value=volumes, + index_mapper=LinearMapper(range=index_range), + value_mapper=LinearMapper(range=DataRange1D(volumes)), + line_color="transparent", + fill_color="black", + bar_width=1.0, + bar_width_type="screen", + antialias=False, + height=100, + resizable="h", + bgcolor="white", + border_visible=True, + ) + vol_plot.tools.append( + PanTool(vol_plot, constrain=True, constrain_direction="x") + ) return vol_plot def _create_component(self): @@ -168,23 +194,21 @@ def _create_component(self): # Set the plot's bottom axis to use the Scales ticking system ticker = ScalesTickGenerator(scale=CalendarScaleSystem()) for plot in price_plot, mini_plot, vol_plot: - bottom_axis = PlotAxis(plot, orientation="bottom", - tick_generator = ticker) + bottom_axis = PlotAxis(plot, orientation="bottom", tick_generator=ticker) plot.overlays.append(bottom_axis) plot.overlays.append(PlotAxis(plot, orientation="left")) hgrid, vgrid = add_default_grids(plot) vgrid.tick_generator = bottom_axis.tick_generator - container = VPlotContainer(bgcolor = "lightgray", - spacing = 40, - padding = 50, - fill_padding=False) + container = VPlotContainer( + bgcolor="lightgray", spacing=40, padding=50, fill_padding=False + ) container.add(mini_plot, vol_plot, price_plot) return container + if __name__ == "__main__": # Save demo so that it doesn't get garbage collected when run within # existing event loop (i.e. from ipython). - demo = demo_main(PlotFrame, size=(800,600), - title="Stock price and volume") + demo = demo_main(PlotFrame, size=(800, 600), title="Stock price and volume") diff --git a/examples/demo/financial_plot.py b/examples/demo/financial_plot.py index c4e20210a..e97bbfece 100644 --- a/examples/demo/financial_plot.py +++ b/examples/demo/financial_plot.py @@ -12,14 +12,22 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ArrayDataSource, BarPlot, DataRange1D, \ - LinearMapper, VPlotContainer, PlotAxis, FilledLinePlot, \ - add_default_grids, PlotLabel +from chaco.api import ( + ArrayDataSource, + BarPlot, + DataRange1D, + LinearMapper, + VPlotContainer, + PlotAxis, + FilledLinePlot, + add_default_grids, + PlotLabel, +) from chaco.tools.api import PanTool, ZoomTool -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create the data and datasource objects @@ -37,77 +45,94 @@ def _create_plot_component(): vol_mapper = LinearMapper(range=DataRange1D(vol_ds)) price_mapper = LinearMapper(range=DataRange1D(price_ds)) - price_plot = FilledLinePlot(index = time_ds, value = price_ds, - index_mapper = xmapper, - value_mapper = price_mapper, - edge_color = "blue", - face_color = "paleturquoise", - alpha = 0.5, - bgcolor = "white", - border_visible = True) + price_plot = FilledLinePlot( + index=time_ds, + value=price_ds, + index_mapper=xmapper, + value_mapper=price_mapper, + edge_color="blue", + face_color="paleturquoise", + alpha=0.5, + bgcolor="white", + border_visible=True, + ) add_default_grids(price_plot) - price_plot.overlays.append(PlotAxis(price_plot, orientation='left')) - price_plot.overlays.append(PlotAxis(price_plot, orientation='bottom')) - price_plot.tools.append(PanTool(price_plot, constrain=True, - constrain_direction="x")) - price_plot.overlays.append(ZoomTool(price_plot, drag_button="right", - always_on=True, - tool_mode="range", - axis="index")) - - vol_plot = BarPlot(index = time_ds, value = vol_ds, - index_mapper = xmapper, - value_mapper = vol_mapper, - line_color = "transparent", - fill_color = "black", - bar_width = 1.0, - bar_width_type = "screen", - antialias = False, - height = 100, - resizable = "h", - bgcolor = "white", - border_visible = True) + price_plot.overlays.append(PlotAxis(price_plot, orientation="left")) + price_plot.overlays.append(PlotAxis(price_plot, orientation="bottom")) + price_plot.tools.append( + PanTool(price_plot, constrain=True, constrain_direction="x") + ) + price_plot.overlays.append( + ZoomTool( + price_plot, + drag_button="right", + always_on=True, + tool_mode="range", + axis="index", + ) + ) + + vol_plot = BarPlot( + index=time_ds, + value=vol_ds, + index_mapper=xmapper, + value_mapper=vol_mapper, + line_color="transparent", + fill_color="black", + bar_width=1.0, + bar_width_type="screen", + antialias=False, + height=100, + resizable="h", + bgcolor="white", + border_visible=True, + ) add_default_grids(vol_plot) - vol_plot.underlays.append(PlotAxis(vol_plot, orientation='left')) - vol_plot.tools.append(PanTool(vol_plot, constrain=True, - constrain_direction="x")) - - container = VPlotContainer(bgcolor = "lightblue", - spacing = 20, - padding = 50, - fill_padding=False) + vol_plot.underlays.append(PlotAxis(vol_plot, orientation="left")) + vol_plot.tools.append(PanTool(vol_plot, constrain=True, constrain_direction="x")) + + container = VPlotContainer( + bgcolor="lightblue", spacing=20, padding=50, fill_padding=False + ) container.add(vol_plot) container.add(price_plot) - container.overlays.append(PlotLabel("Financial Plot", - component=container, - #font="Times New Roman 24")) - font="Arial 24" - )) + container.overlays.append( + PlotLabel( + "Financial Plot", + component=container, + # font="Times New Roman 24")) + font="Arial 24", + ) + ) return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(800,600) -title="Financial plot example" +size = (800, 600) +title = "Financial plot example" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1] - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/financial_plot_dates.py b/examples/demo/financial_plot_dates.py index e7e10b7af..8da3089cf 100644 --- a/examples/demo/financial_plot_dates.py +++ b/examples/demo/financial_plot_dates.py @@ -14,9 +14,17 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ArrayDataSource, BarPlot, DataRange1D, \ - LinearMapper, VPlotContainer, PlotAxis, \ - FilledLinePlot, add_default_grids, PlotLabel +from chaco.api import ( + ArrayDataSource, + BarPlot, + DataRange1D, + LinearMapper, + VPlotContainer, + PlotAxis, + FilledLinePlot, + add_default_grids, + PlotLabel, +) from chaco.tools.api import PanTool, ZoomTool @@ -25,23 +33,26 @@ def create_dates(numpoints, units="days"): - """ Returns **numpoints** number of dates that evenly bracket the current + """Returns **numpoints** number of dates that evenly bracket the current date and time. **units** should be one of "weeks", "days", "hours" "minutes", or "seconds". """ - units_map = { "weeks" : 7*24*3600, - "days" : 24*3600, - "hours" : 3600, - "minutes" : 60, - "seconds" : 1 } + units_map = { + "weeks": 7 * 24 * 3600, + "days": 24 * 3600, + "hours": 3600, + "minutes": 60, + "seconds": 1, + } now = time.time() dt = units_map[units] - dates = linspace(now, now+numpoints*dt, numpoints) + dates = linspace(now, now + numpoints * dt, numpoints) return dates -#=============================================================================== + +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create the data and datasource objects @@ -63,88 +74,109 @@ def _create_plot_component(): vol_mapper = LinearMapper(range=DataRange1D(vol_ds)) price_mapper = LinearMapper(range=DataRange1D(price_ds)) - price_plot = FilledLinePlot(index = time_ds, value = price_ds, - index_mapper = xmapper, - value_mapper = price_mapper, - edge_color = "blue", - face_color = "paleturquoise", - bgcolor = "white", - border_visible = True) - price_plot.overlays.append(PlotAxis(price_plot, orientation='left')), + price_plot = FilledLinePlot( + index=time_ds, + value=price_ds, + index_mapper=xmapper, + value_mapper=price_mapper, + edge_color="blue", + face_color="paleturquoise", + bgcolor="white", + border_visible=True, + ) + price_plot.overlays.append(PlotAxis(price_plot, orientation="left")), # Set the plot's bottom axis to use the Scales ticking system - bottom_axis = PlotAxis(price_plot, orientation="bottom",# mapper=xmapper, - tick_generator=ScalesTickGenerator(scale=CalendarScaleSystem())) + bottom_axis = PlotAxis( + price_plot, + orientation="bottom", # mapper=xmapper, + tick_generator=ScalesTickGenerator(scale=CalendarScaleSystem()), + ) price_plot.overlays.append(bottom_axis) hgrid, vgrid = add_default_grids(price_plot) vgrid.tick_generator = bottom_axis.tick_generator - price_plot.tools.append(PanTool(price_plot, constrain=True, - constrain_direction="x", - restrict_to_data=True)) - price_plot.overlays.append(ZoomTool(price_plot, drag_button="right", - always_on=True, - tool_mode="range", - axis="index", - max_zoom_out_factor=10.0, - x_min_zoom_factor=float(1e-3), - )) - - vol_plot = BarPlot(index = time_ds, value = vol_ds, - index_mapper = xmapper, - value_mapper = vol_mapper, - line_color = "transparent", - fill_color = "black", - bar_width = 1.0, - bar_width_type = "screen", - antialias = False, - height = 100, - resizable = "h", - bgcolor = "white", - border_visible = True) + price_plot.tools.append( + PanTool( + price_plot, constrain=True, constrain_direction="x", restrict_to_data=True + ) + ) + price_plot.overlays.append( + ZoomTool( + price_plot, + drag_button="right", + always_on=True, + tool_mode="range", + axis="index", + max_zoom_out_factor=10.0, + x_min_zoom_factor=float(1e-3), + ) + ) + + vol_plot = BarPlot( + index=time_ds, + value=vol_ds, + index_mapper=xmapper, + value_mapper=vol_mapper, + line_color="transparent", + fill_color="black", + bar_width=1.0, + bar_width_type="screen", + antialias=False, + height=100, + resizable="h", + bgcolor="white", + border_visible=True, + ) hgrid, vgrid = add_default_grids(vol_plot) # Use the same tick generator as the x-axis on the price plot vgrid.tick_generator = bottom_axis.tick_generator - vol_plot.underlays.append(PlotAxis(vol_plot, orientation='left')) - vol_plot.tools.append(PanTool(vol_plot, constrain=True, - constrain_direction="x")) - - container = VPlotContainer(bgcolor = "lightblue", - spacing = 40, - padding = 50, - fill_padding=False) + vol_plot.underlays.append(PlotAxis(vol_plot, orientation="left")) + vol_plot.tools.append(PanTool(vol_plot, constrain=True, constrain_direction="x")) + + container = VPlotContainer( + bgcolor="lightblue", spacing=40, padding=50, fill_padding=False + ) container.add(vol_plot) container.add(price_plot) - container.overlays.append(PlotLabel("Financial Plot with Date Axis", - component=container, - #font="Times New Roman 24")) - font="Arial 24")) + container.overlays.append( + PlotLabel( + "Financial Plot with Date Axis", + component=container, + # font="Times New Roman 24")) + font="Arial 24", + ) + ) return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(800,600) -title="Financial plot example" +size = (800, 600) +title = "Financial plot example" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1] - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/functionplotter.py b/examples/demo/functionplotter.py index 4f3d4e9f4..604f726ff 100644 --- a/examples/demo/functionplotter.py +++ b/examples/demo/functionplotter.py @@ -25,48 +25,67 @@ class PlotExample(HasTraits): low_mode = Enum("value", "track") high_mode = Enum("value", "track") - traits_view = View( Group( - Item('plot', editor=ComponentEditor(), show_label=False), + Item("plot", editor=ComponentEditor(), show_label=False), HGroup( HGroup( - Item('object.plot.x_mapper.range.low_setting', label='Low', - editor=TextEditor(), - visible_when='object.low_mode == "value" ', ), - Item('low_mode', label='Low Mode'), - Item('object.plot.x_mapper.range.high_setting', - label='High', editor=TextEditor(), - visible_when='object.high_mode == "value" '), - Item('high_mode', label='High Mode'), - Item('object.plot.x_mapper.range.tracking_amount', - label='Tracking Amount', - editor=TextEditor(read_only=True), - visible_when='object.high_mode == "track" or ' - 'object.low_mode == "track"'), - label='X', show_border=True + Item( + "object.plot.x_mapper.range.low_setting", + label="Low", + editor=TextEditor(), + visible_when='object.low_mode == "value" ', + ), + Item("low_mode", label="Low Mode"), + Item( + "object.plot.x_mapper.range.high_setting", + label="High", + editor=TextEditor(), + visible_when='object.high_mode == "value" ', + ), + Item("high_mode", label="High Mode"), + Item( + "object.plot.x_mapper.range.tracking_amount", + label="Tracking Amount", + editor=TextEditor(read_only=True), + visible_when='object.high_mode == "track" or ' + 'object.low_mode == "track"', + ), + label="X", + show_border=True, ), HGroup( - Item('object.plot.y_mapper.range.low_setting', - label='Low', editor=TextEditor()), - Item('object.plot.y_mapper.range.high_setting', - label='High', editor=TextEditor()), - label='Y', show_border=True + Item( + "object.plot.y_mapper.range.low_setting", + label="Low", + editor=TextEditor(), + ), + Item( + "object.plot.y_mapper.range.high_setting", + label="High", + editor=TextEditor(), + ), + label="Y", + show_border=True, ), ), - orientation = "vertical"), resizable=True, title="Function Plot", - width=900, height=600 - ) + orientation="vertical", + ), + resizable=True, + title="Function Plot", + width=900, + height=600, + ) def xfunc(self, low, high): dx = (high - low) / self.numpoints - real_low = ceil(low/dx) * dx - real_high = ceil(high/dx) * dx + real_low = ceil(low / dx) * dx + real_high = ceil(high / dx) * dx return linspace(real_low, real_high, self.numpoints) def yfunc(self, low, high): x = self.xfunc(low, high) - return sin(1.0/x) + return sin(1.0 / x) def _low_mode_changed(self, newvalue): if newvalue != "value": @@ -79,8 +98,8 @@ def _high_mode_changed(self, newvalue): def _plot_default(self): container = DataView() - xds = FunctionDataSource(func = self.xfunc) - yds = FunctionDataSource(func = self.yfunc) + xds = FunctionDataSource(func=self.xfunc) + yds = FunctionDataSource(func=self.yfunc) xmapper = container.x_mapper ymapper = container.y_mapper @@ -91,20 +110,27 @@ def _plot_default(self): xmapper.range.set_bounds(-5, 10) ymapper.range.set_bounds(-1, 1.2) - plot = ScatterPlot(index = xds, value = yds, index_mapper = xmapper, - value_mapper = ymapper, - color = "green", - marker = "circle", - marker_size = 3, - line_width = 0) + plot = ScatterPlot( + index=xds, + value=yds, + index_mapper=xmapper, + value_mapper=ymapper, + color="green", + marker="circle", + marker_size=3, + line_width=0, + ) - plot2 = LinePlot(index = xds, value = yds, index_mapper = xmapper, - value_mapper = ymapper, - color = "lightgray") + plot2 = LinePlot( + index=xds, + value=yds, + index_mapper=xmapper, + value_mapper=ymapper, + color="lightgray", + ) container.add(plot2, plot) - plot.tools.append(PanTool(plot, constrain_direction="x", - constrain=True)) + plot.tools.append(PanTool(plot, constrain_direction="x", constrain=True)) plot.tools.append(ZoomTool(plot, axis="index", tool_mode="range")) return container @@ -114,4 +140,3 @@ def _plot_default(self): if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/demo/image_plot_origin_and_orientation.py b/examples/demo/image_plot_origin_and_orientation.py index 1d347634d..cf5aabb4c 100644 --- a/examples/demo/image_plot_origin_and_orientation.py +++ b/examples/demo/image_plot_origin_and_orientation.py @@ -30,42 +30,46 @@ class Demo(HasTraits): traits_view = View( Group( - UItem('plot', editor=ComponentEditor(size=(1000, 500))), - orientation="vertical" + UItem("plot", editor=ComponentEditor(size=(1000, 500))), + orientation="vertical", ), - resizable=True, title="Demo of image origin and orientation" + resizable=True, + title="Demo of image origin and orientation", ) def _plot_default(self): # Create a GridContainer to hold all of our plots: 2 rows, 4 columns: - container = GridContainer(fill_padding=True, - bgcolor="lightgray", use_backbuffer=True, - shape=(2, 4)) - - arrangements = [('top left', 'h'), - ('top right', 'h'), - ('top left', 'v'), - ('top right', 'v'), - ('bottom left', 'h'), - ('bottom right', 'h'), - ('bottom left', 'v'), - ('bottom right', 'v')] - orientation_name = {'h': 'horizontal', 'v': 'vertical'} + container = GridContainer( + fill_padding=True, bgcolor="lightgray", use_backbuffer=True, shape=(2, 4) + ) + + arrangements = [ + ("top left", "h"), + ("top right", "h"), + ("top left", "v"), + ("top right", "v"), + ("bottom left", "h"), + ("bottom right", "h"), + ("bottom left", "v"), + ("bottom right", "v"), + ] + orientation_name = {"h": "horizontal", "v": "vertical"} pd = ArrayPlotData(image=face()) # Plot some bessel functions and add the plots to our container for origin, orientation in arrangements: plot = Plot(pd, default_origin=origin, orientation=orientation) - plot.img_plot('image') + plot.img_plot("image") # Attach some tools to the plot plot.tools.append(PanTool(plot)) zoom = ZoomTool(plot, tool_mode="box", always_on=False) plot.overlays.append(zoom) - title = '{0}, {1}' - plot.title = title.format(orientation_name[orientation], - origin.replace(' ', '-')) + title = "{0}, {1}" + plot.title = title.format( + orientation_name[orientation], origin.replace(" ", "-") + ) # Add to the grid container container.add(plot) diff --git a/examples/demo/logo.py b/examples/demo/logo.py index 6f9fbd550..c2e789e56 100644 --- a/examples/demo/logo.py +++ b/examples/demo/logo.py @@ -1,7 +1,6 @@ """ LOGO overlay """ - from numpy import array, cos, invert, isnan, nan, pi, sin, vstack from traits.api import Array, Enum, Float, Range from traitsui.api import Group, Item, View @@ -12,7 +11,7 @@ class Turtle(AbstractOverlay): x = Float y = Float - angle = Range(0.0, 360.0, value=90.0) # degrees, clockwise + angle = Range(0.0, 360.0, value=90.0) # degrees, clockwise color = ColorTrait("blue") line_color = ColorTrait("green") size = Float(10.0) @@ -20,13 +19,21 @@ class Turtle(AbstractOverlay): _pen = Enum("down", "up") - view = View(Group("x", "y", "angle", Item("color", style="custom"), - Item("line_color", style="custom"), "size", - orientation="vertical")) + view = View( + Group( + "x", + "y", + "angle", + Item("color", style="custom"), + Item("line_color", style="custom"), + "size", + orientation="vertical", + ) + ) def __init__(self, component=None, **traits): super(Turtle, self).__init__(component=component, **traits) - if 'path' not in traits: + if "path" not in traits: self.path = array([self.x, self.y], ndmin=2) def overlay(self, other_component, gc, view_bounds=None, mode="normal"): @@ -41,14 +48,18 @@ def render_turtle(self, gc, component): gc.set_stroke_color(self.color_) gc.set_fill_color(self.color_) gc.begin_path() - gc.lines([[-0.707*self.size, 0.707*self.size], - [-0.707*self.size, -0.707*self.size], - [self.size, 0.0]]) + gc.lines( + [ + [-0.707 * self.size, 0.707 * self.size], + [-0.707 * self.size, -0.707 * self.size], + [self.size, 0.0], + ] + ) gc.fill_path() def render(self, gc, component): # Uses the component to map our path into screen space - nan_mask = invert(isnan(self.path[:,0])).astype(int) + nan_mask = invert(isnan(self.path[:, 0])).astype(int) blocks = [b for b in arg_find_runs(nan_mask, "flat") if nan_mask[b[0]] != 0] screen_pts = component.map_screen(self.path) with gc: @@ -65,7 +76,7 @@ def pendown(self): self.path = vstack((self.path, [self.x, self.y])) def penup(self): - self.path = vstack((self.path, [nan,nan])) + self.path = vstack((self.path, [nan, nan])) self._pen = "up" def forward(self, amt): @@ -94,6 +105,3 @@ def reset(self): def _anytrait_changed(self, trait, val): self.component.request_redraw() - - - diff --git a/examples/demo/multi_line_plot.py b/examples/demo/multi_line_plot.py index dc5a2d8c0..07a2efe51 100644 --- a/examples/demo/multi_line_plot.py +++ b/examples/demo/multi_line_plot.py @@ -11,15 +11,17 @@ from traits.api import Instance, HasTraits from traitsui.api import View, UItem + class MyPlot(HasTraits): - """ Displays a plot with a few buttons to control which overlay - to display + """Displays a plot with a few buttons to control which overlay + to display """ + plot = Instance(Plot) - traits_view = View(UItem('plot', editor=ComponentEditor()), - width=700, height=600, resizable=True - ) + traits_view = View( + UItem("plot", editor=ComponentEditor()), width=700, height=600, resizable=True + ) def __init__(self, x_index, y_index, data, **kw): super(MyPlot, self).__init__(**kw) @@ -27,31 +29,32 @@ def __init__(self, x_index, y_index, data, **kw): # Create the data source for the MultiLinePlot. ds = MultiArrayDataSource(data=data) - xs = ArrayDataSource(x_index, sort_order='ascending') + xs = ArrayDataSource(x_index, sort_order="ascending") xrange = DataRange1D() xrange.add(xs) - ys = ArrayDataSource(y_index, sort_order='ascending') + ys = ArrayDataSource(y_index, sort_order="ascending") yrange = DataRange1D() yrange.add(ys) mlp = MultiLinePlot( - index = xs, - yindex = ys, - index_mapper = LinearMapper(range=xrange), - value_mapper = LinearMapper(range=yrange), - value=ds, - global_max = np.nanmax(data), - global_min = np.nanmin(data), - **kw) + index=xs, + yindex=ys, + index_mapper=LinearMapper(range=xrange), + value_mapper=LinearMapper(range=yrange), + value=ds, + global_max=np.nanmax(data), + global_min=np.nanmin(data), + **kw + ) self.plot = Plot() self.plot.add(mlp) -x_index = np.arange(0,100, 1) -y_index = np.arange(0,1000, 10) -data = np.sin(np.arange(0,x_index.size*y_index.size)) +x_index = np.arange(0, 100, 1) +y_index = np.arange(0, 1000, 10) +data = np.sin(np.arange(0, x_index.size * y_index.size)) # add a random chunk of nan values data[1532:1588] = np.nan data = data.reshape(x_index.size, y_index.size) diff --git a/examples/demo/multi_line_plot_demo.py b/examples/demo/multi_line_plot_demo.py index 848b9c415..8fd875c56 100644 --- a/examples/demo/multi_line_plot_demo.py +++ b/examples/demo/multi_line_plot_demo.py @@ -44,56 +44,54 @@ class MultiLinePlotDemo(HasTraits): # Drives multi_line_plot_renderer.offset offset = Range(-1.0, 1.0, value=0) - traits_view = \ - View( - VGroup( - Group( - Item('plot', editor=ComponentEditor(), show_label=False), - ), - HGroup( - Item('amplitude', springy=True), - Item('offset', springy=True), - springy=True, - ), - HGroup( - Item('object.multi_line_plot_renderer.color', springy=True), - Item('object.multi_line_plot_renderer.line_style', springy=True), - springy=True, - ), + traits_view = View( + VGroup( + Group( + Item("plot", editor=ComponentEditor(), show_label=False), ), - width=800, - height=500, - resizable=True, - ) - + HGroup( + Item("amplitude", springy=True), + Item("offset", springy=True), + springy=True, + ), + HGroup( + Item("object.multi_line_plot_renderer.color", springy=True), + Item("object.multi_line_plot_renderer.line_style", springy=True), + springy=True, + ), + ), + width=800, + height=500, + resizable=True, + ) - #----------------------------------------------------------------------- + # ----------------------------------------------------------------------- # Trait defaults - #----------------------------------------------------------------------- + # ----------------------------------------------------------------------- def _multi_line_plot_renderer_default(self): """Create the default MultiLinePlot instance.""" - xs = ArrayDataSource(self.model.x_index, sort_order='ascending') + xs = ArrayDataSource(self.model.x_index, sort_order="ascending") xrange = DataRange1D() xrange.add(xs) - ys = ArrayDataSource(self.model.y_index, sort_order='ascending') + ys = ArrayDataSource(self.model.y_index, sort_order="ascending") yrange = DataRange1D() yrange.add(ys) # The data source for the MultiLinePlot. ds = MultiArrayDataSource(data=self.model.data) - multi_line_plot_renderer = \ - MultiLinePlot( - index = xs, - yindex = ys, - index_mapper = LinearMapper(range=xrange), - value_mapper = LinearMapper(range=yrange), - value=ds, - global_max = self.model.data.max(), - global_min = self.model.data.min()) + multi_line_plot_renderer = MultiLinePlot( + index=xs, + yindex=ys, + index_mapper=LinearMapper(range=xrange), + value_mapper=LinearMapper(range=yrange), + value=ds, + global_max=self.model.data.max(), + global_min=self.model.data.min(), + ) return multi_line_plot_renderer @@ -103,20 +101,24 @@ def _plot_default(self): plot = Plot(title="MultiLinePlot Demo") plot.add(self.multi_line_plot_renderer) - x_axis = PlotAxis(component=plot, - mapper=self.multi_line_plot_renderer.index_mapper, - orientation='bottom', - title='t (seconds)') - y_axis = PlotAxis(component=plot, - mapper=self.multi_line_plot_renderer.value_mapper, - orientation='left', - title='channel') + x_axis = PlotAxis( + component=plot, + mapper=self.multi_line_plot_renderer.index_mapper, + orientation="bottom", + title="t (seconds)", + ) + y_axis = PlotAxis( + component=plot, + mapper=self.multi_line_plot_renderer.value_mapper, + orientation="left", + title="channel", + ) plot.overlays.extend([x_axis, y_axis]) return plot - #----------------------------------------------------------------------- + # ----------------------------------------------------------------------- # Trait change handlers - #----------------------------------------------------------------------- + # ----------------------------------------------------------------------- def _amplitude_changed(self, amp): self.multi_line_plot_renderer.normalized_amplitude = amp @@ -138,7 +140,7 @@ def _offset_changed(self, off): channels = np.arange(12) # Frequencies of the sine functions in each channel. - freqs = 3*(channels[:,None] + 1) + freqs = 3 * (channels[:, None] + 1) y = np.sin(freqs * t) # Create an instance of DataModel. This is the data to diff --git a/examples/demo/multiaxis.py b/examples/demo/multiaxis.py index d7281f4ed..838197b6b 100644 --- a/examples/demo/multiaxis.py +++ b/examples/demo/multiaxis.py @@ -16,17 +16,30 @@ from scipy.special import jn from chaco.example_support import COLOR_PALETTE + # Enthought library imports from enable.api import Component, ComponentEditor from traits.api import HasTraits, Instance from traitsui.api import Item, VGroup, View # Chaco imports -from chaco.api import create_line_plot, add_default_axes, \ - add_default_grids, OverlayPlotContainer, \ - PlotLabel, Legend, PlotAxis -from chaco.tools.api import (PanTool, LegendTool, LegendHighlighter, - TraitsTool, BroadcasterTool, ZoomTool) +from chaco.api import ( + create_line_plot, + add_default_axes, + add_default_grids, + OverlayPlotContainer, + PlotLabel, + Legend, + PlotAxis, +) +from chaco.tools.api import ( + PanTool, + LegendTool, + LegendHighlighter, + TraitsTool, + BroadcasterTool, + ZoomTool, +) # ============================================================================= # Create the Chaco plot. @@ -35,22 +48,22 @@ def _create_plot_component(): - container = OverlayPlotContainer(padding=60, fill_padding=True, - use_backbuffer=True, border_visible=True) + container = OverlayPlotContainer( + padding=60, fill_padding=True, use_backbuffer=True, border_visible=True + ) # Create the initial X-series of data numpoints = 100 low = -5 high = 15.0 - x = arange(low, high+0.001, (high-low)/numpoints) + x = arange(low, high + 0.001, (high - low) / numpoints) # Plot some bessel functions plots = {} broadcaster = BroadcasterTool() for i in range(4): y = jn(i, x) - plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[i]), - width=2.0) + plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[i]), width=2.0) if i == 0: add_default_grids(plot) left_axis, _ = add_default_axes(plot) @@ -96,10 +109,14 @@ def _create_plot_component(): legend.plots = plots # Add the title at the top - container.overlays.append(PlotLabel("Bessel functions", - component=container, - font="swiss 16", - overlay_position="top")) + container.overlays.append( + PlotLabel( + "Bessel functions", + component=container, + font="swiss 16", + overlay_position="top", + ) + ) # Add the traits inspector tool to the container container.tools.append(TraitsTool(container)) @@ -121,11 +138,12 @@ class Demo(HasTraits): plot = Instance(Component) traits_view = View( - VGroup( - Item('plot', editor=ComponentEditor(size=size), - show_label=False)), - resizable=True, title=title, - width=size[0], height=size[1]) + VGroup(Item("plot", editor=ComponentEditor(size=size), show_label=False)), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): return _create_plot_component() diff --git a/examples/demo/multiaxis_using_Plot.py b/examples/demo/multiaxis_using_Plot.py index 192ff23f4..aca3c90ab 100644 --- a/examples/demo/multiaxis_using_Plot.py +++ b/examples/demo/multiaxis_using_Plot.py @@ -14,6 +14,7 @@ from scipy.special import jn from chaco.example_support import COLOR_PALETTE + # Enthought library imports from enable.api import Component, ComponentEditor from traits.api import HasTraits, Instance @@ -24,16 +25,16 @@ from chaco.tools.api import BroadcasterTool, PanTool, ZoomTool from chaco.api import create_line_plot, add_default_axes -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some x-y data series to plot x = linspace(-2.0, 10.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) for i in range(5): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) # Create some line plots of some of the data plot1 = Plot(pd) @@ -47,7 +48,7 @@ def _create_plot_component(): x = linspace(-5, 15.0, 100) y = jn(5, x) - foreign_plot = create_line_plot((x,y), color=tuple(COLOR_PALETTE[0]), width=2.0) + foreign_plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[0]), width=2.0) left, bottom = add_default_axes(foreign_plot) left.orientation = "right" bottom.orientation = "top" @@ -66,28 +67,32 @@ def _create_plot_component(): return plot1 -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Multi-Y plot" +size = (900, 500) +title = "Multi-Y plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1] - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/noninteractive.py b/examples/demo/noninteractive.py index 91f760257..e2836d35b 100644 --- a/examples/demo/noninteractive.py +++ b/examples/demo/noninteractive.py @@ -36,8 +36,11 @@ def create_plot(): p = Plot(pd, bgcolor="oldlace", padding=50, border_visible=True) for i in range(10): pd.set_data("y" + str(i), jn(i, x)) - p.plot(("index", "y" + str(i)), color=tuple(COLOR_PALETTE[i]), - width=2.0 * dpi_scale) + p.plot( + ("index", "y" + str(i)), + color=tuple(COLOR_PALETTE[i]), + width=2.0 * dpi_scale, + ) p.x_grid.visible = True p.x_grid.line_width *= dpi_scale p.y_grid.visible = True @@ -57,6 +60,7 @@ def draw_plot(filename, size=(800, 600)): def draw_svg(filename, size=(800, 600)): from chaco.svg_graphics_context import SVGGraphicsContext + container = create_plot() container.bounds = list(size) container.do_layout(force=True) @@ -67,47 +71,47 @@ def draw_svg(filename, size=(800, 600)): def draw_pdf(filename, size=(800, 600)): from chaco.pdf_graphics_context import PdfPlotGraphicsContext + container = create_plot() container.outer_bounds = list(size) container.do_layout(force=True) - gc = PdfPlotGraphicsContext(filename=filename, - dest_box=(0.5, 0.5, 5.0, 5.0)) + gc = PdfPlotGraphicsContext(filename=filename, dest_box=(0.5, 0.5, 5.0, 5.0)) for i in range(2): # draw the plot gc.render_component(container) - #Start a new page for subsequent draw commands. + # Start a new page for subsequent draw commands. gc.add_page() gc.save() def get_directory(filename): - print('Please enter a path in which to place generated plots.') - print('Press to generate in the current directory.') + print("Please enter a path in which to place generated plots.") + print("Press to generate in the current directory.") - path = input('Path: ').strip() + path = input("Path: ").strip() if len(path) > 0 and not os.path.exists(path): - print('The given path does not exist.') + print("The given path does not exist.") sys.exit() if not os.path.isabs(path): - print('Creating image: ' + os.path.join(os.getcwd(), path, filename)) + print("Creating image: " + os.path.join(os.getcwd(), path, filename)) else: - print('Creating image: ' + os.path.join(path, filename)) + print("Creating image: " + os.path.join(path, filename)) return os.path.join(path, filename) if __name__ == "__main__": - if ETSConfig.kiva_backend == 'svg': + if ETSConfig.kiva_backend == "svg": # Render the plot as a SVG - draw_svg(get_directory('noninteractive.svg'), size=(800, 600)) - elif ETSConfig.kiva_backend == 'pdf': + draw_svg(get_directory("noninteractive.svg"), size=(800, 600)) + elif ETSConfig.kiva_backend == "pdf": # Render the plot as a PDF, requires on ReportLab - draw_pdf(get_directory('noninteractive.pdf')) + draw_pdf(get_directory("noninteractive.pdf")) else: - draw_plot(get_directory('noninteractive.png'), size=(800, 600)) + draw_plot(get_directory("noninteractive.png"), size=(800, 600)) diff --git a/examples/demo/nonlinear_color_mapping.py b/examples/demo/nonlinear_color_mapping.py index da9ea2be4..f9243fd2a 100644 --- a/examples/demo/nonlinear_color_mapping.py +++ b/examples/demo/nonlinear_color_mapping.py @@ -9,53 +9,71 @@ # Enthought library imports from enable.api import Component, ComponentEditor -from traits.api import HasTraits, Instance, Property, Float, \ - Enum, Array, Tuple, Int, Callable, cached_property +from traits.api import ( + HasTraits, + Instance, + Property, + Float, + Enum, + Array, + Tuple, + Int, + Callable, + cached_property, +) from traitsui.api import Item, UItem, HGroup, View, RangeEditor # Chaco imports -from chaco.api import ArrayPlotData, Plot, ColorBar, HPlotContainer, \ - LinearMapper, LogMapper, CMapImagePlot, \ - TransformColorMapper, viridis +from chaco.api import ( + ArrayPlotData, + Plot, + ColorBar, + HPlotContainer, + LinearMapper, + LogMapper, + CMapImagePlot, + TransformColorMapper, + viridis, +) from chaco.tools.api import PanTool, ZoomTool class DataGrid(HasTraits): """Holds a grid of 2D data that represents a function z = f(x,y).""" - #------------------------------------------------------ + # ------------------------------------------------------ # Primary Traits - #------------------------------------------------------ + # ------------------------------------------------------ # (xmin, ymin xmax, ymax) domain_bounds = Tuple(Float, Float, Float, Float) - + # grid dimensions: (Nx, Ny) grid_size = Tuple(Int, Int) # The function to evaluate on the grid. func = Callable - #------------------------------------------------------ + # ------------------------------------------------------ # Properties - #------------------------------------------------------ + # ------------------------------------------------------ # 1D array of x coordinates. - x_array = Property(Array, depends_on=['domain_bounds, grid_size']) - + x_array = Property(Array, depends_on=["domain_bounds, grid_size"]) + # 1D array of y coordinates. - y_array = Property(Array, depends_on=['domain_bounds, grid_size']) + y_array = Property(Array, depends_on=["domain_bounds, grid_size"]) # 2D array of function values, z = f(x,y) - data = Property(Array, depends_on=['func, x_array, y_array']) + data = Property(Array, depends_on=["func, x_array, y_array"]) - data_min = Property(Float, depends_on=['data']) - data_max = Property(Float, depends_on=['data']) + data_min = Property(Float, depends_on=["data"]) + data_max = Property(Float, depends_on=["data"]) - #------------------------------------------------------ + # ------------------------------------------------------ # Trait handlers - #------------------------------------------------------ - + # ------------------------------------------------------ + @cached_property def _get_x_array(self): xmin = self.domain_bounds[0] @@ -71,7 +89,7 @@ def _get_y_array(self): ny = self.grid_size[1] y_array = linspace(ymin, ymax, ny) return y_array - + @cached_property def _get_data(self): # This might be called with func == None during initialization. @@ -80,8 +98,8 @@ def _get_data(self): # Create a scalar field to colormap. xs = self.x_array ys = self.y_array - x, y = meshgrid(xs,ys) - z = self.func(x,y)[:-1,:-1] + x, y = meshgrid(xs, ys) + z = self.func(x, y)[:-1, :-1] return z @cached_property @@ -90,7 +108,7 @@ def _get_data_min(self): @cached_property def _get_data_max(self): - return self.data.max() + return self.data.max() def _create_plot_component(model): @@ -106,35 +124,31 @@ def _create_plot_component(model): tcm = TransformColorMapper.from_color_map(viridis) # Create the image plot renderer in the main plot. - renderer = plot.img_plot("imagedata", - xbounds=model.x_array, - ybounds=model.y_array, - colormap=tcm)[0] + renderer = plot.img_plot( + "imagedata", xbounds=model.x_array, ybounds=model.y_array, colormap=tcm + )[0] # Create the colorbar. - lm = LinearMapper(range=renderer.value_range, - domain_limits=(renderer.value_range.low, - renderer.value_range.high)) - colorbar = ColorBar(index_mapper=lm, - plot=plot, - orientation='v', - resizable='v', - width=30, - padding=20) + lm = LinearMapper( + range=renderer.value_range, + domain_limits=(renderer.value_range.low, renderer.value_range.high), + ) + colorbar = ColorBar( + index_mapper=lm, plot=plot, orientation="v", resizable="v", width=30, padding=20 + ) colorbar.padding_top = plot.padding_top colorbar.padding_bottom = plot.padding_bottom # Add pan and zoom tools to the colorbar. - colorbar.tools.append(PanTool(colorbar, - constrain_direction="y", - constrain=True)) - zoom_overlay = ZoomTool(colorbar, axis="index", tool_mode="range", - always_on=True, drag_button="right") + colorbar.tools.append(PanTool(colorbar, constrain_direction="y", constrain=True)) + zoom_overlay = ZoomTool( + colorbar, axis="index", tool_mode="range", always_on=True, drag_button="right" + ) colorbar.overlays.append(zoom_overlay) # Create a container to position the plot and the colorbar side-by-side - container = HPlotContainer(use_backbuffer = True) + container = HPlotContainer(use_backbuffer=True) container.add(plot) container.add(colorbar) @@ -146,37 +160,43 @@ class DataGridView(HasTraits): # The DataGrid instance plotted by this view. model = Instance(DataGrid) - colormap_scale = Enum('linear [default]', 'log [data_func]', - 'power [data_func]', 'power [unit_func]', - 'cos [unit_func]', 'sin [unit_func]') - + colormap_scale = Enum( + "linear [default]", + "log [data_func]", + "power [data_func]", + "power [unit_func]", + "cos [unit_func]", + "sin [unit_func]", + ) + power = Float(1.0) - - colorbar_scale = Enum('linear', 'log') + + colorbar_scale = Enum("linear", "log") plot = Instance(Component) - - img_renderer = Property(Instance(CMapImagePlot), depends_on=['plot']) - - colorbar = Property(Instance(ColorBar), depends_on=['plot']) + img_renderer = Property(Instance(CMapImagePlot), depends_on=["plot"]) - traits_view = View( - HGroup( - Item('colormap_scale'), - Item('power', - editor=RangeEditor(low=0.1, - high=3.0, - format="%4.2f"), - visible_when='colormap_scale.startswith("power")', - springy=True), - Item('colorbar_scale'), - springy=True), - UItem('plot',editor=ComponentEditor()), - width=750, height=500, resizable=True, - title="TransformColorMapper Demo", - ) + colorbar = Property(Instance(ColorBar), depends_on=["plot"]) + traits_view = View( + HGroup( + Item("colormap_scale"), + Item( + "power", + editor=RangeEditor(low=0.1, high=3.0, format="%4.2f"), + visible_when='colormap_scale.startswith("power")', + springy=True, + ), + Item("colorbar_scale"), + springy=True, + ), + UItem("plot", editor=ComponentEditor()), + width=750, + height=500, + resizable=True, + title="TransformColorMapper Demo", + ) def _plot_default(self): return _create_plot_component(self.model) @@ -191,50 +211,50 @@ def _get_colorbar(self): return self.plot.components[1] def _colormap_scale_changed(self): - if self.colormap_scale == 'linear [default]': + if self.colormap_scale == "linear [default]": self.img_renderer.color_mapper.data_func = None self.img_renderer.color_mapper.unit_func = None - elif self.colormap_scale == 'log [data_func]': + elif self.colormap_scale == "log [data_func]": self.img_renderer.color_mapper.data_func = log10 self.img_renderer.color_mapper.unit_func = None - elif self.colormap_scale == 'power [data_func]': - self.img_renderer.color_mapper.data_func = lambda x: x**self.power + elif self.colormap_scale == "power [data_func]": + self.img_renderer.color_mapper.data_func = lambda x: x ** self.power self.img_renderer.color_mapper.unit_func = None - elif self.colormap_scale == 'power [unit_func]': + elif self.colormap_scale == "power [unit_func]": self.img_renderer.color_mapper.data_func = None - self.img_renderer.color_mapper.unit_func = lambda x: x**self.power - elif self.colormap_scale == 'cos [unit_func]': + self.img_renderer.color_mapper.unit_func = lambda x: x ** self.power + elif self.colormap_scale == "cos [unit_func]": self.img_renderer.color_mapper.data_func = None - self.img_renderer.color_mapper.unit_func = lambda x: cos(0.5*pi*x) - elif self.colormap_scale == 'sin [unit_func]': + self.img_renderer.color_mapper.unit_func = lambda x: cos(0.5 * pi * x) + elif self.colormap_scale == "sin [unit_func]": self.img_renderer.color_mapper.data_func = None - self.img_renderer.color_mapper.unit_func = lambda x: sin(0.5*pi*x) + self.img_renderer.color_mapper.unit_func = lambda x: sin(0.5 * pi * x) # FIXME: This call to request_redraw() should not be necessary. self.img_renderer.request_redraw() def _power_changed(self): - if self.colormap_scale == 'power [data_func]': - self.img_renderer.color_mapper.data_func = lambda x: x**self.power - elif self.colormap_scale == 'power [unit_func]': - self.img_renderer.color_mapper.unit_func = lambda x: x**self.power + if self.colormap_scale == "power [data_func]": + self.img_renderer.color_mapper.data_func = lambda x: x ** self.power + elif self.colormap_scale == "power [unit_func]": + self.img_renderer.color_mapper.unit_func = lambda x: x ** self.power self.img_renderer.request_redraw() def _colorbar_scale_changed(self): rng = self.colorbar.index_mapper.range dlim = self.colorbar.index_mapper.domain_limits - if self.colorbar_scale == 'linear': + if self.colorbar_scale == "linear": new_mapper = LinearMapper(range=rng, domain_limits=dlim) else: # 'log' new_mapper = LogMapper(range=rng, domain_limits=dlim) self.colorbar.index_mapper = new_mapper - if __name__ == "__main__": grid = DataGrid( - func = lambda x,y: 3.0**(x**2 + 2*(cos(2*pi*y)-1)), - domain_bounds=(0.0,0.0, 2.0,2.0), - grid_size=(200, 200)) - #print "data bounds: ", grid.data_min, grid.data_max + func=lambda x, y: 3.0 ** (x ** 2 + 2 * (cos(2 * pi * y) - 1)), + domain_bounds=(0.0, 0.0, 2.0, 2.0), + grid_size=(200, 200), + ) + # print "data bounds: ", grid.data_min, grid.data_max demo = DataGridView(model=grid) demo.configure_traits() diff --git a/examples/demo/qt_example.py b/examples/demo/qt_example.py index 5797ddb9b..d4b6ea8c0 100644 --- a/examples/demo/qt_example.py +++ b/examples/demo/qt_example.py @@ -4,6 +4,7 @@ The actual plot being created is drawn from the basic/line_plot1.py code. """ from traits.etsconfig.etsconfig import ETSConfig + ETSConfig.toolkit = "qt4" from numpy import linspace @@ -19,9 +20,9 @@ def create_chaco_plot(parent): x = linspace(-2.0, 10.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) for i in range(5): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) # Create some line plots of some of the data plot = Plot(pd, title="Line Plot", padding=50, border_visible=True) @@ -44,7 +45,7 @@ def create_chaco_plot(parent): def main(): app = get_app_qt4() main_window = QtGui.QMainWindow() - main_window.resize(500,500) + main_window.resize(500, 500) enable_window = create_chaco_plot(main_window) diff --git a/examples/demo/quiver.py b/examples/demo/quiver.py index 0997209ab..e8eb5419a 100644 --- a/examples/demo/quiver.py +++ b/examples/demo/quiver.py @@ -18,8 +18,13 @@ from traitsui.api import Item, View # Chaco imports -from chaco.api import add_default_grids, add_default_axes, ArrayPlotData, \ - Plot, OverlayPlotContainer +from chaco.api import ( + add_default_grids, + add_default_axes, + ArrayPlotData, + Plot, + OverlayPlotContainer, +) from chaco.tools.api import PanTool, ZoomTool @@ -28,8 +33,9 @@ class PlotExample(HasTraits): numpts = Int(400) vectorlen = Int(15) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=600, height=600) + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), width=600, height=600 + ) def _plot_default(self): # Create starting points for the vectors. @@ -39,14 +45,14 @@ def _plot_default(self): # Create vectors. vectorlen = self.vectorlen - vectors = array((random(numpts)*vectorlen, random(numpts)*vectorlen)).T + vectors = array((random(numpts) * vectorlen, random(numpts) * vectorlen)).T data = ArrayPlotData() - data.set_data('index', x) - data.set_data('value', y) - data.set_data('vectors', vectors) + data.set_data("index", x) + data.set_data("value", y) + data.set_data("vectors", vectors) quiverplot = Plot(data) - quiverplot.quiverplot(('index', 'value', 'vectors')) + quiverplot.quiverplot(("index", "value", "vectors")) # Attach some tools to the plot quiverplot.tools.append(PanTool(quiverplot, constrain_key="shift")) diff --git a/examples/demo/range_selection_demo.py b/examples/demo/range_selection_demo.py index c2abffa59..f637c4b1c 100644 --- a/examples/demo/range_selection_demo.py +++ b/examples/demo/range_selection_demo.py @@ -22,22 +22,23 @@ from chaco.tools.api import RangeSelection, RangeSelectionOverlay - -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): numpoints = 100 low = -5 high = 15.001 - x = arange(low, high, (high-low)/numpoints) + x = arange(low, high, (high - low) / numpoints) # Plot a bessel function y = jn(0, x) - plot = create_line_plot((x,y), color=(0,0,1,1), width=2.0, index_sort="ascending") + plot = create_line_plot( + (x, y), color=(0, 0, 1, 1), width=2.0, index_sort="ascending" + ) value_range = plot.value_mapper.range - plot.active_tool = RangeSelection(plot, left_button_selects = True) + plot.active_tool = RangeSelection(plot, left_button_selects=True) plot.overlays.append(RangeSelectionOverlay(component=plot)) plot.bgcolor = "white" plot.padding = 50 @@ -47,28 +48,31 @@ def _create_plot_component(): return plot -#=============================================================================== +# =============================================================================== # Attributes to use for the plot view. -size=(600,500) -title="Simple line plot" +size = (600, 500) +title = "Simple line plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1] - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/scales_test.py b/examples/demo/scales_test.py index 3a14be0db..35bace1fa 100644 --- a/examples/demo/scales_test.py +++ b/examples/demo/scales_test.py @@ -22,26 +22,33 @@ from time import time from chaco.example_support import COLOR_PALETTE + # Enthought library imports from enable.api import Component, ComponentEditor from traits.api import HasTraits, Instance from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import create_line_plot, OverlayPlotContainer, PlotLabel, \ - create_scatter_plot, Legend, PlotGrid -from chaco.tools.api import PanTool, ZoomTool, \ - LegendTool, TraitsTool +from chaco.api import ( + create_line_plot, + OverlayPlotContainer, + PlotLabel, + create_scatter_plot, + Legend, + PlotGrid, +) +from chaco.tools.api import PanTool, ZoomTool, LegendTool, TraitsTool from chaco.scales.api import CalendarScaleSystem from chaco.scales_tick_generator import ScalesTickGenerator from chaco.axis import PlotAxis -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== + -def add_default_axes(plot, orientation="normal", vtitle="",htitle=""): +def add_default_axes(plot, orientation="normal", vtitle="", htitle=""): """ Creates left and bottom axes for a plot. Assumes that the index is horizontal and value is vertical by default; set orientation to @@ -54,15 +61,11 @@ def add_default_axes(plot, orientation="normal", vtitle="",htitle=""): v_mapper = plot.index_mapper h_mapper = plot.value_mapper - left = PlotAxis(orientation='left', - title= vtitle, - mapper=v_mapper, - component=plot) + left = PlotAxis(orientation="left", title=vtitle, mapper=v_mapper, component=plot) - bottom = PlotAxis(orientation='bottom', - title= htitle, - mapper=h_mapper, - component=plot) + bottom = PlotAxis( + orientation="bottom", title=htitle, mapper=h_mapper, component=plot + ) plot.underlays.append(left) plot.underlays.append(bottom) @@ -82,23 +85,33 @@ def add_default_grids(plot, orientation="normal", tick_gen=None): v_mapper = plot.value_mapper h_mapper = plot.index_mapper - vgrid = PlotGrid(mapper=v_mapper, orientation='vertical', - component=plot, - line_color="lightgray", line_style="dot", - tick_generator = tick_gen) - - hgrid = PlotGrid(mapper=h_mapper, orientation='horizontal', - component=plot, - line_color="lightgray", line_style="dot", - tick_generator = ScalesTickGenerator()) + vgrid = PlotGrid( + mapper=v_mapper, + orientation="vertical", + component=plot, + line_color="lightgray", + line_style="dot", + tick_generator=tick_gen, + ) + + hgrid = PlotGrid( + mapper=h_mapper, + orientation="horizontal", + component=plot, + line_color="lightgray", + line_style="dot", + tick_generator=ScalesTickGenerator(), + ) plot.underlays.append(vgrid) plot.underlays.append(hgrid) return hgrid, vgrid + def _create_plot_component(): - container = OverlayPlotContainer(padding = 50, fill_padding = True, - bgcolor = "lightgray", use_backbuffer=True) + container = OverlayPlotContainer( + padding=50, fill_padding=True, bgcolor="lightgray", use_backbuffer=True + ) # Create the initial X-series of data numpoints = 100 @@ -107,7 +120,7 @@ def _create_plot_component(): x = linspace(low, high, numpoints) now = time() - timex = linspace(now, now+7*24*3600, numpoints) + timex = linspace(now, now + 7 * 24 * 3600, numpoints) # Plot some bessel functions value_mapper = None @@ -115,11 +128,13 @@ def _create_plot_component(): plots = {} for i in range(10): y = jn(i, x) - if i%2 == 1: - plot = create_line_plot((timex,y), color=tuple(COLOR_PALETTE[i]), width=2.0) + if i % 2 == 1: + plot = create_line_plot( + (timex, y), color=tuple(COLOR_PALETTE[i]), width=2.0 + ) plot.index.sort_order = "ascending" else: - plot = create_scatter_plot((timex,y), color=tuple(COLOR_PALETTE[i])) + plot = create_scatter_plot((timex, y), color=tuple(COLOR_PALETTE[i])) plot.bgcolor = "white" plot.border_visible = True if i == 0: @@ -135,7 +150,7 @@ def _create_plot_component(): plot.index_mapper = index_mapper index_mapper.range.add(plot.index) - if i==0: + if i == 0: plot.tools.append(PanTool(plot)) zoom = ZoomTool(plot, tool_mode="box", always_on=False) plot.overlays.append(zoom) @@ -145,44 +160,52 @@ def _create_plot_component(): plot.overlays.append(legend) container.add(plot) - plots["Bessel j_%d"%i] = plot + plots["Bessel j_%d" % i] = plot # Set the list of plots on the legend legend.plots = plots # Add the title at the top - container.overlays.append(PlotLabel("Bessel functions", - component=container, - font = "swiss 16", - overlay_position="top")) + container.overlays.append( + PlotLabel( + "Bessel functions", + component=container, + font="swiss 16", + overlay_position="top", + ) + ) # Add the traits inspector tool to the container container.tools.append(TraitsTool(container)) return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(800,700) -title="Simple line plot" +size = (800, 700) +title = "Simple line plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1] - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/shell/add_tool.py b/examples/demo/shell/add_tool.py index a0bf57fac..ca67c661e 100644 --- a/examples/demo/shell/add_tool.py +++ b/examples/demo/shell/add_tool.py @@ -14,13 +14,13 @@ from chaco.default_colormaps import viridis # Crate some scalar data -xs = linspace(0,10,200) -ys = linspace(0,20,400) -x,y = meshgrid(xs,ys) -z = sin(x)*y +xs = linspace(0, 10, 200) +ys = linspace(0, 20, 400) +x, y = meshgrid(xs, ys) +z = sin(x) * y # Create a pseudo-color-map -pcolor(x, y, z, name='sin_x_times_y') +pcolor(x, y, z, name="sin_x_times_y") # Change the color mapping colormap(viridis) @@ -30,15 +30,16 @@ # From the current plot object, grab the first plot -img_plot = curplot().plots['sin_x_times_y'][0] +img_plot = curplot().plots["sin_x_times_y"][0] # Add a custom tool - in this case, an ImageInspector from chaco.tools.api import ImageInspectorTool, ImageInspectorOverlay tool = ImageInspectorTool(img_plot) img_plot.tools.append(tool) -overlay = ImageInspectorOverlay(img_plot, image_inspector=tool, - bgcolor="white", border_visible=True) +overlay = ImageInspectorOverlay( + img_plot, image_inspector=tool, bgcolor="white", border_visible=True +) img_plot.overlays.append(overlay) diff --git a/examples/demo/shell/contour.py b/examples/demo/shell/contour.py index cb95fb3a0..9a8ba062d 100644 --- a/examples/demo/shell/contour.py +++ b/examples/demo/shell/contour.py @@ -12,13 +12,13 @@ # Crate some scalar data -xs = linspace(-10,10,200) -ys = linspace(-10,10,400) -x,y = meshgrid(xs,ys) -z = sin(x)*x*jn(0,y) +xs = linspace(-10, 10, 200) +ys = linspace(-10, 10, 400) +x, y = meshgrid(xs, ys) +z = sin(x) * x * jn(0, y) # Create a contour line plot -contour(x,y,z, bgcolor="black") +contour(x, y, z, bgcolor="black") # Add some titles title("contour line plot") diff --git a/examples/demo/shell/contourf.py b/examples/demo/shell/contourf.py index 7cd603085..5d0ba0d85 100644 --- a/examples/demo/shell/contourf.py +++ b/examples/demo/shell/contourf.py @@ -12,13 +12,13 @@ # Crate some scalar data -xs = linspace(-10,10,200) -ys = linspace(-10,10,400) -x, y = meshgrid(xs,ys) +xs = linspace(-10, 10, 200) +ys = linspace(-10, 10, 400) +x, y = meshgrid(xs, ys) z = x * tanh(y) # Create a filled contour plot -contourf(x,y,z) +contourf(x, y, z) colormap(viridis) # Add some titles diff --git a/examples/demo/shell/dates.py b/examples/demo/shell/dates.py index fb21a943a..7af48830a 100644 --- a/examples/demo/shell/dates.py +++ b/examples/demo/shell/dates.py @@ -15,14 +15,15 @@ # Create some data numpoints = 100 -x = linspace(-2*pi, 2*pi, numpoints) +x = linspace(-2 * pi, 2 * pi, numpoints) y1 = sin(x) # Create the dates import time + now = time.time() -dt = 24 * 3600 # data points are spaced by 1 day -dates = linspace(now, now + numpoints*dt, numpoints) +dt = 24 * 3600 # data points are spaced by 1 day +dates = linspace(now, now + numpoints * dt, numpoints) # Create some line plots plot(dates, y1, "b-", bgcolor="white") @@ -41,4 +42,3 @@ # This command is only necessary if running from command line show() - diff --git a/examples/demo/shell/imshow.py b/examples/demo/shell/imshow.py index b7d7d3a92..30a7856f6 100644 --- a/examples/demo/shell/imshow.py +++ b/examples/demo/shell/imshow.py @@ -7,9 +7,9 @@ from chaco.shell import imread, imshow, title, show # Get the image file using the find_resource module -image_path = os.path.join('examples','basic','capitol.jpg') -alt_path = os.path.join('..','basic','capitol.jpg') -image_file = find_resource('Chaco', image_path, alt_path=alt_path) +image_path = os.path.join("examples", "basic", "capitol.jpg") +alt_path = os.path.join("..", "basic", "capitol.jpg") +image_file = find_resource("Chaco", image_path, alt_path=alt_path) # Check to see if the image was found if image_file is None: @@ -23,7 +23,7 @@ imshow(image, origin="top left") # Alternatively, you can call imshow using the path to the image file -#imshow(alt_path) +# imshow(alt_path) # Add a title title("Simple Image Plot") diff --git a/examples/demo/shell/lines.py b/examples/demo/shell/lines.py index 2354364d9..c231c4ffe 100644 --- a/examples/demo/shell/lines.py +++ b/examples/demo/shell/lines.py @@ -10,7 +10,7 @@ from chaco.shell import plot, hold, title, show # Create some data -x = linspace(-2*pi, 2*pi, 100) +x = linspace(-2 * pi, 2 * pi, 100) y1 = sin(x) y2 = cos(x) diff --git a/examples/demo/shell/loglog.py b/examples/demo/shell/loglog.py index 0e165e8d2..41ea2c064 100644 --- a/examples/demo/shell/loglog.py +++ b/examples/demo/shell/loglog.py @@ -14,9 +14,9 @@ x = linspace(1, 15, 200) # Create some line plots -loglog(x, x**2, "b-.", name="y=x**2", bgcolor="white") +loglog(x, x ** 2, "b-.", name="y=x**2", bgcolor="white") hold(True) -loglog(x, x**4+3*x+2, "r-", name="y=x**4+3x+2", bgcolor="white") +loglog(x, x ** 4 + 3 * x + 2, "r-", name="y=x**4+3x+2", bgcolor="white") loglog(x, exp(x), "g-", name="y=exp(x)", bgcolor="white") loglog(x, x, "m--", name="y=x", bgcolor="white") diff --git a/examples/demo/shell/pcolor.py b/examples/demo/shell/pcolor.py index 3704beb45..39280e4a8 100644 --- a/examples/demo/shell/pcolor.py +++ b/examples/demo/shell/pcolor.py @@ -14,15 +14,15 @@ # Crate some scalar data -xs = linspace(0,10,200) -ys = linspace(0,20,400) -x,y = meshgrid(xs,ys) +xs = linspace(0, 10, 200) +ys = linspace(0, 20, 400) +x, y = meshgrid(xs, ys) z = sin(x) * y # Create a pseudo-color-map -pcolor(x,y,z) +pcolor(x, y, z) -#change the color mapping +# change the color mapping colormap(viridis) # Add some titles diff --git a/examples/demo/shell/scatter.py b/examples/demo/shell/scatter.py index 06b6605bb..ea2d623cd 100644 --- a/examples/demo/shell/scatter.py +++ b/examples/demo/shell/scatter.py @@ -10,7 +10,7 @@ # Create some data -x = linspace(-2*pi, 2*pi, 100) +x = linspace(-2 * pi, 2 * pi, 100) y1 = random.random(100) y2 = random.random(100) diff --git a/examples/demo/shell/semilog.py b/examples/demo/shell/semilog.py index 8bc145af3..9bd016727 100644 --- a/examples/demo/shell/semilog.py +++ b/examples/demo/shell/semilog.py @@ -15,7 +15,7 @@ # Create some line plots semilogy(x, exp(x), "b-", name="y=exp(x)", bgcolor="white") hold(True) -semilogy(x, x**x, "r--", name="y=x**x") +semilogy(x, x ** x, "r--", name="y=x**x") semilogy(x, x, "g-", name="y=x") # Add some titles @@ -23,4 +23,3 @@ # This command is only necessary if running from command line show() - diff --git a/examples/demo/simple_line.py b/examples/demo/simple_line.py index 74f41b79f..30fd82874 100644 --- a/examples/demo/simple_line.py +++ b/examples/demo/simple_line.py @@ -26,8 +26,15 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import create_line_plot, add_default_axes, add_default_grids, \ - OverlayPlotContainer, PlotLabel, create_scatter_plot, Legend +from chaco.api import ( + create_line_plot, + add_default_axes, + add_default_grids, + OverlayPlotContainer, + PlotLabel, + create_scatter_plot, + Legend, +) from chaco.tools.api import PanTool, ZoomTool, LegendTool, TraitsTool, DragZoom from chaco.example_support import COLOR_PALETTE @@ -47,22 +54,19 @@ def __init__(self, *args, **kws): def _setup_plots(self): """Creates series of Bessel function plots""" plots = {} - x = arange(self.low, self.high + 0.001, - (self.high - self.low) / self.numpoints) + x = arange(self.low, self.high + 0.001, (self.high - self.low) / self.numpoints) for i in range(self.num_funs): y = jn(i, x) if i % 2 == 1: - plot = create_line_plot((x, y), - color=tuple(COLOR_PALETTE[i]), - width=2.0) + plot = create_line_plot( + (x, y), color=tuple(COLOR_PALETTE[i]), width=2.0 + ) else: - plot = create_scatter_plot((x, y), - color=tuple(COLOR_PALETTE[i])) + plot = create_scatter_plot((x, y), color=tuple(COLOR_PALETTE[i])) if i == 0: - value_mapper, index_mapper, legend = \ - self._setup_plot_tools(plot) + value_mapper, index_mapper, legend = self._setup_plot_tools(plot) else: self._setup_mapper(plot, value_mapper, index_mapper) @@ -73,10 +77,14 @@ def _setup_plots(self): legend.plots = plots # Add the title at the top - self.overlays.append(PlotLabel("Bessel functions", - component=self, - font="swiss 16", - overlay_position="top")) + self.overlays.append( + PlotLabel( + "Bessel functions", + component=self, + font="swiss 16", + overlay_position="top", + ) + ) # Add the traits inspector tool to the container self.tools.append(TraitsTool(self)) @@ -130,17 +138,20 @@ class PlotExample(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation="vertical"), - resizable=True, title=title, - width=size[0], height=size[1] - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): - return OverlappingPlotContainer(padding=50, fill_padding=True, - bgcolor="lightgray", use_backbuffer=True) + return OverlappingPlotContainer( + padding=50, fill_padding=True, bgcolor="lightgray", use_backbuffer=True + ) demo = PlotExample() diff --git a/examples/demo/simple_polar.py b/examples/demo/simple_polar.py index f829c1207..7a943be6d 100644 --- a/examples/demo/simple_polar.py +++ b/examples/demo/simple_polar.py @@ -13,47 +13,51 @@ # Chaco imports from chaco.api import create_polar_plot -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create theta data numpoints = 5000 low = 0 - high = 2*pi - theta = arange(low, high, (high-low) / numpoints) + high = 2 * pi + theta = arange(low, high, (high - low) / numpoints) # Create the radius data - radius = cos(3*theta) + radius = cos(3 * theta) # Create a new polar plot with radius and theta data - plot = create_polar_plot((radius,theta),color=(0.0,0.0,1.0,1), width=4.0) + plot = create_polar_plot((radius, theta), color=(0.0, 0.0, 1.0, 1), width=4.0) return plot -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(600,600) -title="Simple Polar Plot" +size = (600, 600) +title = "Simple Polar Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1] - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/stacked_axis.py b/examples/demo/stacked_axis.py index 94d63c7e5..093d6f1cb 100644 --- a/examples/demo/stacked_axis.py +++ b/examples/demo/stacked_axis.py @@ -11,26 +11,26 @@ from scipy.special import jn from chaco.example_support import COLOR_PALETTE + # Enthought library imports from enable.api import Component, ComponentEditor from traits.api import HasTraits, Instance from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import HPlotContainer, \ - OverlayPlotContainer, PlotAxis, PlotGrid +from chaco.api import HPlotContainer, OverlayPlotContainer, PlotAxis, PlotGrid from chaco.tools.api import BroadcasterTool, PanTool from chaco.api import create_line_plot -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): # Create some x-y data series to plot plot_area = OverlayPlotContainer(border_visible=True) container = HPlotContainer(padding=50, bgcolor="transparent") - #container.spacing = 15 + # container.spacing = 15 x = linspace(-2.0, 10.0, 100) for i in range(5): @@ -38,18 +38,21 @@ def _create_plot_component(): y = jn(i, x) renderer = create_line_plot((x, y), color=color) plot_area.add(renderer) - #plot_area.padding_left = 20 - - axis = PlotAxis(orientation="left", resizable="v", - mapper = renderer.y_mapper, - axis_line_color=color, - tick_color=color, - tick_label_color=color, - title_color=color, - bgcolor="transparent", - title = "jn_%d" % i, - border_visible = True,) - axis.bounds = [60,0] + # plot_area.padding_left = 20 + + axis = PlotAxis( + orientation="left", + resizable="v", + mapper=renderer.y_mapper, + axis_line_color=color, + tick_color=color, + tick_label_color=color, + title_color=color, + bgcolor="transparent", + title="jn_%d" % i, + border_visible=True, + ) + axis.bounds = [60, 0] axis.padding_left = 10 axis.padding_right = 10 @@ -58,11 +61,16 @@ def _create_plot_component(): if i == 4: # Use the last plot's X mapper to create an X axis and a # vertical grid - x_axis = PlotAxis(orientation="bottom", component=renderer, - mapper=renderer.x_mapper) + x_axis = PlotAxis( + orientation="bottom", component=renderer, mapper=renderer.x_mapper + ) renderer.overlays.append(x_axis) - grid = PlotGrid(mapper=renderer.x_mapper, orientation="vertical", - line_color="lightgray", line_style="dot") + grid = PlotGrid( + mapper=renderer.x_mapper, + orientation="vertical", + line_color="lightgray", + line_style="dot", + ) renderer.underlays.append(grid) # Add the plot_area to the horizontal container @@ -80,29 +88,33 @@ def _create_plot_component(): return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(900,500) -title="Multi-Y plot" +size = (900, 500) +title = "Multi-Y plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1] - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): return _create_plot_component() + demo = Demo() if __name__ == "__main__": diff --git a/examples/demo/status_overlay.py b/examples/demo/status_overlay.py index 8e2527471..4ec65aac5 100644 --- a/examples/demo/status_overlay.py +++ b/examples/demo/status_overlay.py @@ -9,59 +9,63 @@ from traits.api import HasTraits, Instance, Button from traitsui.api import UItem, View, HGroup + class MyPlot(HasTraits): - """ Displays a plot with a few buttons to control which overlay - to display + """Displays a plot with a few buttons to control which overlay + to display """ + plot = Instance(Plot) status_overlay = Instance(StatusLayer) - error_button = Button('Error') - warn_button = Button('Warning') - no_problem_button = Button('No problem') + error_button = Button("Error") + warn_button = Button("Warning") + no_problem_button = Button("No problem") - traits_view = View( HGroup(UItem('error_button'), - UItem('warn_button'), - UItem('no_problem_button')), - UItem('plot', editor=ComponentEditor()), - width=700, height=600, resizable=True, - ) + traits_view = View( + HGroup(UItem("error_button"), UItem("warn_button"), UItem("no_problem_button")), + UItem("plot", editor=ComponentEditor()), + width=700, + height=600, + resizable=True, + ) def __init__(self, index, data_series, **kw): super(MyPlot, self).__init__(**kw) plot_data = ArrayPlotData(index=index) - plot_data.set_data('data_series', data_series) + plot_data.set_data("data_series", data_series) self.plot = Plot(plot_data) - self.plot.plot(('index', 'data_series')) + self.plot.plot(("index", "data_series")) def _error_button_fired(self, event): - """ removes the old overlay and replaces it with - an error overlay + """removes the old overlay and replaces it with + an error overlay """ self.clear_status() - self.status_overlay = ErrorLayer(component=self.plot, - align='ul', scale_factor=0.25) + self.status_overlay = ErrorLayer( + component=self.plot, align="ul", scale_factor=0.25 + ) self.plot.overlays.append(self.status_overlay) self.plot.request_redraw() def _warn_button_fired(self, event): - """ removes the old overlay and replaces it with - an warning overlay + """removes the old overlay and replaces it with + an warning overlay """ self.clear_status() - self.status_overlay = WarningLayer(component=self.plot, - align='ur', scale_factor=0.25) + self.status_overlay = WarningLayer( + component=self.plot, align="ur", scale_factor=0.25 + ) self.plot.overlays.append(self.status_overlay) self.plot.request_redraw() def _no_problem_button_fired(self, event): - """ removes the old overlay - """ + """removes the old overlay""" self.clear_status() self.plot.request_redraw() @@ -70,8 +74,9 @@ def clear_status(self): # fade_out will remove the overlay when its done self.status_overlay.fade_out() -index = numpy.array([1,2,3,4,5]) -data_series = index**2 + +index = numpy.array([1, 2, 3, 4, 5]) +data_series = index ** 2 my_plot = MyPlot(index, data_series) my_plot.configure_traits() diff --git a/examples/demo/toolbar_plot.py b/examples/demo/toolbar_plot.py index db78b815d..0f4ce2232 100644 --- a/examples/demo/toolbar_plot.py +++ b/examples/demo/toolbar_plot.py @@ -23,25 +23,26 @@ class ExamplePlotApp(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor(), - width = 600, height = 600, - show_label=False), - resizable=True) + traits_view = View( + Item("plot", editor=ComponentEditor(), width=600, height=600, show_label=False), + resizable=True, + ) def __init__(self, index, series1, series2, **kw): super(ExamplePlotApp, self).__init__(**kw) plot_data = ArrayPlotData(index=index) - plot_data.set_data('series1', series1) - plot_data.set_data('series2', series2) + plot_data.set_data("series1", series1) + plot_data.set_data("series2", series2) self.plot = ToolbarPlot(plot_data) - self.plot.plot(('index', 'series1'), color='auto') - self.plot.plot(('index', 'series2'), color='auto') + self.plot.plot(("index", "series1"), color="auto") + self.plot.plot(("index", "series2"), color="auto") -index = numpy.arange(1.0, 10., 0.01) -series1 = (100.0 + index) / (100.0 - 20*index**2 + 5.0*index**4) -series2 = (100.0 + index) / (100.0 - 20*index**2 + 5.0*index**3) + +index = numpy.arange(1.0, 10.0, 0.01) +series1 = (100.0 + index) / (100.0 - 20 * index ** 2 + 5.0 * index ** 4) +series2 = (100.0 + index) / (100.0 - 20 * index ** 2 + 5.0 * index ** 3) demo = ExamplePlotApp(index, series1, series2) -if __name__== '__main__': +if __name__ == "__main__": demo.configure_traits() diff --git a/examples/demo/tornado.py b/examples/demo/tornado.py index 4aa6ecf28..08c54caeb 100644 --- a/examples/demo/tornado.py +++ b/examples/demo/tornado.py @@ -9,36 +9,59 @@ from traitsui.api import Item, View # Chaco imports -from chaco.api import ArrayDataSource, BarPlot, DataRange1D, LabelAxis, \ - LinearMapper, OverlayPlotContainer, PlotAxis +from chaco.api import ( + ArrayDataSource, + BarPlot, + DataRange1D, + LabelAxis, + LinearMapper, + OverlayPlotContainer, + PlotAxis, +) from chaco.example_support import COLOR_PALETTE + class PlotExample(HasTraits): plot = Instance(Component) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - resizable=True, title="Tornado Plot", - width=800, height=600 - ) + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + resizable=True, + title="Tornado Plot", + width=800, + height=600, + ) def _plot_default(self): - container = OverlayPlotContainer(bgcolor = "white") + container = OverlayPlotContainer(bgcolor="white") plots = self._make_curves() for plot in plots: plot.padding = 60 container.add(plot) - bottom_axis = PlotAxis(plot, orientation='bottom') - - label_list=['var a', 'var b', 'var c', 'var d', 'var e', 'var f', - 'var g', 'var h', 'var i'] - vertical_axis = LabelAxis(plot, orientation='left', - title='Categories', - positions = list(range(1, 10)), - labels=label_list) - vertical2_axis = LabelAxis(plot, orientation='right', - positions = list(range(1, 10)), - labels=label_list) + bottom_axis = PlotAxis(plot, orientation="bottom") + + label_list = [ + "var a", + "var b", + "var c", + "var d", + "var e", + "var f", + "var g", + "var h", + "var i", + ] + vertical_axis = LabelAxis( + plot, + orientation="left", + title="Categories", + positions=list(range(1, 10)), + labels=label_list, + ) + vertical2_axis = LabelAxis( + plot, orientation="right", positions=list(range(1, 10)), labels=label_list + ) plot.underlays.append(vertical_axis) plot.underlays.append(vertical2_axis) @@ -47,7 +70,7 @@ def _plot_default(self): return container def _get_points(self): - index = linspace(pi/4, 3*pi/2, 9) + index = linspace(pi / 4, 3 * pi / 2, 9) data = sin(index) + 2 return (list(range(1, 10)), data) @@ -55,10 +78,10 @@ def _make_curves(self): (index_points, value_points) = self._get_points() size = len(index_points) - middle_value=2500000.0 - mid_values=middle_value*ones(size) - low_values=mid_values-10000.0*value_points - high_values=mid_values+20000.0*value_points + middle_value = 2500000.0 + mid_values = middle_value * ones(size) + low_values = mid_values - 10000.0 * value_points + high_values = mid_values + 20000.0 * value_points idx = ArrayDataSource(index_points) vals = ArrayDataSource(low_values, sort_order="none") @@ -73,28 +96,37 @@ def _make_curves(self): index_mapper = LinearMapper(range=index_range) # Create the value range - value_range = DataRange1D(vals, vals2, low_setting='auto', - high_setting='auto', tight_bounds=False) - value_mapper = LinearMapper(range=value_range,tight_bounds=False) + value_range = DataRange1D( + vals, vals2, low_setting="auto", high_setting="auto", tight_bounds=False + ) + value_mapper = LinearMapper(range=value_range, tight_bounds=False) # Create the plot - plot1 = BarPlot(index=idx, value=vals, - value_mapper=value_mapper, - index_mapper=index_mapper, - starting_value=starting_vals, - line_color='black', - orientation='v', - fill_color=tuple(COLOR_PALETTE[6]), - bar_width=0.8, antialias=False) - - plot2 = BarPlot(index=idx2, value=vals2, - value_mapper=value_mapper, - index_mapper=index_mapper, - starting_value=starting_vals, - line_color='black', - orientation='v', - fill_color=tuple(COLOR_PALETTE[1]), - bar_width=0.8, antialias=False) + plot1 = BarPlot( + index=idx, + value=vals, + value_mapper=value_mapper, + index_mapper=index_mapper, + starting_value=starting_vals, + line_color="black", + orientation="v", + fill_color=tuple(COLOR_PALETTE[6]), + bar_width=0.8, + antialias=False, + ) + + plot2 = BarPlot( + index=idx2, + value=vals2, + value_mapper=value_mapper, + index_mapper=index_mapper, + starting_value=starting_vals, + line_color="black", + orientation="v", + fill_color=tuple(COLOR_PALETTE[1]), + bar_width=0.8, + antialias=False, + ) return [plot1, plot2] diff --git a/examples/demo/two_plots.py b/examples/demo/two_plots.py index c55b42e55..610d70ffc 100644 --- a/examples/demo/two_plots.py +++ b/examples/demo/two_plots.py @@ -14,9 +14,10 @@ from chaco.tools.api import LineInspector, ZoomTool, PanTool -#============================================================================== +# ============================================================================== # # Create the Chaco plot. -#============================================================================== +# ============================================================================== + def _create_plot_component(): @@ -31,14 +32,13 @@ def _create_plot_component(): left_plot = Plot(plotdata) left_plot.x_axis.title = "X" left_plot.y_axis.title = "j0(x)" - renderer = left_plot.plot(("x", "y1"), type="line", color="blue", - width=2.0)[0] - renderer.overlays.append(LineInspector(renderer, axis='value', - write_metadata=True, - is_listener=True)) - renderer.overlays.append(LineInspector(renderer, axis="index", - write_metadata=True, - is_listener=True)) + renderer = left_plot.plot(("x", "y1"), type="line", color="blue", width=2.0)[0] + renderer.overlays.append( + LineInspector(renderer, axis="value", write_metadata=True, is_listener=True) + ) + renderer.overlays.append( + LineInspector(renderer, axis="index", write_metadata=True, is_listener=True) + ) left_plot.overlays.append(ZoomTool(left_plot, tool_mode="range")) left_plot.tools.append(PanTool(left_plot)) @@ -48,13 +48,12 @@ def _create_plot_component(): right_plot.orientation = "v" right_plot.x_axis.title = "j1(x)" right_plot.y_axis.title = "X" - renderer2 = right_plot.plot(("x", "y2"), type="line", color="red", - width=2.0)[0] + renderer2 = right_plot.plot(("x", "y2"), type="line", color="red", width=2.0)[0] renderer2.index = renderer.index - renderer2.overlays.append(LineInspector(renderer2, write_metadata=True, - is_listener=True)) - renderer2.overlays.append(LineInspector(renderer2, axis="value", - is_listener=True)) + renderer2.overlays.append( + LineInspector(renderer2, write_metadata=True, is_listener=True) + ) + renderer2.overlays.append(LineInspector(renderer2, axis="value", is_listener=True)) right_plot.overlays.append(ZoomTool(right_plot, tool_mode="range")) right_plot.tools.append(PanTool(right_plot)) @@ -65,31 +64,34 @@ def _create_plot_component(): return container -#============================================================================== +# ============================================================================== # Attributes to use for the plot view. size = (750, 500) title = "Two Plots" -#============================================================================== +# ============================================================================== # # Demo class that is used by the demo.py application. -#============================================================================== +# ============================================================================== + class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation="vertical"), - resizable=True, title=title, - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + ) def _plot_default(self): return _create_plot_component() + demo = Demo() if __name__ == "__main__": diff --git a/examples/demo/updating_plot/updating_plot1.py b/examples/demo/updating_plot/updating_plot1.py index 47e701503..6821eeb82 100644 --- a/examples/demo/updating_plot/updating_plot1.py +++ b/examples/demo/updating_plot/updating_plot1.py @@ -29,26 +29,25 @@ class PlotFrame(DemoFrame): - def _create_data(self): numpoints = 100 low = -5 high = 15.0 - x = arange(low, high, (high-low)/numpoints) - y = jn(0, x) # use the j0 bessel function + x = arange(low, high, (high - low) / numpoints) + y = jn(0, x) # use the j0 bessel function self.numpoints = numpoints self.x_values = x self.y_values = y - self.current_index = numpoints/2 + self.current_index = numpoints / 2 self.increment = 2 def _create_window(self): self._create_data() - x = self.x_values[:self.current_index] - y = self.y_values[:self.current_index] + x = self.x_values[: self.current_index] + y = self.y_values[: self.current_index] - plot = create_line_plot((x,y), color="red", width=2.0) + plot = create_line_plot((x, y), color="red", width=2.0) plot.padding = 50 plot.fill_padding = True plot.bgcolor = "white" @@ -57,18 +56,16 @@ def _create_window(self): bottom.tick_interval = 2.0 vgrid.grid_interval = 2.0 - self.plot = plot plot.tools.append(PanTool(component=plot)) - plot.overlays.append(ZoomTool(component=plot, tool_mode="box", - always_on=False)) + plot.overlays.append(ZoomTool(component=plot, tool_mode="box", always_on=False)) self.timer = Timer(50.0, self.onTimer) return Window(self, -1, component=plot) def onTimer(self, *args): # adjust the index and increment - if self.current_index <= self.numpoints/8: + if self.current_index <= self.numpoints / 8: self.increment = 2 elif self.current_index == self.numpoints: self.increment = -2 @@ -77,8 +74,8 @@ def onTimer(self, *args): if self.current_index > self.numpoints: self.current_index = self.numpoints - self.plot.index.set_data(self.x_values[:self.current_index]) - self.plot.value.set_data(self.y_values[:self.current_index]) + self.plot.index.set_data(self.x_values[: self.current_index]) + self.plot.value.set_data(self.y_values[: self.current_index]) self.plot.request_redraw() diff --git a/examples/demo/updating_plot/updating_plot2.py b/examples/demo/updating_plot/updating_plot2.py index dfba28a4a..eb594fa4b 100644 --- a/examples/demo/updating_plot/updating_plot2.py +++ b/examples/demo/updating_plot/updating_plot2.py @@ -23,21 +23,31 @@ from chaco.tools.api import MoveTool, PanTool, ZoomTool -COLOR_PALETTE = ("mediumslateblue", "maroon", "darkgreen", "goldenrod", - "purple", "indianred") +COLOR_PALETTE = ( + "mediumslateblue", + "maroon", + "darkgreen", + "goldenrod", + "purple", + "indianred", +) PLOT_SIZE = 250 class AnimatedPlot(HasTraits): - def __init__(self, x, y, color="blue", bgcolor="white"): self.x_values = x[:] self.y_values = y[:] self.numpoints = len(self.x_values) - plot = create_line_plot((self.x_values,self.y_values), color=color, - bgcolor=bgcolor, add_grid=True, add_axis=True) + plot = create_line_plot( + (self.x_values, self.y_values), + color=color, + bgcolor=bgcolor, + add_grid=True, + add_axis=True, + ) plot.resizable = "" plot.bounds = [PLOT_SIZE, PLOT_SIZE] @@ -48,40 +58,41 @@ def __init__(self, x, y, color="blue", bgcolor="white"): plot.unified_draw = True self.plot = plot - self.current_index = self.numpoints/2 + self.current_index = self.numpoints / 2 self.increment = 2 def timer_tick(self): - if self.current_index <= self.numpoints/3: + if self.current_index <= self.numpoints / 3: self.increment = 2 elif self.current_index == self.numpoints: self.increment = -2 self.current_index += self.increment if self.current_index > self.numpoints: self.current_index = self.numpoints - self.plot.index.set_data(self.x_values[:self.current_index]) - self.plot.value.set_data(self.y_values[:self.current_index]) + self.plot.index.set_data(self.x_values[: self.current_index]) + self.plot.value.set_data(self.y_values[: self.current_index]) self.plot.request_redraw() class PlotFrame(DemoFrame): - def _create_window(self): numpoints = 50 low = -5 high = 15.0 - x = arange(low, high, (high-low)/numpoints) + x = arange(low, high, (high - low) / numpoints) container = OverlayPlotContainer(bgcolor="lightgray") self.animated_plots = [] for i, color in enumerate(COLOR_PALETTE): - animated_plot = AnimatedPlot(x, jn(i,x), color) + animated_plot = AnimatedPlot(x, jn(i, x), color) container.add(animated_plot.plot) self.animated_plots.append(animated_plot) for i, a_plot in enumerate(self.animated_plots): - a_plot.plot.position = [50 + (i%3)*(PLOT_SIZE+50), - 50 + (i//3)*(PLOT_SIZE+50)] + a_plot.plot.position = [ + 50 + (i % 3) * (PLOT_SIZE + 50), + 50 + (i // 3) * (PLOT_SIZE + 50), + ] self.timer = Timer(100.0, self.onTimer) self.container = container diff --git a/examples/demo/updating_plot/updating_plot3.py b/examples/demo/updating_plot/updating_plot3.py index 18d39df2f..941f0a97e 100644 --- a/examples/demo/updating_plot/updating_plot3.py +++ b/examples/demo/updating_plot/updating_plot3.py @@ -19,26 +19,39 @@ from chaco.tools.api import MoveTool, PanTool, ZoomTool -COLOR_PALETTE = ("mediumslateblue", "maroon", "darkgreen", "goldenrod", - "purple", "indianred") +COLOR_PALETTE = ( + "mediumslateblue", + "maroon", + "darkgreen", + "goldenrod", + "purple", + "indianred", +) PLOT_SIZE = 250 class AnimatedPlot(HasTraits): - def __init__(self, x, y, color="blue", bgcolor="white"): self.y_values = y[:] if type(x) == ArrayDataSource: self.x_values = x.get_data()[:] - plot = create_line_plot((x, self.y_values), color=color, - bgcolor=bgcolor, add_grid=True, - add_axis=True) + plot = create_line_plot( + (x, self.y_values), + color=color, + bgcolor=bgcolor, + add_grid=True, + add_axis=True, + ) else: self.x_values = x[:] - plot = create_line_plot((self.x_values,self.y_values), color=color, - bgcolor=bgcolor, add_grid=True, - add_axis=True) + plot = create_line_plot( + (self.x_values, self.y_values), + color=color, + bgcolor=bgcolor, + add_grid=True, + add_axis=True, + ) plot.resizable = "" plot.bounds = [PLOT_SIZE, PLOT_SIZE] @@ -50,29 +63,28 @@ def __init__(self, x, y, color="blue", bgcolor="white"): self.plot = plot self.numpoints = len(self.x_values) - self.current_index = self.numpoints/2 + self.current_index = self.numpoints / 2 self.increment = 2 def timer_tick(self): - if self.current_index <= self.numpoints/3: + if self.current_index <= self.numpoints / 3: self.increment = 2 elif self.current_index == self.numpoints: self.increment = -2 self.current_index += self.increment if self.current_index > self.numpoints: self.current_index = self.numpoints - self.plot.index.set_data(self.x_values[:self.current_index]) - self.plot.value.set_data(self.y_values[:self.current_index]) + self.plot.index.set_data(self.x_values[: self.current_index]) + self.plot.value.set_data(self.y_values[: self.current_index]) self.plot.request_redraw() class PlotFrame(DemoFrame): - def _create_window(self): numpoints = 50 low = -5 high = 15.0 - x = arange(low, high, (high-low)/numpoints) + x = arange(low, high, (high - low) / numpoints) container = OverlayPlotContainer(bgcolor="lightgray") common_index = None @@ -81,20 +93,22 @@ def _create_window(self): self.animated_plots = [] for i, color in enumerate(COLOR_PALETTE): if not common_index: - animated_plot = AnimatedPlot(x, jn(i,x), color) + animated_plot = AnimatedPlot(x, jn(i, x), color) common_index = animated_plot.plot.index index_range = animated_plot.plot.index_mapper.range value_range = animated_plot.plot.value_mapper.range else: - animated_plot = AnimatedPlot(common_index, jn(i,x), color) + animated_plot = AnimatedPlot(common_index, jn(i, x), color) animated_plot.plot.index_mapper.range = index_range animated_plot.plot.value_mapper.range = value_range container.add(animated_plot.plot) self.animated_plots.append(animated_plot) for i, a_plot in enumerate(self.animated_plots): - a_plot.plot.position = [50 + (i%3)*(PLOT_SIZE+50), - 50 + (i//3)*(PLOT_SIZE+50)] + a_plot.plot.position = [ + 50 + (i % 3) * (PLOT_SIZE + 50), + 50 + (i // 3) * (PLOT_SIZE + 50), + ] self.timer = Timer(100.0, self.onTimer) self.container = container diff --git a/examples/demo/updating_plot/updating_plot4.py b/examples/demo/updating_plot/updating_plot4.py index 5a3712e16..c74573c8a 100644 --- a/examples/demo/updating_plot/updating_plot4.py +++ b/examples/demo/updating_plot/updating_plot4.py @@ -22,26 +22,41 @@ from chaco.tools.api import MoveTool, PanTool, ZoomTool -COLOR_PALETTE = ("mediumslateblue", "maroon", "darkgreen", "goldenrod", - "purple", "indianred") +COLOR_PALETTE = ( + "mediumslateblue", + "maroon", + "darkgreen", + "goldenrod", + "purple", + "indianred", +) PLOT_SIZE = 250 class AnimatedPlot(HasTraits): - def __init__(self, x, y, color="blue", bgcolor="white", orientation="h"): self.y_values = y[:] if type(x) == ArrayDataSource: self.x_values = x.get_data()[:] - plot = create_line_plot((x, self.y_values), color=color, - bgcolor=bgcolor, add_grid=True, - add_axis=True, orientation=orientation) + plot = create_line_plot( + (x, self.y_values), + color=color, + bgcolor=bgcolor, + add_grid=True, + add_axis=True, + orientation=orientation, + ) else: self.x_values = x[:] - plot = create_line_plot((self.x_values,self.y_values), color=color, - bgcolor=bgcolor, add_grid=True, - add_axis=True, orientation=orientation) + plot = create_line_plot( + (self.x_values, self.y_values), + color=color, + bgcolor=bgcolor, + add_grid=True, + add_axis=True, + orientation=orientation, + ) plot.resizable = "" plot.bounds = [PLOT_SIZE, PLOT_SIZE] @@ -53,29 +68,28 @@ def __init__(self, x, y, color="blue", bgcolor="white", orientation="h"): self.plot = plot self.numpoints = len(self.x_values) - self.current_index = self.numpoints/2 + self.current_index = self.numpoints / 2 self.increment = 2 def timer_tick(self): - if self.current_index <= self.numpoints/3: + if self.current_index <= self.numpoints / 3: self.increment = 2 elif self.current_index == self.numpoints: self.increment = -2 self.current_index += self.increment if self.current_index > self.numpoints: self.current_index = self.numpoints - self.plot.index.set_data(self.x_values[:self.current_index]) - self.plot.value.set_data(self.y_values[:self.current_index]) + self.plot.index.set_data(self.x_values[: self.current_index]) + self.plot.value.set_data(self.y_values[: self.current_index]) self.plot.request_redraw() class PlotFrame(DemoFrame): - def _create_window(self): numpoints = 50 low = -5 high = 15.0 - x = arange(low, high, (high-low)/numpoints) + x = arange(low, high, (high - low) / numpoints) container = OverlayPlotContainer(bgcolor="lightgray") common_index = None @@ -84,7 +98,7 @@ def _create_window(self): self.animated_plots = [] for i, color in enumerate(COLOR_PALETTE): if not common_index: - animated_plot = AnimatedPlot(x, jn(i,x), color) + animated_plot = AnimatedPlot(x, jn(i, x), color) plot = animated_plot.plot common_index = plot.index index_range = plot.index_mapper.range @@ -94,8 +108,9 @@ def _create_window(self): orientation = "v" else: orientation = "h" - animated_plot = AnimatedPlot(common_index, jn(i,x), color, - orientation=orientation) + animated_plot = AnimatedPlot( + common_index, jn(i, x), color, orientation=orientation + ) plot = animated_plot.plot plot.index_mapper.range = index_range plot.value_mapper.range = value_range @@ -104,8 +119,10 @@ def _create_window(self): self.animated_plots.append(animated_plot) for i, a_plot in enumerate(self.animated_plots): - a_plot.plot.position = [50 + (i%3)*(PLOT_SIZE+50), - 50 + (i//3)*(PLOT_SIZE+50)] + a_plot.plot.position = [ + 50 + (i % 3) * (PLOT_SIZE + 50), + 50 + (i // 3) * (PLOT_SIZE + 50), + ] self.timer = Timer(100.0, self.onTimer) self.container = container diff --git a/examples/demo/updating_plot/updating_plot5.py b/examples/demo/updating_plot/updating_plot5.py index 0b89b0ac2..a1a4588c1 100644 --- a/examples/demo/updating_plot/updating_plot5.py +++ b/examples/demo/updating_plot/updating_plot5.py @@ -19,26 +19,41 @@ from chaco.tools.api import MoveTool, PanTool, ZoomTool -COLOR_PALETTE = ("mediumslateblue", "maroon", "darkgreen", "goldenrod", - "purple", "indianred") +COLOR_PALETTE = ( + "mediumslateblue", + "maroon", + "darkgreen", + "goldenrod", + "purple", + "indianred", +) PLOT_SIZE = 250 class AnimatedPlot(HasTraits): - def __init__(self, x, y, color="blue", bgcolor="none", orientation="h"): self.y_values = y[:] if type(x) == ArrayDataSource: self.x_values = x.get_data()[:] - plot = create_line_plot((x, self.y_values), color=color, - bgcolor=bgcolor, add_grid=True, - add_axis=True, orientation=orientation) + plot = create_line_plot( + (x, self.y_values), + color=color, + bgcolor=bgcolor, + add_grid=True, + add_axis=True, + orientation=orientation, + ) else: self.x_values = x[:] - plot = create_line_plot((self.x_values,self.y_values), color=color, - bgcolor=bgcolor, add_grid=True, - add_axis=True, orientation=orientation) + plot = create_line_plot( + (self.x_values, self.y_values), + color=color, + bgcolor=bgcolor, + add_grid=True, + add_axis=True, + orientation=orientation, + ) plot.resizable = "" plot.bounds = [PLOT_SIZE, PLOT_SIZE] @@ -50,29 +65,28 @@ def __init__(self, x, y, color="blue", bgcolor="none", orientation="h"): self.plot = plot self.numpoints = len(self.x_values) - self.current_index = self.numpoints/2 + self.current_index = self.numpoints / 2 self.increment = 2 def timer_tick(self): - if self.current_index <= self.numpoints/3: + if self.current_index <= self.numpoints / 3: self.increment = 2 elif self.current_index == self.numpoints: self.increment = -2 self.current_index += self.increment if self.current_index > self.numpoints: self.current_index = self.numpoints - self.plot.index.set_data(self.x_values[:self.current_index]) - self.plot.value.set_data(self.y_values[:self.current_index]) + self.plot.index.set_data(self.x_values[: self.current_index]) + self.plot.value.set_data(self.y_values[: self.current_index]) self.plot.request_redraw() class PlotFrame(DemoFrame): - def _create_window(self): numpoints = 50 low = -5 high = 15.0 - x = arange(low, high, (high-low)/numpoints) + x = arange(low, high, (high - low) / numpoints) container = OverlayPlotContainer(bgcolor="lightgray") common_index = None @@ -81,26 +95,28 @@ def _create_window(self): self.animated_plots = [] for i, color in enumerate(COLOR_PALETTE): if i == 0: - animated_plot = AnimatedPlot(x, jn(i,x), color) + animated_plot = AnimatedPlot(x, jn(i, x), color) plot = animated_plot.plot common_index = plot.index index_range = plot.index_mapper.range value_range = plot.value_mapper.range elif i % 2 == 0: - animated_plot = AnimatedPlot(common_index, jn(i,x), color) + animated_plot = AnimatedPlot(common_index, jn(i, x), color) plot = animated_plot.plot plot.index_mapper.range = index_range plot.value_mapper.range = value_range else: - animated_plot = AnimatedPlot(x, jn(i,x), color, orientation="v") + animated_plot = AnimatedPlot(x, jn(i, x), color, orientation="v") plot = animated_plot.plot container.add(plot) self.animated_plots.append(animated_plot) for i, a_plot in enumerate(self.animated_plots): - a_plot.plot.position = [50 + (i%3)*(PLOT_SIZE+50), - 50 + (i//3)*(PLOT_SIZE+50)] + a_plot.plot.position = [ + 50 + (i % 3) * (PLOT_SIZE + 50), + 50 + (i // 3) * (PLOT_SIZE + 50), + ] self.timer = Timer(100.0, self.onTimer) self.container = container diff --git a/examples/demo/vertical_plot.py b/examples/demo/vertical_plot.py index e953802df..b073e0a47 100644 --- a/examples/demo/vertical_plot.py +++ b/examples/demo/vertical_plot.py @@ -17,33 +17,37 @@ from enable.api import Component, ComponentEditor from traits.api import HasTraits, Instance from traitsui.api import Item, Group, View -from chaco.api import PlotLabel, VPlotContainer, HPlotContainer, \ - create_line_plot +from chaco.api import PlotLabel, VPlotContainer, HPlotContainer, create_line_plot # ====================================================================== # Change one or both of these to experiment with different orientations # of the plot containers and the lines within each plot: -container_class = HPlotContainer # HPlotContainer or VPlotContainer -plot_orientation = 'v' # 'v' or 'h' +container_class = HPlotContainer # HPlotContainer or VPlotContainer +plot_orientation = "v" # 'v' or 'h' # ====================================================================== -#=============================================================================== +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def _create_plot_component(): numpoints = 100 low = -5 high = 15.0 - x = arange(low, high, (high-low)/numpoints) - container = container_class(resizable = "hv", bgcolor="lightgray", - fill_padding=True, padding = 10) + x = arange(low, high, (high - low) / numpoints) + container = container_class( + resizable="hv", bgcolor="lightgray", fill_padding=True, padding=10 + ) # Plot some bessel functions value_range = None for i in range(10): y = jn(i, x) - plot = create_line_plot((x,y), color=tuple(COLOR_PALETTE[i]), width=2.0, - orientation=plot_orientation) + plot = create_line_plot( + (x, y), + color=tuple(COLOR_PALETTE[i]), + width=2.0, + orientation=plot_orientation, + ) plot.origin_axis_visible = True plot.origin = "top left" plot.padding_left = 10 @@ -55,40 +59,48 @@ def _create_plot_component(): else: plot.value_range = value_range value_range.add(plot.value) - if i%2 == 1: + if i % 2 == 1: plot.line_style = "dash" container.add(plot) container.padding_top = 50 - container.overlays.append(PlotLabel("Bessel Functions in a Strip Plot", - component=container, - font = "swiss 16", - overlay_position = "top")) + container.overlays.append( + PlotLabel( + "Bessel Functions in a Strip Plot", + component=container, + font="swiss 16", + overlay_position="top", + ) + ) return container -#=============================================================================== + +# =============================================================================== # Attributes to use for the plot view. -size=(800,600) -title="Vertical Line Plot" +size = (800, 600) +title = "Vertical Line Plot" -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): plot = Instance(Component) traits_view = View( - Group( - Item('plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title=title, - width=size[0], height=size[1] - ) + Group( + Item("plot", editor=ComponentEditor(size=size), show_label=False), + orientation="vertical", + ), + resizable=True, + title=title, + width=size[0], + height=size[1], + ) def _plot_default(self): - return _create_plot_component() + return _create_plot_component() + demo = Demo() diff --git a/examples/demo/vtk/cmap_scatter.py b/examples/demo/vtk/cmap_scatter.py index 077e029dd..a17edcd6d 100644 --- a/examples/demo/vtk/cmap_scatter.py +++ b/examples/demo/vtk/cmap_scatter.py @@ -20,22 +20,33 @@ # Chaco imports -from chaco.api import ArrayPlotData, ColorBar, \ - ColormappedSelectionOverlay, OverlayPlotContainer, \ - viridis, LinearMapper, Plot -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, \ - RangeSelectionOverlay, MoveTool - -#=============================================================================== +from chaco.api import ( + ArrayPlotData, + ColorBar, + ColormappedSelectionOverlay, + OverlayPlotContainer, + viridis, + LinearMapper, + Plot, +) +from chaco.tools.api import ( + PanTool, + ZoomTool, + RangeSelection, + RangeSelectionOverlay, + MoveTool, +) + +# =============================================================================== # # Create the Chaco plot. -#=============================================================================== +# =============================================================================== def create_plot(): # Create some data numpts = 200 x = sort(random(numpts)) y = random(numpts) - color = exp(-(x**2 + y**2)) + color = exp(-(x ** 2 + y ** 2)) # Create a plot data obect and give it this data pd = ArrayPlotData() @@ -45,16 +56,18 @@ def create_plot(): # Create the plot plot = Plot(pd) - plot.plot(("index", "value", "color"), - type="cmap_scatter", - name="my_plot", - color_mapper=viridis, - marker = "square", - fill_alpha = 0.5, - marker_size = 6, - outline_color = "black", - border_visible = True, - bgcolor = "white") + plot.plot( + ("index", "value", "color"), + type="cmap_scatter", + name="my_plot", + color_mapper=viridis, + marker="square", + fill_alpha=0.5, + marker_size=6, + outline_color="black", + border_visible=True, + bgcolor="white", + ) # Tweak some of the plot properties plot.title = "Colormapped Scatter Plot" @@ -65,8 +78,8 @@ def create_plot(): plot.y_axis.font = "modern 16" # Set colors - #plot.title_color = "white" - #for axis in plot.x_axis, plot.y_axis: + # plot.title_color = "white" + # for axis in plot.x_axis, plot.y_axis: # axis.trait_set(title_color="white", tick_label_color="white") # Right now, some of the tools are a little invasive, and we need the @@ -77,53 +90,67 @@ def create_plot(): plot.tools.append(PanTool(plot, constrain_key="shift")) zoom = ZoomTool(component=plot, tool_mode="box", always_on=False) plot.overlays.append(zoom) - selection = ColormappedSelectionOverlay(cmap_renderer, fade_alpha=0.35, - selection_type="mask") + selection = ColormappedSelectionOverlay( + cmap_renderer, fade_alpha=0.35, selection_type="mask" + ) cmap_renderer.overlays.append(selection) plot.tools.append(MoveTool(plot, drag_button="right")) return plot + def create_colorbar(colormap): - colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), - color_mapper=colormap, orientation='v', resizable='', - height=400, width=30, padding=20) + colorbar = ColorBar( + index_mapper=LinearMapper(range=colormap.range), + color_mapper=colormap, + orientation="v", + resizable="", + height=400, + width=30, + padding=20, + ) colorbar.tools.append(RangeSelection(component=colorbar)) - colorbar.overlays.append(RangeSelectionOverlay(component=colorbar, - border_color="white", alpha=0.8, fill_color="lightgray")) + colorbar.overlays.append( + RangeSelectionOverlay( + component=colorbar, border_color="white", alpha=0.8, fill_color="lightgray" + ) + ) colorbar.tools.append(MoveTool(colorbar, drag_button="left")) return colorbar + def start_vtk(component): - f = mlab.figure(size=(700,500)) + f = mlab.figure(size=(700, 500)) m = mlab.test_mesh() scene = mlab.gcf().scene render_window = scene.render_window renderer = scene.renderer rwi = scene.interactor - window = EnableVTKWindow(rwi, renderer, - component = component, - istyle_class = tvtk.InteractorStyleTrackballCamera, - bgcolor = "transparent", - event_passthrough = True, - ) + window = EnableVTKWindow( + rwi, + renderer, + component=component, + istyle_class=tvtk.InteractorStyleTrackballCamera, + bgcolor="transparent", + event_passthrough=True, + ) mlab.show() + def main(): plot = create_plot() - plot.bounds = [400,300] - plot.outer_position = [30,30] + plot.bounds = [400, 300] + plot.outer_position = [30, 30] plot.resizable = "" cmap_renderer = plot.plots["my_plot"][0] # Create the colorbar, handing in the appropriate range and colormap colorbar = create_colorbar(plot.color_mapper) - colorbar.outer_position = [450,30] + colorbar.outer_position = [450, 30] colorbar.plot = cmap_renderer colorbar.padding_top = plot.padding_top colorbar.padding_bottom = plot.padding_bottom - container = OverlayPlotContainer(bgcolor = "transparent", - fit_window = True) + container = OverlayPlotContainer(bgcolor="transparent", fit_window=True) container.add(plot) container.add(colorbar) @@ -132,4 +159,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/examples/demo/vtk/spectrum.py b/examples/demo/vtk/spectrum.py index 8d09bcdd7..7ae224d3a 100644 --- a/examples/demo/vtk/spectrum.py +++ b/examples/demo/vtk/spectrum.py @@ -25,64 +25,69 @@ def create_plot_component(obj): # Setup the spectrum plot - frequencies = linspace(0., float(SAMPLING_RATE)/2, num=NUM_SAMPLES/2) + frequencies = linspace(0.0, float(SAMPLING_RATE) / 2, num=NUM_SAMPLES / 2) obj.spectrum_data = ArrayPlotData(frequency=frequencies) - empty_amplitude = zeros(NUM_SAMPLES/2) - obj.spectrum_data.set_data('amplitude', empty_amplitude) + empty_amplitude = zeros(NUM_SAMPLES / 2) + obj.spectrum_data.set_data("amplitude", empty_amplitude) obj.spectrum_plot = Plot(obj.spectrum_data) - obj.spectrum_plot.plot(("frequency", "amplitude"), name="Spectrum", - color="red") + obj.spectrum_plot.plot(("frequency", "amplitude"), name="Spectrum", color="red") obj.spectrum_plot.padding = 50 obj.spectrum_plot.title = "Spectrum" spec_range = list(obj.spectrum_plot.plots.values())[0][0].value_mapper.range spec_range.low = 0.0 spec_range.high = 5.0 - obj.spectrum_plot.index_axis.title = 'Frequency (hz)' - obj.spectrum_plot.value_axis.title = 'Amplitude' + obj.spectrum_plot.index_axis.title = "Frequency (hz)" + obj.spectrum_plot.value_axis.title = "Amplitude" # Time Series plot - times = linspace(0., float(NUM_SAMPLES)/SAMPLING_RATE, num=NUM_SAMPLES) + times = linspace(0.0, float(NUM_SAMPLES) / SAMPLING_RATE, num=NUM_SAMPLES) obj.time_data = ArrayPlotData(time=times) empty_amplitude = zeros(NUM_SAMPLES) - obj.time_data.set_data('amplitude', empty_amplitude) + obj.time_data.set_data("amplitude", empty_amplitude) obj.time_plot = Plot(obj.time_data) obj.time_plot.plot(("time", "amplitude"), name="Time", color="blue") obj.time_plot.padding = 50 obj.time_plot.title = "Time" - obj.time_plot.index_axis.title = 'Time (seconds)' - obj.time_plot.value_axis.title = 'Amplitude' + obj.time_plot.index_axis.title = "Time (seconds)" + obj.time_plot.value_axis.title = "Amplitude" time_range = list(obj.time_plot.plots.values())[0][0].value_mapper.range time_range.low = -0.2 time_range.high = 0.2 # Spectrogram plot - spectrogram_data = zeros(( NUM_SAMPLES/2, SPECTROGRAM_LENGTH)) + spectrogram_data = zeros((NUM_SAMPLES / 2, SPECTROGRAM_LENGTH)) obj.spectrogram_plotdata = ArrayPlotData() - obj.spectrogram_plotdata.set_data('imagedata', spectrogram_data) + obj.spectrogram_plotdata.set_data("imagedata", spectrogram_data) spectrogram_plot = Plot(obj.spectrogram_plotdata) spectrogram_time = linspace( - 0.0, float(SPECTROGRAM_LENGTH*NUM_SAMPLES)/float(SAMPLING_RATE), - num=SPECTROGRAM_LENGTH) - spectrogram_freq = linspace(0.0, float(SAMPLING_RATE/2), num=NUM_SAMPLES/2) + 0.0, + float(SPECTROGRAM_LENGTH * NUM_SAMPLES) / float(SAMPLING_RATE), + num=SPECTROGRAM_LENGTH, + ) + spectrogram_freq = linspace(0.0, float(SAMPLING_RATE / 2), num=NUM_SAMPLES / 2) xbounds = (spectrogram_time[0], spectrogram_time[-1]) ybounds = (spectrogram_freq[0], spectrogram_freq[-1]) - spectrogram_plot.img_plot('imagedata', - name='Spectrogram', - xbounds=xbounds, - ybounds=ybounds, - colormap=viridis, - ) - range_obj = spectrogram_plot.plots['Spectrogram'][0].value_mapper.range + spectrogram_plot.img_plot( + "imagedata", + name="Spectrogram", + xbounds=xbounds, + ybounds=ybounds, + colormap=viridis, + ) + range_obj = spectrogram_plot.plots["Spectrogram"][0].value_mapper.range range_obj.high = 5 range_obj.low = 0.0 - spectrogram_plot.title = 'Spectrogram' + spectrogram_plot.title = "Spectrogram" obj.spectrogram_plot = spectrogram_plot return obj.spectrum_plot, obj.time_plot, obj.spectrogram_plot + _stream = None + + def get_audio_data(): global _stream if _stream is None: @@ -90,13 +95,18 @@ def get_audio_data(): # The stream is always closed (if it was opened) in a try finally # block at the end of this file, pa = pyaudio.PyAudio() - _stream = pa.open(format=pyaudio.paInt16, channels=1, - rate=SAMPLING_RATE, - input=True, frames_per_buffer=NUM_SAMPLES) - - audio_data = fromstring(_stream.read(NUM_SAMPLES), dtype=short) + _stream = pa.open( + format=pyaudio.paInt16, + channels=1, + rate=SAMPLING_RATE, + input=True, + frames_per_buffer=NUM_SAMPLES, + ) + + audio_data = fromstring(_stream.read(NUM_SAMPLES), dtype=short) normalized_data = audio_data / 32768.0 - return (abs(fft(normalized_data))[:NUM_SAMPLES/2], normalized_data) + return (abs(fft(normalized_data))[: NUM_SAMPLES / 2], normalized_data) + class TimerController(HasTraits): interactor = Any() @@ -107,13 +117,12 @@ def on_timer(self, vtk_obj=None, eventname=""): spectrum, time = get_audio_data() except IOError: return - self.spectrum_data.set_data('amplitude', spectrum) - self.time_data.set_data('amplitude', time) - spectrogram_data = self.spectrogram_plotdata.get_data('imagedata') - spectrogram_data = hstack((spectrogram_data[:,1:], - transpose([spectrum]))) + self.spectrum_data.set_data("amplitude", spectrum) + self.time_data.set_data("amplitude", time) + spectrogram_data = self.spectrogram_plotdata.get_data("imagedata") + spectrogram_data = hstack((spectrogram_data[:, 1:], transpose([spectrum]))) - self.spectrogram_plotdata.set_data('imagedata', spectrogram_data) + self.spectrogram_plotdata.set_data("imagedata", spectrogram_data) self.spectrum_plot.request_redraw() @@ -121,7 +130,8 @@ def main(): from tvtk.api import tvtk from mayavi import mlab from enable.vtk_backend.vtk_window import EnableVTKWindow - f = mlab.figure(size=(900,850)) + + f = mlab.figure(size=(900, 850)) m = mlab.test_mesh() scene = mlab.gcf().scene render_window = scene.render_window @@ -136,9 +146,9 @@ def main(): for i, p in enumerate(plots): p.resizable = "" p.bgcolor = "transparent" - p.bounds = [200,200] + p.bounds = [200, 200] p.outer_x = 0 - p.outer_y = i*250 + p.outer_y = i * 250 p.tools.append(MoveTool(p, drag_button="right")) p.tools.append(PanTool(p)) p.tools.append(ZoomTool(p)) @@ -148,20 +158,21 @@ def main(): spectrogram.tools[-2].constrain = True spectrogram.tools[-2].constrain_direction = "y" - container = OverlayPlotContainer(bgcolor = "transparent", - fit_window = True) + container = OverlayPlotContainer(bgcolor="transparent", fit_window=True) container.add(*plots) container.timer_callback = timer_controller.on_timer - window = EnableVTKWindow(rwi, renderer, - component = container, - istyle_class = tvtk.InteractorStyleTrackballCamera, - bgcolor = "transparent", - event_passthrough = True, - ) + window = EnableVTKWindow( + rwi, + renderer, + component=container, + istyle_class=tvtk.InteractorStyleTrackballCamera, + bgcolor="transparent", + event_passthrough=True, + ) mlab.show() + if __name__ == "__main__": main() - diff --git a/examples/demo/vtk/vtk_example.py b/examples/demo/vtk/vtk_example.py index f5fa74bc0..d0809c281 100644 --- a/examples/demo/vtk/vtk_example.py +++ b/examples/demo/vtk/vtk_example.py @@ -1,4 +1,3 @@ - from numpy import linspace from scipy.special import jn @@ -8,16 +7,23 @@ from chaco.api import ArrayPlotData, Plot, OverlayPlotContainer from chaco.tools.api import PanTool, ZoomTool, MoveTool + def main(): # Create some x-y data series to plot x = linspace(-2.0, 10.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) for i in range(5): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) # Create some line plots of some of the data - plot = Plot(pd, bgcolor="none", padding=30, border_visible=True, - overlay_border=True, use_backbuffer=False) + plot = Plot( + pd, + bgcolor="none", + padding=30, + border_visible=True, + overlay_border=True, + use_backbuffer=False, + ) plot.legend.visible = True plot.plot(("index", "y0", "y1", "y2"), name="j_n, n<3", color="auto") plot.plot(("index", "y3"), name="j_3", color="auto") @@ -27,7 +33,7 @@ def main(): # Create the mlab test mesh and get references to various parts of the # VTK pipeline - f = mlab.figure(size=(600,500)) + f = mlab.figure(size=(600, 500)) m = mlab.test_mesh() scene = mlab.gcf().scene render_window = scene.render_window @@ -35,29 +41,30 @@ def main(): rwi = scene.interactor plot.resizable = "" - plot.bounds = [200,200] + plot.bounds = [200, 200] plot.padding = 25 plot.bgcolor = "lightgray" - plot.outer_position = [30,30] - plot.tools.append(MoveTool(component=plot,drag_button="right")) + plot.outer_position = [30, 30] + plot.tools.append(MoveTool(component=plot, drag_button="right")) - container = OverlayPlotContainer(bgcolor = "transparent", - fit_window = True) + container = OverlayPlotContainer(bgcolor="transparent", fit_window=True) container.add(plot) # Create the Enable Window - window = EnableVTKWindow(rwi, renderer, - component=container, - #istyle_class = tvtk.InteractorStyleSwitch, - #istyle_class = tvtk.InteractorStyle, - istyle_class = tvtk.InteractorStyleTrackballCamera, - bgcolor = "transparent", - event_passthrough = True, - ) + window = EnableVTKWindow( + rwi, + renderer, + component=container, + # istyle_class = tvtk.InteractorStyleSwitch, + # istyle_class = tvtk.InteractorStyle, + istyle_class=tvtk.InteractorStyleTrackballCamera, + bgcolor="transparent", + event_passthrough=True, + ) mlab.show() return window, render_window -if __name__=="__main__": - main() +if __name__ == "__main__": + main() diff --git a/examples/demo/vtk_example.py b/examples/demo/vtk_example.py index 068403386..87c8a0571 100644 --- a/examples/demo/vtk_example.py +++ b/examples/demo/vtk_example.py @@ -11,16 +11,23 @@ from chaco.api import ArrayPlotData, Plot, OverlayPlotContainer from chaco.tools.api import PanTool, ZoomTool, MoveTool + def main(): # Create some x-y data series to plot x = linspace(-2.0, 10.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) for i in range(5): - pd.set_data("y" + str(i), jn(i,x)) + pd.set_data("y" + str(i), jn(i, x)) # Create some line plots of some of the data - plot = Plot(pd, bgcolor="none", padding=30, border_visible=True, - overlay_border=True, use_backbuffer=False) + plot = Plot( + pd, + bgcolor="none", + padding=30, + border_visible=True, + overlay_border=True, + use_backbuffer=False, + ) plot.legend.visible = True plot.plot(("index", "y0", "y1", "y2"), name="j_n, n<3", color="auto") plot.plot(("index", "y3"), name="j_3", color="auto") @@ -30,7 +37,7 @@ def main(): # Create the mlab test mesh and get references to various parts of the # VTK pipeline - f = mlab.figure(size=(600,500)) + f = mlab.figure(size=(600, 500)) m = mlab.test_mesh() scene = mlab.gcf().scene render_window = scene.render_window @@ -38,28 +45,29 @@ def main(): rwi = scene.interactor plot.resizable = "" - plot.bounds = [200,200] + plot.bounds = [200, 200] plot.padding = 25 - plot.outer_position = [30,30] - plot.tools.append(MoveTool(component=plot,drag_button="right")) + plot.outer_position = [30, 30] + plot.tools.append(MoveTool(component=plot, drag_button="right")) - container = OverlayPlotContainer(bgcolor = "transparent", - fit_window = True) + container = OverlayPlotContainer(bgcolor="transparent", fit_window=True) container.add(plot) # Create the Enable Window - window = EnableVTKWindow(rwi, renderer, - component=container, - #istyle_class = tvtk.InteractorStyleSwitch, - #istyle_class = tvtk.InteractorStyle, - istyle_class = tvtk.InteractorStyleTrackballCamera, - bgcolor = "transparent", - event_passthrough = True, - ) + window = EnableVTKWindow( + rwi, + renderer, + component=container, + # istyle_class = tvtk.InteractorStyleSwitch, + # istyle_class = tvtk.InteractorStyle, + istyle_class=tvtk.InteractorStyleTrackballCamera, + bgcolor="transparent", + event_passthrough=True, + ) mlab.show() return window, render_window -if __name__=="__main__": - main() +if __name__ == "__main__": + main() diff --git a/examples/demo/world_map.py b/examples/demo/world_map.py index 5caa52a14..312fa549a 100644 --- a/examples/demo/world_map.py +++ b/examples/demo/world_map.py @@ -24,6 +24,7 @@ from traits.api import HasTraits, Instance, Str from traitsui.api import Item, View + class WorldMapPlot(HasTraits): ### Public Traits ########################################################## @@ -34,20 +35,20 @@ class WorldMapPlot(HasTraits): # The URL which points to the world map image to be downloaded image_url = Str("http://eoimages.gsfc.nasa.gov/ve//2433/land_shallow_topo_2048.jpg") - ### Private Traits ######################################################### # The path to where the image exists on the filesystem image_path = Str() # The view - traits_view = View(Item('plot', editor=ComponentEditor(), - width=800, height=400, show_label=False), - resizable=True) + traits_view = View( + Item("plot", editor=ComponentEditor(), width=800, height=400, show_label=False), + resizable=True, + ) - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Public interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def __init__(self, **kw): super(WorldMapPlot, self).__init__(**kw) @@ -65,8 +66,8 @@ def __init__(self, **kw): # transform each of the locations to the image data space, including # moving the origin from bottom left to top left - locations_x = (locations_x + 180) * image.data.shape[1]/360 - locations_y = (locations_y*-1 + 90) * image.data.shape[0]/180 + locations_x = (locations_x + 180) * image.data.shape[1] / 360 + locations_y = (locations_y * -1 + 90) * image.data.shape[0] / 180 # Create the plott data, adding the image and the locations plot_data = ArrayPlotData() @@ -77,13 +78,17 @@ def __init__(self, **kw): # Create the plot with the origin as top left, which matches # how the image data is aligned self.plot = Plot(plot_data, default_origin="top left") - self.plot.img_plot('imagedata') + self.plot.img_plot("imagedata") # Plot the locations as a scatter plot to be overlayed on top # of the map - loc_plot = self.plot.plot(('locations_x', 'locations_y'), - type='scatter', size=3, color='yellow', - marker='dot')[0] + loc_plot = self.plot.plot( + ("locations_x", "locations_y"), + type="scatter", + size=3, + color="yellow", + marker="dot", + )[0] loc_plot.x_mapper.range.high = image.data.shape[1] loc_plot.x_mapper.range.low = 0 @@ -94,26 +99,28 @@ def __init__(self, **kw): zoom = ZoomTool(component=self.plot, tool_mode="box", always_on=False) self.plot.overlays.append(zoom) - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- # Protected interface - #--------------------------------------------------------------------------- + # --------------------------------------------------------------------------- def _download_map_image(self): - """ Downloads a map from the image_url attribute. This is done - primarily to keep the redistributable Chaco package as small - as possible + """Downloads a map from the image_url attribute. This is done + primarily to keep the redistributable Chaco package as small + as possible """ example_dir = os.path.dirname(__file__) - self.image_path = os.path.join(example_dir, 'data', - os.path.split(self.image_url)[1]) + self.image_path = os.path.join( + example_dir, "data", os.path.split(self.image_url)[1] + ) if not os.path.exists(self.image_path): print("Downloading map image") request.urlretrieve(self.image_url, self.image_path) -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = WorldMapPlot() if __name__ == "__main__": diff --git a/examples/demo/xray_plot.py b/examples/demo/xray_plot.py index 0c9d2d0ed..b51552081 100644 --- a/examples/demo/xray_plot.py +++ b/examples/demo/xray_plot.py @@ -3,7 +3,6 @@ """ - import numpy from traits.api import HasTraits, Instance, Enum @@ -15,14 +14,14 @@ class BoxSelectTool(BaseTool): - """ Tool for selecting all points within a box + """Tool for selecting all points within a box - There are 2 states for this tool, normal and selecting. While the - left mouse button is down the metadata on the datasources will be - updated with the current selected bounds. + There are 2 states for this tool, normal and selecting. While the + left mouse button is down the metadata on the datasources will be + updated with the current selected bounds. - Note that the tool does not actually store the selected point, but the - bounds of the box. + Note that the tool does not actually store the selected point, but the + bounds of the box. """ event_state = Enum("normal", "selecting") @@ -39,15 +38,15 @@ def selecting_mouse_move(self, event): x2, y2 = self.map_to_data(event.x + 25, event.y + 25) index_datasource = self.component.index - index_datasource.metadata['selections'] = (x1, x2) + index_datasource.metadata["selections"] = (x1, x2) value_datasource = self.component.value - value_datasource.metadata['selections'] = (y1, y2) + value_datasource.metadata["selections"] = (y1, y2) self.component.request_redraw() def map_to_data(self, x, y): - """ Returns the data space coordinates of the given x and y. + """Returns the data space coordinates of the given x and y. Takes into account orientation of the plot and the axis setting. """ @@ -64,15 +63,15 @@ def map_to_data(self, x, y): class XRayOverlay(AbstractOverlay): - """ Overlay which draws scatter markers on top of plot data points. + """Overlay which draws scatter markers on top of plot data points. - This overlay should be combined with a tool which updates the - datasources metadata with selection bounds. + This overlay should be combined with a tool which updates the + datasources metadata with selection bounds. """ marker = DotMarker() - def overlay(self, component, gc, view_bounds=None, mode='normal'): + def overlay(self, component, gc, view_bounds=None, mode="normal"): x_range = self._get_selection_index_screen_range() y_range = self._get_selection_value_screen_range() @@ -92,7 +91,7 @@ def overlay(self, component, gc, view_bounds=None, mode='normal'): if len(pts) == 0: return screen_pts = self.component.map_screen(pts) - if hasattr(gc, 'draw_marker_at_points'): + if hasattr(gc, "draw_marker_at_points"): gc.draw_marker_at_points(screen_pts, 3, DOT_MARKER) else: gc.save_state() @@ -105,21 +104,23 @@ def overlay(self, component, gc, view_bounds=None, mode='normal'): gc.restore_state() def _get_selected_points(self): - """ gets all the points within the bounds defined in the datasources - metadata + """gets all the points within the bounds defined in the datasources + metadata """ index_datasource = self.component.index - index_selection = index_datasource.metadata['selections'] + index_selection = index_datasource.metadata["selections"] index = index_datasource.get_data() value_datasource = self.component.value - value_selection = value_datasource.metadata['selections'] + value_selection = value_datasource.metadata["selections"] value = value_datasource.get_data() - x_indices = numpy.where((index > index_selection[0]) & - (index < index_selection[-1])) - y_indices = numpy.where((value > value_selection[0]) & - (value < value_selection[-1])) + x_indices = numpy.where( + (index > index_selection[0]) & (index < index_selection[-1]) + ) + y_indices = numpy.where( + (value > value_selection[0]) & (value < value_selection[-1]) + ) indices = list(set(x_indices[0]) & set(y_indices[0])) @@ -129,21 +130,21 @@ def _get_selected_points(self): return list(zip(sel_index, sel_value)) def _get_selection_index_screen_range(self): - """ maps the selected bounds which were set by the tool into screen - space. The screen space points can be used for drawing the overlay + """maps the selected bounds which were set by the tool into screen + space. The screen space points can be used for drawing the overlay """ index_datasource = self.component.index index_mapper = self.component.index_mapper - index_selection = index_datasource.metadata['selections'] + index_selection = index_datasource.metadata["selections"] return tuple(index_mapper.map_screen(numpy.array(index_selection))) def _get_selection_value_screen_range(self): - """ maps the selected bounds which were set by the tool into screen - space. The screen space points can be used for drawing the overlay + """maps the selected bounds which were set by the tool into screen + space. The screen space points can be used for drawing the overlay """ value_datasource = self.component.value value_mapper = self.component.value_mapper - value_selection = value_datasource.metadata['selections'] + value_selection = value_datasource.metadata["selections"] return tuple(value_mapper.map_screen(numpy.array(value_selection))) @@ -151,21 +152,21 @@ class PlotExample(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor()), - width=600, height=600) + traits_view = View(Item("plot", editor=ComponentEditor()), width=600, height=600) def __init__(self, index, value, *args, **kw): super(PlotExample, self).__init__(*args, **kw) plot_data = ArrayPlotData(index=index) - plot_data.set_data('value', value) + plot_data.set_data("value", value) self.plot = Plot(plot_data) - line = self.plot.plot(('index', 'value'))[0] + line = self.plot.plot(("index", "value"))[0] line.overlays.append(XRayOverlay(line)) line.tools.append(BoxSelectTool(line)) + index = numpy.arange(0, 25, 0.25) value = numpy.sin(index) + numpy.arange(0, 10, 0.1) diff --git a/examples/demo/zoomed_plot/grid_plot_factory.py b/examples/demo/zoomed_plot/grid_plot_factory.py index bb9a94b21..7d69f7791 100644 --- a/examples/demo/zoomed_plot/grid_plot_factory.py +++ b/examples/demo/zoomed_plot/grid_plot_factory.py @@ -1,67 +1,89 @@ - # Local relative imports -from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, LinePlot, \ - ScatterPlot, PlotAxis, PlotGrid - - -def create_gridded_line_plot(x, y, orientation="h", color="red", width=1.0, - dash="solid", value_mapper_class=LinearMapper, - padding=30): +from chaco.api import ( + ArrayDataSource, + DataRange1D, + LinearMapper, + LinePlot, + ScatterPlot, + PlotAxis, + PlotGrid, +) + + +def create_gridded_line_plot( + x, + y, + orientation="h", + color="red", + width=1.0, + dash="solid", + value_mapper_class=LinearMapper, + padding=30, +): assert len(x) == len(y) # If you know it is monotonically increasing, sort_order can # be set to 'ascending' - index = ArrayDataSource(x,sort_order='none') + index = ArrayDataSource(x, sort_order="none") value = ArrayDataSource(y, sort_order="none") - index_range = DataRange1D(tight_bounds = False) + index_range = DataRange1D(tight_bounds=False) index_range.add(index) index_mapper = LinearMapper(range=index_range) - value_range = DataRange1D(tight_bounds = False) + value_range = DataRange1D(tight_bounds=False) value_range.add(value) value_mapper = value_mapper_class(range=value_range) - plot = LinePlot(index=index, value=value, - index_mapper = index_mapper, - value_mapper = value_mapper, - orientation = orientation, - color = color, - line_width = width, - line_style = dash, - padding = [40, 15, 15, 20], # left, right, top, bottom - border_visible = True, - border_width = 1, - bgcolor = "white", - use_backbuffer = True, - backbuffer_padding = False, - unified_draw = True, - draw_layer = "plot", - overlay_border = True) - - vertical_grid = PlotGrid(component = plot, - mapper=index_mapper, - orientation='vertical', - line_color="gray", - line_style='dot', - use_draw_order = True) - - horizontal_grid = PlotGrid(component = plot, - mapper=value_mapper, - orientation='horizontal', - line_color="gray", - line_style='dot', - use_draw_order = True) - - vertical_axis = PlotAxis(orientation='left', - mapper=plot.value_mapper, - use_draw_order = True) - - horizontal_axis = PlotAxis(orientation='bottom', - title='Time (s)', - mapper=plot.index_mapper, - use_draw_order = True) + plot = LinePlot( + index=index, + value=value, + index_mapper=index_mapper, + value_mapper=value_mapper, + orientation=orientation, + color=color, + line_width=width, + line_style=dash, + padding=[40, 15, 15, 20], # left, right, top, bottom + border_visible=True, + border_width=1, + bgcolor="white", + use_backbuffer=True, + backbuffer_padding=False, + unified_draw=True, + draw_layer="plot", + overlay_border=True, + ) + + vertical_grid = PlotGrid( + component=plot, + mapper=index_mapper, + orientation="vertical", + line_color="gray", + line_style="dot", + use_draw_order=True, + ) + + horizontal_grid = PlotGrid( + component=plot, + mapper=value_mapper, + orientation="horizontal", + line_color="gray", + line_style="dot", + use_draw_order=True, + ) + + vertical_axis = PlotAxis( + orientation="left", mapper=plot.value_mapper, use_draw_order=True + ) + + horizontal_axis = PlotAxis( + orientation="bottom", + title="Time (s)", + mapper=plot.index_mapper, + use_draw_order=True, + ) plot.underlays.append(vertical_grid) plot.underlays.append(horizontal_grid) @@ -72,65 +94,84 @@ def create_gridded_line_plot(x, y, orientation="h", color="red", width=1.0, plot.overlays.append(horizontal_axis) return plot -def create_gridded_scatter_plot(x, y, orientation="h", color="red", width=1.0, - fill_color="red", marker="square", marker_size=2, - value_mapper_class=LinearMapper, padding=30): + +def create_gridded_scatter_plot( + x, + y, + orientation="h", + color="red", + width=1.0, + fill_color="red", + marker="square", + marker_size=2, + value_mapper_class=LinearMapper, + padding=30, +): assert len(x) == len(y) # If you know it is monotonically increasing, sort_order can # be set to 'ascending' - index = ArrayDataSource(x,sort_order='none') + index = ArrayDataSource(x, sort_order="none") value = ArrayDataSource(y, sort_order="none") - index_range = DataRange1D(tight_bounds = False) + index_range = DataRange1D(tight_bounds=False) index_range.add(index) index_mapper = LinearMapper(range=index_range) - value_range = DataRange1D(tight_bounds = False) + value_range = DataRange1D(tight_bounds=False) value_range.add(value) value_mapper = value_mapper_class(range=value_range) - plot = ScatterPlot(index=index, value=value, - index_mapper = index_mapper, - value_mapper = value_mapper, - orientation = orientation, - color = color, - fill_color=fill_color, - marker=marker, - marker_size=marker_size, - padding = [40, 15, 15, 20], # left, right, top, bottom - border_visible = True, - border_width = 1, - bgcolor = "white", - use_backbuffer = True, - backbuffer_padding = False, - unified_draw = True, - draw_layer = "plot", - overlay_border = True) - - vertical_grid = PlotGrid(component = plot, - mapper=index_mapper, - orientation='vertical', - line_color="gray", - line_style='dot', - use_draw_order = True) - - horizontal_grid = PlotGrid(component = plot, - mapper=value_mapper, - orientation='horizontal', - line_color="gray", - line_style='dot', - use_draw_order = True) - - vertical_axis = PlotAxis(orientation='left', - mapper=plot.value_mapper, - use_draw_order = True) - - horizontal_axis = PlotAxis(orientation='bottom', - title='Time (s)', - mapper=plot.index_mapper, - use_draw_order = True) + plot = ScatterPlot( + index=index, + value=value, + index_mapper=index_mapper, + value_mapper=value_mapper, + orientation=orientation, + color=color, + fill_color=fill_color, + marker=marker, + marker_size=marker_size, + padding=[40, 15, 15, 20], # left, right, top, bottom + border_visible=True, + border_width=1, + bgcolor="white", + use_backbuffer=True, + backbuffer_padding=False, + unified_draw=True, + draw_layer="plot", + overlay_border=True, + ) + + vertical_grid = PlotGrid( + component=plot, + mapper=index_mapper, + orientation="vertical", + line_color="gray", + line_style="dot", + use_draw_order=True, + ) + + horizontal_grid = PlotGrid( + component=plot, + mapper=value_mapper, + orientation="horizontal", + line_color="gray", + line_style="dot", + use_draw_order=True, + ) + + vertical_axis = PlotAxis( + orientation="left", mapper=plot.value_mapper, use_draw_order=True + ) + + horizontal_axis = PlotAxis( + orientation="bottom", + title="Time (s)", + mapper=plot.index_mapper, + use_draw_order=True, + ) plot.underlays.append(vertical_grid) plot.underlays.append(horizontal_grid) @@ -140,6 +181,3 @@ def create_gridded_scatter_plot(x, y, orientation="h", color="red", width=1.0, plot.overlays.append(vertical_axis) plot.overlays.append(horizontal_axis) return plot - - - diff --git a/examples/demo/zoomed_plot/wav_to_numeric.py b/examples/demo/zoomed_plot/wav_to_numeric.py index b23e0bd36..80928a3be 100644 --- a/examples/demo/zoomed_plot/wav_to_numeric.py +++ b/examples/demo/zoomed_plot/wav_to_numeric.py @@ -8,40 +8,43 @@ # Enthought library imports from traits.util.resource import find_resource -def wav_to_numeric( fname, max_frames=-1 ): - f = wave.open( fname, 'rb' ) - sampleRate = f.getframerate() - channels = f.getnchannels() - if max_frames < 0: - max_frames = f.getnframes() +def wav_to_numeric(fname, max_frames=-1): + f = wave.open(fname, "rb") + sampleRate = f.getframerate() + channels = f.getnchannels() - frames = f.readframes(max_frames) + if max_frames < 0: + max_frames = f.getnframes() - if f.getsampwidth() == 2: - data = numpy.fromstring(frames, numpy.uint16).astype(numpy.float64) - (2**15 - 0.5) - else: - data = numpy.fromstring(frames, numpy.uint8).astype(numpy.float64) - 127.5 + frames = f.readframes(max_frames) - if channels == 2: - left = data[0::2] - right = data[1::2] + if f.getsampwidth() == 2: + data = numpy.fromstring(frames, numpy.uint16).astype(numpy.float64) - ( + 2 ** 15 - 0.5 + ) + else: + data = numpy.fromstring(frames, numpy.uint8).astype(numpy.float64) - 127.5 - data = left + if channels == 2: + left = data[0::2] + right = data[1::2] - index = numpy.arange(len(data)) * 1.0/sampleRate + data = left + + index = numpy.arange(len(data)) * 1.0 / sampleRate + + return index, data - return index, data def test(): - sample_path = os.path.join('examples','data','sample.wav') - alt_path = os.path.join('..','data','sample.wav') - fname = find_resource('Chaco', sample_path, alt_path=alt_path, - return_path=True) + sample_path = os.path.join("examples", "data", "sample.wav") + alt_path = os.path.join("..", "data", "sample.wav") + fname = find_resource("Chaco", sample_path, alt_path=alt_path, return_path=True) index, data = wav_to_numeric(fname) print(data[:100]) return index, data -if __name__== '__main__': - test() +if __name__ == "__main__": + test() diff --git a/examples/demo/zoomed_plot/zoom_overlay.py b/examples/demo/zoomed_plot/zoom_overlay.py index 6bddc45ca..895d7d340 100644 --- a/examples/demo/zoomed_plot/zoom_overlay.py +++ b/examples/demo/zoomed_plot/zoom_overlay.py @@ -45,10 +45,9 @@ def calculate_points(self, component): left_end = array([self.destination.x, y]) right_end = array([self.destination.x2, y]) - polygon = array((left_top, left_mid, left_end, - right_end,right_mid, right_top)) + polygon = array((left_top, left_mid, left_end, right_end, right_mid, right_top)) left_line = array((left_top, left_mid, left_end)) - right_line = array((right_end,right_mid, right_top)) + right_line = array((right_end, right_mid, right_top)) return left_line, right_line, polygon @@ -91,14 +90,15 @@ def _get_selection_screencoords(self): else: return None - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ # Trait event handlers - #------------------------------------------------------------------------ + # ------------------------------------------------------------------------ def _source_changed(self, old, new): if old is not None and old.controller is not None: - old.controller.observe(self._selection_update_handler, "selection", - remove=True) + old.controller.observe( + self._selection_update_handler, "selection", remove=True + ) if new is not None and new.controller is not None: new.controller.observe(self._selection_update_handler, "selection") diff --git a/examples/demo/zoomed_plot/zoom_plot.py b/examples/demo/zoomed_plot/zoom_plot.py index f63f9c37f..40ad6a7ea 100644 --- a/examples/demo/zoomed_plot/zoom_plot.py +++ b/examples/demo/zoomed_plot/zoom_plot.py @@ -26,109 +26,117 @@ # Relative imports from .zoom_overlay import ZoomOverlay -sample_path = os.path.join('examples','data','sample.wav') -alt_path = os.path.join('..','data','sample.wav') -fname = find_resource('Chaco', sample_path, alt_path=alt_path, - return_path=True) +sample_path = os.path.join("examples", "data", "sample.wav") +alt_path = os.path.join("..", "data", "sample.wav") +fname = find_resource("Chaco", sample_path, alt_path=alt_path, return_path=True) numpts = 3000 + def read_music_data(): from .wav_to_numeric import wav_to_numeric + index, data = wav_to_numeric(fname) return index[:numpts], data[:numpts] class ZoomPlot(HasTraits): - '''Encapsulation of the zoom plot concept. + """Encapsulation of the zoom plot concept. This class organzies the data, plot container and ZoomOverlay required for a zoom plot. ZoomPlot represents the first step towards a reusable and extensible generalization of the zoom plot. - ''' + """ data = Instance(ArrayPlotData) plot = Instance(Component) - + def update_data(self, x, y): - '''Update the data in the plot windows''' + """Update the data in the plot windows""" # FIXME: This isn't forcing the update, so the crufty code below is used. - #self.plot.data['x'] = x - #self.plot.data['y'] = y + # self.plot.data['x'] = x + # self.plot.data['y'] = y self.plot.components[0].index.set_data(x) self.plot.components[0].value.set_data(y) self.plot.components[1].index.set_data(x) self.plot.components[1].value.set_data(y) def _data_default(self): - x = linspace(0, 4*pi, 1201) - y = sin(x**2) + x = linspace(0, 4 * pi, 1201) + y = sin(x ** 2) data = ArrayPlotData(x=x, y=y) - + return data def _plot_default(self): plotter = Plot(data=self.data) - main_plot = plotter.plot(['x','y'])[0] - self.configure_plot(main_plot, xlabel='') + main_plot = plotter.plot(["x", "y"])[0] + self.configure_plot(main_plot, xlabel="") plotter2 = Plot(data=self.data) - zoom_plot = plotter2.plot(['x','y'])[0] + zoom_plot = plotter2.plot(["x", "y"])[0] self.configure_plot(zoom_plot) - - outer_container = VPlotContainer(padding=20, - fill_padding=True, - spacing=0, - stack_order='top_to_bottom', - bgcolor='lightgray', - use_backbuffer=True) + + outer_container = VPlotContainer( + padding=20, + fill_padding=True, + spacing=0, + stack_order="top_to_bottom", + bgcolor="lightgray", + use_backbuffer=True, + ) outer_container.add(main_plot) outer_container.add(zoom_plot) # FIXME: This is set to the windows bg color. Should get from the system. - #outer_container.bgcolor = (236/255., 233/255., 216/255., 1.0) + # outer_container.bgcolor = (236/255., 233/255., 216/255., 1.0) main_plot.controller = RangeSelection(main_plot) - + zoom_overlay = ZoomOverlay(source=main_plot, destination=zoom_plot) outer_container.overlays.append(zoom_overlay) return outer_container @staticmethod - def configure_plot(plot, xlabel='Time (s)'): - """ Set up colors, grids, etc. on plot objects. - """ - plot.bgcolor = 'white' + def configure_plot(plot, xlabel="Time (s)"): + """Set up colors, grids, etc. on plot objects.""" + plot.bgcolor = "white" plot.border_visible = True plot.padding = [40, 15, 15, 20] - plot.color = 'darkred' + plot.color = "darkred" plot.line_width = 1.1 - - vertical_grid = PlotGrid(component=plot, - mapper=plot.index_mapper, - orientation='vertical', - line_color="gray", - line_style='dot', - use_draw_order = True) - - horizontal_grid = PlotGrid(component=plot, - mapper=plot.value_mapper, - orientation='horizontal', - line_color="gray", - line_style='dot', - use_draw_order = True) - - vertical_axis = PlotAxis(orientation='left', - mapper=plot.value_mapper, - use_draw_order = True) - - horizontal_axis = PlotAxis(orientation='bottom', - title=xlabel, - mapper=plot.index_mapper, - use_draw_order = True) + + vertical_grid = PlotGrid( + component=plot, + mapper=plot.index_mapper, + orientation="vertical", + line_color="gray", + line_style="dot", + use_draw_order=True, + ) + + horizontal_grid = PlotGrid( + component=plot, + mapper=plot.value_mapper, + orientation="horizontal", + line_color="gray", + line_style="dot", + use_draw_order=True, + ) + + vertical_axis = PlotAxis( + orientation="left", mapper=plot.value_mapper, use_draw_order=True + ) + + horizontal_axis = PlotAxis( + orientation="bottom", + title=xlabel, + mapper=plot.index_mapper, + use_draw_order=True, + ) plot.underlays.append(vertical_grid) plot.underlays.append(horizontal_grid) @@ -137,32 +145,40 @@ def configure_plot(plot, xlabel='Time (s)'): # and only overlays get to render in addition to the backbuffer. plot.overlays.append(vertical_axis) plot.overlays.append(horizontal_axis) - -#=============================================================================== + + +# =============================================================================== # Attributes to use for the plot view. size = (800, 600) title = fname -#=============================================================================== +# =============================================================================== # # Demo class that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class ZoomPlotView(HasTraits): zoom_plot = Instance(ZoomPlot, ()) - + traits_view = View( - Group( - Item('object.zoom_plot.plot', editor=ComponentEditor(size=size), - show_label=False), - orientation = "vertical"), - resizable=True, title='Zoom Plot', - width=size[0], height=size[1] - ) + Group( + Item( + "object.zoom_plot.plot", + editor=ComponentEditor(size=size), + show_label=False, + ), + orientation="vertical", + ), + resizable=True, + title="Zoom Plot", + width=size[0], + height=size[1], + ) + demo = ZoomPlotView() # Configure the zoom plot by giving it data try: - x,y = read_music_data() + x, y = read_music_data() demo.zoom_plot.update_data(x, y) except: # Use the defaults diff --git a/examples/tutorials/scipy2008/connected_orientation.py b/examples/tutorials/scipy2008/connected_orientation.py index cb46d1a67..d5356029d 100644 --- a/examples/tutorials/scipy2008/connected_orientation.py +++ b/examples/tutorials/scipy2008/connected_orientation.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, HPlotContainer, Plot @@ -7,19 +6,24 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class FlippedExample(HasTraits): container = Instance(HPlotContainer) - traits_view = View(Item('container', editor=ComponentEditor(), show_label=False), - width=1000, height=600, resizable=True, - title="Connected Range, Flipped") + traits_view = View( + Item("container", editor=ComponentEditor(), show_label=False), + width=1000, + height=600, + resizable=True, + title="Connected Range, Flipped", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create the scatter plot scatter = Plot(plotdata) @@ -41,9 +45,10 @@ def __init__(self): # Set the two plots' ranges to be the same scatter.range2d = line.range2d -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = FlippedExample() if __name__ == "__main__": demo.configure_traits() diff --git a/examples/tutorials/scipy2008/connected_range.py b/examples/tutorials/scipy2008/connected_range.py index a840534d7..0a88d3256 100644 --- a/examples/tutorials/scipy2008/connected_range.py +++ b/examples/tutorials/scipy2008/connected_range.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, HPlotContainer, Plot @@ -7,19 +6,24 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ConnectedRange(HasTraits): container = Instance(HPlotContainer) - traits_view = View(Item('container', editor=ComponentEditor(), show_label=False), - width=1000, height=600, resizable=True, - title="Connected Range") + traits_view = View( + Item("container", editor=ComponentEditor(), show_label=False), + width=1000, + height=600, + resizable=True, + title="Connected Range", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create the scatter plot scatter = Plot(plotdata) @@ -42,9 +46,9 @@ def __init__(self): scatter.range2d = line.range2d -#=============================================================================== +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=ConnectedRange() +# =============================================================================== +demo = ConnectedRange() if __name__ == "__main__": demo.configure_traits() diff --git a/examples/tutorials/scipy2008/connected_single_range.py b/examples/tutorials/scipy2008/connected_single_range.py index af622e453..aef3d16d8 100644 --- a/examples/tutorials/scipy2008/connected_single_range.py +++ b/examples/tutorials/scipy2008/connected_single_range.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, HPlotContainer, Plot @@ -7,19 +6,24 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ConnectedRange(HasTraits): container = Instance(HPlotContainer) - traits_view = View(Item('container', editor=ComponentEditor(), show_label=False), - width=1000, height=600, resizable=True, - title="Connected Range") + traits_view = View( + Item("container", editor=ComponentEditor(), show_label=False), + width=1000, + height=600, + resizable=True, + title="Connected Range", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create the scatter plot scatter = Plot(plotdata) @@ -41,9 +45,10 @@ def __init__(self): # Set the two plots' ranges to be the same scatter.index_range = line.index_range -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=ConnectedRange() +# =============================================================================== +demo = ConnectedRange() if __name__ == "__main__": demo.configure_traits() diff --git a/examples/tutorials/scipy2008/connected_widgets.py b/examples/tutorials/scipy2008/connected_widgets.py index 146241866..83be676eb 100644 --- a/examples/tutorials/scipy2008/connected_widgets.py +++ b/examples/tutorials/scipy2008/connected_widgets.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot @@ -7,22 +6,27 @@ from traits.api import Enum, HasTraits, Instance from traitsui.api import Item, View + class PlotEditor(HasTraits): plot = Instance(Plot) plot_type = Enum("scatter", "line") orientation = Enum("horizontal", "vertical") - traits_view = View(Item('orientation', label="Orientation"), - Item('plot', editor=ComponentEditor(), show_label=False), - width=500, height=500, resizable=True, - title="Chaco Plot") + traits_view = View( + Item("orientation", label="Orientation"), + Item("plot", editor=ComponentEditor(), show_label=False), + width=500, + height=500, + resizable=True, + title="Chaco Plot", + ) def __init__(self, *args, **kw): HasTraits.__init__(self, *args, **kw) # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create the scatter plot plot = Plot(plotdata) plot.plot(("x", "y"), type=self.plot_type, color="blue") @@ -36,14 +40,14 @@ def _orientation_changed(self): else: self.plot.orientation = "h" + if __name__ == "__main__": # Create the two plots - scatter = PlotEditor(plot_type = "scatter") - line = PlotEditor(plot_type = "line") + scatter = PlotEditor(plot_type="scatter") + line = PlotEditor(plot_type="line") # Hook up their ranges scatter.plot.range2d = line.plot.range2d # Bring up both plots by calling edit_traits(). (We call configure_traits() # on the second one so that the application main loop stays running.) line.edit_traits() scatter.configure_traits() - diff --git a/examples/tutorials/scipy2008/container.py b/examples/tutorials/scipy2008/container.py index 92fd45ce3..6ee0e0b66 100644 --- a/examples/tutorials/scipy2008/container.py +++ b/examples/tutorials/scipy2008/container.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, HPlotContainer, Plot @@ -6,19 +5,24 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ContainerExample(HasTraits): plot = Instance(HPlotContainer) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=1000, height=600, resizable=True, - title="Chaco Plot") + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=1000, + height=600, + resizable=True, + title="Chaco Plot", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create the scatter plot scatter = Plot(plotdata) scatter.plot(("x", "y"), type="scatter", color="blue") @@ -29,10 +33,10 @@ def __init__(self): container = HPlotContainer(scatter, line) self.plot = container -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=ContainerExample() +# =============================================================================== +demo = ContainerExample() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/container_nospace.py b/examples/tutorials/scipy2008/container_nospace.py index ce10f0026..46cba397a 100644 --- a/examples/tutorials/scipy2008/container_nospace.py +++ b/examples/tutorials/scipy2008/container_nospace.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, HPlotContainer, Plot @@ -6,18 +5,23 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ContainerExample(HasTraits): plot = Instance(HPlotContainer) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=1000, height=600, resizable=True) + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=1000, + height=600, + resizable=True, + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create the scatter plot scatter = Plot(plotdata) scatter.plot(("x", "y"), type="scatter", color="blue") @@ -33,9 +37,10 @@ def __init__(self): self.plot = container -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=ContainerExample() +# =============================================================================== +demo = ContainerExample() if __name__ == "__main__": demo.configure_traits() diff --git a/examples/tutorials/scipy2008/container_vertical.py b/examples/tutorials/scipy2008/container_vertical.py index 2f2812496..8ac8d78ec 100644 --- a/examples/tutorials/scipy2008/container_vertical.py +++ b/examples/tutorials/scipy2008/container_vertical.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, VPlotContainer, Plot @@ -6,18 +5,23 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ContainerExample2(HasTraits): plot = Instance(VPlotContainer) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=600, height=800, resizable=True) + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=600, + height=800, + resizable=True, + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create the scatter plot scatter = Plot(plotdata) scatter.plot(("x", "y"), type="scatter", color="blue") @@ -28,11 +32,10 @@ def __init__(self): container = VPlotContainer(scatter, line) self.plot = container -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=ContainerExample2() +# =============================================================================== +demo = ContainerExample2() if __name__ == "__main__": demo.configure_traits() - - diff --git a/examples/tutorials/scipy2008/custom_overlay.py b/examples/tutorials/scipy2008/custom_overlay.py index e6ec562f9..dee80a346 100644 --- a/examples/tutorials/scipy2008/custom_overlay.py +++ b/examples/tutorials/scipy2008/custom_overlay.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot, AbstractOverlay @@ -6,8 +5,8 @@ from enable.component_editor import ComponentEditor from enable.api import ColorTrait from traits.api import Button, Float, Range, HasTraits, Instance -from traitsui.api import Item, View, Group, HGroup, RangeEditor, \ - spring, Handler +from traitsui.api import Item, View, Group, HGroup, RangeEditor, spring, Handler + class CustomOverlay(AbstractOverlay): x = Float(10, editor=RangeEditor(low=1.0, high=600, mode="slider")) @@ -16,10 +15,16 @@ class CustomOverlay(AbstractOverlay): height = Range(10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider")) color = ColorTrait("red") - traits_view = View(Group( - Item("x"), Item("y"), Item("width"), Item("height"), - Item("color"), orientation = "vertical" - )) + traits_view = View( + Group( + Item("x"), + Item("y"), + Item("width"), + Item("height"), + Item("color"), + orientation="vertical", + ) + ) def overlay(self, component, gc, view_bounds=None, mode="normal"): gc.set_fill_color(self.color_) @@ -31,8 +36,8 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): def _anytrait_changed(self): self.component.request_redraw() -class ScatterPlotHandler(Handler): +class ScatterPlotHandler(Handler): def object_edit_overlay_changed(self, info): info.object.plot.overlays[-1].edit_traits(parent=info.ui.control) @@ -41,22 +46,26 @@ class ScatterPlot(HasTraits): plot = Instance(Plot) - edit_overlay = Button('Edit Overlay') + edit_overlay = Button("Edit Overlay") - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - HGroup(spring, - Item('edit_overlay', show_label=False, - emphasized=True, - height=50), - spring), - handler = ScatterPlotHandler, - width=800, height=600, resizable=True) + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + HGroup( + spring, + Item("edit_overlay", show_label=False, emphasized=True, height=50), + spring, + ), + handler=ScatterPlotHandler, + width=800, + height=600, + resizable=True, + ) def _plot_default(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a scatter plot in the Plot @@ -66,9 +75,10 @@ def _plot_default(self): plot.overlays.append(CustomOverlay(plot)) return plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = ScatterPlot() if __name__ == "__main__": demo.configure_traits() diff --git a/examples/tutorials/scipy2008/custom_overlay_dataspace.py b/examples/tutorials/scipy2008/custom_overlay_dataspace.py index ecf1b15ab..7fea3692a 100644 --- a/examples/tutorials/scipy2008/custom_overlay_dataspace.py +++ b/examples/tutorials/scipy2008/custom_overlay_dataspace.py @@ -1,14 +1,12 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot, AbstractOverlay from chaco.tools.api import PanTool from enable.component_editor import ComponentEditor from enable.api import ColorTrait -from traits.api import Button, CArray, Bool, Float, Range, HasTraits,\ - Instance -from traitsui.api import Item, View, Group, RangeEditor, \ - HGroup, Handler, spring +from traits.api import Button, CArray, Bool, Float, Range, HasTraits, Instance +from traitsui.api import Item, View, Group, RangeEditor, HGroup, Handler, spring + class CustomOverlay(AbstractOverlay): x = Float(10, editor=RangeEditor(low=1.0, high=600, mode="slider")) @@ -20,12 +18,17 @@ class CustomOverlay(AbstractOverlay): _anchor = CArray - traits_view = View(Group( - Item("x"), Item("y"), Item("width"), Item("height"), - Item("color"), - Item("dataspace", label="Data space?"), - orientation = "vertical" - )) + traits_view = View( + Group( + Item("x"), + Item("y"), + Item("width"), + Item("height"), + Item("color"), + Item("dataspace", label="Data space?"), + orientation="vertical", + ) + ) def overlay(self, component, gc, view_bounds=None, mode="normal"): if self.dataspace: @@ -44,8 +47,8 @@ def _dataspace_changed(self): # Map our current x,y point into data space self._anchor = self.component.map_data((self.x, self.y)) -class ScatterPlotHandler(Handler): +class ScatterPlotHandler(Handler): def object_edit_overlay_changed(self, info): info.object.plot.overlays[-1].edit_traits(parent=info.ui.control) @@ -54,22 +57,26 @@ class ScatterPlot(HasTraits): plot = Instance(Plot) - edit_overlay = Button('Edit Overlay') - - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - HGroup(spring, - Item('edit_overlay', show_label=False, - emphasized=True, - height=50), - spring), - handler = ScatterPlotHandler, - width=800, height=600, resizable=True) + edit_overlay = Button("Edit Overlay") + + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + HGroup( + spring, + Item("edit_overlay", show_label=False, emphasized=True, height=50), + spring, + ), + handler=ScatterPlotHandler, + width=800, + height=600, + resizable=True, + ) def _plot_default(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a scatter plot in the Plot @@ -79,9 +86,10 @@ def _plot_default(self): plot.overlays.append(CustomOverlay(plot)) return plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = ScatterPlot() if __name__ == "__main__": demo.configure_traits() diff --git a/examples/tutorials/scipy2008/custom_overlay_movetool.py b/examples/tutorials/scipy2008/custom_overlay_movetool.py index 155968aea..c6b9d20c8 100644 --- a/examples/tutorials/scipy2008/custom_overlay_movetool.py +++ b/examples/tutorials/scipy2008/custom_overlay_movetool.py @@ -1,14 +1,12 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot, AbstractOverlay from chaco.tools.api import PanTool, MoveTool from enable.component_editor import ComponentEditor from enable.api import ColorTrait -from traits.api import Button, CArray, Bool, Float, Range, \ - HasTraits, Instance, Property -from traitsui.api import Item, View, Group, RangeEditor, \ - HGroup, Handler, spring +from traits.api import Button, CArray, Bool, Float, Range, HasTraits, Instance, Property +from traitsui.api import Item, View, Group, RangeEditor, HGroup, Handler, spring + class CustomOverlay(AbstractOverlay): x = Float(10, editor=RangeEditor(low=1.0, high=600, mode="slider")) @@ -21,12 +19,17 @@ class CustomOverlay(AbstractOverlay): _anchor = CArray - traits_view = View(Group( - Item("x"), Item("y"), Item("width"), Item("height"), - Item("color"), - Item("dataspace", label="Data space?"), - orientation = "vertical" - )) + traits_view = View( + Group( + Item("x"), + Item("y"), + Item("width"), + Item("height"), + Item("color"), + Item("dataspace", label="Data space?"), + orientation="vertical", + ) + ) def overlay(self, component, gc, view_bounds=None, mode="normal"): if self.dataspace: @@ -51,8 +54,8 @@ def _dataspace_changed(self): # Map our current x,y point into data space self._anchor = self.component.map_data((self.x, self.y)) -class ScatterPlotHandler(Handler): +class ScatterPlotHandler(Handler): def object_edit_overlay_changed(self, info): info.object.plot.overlays[-1].edit_traits(parent=info.ui.control) @@ -61,22 +64,26 @@ class ScatterPlot(HasTraits): plot = Instance(Plot) - edit_overlay = Button('Edit Overlay') - - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - HGroup(spring, - Item('edit_overlay', show_label=False, - emphasized=True, - height=50), - spring), - handler = ScatterPlotHandler, - width=800, height=600, resizable=True) + edit_overlay = Button("Edit Overlay") + + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + HGroup( + spring, + Item("edit_overlay", show_label=False, emphasized=True, height=50), + spring, + ), + handler=ScatterPlotHandler, + width=800, + height=600, + resizable=True, + ) def _plot_default(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a scatter plot in the Plot @@ -90,9 +97,10 @@ def _plot_default(self): plot.overlays.append(overlay) return plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = ScatterPlot() if __name__ == "__main__": demo.configure_traits() diff --git a/examples/tutorials/scipy2008/custom_tool.py b/examples/tutorials/scipy2008/custom_tool.py index a787cdddc..6afc507f0 100644 --- a/examples/tutorials/scipy2008/custom_tool.py +++ b/examples/tutorials/scipy2008/custom_tool.py @@ -1,5 +1,3 @@ - - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot @@ -8,6 +6,7 @@ from traits.api import Enum, HasTraits, Instance from traitsui.api import Item, View + class CustomTool(BaseTool): event_state = Enum("normal", "mousedown") @@ -31,15 +30,19 @@ class ScatterPlot(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=800, height=600, resizable=True, - title="Custom Tool") + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=800, + height=600, + resizable=True, + title="Custom Tool", + ) def _plot_default(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a scatter plot in the Plot @@ -48,9 +51,10 @@ def _plot_default(self): plot.tools.append(CustomTool(plot)) return plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=ScatterPlot() +# =============================================================================== +demo = ScatterPlot() if __name__ == "__main__": demo.edit_traits(kind="livemodal") diff --git a/examples/tutorials/scipy2008/custom_tool_click.py b/examples/tutorials/scipy2008/custom_tool_click.py index f9cf2c51a..03da4947d 100644 --- a/examples/tutorials/scipy2008/custom_tool_click.py +++ b/examples/tutorials/scipy2008/custom_tool_click.py @@ -1,5 +1,3 @@ - - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot @@ -8,8 +6,8 @@ from traits.api import Enum, HasTraits, Instance from traitsui.api import Item, View -class CustomTool(BaseTool): +class CustomTool(BaseTool): def normal_mouse_move(self, event): print("Screen point:", event.x, event.y) @@ -19,19 +17,24 @@ def normal_left_down(self, event): def normal_left_up(self, event): print("Mouse went up at:", event.x, event.y) + class ScatterPlot(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=800, height=600, resizable=True, - title="Custom Tool") + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=800, + height=600, + resizable=True, + title="Custom Tool", + ) def _plot_default(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a scatter plot in the Plot @@ -40,9 +43,10 @@ def _plot_default(self): plot.tools.append(CustomTool(plot)) return plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=ScatterPlot() +# =============================================================================== +demo = ScatterPlot() if __name__ == "__main__": demo.edit_traits(kind="livemodal") diff --git a/examples/tutorials/scipy2008/custom_tool_screen.py b/examples/tutorials/scipy2008/custom_tool_screen.py index 56af2c115..7a9597d36 100644 --- a/examples/tutorials/scipy2008/custom_tool_screen.py +++ b/examples/tutorials/scipy2008/custom_tool_screen.py @@ -1,5 +1,3 @@ - - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot @@ -8,24 +6,29 @@ from traits.api import Enum, HasTraits, Instance from traitsui.api import Item, View -class CustomTool(BaseTool): +class CustomTool(BaseTool): def normal_mouse_move(self, event): print("Screen point:", event.x, event.y) + class ScatterPlot(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=800, height=600, resizable=True, - title="Custom Tool") + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=800, + height=600, + resizable=True, + title="Custom Tool", + ) def _plot_default(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a scatter plot in the Plot @@ -34,9 +37,10 @@ def _plot_default(self): plot.tools.append(CustomTool(plot)) return plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=ScatterPlot() +# =============================================================================== +demo = ScatterPlot() if __name__ == "__main__": demo.edit_traits(kind="livemodal") diff --git a/examples/tutorials/scipy2008/data_chooser.py b/examples/tutorials/scipy2008/data_chooser.py index 5891d00de..b75d3d594 100644 --- a/examples/tutorials/scipy2008/data_chooser.py +++ b/examples/tutorials/scipy2008/data_chooser.py @@ -1,4 +1,3 @@ - from numpy import linspace from scipy.special import jn @@ -7,20 +6,23 @@ from traits.api import Dict, Enum, HasTraits, Instance from traitsui.api import Item, View + class DataChooser(HasTraits): plot = Instance(Plot) data_name = Enum("jn0", "jn1", "jn2") - traits_view = View(Item('data_name', label="Y data"), - Item('plot', editor=ComponentEditor(), show_label=False), - width=800, height=600, resizable=True, - title="Data Chooser") + traits_view = View( + Item("data_name", label="Y data"), + Item("plot", editor=ComponentEditor(), show_label=False), + width=800, + height=600, + resizable=True, + title="Data Chooser", + ) def __init__(self): x = linspace(-5, 10, 100) - self.data = {"jn0": jn(0, x), - "jn1": jn(1, x), - "jn2": jn(2, x)} + self.data = {"jn0": jn(0, x), "jn1": jn(1, x), "jn2": jn(2, x)} # Create the data and the PlotData object self.plotdata = ArrayPlotData(x=x, y=self.data["jn0"]) @@ -35,10 +37,9 @@ def _data_name_changed(self, old, new): self.plotdata.set_data("y", self.data[self.data_name]) -#=============================================================================== +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=DataChooser() +# =============================================================================== +demo = DataChooser() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/first_plot.py b/examples/tutorials/scipy2008/first_plot.py index 2da1a20bf..e82e82489 100644 --- a/examples/tutorials/scipy2008/first_plot.py +++ b/examples/tutorials/scipy2008/first_plot.py @@ -1,26 +1,27 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot from enable.component_editor import ComponentEditor from traits.api import HasTraits, Instance from traitsui.api import Item, View + class LinePlot(HasTraits): plot = Instance(Plot) traits_view = View( - Item('plot', editor=ComponentEditor(), - show_label=False), - width=500, height=500, - resizable=True, - title = "Chaco Plot") + Item("plot", editor=ComponentEditor(), show_label=False), + width=500, + height=500, + resizable=True, + title="Chaco Plot", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a line plot in the Plot @@ -30,10 +31,10 @@ def __init__(self): # Assign it to our self.plot attribute self.plot = plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== -demo=LinePlot() +# =============================================================================== +demo = LinePlot() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/image.py b/examples/tutorials/scipy2008/image.py index 5941a9ac7..e9a356c70 100644 --- a/examples/tutorials/scipy2008/image.py +++ b/examples/tutorials/scipy2008/image.py @@ -1,4 +1,3 @@ - from numpy import linspace, meshgrid, exp from chaco.api import ArrayPlotData, Plot, viridis @@ -6,14 +5,18 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ImagePlot(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=600, height=600, - resizable=True, - title="Chaco Plot") + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=600, + height=600, + resizable=True, + title="Chaco Plot", + ) def __init__(self): # Create the data and the PlotData object. For a 2D plot, we need to @@ -22,18 +25,18 @@ def __init__(self): x = linspace(0, 10, 50) y = linspace(0, 5, 50) xgrid, ygrid = meshgrid(x, y) - z = exp(-(xgrid*xgrid + ygrid*ygrid) / 100) - plotdata = ArrayPlotData(imagedata = z) + z = exp(-(xgrid * xgrid + ygrid * ygrid) / 100) + plotdata = ArrayPlotData(imagedata=z) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create an image plot in the Plot plot.img_plot("imagedata", colormap=viridis) self.plot = plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = ImagePlot() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/overlapping.py b/examples/tutorials/scipy2008/overlapping.py index b6ec43a3f..2c6cc79ce 100644 --- a/examples/tutorials/scipy2008/overlapping.py +++ b/examples/tutorials/scipy2008/overlapping.py @@ -1,4 +1,3 @@ - from numpy import linspace, cos, sin from chaco.api import ArrayPlotData, Plot @@ -6,18 +5,23 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class OverlappingExample(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=800, height=600, resizable=True, - title="Chaco Plot") + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=800, + height=600, + resizable=True, + title="Chaco Plot", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = x/2 * sin(x) + y = x / 2 * sin(x) y2 = cos(x) plotdata = ArrayPlotData(x=x, y=y, y2=y2) # Create a Plot and associate it with the PlotData @@ -28,10 +32,10 @@ def __init__(self): plot.plot(("x", "y2"), type="line", color="red") self.plot = plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = OverlappingExample() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/ploteditor.py b/examples/tutorials/scipy2008/ploteditor.py index 61148085b..ae46736bb 100644 --- a/examples/tutorials/scipy2008/ploteditor.py +++ b/examples/tutorials/scipy2008/ploteditor.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot @@ -7,21 +6,26 @@ from traits.api import Enum, HasTraits, Instance from traitsui.api import Item, Group, View + class PlotEditor(HasTraits): plot = Instance(Plot) plot_type = Enum("scatter", "line") orientation = Enum("horizontal", "vertical") - traits_view = View(Item('orientation', label="Orientation"), - Item('plot', editor=ComponentEditor(), show_label=False), - width=500, height=500, resizable=True) + traits_view = View( + Item("orientation", label="Orientation"), + Item("plot", editor=ComponentEditor(), show_label=False), + width=500, + height=500, + resizable=True, + ) def __init__(self, *args, **kw): HasTraits.__init__(self, *args, **kw) # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create the scatter plot plot = Plot(plotdata) plot.plot(("x", "y"), type=self.plot_type, color="blue") @@ -37,9 +41,9 @@ def _orientation_changed(self): self.plot.request_redraw() -#=============================================================================== +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== class Demo(HasTraits): # Scatter plot. @@ -48,17 +52,16 @@ class Demo(HasTraits): # Line plot. line_plot = Instance(PlotEditor) - traits_view = View(Group( - Item('@scatter_plot', show_label=False), - label='Scatter'), - Group(Item('@line_plot', show_label= False ), - label='Line'), - title='Chaco Plot', - resizable=True) + traits_view = View( + Group(Item("@scatter_plot", show_label=False), label="Scatter"), + Group(Item("@line_plot", show_label=False), label="Line"), + title="Chaco Plot", + resizable=True, + ) def __init__(self, *args, **kws): - super(Demo, self). __init__(*args, **kws) - #Hook up the ranges. + super(Demo, self).__init__(*args, **kws) + # Hook up the ranges. self.scatter_plot.plot.range2d = self.line_plot.plot.range2d def _scatter_plot_default(self): @@ -67,7 +70,7 @@ def _scatter_plot_default(self): def _line_plot_default(self): return PlotEditor(plot_type="line") + demo = Demo() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/scatter.py b/examples/tutorials/scipy2008/scatter.py index 776ba62ff..c1fb03c5c 100644 --- a/examples/tutorials/scipy2008/scatter.py +++ b/examples/tutorials/scipy2008/scatter.py @@ -1,37 +1,38 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot from enable.component_editor import ComponentEditor from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ScatterPlot(HasTraits): plot = Instance(Plot) traits_view = View( - Item('plot', editor=ComponentEditor(), - show_label=False), - width=500, height=500, - resizable=True, - title="Chaco Plot") + Item("plot", editor=ComponentEditor(), show_label=False), + width=500, + height=500, + resizable=True, + title="Chaco Plot", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a scatter plot in the Plot plot.plot(("x", "y"), type="scatter", color="blue") self.plot = plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = ScatterPlot() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/tool_chooser.py b/examples/tutorials/scipy2008/tool_chooser.py index 16c79b504..5a7b4753f 100644 --- a/examples/tutorials/scipy2008/tool_chooser.py +++ b/examples/tutorials/scipy2008/tool_chooser.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot @@ -7,20 +6,25 @@ from traits.api import HasTraits, Instance, List from traitsui.api import Item, View, CheckListEditor + class ToolChooserExample(HasTraits): plot = Instance(Plot) - tools = List(editor=CheckListEditor(values = ["PanTool", "ZoomTool", "DragZoom"])) - traits_view = View(Item("tools", label="Tools", style="custom"), - Item('plot', editor=ComponentEditor(), show_label=False), - width=800, height=600, resizable=True, - title="Tool Chooser") + tools = List(editor=CheckListEditor(values=["PanTool", "ZoomTool", "DragZoom"])) + traits_view = View( + Item("tools", label="Tools", style="custom"), + Item("plot", editor=ComponentEditor(), show_label=False), + width=800, + height=600, + resizable=True, + title="Tool Chooser", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 500) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a line plot in the Plot @@ -40,11 +44,10 @@ def _tools_changed(self): self.plot.tools.append(cls(self.plot)) -#=============================================================================== +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = ToolChooserExample() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/tools.py b/examples/tutorials/scipy2008/tools.py index 17edb23d7..472e3a3b7 100644 --- a/examples/tutorials/scipy2008/tools.py +++ b/examples/tutorials/scipy2008/tools.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from chaco.api import ArrayPlotData, Plot @@ -7,18 +6,23 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ToolsExample(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=800, height=600, resizable=True, - title="Pan & Zoom") + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=800, + height=600, + resizable=True, + title="Pan & Zoom", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 500) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a line plot in the Plot @@ -29,11 +33,11 @@ def __init__(self): plot.tools.append(DragZoom(plot, drag_button="right")) self.plot = plot -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = ToolsExample() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/traits_example.py b/examples/tutorials/scipy2008/traits_example.py index 4893d1087..998e04545 100644 --- a/examples/tutorials/scipy2008/traits_example.py +++ b/examples/tutorials/scipy2008/traits_example.py @@ -1,4 +1,3 @@ - from numpy import linspace, sin from enable.api import ColorTrait @@ -7,6 +6,7 @@ from traits.api import HasTraits, Instance, Int from traitsui.api import Group, Item, View + class ScatterPlotTraits(HasTraits): plot = Instance(Plot) @@ -15,20 +15,24 @@ class ScatterPlotTraits(HasTraits): marker_size = Int(4) traits_view = View( - Group(Item('color', label="Color", style="custom"), - Item('marker', label="Marker"), - Item('marker_size', label="Size"), - Item('plot', editor=ComponentEditor(), show_label=False), - orientation = "vertical"), - width=800, height=600, resizable=True, - title="Chaco Plot" - ) + Group( + Item("color", label="Color", style="custom"), + Item("marker", label="Marker"), + Item("marker_size", label="Size"), + Item("plot", editor=ComponentEditor(), show_label=False), + orientation="vertical", + ), + width=800, + height=600, + resizable=True, + title="Chaco Plot", + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create a line plot in the Plot @@ -44,11 +48,11 @@ def _marker_changed(self): def _marker_size_changed(self): self.renderer.marker_size = self.marker_size -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = ScatterPlotTraits() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/scipy2008/traits_image.py b/examples/tutorials/scipy2008/traits_image.py index 4152b21cb..418117bb7 100644 --- a/examples/tutorials/scipy2008/traits_image.py +++ b/examples/tutorials/scipy2008/traits_image.py @@ -1,4 +1,3 @@ - from numpy import linspace, meshgrid, exp from chaco.api import ArrayPlotData, Plot, viridis @@ -6,19 +5,23 @@ from traits.api import Enum, HasTraits, Instance from traitsui.api import Group, Item, View + class ImagePlotTraits(HasTraits): plot = Instance(Plot) origin = Enum("bottom left", "top left", "bottom right", "top right") traits_view = View( - Group( - Item('origin', label="Data origin"), - Item('plot', editor=ComponentEditor(), show_label=False), - orientation = "vertical"), - width=600, height=600, resizable=True, - title="Chaco Plot" - ) + Group( + Item("origin", label="Data origin"), + Item("plot", editor=ComponentEditor(), show_label=False), + orientation="vertical", + ), + width=600, + height=600, + resizable=True, + title="Chaco Plot", + ) def __init__(self): # Create the data and the PlotData object. For a 2D plot, we need to @@ -27,24 +30,25 @@ def __init__(self): x = linspace(0, 8, 50) y = linspace(0, 6, 50) xgrid, ygrid = meshgrid(x, y) - z = exp(-(xgrid*xgrid + ygrid*ygrid) / 100) - plotdata = ArrayPlotData(imagedata = z) + z = exp(-(xgrid * xgrid + ygrid * ygrid) / 100) + plotdata = ArrayPlotData(imagedata=z) # Create a Plot and associate it with the PlotData plot = Plot(plotdata) # Create an image plot in the Plot - self.renderer = plot.img_plot("imagedata", name="plot1", - xbounds=xgrid, ybounds=ygrid, colormap=viridis)[0] + self.renderer = plot.img_plot( + "imagedata", name="plot1", xbounds=xgrid, ybounds=ygrid, colormap=viridis + )[0] self.plot = plot def _origin_changed(self): self.renderer.origin = self.origin self.plot.request_redraw() -#=============================================================================== + +# =============================================================================== # demo object that is used by the demo.py application. -#=============================================================================== +# =============================================================================== demo = ImagePlotTraits() if __name__ == "__main__": demo.configure_traits() - diff --git a/examples/tutorials/tutor.py b/examples/tutorials/tutor.py index 0d1aa2647..2ecefc8c9 100644 --- a/examples/tutorials/tutor.py +++ b/examples/tutorials/tutor.py @@ -1,4 +1,4 @@ -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- # # Copyright (c) 2009-2010, Enthought, Inc. # All rights reserved. @@ -13,7 +13,7 @@ # Author: Vibha Srinivasan # Date: 02/03/2009 # -#------------------------------------------------------------------------------- +# ------------------------------------------------------------------------------- """ Run the Chaco demo. """ @@ -22,8 +22,4 @@ # Uncomment the config_filename portion to see a tree editor based on the # examples.cfg file. -demo(use_files=True, - config_filename='tutorials.cfg', - title = 'Chaco Tutorials' - ) - +demo(use_files=True, config_filename="tutorials.cfg", title="Chaco Tutorials") diff --git a/examples/tutorials/tutorial1.py b/examples/tutorials/tutorial1.py index 3044b1ea7..c557b9425 100644 --- a/examples/tutorials/tutorial1.py +++ b/examples/tutorials/tutorial1.py @@ -9,8 +9,8 @@ # First, we create two arrays of data, x and y. 'x' will be a sequence of # 100 points spanning the range -2pi to 2pi, and 'y' will be sin(x). numpoints = 100 -step = 4*pi / numpoints -x = arange(-2*pi, 2*pi+step/2, step) +step = 4 * pi / numpoints +x = arange(-2 * pi, 2 * pi + step / 2, step) y = sin(x) @@ -19,13 +19,13 @@ # plot types (line, scatter, etc.). In later tutorials we'll see what the # factories are actually doing, and how to manually assemble plotting # primitives in more powerful ways. For now, factories suit our needs. -myplot = chaco.create_line_plot((x,y), bgcolor="white", add_grid=True, add_axis=True) +myplot = chaco.create_line_plot((x, y), bgcolor="white", add_grid=True, add_axis=True) # We now need to set the plot's size, and add a little padding for the axes. # (Normally, when Chaco plots are placed inside WX windows, the bounds are # set automatically by the window.) myplot.padding = 50 -myplot.bounds = [400,400] +myplot.bounds = [400, 400] def main(): @@ -37,25 +37,26 @@ def main(): plot_gc.render_component(myplot) # Get the directory to save the image in - print('Please enter a path in which to place generated plots.') - print('Press to generate in the current directory.') - path = input('Path: ').strip() + print("Please enter a path in which to place generated plots.") + print("Press to generate in the current directory.") + path = input("Path: ").strip() path = os.path.expanduser(path) if len(path) > 0 and not os.path.exists(path): - print('The given path does not exist.') + print("The given path does not exist.") sys.exit() # The file name to save the plot as file_name = "tutorial1.png" if not os.path.isabs(path): - print('Creating image: ' + os.path.join(os.getcwd(), path, file_name)) + print("Creating image: " + os.path.join(os.getcwd(), path, file_name)) else: - print('Creating image: ' + os.path.join(path, file_name)) + print("Creating image: " + os.path.join(path, file_name)) # Finally, we tell the graphics context to save itself to disk as an image. plot_gc.save(os.path.join(path, file_name)) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/examples/tutorials/tutorial10.py b/examples/tutorials/tutorial10.py index fe6eea512..52c2fa228 100644 --- a/examples/tutorials/tutorial10.py +++ b/examples/tutorials/tutorial10.py @@ -11,13 +11,16 @@ def _container_default(self): container = super(PlotExample3, self)._container_default() rplot, lplot = self.right_plot, self.left_plot - lplot.overlays.append(LineInspector(component=lplot, - write_metadata=True, is_listener=True)) - rplot.overlays.append(LineInspector(component=rplot, - write_metadata=True, is_listener=True)) + lplot.overlays.append( + LineInspector(component=lplot, write_metadata=True, is_listener=True) + ) + rplot.overlays.append( + LineInspector(component=rplot, write_metadata=True, is_listener=True) + ) return container + demo = PlotExample3() if __name__ == "__main__": diff --git a/examples/tutorials/tutorial10b.py b/examples/tutorials/tutorial10b.py index 08e0184cd..e89e6d127 100644 --- a/examples/tutorials/tutorial10b.py +++ b/examples/tutorials/tutorial10b.py @@ -11,14 +11,17 @@ def _container_default(self): container = super(PlotExample3, self)._container_default() rplot, lplot = self.right_plot, self.left_plot - lplot.overlays.append(LineInspector(component=lplot, - write_metadata=True, is_listener=True)) - rplot.overlays.append(LineInspector(component=rplot, - write_metadata=True, is_listener=True)) + lplot.overlays.append( + LineInspector(component=lplot, write_metadata=True, is_listener=True) + ) + rplot.overlays.append( + LineInspector(component=rplot, write_metadata=True, is_listener=True) + ) rplot.index = lplot.index return container + demo = PlotExample3() if __name__ == "__main__": diff --git a/examples/tutorials/tutorial11.py b/examples/tutorials/tutorial11.py index ac4425b42..b10f6d02b 100644 --- a/examples/tutorials/tutorial11.py +++ b/examples/tutorials/tutorial11.py @@ -22,16 +22,43 @@ def _container_default(self): rplot.y_axis.mapper = rplot.index_mapper rplot.x_axis.mapper = rplot.value_mapper + lplot.overlays.append( + LineInspector( + component=lplot, + axis="value", + write_metadata=True, + is_listener=True, + color="blue", + ) + ) + lplot.overlays.append( + LineInspector( + component=lplot, + axis="value", + write_metadata=True, + is_listener=True, + color="blue", + ) + ) - lplot.overlays.append(LineInspector(component=lplot, - axis="value", write_metadata=True, is_listener=True, color="blue")) - lplot.overlays.append(LineInspector(component=lplot, - axis="value", write_metadata=True, is_listener=True, color="blue")) - - rplot.overlays.append(LineInspector(component=rplot, - axis="value", write_metadata=True, is_listener=True, color="blue")) - rplot.overlays.append(LineInspector(component=rplot, - axis="value", write_metadata=True, is_listener=True, color="blue")) + rplot.overlays.append( + LineInspector( + component=rplot, + axis="value", + write_metadata=True, + is_listener=True, + color="blue", + ) + ) + rplot.overlays.append( + LineInspector( + component=rplot, + axis="value", + write_metadata=True, + is_listener=True, + color="blue", + ) + ) return container diff --git a/examples/tutorials/tutorial2.py b/examples/tutorials/tutorial2.py index a67b0d790..550419eea 100644 --- a/examples/tutorials/tutorial2.py +++ b/examples/tutorials/tutorial2.py @@ -11,11 +11,14 @@ from tutorial1 import myplot + class PlotExample(HasTraits): plot = myplot - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - title="Chaco Tutorial") + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), title="Chaco Tutorial" + ) + demo = PlotExample() diff --git a/examples/tutorials/tutorial2_ipython.py b/examples/tutorials/tutorial2_ipython.py index 9ec42c4cd..3eff41374 100644 --- a/examples/tutorials/tutorial2_ipython.py +++ b/examples/tutorials/tutorial2_ipython.py @@ -24,20 +24,22 @@ demo.configure_traits() plot = demo.plot + def xtitle(text): plot.x_axis.title = text plot.request_redraw() + def ytitle(text): plot.y_axis.title = text plot.request_redraw() + def xrange(low, high): plot.x_mapper.range.low = low plot.x_mapper.range.high = high + def yrange(low, high): plot.y_mapper.range.low = low plot.y_mapper.range.high = high - - diff --git a/examples/tutorials/tutorial6.py b/examples/tutorials/tutorial6.py index 3d3aaf074..8008bfd35 100644 --- a/examples/tutorials/tutorial6.py +++ b/examples/tutorials/tutorial6.py @@ -8,10 +8,12 @@ from tutorial2 import demo + class EventPrinter(AbstractController): def dispatch(self, event, suffix): print(suffix, "event received at (%d,%d)" % (event.x, event.y)) + plot = demo.plot plot.tools.append(EventPrinter(plot)) diff --git a/examples/tutorials/tutorial7.py b/examples/tutorials/tutorial7.py index abfbc5fab..af9a95b8f 100644 --- a/examples/tutorials/tutorial7.py +++ b/examples/tutorials/tutorial7.py @@ -5,12 +5,14 @@ from tutorial2 import demo + class DataPrinter(AbstractController): def dispatch(self, event, suffix): x = self.component.x_mapper.map_data(event.x) y = self.component.y_mapper.map_data(event.y) print(suffix, "event received at (%f,%f)" % (x, y)) + plot = demo.plot plot.tools.append(DataPrinter(component=plot)) diff --git a/examples/tutorials/tutorial8.py b/examples/tutorials/tutorial8.py index bcd31685f..ab93dbc4f 100644 --- a/examples/tutorials/tutorial8.py +++ b/examples/tutorials/tutorial8.py @@ -18,37 +18,47 @@ class PlotExample(HasTraits): container = Instance(HPlotContainer) - traits_view = View(Item('container', editor=ComponentEditor(), - show_label=False, width=800, height=600), - title="Chaco Tutorial") + traits_view = View( + Item( + "container", + editor=ComponentEditor(), + show_label=False, + width=800, + height=600, + ), + title="Chaco Tutorial", + ) def _container_default(self): - x = arange(-5.0, 15.0, 20.0/100) + x = arange(-5.0, 15.0, 20.0 / 100) y = jn(0, x) - left_plot = create_line_plot((x,y), bgcolor="white", - add_grid=True, add_axis=True) + left_plot = create_line_plot( + (x, y), bgcolor="white", add_grid=True, add_axis=True + ) left_plot.tools.append(PanTool(left_plot)) self.left_plot = left_plot y = jn(1, x) - right_plot = create_line_plot((x,y), bgcolor="white", - add_grid=True, add_axis=True) + right_plot = create_line_plot( + (x, y), bgcolor="white", add_grid=True, add_axis=True + ) right_plot.tools.append(PanTool(right_plot)) right_plot.y_axis.orientation = "right" self.right_plot = right_plot # Tone down the colors on the grids - right_plot.hgrid.line_color = (0.3,0.3,0.3,0.5) - right_plot.vgrid.line_color = (0.3,0.3,0.3,0.5) - left_plot.hgrid.line_color = (0.3,0.3,0.3,0.5) - left_plot.vgrid.line_color = (0.3,0.3,0.3,0.5) + right_plot.hgrid.line_color = (0.3, 0.3, 0.3, 0.5) + right_plot.vgrid.line_color = (0.3, 0.3, 0.3, 0.5) + left_plot.hgrid.line_color = (0.3, 0.3, 0.3, 0.5) + left_plot.vgrid.line_color = (0.3, 0.3, 0.3, 0.5) container = HPlotContainer(spacing=20, padding=50, bgcolor="lightgray") container.add(left_plot) container.add(right_plot) return container + demo = PlotExample() if __name__ == "__main__": diff --git a/examples/tutorials/tutorial9.py b/examples/tutorials/tutorial9.py index 69c50d60d..32c216c1c 100644 --- a/examples/tutorials/tutorial9.py +++ b/examples/tutorials/tutorial9.py @@ -10,12 +10,15 @@ def _container_default(self): rplot, lplot = self.right_plot, self.left_plot rplot.index_mapper.range = lplot.index_mapper.range - lplot.value_mapper.range.low = min(rplot.value_mapper.range.low, - lplot.value_mapper.range.low,) + lplot.value_mapper.range.low = min( + rplot.value_mapper.range.low, + lplot.value_mapper.range.low, + ) rplot.value_mapper.range = lplot.value_mapper.range return container + demo = PlotExample2() if __name__ == "__main__": diff --git a/examples/tutorials/tutorial9b.py b/examples/tutorials/tutorial9b.py index 4c5a0ce93..43dd54ddc 100644 --- a/examples/tutorials/tutorial9b.py +++ b/examples/tutorials/tutorial9b.py @@ -14,11 +14,12 @@ def _container_default(self): rplot.index_mapper.range = lplot.index_mapper.range rplot.value_mapper.range = lplot.value_mapper.range - lplot.overlays.append(ZoomTool(lplot, tool_mode="box",always_on=False)) - rplot.overlays.append(ZoomTool(rplot, tool_mode="box",always_on=False)) + lplot.overlays.append(ZoomTool(lplot, tool_mode="box", always_on=False)) + rplot.overlays.append(ZoomTool(rplot, tool_mode="box", always_on=False)) return container + demo = PlotExample2() if __name__ == "__main__": diff --git a/examples/user_guide/grid_plot_container.py b/examples/user_guide/grid_plot_container.py index 6a2b7943d..040324fd2 100644 --- a/examples/user_guide/grid_plot_container.py +++ b/examples/user_guide/grid_plot_container.py @@ -15,41 +15,40 @@ class GridContainerExample(HasTraits): plot = Instance(GridPlotContainer) traits_view = View( - Item('plot', editor=ComponentEditor(), show_label=False), - width=1000, height=600, resizable=True + Item("plot", editor=ComponentEditor(), show_label=False), + width=1000, + height=600, + resizable=True, ) def _plot_default(self): # Create a GridContainer to hold all of our plots: 2 rows, 3 columns - container = GridPlotContainer(shape=(2,3), - spacing=(10,5), - valign='top', - bgcolor='lightgray') + container = GridPlotContainer( + shape=(2, 3), spacing=(10, 5), valign="top", bgcolor="lightgray" + ) # Create x data x = linspace(-5, 15.0, 100) - pd = ArrayPlotData(index = x) + pd = ArrayPlotData(index=x) # Plot some Bessel functions and add the plots to our container for i in range(6): - data_name = 'y{}'.format(i) - pd.set_data(data_name, jn(i,x)) + data_name = "y{}".format(i) + pd.set_data(data_name, jn(i, x)) plot = Plot(pd) - plot.plot(('index', data_name), - color=COLOR_PALETTE[i], - line_width=3.0) + plot.plot(("index", data_name), color=COLOR_PALETTE[i], line_width=3.0) # Set each plot's aspect based on its position in the grid plot.height = ((i % 3) + 1) * 50.0 - plot.resizable = 'h' + plot.resizable = "h" # Add to the grid container container.add(plot) return container -if __name__ == '__main__': + +if __name__ == "__main__": demo = GridContainerExample() demo.configure_traits() - diff --git a/examples/user_guide/h_plot_container.py b/examples/user_guide/h_plot_container.py index fb63c77c2..0240df6a9 100644 --- a/examples/user_guide/h_plot_container.py +++ b/examples/user_guide/h_plot_container.py @@ -5,18 +5,23 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ContainerExample(HasTraits): plot = Instance(HPlotContainer) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=1000, height=600, resizable=True) + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=1000, + height=600, + resizable=True, + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a scatter plot scatter_plot = Plot(plotdata) @@ -30,7 +35,7 @@ def __init__(self): container = HPlotContainer(line_plot, scatter_plot, spacing=100) self.plot = container + if __name__ == "__main__": demo = ContainerExample() demo.configure_traits() - diff --git a/examples/user_guide/h_plot_container_add_multiple_times.py b/examples/user_guide/h_plot_container_add_multiple_times.py index bfaccb972..d65be0209 100644 --- a/examples/user_guide/h_plot_container_add_multiple_times.py +++ b/examples/user_guide/h_plot_container_add_multiple_times.py @@ -9,18 +9,20 @@ from traits.api import HasTraits, Instance from traitsui.api import Item, View + class ContainerExample(HasTraits): plot = Instance(VPlotContainer) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - resizable=True) + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), resizable=True + ) def __init__(self): # Create the data and the PlotData object x = linspace(-14, 14, 100) - y = sin(x) * x**3 - plotdata = ArrayPlotData(x = x, y = y) + y = sin(x) * x ** 3 + plotdata = ArrayPlotData(x=x, y=y) # Create a scatter plot scatter_plot = Plot(plotdata) @@ -35,8 +37,9 @@ def __init__(self): # Create a vertical container containing two horizontal containers h_container1 = HPlotContainer() h_container2 = HPlotContainer() - outer_container = VPlotContainer(h_container1, h_container2, - stack_order="top_to_bottom") + outer_container = VPlotContainer( + h_container1, h_container2, stack_order="top_to_bottom" + ) # Add the two plots to the first container h_container1.add(scatter_plot, line_plot1, line_plot2) @@ -47,7 +50,7 @@ def __init__(self): self.plot = outer_container + if __name__ == "__main__": demo = ContainerExample() demo.configure_traits() - diff --git a/examples/user_guide/h_plot_container_colorbar.py b/examples/user_guide/h_plot_container_colorbar.py index 5e7db851f..5b74f9714 100644 --- a/examples/user_guide/h_plot_container_colorbar.py +++ b/examples/user_guide/h_plot_container_colorbar.py @@ -8,35 +8,43 @@ N_POINTS = 100 + class ColorbarExample(HasTraits): plot = Instance(HPlotContainer) - traits_view = View(Item('plot', editor=ComponentEditor(), show_label=False), - width=600, height=600, resizable=True) + traits_view = View( + Item("plot", editor=ComponentEditor(), show_label=False), + width=600, + height=600, + resizable=True, + ) def __init__(self): # Create some data x = np.random.random(N_POINTS) y = np.random.random(N_POINTS) - color = np.exp(-(x**2 + y**2)) + color = np.exp(-(x ** 2 + y ** 2)) # Create a plot data object and give it this data data = ArrayPlotData(index=x, value=y, color=color) # Create the plot plot = Plot(data) - plot.plot(("index", "value", "color"), type="cmap_scatter", - color_mapper=viridis) + plot.plot( + ("index", "value", "color"), type="cmap_scatter", color_mapper=viridis + ) # Create the colorbar, handing in the appropriate range and colormap colormap = plot.color_mapper - colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range), - color_mapper=colormap, - orientation='v', - resizable='v', - width=30, - padding=20) + colorbar = ColorBar( + index_mapper=LinearMapper(range=colormap.range), + color_mapper=colormap, + orientation="v", + resizable="v", + width=30, + padding=20, + ) colorbar.padding_top = plot.padding_top colorbar.padding_bottom = plot.padding_bottom @@ -45,6 +53,7 @@ def __init__(self): container = HPlotContainer(plot, colorbar) self.plot = container + if __name__ == "__main__": demo = ColorbarExample() demo.configure_traits() diff --git a/examples/user_guide/overlay_container_inset.py b/examples/user_guide/overlay_container_inset.py index 39984e976..77e297ab7 100644 --- a/examples/user_guide/overlay_container_inset.py +++ b/examples/user_guide/overlay_container_inset.py @@ -15,8 +15,10 @@ class OverlayContainerExample(HasTraits): plot = Instance(OverlayPlotContainer) traits_view = View( - Item('plot', editor=ComponentEditor(), show_label=False), - width=800, height=600, resizable=True + Item("plot", editor=ComponentEditor(), show_label=False), + width=800, + height=600, + resizable=True, ) def _plot_default(self): @@ -26,19 +28,19 @@ def _plot_default(self): pd = ArrayPlotData(index=x, value=y) zoomable_plot = Plot(pd) - zoomable_plot.plot(('index', 'value'), - name='external', color='red', line_width=3) + zoomable_plot.plot( + ("index", "value"), name="external", color="red", line_width=3 + ) # Attach tools to the plot - zoom = ZoomTool(component=zoomable_plot, - tool_mode="box", always_on=False) + zoom = ZoomTool(component=zoomable_plot, tool_mode="box", always_on=False) zoomable_plot.overlays.append(zoom) zoomable_plot.tools.append(PanTool(zoomable_plot)) # Create a second inset plot, not resizable, not zoom-able inset_plot = Plot(pd) - inset_plot.plot(('index', 'value'), color='blue') - inset_plot.resizable = '' + inset_plot.plot(("index", "value"), color="blue") + inset_plot.resizable = "" inset_plot.bounds = [250, 150] inset_plot.position = [450, 350] inset_plot.border_visible = True @@ -49,7 +51,7 @@ def _plot_default(self): container.add(inset_plot) return container -if __name__ == '__main__': + +if __name__ == "__main__": demo = OverlayContainerExample() demo.configure_traits() - diff --git a/examples/user_guide/plot_types/create_plot_snapshots.py b/examples/user_guide/plot_types/create_plot_snapshots.py index 4e0f673d8..6384f261c 100644 --- a/examples/user_guide/plot_types/create_plot_snapshots.py +++ b/examples/user_guide/plot_types/create_plot_snapshots.py @@ -47,17 +47,17 @@ AXIS_WIDTH = 2 PLOT_DEFAULTS = { - 'color': 'blue', - 'line_width': 3.0, - 'border_visible': True, - 'border_width': AXIS_WIDTH + "color": "blue", + "line_width": 3.0, + "border_visible": True, + "border_width": AXIS_WIDTH, } AXIS_DEFAULTS = { - 'axis_line_weight': AXIS_WIDTH, - 'tick_weight': AXIS_WIDTH, - 'tick_label_font': 'modern 16', - 'title_font': 'modern 20', + "axis_line_weight": AXIS_WIDTH, + "tick_weight": AXIS_WIDTH, + "tick_label_font": "modern 16", + "title_font": "modern 20", } @@ -76,7 +76,6 @@ def get_data_sources(x=None, y=None): def get_mappers(x_source, y_source): - def _1D_mapper(source): data_range = DataRange1D() data_range.add(source) @@ -85,18 +84,22 @@ def _1D_mapper(source): return _1D_mapper(x_source), _1D_mapper(y_source) -def add_axes(plot, x_label='', y_label=''): - y_axis = PlotAxis(orientation='left', - title=y_label, - mapper=plot.y_mapper, - component=plot, - **AXIS_DEFAULTS) +def add_axes(plot, x_label="", y_label=""): + y_axis = PlotAxis( + orientation="left", + title=y_label, + mapper=plot.y_mapper, + component=plot, + **AXIS_DEFAULTS + ) - x_axis = PlotAxis(orientation='bottom', - title=x_label, - mapper=plot.x_mapper, - component=plot, - **AXIS_DEFAULTS) + x_axis = PlotAxis( + orientation="bottom", + title=x_label, + mapper=plot.x_mapper, + component=plot, + **AXIS_DEFAULTS + ) plot.underlays.append(x_axis) plot.underlays.append(y_axis) @@ -106,7 +109,7 @@ def save_plot(plot, filename): width, height = plot.outer_bounds plot.do_layout(force=True) - gc = PlotGraphicsContext((width, height), dpi=72.0*2) + gc = PlotGraphicsContext((width, height), dpi=72.0 * 2) gc.render_component(plot) gc.save(filename) @@ -114,6 +117,7 @@ def save_plot(plot, filename): # ---- factories for example plots + def get_line_plot(render_style): prng = np.random.RandomState(seed=1234) x_data = np.linspace(0, 10, 50) @@ -123,13 +127,15 @@ def get_line_plot(render_style): x_mapper, y_mapper = get_mappers(x, y) line_plot = LinePlot( - index=x, value=y, - index_mapper=x_mapper, value_mapper=y_mapper, + index=x, + value=y, + index_mapper=x_mapper, + value_mapper=y_mapper, render_style=render_style, **PLOT_DEFAULTS ) - add_axes(line_plot, x_label='x', y_label='y') + add_axes(line_plot, x_label="x", y_label="y") return line_plot @@ -141,126 +147,141 @@ def get_line_plot(render_style): def get_scatter_plot(): boston = datasets.load_boston() - prices = boston['target'] - lower_status = boston['data'][:, -1] + prices = boston["target"] + lower_status = boston["data"][:, -1] x, y = get_data_sources(x=lower_status, y=prices) x_mapper, y_mapper = get_mappers(x, y) scatter_plot = ScatterPlot( - index=x, value=y, - index_mapper=x_mapper, value_mapper=y_mapper, - marker='circle', + index=x, + value=y, + index_mapper=x_mapper, + value_mapper=y_mapper, + marker="circle", **PLOT_DEFAULTS ) scatter_plot.line_width = 1.0 - add_axes(scatter_plot, x_label='Percent lower status in the population', - y_label='Median house prices') + add_axes( + scatter_plot, + x_label="Percent lower status in the population", + y_label="Median house prices", + ) return scatter_plot def get_cmap_scatter_plot(): boston = datasets.load_boston() - prices = boston['target'] - lower_status = boston['data'][:, -1] - nox = boston['data'][:, 4] + prices = boston["target"] + lower_status = boston["data"][:, -1] + nox = boston["data"][:, 4] x, y = get_data_sources(x=lower_status, y=prices) x_mapper, y_mapper = get_mappers(x, y) color_source = ArrayDataSource(nox) - color_mapper = dc.reverse(dc.RdYlGn)( - DataRange1D(low=nox.min(), high=nox.max()) - ) + color_mapper = dc.reverse(dc.RdYlGn)(DataRange1D(low=nox.min(), high=nox.max())) scatter_plot = ColormappedScatterPlot( - index=x, value=y, - index_mapper=x_mapper, value_mapper=y_mapper, + index=x, + value=y, + index_mapper=x_mapper, + value_mapper=y_mapper, color_data=color_source, color_mapper=color_mapper, - marker='circle', - title='Color represents nitric oxides concentration', - render_method='bruteforce', + marker="circle", + title="Color represents nitric oxides concentration", + render_method="bruteforce", **PLOT_DEFAULTS ) - add_axes(scatter_plot, x_label='Percent lower status in the population', - y_label='Median house prices') + add_axes( + scatter_plot, + x_label="Percent lower status in the population", + y_label="Median house prices", + ) return scatter_plot def get_4d_scatter_plot(): boston = datasets.load_boston() - prices = boston['target'] - lower_status = boston['data'][:, -1] - tax = boston['data'][:, 9] - nox = boston['data'][:, 4] + prices = boston["target"] + lower_status = boston["data"][:, -1] + tax = boston["data"][:, 9] + nox = boston["data"][:, 4] x, y = get_data_sources(x=lower_status, y=prices) x_mapper, y_mapper = get_mappers(x, y) color_source = ArrayDataSource(nox) - color_mapper = dc.reverse(dc.RdYlGn)( - DataRange1D(low=nox.min(), high=nox.max()) - ) + color_mapper = dc.reverse(dc.RdYlGn)(DataRange1D(low=nox.min(), high=nox.max())) # normalize between 0 and 10 - marker_size = tax / tax.max() * 10. + marker_size = tax / tax.max() * 10.0 scatter_plot = ColormappedScatterPlot( - index=x, value=y, - index_mapper=x_mapper, value_mapper=y_mapper, + index=x, + value=y, + index_mapper=x_mapper, + value_mapper=y_mapper, color_data=color_source, color_mapper=color_mapper, fill_alpha=0.8, - marker='circle', + marker="circle", marker_size=marker_size, - title='Size represents property-tax rate, ' - 'color nitric oxides concentration', - render_method='bruteforce', + title="Size represents property-tax rate, " "color nitric oxides concentration", + render_method="bruteforce", **PLOT_DEFAULTS ) - add_axes(scatter_plot, x_label='Percent lower status in the population', - y_label='Median house prices') + add_axes( + scatter_plot, + x_label="Percent lower status in the population", + y_label="Median house prices", + ) return scatter_plot def get_variable_size_scatter_plot(): boston = datasets.load_boston() - prices = boston['target'] - lower_status = boston['data'][:, -1] - tax = boston['data'][:, 9] + prices = boston["target"] + lower_status = boston["data"][:, -1] + tax = boston["data"][:, 9] x, y = get_data_sources(x=lower_status, y=prices) x_mapper, y_mapper = get_mappers(x, y) # normalize between 0 and 10 - marker_size = tax / tax.max() * 10. + marker_size = tax / tax.max() * 10.0 scatter_plot = ScatterPlot( - index=x, value=y, - index_mapper=x_mapper, value_mapper=y_mapper, - marker='circle', + index=x, + value=y, + index_mapper=x_mapper, + value_mapper=y_mapper, + marker="circle", marker_size=marker_size, - title='Size represents property-tax rate', + title="Size represents property-tax rate", **PLOT_DEFAULTS ) scatter_plot.color = (0.0, 1.0, 0.3, 0.4) - add_axes(scatter_plot, x_label='Percent lower status in the population', - y_label='Median house prices') + add_axes( + scatter_plot, + x_label="Percent lower status in the population", + y_label="Median house prices", + ) return scatter_plot def get_jitter_plot(): boston = datasets.load_boston() - prices = boston['target'] + prices = boston["target"] x, y = get_data_sources(y=prices) x_mapper, y_mapper = get_mappers(x, y) @@ -268,18 +289,20 @@ def get_jitter_plot(): jitter_plot = JitterPlot( index=y, index_mapper=y_mapper, - orientation='h', - marker='circle', + orientation="h", + marker="circle", jitter_width=100, **PLOT_DEFAULTS ) - jitter_plot.line_width = 1. - - x_axis = PlotAxis(orientation='bottom', - title='Median house prices', - mapper=jitter_plot.index_mapper, - component=jitter_plot, - **AXIS_DEFAULTS) + jitter_plot.line_width = 1.0 + + x_axis = PlotAxis( + orientation="bottom", + title="Median house prices", + mapper=jitter_plot.index_mapper, + component=jitter_plot, + **AXIS_DEFAULTS + ) jitter_plot.underlays.append(x_axis) @@ -293,8 +316,8 @@ def get_candle_plot(): x = ArrayDataSource(np.arange(3)) center = ArrayDataSource(data.mean(0)) - bar_min = ArrayDataSource(data.mean(0)-data.std(0)) - bar_max = ArrayDataSource(data.mean(0)+data.std(0)) + bar_min = ArrayDataSource(data.mean(0) - data.std(0)) + bar_max = ArrayDataSource(data.mean(0) + data.std(0)) stem_min = ArrayDataSource(data.min(0)) stem_max = ArrayDataSource(data.max(0)) @@ -311,21 +334,20 @@ def get_candle_plot(): bar_max=bar_max, min_values=stem_min, max_values=stem_max, - center_color='yellow', - bar_color='orange', + center_color="yellow", + bar_color="orange", **PLOT_DEFAULTS ) - add_axes(candle_plot, x_label='Items', y_label='Values') + add_axes(candle_plot, x_label="Items", y_label="Values") return candle_plot def get_errorbar_plot(): - x = np.linspace(1., 5., 10) - y = 3.2 * x**2 + 4.0 - y_with_noise = (y[None, :] - + scipy.stats.norm(loc=0, scale=2.8).rvs((10, 1))) + x = np.linspace(1.0, 5.0, 10) + y = 3.2 * x ** 2 + 4.0 + y_with_noise = y[None, :] + scipy.stats.norm(loc=0, scale=2.8).rvs((10, 1)) means = y_with_noise.mean(0) stds = y_with_noise.std(0) @@ -340,16 +362,17 @@ def get_errorbar_plot(): y_range.add(y, low, high) errorbar_plot = ErrorBarPlot( - index=x, value=y, + index=x, + value=y, index_mapper=LinearMapper(range=x_range), value_mapper=LinearMapper(range=y_range), value_low=low, value_high=high, - endcap_size=11., + endcap_size=11.0, **PLOT_DEFAULTS ) - add_axes(errorbar_plot, x_label='Test values', y_label='Measured') + add_axes(errorbar_plot, x_label="Test values", y_label="Measured") return errorbar_plot @@ -363,14 +386,16 @@ def get_filled_line_plot(): x_mapper, y_mapper = get_mappers(x, y) line_plot = FilledLinePlot( - index=x, value=y, - index_mapper=x_mapper, value_mapper=y_mapper, - fill_color='lightgreen', + index=x, + value=y, + index_mapper=x_mapper, + value_mapper=y_mapper, + fill_color="lightgreen", edge_width=3.0, **PLOT_DEFAULTS ) - add_axes(line_plot, x_label='x', y_label='y') + add_axes(line_plot, x_label="x", y_label="y") return line_plot @@ -378,48 +403,44 @@ def get_filled_line_plot(): def get_image_plot(): # Create some RGBA image data image = np.zeros((200, 400, 4), dtype=np.uint8) - image[:, 0:40, 0] += 255 # Vertical red stripe - image[0:25, :, 1] += 255 # Horizontal green stripe; also yellow square + image[:, 0:40, 0] += 255 # Vertical red stripe + image[0:25, :, 1] += 255 # Horizontal green stripe; also yellow square image[-80:, -160:, 2] += 255 # Blue square image[:, :, 3] = 255 - index = GridDataSource(np.linspace(0, 4., 400), np.linspace(-1, 1., 200)) - index_mapper = GridMapper(range=DataRange2D(low=(0, -1), high=(4., 1.))) + index = GridDataSource(np.linspace(0, 4.0, 400), np.linspace(-1, 1.0, 200)) + index_mapper = GridMapper(range=DataRange2D(low=(0, -1), high=(4.0, 1.0))) image_source = ImageData(data=image, value_depth=4) image_plot = ImagePlot( - index=index, - value=image_source, - index_mapper=index_mapper, - **PLOT_DEFAULTS + index=index, value=image_source, index_mapper=index_mapper, **PLOT_DEFAULTS ) - add_axes(image_plot, x_label='x', y_label='y') + add_axes(image_plot, x_label="x", y_label="y") return image_plot def get_image_from_file(): import os.path - filename = os.path.join('..', '..', - 'demo', 'basic', 'capitol.jpg') + + filename = os.path.join("..", "..", "demo", "basic", "capitol.jpg") image_source = ImageData.fromfile(filename) w, h = image_source.get_width(), image_source.get_height() index = GridDataSource(np.arange(w), np.arange(h)) - index_mapper = GridMapper(range=DataRange2D(low=(0, 0), - high=(w-1, h-1))) + index_mapper = GridMapper(range=DataRange2D(low=(0, 0), high=(w - 1, h - 1))) image_plot = ImagePlot( index=index, value=image_source, index_mapper=index_mapper, - origin='top left', + origin="top left", **PLOT_DEFAULTS ) - add_axes(image_plot, x_label='x', y_label='y') + add_axes(image_plot, x_label="x", y_label="y") return image_plot @@ -429,9 +450,9 @@ def get_cmap_image_plot(): NPOINTS = 200 xs = np.linspace(-2 * np.pi, +2 * np.pi, NPOINTS) - ys = np.linspace(-1.5*np.pi, +1.5*np.pi, NPOINTS) + ys = np.linspace(-1.5 * np.pi, +1.5 * np.pi, NPOINTS) x, y = np.meshgrid(xs, ys) - z = scipy.special.jn(2, x)*y*x + z = scipy.special.jn(2, x) * y * x index = GridDataSource(xdata=xs, ydata=ys) index_mapper = GridMapper(range=DataRange2D(index)) @@ -447,7 +468,7 @@ def get_cmap_image_plot(): **PLOT_DEFAULTS ) - add_axes(cmap_plot, x_label='x', y_label='y') + add_axes(cmap_plot, x_label="x", y_label="y") return cmap_plot @@ -457,9 +478,9 @@ def get_contour_line_plot(): # Create a scalar field to contour xs = np.linspace(-2 * np.pi, +2 * np.pi, NPOINTS_X) - ys = np.linspace(-1.5*np.pi, +1.5*np.pi, NPOINTS_Y) + ys = np.linspace(-1.5 * np.pi, +1.5 * np.pi, NPOINTS_Y) x, y = np.meshgrid(xs, ys) - z = scipy.special.jn(2, x)*y*x + z = scipy.special.jn(2, x) * y * x index = GridDataSource(xdata=xs, ydata=ys) index_mapper = GridMapper(range=DataRange2D(index)) @@ -476,7 +497,7 @@ def get_contour_line_plot(): **PLOT_DEFAULTS ) - add_axes(contour_plot, x_label='x', y_label='y') + add_axes(contour_plot, x_label="x", y_label="y") return contour_plot @@ -486,9 +507,9 @@ def get_contour_poly_plot(): # Create a scalar field to contour xs = np.linspace(-2 * np.pi, +2 * np.pi, NPOINTS_X) - ys = np.linspace(-1.5*np.pi, +1.5*np.pi, NPOINTS_Y) + ys = np.linspace(-1.5 * np.pi, +1.5 * np.pi, NPOINTS_Y) x, y = np.meshgrid(xs, ys) - z = scipy.special.jn(2, x)*y*x + z = scipy.special.jn(2, x) * y * x index = GridDataSource(xdata=xs, ydata=ys) index_mapper = GridMapper(range=DataRange2D(index)) @@ -504,7 +525,7 @@ def get_contour_poly_plot(): **PLOT_DEFAULTS ) - add_axes(contour_plot, x_label='x', y_label='y') + add_axes(contour_plot, x_label="x", y_label="y") return contour_plot @@ -522,21 +543,21 @@ def get_polygon_plot(): index_mapper=x_mapper, value_mapper=y_mapper, edge_width=4.0, - face_color='orange', + face_color="orange", **PLOT_DEFAULTS ) - add_axes(polygon_plot, x_label='x', y_label='y') + add_axes(polygon_plot, x_label="x", y_label="y") return polygon_plot def get_bar_plot(): boston = datasets.load_boston() - prices = boston['target'] + prices = boston["target"] ys, bin_edges = np.histogram(prices, bins=10) - ys = ys.astype('d') / ys.sum() + ys = ys.astype("d") / ys.sum() xs = (bin_edges[:-1] + bin_edges[1:]) / 2.0 x, y = get_data_sources(x=xs, y=ys) @@ -545,8 +566,8 @@ def get_bar_plot(): # we need to make the range of the x coordinate a bit larger, otherwise # half of the first and last bar are cut delta = bin_edges[1] - bin_edges[0] - x_mapper.range.low = xs[0] - delta / 2. - x_mapper.range.high = xs[-1] + delta / 2. + x_mapper.range.low = xs[0] - delta / 2.0 + x_mapper.range.high = xs[-1] + delta / 2.0 y_mapper.range.high += 0.02 @@ -555,12 +576,12 @@ def get_bar_plot(): value=y, index_mapper=x_mapper, value_mapper=y_mapper, - fill_color='blue', + fill_color="blue", bar_width=3.0, **PLOT_DEFAULTS ) - add_axes(bar_plot, x_label='Median house prices', y_label='Frequency') + add_axes(bar_plot, x_label="Median house prices", y_label="Frequency") return bar_plot @@ -577,9 +598,8 @@ def get_quiver_plot(): # vectors are tangent to a circle centered in (0, 0) and the size depends # on the radius - r = np.sqrt(xs*xs + ys*ys) * 20.0 - v = r * np.array([-np.sin(np.arctan2(ys, xs)), - np.cos(np.arctan2(ys, xs))]) + r = np.sqrt(xs * xs + ys * ys) * 20.0 + v = r * np.array([-np.sin(np.arctan2(ys, xs)), np.cos(np.arctan2(ys, xs))]) v_source = MultiArrayDataSource(v.T) quiver_plot = QuiverPlot( @@ -588,10 +608,10 @@ def get_quiver_plot(): vectors=v_source, index_mapper=x_mapper, value_mapper=y_mapper, - aspect_ratio=1.0 + aspect_ratio=1.0, ) - add_axes(quiver_plot, x_label='x', y_label='y') + add_axes(quiver_plot, x_label="x", y_label="y") return quiver_plot @@ -600,10 +620,10 @@ def get_polar_plot(): # Create theta N_POINTS = 5000 low, high = 0, np.pi - theta = np.arange(low, high, (high-low) / N_POINTS) + theta = np.arange(low, high, (high - low) / N_POINTS) # Create the radius data - radius = np.cos(3*theta) + radius = np.cos(3 * theta) # FIXME: at the moment PolarMapper does not actually do anything, so # we need to transform to Cartesian coordinates by hand @@ -615,7 +635,8 @@ def get_polar_plot(): value_mapper = PolarMapper(range=DataRange1D(y)) polar_plot = PolarLineRenderer( - index=x, value=y, + index=x, + value=y, index_mapper=index_mapper, value_mapper=value_mapper, aspect_ratio=1.0, @@ -630,13 +651,15 @@ def get_multiline_plot(): prng = np.random.RandomState(seed=1234) x = np.linspace(0, 10, 50) - y_data = np.column_stack([ - x ** 2, - 50 * np.sin(x), - 50 * np.cos(x), - 0.5 * x ** 2 + 2 * prng.randn(50), - 0.7 * x ** 2 + prng.randn(50), - ]) + y_data = np.column_stack( + [ + x ** 2, + 50 * np.sin(x), + 50 * np.cos(x), + 0.5 * x ** 2 + 2 * prng.randn(50), + 0.7 * x ** 2 + prng.randn(50), + ] + ) # data sources for the two axes xs = ArrayDataSource(np.arange(50)) @@ -647,7 +670,7 @@ def get_multiline_plot(): # data source for the multiple lines lines_source = MultiArrayDataSource(data=y_data.T) - colors = ['blue', 'green', 'yellow', 'orange', 'red'] + colors = ["blue", "green", "yellow", "orange", "red"] def color_generator(color_idx): return color_table[colors[color_idx]] @@ -664,45 +687,53 @@ def color_generator(color_idx): **PLOT_DEFAULTS ) - add_axes(multiline_plot, x_label='Days', y_label='Stock price changes') + add_axes(multiline_plot, x_label="Days", y_label="Stock price changes") - y_grid = PlotGrid(mapper=y_mapper, orientation="horizontal", - line_style="dot", component=multiline_plot) + y_grid = PlotGrid( + mapper=y_mapper, + orientation="horizontal", + line_style="dot", + component=multiline_plot, + ) multiline_plot.overlays.append(y_grid) return multiline_plot all_examples = { - 'line': get_line_plot_connected, - 'line_hold': get_line_plot_hold, - 'line_connectedhold': get_line_plot_connectedhold, - 'scatter': get_scatter_plot, - 'cmap_scatter': get_cmap_scatter_plot, - '4d_scatter': get_4d_scatter_plot, - 'vsize_scatter': get_variable_size_scatter_plot, - 'jitter': get_jitter_plot, - 'candle': get_candle_plot, - 'errorbar': get_errorbar_plot, - 'filled_line': get_filled_line_plot, - 'image': get_image_plot, - 'image_from_file': get_image_from_file, - 'cmap_image': get_cmap_image_plot, - 'contour_line': get_contour_line_plot, - 'contour_poly': get_contour_poly_plot, - 'polygon': get_polygon_plot, - 'bar': get_bar_plot, - 'quiver': get_quiver_plot, - 'polar': get_polar_plot, - 'multiline': get_multiline_plot, + "line": get_line_plot_connected, + "line_hold": get_line_plot_hold, + "line_connectedhold": get_line_plot_connectedhold, + "scatter": get_scatter_plot, + "cmap_scatter": get_cmap_scatter_plot, + "4d_scatter": get_4d_scatter_plot, + "vsize_scatter": get_variable_size_scatter_plot, + "jitter": get_jitter_plot, + "candle": get_candle_plot, + "errorbar": get_errorbar_plot, + "filled_line": get_filled_line_plot, + "image": get_image_plot, + "image_from_file": get_image_from_file, + "cmap_image": get_cmap_image_plot, + "contour_line": get_contour_line_plot, + "contour_poly": get_contour_poly_plot, + "polygon": get_polygon_plot, + "bar": get_bar_plot, + "quiver": get_quiver_plot, + "polar": get_polar_plot, + "multiline": get_multiline_plot, } def main(): p = argparse.ArgumentParser() - p.add_argument("-n", "--name", help=( - "Name of the plot snapshot to create. If this is omitted, all " - "snapshots are created.") + p.add_argument( + "-n", + "--name", + help=( + "Name of the plot snapshot to create. If this is omitted, all " + "snapshots are created." + ), ) name = p.parse_args().name if name is None: @@ -715,7 +746,7 @@ def main(): def create_plot_types(names): for name in names: - fname = '{}_plot.png'.format(name) + fname = "{}_plot.png".format(name) print("*** creating figure {!r} for type {!r} ***".format(fname, name)) plot = all_examples[name]() @@ -725,5 +756,5 @@ def create_plot_types(names): save_plot(window.container, fname) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/examples/user_guide/plot_types/plot_window.py b/examples/user_guide/plot_types/plot_window.py index a3f25556e..130267b29 100644 --- a/examples/user_guide/plot_types/plot_window.py +++ b/examples/user_guide/plot_types/plot_window.py @@ -4,16 +4,17 @@ from traits.api import HasTraits, Instance, observe from traitsui.api import Item, View + class PlotWindow(HasTraits): plot = Instance(PlotComponent) container = Instance(DataView) - @observe('plot') + @observe("plot") def _update_container(self, event): self.container = DataView( - padding=(80,20,20,60), # make some space for axis labels - border_visible=False + padding=(80, 20, 20, 60), # make some space for axis labels + border_visible=False, ) self.container.add(self.plot) @@ -22,9 +23,9 @@ def _update_container(self, event): # remove axes etc self.container.underlays = [] - - - traits_view = View(Item('container', - editor=ComponentEditor(), - show_label=False), - width=600, height=400, resizable=True) + traits_view = View( + Item("container", editor=ComponentEditor(), show_label=False), + width=600, + height=400, + resizable=True, + ) diff --git a/examples/user_guide/power_function_example.py b/examples/user_guide/power_function_example.py index 23b97ac9b..8c74d2511 100644 --- a/examples/user_guide/power_function_example.py +++ b/examples/user_guide/power_function_example.py @@ -19,20 +19,15 @@ class PowerFunctionExample(HasStrictTraits): power = Range(0, 5, value=2) #: The x-values to plot. - x = Array(shape=(None,), dtype='float') + x = Array(shape=(None,), dtype="float") # Trait defaults -------------------------------------------------------- def _plot_default(self): - y = self.x**self.power + y = self.x ** self.power plot_data = ArrayPlotData(x=self.x, y=y) plot = Plot(plot_data) - plot.plot( - ('x', 'y'), - 'line', - name="power function", - color='auto' - ) + plot.plot(("x", "y"), "line", name="power function", color="auto") # configure the plot plot.padding_top = 25 @@ -40,9 +35,9 @@ def _plot_default(self): plot.index_grid.visible = False plot.value_grid.visible = False plot.title = "Power Function n={}".format(self.power) - plot.title_position = 'right' + plot.title_position = "right" plot.title_angle = -90 - plot.legend_alignment = 'ul' + plot.legend_alignment = "ul" plot.legend.border_visible = False plot.legend.bgcolor = (0.9, 0.9, 0.9, 0.5) plot.legend.visible = True @@ -57,17 +52,17 @@ def _x_default(self): # Trait change handlers ------------------------------------------------- - @on_trait_change('power') + @on_trait_change("power") def _update_y(self): - y = self.x**self.power - self.plot.data.set_data('y', y) + y = self.x ** self.power + self.plot.data.set_data("y", y) - @on_trait_change('x') + @on_trait_change("x") def _update_data(self): - y = self.x**self.power + y = self.x ** self.power self.plot.data.update_data(x=self.x, y=y) - @on_trait_change('power') + @on_trait_change("power") def _update_title(self): self.plot.title = "Power Function n={}".format(self.power) @@ -75,17 +70,17 @@ def _update_title(self): view = View( VGroup( - Item('plot', editor=ComponentEditor()), + Item("plot", editor=ComponentEditor()), VGroup( - Item('power'), + Item("power"), ), show_labels=False, ), resizable=True, - title="Power Function Example" + title="Power Function Example", ) -if __name__ == '__main__': +if __name__ == "__main__": view = PowerFunctionExample() view.configure_traits() From 5399b1735a19b6287fc073f57c01faa3f87187fa Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Fri, 2 Apr 2021 10:42:10 -0500 Subject: [PATCH 3/7] run black again but specify -l 79 --- chaco/_speedups_fallback.py | 4 +- chaco/abstract_plot_renderer.py | 6 +- chaco/api.py | 5 +- chaco/array_data_source.py | 5 +- chaco/array_plot_data.py | 3 +- chaco/axis.py | 55 +++- chaco/barplot.py | 23 +- chaco/base.py | 4 +- chaco/base_1d_mapper.py | 4 +- chaco/base_1d_plot.py | 20 +- chaco/base_2d_plot.py | 24 +- chaco/base_candle_plot.py | 12 +- chaco/base_contour_plot.py | 21 +- chaco/base_plot_container.py | 3 +- chaco/base_plot_frame.py | 3 +- chaco/base_xy_plot.py | 48 +++- chaco/candle_plot.py | 10 +- chaco/chaco_plot_container_editor.py | 3 +- chaco/chaco_plot_editor.py | 18 +- chaco/cmap_image_plot.py | 8 +- chaco/color_bar.py | 27 +- chaco/color_mapper.py | 16 +- chaco/colormap_generators.py | 8 +- chaco/colormapped_scatterplot.py | 43 +++- chaco/colormapped_selection_overlay.py | 17 +- chaco/contour_line_plot.py | 4 +- chaco/contour_poly_plot.py | 4 +- chaco/cross_plot_frame.py | 6 +- chaco/data_frame_plot_data.py | 3 +- chaco/data_range_1d.py | 12 +- chaco/data_range_2d.py | 11 +- chaco/data_view.py | 28 +- chaco/default_colormaps.py | 243 +++++++++++++++--- chaco/errorbar_plot.py | 6 +- chaco/filled_line_plot.py | 3 +- chaco/function_data_source.py | 4 +- chaco/grid.py | 37 ++- chaco/grid_data_source.py | 6 +- chaco/grid_mapper.py | 23 +- chaco/image_data.py | 4 +- chaco/image_plot.py | 6 +- chaco/jitterplot.py | 19 +- chaco/label.py | 17 +- chaco/label_axis.py | 17 +- chaco/layers/status_layer.py | 14 +- chaco/layers/svg_range_selection_overlay.py | 12 +- chaco/legend.py | 19 +- chaco/lineplot.py | 22 +- chaco/log_mapper.py | 13 +- chaco/multi_array_data_source.py | 9 +- chaco/multi_line_plot.py | 27 +- chaco/overlays/databox.py | 20 +- chaco/overlays/simple_inspector_overlay.py | 5 +- chaco/overlays/tests/test_databox.py | 15 +- chaco/pdf_graphics_context.py | 6 +- chaco/plot.py | 142 +++++++--- chaco/plot_component.py | 3 +- chaco/plot_containers.py | 63 ++++- chaco/plot_factory.py | 4 +- chaco/plot_graphics_context.py | 13 +- chaco/plotscrollbar.py | 16 +- chaco/plugin/plot_editor.py | 4 +- chaco/polar_line_renderer.py | 4 +- chaco/polygon_plot.py | 4 +- chaco/quiverplot.py | 16 +- chaco/scales/formatters.py | 61 ++++- chaco/scales/scales.py | 37 ++- chaco/scales/tests/test_scales.py | 35 ++- chaco/scales/tests/test_time_scale.py | 19 +- .../tests/test_time_scale_resolution.py | 30 ++- chaco/scales/time_scale.py | 42 ++- chaco/scatter_inspector_overlay.py | 10 +- chaco/scatterplot.py | 23 +- chaco/segment_plot.py | 26 +- chaco/shell/commands.py | 18 +- chaco/shell/plot_maker.py | 21 +- chaco/shell/plot_window.py | 4 +- chaco/shell/preferences.py | 4 +- chaco/shell/scaly_plot.py | 8 +- chaco/shell/session.py | 4 +- chaco/svg_graphics_context.py | 9 +- chaco/tests/segment_plot_test_case.py | 39 ++- chaco/tests/test_arraydatasource.py | 24 +- chaco/tests/test_base_utils.py | 11 +- chaco/tests/test_border.py | 4 +- chaco/tests/test_colormapper.py | 6 +- chaco/tests/test_contour.py | 12 +- chaco/tests/test_datarange_1d.py | 4 +- chaco/tests/test_datarange_2d.py | 4 +- chaco/tests/test_discrete_colormapper.py | 8 +- chaco/tests/test_function_data_source.py | 64 +++-- chaco/tests/test_grid_data_source.py | 12 +- chaco/tests/test_grid_mapper.py | 8 +- chaco/tests/test_hittest.py | 8 +- chaco/tests/test_image_data.py | 12 +- chaco/tests/test_image_plot.py | 13 +- chaco/tests/test_jitterplot.py | 31 ++- chaco/tests/test_line_scatterplot.py | 30 ++- chaco/tests/test_linearmapper.py | 32 ++- chaco/tests/test_multi_array_data_source.py | 16 +- chaco/tests/test_plot.py | 4 +- chaco/tests/test_plotcontainer.py | 12 +- chaco/tests/test_scatterplot_1d.py | 35 ++- chaco/tests/test_serializable.py | 4 +- chaco/tests/test_speedups.py | 13 +- chaco/tests/test_text_plot_1d.py | 11 +- chaco/tests/text_plot_test_case.py | 15 +- chaco/tests_with_backend/test_2d_case.py | 20 +- chaco/text_plot.py | 7 +- chaco/text_plot_1d.py | 3 +- chaco/ticks.py | 38 ++- chaco/tools/api.py | 7 +- chaco/tools/base_zoom_tool.py | 4 +- chaco/tools/better_selecting_zoom.py | 20 +- chaco/tools/better_zoom.py | 12 +- chaco/tools/cursor_tool.py | 5 +- chaco/tools/data_label_tool.py | 7 +- chaco/tools/drag_tool.py | 3 +- chaco/tools/highlight_tool.py | 4 +- chaco/tools/image_inspector_tool.py | 4 +- chaco/tools/lasso_selection.py | 27 +- chaco/tools/legend_highlighter.py | 8 +- chaco/tools/legend_tool.py | 7 +- chaco/tools/line_inspector.py | 16 +- chaco/tools/line_segment_tool.py | 9 +- chaco/tools/pan_tool.py | 4 +- chaco/tools/pan_tool2.py | 15 +- chaco/tools/range_selection.py | 12 +- chaco/tools/range_selection_2d.py | 18 +- chaco/tools/range_selection_overlay.py | 11 +- chaco/tools/rectangular_selection.py | 4 +- chaco/tools/regression_lasso.py | 9 +- chaco/tools/scatter_inspector.py | 12 +- chaco/tools/select_tool.py | 4 +- chaco/tools/simple_zoom.py | 58 ++++- chaco/tools/tests/test_range_selection.py | 4 +- chaco/tools/tests/test_range_zoom.py | 8 +- chaco/tools/tests/test_scatter_inspector.py | 8 +- chaco/tools/tool_history_mixin.py | 12 +- chaco/tools/toolbars/plot_toolbar.py | 72 ++++-- chaco/tools/toolbars/toolbar_buttons.py | 14 +- chaco/tools/tracking_pan_tool.py | 16 +- chaco/tools/tracking_zoom.py | 27 +- chaco/tools/traits_tool.py | 4 +- chaco/tooltip.py | 4 +- chaco/transform_color_mapper.py | 17 +- .../demo/advanced/asynchronous_updates.py | 30 ++- examples/demo/advanced/data_cube.py | 33 ++- examples/demo/advanced/data_stream.py | 15 +- .../demo/advanced/javascript_hover_tools.py | 8 +- .../scalar_image_function_inspector.py | 73 ++++-- .../scalar_image_function_inspector_old.py | 80 ++++-- examples/demo/advanced/spec_waterfall.py | 17 +- examples/demo/advanced/spectrum.py | 12 +- examples/demo/aspect_ratio.py | 10 +- examples/demo/basic/bar_plot_stacked.py | 4 +- examples/demo/basic/cmap_image_select.py | 12 +- examples/demo/basic/cmap_scatter.py | 12 +- examples/demo/basic/cmap_segment_plot.py | 7 +- examples/demo/basic/contour_cmap_plot.py | 4 +- examples/demo/basic/contour_plot.py | 4 +- examples/demo/basic/discrete_cmap_scatter.py | 12 +- examples/demo/basic/draw_layers.py | 12 +- examples/demo/basic/grid_container.py | 7 +- examples/demo/basic/hittest_tool.py | 4 +- examples/demo/basic/horizon_plot.py | 26 +- examples/demo/basic/image_from_file.py | 13 +- examples/demo/basic/image_inspector.py | 5 +- examples/demo/basic/image_lasso.py | 4 +- examples/demo/basic/image_plot.py | 9 +- examples/demo/basic/line_plot1.py | 6 +- examples/demo/basic/line_plot_hold.py | 4 +- examples/demo/basic/minard_napoleon.py | 8 +- examples/demo/basic/nans_plot.py | 6 +- examples/demo/basic/pandas_data.py | 6 +- examples/demo/basic/regression.py | 11 +- examples/demo/basic/scatter_1d.py | 12 +- examples/demo/basic/scatter_inspector2.py | 7 +- examples/demo/basic/scatter_rect_select.py | 11 +- examples/demo/basic/scatter_select.py | 8 +- examples/demo/basic/scatter_toggle.py | 15 +- examples/demo/basic/scrollbar.py | 4 +- examples/demo/basic/tabbed_plots.py | 8 +- examples/demo/basic/zoomable_colorbar.py | 14 +- examples/demo/bigdata.py | 4 +- examples/demo/canvas/axis_tool.py | 28 +- examples/demo/canvas/canvas.py | 29 ++- examples/demo/canvas/cliptest.py | 11 +- examples/demo/canvas/data_source_button.py | 4 +- examples/demo/canvas/mp_viewport_pan_tool.py | 4 +- examples/demo/canvas/mptools.py | 21 +- examples/demo/canvas/plot_clone_tool.py | 10 +- examples/demo/chaco_trait_editor.py | 13 +- examples/demo/cursor_tool_demo.py | 4 +- examples/demo/data_labels.py | 17 +- examples/demo/data_view.py | 8 +- examples/demo/depth.py | 5 +- examples/demo/domain_limits.py | 8 +- examples/demo/edit_line.py | 18 +- examples/demo/financial/correlations.py | 23 +- examples/demo/financial/stock_prices.py | 19 +- examples/demo/financial_plot.py | 4 +- examples/demo/financial_plot_dates.py | 9 +- examples/demo/functionplotter.py | 4 +- .../demo/image_plot_origin_and_orientation.py | 5 +- examples/demo/logo.py | 8 +- examples/demo/multi_line_plot.py | 5 +- examples/demo/multi_line_plot_demo.py | 12 +- examples/demo/multiaxis.py | 8 +- examples/demo/multiaxis_using_Plot.py | 4 +- examples/demo/noninteractive.py | 4 +- examples/demo/nonlinear_color_mapping.py | 41 ++- examples/demo/quiver.py | 8 +- examples/demo/scales_test.py | 12 +- examples/demo/simple_line.py | 19 +- examples/demo/simple_polar.py | 4 +- examples/demo/stacked_axis.py | 4 +- examples/demo/status_overlay.py | 6 +- examples/demo/toolbar_plot.py | 8 +- examples/demo/tornado.py | 11 +- examples/demo/two_plots.py | 20 +- examples/demo/updating_plot/updating_plot1.py | 4 +- examples/demo/updating_plot/updating_plot5.py | 4 +- examples/demo/vertical_plot.py | 7 +- examples/demo/vtk/cmap_scatter.py | 5 +- examples/demo/vtk/spectrum.py | 16 +- examples/demo/world_map.py | 12 +- examples/demo/xray_plot.py | 4 +- examples/demo/zoomed_plot/wav_to_numeric.py | 8 +- examples/demo/zoomed_plot/zoom_overlay.py | 4 +- examples/demo/zoomed_plot/zoom_plot.py | 4 +- .../tutorials/scipy2008/custom_overlay.py | 18 +- .../scipy2008/custom_overlay_dataspace.py | 18 +- .../scipy2008/custom_overlay_movetool.py | 29 ++- examples/tutorials/scipy2008/tool_chooser.py | 4 +- examples/tutorials/scipy2008/traits_image.py | 6 +- examples/tutorials/tutorial1.py | 4 +- examples/tutorials/tutorial10.py | 8 +- examples/tutorials/tutorial10b.py | 8 +- examples/tutorials/tutorial2.py | 3 +- examples/tutorials/tutorial9b.py | 8 +- examples/user_guide/grid_plot_container.py | 4 +- .../h_plot_container_add_multiple_times.py | 3 +- .../user_guide/h_plot_container_colorbar.py | 4 +- .../user_guide/overlay_container_inset.py | 4 +- .../plot_types/create_plot_snapshots.py | 20 +- 246 files changed, 2940 insertions(+), 815 deletions(-) diff --git a/chaco/_speedups_fallback.py b/chaco/_speedups_fallback.py index 6b0f08c8a..f65a5edb7 100644 --- a/chaco/_speedups_fallback.py +++ b/chaco/_speedups_fallback.py @@ -163,7 +163,9 @@ def apply_selection_fade(mapped_image, mask, fade_alpha, fade_background): mapped_image[imask, 0:3] = image_region -def map_colors(data_array, steps, low, high, red_lut, green_lut, blue_lut, alpha_lut): +def map_colors( + data_array, steps, low, high, red_lut, green_lut, blue_lut, alpha_lut +): """Map colors from color lookup tables to a data array. This is used in ColorMapper.map_screen diff --git a/chaco/abstract_plot_renderer.py b/chaco/abstract_plot_renderer.py index 449268c84..ce53cf649 100644 --- a/chaco/abstract_plot_renderer.py +++ b/chaco/abstract_plot_renderer.py @@ -43,7 +43,11 @@ def map_data(self, screen_pt): raise NotImplementedError def map_index( - self, screen_pt, threshold=0.0, outside_returns_none=True, index_only=False + self, + screen_pt, + threshold=0.0, + outside_returns_none=True, + index_only=False, ): """Maps a screen space point to an index into the plot's index array(s). diff --git a/chaco/api.py b/chaco/api.py index 7563647d0..725e122ee 100644 --- a/chaco/api.py +++ b/chaco/api.py @@ -54,7 +54,10 @@ from .data_view import DataView from .simple_plot_frame import SimplePlotFrame from .plot_component import PlotComponent -from .plot_graphics_context import PlotGraphicsContext, PlotGraphicsContextMixin +from .plot_graphics_context import ( + PlotGraphicsContext, + PlotGraphicsContextMixin, +) from .plot_containers import ( OverlayPlotContainer, HPlotContainer, diff --git a/chaco/array_data_source.py b/chaco/array_data_source.py index 960dac4c8..0b4a5992a 100644 --- a/chaco/array_data_source.py +++ b/chaco/array_data_source.py @@ -281,7 +281,10 @@ def _compute_bounds(self, data=None): # label-ish data sources. self._cached_bounds = (0.0, 0.0) - self._cached_bounds = (data[self._min_index], data[self._max_index]) + self._cached_bounds = ( + data[self._min_index], + data[self._max_index], + ) # ------------------------------------------------------------------------ # Event handlers diff --git a/chaco/array_plot_data.py b/chaco/array_plot_data.py index 1483849c9..14f452f03 100644 --- a/chaco/array_plot_data.py +++ b/chaco/array_plot_data.py @@ -172,7 +172,8 @@ def _generate_names(self, n): """Generate n new names""" max_index = max(self._generate_indices()) names = [ - "series{0:d}".format(n) for n in range(max_index + 1, max_index + n + 1) + "series{0:d}".format(n) + for n in range(max_index + 1, max_index + n + 1) ] return names diff --git a/chaco/axis.py b/chaco/axis.py index 46ba1f537..e321014e4 100644 --- a/chaco/axis.py +++ b/chaco/axis.py @@ -36,7 +36,11 @@ ) # Local relative imports -from .ticks import AbstractTickGenerator, DefaultTickGenerator, MinorTickGenerator +from .ticks import ( + AbstractTickGenerator, + DefaultTickGenerator, + MinorTickGenerator, +) from .abstract_mapper import AbstractMapper from .abstract_overlay import AbstractOverlay from .label import Label @@ -249,7 +253,9 @@ def _draw_overlay(self, gc, view_bounds=None, mode="normal"): """ self._draw_component(gc, view_bounds, mode) - def _draw_component(self, gc, view_bounds=None, mode="normal", component=None): + def _draw_component( + self, gc, view_bounds=None, mode="normal", component=None + ): """Draws the component. This method is preserved for backwards compatibility. Overrides @@ -273,7 +279,9 @@ def _draw_component(self, gc, view_bounds=None, mode="normal", component=None): gc.set_font(self.tick_label_font) if self.axis_line_visible: - self._draw_axis_line(gc, self._origin_point, self._end_axis_point) + self._draw_axis_line( + gc, self._origin_point, self._end_axis_point + ) if self.title: self._draw_title(gc) @@ -345,7 +353,12 @@ def _draw_title(self, gc, label=None, axis_offset=None): axis_offset = 25 else: axis_offset = ( - max([l._bounding_box[axis_index] for l in self.ticklabel_cache]) + max( + [ + l._bounding_box[axis_index] + for l in self.ticklabel_cache + ] + ) * 1.3 ) @@ -491,7 +504,11 @@ def _compute_tick_positions(self, gc, overlay_component=None): tick_list, labels = tmp # compute the labels here self.ticklabel_cache = [ - Label(text=lab, font=self.tick_label_font, color=self.tick_label_color) + Label( + text=lab, + font=self.tick_label_font, + color=self.tick_label_color, + ) for lab in labels ] self._tick_label_bounding_boxes = [ @@ -551,7 +568,9 @@ def build_label(val): margin=self.tick_label_margin, ) - self.ticklabel_cache = [build_label(val) for val in self._tick_label_list] + self.ticklabel_cache = [ + build_label(val) for val in self._tick_label_list + ] self._tick_label_bounding_boxes = [ array(ticklabel.get_bounding_box(gc), float) for ticklabel in self.ticklabel_cache @@ -571,7 +590,9 @@ def _calculate_geometry(self): self._origin_point = array(self.position) self._inside_vector = array([0.0, -1.0]) else: # self.oriention == 'bottom' - self._origin_point = array(self.position) + array([0.0, self.bounds[1]]) + self._origin_point = array(self.position) + array( + [0.0, self.bounds[1]] + ) self._inside_vector = array([0.0, 1.0]) if "right" in origin: screenlow, screenhigh = screenhigh, screenlow @@ -582,7 +603,9 @@ def _calculate_geometry(self): self._major_axis = array([0.0, 1.0]) self._title_orientation = array([-1.0, 0]) if self.orientation == "left": - self._origin_point = array(self.position) + array([self.bounds[0], 0.0]) + self._origin_point = array(self.position) + array( + [self.bounds[0], 0.0] + ) self._inside_vector = array([1.0, 0.0]) else: # self.orientation == 'right' self._origin_point = array(self.position) @@ -616,10 +639,14 @@ def _calculate_geometry_overlay(self, overlay_component=None): self._major_axis = array([1.0, 0.0]) self._title_orientation = array([0.0, 1.0]) if self.orientation == "top": - self._origin_point = array([overlay_component.x, overlay_component.y2]) + self._origin_point = array( + [overlay_component.x, overlay_component.y2] + ) self._inside_vector = array([0.0, -1.0]) else: - self._origin_point = array([overlay_component.x, overlay_component.y]) + self._origin_point = array( + [overlay_component.x, overlay_component.y] + ) self._inside_vector = array([0.0, 1.0]) if "right" in component_origin: screenlow, screenhigh = screenhigh, screenlow @@ -630,10 +657,14 @@ def _calculate_geometry_overlay(self, overlay_component=None): self._major_axis = array([0.0, 1.0]) self._title_orientation = array([-1.0, 0]) if self.orientation == "left": - self._origin_point = array([overlay_component.x, overlay_component.y]) + self._origin_point = array( + [overlay_component.x, overlay_component.y] + ) self._inside_vector = array([1.0, 0.0]) else: - self._origin_point = array([overlay_component.x2, overlay_component.y]) + self._origin_point = array( + [overlay_component.x2, overlay_component.y] + ) self._inside_vector = array([-1.0, 0.0]) if "top" in component_origin: screenlow, screenhigh = screenhigh, screenlow diff --git a/chaco/barplot.py b/chaco/barplot.py index df3f7d1f7..6e36884db 100644 --- a/chaco/barplot.py +++ b/chaco/barplot.py @@ -2,7 +2,15 @@ """ import logging -from numpy import array, compress, column_stack, invert, isnan, transpose, zeros +from numpy import ( + array, + compress, + column_stack, + invert, + isnan, + transpose, + zeros, +) from traits.api import ( Any, Bool, @@ -184,7 +192,11 @@ def map_data(self, screen_pt): return self.index_mapper.map_data(screen_coord) def map_index( - self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=False + self, + screen_pt, + threshold=2.0, + outside_returns_none=True, + index_only=False, ): """Maps a screen space point to an index into the plot's index array(s). @@ -267,7 +279,12 @@ def _gather_points(self): if self.bar_width_type == "data": half_width = self.bar_width / 2.0 points = column_stack( - (index - half_width, index + half_width, starting_values, value) + ( + index - half_width, + index + half_width, + starting_values, + value, + ) ) else: points = column_stack((index, starting_values, value)) diff --git a/chaco/base.py b/chaco/base.py index 5c3350aa2..6bb3fc233 100644 --- a/chaco/base.py +++ b/chaco/base.py @@ -30,7 +30,9 @@ delta = {"ascending": 1, "descending": -1, "flat": 0} -rgba_dtype = dtype([("r", float32), ("g", float32), ("b", float32), ("a", float32)]) +rgba_dtype = dtype( + [("r", float32), ("g", float32), ("b", float32), ("a", float32)] +) point_dtype = dtype([("x", float), ("y", float)]) # Dimensions diff --git a/chaco/base_1d_mapper.py b/chaco/base_1d_mapper.py index 7b017a66f..af62f3efa 100644 --- a/chaco/base_1d_mapper.py +++ b/chaco/base_1d_mapper.py @@ -102,7 +102,9 @@ def _set_screen_bounds(self, new_bounds): self.updated = True def _adjust_range(self, old_bounds, new_bounds): - initialized = self._low_bound_initialized and self._high_bound_initialized + initialized = ( + self._low_bound_initialized and self._high_bound_initialized + ) if self.range is not None and initialized: rangelow = self.range.low rangehigh = self.range.high diff --git a/chaco/base_1d_plot.py b/chaco/base_1d_plot.py index cb05e113d..8b41cf710 100644 --- a/chaco/base_1d_plot.py +++ b/chaco/base_1d_plot.py @@ -5,7 +5,15 @@ from numpy import argsort, asarray # Enthought library imports -from traits.api import Any, Bool, Enum, Instance, Property, cached_property, observe +from traits.api import ( + Any, + Bool, + Enum, + Instance, + Property, + cached_property, + observe, +) # local imports from .abstract_plot_renderer import AbstractPlotRenderer @@ -130,7 +138,11 @@ def map_data(self, screen_pts): return asarray(self.index_mapper.map_data(x)) def map_index( - self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=True + self, + screen_pt, + threshold=2.0, + outside_returns_none=True, + index_only=True, ): """Maps a screen space point to an index into the plot's index array. @@ -173,7 +185,9 @@ def map_index( if self._cached_data_pts_sorted is None: self._cached_data_argsort = argsort(self._cached_data) - self._cached_data_pts_sorted = self._cached_data[self._cached_data_argsort] + self._cached_data_pts_sorted = self._cached_data[ + self._cached_data_argsort + ] # XXX better to just use argmin(abs(data - data_pt))? diff --git a/chaco/base_2d_plot.py b/chaco/base_2d_plot.py index 2cd9159f0..81c01939d 100644 --- a/chaco/base_2d_plot.py +++ b/chaco/base_2d_plot.py @@ -122,7 +122,11 @@ def map_data(self, screen_pts): return self.index_mapper.map_data(screen_pts) def map_index( - self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=False + self, + screen_pt, + threshold=2.0, + outside_returns_none=True, + index_only=False, ): """Maps a screen space point to an index into the plot's index arrays. @@ -188,7 +192,9 @@ def map_index( return None, None sx, sy = self.map_screen([(x, y)])[0] - if (screen_pt[0] - sx) ** 2 + (screen_pt[1] - sy) ** 2 < threshold ** 2: + if (screen_pt[0] - sx) ** 2 + ( + screen_pt[1] - sy + ) ** 2 < threshold ** 2: return x_ndx, y_ndx else: return None, None @@ -272,9 +278,19 @@ def _update_index_mapper(self, event=None): if self.index_mapper is not None: if self.orientation == "h": - self.index_mapper.screen_bounds = (x_low, x_high, y_low, y_high) + self.index_mapper.screen_bounds = ( + x_low, + x_high, + y_low, + y_high, + ) else: - self.index_mapper.screen_bounds = (y_low, y_high, x_low, x_high) + self.index_mapper.screen_bounds = ( + y_low, + y_high, + x_low, + x_high, + ) self.index_mapper_changed = True self.invalidate_draw() diff --git a/chaco/base_candle_plot.py b/chaco/base_candle_plot.py index f3816c646..803be02d5 100644 --- a/chaco/base_candle_plot.py +++ b/chaco/base_candle_plot.py @@ -13,7 +13,8 @@ def Alias(name): return Property( - lambda obj: getattr(obj, name), lambda obj, val: setattr(obj, name, val) + lambda obj: getattr(obj, name), + lambda obj, val: setattr(obj, name, val), ) @@ -116,19 +117,22 @@ def _render(self, gc, right, left, min, bar_min, center, bar_max, max): if min is None: gc.line_set( - stack((bar_vert_center, bar_max)), stack((bar_vert_center, max)) + stack((bar_vert_center, bar_max)), + stack((bar_vert_center, max)), ) if self.end_cap: gc.line_set(stack((left, max)), stack((right, max))) elif max is None: gc.line_set( - stack((bar_vert_center, min)), stack((bar_vert_center, bar_min)) + stack((bar_vert_center, min)), + stack((bar_vert_center, bar_min)), ) if self.end_cap: gc.line_set(stack((left, min)), stack((right, min))) else: gc.line_set( - stack((bar_vert_center, min)), stack((bar_vert_center, max)) + stack((bar_vert_center, min)), + stack((bar_vert_center, max)), ) if self.end_cap: gc.line_set(stack((left, max)), stack((right, max))) diff --git a/chaco/base_contour_plot.py b/chaco/base_contour_plot.py index a3a96609b..327933f53 100644 --- a/chaco/base_contour_plot.py +++ b/chaco/base_contour_plot.py @@ -2,7 +2,17 @@ # Enthought library imports from enable.api import ColorTrait -from traits.api import Bool, Instance, Int, List, Property, Range, Str, Trait, Tuple +from traits.api import ( + Bool, + Instance, + Int, + List, + Property, + Range, + Str, + Trait, + Tuple, +) # Local relative imports from .base_2d_plot import Base2DPlot @@ -176,11 +186,16 @@ def _get_color_mapper(self): def _set_color_mapper(self, color_mapper): # Remove the dynamic event handler from the old color mapper if self.colors is not None and isinstance(self.colors, ColorMapper): - self.colors.observe(self._update_color_mapper, "updated", remove=True) + self.colors.observe( + self._update_color_mapper, "updated", remove=True + ) # Check to see if we should copy over the range as well if color_mapper is not None: - if color_mapper.range is None and self.colors.range is not None: + if ( + color_mapper.range is None + and self.colors.range is not None + ): color_mapper.range = self.colors.range # Attach the dynamic event handler to the new color mapper diff --git a/chaco/base_plot_container.py b/chaco/base_plot_container.py index f26f605c1..da14afe1d 100644 --- a/chaco/base_plot_container.py +++ b/chaco/base_plot_container.py @@ -71,5 +71,6 @@ def _use_draw_order_changed(self, old, new): """ if new == False: raise RuntimeError( - "The old-style drawing mechanism is no longer " "supported in Chaco." + "The old-style drawing mechanism is no longer " + "supported in Chaco." ) diff --git a/chaco/base_plot_frame.py b/chaco/base_plot_frame.py index 9e0f2b721..33c5f746f 100644 --- a/chaco/base_plot_frame.py +++ b/chaco/base_plot_frame.py @@ -143,7 +143,8 @@ def __getattr__(self, name): return self._frame_slots[name] else: raise AttributeError( - "'%s' object has no attribute '%s'" % (self.__class__.__name__, name) + "'%s' object has no attribute '%s'" + % (self.__class__.__name__, name) ) def __setattr__(self, name, value): diff --git a/chaco/base_xy_plot.py b/chaco/base_xy_plot.py index 5f9bc63c0..d39351c09 100644 --- a/chaco/base_xy_plot.py +++ b/chaco/base_xy_plot.py @@ -181,12 +181,16 @@ def __init__(self, **kwtraits): AbstractPlotRenderer.__init__(self, **kwtraits) if self.index is not None: self.index.observe(self._either_data_updated, "data_changed") - self.index.observe(self._either_metadata_updated, "metadata_changed") + self.index.observe( + self._either_metadata_updated, "metadata_changed" + ) if self.index_mapper: self.index_mapper.observe(self._mapper_updated_handler, "updated") if self.value is not None: self.value.observe(self._either_data_updated, "data_changed") - self.value.observe(self._either_metadata_updated, "metadata_changed") + self.value.observe( + self._either_metadata_updated, "metadata_changed" + ) if self.value_mapper: self.value_mapper.observe(self._mapper_updated_handler, "updated") @@ -264,7 +268,11 @@ def get_closest_point(self, screen_pt, threshold=7.0): if ndx is not None: x = self.x_mapper.map_screen(self.index.get_data()[ndx]) y = self.y_mapper.map_screen(self.value.get_data()[ndx]) - return (x, y, sqrt((x - screen_pt[0]) ** 2 + (y - screen_pt[1]) ** 2)) + return ( + x, + y, + sqrt((x - screen_pt[0]) ** 2 + (y - screen_pt[1]) ** 2), + ) else: return None @@ -303,7 +311,11 @@ def get_closest_line(self, screen_pt, threshold=7.0): # even that we only have 1 point, just return that point. datalen = len(index_data) if datalen == 1: - dist = (x, y, sqrt((x - screen_pt[0]) ** 2 + (y - screen_pt[1]) ** 2)) + dist = ( + x, + y, + sqrt((x - screen_pt[0]) ** 2 + (y - screen_pt[1]) ** 2), + ) if (threshold == 0.0) or (dist <= threshold): return (x, y, x, y, dist) else: @@ -356,12 +368,18 @@ def map_data(self, screen_pt, all_values=False): if self.orientation == "v": x, y = y, x if all_values: - return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) + return array( + (self.index_mapper.map_data(x), self.value_mapper.map_data(y)) + ) else: return self.index_mapper.map_data(x) def map_index( - self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=False + self, + screen_pt, + threshold=2.0, + outside_returns_none=True, + index_only=False, ): """Maps a screen space point to an index into the plot's index array(s). @@ -543,14 +561,20 @@ def _get_vgrid(self): def _get_x_axis(self): for obj in self.underlays + self.overlays: - if isinstance(obj, PlotAxis) and obj.orientation in ("bottom", "top"): + if isinstance(obj, PlotAxis) and obj.orientation in ( + "bottom", + "top", + ): return obj else: return None def _get_y_axis(self): for obj in self.underlays + self.overlays: - if isinstance(obj, PlotAxis) and obj.orientation in ("left", "right"): + if isinstance(obj, PlotAxis) and obj.orientation in ( + "left", + "right", + ): return obj else: return None @@ -612,7 +636,9 @@ def _orientation_changed(self): def _index_changed(self, old, new): if old is not None: old.observe(self._either_data_updated, "data_changed", remove=True) - old.observe(self._either_metadata_updated, "metadata_changed", remove=True) + old.observe( + self._either_metadata_updated, "metadata_changed", remove=True + ) if new is not None: new.observe(self._either_data_updated, "data_changed") new.observe(self._either_metadata_updated, "metadata_changed") @@ -631,7 +657,9 @@ def _either_metadata_updated(self, event): def _value_changed(self, old, new): if old is not None: old.observe(self._either_data_updated, "data_changed", remove=True) - old.observe(self._either_metadata_updated, "metadata_changed", remove=True) + old.observe( + self._either_metadata_updated, "metadata_changed", remove=True + ) if new is not None: new.observe(self._either_data_updated, "data_changed") new.observe(self._either_metadata_updated, "metadata_changed") diff --git a/chaco/candle_plot.py b/chaco/candle_plot.py index 0f07e18db..695a2a125 100644 --- a/chaco/candle_plot.py +++ b/chaco/candle_plot.py @@ -71,10 +71,16 @@ def map_data(self, screen_pt, all_values=True): x, y = screen_pt if self.orientation == "v": x, y = y, x - return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) + return array( + (self.index_mapper.map_data(x), self.value_mapper.map_data(y)) + ) def map_index( - self, screen_pt, threshold=0.0, outside_returns_none=True, index_only=True + self, + screen_pt, + threshold=0.0, + outside_returns_none=True, + index_only=True, ): if not index_only: raise NotImplementedError( diff --git a/chaco/chaco_plot_container_editor.py b/chaco/chaco_plot_container_editor.py index 6d153d27a..d484289b5 100644 --- a/chaco/chaco_plot_container_editor.py +++ b/chaco/chaco_plot_container_editor.py @@ -12,6 +12,7 @@ class PlotContainerEditor(ComponentEditor): def __init__(self, *args, **kwds): super(PlotContainerEditor, self).__init__(*args, **kwds) warnings.warn( - "DEPRECATED: Use enable.component_editor" ".ComponentEditor instead.", + "DEPRECATED: Use enable.component_editor" + ".ComponentEditor instead.", DeprecationWarning, ) diff --git a/chaco/chaco_plot_editor.py b/chaco/chaco_plot_editor.py index e442994b6..64a8b0ada 100644 --- a/chaco/chaco_plot_editor.py +++ b/chaco/chaco_plot_editor.py @@ -233,7 +233,9 @@ def init(self, parent): if plotitem.title != "": container.overlays.append( - PlotLabel(plotitem.title, component=container, overlay_position="top") + PlotLabel( + plotitem.title, component=container, overlay_position="top" + ) ) self._container = container @@ -348,7 +350,9 @@ def update_editor(self, event=None): orientation=plotitem.orientation, ) else: - raise RuntimeError("Unknown plot type '%s' in ChacoPlotEditor." % plot_type) + raise RuntimeError( + "Unknown plot type '%s' in ChacoPlotEditor." % plot_type + ) self._set_basic_properties(plot, plotitem) @@ -439,12 +443,18 @@ def _update_axis_grids(self, plot=None, plotitem=None): # index and value axes. So we have to search through the underlays for # PlotAxis instances whose ranges match the index and value ranges. for axis in plot.underlays + plot.overlays: - if isinstance(axis, PlotAxis) and axis.mapper.range is plot.index_range: + if ( + isinstance(axis, PlotAxis) + and axis.mapper.range is plot.index_range + ): axis.title_font = plotitem.x_label_font axis.title_color = plotitem.x_label_color for axis in plot.underlays + plot.overlays: - if isinstance(axis, PlotAxis) and axis.mapper.range is plot.value_range: + if ( + isinstance(axis, PlotAxis) + and axis.mapper.range is plot.value_range + ): axis.title_font = plotitem.y_label_font axis.title_color = plotitem.y_label_color diff --git a/chaco/cmap_image_plot.py b/chaco/cmap_image_plot.py index e2d5bddfe..69e36742f 100644 --- a/chaco/cmap_image_plot.py +++ b/chaco/cmap_image_plot.py @@ -91,7 +91,9 @@ def _render(self, gc): """ if not self._mapped_image_cache_valid: if "selection_masks" in self.value.metadata: - self._compute_cached_image(self.value.metadata["selection_masks"]) + self._compute_cached_image( + self.value.metadata["selection_masks"] + ) else: self._compute_cached_image() ImagePlot._render(self, gc) @@ -132,7 +134,9 @@ def _compute_cached_image(self, selection_masks=None): else: self._mapped_image_cache_valid = True ImagePlot._compute_cached_image( - self, self.value.data, mapper=lambda data: self._cmap_values(data) + self, + self.value.data, + mapper=lambda data: self._cmap_values(data), ) def _update_value_mapper(self, event=None): diff --git a/chaco/color_bar.py b/chaco/color_bar.py index 615bed5ff..849c8d940 100644 --- a/chaco/color_bar.py +++ b/chaco/color_bar.py @@ -4,7 +4,15 @@ from numpy import array, arange, ascontiguousarray, ones, transpose, uint8 # Enthought library imports -from traits.api import Any, Bool, Enum, Instance, Property, cached_property, observe +from traits.api import ( + Any, + Bool, + Enum, + Instance, + Property, + cached_property, + observe, +) from traits.observation.api import parse from kiva.image import GraphicsContext @@ -110,10 +118,14 @@ def __init__(self, *args, **kw): axis_orientation = "left" self._grid = PlotGrid( - orientation=grid_orientation, mapper=self.index_mapper, component=self + orientation=grid_orientation, + mapper=self.index_mapper, + component=self, ) self._axis = PlotAxis( - orientation=axis_orientation, mapper=self.index_mapper, component=self + orientation=axis_orientation, + mapper=self.index_mapper, + component=self, ) self.overlays.append(self._grid) self.overlays.append(self._axis) @@ -153,7 +165,10 @@ def _draw_plot(self, gc, view_bounds=None, mode="normal"): colors = self.color_mapper.map_screen(data_points) img = self._make_color_image( - colors, self.bounds[perpendicular_dim], self.orientation, self.direction + colors, + self.bounds[perpendicular_dim], + self.orientation, + self.direction, ) gc.draw_image(img, (self.x, self.y, self.width, self.height)) @@ -170,7 +185,9 @@ def _make_color_image(self, color_values, width, orientation, direction): ) if orientation == "v": - bmparray = ascontiguousarray(transpose(bmparray, axes=(1, 0, 2))[::-1]) + bmparray = ascontiguousarray( + transpose(bmparray, axes=(1, 0, 2))[::-1] + ) bmparray = bmparray.astype(uint8) img = GraphicsContext(bmparray, "rgba32") return img diff --git a/chaco/color_mapper.py b/chaco/color_mapper.py index 08c2be7e8..e3a816b14 100644 --- a/chaco/color_mapper.py +++ b/chaco/color_mapper.py @@ -290,7 +290,9 @@ def map_index(self, ary): self._recalculate() indices = ( - (ary - self.range.low) / (self.range.high - self.range.low) * self.steps + (ary - self.range.low) + / (self.range.high - self.range.low) + * self.steps ) return clip(indices.astype(int), 0, self.steps - 1) @@ -342,11 +344,15 @@ def _get_color_bands(self): def _recalculate(self): """Recalculates the mapping arrays.""" - self._red_lut = self._make_mapping_array(self.steps, self._segmentdata["red"]) + self._red_lut = self._make_mapping_array( + self.steps, self._segmentdata["red"] + ) self._green_lut = self._make_mapping_array( self.steps, self._segmentdata["green"] ) - self._blue_lut = self._make_mapping_array(self.steps, self._segmentdata["blue"]) + self._blue_lut = self._make_mapping_array( + self.steps, self._segmentdata["blue"] + ) self._alpha_lut = self._make_mapping_array( self.steps, self._segmentdata["alpha"] ) @@ -397,7 +403,9 @@ def _make_mapping_array(self, n, data): "data mapping points must start with x=0. and end with x=1" ) if sometrue(sort(x) - x): - raise ValueError("data mapping points must have x in increasing order") + raise ValueError( + "data mapping points must have x in increasing order" + ) # begin generation of lookup table x = x * (n - 1) lut = zeros((n,), float32) diff --git a/chaco/colormap_generators.py b/chaco/colormap_generators.py index abb947af9..8d7ced44b 100644 --- a/chaco/colormap_generators.py +++ b/chaco/colormap_generators.py @@ -42,7 +42,9 @@ def adjust_hue(msh_sat, m_unsat): return h_sat else: spin = ( - s_sat * np.sqrt(m_unsat * m_unsat - m_sat * m_sat) / (m_sat * np.sin(s_sat)) + s_sat + * np.sqrt(m_unsat * m_unsat - m_sat * m_sat) + / (m_sat * np.sin(s_sat)) ) if h_sat > -np.pi / 3: return h_sat + spin @@ -141,7 +143,9 @@ def generate_cubehelix_palette( x **= gamma amplitude = saturation * x * (1 - x) / 2.0 red = x + amplitude * (-0.14861 * np.cos(theta) + 1.78277 * np.sin(theta)) - green = x + amplitude * (-0.29227 * np.cos(theta) - 0.90649 * np.sin(theta)) + green = x + amplitude * ( + -0.29227 * np.cos(theta) - 0.90649 * np.sin(theta) + ) blue = x + amplitude * (1.97294 * np.cos(theta)) srgb_palette = np.column_stack([red, green, blue]).clip(0.0, 1.0) return srgb_palette diff --git a/chaco/colormapped_scatterplot.py b/chaco/colormapped_scatterplot.py index f8cf2d540..0b29996d4 100644 --- a/chaco/colormapped_scatterplot.py +++ b/chaco/colormapped_scatterplot.py @@ -36,7 +36,9 @@ def __init__(self): vgroup = self.content vgroup.content[0].content.append( Item( - "fill_alpha", label="Fill alpha", editor=RangeEditor(low=0.0, high=1.0) + "fill_alpha", + label="Fill alpha", + editor=RangeEditor(low=0.0, high=1.0), ) ) @@ -119,7 +121,9 @@ def _draw_plot(self, gc, view_bounds=None, mode="normal"): # Take into account fill_alpha even if we are rendering with only two values old_color = self.color self.color = tuple(self.fill_alpha * array(self.color_)) - super(ColormappedScatterPlot, self)._draw_component(gc, view_bounds, mode) + super(ColormappedScatterPlot, self)._draw_component( + gc, view_bounds, mode + ) self.color = old_color else: colors = self._cached_data_pts[:, 2] @@ -151,7 +155,11 @@ def _gather_points(self): value_range_mask = self.value_mapper.range.mask_data(value) nan_mask = invert(isnan(index_mask)) & invert(isnan(value_mask)) point_mask = ( - index_mask & value_mask & nan_mask & index_range_mask & value_range_mask + index_mask + & value_mask + & nan_mask + & index_range_mask + & value_range_mask ) if self.color_data is not None: @@ -183,7 +191,9 @@ def _render(self, gc, points): return super(ColormappedScatterPlot, self)._render(gc, points) # If the GC doesn't have draw_*_at_points, then use bruteforce - if hasattr(gc, "draw_marker_at_points") or hasattr(gc, "draw_path_at_points"): + if hasattr(gc, "draw_marker_at_points") or hasattr( + gc, "draw_path_at_points" + ): batch_capable = True else: batch_capable = False @@ -239,7 +249,9 @@ def _compute_bands(self, points, smartmode=False): # Now we want to determine where the continuous bands are. We do # this by right-shifting the sorted_color_indices array, subtracting # it from the original, and looking for all the nonzero points. - shifted = right_shift(sorted_color_indices, sorted_color_indices[0]) + shifted = right_shift( + sorted_color_indices, sorted_color_indices[0] + ) start_indices = concatenate( [[0], nonzero(sorted_color_indices - shifted)[0]] ) @@ -263,7 +275,9 @@ def _calc_render_method(self, numpoints): else: return "bruteforce" - def _set_draw_info(self, gc, mode, color, outline_color=None, outline_weight=None): + def _set_draw_info( + self, gc, mode, color, outline_color=None, outline_weight=None + ): """Sets the stroke color, fill color, and line width on the graphics context. """ @@ -321,7 +335,9 @@ def _render_banded(self, gc, points): for color_index in index_bands.keys(): self._set_draw_info(gc, mode, color_bands[color_index]) gc.draw_marker_at_points( - xy_points[index_bands[color_index]], size, marker.kiva_marker + xy_points[index_bands[color_index]], + size, + marker.kiva_marker, ) elif hasattr(gc, "draw_path_at_points"): @@ -350,7 +366,9 @@ def _render_banded(self, gc, points): ) gc.draw_path_at_points(xy, path, mode) else: - raise RuntimeError("Batch drawing requested on non-batch-capable GC.") + raise RuntimeError( + "Batch drawing requested on non-batch-capable GC." + ) def _render_bruteforce(self, gc, points): """Draws the points, setting the stroke color for each one.""" @@ -368,12 +386,17 @@ def _render_bruteforce(self, gc, points): marker_cls = self.marker_ marker_size = self.marker_size - if isinstance(marker_size, ndarray) and self._cached_point_mask is not None: + if ( + isinstance(marker_size, ndarray) + and self._cached_point_mask is not None + ): marker_size = marker_size[self._cached_point_mask] mode = marker_cls.draw_mode if marker_cls != "custom": - if hasattr(gc, "draw_marker_at_points") and self.marker not in ( + if hasattr( + gc, "draw_marker_at_points" + ) and self.marker not in ( "custom", "circle", "diamond", diff --git a/chaco/colormapped_selection_overlay.py b/chaco/colormapped_selection_overlay.py index 173b5ac2f..8e12e69ad 100644 --- a/chaco/colormapped_selection_overlay.py +++ b/chaco/colormapped_selection_overlay.py @@ -77,7 +77,9 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): mask = (data_pts >= low) & (data_pts <= high) elif self.selection_type == "mask": - mask = functools.reduce(logical_and, datasource.metadata["selection_masks"]) + mask = functools.reduce( + logical_and, datasource.metadata["selection_masks"] + ) if sum(mask) < 2: return @@ -101,7 +103,9 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): def _component_changed(self, old, new): if old: - old.observe(self.datasource_change_handler, "color_data", remove=True) + old.observe( + self.datasource_change_handler, "color_data", remove=True + ) if new: new.observe(self.datasource_change_handler, "color_data") self._old_alpha = new.fill_alpha @@ -118,12 +122,17 @@ def datasource_change_handler(self, event): obj, name, old, new = (event.object, event.name, event.old, event.new) if old: - old.observe(self.selection_change_handler, "metadata_changed", remove=True) + old.observe( + self.selection_change_handler, "metadata_changed", remove=True + ) if new: new.observe(self.selection_change_handler, "metadata_changed") self.selection_change_handler( TraitChangeEvent( - object=new, name="metadata_changed", old=None, new=new.metadata + object=new, + name="metadata_changed", + old=None, + new=new.metadata, ) ) diff --git a/chaco/contour_line_plot.py b/chaco/contour_line_plot.py index 92dff38da..ddbd15087 100644 --- a/chaco/contour_line_plot.py +++ b/chaco/contour_line_plot.py @@ -103,7 +103,9 @@ def _render(self, gc): if self.orientation == "h": strace = self.index_mapper.map_screen(trace) else: - strace = array(self.index_mapper.map_screen(trace))[:, ::-1] + strace = array(self.index_mapper.map_screen(trace))[ + :, ::-1 + ] gc.begin_path() gc.lines(strace) gc.stroke_path() diff --git a/chaco/contour_poly_plot.py b/chaco/contour_poly_plot.py index b441bff60..820d7c1da 100644 --- a/chaco/contour_poly_plot.py +++ b/chaco/contour_poly_plot.py @@ -60,7 +60,9 @@ def _render(self, gc): if self.orientation == "h": spoly = self.index_mapper.map_screen(poly) else: - spoly = array(self.index_mapper.map_screen(poly))[:, ::-1] + spoly = array(self.index_mapper.map_screen(poly))[ + :, ::-1 + ] gc.lines(spoly) gc.close_path() gc.draw_path() diff --git a/chaco/cross_plot_frame.py b/chaco/cross_plot_frame.py index da3533a20..366cc99fe 100644 --- a/chaco/cross_plot_frame.py +++ b/chaco/cross_plot_frame.py @@ -13,7 +13,11 @@ # Local, relative imports from .base_plot_frame import BasePlotFrame -from .plot_containers import HPlotContainer, OverlayPlotContainer, VPlotContainer +from .plot_containers import ( + HPlotContainer, + OverlayPlotContainer, + VPlotContainer, +) class CrossPlotFrame(BasePlotFrame): diff --git a/chaco/data_frame_plot_data.py b/chaco/data_frame_plot_data.py index e31579760..89d4b3a64 100644 --- a/chaco/data_frame_plot_data.py +++ b/chaco/data_frame_plot_data.py @@ -154,7 +154,8 @@ def _generate_names(self, n): """Generate n new names""" max_index = max(self._generate_indices()) names = [ - "series{0:d}".format(i) for i in range(max_index + 1, max_index + n + 1) + "series{0:d}".format(i) + for i in range(max_index + 1, max_index + n + 1) ] return names diff --git a/chaco/data_range_1d.py b/chaco/data_range_1d.py index 42bdade7b..75ce46c44 100644 --- a/chaco/data_range_1d.py +++ b/chaco/data_range_1d.py @@ -228,7 +228,9 @@ def _do_set_low_setting(self, val, fire_event=True): # value. if val == "auto": if len(self.sources) > 0: - val = min([source.get_bounds()[0] for source in self.sources]) + val = min( + [source.get_bounds()[0] for source in self.sources] + ) else: val = -inf elif val == "track": @@ -280,7 +282,9 @@ def _do_set_high_setting(self, val, fire_event=True): # value. if val == "auto": if len(self.sources) > 0: - val = max([source.get_bounds()[1] for source in self.sources]) + val = max( + [source.get_bounds()[1] for source in self.sources] + ) else: val = inf elif val == "track": @@ -311,7 +315,9 @@ def _refresh_bounds(self): null_bounds = True else: bounds_list = [ - source.get_bounds() for source in self.sources if source.get_size() > 0 + source.get_bounds() + for source in self.sources + if source.get_size() > 0 ] if len(bounds_list) == 0: diff --git a/chaco/data_range_2d.py b/chaco/data_range_2d.py index 36e148174..be4f9e9ac 100644 --- a/chaco/data_range_2d.py +++ b/chaco/data_range_2d.py @@ -5,7 +5,16 @@ from numpy import compress, inf, transpose # Enthought library imports -from traits.api import Any, Bool, CFloat, Instance, Property, Trait, Tuple, observe +from traits.api import ( + Any, + Bool, + CFloat, + Instance, + Property, + Trait, + Tuple, + observe, +) # Local relative imports from .base_data_range import BaseDataRange diff --git a/chaco/data_view.py b/chaco/data_view.py index 03a07a907..ebd907693 100644 --- a/chaco/data_view.py +++ b/chaco/data_view.py @@ -45,7 +45,10 @@ def set_mapper(self, attr_name, new): def get_axis(self, attr_name): """Getter function used by AxisProperty.""" - if (attr_name, self.orientation) in [("index_axis", "h"), ("value_axis", "v")]: + if (attr_name, self.orientation) in [ + ("index_axis", "h"), + ("value_axis", "v"), + ]: return self.x_axis else: return self.y_axis @@ -53,7 +56,10 @@ def get_axis(self, attr_name): def set_axis(self, attr_name, new): """Setter function used by AxisProperty.""" - if (attr_name, self.orientation) in [("index_axis", "h"), ("value_axis", "v")]: + if (attr_name, self.orientation) in [ + ("index_axis", "h"), + ("value_axis", "v"), + ]: self.x_axis = new else: self.y_axis = new @@ -65,7 +71,10 @@ def set_axis(self, attr_name, new): def get_grid(self, attr_name): """Getter function used by GridProperty.""" - if (attr_name, self.orientation) in [("index_grid", "v"), ("value_grid", "h")]: + if (attr_name, self.orientation) in [ + ("index_grid", "v"), + ("value_grid", "h"), + ]: return self.y_grid else: return self.x_grid @@ -73,7 +82,10 @@ def get_grid(self, attr_name): def set_grid(self, attr_name, new): """Setter function used by GridProperty.""" - if (attr_name, self.orientation) in [("index_grid", "v"), ("value_grid", "h")]: + if (attr_name, self.orientation) in [ + ("index_grid", "v"), + ("value_grid", "h"), + ]: self.y_grid = new else: self.y_grid = new @@ -94,7 +106,9 @@ class DataView(OverlayPlotContainer): orientation = Enum("h", "v") #: The default location of the origin for new plots - default_origin = Enum("bottom left", "top left", "bottom right", "top right") + default_origin = Enum( + "bottom left", "top left", "bottom right", "top right" + ) #: The origin reported to axes, etc origin = Property(depends_on="default_origin") @@ -237,7 +251,9 @@ def map_data(self, screen_pt): # At some point it would be good to change the DataView to use # the GridMapper, and then use its map_data() method. x, y = screen_pt - return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) + return array( + (self.index_mapper.map_data(x), self.value_mapper.map_data(y)) + ) # ------------------------------------------------------------------------ # Private methods diff --git a/chaco/default_colormaps.py b/chaco/default_colormaps.py index 426675b9b..8dbb06246 100644 --- a/chaco/default_colormaps.py +++ b/chaco/default_colormaps.py @@ -26,7 +26,10 @@ # Local imports. from .color_mapper import ColorMapper from .discrete_color_mapper import DiscreteColorMapper -from .colormap_generators import generate_cubehelix_palette, generate_diverging_palette +from .colormap_generators import ( + generate_cubehelix_palette, + generate_diverging_palette, +) # The colormaps will be added to this at the end of the file. __all__ = [ @@ -180,14 +183,22 @@ def bone(range, **traits): """ Generator function for the 'bone' colormap. """ _data = { - "red": ((0.0, 0.0, 0.0), (0.746032, 0.652778, 0.652778), (1.0, 1.0, 1.0)), + "red": ( + (0.0, 0.0, 0.0), + (0.746032, 0.652778, 0.652778), + (1.0, 1.0, 1.0), + ), "green": ( (0.0, 0.0, 0.0), (0.365079, 0.319444, 0.319444), (0.746032, 0.777778, 0.777778), (1.0, 1.0, 1.0), ), - "blue": ((0.0, 0.0, 0.0), (0.365079, 0.444444, 0.444444), (1.0, 1.0, 1.0)), + "blue": ( + (0.0, 0.0, 0.0), + (0.365079, 0.444444, 0.444444), + (1.0, 1.0, 1.0), + ), } return ColorMapper.from_segment_map(_data, range=range, **traits) @@ -209,7 +220,11 @@ def copper(range, **traits): """ Generator function for the 'copper' colormap. """ _data = { - "red": ((0.0, 0.0, 0.0), (0.809524, 1.000000, 1.000000), (1.0, 1.0, 1.0)), + "red": ( + (0.0, 0.0, 0.0), + (0.809524, 1.000000, 1.000000), + (1.0, 1.0, 1.0), + ), "green": ((0.0, 0.0, 0.0), (1.0, 0.7812, 0.7812)), "blue": ((0.0, 0.0, 0.0), (1.0, 0.4975, 0.4975)), } @@ -480,14 +495,22 @@ def hot(range, **traits): """ Generator function for the 'hot' colormap. """ _data = { - "red": ((0.0, 0.0416, 0.0416), (0.365079, 1.000000, 1.000000), (1.0, 1.0, 1.0)), + "red": ( + (0.0, 0.0416, 0.0416), + (0.365079, 1.000000, 1.000000), + (1.0, 1.0, 1.0), + ), "green": ( (0.0, 0.0, 0.0), (0.365079, 0.000000, 0.000000), (0.746032, 1.000000, 1.000000), (1.0, 1.0, 1.0), ), - "blue": ((0.0, 0.0, 0.0), (0.746032, 0.000000, 0.000000), (1.0, 1.0, 1.0)), + "blue": ( + (0.0, 0.0, 0.0), + (0.746032, 0.000000, 0.000000), + (1.0, 1.0, 1.0), + ), } return ColorMapper.from_segment_map(_data, range=range, **traits) @@ -536,7 +559,13 @@ def jet(range, **traits): """ Generator function for the 'jet' colormap. """ _data = { - "red": ((0.0, 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89, 1, 1), (1, 0.5, 0.5)), + "red": ( + (0.0, 0, 0), + (0.35, 0, 0), + (0.66, 1, 1), + (0.89, 1, 1), + (1, 0.5, 0.5), + ), "green": ( (0.0, 0, 0), (0.125, 0, 0), @@ -545,7 +574,13 @@ def jet(range, **traits): (0.91, 0, 0), (1, 0, 0), ), - "blue": ((0.0, 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1), (0.65, 0, 0), (1, 0, 0)), + "blue": ( + (0.0, 0.5, 0.5), + (0.11, 1, 1), + (0.34, 1, 1), + (0.65, 0, 0), + (1, 0, 0), + ), } return ColorMapper.from_segment_map(_data, range=range, **traits) @@ -965,7 +1000,11 @@ def cw1_004(range, **traits): def cw1_005(range, **traits): """ Generator function for the Crumblingwalls cw1-005 gradient """ colors = array( - [(0.7059, 0.1686, 0.0980), (0.7961, 0.5176, 0.2039), (0.2863, 0.3255, 0.1294)] + [ + (0.7059, 0.1686, 0.0980), + (0.7961, 0.5176, 0.2039), + (0.2863, 0.3255, 0.1294), + ] ) return ColorMapper.from_palette_array(colors, range=range, **traits) @@ -975,7 +1014,11 @@ def cw1_006(range, **traits): """ Generator function for the Crumblingwalls cw1-006 gradient """ colors = array( - [(0.4275, 0.2824, 0.4667), (0.2039, 0.1843, 0.4667), (0.0863, 0.4078, 0.2078)] + [ + (0.4275, 0.2824, 0.4667), + (0.2039, 0.1843, 0.4667), + (0.0863, 0.4078, 0.2078), + ] ) return ColorMapper.from_palette_array(colors, range=range, **traits) @@ -985,7 +1028,11 @@ def cw1_028(range, **traits): """ Generator function for the Crumblingwalls cw1-058 gradient """ colors = array( - [(0.2275, 0.2275, 0.4784), (0.3294, 0.5137, 0.8588), (0.4078, 0.8471, 0.8510)] + [ + (0.2275, 0.2275, 0.4784), + (0.3294, 0.5137, 0.8588), + (0.4078, 0.8471, 0.8510), + ] ) return ColorMapper.from_palette_array(colors, range=range, **traits) @@ -2344,9 +2391,21 @@ def gist_earth(range, **traits): (0.025210084393620491, 0.0, 0.0), (0.029411764815449715, 0.0, 0.0), (0.033613447099924088, 0.0, 0.0), - (0.037815127521753311, 0.0039215688593685627, 0.0039215688593685627), - (0.042016807943582535, 0.0078431377187371254, 0.0078431377187371254), - (0.046218488365411758, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.037815127521753311, + 0.0039215688593685627, + 0.0039215688593685627, + ), + ( + 0.042016807943582535, + 0.0078431377187371254, + 0.0078431377187371254, + ), + ( + 0.046218488365411758, + 0.0078431377187371254, + 0.0078431377187371254, + ), (0.050420168787240982, 0.011764706112444401, 0.011764706112444401), (0.054621849209070206, 0.015686275437474251, 0.015686275437474251), (0.058823529630899429, 0.019607843831181526, 0.019607843831181526), @@ -3066,8 +3125,16 @@ def gist_gray(range, **traits): _data = dict( red=[ (0.0, 0.0, 0.0), - (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), - (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.0042016808874905109, + 0.0039215688593685627, + 0.0039215688593685627, + ), + ( + 0.0084033617749810219, + 0.0078431377187371254, + 0.0078431377187371254, + ), (0.012605042196810246, 0.011764706112444401, 0.011764706112444401), (0.016806723549962044, 0.015686275437474251, 0.015686275437474251), (0.021008403971791267, 0.019607843831181526, 0.019607843831181526), @@ -3307,8 +3374,16 @@ def gist_gray(range, **traits): ], green=[ (0.0, 0.0, 0.0), - (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), - (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.0042016808874905109, + 0.0039215688593685627, + 0.0039215688593685627, + ), + ( + 0.0084033617749810219, + 0.0078431377187371254, + 0.0078431377187371254, + ), (0.012605042196810246, 0.011764706112444401, 0.011764706112444401), (0.016806723549962044, 0.015686275437474251, 0.015686275437474251), (0.021008403971791267, 0.019607843831181526, 0.019607843831181526), @@ -3548,8 +3623,16 @@ def gist_gray(range, **traits): ], blue=[ (0.0, 0.0, 0.0), - (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), - (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.0042016808874905109, + 0.0039215688593685627, + 0.0039215688593685627, + ), + ( + 0.0084033617749810219, + 0.0078431377187371254, + 0.0078431377187371254, + ), (0.012605042196810246, 0.011764706112444401, 0.011764706112444401), (0.016806723549962044, 0.015686275437474251, 0.015686275437474251), (0.021008403971791267, 0.019607843831181526, 0.019607843831181526), @@ -3796,8 +3879,16 @@ def gist_heat(range, **traits): _data = dict( red=[ (0.0, 0.0, 0.0), - (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), - (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.0042016808874905109, + 0.0039215688593685627, + 0.0039215688593685627, + ), + ( + 0.0084033617749810219, + 0.0078431377187371254, + 0.0078431377187371254, + ), (0.012605042196810246, 0.015686275437474251, 0.015686275437474251), (0.016806723549962044, 0.019607843831181526, 0.019607843831181526), (0.021008403971791267, 0.027450980618596077, 0.027450980618596077), @@ -4150,7 +4241,11 @@ def gist_heat(range, **traits): (0.46638655662536621, 0.0, 0.0), (0.47058823704719543, 0.0, 0.0), (0.47478991746902466, 0.0, 0.0), - (0.47899159789085388, 0.0039215688593685627, 0.0039215688593685627), + ( + 0.47899159789085388, + 0.0039215688593685627, + 0.0039215688593685627, + ), (0.48319327831268311, 0.011764706112444401, 0.011764706112444401), (0.48739495873451233, 0.019607843831181526, 0.019607843831181526), (0.49159663915634155, 0.027450980618596077, 0.027450980618596077), @@ -4588,7 +4683,11 @@ def gist_ncar(range, **traits): (0.30303031206130981, 0.0, 0.0), (0.30808082222938538, 0.0, 0.0), (0.31313130259513855, 0.0, 0.0), - (0.31818181276321411, 0.0039215688593685627, 0.0039215688593685627), + ( + 0.31818181276321411, + 0.0039215688593685627, + 0.0039215688593685627, + ), (0.32323232293128967, 0.043137256056070328, 0.043137256056070328), (0.32828283309936523, 0.08235294371843338, 0.08235294371843338), (0.3333333432674408, 0.11764705926179886, 0.11764705926179886), @@ -4727,7 +4826,11 @@ def gist_ncar(range, **traits): ], green=[ (0.0, 0.0, 0.0), - (0.0050505050458014011, 0.035294119268655777, 0.035294119268655777), + ( + 0.0050505050458014011, + 0.035294119268655777, + 0.035294119268655777, + ), (0.010101010091602802, 0.074509806931018829, 0.074509806931018829), (0.015151515603065491, 0.10980392247438431, 0.10980392247438431), (0.020202020183205605, 0.14901961386203766, 0.14901961386203766), @@ -5011,7 +5114,11 @@ def gist_ncar(range, **traits): (0.40909090638160706, 0.0, 0.0), (0.41414141654968262, 0.0, 0.0), (0.41919192671775818, 0.0, 0.0), - (0.42424243688583374, 0.0039215688593685627, 0.0039215688593685627), + ( + 0.42424243688583374, + 0.0039215688593685627, + 0.0039215688593685627, + ), (0.42929291725158691, 0.027450980618596077, 0.027450980618596077), (0.43434342741966248, 0.050980392843484879, 0.050980392843484879), (0.43939393758773804, 0.074509806931018829, 0.074509806931018829), @@ -5043,8 +5150,16 @@ def gist_ncar(range, **traits): (0.57070708274841309, 0.0, 0.0), (0.57575756311416626, 0.0, 0.0), (0.58080810308456421, 0.0, 0.0), - (0.58585858345031738, 0.0039215688593685627, 0.0039215688593685627), - (0.59090906381607056, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.58585858345031738, + 0.0039215688593685627, + 0.0039215688593685627, + ), + ( + 0.59090906381607056, + 0.0078431377187371254, + 0.0078431377187371254, + ), (0.59595960378646851, 0.011764706112444401, 0.011764706112444401), (0.60101008415222168, 0.019607843831181526, 0.019607843831181526), (0.60606062412261963, 0.023529412224888802, 0.023529412224888802), @@ -5062,7 +5177,11 @@ def gist_ncar(range, **traits): (0.66666668653488159, 0.019607843831181526, 0.019607843831181526), (0.67171716690063477, 0.015686275437474251, 0.015686275437474251), (0.67676764726638794, 0.011764706112444401, 0.011764706112444401), - (0.68181818723678589, 0.0039215688593685627, 0.0039215688593685627), + ( + 0.68181818723678589, + 0.0039215688593685627, + 0.0039215688593685627, + ), (0.68686866760253906, 0.0, 0.0), (0.69191920757293701, 0.0, 0.0), (0.69696968793869019, 0.0, 0.0), @@ -5321,7 +5440,11 @@ def gist_rainbow(range, **traits): (0.76890754699707031, 0.0, 0.0), (0.77310925722122192, 0.0, 0.0), (0.77731090784072876, 0.0, 0.0), - (0.78151261806488037, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.78151261806488037, + 0.0078431377187371254, + 0.0078431377187371254, + ), (0.78571426868438721, 0.027450980618596077, 0.027450980618596077), (0.78991597890853882, 0.070588238537311554, 0.070588238537311554), (0.79411762952804565, 0.094117648899555206, 0.094117648899555206), @@ -5561,7 +5684,11 @@ def gist_rainbow(range, **traits): (0.76470589637756348, 0.070588238537311554, 0.070588238537311554), (0.76890754699707031, 0.050980392843484879, 0.050980392843484879), (0.77310925722122192, 0.031372550874948502, 0.031372550874948502), - (0.77731090784072876, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.77731090784072876, + 0.0078431377187371254, + 0.0078431377187371254, + ), (0.78151261806488037, 0.0, 0.0), (0.78571426868438721, 0.0, 0.0), (0.78991597890853882, 0.0, 0.0), @@ -5714,7 +5841,11 @@ def gist_rainbow(range, **traits): (0.39495798945426941, 0.0, 0.0), (0.39915966987609863, 0.0, 0.0), (0.40336135029792786, 0.0, 0.0), - (0.40756303071975708, 0.0039215688593685627, 0.0039215688593685627), + ( + 0.40756303071975708, + 0.0039215688593685627, + 0.0039215688593685627, + ), (0.4117647111415863, 0.047058824449777603, 0.047058824449777603), (0.41596639156341553, 0.066666670143604279, 0.066666670143604279), (0.42016807198524475, 0.090196080505847931, 0.090196080505847931), @@ -5866,7 +5997,11 @@ def gist_stern(range, **traits): _data = dict( red=[ (0.0, 0.0, 0.0), - (0.0042016808874905109, 0.070588238537311554, 0.070588238537311554), + ( + 0.0042016808874905109, + 0.070588238537311554, + 0.070588238537311554, + ), (0.0084033617749810219, 0.14117647707462311, 0.14117647707462311), (0.012605042196810246, 0.21176470816135406, 0.21176470816135406), (0.016806723549962044, 0.28235295414924622, 0.28235295414924622), @@ -6107,8 +6242,16 @@ def gist_stern(range, **traits): ], green=[ (0.0, 0.0, 0.0), - (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), - (0.0084033617749810219, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.0042016808874905109, + 0.0039215688593685627, + 0.0039215688593685627, + ), + ( + 0.0084033617749810219, + 0.0078431377187371254, + 0.0078431377187371254, + ), (0.012605042196810246, 0.011764706112444401, 0.011764706112444401), (0.016806723549962044, 0.015686275437474251, 0.015686275437474251), (0.021008403971791267, 0.019607843831181526, 0.019607843831181526), @@ -6348,8 +6491,16 @@ def gist_stern(range, **traits): ], blue=[ (0.0, 0.0, 0.0), - (0.0042016808874905109, 0.0039215688593685627, 0.0039215688593685627), - (0.0084033617749810219, 0.011764706112444401, 0.011764706112444401), + ( + 0.0042016808874905109, + 0.0039215688593685627, + 0.0039215688593685627, + ), + ( + 0.0084033617749810219, + 0.011764706112444401, + 0.011764706112444401, + ), (0.012605042196810246, 0.019607843831181526, 0.019607843831181526), (0.016806723549962044, 0.027450980618596077, 0.027450980618596077), (0.021008403971791267, 0.035294119268655777, 0.035294119268655777), @@ -6832,7 +6983,11 @@ def gist_yarg(range, **traits): (0.98319327831268311, 0.019607843831181526, 0.019607843831181526), (0.98739492893218994, 0.015686275437474251, 0.015686275437474251), (0.99159663915634155, 0.011764706112444401, 0.011764706112444401), - (0.99579828977584839, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.99579828977584839, + 0.0078431377187371254, + 0.0078431377187371254, + ), (1.0, 0.0039215688593685627, 0.0039215688593685627), ], green=[ @@ -7073,7 +7228,11 @@ def gist_yarg(range, **traits): (0.98319327831268311, 0.019607843831181526, 0.019607843831181526), (0.98739492893218994, 0.015686275437474251, 0.015686275437474251), (0.99159663915634155, 0.011764706112444401, 0.011764706112444401), - (0.99579828977584839, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.99579828977584839, + 0.0078431377187371254, + 0.0078431377187371254, + ), (1.0, 0.0039215688593685627, 0.0039215688593685627), ], blue=[ @@ -7314,7 +7473,11 @@ def gist_yarg(range, **traits): (0.98319327831268311, 0.019607843831181526, 0.019607843831181526), (0.98739492893218994, 0.015686275437474251, 0.015686275437474251), (0.99159663915634155, 0.011764706112444401, 0.011764706112444401), - (0.99579828977584839, 0.0078431377187371254, 0.0078431377187371254), + ( + 0.99579828977584839, + 0.0078431377187371254, + 0.0078431377187371254, + ), (1.0, 0.0039215688593685627, 0.0039215688593685627), ], ) diff --git a/chaco/errorbar_plot.py b/chaco/errorbar_plot.py index 50b042597..94c80d18e 100644 --- a/chaco/errorbar_plot.py +++ b/chaco/errorbar_plot.py @@ -83,7 +83,11 @@ def _gather_points(self): nan_mask = invert(isnan(index_mask) | isnan(value_mask)) point_mask = ( - index_mask & value_mask & nan_mask & index_range_mask & value_range_mask + index_mask + & value_mask + & nan_mask + & index_range_mask + & value_range_mask ) points = column_stack((index, value_low, value_high)) diff --git a/chaco/filled_line_plot.py b/chaco/filled_line_plot.py index 05a599971..7a1fd9fb4 100644 --- a/chaco/filled_line_plot.py +++ b/chaco/filled_line_plot.py @@ -8,7 +8,8 @@ def Alias(name): return Property( - lambda obj: getattr(obj, name), lambda obj, val: setattr(obj, name, val) + lambda obj: getattr(obj, name), + lambda obj, val: setattr(obj, name, val), ) diff --git a/chaco/function_data_source.py b/chaco/function_data_source.py index db39641d1..713f17235 100644 --- a/chaco/function_data_source.py +++ b/chaco/function_data_source.py @@ -46,7 +46,9 @@ def recalculate(self, event=None): self._data = array([], dtype=float) def set_data(self, *args, **kw): - raise RuntimeError("Cannot set numerical data on a {0}".format(self.__class__)) + raise RuntimeError( + "Cannot set numerical data on a {0}".format(self.__class__) + ) def set_mask(self, mask): # This would be REALLY FREAKING SLICK, but it's current unimplemented diff --git a/chaco/grid.py b/chaco/grid.py index 7744ab9cc..d3af7f32c 100644 --- a/chaco/grid.py +++ b/chaco/grid.py @@ -3,7 +3,16 @@ """ -from numpy import around, array, asarray, column_stack, float64, inf, zeros, zeros_like +from numpy import ( + around, + array, + asarray, + column_stack, + float64, + inf, + zeros, + zeros_like, +) # Enthought library imports from enable.api import black_color_trait, LineStyle @@ -65,7 +74,8 @@ def float_or_auto(val): def Alias(name): return Property( - lambda obj: getattr(obj, name), lambda obj, val: setattr(obj, name, val) + lambda obj: getattr(obj, name), + lambda obj, val: setattr(obj, name, val), ) @@ -273,11 +283,15 @@ def _compute_ticks(self, component=None): if self.orientation == "horizontal": self._tick_positions = around( - column_stack((zeros_like(tick_positions) + position[0], tick_positions)) + column_stack( + (zeros_like(tick_positions) + position[0], tick_positions) + ) ) elif self.orientation == "vertical": self._tick_positions = around( - column_stack((tick_positions, zeros_like(tick_positions) + position[1])) + column_stack( + (tick_positions, zeros_like(tick_positions) + position[1]) + ) ) else: raise self.NotImplementedError @@ -295,7 +309,9 @@ def _compute_ticks(self, component=None): data_extents = self.transverse_bounds(ticks) tmapper = self.transverse_mapper if isinstance(data_extents, tuple): - self._tick_extents[:] = tmapper.map_screen(asarray(data_extents)) + self._tick_extents[:] = tmapper.map_screen( + asarray(data_extents) + ) else: extents = array( [ @@ -355,7 +371,9 @@ def _draw_component(self, gc, view_bounds=None, mode="normal"): gc.set_antialias(False) if self.component is not None: - gc.clip_to_rect(*(self.component.position + self.component.bounds)) + gc.clip_to_rect( + *(self.component.position + self.component.bounds) + ) else: gc.clip_to_rect(*(self.position + self.bounds)) @@ -428,7 +446,12 @@ def _orientation_changed(self): def __getstate__(self): state = super(PlotGrid, self).__getstate__() - for key in ["_cache_valid", "_tick_list", "_tick_positions", "_tick_extents"]: + for key in [ + "_cache_valid", + "_tick_list", + "_tick_positions", + "_tick_extents", + ]: if key in state: del state[key] diff --git a/chaco/grid_data_source.py b/chaco/grid_data_source.py index 5ac11a503..d4f71013a 100644 --- a/chaco/grid_data_source.py +++ b/chaco/grid_data_source.py @@ -54,7 +54,11 @@ class GridDataSource(AbstractDataSource): # ------------------------------------------------------------------------ def __init__( - self, xdata=array([]), ydata=array([]), sort_order=("none", "none"), **kwargs + self, + xdata=array([]), + ydata=array([]), + sort_order=("none", "none"), + **kwargs ): super(GridDataSource, self).__init__(**kwargs) self.set_data(xdata, ydata, sort_order) diff --git a/chaco/grid_mapper.py b/chaco/grid_mapper.py index fa57836f5..0f8a0259f 100644 --- a/chaco/grid_mapper.py +++ b/chaco/grid_mapper.py @@ -153,7 +153,9 @@ def _update_aspect_x(self): y_width = self._ymapper.high_pos - self._ymapper.low_pos if y_width == 0: return - y_scale = (self._ymapper.range.high - self._ymapper.range.low) / y_width + y_scale = ( + self._ymapper.range.high - self._ymapper.range.low + ) / y_width x_range_low = self._xmapper.range.low x_width = self._xmapper.high_pos - self._xmapper.low_pos sign = self._xmapper.sign * self._ymapper.sign @@ -161,13 +163,17 @@ def _update_aspect_x(self): return x_scale = sign * y_scale / self.aspect_ratio with self._update_aspect(): - self._xmapper.range.set_bounds(x_range_low, x_range_low + x_scale * x_width) + self._xmapper.range.set_bounds( + x_range_low, x_range_low + x_scale * x_width + ) def _update_aspect_y(self): x_width = self._xmapper.high_pos - self._xmapper.low_pos if x_width == 0: return - x_scale = (self._xmapper.range.high - self._xmapper.range.low) / x_width + x_scale = ( + self._xmapper.range.high - self._xmapper.range.low + ) / x_width y_range_low = self._ymapper.range.low y_width = self._ymapper.high_pos - self._ymapper.low_pos sign = self._xmapper.sign * self._ymapper.sign @@ -175,7 +181,9 @@ def _update_aspect_y(self): return y_scale = sign * x_scale * self.aspect_ratio with self._update_aspect(): - self._ymapper.range.set_bounds(y_range_low, y_range_low + y_scale * y_width) + self._ymapper.range.set_bounds( + y_range_low, y_range_low + y_scale * y_width + ) # ------------------------------------------------------------------------ # Property handlers @@ -215,7 +223,12 @@ def _set_screen_bounds(self, new_bounds): self._update_bounds() def _get_screen_bounds(self): - return (self.x_low_pos, self.x_high_pos, self.y_low_pos, self.y_high_pos) + return ( + self.x_low_pos, + self.x_high_pos, + self.y_low_pos, + self.y_high_pos, + ) def _updated_fired_for__xmapper(self): if not self._updating_aspect: diff --git a/chaco/image_data.py b/chaco/image_data.py index ff80c3f86..8f3025c75 100644 --- a/chaco/image_data.py +++ b/chaco/image_data.py @@ -97,7 +97,9 @@ def fromfile(cls, filename): elif fmt == "rgba32": imgdata.value_depth = 4 else: - raise ValueError("Unknown image format in file %s: %s" % (filename, fmt)) + raise ValueError( + "Unknown image format in file %s: %s" % (filename, fmt) + ) return imgdata def get_width(self): diff --git a/chaco/image_plot.py b/chaco/image_plot.py index c8d820797..34ec3c4d7 100644 --- a/chaco/image_plot.py +++ b/chaco/image_plot.py @@ -165,7 +165,11 @@ def _render(self, gc): gc.draw_image(self._cached_image, self._cached_dest_rect) def map_index( - self, screen_pt, threshold=0.0, outside_returns_none=True, index_only=False + self, + screen_pt, + threshold=0.0, + outside_returns_none=True, + index_only=False, ): """Maps a screen space point to an index into the plot's index array(s). diff --git a/chaco/jitterplot.py b/chaco/jitterplot.py index f260ecad5..313433fd1 100644 --- a/chaco/jitterplot.py +++ b/chaco/jitterplot.py @@ -43,7 +43,9 @@ def map_screen(self, data_array): new_x = [x for x in data_array if x not in sm] if new_x: new_y = self._make_jitter_vals(len(new_x)) - sm.update(dict((new_x[i], new_y[i]) for i in range(len(new_x)))) + sm.update( + dict((new_x[i], new_y[i]) for i in range(len(new_x))) + ) xs = self.index_mapper.map_screen(data_array) ys = [sm[x] for x in xs] @@ -64,7 +66,11 @@ def _make_jitter_vals(self, data_array): return vals def map_index( - self, screen_pt, threshold=2.0, outside_returns_none=True, index_only=True + self, + screen_pt, + threshold=2.0, + outside_returns_none=True, + index_only=True, ): """Maps a screen space point to an index into the plot's index array(s).""" screen_points = self._cached_screen_pts @@ -81,7 +87,9 @@ def map_index( if self._cached_data_pts_sorted is None: self._cached_data_argsort = np.argsort(self._cached_data) - self._cached_data_pts_sorted = self._cached_data[self._cached_data_argsort] + self._cached_data_pts_sorted = self._cached_data[ + self._cached_data_argsort + ] data = self._cached_data_pts_sorted try: @@ -101,7 +109,10 @@ def map_index( return orig_ndx sx, sy = screen_points[orig_ndx] - if sqrt((screen_pt[0] - sx) ** 2 + (screen_pt[1] - sy) ** 2) <= threshold: + if ( + sqrt((screen_pt[0] - sx) ** 2 + (screen_pt[1] - sy) ** 2) + <= threshold + ): return orig_ndx else: return None diff --git a/chaco/label.py b/chaco/label.py index 20d93979f..ce1a7fbed 100644 --- a/chaco/label.py +++ b/chaco/label.py @@ -257,19 +257,26 @@ def _calc_line_positions(self, gc): max_width = 0 for line in self.text.split("\n")[::-1]: if line != "": - (width, height, descent, leading) = gc.get_full_text_extent( - line - ) + ( + width, + height, + descent, + leading, + ) = gc.get_full_text_extent(line) ascent = height - abs(descent) if width > max_width: max_width = width - new_y_pos = prev_y_pos + prev_y_height + self.line_spacing + new_y_pos = ( + prev_y_pos + prev_y_height + self.line_spacing + ) else: # For blank lines, we use the height of the previous # line, if there is one. The width is 0. leading = 0 if prev_y_height != -self.line_spacing: - new_y_pos = prev_y_pos + prev_y_height + self.line_spacing + new_y_pos = ( + prev_y_pos + prev_y_height + self.line_spacing + ) ascent = prev_y_height else: new_y_pos = prev_y_pos diff --git a/chaco/label_axis.py b/chaco/label_axis.py index ea81b5757..8f472ac9b 100644 --- a/chaco/label_axis.py +++ b/chaco/label_axis.py @@ -67,8 +67,12 @@ def _compute_tick_positions(self, gc, component=None): pos_max = None for i, position in enumerate(self.positions): if datalow <= position <= datahigh: - pos_max = max(position, pos_max) if pos_max is not None else position - pos_min = min(position, pos_min) if pos_min is not None else position + pos_max = ( + max(position, pos_max) if pos_max is not None else position + ) + pos_min = ( + min(position, pos_min) if pos_min is not None else position + ) pos_index.append(i) pos.append(position) if len(pos_index) == 0: @@ -83,7 +87,9 @@ def _compute_tick_positions(self, gc, component=None): tick_indices = unique(searchsorted(pos, tick_list)) tick_indices = tick_indices[tick_indices < len(pos)] tick_positions = take(pos, tick_indices) - self._tick_label_list = take(self.labels, take(pos_index, tick_indices)) + self._tick_label_list = take( + self.labels, take(pos_index, tick_indices) + ) if datalow > datahigh: raise RuntimeError( @@ -91,7 +97,10 @@ def _compute_tick_positions(self, gc, component=None): ) mapped_label_positions = [ - ((self.mapper.map_screen(pos) - screenlow) / (screenhigh - screenlow)) + ( + (self.mapper.map_screen(pos) - screenlow) + / (screenhigh - screenlow) + ) for pos in tick_positions ] self._tick_positions = [ diff --git a/chaco/layers/status_layer.py b/chaco/layers/status_layer.py index 99efa6f86..377929f57 100644 --- a/chaco/layers/status_layer.py +++ b/chaco/layers/status_layer.py @@ -90,11 +90,13 @@ def overlay(self, other_component, gc, view_bounds=None, mode="normal"): # Set up the transforms to align the graphic to the desired position if self.align == "ur": gc.translate_ctm( - origin_x + (plot_width - scale_width), origin_y + plot_height + origin_x + (plot_width - scale_width), + origin_y + plot_height, ) elif self.align == "lr": gc.translate_ctm( - origin_x + (plot_width - scale_width), origin_y + scale_height + origin_x + (plot_width - scale_width), + origin_y + scale_height, ) elif self.align == "ul": gc.translate_ctm(origin_x, origin_y + plot_height) @@ -135,8 +137,12 @@ def _fade_out_step(self): class ErrorLayer(StatusLayer): - filename = os.path.join(os.path.dirname(__file__), "data", "Dialog-error.svg") + filename = os.path.join( + os.path.dirname(__file__), "data", "Dialog-error.svg" + ) class WarningLayer(StatusLayer): - filename = os.path.join(os.path.dirname(__file__), "data", "Dialog-warning.svg") + filename = os.path.join( + os.path.dirname(__file__), "data", "Dialog-warning.svg" + ) diff --git a/chaco/layers/svg_range_selection_overlay.py b/chaco/layers/svg_range_selection_overlay.py index 644e53443..6c9625a22 100644 --- a/chaco/layers/svg_range_selection_overlay.py +++ b/chaco/layers/svg_range_selection_overlay.py @@ -18,7 +18,9 @@ class SvgRangeSelectionOverlay(StatusLayer): the other which defines the fill. """ - filename = os.path.join(os.path.dirname(__file__), "data", "range_selection.svg") + filename = os.path.join( + os.path.dirname(__file__), "data", "range_selection.svg" + ) alpha = 0.5 @@ -62,9 +64,13 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): if self.axis == "index": if isinstance(self.mapper, GridMapper): - scale_width = (coords[-1][0] - coords[0][0]) / self.doc_width + scale_width = ( + coords[-1][0] - coords[0][0] + ) / self.doc_width else: - scale_width = (coords[0][-1] - coords[0][0]) / self.doc_width + scale_width = ( + coords[0][-1] - coords[0][0] + ) / self.doc_width scale_height = float(plot_height) / self.doc_height gc.translate_ctm(coords[0][0], origin_y + plot_height) else: diff --git a/chaco/legend.py b/chaco/legend.py index d36829837..3491b7557 100644 --- a/chaco/legend.py +++ b/chaco/legend.py @@ -260,7 +260,9 @@ def _draw_as_overlay(self, gc, view_bounds=None, mode="normal"): # feature. with gc: - gc.clip_to_rect(int(self.x), int(self.y), int(self.width), int(self.height)) + gc.clip_to_rect( + int(self.x), int(self.y), int(self.width), int(self.height) + ) edge_space = self.border_width + self.border_padding icon_width, icon_height = self.icon_bounds @@ -357,7 +359,9 @@ def get_preferred_size(self): if len(self.plots) == 0: return [0, 0] - plot_names, visible_plots = list(map(list, zip(*sorted(self.plots.items())))) + plot_names, visible_plots = list( + map(list, zip(*sorted(self.plots.items()))) + ) label_names = self.labels if len(label_names) == 0: if len(self.plots) > 0: @@ -409,12 +413,15 @@ def get_preferred_size(self): # We need a dummy GC in order to get font metrics dummy_gc = font_metrics_provider() - label_sizes = array([label.get_width_height(dummy_gc) for label in labels]) + label_sizes = array( + [label.get_width_height(dummy_gc) for label in labels] + ) if len(label_sizes) > 0: max_label_width = max(label_sizes[:, 0]) total_label_height = ( - sum(label_sizes[:, 1]) + (len(label_sizes) - 1) * self.line_spacing + sum(label_sizes[:, 1]) + + (len(label_sizes) - 1) * self.line_spacing ) else: max_label_width = 0 @@ -427,7 +434,9 @@ def get_preferred_size(self): + self.hpadding + 2 * self.border_padding ) - legend_height = total_label_height + self.vpadding + 2 * self.border_padding + legend_height = ( + total_label_height + self.vpadding + 2 * self.border_padding + ) self._cached_labels = labels self._cached_label_sizes = label_sizes diff --git a/chaco/lineplot.py b/chaco/lineplot.py index f92d312dc..3c0916a79 100644 --- a/chaco/lineplot.py +++ b/chaco/lineplot.py @@ -114,7 +114,8 @@ def hittest(self, screen_pt, threshold=7.0, return_distance=False): if return_distance: scrn_pt = self.map_screen(data_pt) dist = sqrt( - (screen_pt[0] - scrn_pt[0]) ** 2 + (screen_pt[1] - scrn_pt[1]) ** 2 + (screen_pt[0] - scrn_pt[0]) ** 2 + + (screen_pt[1] - scrn_pt[1]) ** 2 ) return (data_pt[0], data_pt[1], dist) else: @@ -158,7 +159,9 @@ def hittest(self, screen_pt, threshold=7.0, return_distance=False): ndx2 - 1, ), ) - end_ndx = min(len(self.value.get_data()) - 1, max(ndx1 + 1, ndx2 + 1)) + end_ndx = min( + len(self.value.get_data()) - 1, max(ndx1 + 1, ndx2 + 1) + ) # Compute the distances to all points in the range of interest start = array( @@ -212,7 +215,9 @@ def interpolate(self, index_value): """ if self.index is None or self.value is None: - raise IndexError("cannot index when data source index or value is None") + raise IndexError( + "cannot index when data source index or value is None" + ) index_data = self.index.get_data() value_data = self.value.get_data() @@ -328,7 +333,9 @@ def _downsample(self): downsampled = [] else: # TODO: implement other downsampling methods - from chaco.downsample.lttb import largest_triangle_three_buckets + from chaco.downsample.lttb import ( + largest_triangle_three_buckets, + ) downsampled = [ largest_triangle_three_buckets(p, delta_screen) @@ -353,7 +360,9 @@ def _render(self, gc, points, selected_points=None): "connectedhold": self._render_connected_hold, "connectedpoints": self._render_normal, } - render = render_method_dict.get(self.render_style, self._render_normal) + render = render_method_dict.get( + self.render_style, self._render_normal + ) if selected_points is not None: gc.set_stroke_color(self.selected_color_) @@ -471,7 +480,8 @@ def _closest_point(target, p1, p2): that range is a point outisde p1, p2 on the line Note: can divide by zero, so user should check for that""" t = ( - (p1[0] - target[0]) * (p1[0] - p2[0]) + (p1[1] - target[1]) * (p1[1] - p2[1]) + (p1[0] - target[0]) * (p1[0] - p2[0]) + + (p1[1] - target[1]) * (p1[1] - p2[1]) ) / ((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1])) return t diff --git a/chaco/log_mapper.py b/chaco/log_mapper.py index 6bd700d88..4316576dd 100644 --- a/chaco/log_mapper.py +++ b/chaco/log_mapper.py @@ -1,7 +1,18 @@ """ Defines the LogMapper and InvalidDataRangeException classes. """ # Major library imports -from numpy import array, isnan, log, log10, exp, zeros, sometrue, floor, ceil, ndarray +from numpy import ( + array, + isnan, + log, + log10, + exp, + zeros, + sometrue, + floor, + ceil, + ndarray, +) import numpy as np # Enthought library imports diff --git a/chaco/multi_array_data_source.py b/chaco/multi_array_data_source.py index 1ae31dbcf..d1f9d2a54 100644 --- a/chaco/multi_array_data_source.py +++ b/chaco/multi_array_data_source.py @@ -179,7 +179,9 @@ def get_bounds(self, value=None, index=None): # value is None and index is None: with warnings.catch_warnings(): warnings.filterwarnings( - "ignore", "All-NaN (slice|axis) encountered", RuntimeWarning + "ignore", + "All-NaN (slice|axis) encountered", + RuntimeWarning, ) maxi = nanmax(self._data) mini = nanmin(self._data) @@ -210,8 +212,9 @@ def _set_data(self, value): value = value[newaxis, :] if len(value.shape) != 2: - msg = "Input is %d dimensional, but it must be 1 or 2" "dimensional." % len( - value.shape + msg = ( + "Input is %d dimensional, but it must be 1 or 2" + "dimensional." % len(value.shape) ) raise ValueError(msg) diff --git a/chaco/multi_line_plot.py b/chaco/multi_line_plot.py index ab446c61f..4ae14aa3e 100644 --- a/chaco/multi_line_plot.py +++ b/chaco/multi_line_plot.py @@ -140,10 +140,18 @@ class MultiLinePlot(BaseXYPlot): amplitude_scale = Property( Float, - depends_on=["global_min", "global_max", "data", "use_global_bounds", "yindex"], + depends_on=[ + "global_min", + "global_max", + "data", + "use_global_bounds", + "yindex", + ], ) - amplitude = Property(Float, depends_on=["normalized_amplitude", "amplitude_scale"]) + amplitude = Property( + Float, depends_on=["normalized_amplitude", "amplitude_scale"] + ) # ------------------------------------------------------------------------ # Private traits @@ -214,7 +222,8 @@ def trait_view(self, obj): def get_screen_points(self): self._gather_points() scrn_pts_list = [ - [self.map_screen(ary) for ary in line] for line in self._cached_data_pts + [self.map_screen(ary) for ary in line] + for line in self._cached_data_pts ] return scrn_pts_list @@ -408,7 +417,10 @@ def _gather_points(self): z = transpose( array( - (sorted_index[ndx : ndx + 2], sorted_value[ndx : ndx + 2]) + ( + sorted_index[ndx : ndx + 2], + sorted_value[ndx : ndx + 2], + ) ) ) points.append(z) @@ -425,7 +437,12 @@ def _gather_points(self): end += 1 run_data = transpose( - array((block_index[start:end], block_value[start:end])) + array( + ( + block_index[start:end], + block_value[start:end], + ) + ) ) points.append(run_data) line_points.append(points) diff --git a/chaco/overlays/databox.py b/chaco/overlays/databox.py index 9d55922b6..a8daeb27d 100644 --- a/chaco/overlays/databox.py +++ b/chaco/overlays/databox.py @@ -58,13 +58,21 @@ class DataBox(AbstractOverlay): def __init__(self, *args, **kw): super(DataBox, self).__init__(*args, **kw) if hasattr(self.component, "range2d"): - self.component.range2d._xrange.observe(self.my_component_moved, "updated") - self.component.range2d._yrange.observe(self.my_component_moved, "updated") + self.component.range2d._xrange.observe( + self.my_component_moved, "updated" + ) + self.component.range2d._yrange.observe( + self.my_component_moved, "updated" + ) elif hasattr(self.component, "x_mapper") and hasattr( self.component, "y_mapper" ): - self.component.x_mapper.range.observe(self.my_component_moved, "updated") - self.component.y_mapper.range.observe(self.my_component_moved, "updated") + self.component.x_mapper.range.observe( + self.my_component_moved, "updated" + ) + self.component.y_mapper.range.observe( + self.my_component_moved, "updated" + ) else: raise RuntimeError( "DataBox cannot find a suitable mapper on its component." @@ -98,7 +106,9 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): gc.set_antialias(0) gc.set_line_width(self.border_size) gc.set_stroke_color(self.border_color_) - gc.clip_to_rect(component.x, component.y, component.width, component.height) + gc.clip_to_rect( + component.x, component.y, component.width, component.height + ) rect = self.position + self.bounds if self.color != "transparent": diff --git a/chaco/overlays/simple_inspector_overlay.py b/chaco/overlays/simple_inspector_overlay.py index cf86350ad..df044e0ae 100644 --- a/chaco/overlays/simple_inspector_overlay.py +++ b/chaco/overlays/simple_inspector_overlay.py @@ -178,7 +178,10 @@ def _new_value_updated(self, event): d = new_value_event text = [] self.text_grid.string_array = array( - [[formatter(**d) for formatter in row] for row in self.field_formatters] + [ + [formatter(**d) for formatter in row] + for row in self.field_formatters + ] ) self.text_grid.request_redraw() diff --git a/chaco/overlays/tests/test_databox.py b/chaco/overlays/tests/test_databox.py index 5eeb05c90..082fdc915 100644 --- a/chaco/overlays/tests/test_databox.py +++ b/chaco/overlays/tests/test_databox.py @@ -3,7 +3,13 @@ from traits.testing.api import UnittestTools -from chaco.api import CMapImagePlot, GridDataSource, GridMapper, DataRange2D, ImageData +from chaco.api import ( + CMapImagePlot, + GridDataSource, + GridMapper, + DataRange2D, + ImageData, +) from chaco.overlays.databox import DataBox @@ -50,5 +56,10 @@ def test_update_data_position(self): # Without moving the DataBox, data_position trait defaults # to the list [0.0, 0.0] starting_position = [0.0, 0.0] - expected = (self.databox, "data_position", starting_position, starting_position) + expected = ( + self.databox, + "data_position", + starting_position, + starting_position, + ) self.assertSequenceEqual([expected], result.events) diff --git a/chaco/pdf_graphics_context.py b/chaco/pdf_graphics_context.py index d3ac3df86..3da9217fa 100644 --- a/chaco/pdf_graphics_context.py +++ b/chaco/pdf_graphics_context.py @@ -92,7 +92,11 @@ def add_page(self): self._page_initialized = False def render_component( - self, component, container_coords=False, halign="center", valign="top" + self, + component, + container_coords=False, + halign="center", + valign="top", ): """Erases the current contents of the graphics context and renders the given component at the maximum possible scaling while diff --git a/chaco/plot.py b/chaco/plot.py index e4f96fcb3..e0f69367b 100644 --- a/chaco/plot.py +++ b/chaco/plot.py @@ -199,7 +199,10 @@ def __init__(self, data=None, **kwtraits): if not self._title: self._title = PlotLabel( - font="swiss 16", visible=False, overlay_position="top", component=self + font="swiss 16", + visible=False, + overlay_position="top", + component=self, ) if title is not None: self.title = title @@ -217,7 +220,13 @@ def __init__(self, data=None, **kwtraits): self._plot_ui_info = None def add_xy_plot( - self, index_name, value_name, renderer_factory, name=None, origin=None, **kwds + self, + index_name, + value_name, + renderer_factory, + name=None, + origin=None, + **kwds ): """Add a BaseXYPlot renderer subclass to this Plot. @@ -354,7 +363,14 @@ def plot( if origin is None: origin = self.default_origin - if plot_type in ("line", "scatter", "polygon", "bar", "filled_line", "segment"): + if plot_type in ( + "line", + "scatter", + "polygon", + "bar", + "filled_line", + "segment", + ): # Tie data to the index range if len(data) == 1: if self.default_index is None: @@ -383,10 +399,12 @@ def plot( cls = self.renderer_map[plot_type] # handle auto-coloring request if styles.get("color") == "auto": - self._auto_color_idx = (self._auto_color_idx + 1) % len( - self.auto_colors - ) - styles["color"] = self.auto_colors[self._auto_color_idx] + self._auto_color_idx = ( + self._auto_color_idx + 1 + ) % len(self.auto_colors) + styles["color"] = self.auto_colors[ + self._auto_color_idx + ] elif plot_type in ("polygon", "filled_line"): cls = self.renderer_map[plot_type] # handle auto-coloring request @@ -408,10 +426,12 @@ def plot( cls = self.renderer_map[plot_type] # handle auto-coloring request if styles.get("color") == "auto": - self._auto_color_idx = (self._auto_color_idx + 1) % len( - self.auto_colors - ) - styles["fill_color"] = self.auto_colors[self._auto_color_idx] + self._auto_color_idx = ( + self._auto_color_idx + 1 + ) % len(self.auto_colors) + styles["fill_color"] = self.auto_colors[ + self._auto_color_idx + ] else: raise ValueError("Unhandled plot type: " + plot_type) @@ -453,7 +473,9 @@ def plot( # For bar plots, compute the ranges from the data to make the # plot look clean. - def custom_index_func(data_low, data_high, margin, tight_bounds): + def custom_index_func( + data_low, data_high, margin, tight_bounds + ): """Compute custom bounds of the plot along index (in data space). """ @@ -465,7 +487,9 @@ def custom_index_func(data_low, data_high, margin, tight_bounds): if self.index_range.bounds_func is None: self.index_range.bounds_func = custom_index_func - def custom_value_func(data_low, data_high, margin, tight_bounds): + def custom_value_func( + data_low, data_high, margin, tight_bounds + ): """Compute custom bounds of the plot along value (in data space). """ @@ -485,7 +509,9 @@ def custom_value_func(data_low, data_high, margin, tight_bounds): elif plot_type in ("text"): if len(data) != 3: - raise ValueError("Text plots require (index, value, text) data") + raise ValueError( + "Text plots require (index, value, text) data" + ) index = self._get_or_create_datasource(data[0]) if self.default_index is None: self.default_index = index @@ -496,19 +522,23 @@ def custom_value_func(data_low, data_high, margin, tight_bounds): if self.index_scale == "linear": imap = LinearMapper( - range=self.index_range, stretch_data=self.index_mapper.stretch_data + range=self.index_range, + stretch_data=self.index_mapper.stretch_data, ) else: imap = LogMapper( - range=self.index_range, stretch_data=self.index_mapper.stretch_data + range=self.index_range, + stretch_data=self.index_mapper.stretch_data, ) if self.value_scale == "linear": vmap = LinearMapper( - range=self.value_range, stretch_data=self.value_mapper.stretch_data + range=self.value_range, + stretch_data=self.value_mapper.stretch_data, ) else: vmap = LogMapper( - range=self.value_range, stretch_data=self.value_mapper.stretch_data + range=self.value_range, + stretch_data=self.value_mapper.stretch_data, ) cls = self.renderer_map[plot_type] @@ -548,7 +578,10 @@ def custom_value_func(data_low, data_high, margin, tight_bounds): colormap = styles.pop("color_mapper") - if self.color_mapper is not None and self.color_mapper.range is not None: + if ( + self.color_mapper is not None + and self.color_mapper.range is not None + ): color_range = self.color_mapper.range else: color_range = DataRange1D() @@ -563,9 +596,14 @@ def custom_value_func(data_low, data_high, margin, tight_bounds): color_range.add(color) self.color_mapper = colormap(color_range) else: - raise ValueError("Unexpected colormap %r in plot()." % colormap) + raise ValueError( + "Unexpected colormap %r in plot()." % colormap + ) - if self.color_mapper is not None and self.color_mapper.range is not None: + if ( + self.color_mapper is not None + and self.color_mapper.range is not None + ): color_range = self.color_mapper.range else: color_range = DataRange1D() @@ -584,19 +622,23 @@ def custom_value_func(data_low, data_high, margin, tight_bounds): if self.index_scale == "linear": imap = LinearMapper( - range=self.index_range, stretch_data=self.index_mapper.stretch_data + range=self.index_range, + stretch_data=self.index_mapper.stretch_data, ) else: imap = LogMapper( - range=self.index_range, stretch_data=self.index_mapper.stretch_data + range=self.index_range, + stretch_data=self.index_mapper.stretch_data, ) if self.value_scale == "linear": vmap = LinearMapper( - range=self.value_range, stretch_data=self.value_mapper.stretch_data + range=self.value_range, + stretch_data=self.value_mapper.stretch_data, ) else: vmap = LogMapper( - range=self.value_range, stretch_data=self.value_mapper.stretch_data + range=self.value_range, + stretch_data=self.value_mapper.stretch_data, ) cls = self.renderer_map[plot_type] @@ -917,7 +959,9 @@ def _create_2d_plot( self.plots[name] = [plot] return self.plots[name] - def candle_plot(self, data, name=None, value_scale="linear", origin=None, **styles): + def candle_plot( + self, data, name=None, value_scale="linear", origin=None, **styles + ): """Adds a new sub-plot using the given data and plot style. Parameters @@ -994,7 +1038,9 @@ def candle_plot(self, data, name=None, value_scale="linear", origin=None, **styl min = None max = None elif len(data) == 4: - index, bar_min, center, bar_max = map(self._get_or_create_datasource, data) + index, bar_min, center, bar_max = map( + self._get_or_create_datasource, data + ) self.value_range.add(bar_min, center, bar_max) min = None max = None @@ -1012,24 +1058,30 @@ def candle_plot(self, data, name=None, value_scale="linear", origin=None, **styl self.index_range.add(index) if styles.get("bar_color") == "auto" or styles.get("color") == "auto": - self._auto_color_idx = (self._auto_color_idx + 1) % len(self.auto_colors) + self._auto_color_idx = (self._auto_color_idx + 1) % len( + self.auto_colors + ) styles["color"] = self.auto_colors[self._auto_color_idx] if self.index_scale == "linear": imap = LinearMapper( - range=self.index_range, stretch_data=self.index_mapper.stretch_data + range=self.index_range, + stretch_data=self.index_mapper.stretch_data, ) else: imap = LogMapper( - range=self.index_range, stretch_data=self.index_mapper.stretch_data + range=self.index_range, + stretch_data=self.index_mapper.stretch_data, ) if self.value_scale == "linear": vmap = LinearMapper( - range=self.value_range, stretch_data=self.value_mapper.stretch_data + range=self.value_range, + stretch_data=self.value_mapper.stretch_data, ) else: vmap = LogMapper( - range=self.value_range, stretch_data=self.value_mapper.stretch_data + range=self.value_range, + stretch_data=self.value_mapper.stretch_data, ) cls = self.renderer_map["candle"] @@ -1184,7 +1236,12 @@ def plot_1d( direction = "flipped" plots = [] - if plot_type in ("scatter_1d", "textplot_1d", "line_scatter_1d", "jitterplot"): + if plot_type in ( + "scatter_1d", + "textplot_1d", + "line_scatter_1d", + "jitterplot", + ): # Tie data to the index range index = self._get_or_create_datasource(data[0]) if self.default_index is None: @@ -1208,11 +1265,13 @@ def plot_1d( if scale == "linear": imap = LinearMapper( - range=index_range, stretch_data=index_mapper.stretch_data + range=index_range, + stretch_data=index_mapper.stretch_data, ) else: imap = LogMapper( - range=index_range, stretch_data=index_mapper.stretch_data + range=index_range, + stretch_data=index_mapper.stretch_data, ) cls = self.renderer_map[plot_type] @@ -1232,11 +1291,13 @@ def plot_1d( if scale == "linear": imap = LinearMapper( - range=index_range, stretch_data=index_mapper.stretch_data + range=index_range, + stretch_data=index_mapper.stretch_data, ) else: imap = LogMapper( - range=index_range, stretch_data=index_mapper.stretch_data + range=index_range, + stretch_data=index_mapper.stretch_data, ) cls = self.renderer_map[plot_type] plot = cls( @@ -1262,7 +1323,9 @@ def delplot(self, *names): # Remove all the renderers from us (container) and create a set of the # datasources that we might have to remove from the ranges deleted_sources = set() - for renderer in itertools.chain(*[self.plots.pop(name) for name in names]): + for renderer in itertools.chain( + *[self.plots.pop(name) for name in names] + ): self.remove(renderer) deleted_sources.add(renderer.index) deleted_sources.add(renderer.value) @@ -1355,7 +1418,8 @@ def _get_or_create_datasource(self, name): ds = data else: raise ValueError( - "Couldn't create datasource for data of " "type %s" % type(data) + "Couldn't create datasource for data of " + "type %s" % type(data) ) self.datasources[name] = ds diff --git a/chaco/plot_component.py b/chaco/plot_component.py index d7a8f30c7..833af6c4e 100644 --- a/chaco/plot_component.py +++ b/chaco/plot_component.py @@ -72,7 +72,8 @@ def _use_draw_order_changed(self, old, new): """ if new == False: raise RuntimeError( - "The old-style drawing mechanism is no longer " "supported in Chaco." + "The old-style drawing mechanism is no longer " + "supported in Chaco." ) @observe("+requires_redraw") diff --git a/chaco/plot_containers.py b/chaco/plot_containers.py index f9f0acfbd..3420d0f5c 100644 --- a/chaco/plot_containers.py +++ b/chaco/plot_containers.py @@ -1,7 +1,17 @@ """ Defines various plot container classes, including stacked, grid, and overlay. """ # Major library imports -from numpy import amax, any, arange, array, cumsum, hstack, sum, zeros, zeros_like +from numpy import ( + amax, + any, + arange, + array, + cumsum, + hstack, + sum, + zeros, + zeros_like, +) # Enthought library imports from traits.api import ( @@ -58,7 +68,9 @@ class ConstraintsPlotContainer(ConstraintsContainer): """A Plot container that supports constraints-based layout""" # !! Bits copied from BasePlotContainer !! - container_under_layers = Tuple("background", "image", "underlay", "plot") + container_under_layers = Tuple( + "background", "image", "underlay", "plot" + ) draw_order = Instance(list, args=(DEFAULT_DRAWING_ORDER,)) draw_layer = String("plot") # !! Bits copied from BasePlotContainer !! @@ -236,7 +248,9 @@ def _do_stack_layout(self, components, align): position = list(component.outer_position) position[ndx] = cur_pos - bounds = new_bounds_dict.get(component, list(component.outer_bounds)) + bounds = new_bounds_dict.get( + component, list(component.outer_bounds) + ) cur_pos += bounds[ndx] + self.spacing if (bounds[other_ndx] > size[other_ndx]) or ( @@ -254,7 +268,9 @@ def _do_stack_layout(self, components, align): elif align == "max": position[other_ndx] = size[other_ndx] - bounds[other_ndx] elif align == "center": - position[other_ndx] = (size[other_ndx] - bounds[other_ndx]) / 2.0 + position[other_ndx] = ( + size[other_ndx] - bounds[other_ndx] + ) / 2.0 component.outer_position = position component.outer_bounds = bounds @@ -506,7 +522,9 @@ def compute_size_array(self, size): # Regardless of the relationship between available space and # resizable preferred sizes, columns/rows where the non-resizable # component is largest will always get that amount of space. - return_lengths[fixed_length_indices] = fixed_lengths[fixed_length_indices] + return_lengths[fixed_length_indices] = fixed_lengths[ + fixed_length_indices + ] if size <= fixed_size: # We don't use fixed_length_indices here because that mask is @@ -518,7 +536,9 @@ def compute_size_array(self, size): return_lengths[indices] = fixed_lengths[indices] return_lengths[~indices] = 0 - elif size > fixed_size and (fixed_lengths > resizable_lengths).all(): + elif ( + size > fixed_size and (fixed_lengths > resizable_lengths).all() + ): # If we only have to consider non-resizable lengths, and we have # extra space available, then we need to give each column an # amount of extra space corresponding to its size. @@ -539,10 +559,13 @@ def compute_size_array(self, size): ) desired_space = sum(delta_lengths) if desired_space > 0: - avail_space = size - sum(fixed_lengths) # [fixed_length_indices]) + avail_space = size - sum( + fixed_lengths + ) # [fixed_length_indices]) scale = avail_space / desired_space return_lengths[resizable_indices] = ( - fixed_lengths[resizable_indices] + scale * delta_lengths + fixed_lengths[resizable_indices] + + scale * delta_lengths ).astype(int) elif fully_resizable_indices.any(): @@ -551,7 +574,9 @@ def compute_size_array(self, size): # over for the fully resizable components. Give the resizable # components their desired amount of space, and then give the # remaining space to the fully resizable components. - return_lengths[resizable_indices] = resizable_lengths[resizable_indices] + return_lengths[resizable_indices] = resizable_lengths[ + resizable_indices + ] avail_space = size - preferred_size count = sum(fully_resizable_indices) space = avail_space / count @@ -593,8 +618,12 @@ def get_preferred_size(self, components=None): self._h_size_prefs.update_from_component(component, j) self._v_size_prefs.update_from_component(component, i) - total_width = sum(self._h_size_prefs.get_preferred_size()) + self.hpadding - total_height = sum(self._v_size_prefs.get_preferred_size()) + self.vpadding + total_width = ( + sum(self._h_size_prefs.get_preferred_size()) + self.hpadding + ) + total_height = ( + sum(self._v_size_prefs.get_preferred_size()) + self.vpadding + ) total_size = array([total_width, total_height]) # Account for spacing. There are N+1 of spaces, where N is the size in @@ -603,7 +632,9 @@ def get_preferred_size(self, components=None): spacing = zeros(2) else: spacing = array(self.spacing) - total_spacing = array(components.shape[::-1]) * spacing * 2 * (total_size > 0) + total_spacing = ( + array(components.shape[::-1]) * spacing * 2 * (total_size > 0) + ) total_size += total_spacing for orientation, ndx in (("h", 0), ("v", 1)): @@ -648,8 +679,12 @@ def _do_layout(self): # Compute the total space used by non-resizable and resizable components # with non-zero preferred sizes. - widths = self._h_size_prefs.compute_size_array(size[0] - total_spacing[0]) - heights = self._v_size_prefs.compute_size_array(size[1] - total_spacing[1]) + widths = self._h_size_prefs.compute_size_array( + size[0] - total_spacing[0] + ) + heights = self._v_size_prefs.compute_size_array( + size[1] - total_spacing[1] + ) # Set the baseline h and v positions for each cell. Resizable components # will get these as their position, but non-resizable components will have diff --git a/chaco/plot_factory.py b/chaco/plot_factory.py index 889b82787..d782ab28e 100644 --- a/chaco/plot_factory.py +++ b/chaco/plot_factory.py @@ -295,7 +295,9 @@ def add_default_axes( v_mapper = plot.index_mapper h_mapper = plot.value_mapper - left = axis_class(orientation="left", title=vtitle, mapper=v_mapper, component=plot) + left = axis_class( + orientation="left", title=vtitle, mapper=v_mapper, component=plot + ) bottom = axis_class( orientation="bottom", title=htitle, mapper=h_mapper, component=plot diff --git a/chaco/plot_graphics_context.py b/chaco/plot_graphics_context.py index a90e2b3b9..9572748ea 100644 --- a/chaco/plot_graphics_context.py +++ b/chaco/plot_graphics_context.py @@ -23,9 +23,14 @@ class correctly offsets the coordinate frame by (0.5, 0.5) and increases def __init__(self, size_or_ary, *args, **kw): scale = kw.pop("dpi", 72.0) / 72.0 if type(size_or_ary) in (list, tuple) and len(size_or_ary) == 2: - size_or_ary = (size_or_ary[0] * scale + 1, size_or_ary[1] * scale + 1) + size_or_ary = ( + size_or_ary[0] * scale + 1, + size_or_ary[1] * scale + 1, + ) - super(PlotGraphicsContextMixin, self).__init__(size_or_ary, *args, **kw) + super(PlotGraphicsContextMixin, self).__init__( + size_or_ary, *args, **kw + ) self.translate_ctm(0.5, 0.5) self.scale_ctm(scale, scale) @@ -55,7 +60,9 @@ def render_component(self, component, container_coords=False): y = -y with self: self.translate_ctm(x, y) - component.draw(self, view_bounds=(0, 0, self.width(), self.height())) + component.draw( + self, view_bounds=(0, 0, self.width(), self.height()) + ) def clip_to_rect(self, x, y, width, height): """Offsets the coordinate frame by (0.5, 0.5) and increases the actual diff --git a/chaco/plotscrollbar.py b/chaco/plotscrollbar.py index 34cc70415..5e2c054a8 100644 --- a/chaco/plotscrollbar.py +++ b/chaco/plotscrollbar.py @@ -79,7 +79,9 @@ def _handle_dataspace_update(self): # Get the current datasource bounds range = self.mapper.range bounds_list = [ - source.get_bounds() for source in range.sources if source.get_size() > 0 + source.get_bounds() + for source in range.sources + if source.get_size() > 0 ] mins, maxes = zip(*bounds_list) dmin = min(mins) @@ -102,7 +104,9 @@ def _handle_dataspace_update(self): print("scrollrange:", foo) self.trait_setq( range=foo, - scroll_position=max(min(self.scroll_position, totalmax - view), totalmin), + scroll_position=max( + min(self.scroll_position, totalmax - view), totalmin + ), ) self._scroll_updated = True self.request_redraw() @@ -149,8 +153,12 @@ def _modify_plot_listeners(self, plot, action="attach"): remove = False else: remove = True - plot.observe(self._component_bounds_handler, "bounds.items", remove=remove) - plot.observe(self._component_pos_handler, "position.items", remove=remove) + plot.observe( + self._component_bounds_handler, "bounds.items", remove=remove + ) + plot.observe( + self._component_pos_handler, "position.items", remove=remove + ) def _component_bounds_handler(self, event): self._handle_dataspace_update() diff --git a/chaco/plugin/plot_editor.py b/chaco/plugin/plot_editor.py index aa751f1a1..727ab2030 100644 --- a/chaco/plugin/plot_editor.py +++ b/chaco/plugin/plot_editor.py @@ -21,7 +21,9 @@ class PlotEditor(TraitsUIEditor): """A Workbench Editor showing a Chaco plot for the shell interface.""" bgcolor = Str("white") - image_default_origin = Enum("bottom left", "top left", "bottom right", "top right") + image_default_origin = Enum( + "bottom left", "top left", "bottom right", "top right" + ) # The plot. component = Property(Any) diff --git a/chaco/polar_line_renderer.py b/chaco/polar_line_renderer.py index 5cf06ee15..6b18daded 100644 --- a/chaco/polar_line_renderer.py +++ b/chaco/polar_line_renderer.py @@ -113,7 +113,9 @@ def map_data(self, screen_pt): x, y = screen_pt else: y, x = screen_pt - return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) + return array( + (self.index_mapper.map_data(x), self.value_mapper.map_data(y)) + ) def _downsample(self): return self.map_screen(self._cached_data_pts) diff --git a/chaco/polygon_plot.py b/chaco/polygon_plot.py index 39d1c2173..6403b33d7 100644 --- a/chaco/polygon_plot.py +++ b/chaco/polygon_plot.py @@ -123,7 +123,9 @@ def hittest(self, screen_pt, threshold=7.0, return_distance=False): point is inside the polygon, and False otherwise. """ if self.hittest_type in ("line", "point"): - return BaseXYPlot.hittest(self, screen_pt, threshold, return_distance) + return BaseXYPlot.hittest( + self, screen_pt, threshold, return_distance + ) data_pt = self.map_data(screen_pt, all_values=True) index = self.index.get_data() diff --git a/chaco/quiverplot.py b/chaco/quiverplot.py index 962dbcf50..3a8646436 100644 --- a/chaco/quiverplot.py +++ b/chaco/quiverplot.py @@ -56,7 +56,9 @@ def _gather_points_old(self): return vectors = self.vectors.get_data() - self._cached_vector_data = compress(self._cached_point_mask, vectors, axis=0) + self._cached_vector_data = compress( + self._cached_point_mask, vectors, axis=0 + ) if self._cached_selected_pts is not None: indices = self._cached_selection_point_mask @@ -83,12 +85,16 @@ def _render(self, gc, points, icon_mode=False): if self.arrow_size > 0: vec = self._cached_vector_data - unit_vec = vec / sqrt(vec[:, 0] ** 2 + vec[:, 1] ** 2)[:, newaxis] + unit_vec = ( + vec / sqrt(vec[:, 0] ** 2 + vec[:, 1] ** 2)[:, newaxis] + ) a = 0.707106781 # sqrt(2)/2 # Draw the left arrowhead (for an arrow pointing straight up) arrow_ends = ( - ends - array(unit_vec * matrix([[a, a], [-a, a]])) * self.arrow_size + ends + - array(unit_vec * matrix([[a, a], [-a, a]])) + * self.arrow_size ) gc.begin_path() gc.line_set(ends, arrow_ends) @@ -96,7 +102,9 @@ def _render(self, gc, points, icon_mode=False): # Draw the left arrowhead (for an arrow pointing straight up) arrow_ends = ( - ends - array(unit_vec * matrix([[a, -a], [a, a]])) * self.arrow_size + ends + - array(unit_vec * matrix([[a, -a], [a, a]])) + * self.arrow_size ) gc.begin_path() gc.line_set(ends, arrow_ends) diff --git a/chaco/scales/formatters.py b/chaco/scales/formatters.py index 726efdd5e..e50c79a81 100644 --- a/chaco/scales/formatters.py +++ b/chaco/scales/formatters.py @@ -195,7 +195,13 @@ def _nice_sci(self, val, mdigits, force_sign=False): return m_str def estimate_width( - self, start, end, numlabels=None, char_width=None, fill_ratio=0.3, ticker=None + self, + start, + end, + numlabels=None, + char_width=None, + fill_ratio=0.3, + ticker=None, ): """Returns an estimate of the total number of characters used by the the labels for the given set of inputs, as well as the number of labels. @@ -350,7 +356,13 @@ def format(self, ticks, numlabels=None, char_width=None): return BasicFormatter.format(self, ticks, numlabels, char_width) def estimate_width( - self, start, end, numlabels=None, char_width=None, fill_ratio=0.3, ticker=None + self, + start, + end, + numlabels=None, + char_width=None, + fill_ratio=0.3, + ticker=None, ): if numlabels == 0 or char_width == 0: return (0, 0) @@ -362,7 +374,9 @@ def estimate_width( avg_size = len("%g%g" % (start, end)) / 2.0 initial_estimate = round(fill_ratio * char_width / avg_size) else: - raise ValueError("num_labels and char_width should not both be None.") + raise ValueError( + "num_labels and char_width should not both be None." + ) est_ticks = int(ticker.num_ticks(start, end, initial_estimate)) elif numlabels: @@ -372,7 +386,9 @@ def estimate_width( elif char_width: est_ticks = round(fill_ratio * char_width / avg_size) - start, mid, end = map(len, self.format([start, (start + end) / 2.0, end])) + start, mid, end = map( + len, self.format([start, (start + end) / 2.0, end]) + ) if est_ticks > 2: size = start + end + (est_ticks - 2) * mid else: @@ -521,7 +537,12 @@ def _get_resolution(self, resolution, interval): return resol def format( - self, ticks, numlabels=None, char_width=None, fill_ratio=0.3, ticker=None + self, + ticks, + numlabels=None, + char_width=None, + fill_ratio=0.3, + ticker=None, ): """Formats a set of time values. @@ -562,7 +583,9 @@ def format( if char_width: # If a width is provided, then we pick the most appropriate scale, # otherwise just use the widest format - good_formats = array(formats)[widths * len(ticks) < fill_ratio * char_width] + good_formats = array(formats)[ + widths * len(ticks) < fill_ratio * char_width + ] if len(good_formats) > 0: format = good_formats[-1] @@ -607,17 +630,23 @@ def format( # time is by checking that we have 0 units of the resolution, i.e. # we are at zero minutes, so display hours, or we are at zero seconds, # so display minutes (and if that is zero as well, then display hours). - while tm[time_tuple_ndx_for_resol[self.format_order[next_ndx]]] == 0: + while ( + tm[time_tuple_ndx_for_resol[self.format_order[next_ndx]]] == 0 + ): next_ndx += 1 if next_ndx == len(self.format_order): break if resol in ("minsec", "hourmin") and not hybrid_handled: - if (resol == "minsec" and tm.tm_min == 0 and tm.tm_sec != 0) or ( - resol == "hourmin" and tm.tm_hour == 0 and tm.tm_min != 0 + if ( + resol == "minsec" and tm.tm_min == 0 and tm.tm_sec != 0 + ) or ( + resol == "hourmin" + and tm.tm_hour == 0 + and tm.tm_min != 0 ): - next_format = self.formats[self.format_order[resol_ndx - 1]][1][ - 0 - ] + next_format = self.formats[ + self.format_order[resol_ndx - 1] + ][1][0] s = strftimeEx(next_format, t, tm) break else: @@ -638,7 +667,13 @@ def format( return labels def estimate_width( - self, start, end, numlabels=None, char_width=None, fill_ratio=0.2, ticker=None + self, + start, + end, + numlabels=None, + char_width=None, + fill_ratio=0.2, + ticker=None, ): """Returns an estimate of the total number of characters used by the the labels for the given set of inputs, as well as the number of labels. diff --git a/chaco/scales/scales.py b/chaco/scales/scales.py index 4c761661c..4f0d3deb2 100644 --- a/chaco/scales/scales.py +++ b/chaco/scales/scales.py @@ -171,7 +171,9 @@ def _nice(x, round=False): if x <= 0: import warnings - warnings.warn("Invalid (negative) range passed to tick interval calculation") + warnings.warn( + "Invalid (negative) range passed to tick interval calculation" + ) x = abs(x) expv = floor(log10(x)) f = x / pow(10, expv) @@ -196,7 +198,9 @@ def _nice(x, round=False): return nf * pow(10, expv) -def heckbert_interval(data_low, data_high, numticks=8, nicefunc=_nice, enclose=False): +def heckbert_interval( + data_low, data_high, numticks=8, nicefunc=_nice, enclose=False +): """Returns a "nice" range and resolution for an interval and a preferred number of ticks, using Paul Heckbert's algorithm in Graphics Gems. @@ -240,7 +244,9 @@ def ticks(self, start, end, desired_ticks=8): """ if start == end or isnan(start) or isnan(end): return [start] - min, max, delta = heckbert_interval(start, end, desired_ticks, enclose=True) + min, max, delta = heckbert_interval( + start, end, desired_ticks, enclose=True + ) return frange(min, max, delta) def num_ticks(self, start, end, desired_ticks=8): @@ -369,7 +375,9 @@ def ticks(self, start, end, desired_ticks=8): if log_interval < 1.0: # If the data is spaced by less than a factor of 10, then use # regular/linear ticking - min, max, delta = heckbert_interval(start, end, desired_ticks, enclose=True) + min, max, delta = heckbert_interval( + start, end, desired_ticks, enclose=True + ) return frange(min, max, delta) elif log_interval < desired_ticks: @@ -377,7 +385,9 @@ def ticks(self, start, end, desired_ticks=8): for interval in magic_numbers: n1 = self._logtickceil_as_irep(start, interval) n2 = self._logtickfloor_as_irep(end, interval) - ticks = [self._irep_to_value(n, interval) for n in range(n1, n2 + 1)] + ticks = [ + self._irep_to_value(n, interval) for n in range(n1, n2 + 1) + ] if len(ticks) < desired_ticks * 1.5: return ticks return ticks @@ -485,7 +495,9 @@ def labels(self, start, end, numlabels=None, char_width=None): # Check for insufficient arguments. if numlabels is None and char_width is None: - raise ValueError("Either numlabels or char_width (or both) must be given.") + raise ValueError( + "Either numlabels or char_width (or both) must be given." + ) if numlabels == 0 or char_width == 0 or isnan(start) or isnan(end): return [] @@ -525,12 +537,17 @@ def labels(self, start, end, numlabels=None, char_width=None): scales = self.scales counts, widths = zip( - *[s.label_width(start, end, char_width=char_width) for s in scales] + *[ + s.label_width(start, end, char_width=char_width) + for s in scales + ] ) widths = array(widths) closest = argmin(abs(widths - char_width * self.fill_ratio)) if numlabels is None: - numlabels = scales[closest].num_ticks(start, end, counts[closest]) + numlabels = scales[closest].num_ticks( + start, end, counts[closest] + ) labels = scales[closest].labels( start, end, numlabels, char_width=char_width ) @@ -558,7 +575,9 @@ def _get_scale(self, start, end, numticks): return closest_scale def _get_scale_bisect(self, start, end, numticks): - scale_intervals = [s.num_ticks(start, end, numticks) for s in self.scales] + scale_intervals = [ + s.num_ticks(start, end, numticks) for s in self.scales + ] sorted_scales = sorted(zip(scale_intervals, self.scales)) ndx = bisect(sorted_scales, numticks, lo=0, hi=len(self.scales)) if ndx == len(self.scales): diff --git a/chaco/scales/tests/test_scales.py b/chaco/scales/tests/test_scales.py index 98e157722..6fa526794 100644 --- a/chaco/scales/tests/test_scales.py +++ b/chaco/scales/tests/test_scales.py @@ -3,7 +3,14 @@ from numpy import array from ..formatters import BasicFormatter, OffsetFormatter -from ..scales import Pow10Scale, FixedScale, LogScale, DefaultScale, ScaleSystem, frange +from ..scales import ( + Pow10Scale, + FixedScale, + LogScale, + DefaultScale, + ScaleSystem, + frange, +) class TicksTestCase(unittest.TestCase): @@ -39,12 +46,15 @@ def test_log_scale_subdecade(self): scale = LogScale() ticks = scale.ticks(1.0, 2.0) self.check_ticks( - ticks, array((1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0)) + ticks, + array((1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0)), ) ticks = scale.ticks(0.9, 2.1) self.check_ticks(ticks, array((1.0, 1.25, 1.5, 1.75, 2.0))) ticks = scale.ticks(1.1, 9.9) - self.check_ticks(ticks, array((2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0))) + self.check_ticks( + ticks, array((2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0)) + ) def test_log_scale_interval1(self): # Test the case where 1 < log_interval < desired_ticks, and interval=1 @@ -56,11 +66,15 @@ def test_log_scale_interval1(self): ) ticks = scale.ticks(9.3, 99.9) self.check_ticks( - ticks, array((10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0)) + ticks, + array((10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0)), ) ticks = scale.ticks(9.9, 100.0) self.check_ticks( - ticks, array((10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0)) + ticks, + array( + (10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0) + ), ) def test_log_scale(self): @@ -68,7 +82,8 @@ def test_log_scale(self): ticks = scale.ticks(0.1, 10.0) self.check_ticks( - ticks, array((0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0)) + ticks, + array((0.1, 0.2, 0.4, 0.6, 0.8, 1.0, 2.0, 4.0, 6.0, 8.0, 10.0)), ) ticks = scale.ticks(10.0, 1000.0) self.check_ticks( @@ -133,7 +148,9 @@ def test_fixed_scales(self): ticker = ScaleSystem(default_scale=None, *scales) self.check_ticks(ticker.ticks(5, 35, 3), (10.0, 20.0, 30.0)) self.check_ticks(ticker.ticks(5, 35, 20), frange(5.0, 35.0, 1.0)) - self.check_ticks(ticker.ticks(5, 614, 10), (100, 200, 300, 400, 500, 600)) + self.check_ticks( + ticker.ticks(5, 614, 10), (100, 200, 300, 400, 500, 600) + ) def test_revert_to_default(self): scales = [ @@ -207,7 +224,9 @@ def test_estimate_default_scale(self): (3e8, 6e8, 8), ) for start, end, numlabels in test_intervals: - estimate = fmt.estimate_width(start, end, numlabels, ticker=scale)[1] + estimate = fmt.estimate_width(start, end, numlabels, ticker=scale)[ + 1 + ] ticks = scale.ticks(start, end, numlabels) labels = fmt.format(ticks, numlabels, None) actual = sum(map(len, labels)) diff --git a/chaco/scales/tests/test_time_scale.py b/chaco/scales/tests/test_time_scale.py index ac4f0440d..e379bec94 100644 --- a/chaco/scales/tests/test_time_scale.py +++ b/chaco/scales/tests/test_time_scale.py @@ -6,7 +6,12 @@ import numpy as np import numpy.testing as nptest -from chaco.scales.time_scale import tfrac, trange, TimeScale, CalendarScaleSystem +from chaco.scales.time_scale import ( + tfrac, + trange, + TimeScale, + CalendarScaleSystem, +) from chaco.scales.api import TimeFormatter # Note on testing: @@ -87,7 +92,9 @@ def test_tfrac_years_01_Alice_Springs(self): self.assertEqual( base, 3600 * -9.5 ) # Alice Springs year start UTC timestamp - self.assertEqual(frac, 3600 * 10.5 + 1) # 10:30:01 in the morning Jan 1 + self.assertEqual( + frac, 3600 * 10.5 + 1 + ) # 10:30:01 in the morning Jan 1 def test_tfrac_years_01_Honolulu(self): # Pacific/Honolulu (UTC-10:00, never DST) @@ -116,7 +123,9 @@ def test_tfrac_years_02_Alice_Springs(self): self.assertEqual( base, 3600 * -9.5 ) # Alice Springs decade start UTC timestamp - self.assertEqual(frac, 3600 * 10.5 + 1) # 10:30:01 in the morning Jan 1 + self.assertEqual( + frac, 3600 * 10.5 + 1 + ) # 10:30:01 in the morning Jan 1 def test_tfrac_years_02_Honolulu(self): # Pacific/Honolulu (UTC-10:00, never DST) @@ -140,7 +149,9 @@ def test_tfrac_days_01_Alice_Springs(self): with set_timezone(ALICE_SPRINGS): t = 3601 (base, frac) = tfrac(t, days=1) - self.assertEqual(base, 3600 * -9.5) # Alice Springs day start UTC timestamp + self.assertEqual( + base, 3600 * -9.5 + ) # Alice Springs day start UTC timestamp self.assertEqual(frac, 3600 * 10.5 + 1) # 10:30:01 in the morning def test_tfrac_days_01_Honolulu(self): diff --git a/chaco/scales/tests/test_time_scale_resolution.py b/chaco/scales/tests/test_time_scale_resolution.py index 001ddf88b..d9c809260 100644 --- a/chaco/scales/tests/test_time_scale_resolution.py +++ b/chaco/scales/tests/test_time_scale_resolution.py @@ -34,7 +34,11 @@ def sec_from_hms(start, *times): class TRangeTestCase(TicksTestCase): def test_null_ranges(self): ranges = ( - ((2005, 3, 15, 10, 23, 15), (2005, 3, 15, 10, 23, 45), {"minutes": 1}), + ( + (2005, 3, 15, 10, 23, 15), + (2005, 3, 15, 10, 23, 45), + {"minutes": 1}, + ), ((2005, 3, 15, 10, 23), (2005, 3, 15, 10, 47), {"hours": 1}), ((2005, 3, 15, 5, 23), (2005, 3, 15, 18, 43), {"days": 1}), ((2005, 3, 15, 10, 30), (2005, 12, 25, 18, 30), {"years": 1}), @@ -79,7 +83,9 @@ def test_daily_leap(self): def test_hourly(self): # test between Feb 29,2004 10:15pm and Mar 1st 3:15am - ticks = trange(DTS(2004, 2, 29, 22, 15), DTS(2004, 3, 1, 3, 15), hours=1) + ticks = trange( + DTS(2004, 2, 29, 22, 15), DTS(2004, 3, 1, 3, 15), hours=1 + ) start = DTS(2004, 2, 29, 23) desired = [start + i * 3600 for i in range(5)] self.check_ticks(ticks, desired) @@ -132,7 +138,9 @@ def test_day_of_month(self): start = DTS(2005, 3, 12) end = DTS(2005, 4, 10) desired = list( - starmap(DTS, ((2005, 3, 15), (2005, 3, 22), (2005, 4, 1), (2005, 4, 8))) + starmap( + DTS, ((2005, 3, 15), (2005, 3, 22), (2005, 4, 1), (2005, 4, 8)) + ) ) self.check_ticks(ts.ticks(start, end), desired) @@ -143,7 +151,13 @@ def test_month_of_year(self): desired = list( starmap( DTS, - ((2005, 1, 1), (2005, 4, 1), (2005, 8, 1), (2006, 1, 1), (2006, 4, 1)), + ( + (2005, 1, 1), + (2005, 4, 1), + (2005, 8, 1), + (2006, 1, 1), + (2006, 4, 1), + ), ) ) self.check_ticks(ts.ticks(start, end), desired) @@ -156,7 +170,9 @@ def test_microsecond(self): start = base + 2.8e-6 end = base + 9.2e-6 ticks = ts.ticks(start, end) - desired = [base + i for i in (3e-6, 4e-6, 5e-6, 6e-6, 7e-6, 8e-6, 9e-6)] + desired = [ + base + i for i in (3e-6, 4e-6, 5e-6, 6e-6, 7e-6, 8e-6, 9e-6) + ] self.check_ticks(ticks, desired) @@ -199,7 +215,9 @@ def test_widths(self): test_intervals = ([(2005, 3, 15, 10, 30), (2005, 3, 15, 10, 50), 50],) expected = (4.0, 12.0) for start, end, width in test_intervals: - est_width = scale.label_width(DTS(*start), DTS(*end), char_width=width) + est_width = scale.label_width( + DTS(*start), DTS(*end), char_width=width + ) self.assertEqual(est_width, expected) def test_labels(self): diff --git a/chaco/scales/time_scale.py b/chaco/scales/time_scale.py index 9d0eea21f..40a428526 100644 --- a/chaco/scales/time_scale.py +++ b/chaco/scales/time_scale.py @@ -6,10 +6,25 @@ from .scales import AbstractScale, ScaleSystem, frange, heckbert_interval from .formatters import TimeFormatter -from .safetime import safe_fromtimestamp, datetime, timedelta, EPOCH, MINYEAR, MAXYEAR +from .safetime import ( + safe_fromtimestamp, + datetime, + timedelta, + EPOCH, + MINYEAR, + MAXYEAR, +) # Labels for date and time units. -datetime_scale = ["microsecond", "second", "minute", "hour", "day", "month", "year"] +datetime_scale = [ + "microsecond", + "second", + "minute", + "hour", + "day", + "month", + "year", +] datetime_zeros = list(zip(datetime_scale, [0, 0, 0, 0, 1, 1, 1])) @@ -115,7 +130,8 @@ def trange_months(start, end, months): dt_end = safe_fromtimestamp(end) dmonths = (12 * (dt_start.year - 2000) + dt_start.month - 1) % months dt = _advance_month( - dt_start.replace(day=1, hour=0, minute=0, second=0, microsecond=0), -dmonths + dt_start.replace(day=1, hour=0, minute=0, second=0, microsecond=0), + -dmonths, ) while dt < dt_start: dt = _advance_month(dt, months) @@ -178,7 +194,8 @@ def trange(start, end, **time_unit): if len(time_units) != 1: raise ValueError( - "trange() only takes one keyword argument, got %d" % len(time_units) + "trange() only takes one keyword argument, got %d" + % len(time_units) ) # Months and years are non-uniform, so we special-case them. @@ -268,7 +285,9 @@ def num_ticks(self, start, end, desired_ticks=None): # This is only approximate, but puts us in the ballpark if self.unit in ("milliseconds", "microseconds"): ticks = self.ticks(start, end, desired_ticks=8) - coarsest_scale_count = (end - start) / (500 * self.SECS_PER_UNIT[self.unit]) + coarsest_scale_count = (end - start) / ( + 500 * self.SECS_PER_UNIT[self.unit] + ) return max(len(ticks), coarsest_scale_count) else: return (end - start) / self.resolution @@ -332,7 +351,11 @@ def cal_ticks(self, start, end): elif self.unit == "month_of_year": # get naive datetimes for start of each month in range of years - dates = [datetime(year, month, 1) for year in years for month in self.vals] + dates = [ + datetime(year, month, 1) + for year in years + for month in self.vals + ] else: raise ValueError("Unknown calendar unit '%s'" % self.unit) @@ -351,7 +374,9 @@ def labels(self, start, end, numlabels=None, char_width=None): Overrides AbstractScale. """ ticks = self.ticks(start, end, numlabels) - labels = self.formatter.format(ticks, numlabels, char_width, ticker=self) + labels = self.formatter.format( + ticks, numlabels, char_width, ticker=self + ) return list(zip(ticks, labels)) def label_width(self, start, end, numlabels=None, char_width=None): @@ -410,7 +435,8 @@ def _get_scale(self, start, end, numticks): closest_scale = self.default_scale else: raise ValueError( - "CalendarScaleSystem has not be configured " "with any scales." + "CalendarScaleSystem has not be configured " + "with any scales." ) elif end - start < 1e-6 or end - start > 1e5 * 365 * 24 * 3600: closest_scale = self.default_scale diff --git a/chaco/scatter_inspector_overlay.py b/chaco/scatter_inspector_overlay.py index 14ac13342..08834f812 100644 --- a/chaco/scatter_inspector_overlay.py +++ b/chaco/scatter_inspector_overlay.py @@ -49,7 +49,10 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): if not plot or not plot.index or not getattr(plot, "value", True): return - for inspect_type in (self.hover_metadata_name, self.selection_metadata_name): + for inspect_type in ( + self.hover_metadata_name, + self.selection_metadata_name, + ): if inspect_type in plot.index.metadata: # if hasattr(plot,"value") and not inspect_type in plot.value.metadata: # continue @@ -135,7 +138,10 @@ def _component_changed(self, old, new): if getattr(new, dsname): self._ds_changed( TraitChangeEvent( - object=new, name=dsname, old=None, new=getattr(new, dsname) + object=new, + name=dsname, + old=None, + new=getattr(new, dsname), ) ) diff --git a/chaco/scatterplot.py b/chaco/scatterplot.py index 1c1398cbc..0ff6c9baf 100644 --- a/chaco/scatterplot.py +++ b/chaco/scatterplot.py @@ -240,7 +240,9 @@ class ScatterPlot(BaseXYPlot): # The RGBA tuple for rendering the fill. It is always a tuple of length 4. # It has the same RGB values as outline_color_, and its alpha value is the # alpha value of self.outline_color multiplied by self.alpha. - effective_outline_color = Property(Tuple, depends_on=["outline_color", "alpha"]) + effective_outline_color = Property( + Tuple, depends_on=["outline_color", "alpha"] + ) # Traits UI View for customizing the plot. traits_view = ScatterPlotView() @@ -313,10 +315,16 @@ def map_data(self, screen_pt, all_values=True): x, y = screen_pt if self.orientation == "v": x, y = y, x - return array((self.index_mapper.map_data(x), self.value_mapper.map_data(y))) + return array( + (self.index_mapper.map_data(x), self.value_mapper.map_data(y)) + ) def map_index( - self, screen_pt, threshold=0.0, outside_returns_none=True, index_only=False + self, + screen_pt, + threshold=0.0, + outside_returns_none=True, + index_only=False, ): """Maps a screen space point to an index into the plot's index array(s). @@ -340,7 +348,9 @@ def map_index( return None try: - ndx = reverse_map_1d(index_data, data_pt, self.index.sort_order) + ndx = reverse_map_1d( + index_data, data_pt, self.index.sort_order + ) except IndexError as e: # if reverse_map raises this exception, it means that data_pt is # outside the range of values in index_data. @@ -529,7 +539,10 @@ def _render(self, gc, points, icon_mode=False): point_mask=self._cached_point_mask, ) - if self._cached_selected_pts is not None and len(self._cached_selected_pts) > 0: + if ( + self._cached_selected_pts is not None + and len(self._cached_selected_pts) > 0 + ): sel_pts = self.map_screen(self._cached_selected_pts) self.render_markers_func( gc, diff --git a/chaco/segment_plot.py b/chaco/segment_plot.py index fff539142..3b7599f96 100644 --- a/chaco/segment_plot.py +++ b/chaco/segment_plot.py @@ -194,7 +194,9 @@ def _render_line(self, gc, starts, ends, colors, widths): gc.line_set(starts, ends) gc.stroke_path() else: - for color, width, start, end in np.broadcast(colors, widths, starts, ends): + for color, width, start, end in np.broadcast( + colors, widths, starts, ends + ): gc.set_stroke_color(color) gc.set_line_width(float(width)) gc.move_to(start["x"], start["y"]) @@ -325,10 +327,17 @@ def _render_cubic(self, gc, starts, ends, colors, widths): # no alpha, can draw a single unconnected path, faster gc.set_line_width(widths[0]) gc.set_stroke_color(colors[0]) - for start, end, mid_1, mid_2 in np.broadcast(starts, ends, mids_1, mids_2): + for start, end, mid_1, mid_2 in np.broadcast( + starts, ends, mids_1, mids_2 + ): gc.move_to(start["x"], start["y"]) gc.curve_to( - mid_1["x"], mid_1["y"], mid_2["x"], mid_2["y"], end["x"], end["y"] + mid_1["x"], + mid_1["y"], + mid_2["x"], + mid_2["y"], + end["x"], + end["y"], ) gc.stroke_path() else: @@ -339,7 +348,12 @@ def _render_cubic(self, gc, starts, ends, colors, widths): gc.set_line_width(float(width)) gc.move_to(start["x"], start["y"]) gc.curve_to( - mid_1["x"], mid_1["y"], mid_2["x"], mid_2["y"], end["x"], end["y"] + mid_1["x"], + mid_1["y"], + mid_2["x"], + mid_2["y"], + end["x"], + end["y"], ) gc.stroke_path() @@ -384,7 +398,9 @@ def _get_effective_colors(self): if colors.shape[-1] == 4: colors[:, -1] *= self.alpha else: - colors = np.column_stack([colors, np.full(len(colors), self.alpha)]) + colors = np.column_stack( + [colors, np.full(len(colors), self.alpha)] + ) if self.selected_mask is not None: colors[~self.selected_mask, -1] *= self.selection_alpha diff --git a/chaco/shell/commands.py b/chaco/shell/commands.py index 588a7b6c8..239fcdc18 100644 --- a/chaco/shell/commands.py +++ b/chaco/shell/commands.py @@ -193,7 +193,9 @@ def show(): is_event_loop_running = getattr( guisupport, "is_event_loop_running_" + ETSConfig.toolkit ) - start_event_loop = getattr(guisupport, "start_event_loop_" + ETSConfig.toolkit) + start_event_loop = getattr( + guisupport, "start_event_loop_" + ETSConfig.toolkit + ) if not is_event_loop_running(): frame = session.active_window @@ -292,7 +294,9 @@ def _do_plot_boilerplate(kwargs, image=False): cont.tools.append(PanTool(cont)) if not ZoomTool in existing_tools: cont.overlays.append( - ZoomTool(cont, tool_mode="box", always_on=True, drag_button="right") + ZoomTool( + cont, tool_mode="box", always_on=True, drag_button="right" + ) ) if not session.hold: @@ -428,7 +432,9 @@ def pcolor(*data, **kwargs): cont = _do_plot_boilerplate(kwargs) - plots = plot_maker.do_pcolor(session.data, session.colormap, cont, *data, **kwargs) + plots = plot_maker.do_pcolor( + session.data, session.colormap, cont, *data, **kwargs + ) cont.request_redraw() @@ -780,7 +786,11 @@ def tool(): def save( - filename="chacoplot.png", dpi=72, pagesize="letter", dest_box=None, units="inch" + filename="chacoplot.png", + dpi=72, + pagesize="letter", + dest_box=None, + units="inch", ): """Saves the active plot to an file. Currently supported file types are: bmp, png, jpg. diff --git a/chaco/shell/plot_maker.py b/chaco/shell/plot_maker.py index 948c20c48..93d36bbce 100644 --- a/chaco/shell/plot_maker.py +++ b/chaco/shell/plot_maker.py @@ -112,14 +112,19 @@ def make_data_sources(session, index_sort="none", *args): if len(data[0].shape) == 1: if len(data) == 1: # Only a single array was provided - index_ds = ArrayDataSource(arange(len(data[0])), sort_order="ascending") + index_ds = ArrayDataSource( + arange(len(data[0])), sort_order="ascending" + ) value_ds = ArrayDataSource(data[0], sort_order="none") return [(index_ds, value_ds)] else: # multiple arrays were provided index_ds = ArrayDataSource(data[0], sort_order=index_sort) - return [(index_ds, ArrayDataSource(v, sort_order="none")) for v in data[1:]] + return [ + (index_ds, ArrayDataSource(v, sort_order="none")) + for v in data[1:] + ] # 2D arrays elif len(data[0].shape) == 2: @@ -237,7 +242,9 @@ def _process_group(group, plot_data=None): plotinfo = group[1] y = group[0] y_data = plot_data.get_data(y) - x = plot_data.set_data("", arange(len(y_data)), generate_name=True) + x = plot_data.set_data( + "", arange(len(y_data)), generate_name=True + ) else: x, y = group elif len(group) == 3: @@ -305,7 +312,9 @@ def do_plot(plotdata, active_plot, *data_and_formats, **kwtraits): format["color"] = markercolor x_sort_order = _check_sort_order(plotdata.get_data(x)) - plots.extend(active_plot.plot((x, y), type=",".join(plot_type), **format)) + plots.extend( + active_plot.plot((x, y), type=",".join(plot_type), **format) + ) # Set the sort order x_ds = active_plot.datasources[x] @@ -376,7 +385,9 @@ def do_pcolor(plotdata, colormap, active_plot, *data, **kwargs): raise ValueError("do_pcolor takes one or three data sources") plot_list = [ - active_plot.img_plot(z, xbounds=x, ybounds=y, colormap=colormap, **kwargs) + active_plot.img_plot( + z, xbounds=x, ybounds=y, colormap=colormap, **kwargs + ) ] return plot_list diff --git a/chaco/shell/plot_window.py b/chaco/shell/plot_window.py index 05034de62..c9a365b0d 100644 --- a/chaco/shell/plot_window.py +++ b/chaco/shell/plot_window.py @@ -252,4 +252,6 @@ def closeEvent(self, event): class PlotWindow(object): def __init__(self, *args, **kwargs): - raise NotImplementedError("PlotWindow not implemented for `null` toolkit") + raise NotImplementedError( + "PlotWindow not implemented for `null` toolkit" + ) diff --git a/chaco/shell/preferences.py b/chaco/shell/preferences.py index ca676e958..7b23ee90c 100644 --- a/chaco/shell/preferences.py +++ b/chaco/shell/preferences.py @@ -24,7 +24,9 @@ class Preferences(HasTraits): bgcolor = white_color_trait # The default location of the origin for new image plots - image_default_origin = Enum("top left", "bottom left", "bottom right", "top right") + image_default_origin = Enum( + "top left", "bottom left", "bottom right", "top right" + ) @classmethod def from_file(cls, filename): diff --git a/chaco/shell/scaly_plot.py b/chaco/shell/scaly_plot.py index 816ffeac1..7192af204 100644 --- a/chaco/shell/scaly_plot.py +++ b/chaco/shell/scaly_plot.py @@ -99,9 +99,13 @@ def _init_components(self): self.value_mapper = vmap if self.x_ticks is None: - self.x_ticks = ScalesTickGenerator(scale=self._make_scale(self.index_scale)) + self.x_ticks = ScalesTickGenerator( + scale=self._make_scale(self.index_scale) + ) if self.y_ticks is None: - self.y_ticks = ScalesTickGenerator(scale=self._make_scale(self.value_scale)) + self.y_ticks = ScalesTickGenerator( + scale=self._make_scale(self.value_scale) + ) if self.x_grid is None: self.x_grid = PlotGrid( diff --git a/chaco/shell/session.py b/chaco/shell/session.py index 3a006345e..3cf2cb077 100644 --- a/chaco/shell/session.py +++ b/chaco/shell/session.py @@ -154,5 +154,7 @@ def _colormap_changed(self): p.invalidate_draw() p.request_redraw() elif hasattr(p, "colors"): - if isinstance(p.colors, str) or isinstance(p.colors, AbstractColormap): + if isinstance(p.colors, str) or isinstance( + p.colors, AbstractColormap + ): p.colors = color_map_dict[self.colormap] diff --git a/chaco/svg_graphics_context.py b/chaco/svg_graphics_context.py index 3443ecd99..0ec1c0373 100644 --- a/chaco/svg_graphics_context.py +++ b/chaco/svg_graphics_context.py @@ -22,7 +22,10 @@ class correctly offsets the coordinate frame by (0.5, 0.5) and increases def __init__(self, size_or_ary, dpi=72.0, *args, **kw): scale = dpi / 72.0 if type(size_or_ary) in (list, tuple) and len(size_or_ary) == 2: - size_or_ary = (size_or_ary[0] * scale + 1, size_or_ary[1] * scale + 1) + size_or_ary = ( + size_or_ary[0] * scale + 1, + size_or_ary[1] * scale + 1, + ) super(SVGGraphicsContext, self).__init__(size_or_ary, *args, **kw) self.translate_ctm(0.5, 0.5) @@ -69,4 +72,6 @@ def clip_to_rect(self, x, y, width, height): Overrides Kiva GraphicsContext. """ - GraphicsContext.clip_to_rect(self, x - 0.5, y - 0.5, width + 1, height + 1) + GraphicsContext.clip_to_rect( + self, x - 0.5, y - 0.5, width + 1, height + 1 + ) diff --git a/chaco/tests/segment_plot_test_case.py b/chaco/tests/segment_plot_test_case.py index af90e1354..468690403 100644 --- a/chaco/tests/segment_plot_test_case.py +++ b/chaco/tests/segment_plot_test_case.py @@ -4,7 +4,12 @@ from numpy.testing import assert_array_equal # Chaco imports -from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext +from chaco.api import ( + ArrayDataSource, + DataRange1D, + LinearMapper, + PlotGraphicsContext, +) from chaco.base import rgba_dtype from chaco.segment_plot import SegmentPlot from chaco.default_colormaps import viridis @@ -54,8 +59,12 @@ def set_width_data(self): def test_segment(self): self.assertEqual(self.segment_plot.origin, "bottom left") - self.assertIs(self.segment_plot.x_mapper, self.segment_plot.index_mapper) - self.assertIs(self.segment_plot.y_mapper, self.segment_plot.value_mapper) + self.assertIs( + self.segment_plot.x_mapper, self.segment_plot.index_mapper + ) + self.assertIs( + self.segment_plot.y_mapper, self.segment_plot.value_mapper + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.segment_plot) @@ -66,8 +75,12 @@ def test_segment_orthogonal(self): self.segment_plot.render_style = "orthogonal" self.assertEqual(self.segment_plot.origin, "bottom left") - self.assertIs(self.segment_plot.x_mapper, self.segment_plot.index_mapper) - self.assertIs(self.segment_plot.y_mapper, self.segment_plot.value_mapper) + self.assertIs( + self.segment_plot.x_mapper, self.segment_plot.index_mapper + ) + self.assertIs( + self.segment_plot.y_mapper, self.segment_plot.value_mapper + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.segment_plot) @@ -78,8 +91,12 @@ def test_segment_quad(self): self.segment_plot.render_style = "quad" self.assertEqual(self.segment_plot.origin, "bottom left") - self.assertIs(self.segment_plot.x_mapper, self.segment_plot.index_mapper) - self.assertIs(self.segment_plot.y_mapper, self.segment_plot.value_mapper) + self.assertIs( + self.segment_plot.x_mapper, self.segment_plot.index_mapper + ) + self.assertIs( + self.segment_plot.y_mapper, self.segment_plot.value_mapper + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.segment_plot) @@ -90,8 +107,12 @@ def test_segment_cubic(self): self.segment_plot.render_style = "cubic" self.assertEqual(self.segment_plot.origin, "bottom left") - self.assertIs(self.segment_plot.x_mapper, self.segment_plot.index_mapper) - self.assertIs(self.segment_plot.y_mapper, self.segment_plot.value_mapper) + self.assertIs( + self.segment_plot.x_mapper, self.segment_plot.index_mapper + ) + self.assertIs( + self.segment_plot.y_mapper, self.segment_plot.value_mapper + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.segment_plot) diff --git a/chaco/tests/test_arraydatasource.py b/chaco/tests/test_arraydatasource.py index f6480755a..02c4df286 100644 --- a/chaco/tests/test_arraydatasource.py +++ b/chaco/tests/test_arraydatasource.py @@ -38,7 +38,9 @@ def test_basic_setup(self): def test_set_data(self): new_array = arange(0, 20, 2) - with self.assertTraitChanges(self.data_source, "data_changed", count=1): + with self.assertTraitChanges( + self.data_source, "data_changed", count=1 + ): self.data_source.set_data(new_array) assert_array_equal(new_array, self.data_source._data) @@ -48,7 +50,9 @@ def test_set_data(self): def test_set_data_ordered(self): new_array = arange(20, 0, -2) - with self.assertTraitChanges(self.data_source, "data_changed", count=1): + with self.assertTraitChanges( + self.data_source, "data_changed", count=1 + ): self.data_source.set_data(new_array, sort_order="descending") assert_array_equal(new_array, self.data_source._data) @@ -56,7 +60,9 @@ def test_set_data_ordered(self): self.assertEqual(self.data_source.sort_order, "descending") def test_set_mask(self): - with self.assertTraitChanges(self.data_source, "data_changed", count=1): + with self.assertTraitChanges( + self.data_source, "data_changed", count=1 + ): self.data_source.set_mask(self.mymask) assert_array_equal(self.myarray, self.data_source._data) @@ -68,7 +74,9 @@ def test_remove_mask(self): self.data_source.set_mask(self.mymask) self.assertTrue(self.data_source.is_masked()) - with self.assertTraitChanges(self.data_source, "data_changed", count=1): + with self.assertTraitChanges( + self.data_source, "data_changed", count=1 + ): self.data_source.remove_mask() assert_array_equal(self.myarray, self.data_source._data) @@ -207,11 +215,15 @@ def test_metadata(self): ) def test_metadata_changed(self): - with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + with self.assertTraitChanges( + self.data_source, "metadata_changed", count=1 + ): self.data_source.metadata = {"new_metadata": True} def test_metadata_items_changed(self): - with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + with self.assertTraitChanges( + self.data_source, "metadata_changed", count=1 + ): self.data_source.metadata["new_metadata"] = True def test_serialization_state(self): diff --git a/chaco/tests/test_base_utils.py b/chaco/tests/test_base_utils.py index 96be014b7..f414798ed 100644 --- a/chaco/tests/test_base_utils.py +++ b/chaco/tests/test_base_utils.py @@ -139,7 +139,8 @@ def test_find_runs_none(self): def test_find_runs_descending(self): x = array([30, 41, 40, 39, 38, 37, 12]) assert_equal( - find_runs(x, order="descending"), [[30], [41, 40, 39, 38, 37], [12]] + find_runs(x, order="descending"), + [[30], [41, 40, 39, 38, 37], [12]], ) def test_find_runs_flat(self): @@ -152,7 +153,9 @@ def test_find_runs_flat(self): class ArgFindRunsTestCase(unittest.TestCase): def test_arg_find_runs_middle(self): x = array([0, 8, 7, 8, 9, 2, 3, 4, 10]) - assert_equal(arg_find_runs(x), [[0, 1], [1, 2], [2, 5], [5, 8], [8, 9]]) + assert_equal( + arg_find_runs(x), [[0, 1], [1, 2], [2, 5], [5, 8], [8, 9]] + ) def test_arg_find_runs_start(self): x = array([3, 4, 5, 12, 9, 17]) @@ -178,7 +181,9 @@ def test_arg_find_runs_none(self): def test_arg_find_runs_descending(self): x = array([30, 41, 40, 39, 38, 37, 12]) - assert_equal(arg_find_runs(x, order="descending"), [[0, 1], [1, 6], [6, 7]]) + assert_equal( + arg_find_runs(x, order="descending"), [[0, 1], [1, 6], [6, 7]] + ) def test_arg_find_runs_flat(self): x = array([0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0]) diff --git a/chaco/tests/test_border.py b/chaco/tests/test_border.py index 157aa5bda..f2e911975 100644 --- a/chaco/tests/test_border.py +++ b/chaco/tests/test_border.py @@ -15,7 +15,9 @@ class DrawBorderTestCase(unittest.TestCase): def assertRavelEqual(self, x, y): - self.assertTrue(alltrue(ravel(x) == ravel(y)), "\n%s\n !=\n%s" % (x, y)) + self.assertTrue( + alltrue(ravel(x) == ravel(y)), "\n%s\n !=\n%s" % (x, y) + ) def test_draw_border_simple(self): """Borders should have the correct height and width.""" diff --git a/chaco/tests/test_colormapper.py b/chaco/tests/test_colormapper.py index 8fd8f31fd..f1cb7eebf 100644 --- a/chaco/tests/test_colormapper.py +++ b/chaco/tests/test_colormapper.py @@ -29,7 +29,8 @@ def test_simple_map(self): close = allclose(ravel(b[:, :1]), expected, atol=0.02) self.assertTrue( - close, "Simple map failed. Expected %s. Got %s" % (expected, b[:, :1]) + close, + "Simple map failed. Expected %s. Got %s" % (expected, b[:, :1]), ) def test_change_min_max(self): @@ -92,7 +93,8 @@ def test_array_factory(self): self.assertTrue( allclose(ravel(b[:, :1]), expected, atol=0.02), - "Array factory failed. Expected %s. Got %s" % (expected, b[:, :1]), + "Array factory failed. Expected %s. Got %s" + % (expected, b[:, :1]), ) def test_alpha_palette(self): diff --git a/chaco/tests/test_contour.py b/chaco/tests/test_contour.py index 228a3faea..84749ea45 100644 --- a/chaco/tests/test_contour.py +++ b/chaco/tests/test_contour.py @@ -12,7 +12,9 @@ def test_contour_trace_levels_no_mask(self): xs = np.array([0, 1, 2, 3]) ys = np.array([10, 20, 30, 40]) xg, yg = np.meshgrid(xs, ys) - data = np.array([[0, 0, 1, 2], [0, 1, 2, 3], [1, 2, 0, 3], [2, 3, 3, 3]]) + data = np.array( + [[0, 0, 1, 2], [0, 1, 2, 3], [1, 2, 0, 3], [2, 3, 3, 3]] + ) mask = np.ones(data.shape, dtype=bool) # When @@ -21,9 +23,13 @@ def test_contour_trace_levels_no_mask(self): # Then levels = c.trace(0.0) self.assertEqual(len(levels), 2) - self._check_level(levels[0], [1.0, 1.0, 0.0, 0.0], [10.0, 10.0, 20.0, 20.0]) self._check_level( - levels[1], [2.0, 2.0, 2.0, 2.0, 2.0], [30.0, 30.0, 30.0, 30.0, 30.0] + levels[0], [1.0, 1.0, 0.0, 0.0], [10.0, 10.0, 20.0, 20.0] + ) + self._check_level( + levels[1], + [2.0, 2.0, 2.0, 2.0, 2.0], + [30.0, 30.0, 30.0, 30.0, 30.0], ) levels = c.trace(1.0) diff --git a/chaco/tests/test_datarange_1d.py b/chaco/tests/test_datarange_1d.py index 2a9d79926..c8e4570e0 100644 --- a/chaco/tests/test_datarange_1d.py +++ b/chaco/tests/test_datarange_1d.py @@ -254,7 +254,9 @@ def custom_func(low, high, margin, tight_bounds): assert_equal(margin, 1.0) return -999.0, 999.0 - r = DataRange1D(tight_bounds=False, margin=1.0, bounds_func=custom_func) + r = DataRange1D( + tight_bounds=False, margin=1.0, bounds_func=custom_func + ) ary = arange(10.0) ds = ArrayDataSource(ary) r.sources.append(ds) diff --git a/chaco/tests/test_datarange_2d.py b/chaco/tests/test_datarange_2d.py index 721d7baf0..f3fba9a7a 100644 --- a/chaco/tests/test_datarange_2d.py +++ b/chaco/tests/test_datarange_2d.py @@ -173,7 +173,9 @@ def test_clip_data(self): assert_equal( r.clip_data(ary), array([[16.0, 12.0], [18.0, 16.0], [20.0, 20.0]]) ) - assert_equal(r.clip_data(ary[::-1]), array([[20, 20], [18, 16], [16, 12]])) + assert_equal( + r.clip_data(ary[::-1]), array([[20, 20], [18, 16], [16, 12]]) + ) def test_mask_data(self): r = DataRange2D(low=[2.0, 5.0], high=[10.0, 18.0]) diff --git a/chaco/tests/test_discrete_colormapper.py b/chaco/tests/test_discrete_colormapper.py index d7d844e52..572a3b5dc 100644 --- a/chaco/tests/test_discrete_colormapper.py +++ b/chaco/tests/test_discrete_colormapper.py @@ -120,9 +120,13 @@ def colormap_function(range, **traits): "green": [(0.0, 0, 0), (1.0, 1.0, 1.0)], "blue": [(0.0, 0, 0), (1.0, 1.0, 1.0)], } - return ColorMapper.from_segment_map(_gray_data, range=range, **traits) + return ColorMapper.from_segment_map( + _gray_data, range=range, **traits + ) - self.colormap = DiscreteColorMapper.from_colormap(colormap_function, steps=5) + self.colormap = DiscreteColorMapper.from_colormap( + colormap_function, steps=5 + ) gray_data = empty(shape=(5, 4)) gray_data[:] = array([0.0, 0.25, 0.5, 0.75, 1.0]).reshape(5, 1) diff --git a/chaco/tests/test_function_data_source.py b/chaco/tests/test_function_data_source.py index 35ce92e10..ae73c8c2b 100644 --- a/chaco/tests/test_function_data_source.py +++ b/chaco/tests/test_function_data_source.py @@ -32,33 +32,53 @@ def test_basic_setup(self): def test_set_data(self): with self.assertRaises(RuntimeError): - self.data_source.set_data(lambda low, high: linspace(low, high, 101)) + self.data_source.set_data( + lambda low, high: linspace(low, high, 101) + ) def test_range_high_changed(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) + self.data_source.data_range = DataRange1D( + low_setting=0.0, high_setting=1.0 + ) - with self.assertTraitChanges(self.data_source, "data_changed", count=1): + with self.assertTraitChanges( + self.data_source, "data_changed", count=1 + ): self.data_source.data_range.high_setting = 2.0 - assert_array_equal(linspace(0.0, 2.0, 101) ** 2, self.data_source.get_data()) + assert_array_equal( + linspace(0.0, 2.0, 101) ** 2, self.data_source.get_data() + ) def test_range_low_changed(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) + self.data_source.data_range = DataRange1D( + low_setting=0.0, high_setting=1.0 + ) - with self.assertTraitChanges(self.data_source, "data_changed", count=1): + with self.assertTraitChanges( + self.data_source, "data_changed", count=1 + ): self.data_source.data_range.low_setting = -1.0 - assert_array_equal(linspace(-1.0, 1.0, 101) ** 2, self.data_source.get_data()) + assert_array_equal( + linspace(-1.0, 1.0, 101) ** 2, self.data_source.get_data() + ) def test_range_data_range_changed(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) + self.data_source.data_range = DataRange1D( + low_setting=0.0, high_setting=1.0 + ) - with self.assertTraitChanges(self.data_source, "data_changed", count=1): + with self.assertTraitChanges( + self.data_source, "data_changed", count=1 + ): self.data_source.data_range = DataRange1D( low_setting=-2.0, high_setting=2.0 ) - assert_array_equal(linspace(-2.0, 2.0, 101) ** 2, self.data_source.get_data()) + assert_array_equal( + linspace(-2.0, 2.0, 101) ** 2, self.data_source.get_data() + ) def test_set_mask(self): mymask = array([i % 2 for i in range(101)], dtype=bool) @@ -71,9 +91,13 @@ def test_remove_mask(self): self.data_source.remove_mask() def test_get_data(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) + self.data_source.data_range = DataRange1D( + low_setting=0.0, high_setting=1.0 + ) - assert_array_equal(linspace(0.0, 1.0, 101) ** 2, self.data_source.get_data()) + assert_array_equal( + linspace(0.0, 1.0, 101) ** 2, self.data_source.get_data() + ) def test_get_data_no_data(self): self.data_source = FunctionDataSource() @@ -81,26 +105,34 @@ def test_get_data_no_data(self): assert_array_equal(self.data_source.get_data(), array([], dtype=float)) def test_get_data_mask(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=1.0) + self.data_source.data_range = DataRange1D( + low_setting=0.0, high_setting=1.0 + ) data, mask = self.data_source.get_data_mask() assert_array_equal(data, linspace(0.0, 1.0, 101) ** 2) assert_array_equal(mask, ones(shape=101, dtype=bool)) def test_bounds(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=2.0) + self.data_source.data_range = DataRange1D( + low_setting=0.0, high_setting=2.0 + ) bounds = self.data_source.get_bounds() self.assertEqual(bounds, (0.0, 4.0)) @unittest.skip("default sort_order is ascending, which isn't right") def test_bounds_non_monotone(self): - self.data_source.data_range = DataRange1D(low_setting=-2.0, high_setting=2.0) + self.data_source.data_range = DataRange1D( + low_setting=-2.0, high_setting=2.0 + ) bounds = self.data_source.get_bounds() self.assertEqual(bounds, (0.0, 4.0)) def test_data_size(self): - self.data_source.data_range = DataRange1D(low_setting=0.0, high_setting=2.0) + self.data_source.data_range = DataRange1D( + low_setting=0.0, high_setting=2.0 + ) self.assertEqual(101, self.data_source.get_size()) diff --git a/chaco/tests/test_grid_data_source.py b/chaco/tests/test_grid_data_source.py index 42d269d3f..698f45174 100644 --- a/chaco/tests/test_grid_data_source.py +++ b/chaco/tests/test_grid_data_source.py @@ -24,7 +24,9 @@ def test_empty(self): self.assertEqual(data_source.sort_order, ("none", "none")) self.assertEqual(data_source.index_dimension, "image") self.assertEqual(data_source.value_dimension, "scalar") - self.assertEqual(data_source.metadata, {"selections": [], "annotations": []}) + self.assertEqual( + data_source.metadata, {"selections": [], "annotations": []} + ) xdata, ydata = data_source.get_data() assert_array_equal(xdata.get_data(), array([])) assert_array_equal(ydata.get_data(), array([])) @@ -69,9 +71,13 @@ def test_metadata(self): ) def test_metadata_changed(self): - with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + with self.assertTraitChanges( + self.data_source, "metadata_changed", count=1 + ): self.data_source.metadata = {"new_metadata": True} def test_metadata_items_changed(self): - with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + with self.assertTraitChanges( + self.data_source, "metadata_changed", count=1 + ): self.data_source.metadata["new_metadata"] = True diff --git a/chaco/tests/test_grid_mapper.py b/chaco/tests/test_grid_mapper.py index fbae180c1..534ae60b7 100644 --- a/chaco/tests/test_grid_mapper.py +++ b/chaco/tests/test_grid_mapper.py @@ -19,7 +19,9 @@ def test_basic(self): self.mapper.y_low_pos = 0 self.mapper.y_high_pos = 10 result = self.mapper.map_screen(transpose((self.x_ary, self.y_ary))) - assert_equal(result, [(50, 0), (60, 0), (70, 5), (80, 5), (90, 10), (100, 10)]) + assert_equal( + result, [(50, 0), (60, 0), (70, 5), (80, 5), (90, 10), (100, 10)] + ) def test_map_screen_scalar(self): self.mapper.x_low_pos = 50 @@ -34,7 +36,9 @@ def test_map_data(self): self.mapper.x_high_pos = 100 self.mapper.y_low_pos = 0 self.mapper.y_high_pos = 10 - screen_ary = array([(50, 0), (60, 0), (70, 5), (80, 5), (90, 10), (100, 10)]) + screen_ary = array( + [(50, 0), (60, 0), (70, 5), (80, 5), (90, 10), (100, 10)] + ) result = self.mapper.map_data(screen_ary) assert_equal(result, transpose((self.x_ary, self.y_ary))) diff --git a/chaco/tests/test_hittest.py b/chaco/tests/test_hittest.py index 579bac2de..92f86814a 100644 --- a/chaco/tests/test_hittest.py +++ b/chaco/tests/test_hittest.py @@ -4,7 +4,13 @@ import unittest from numpy import arange, array, linalg -from chaco.api import ArrayDataSource, ArrayPlotData, Plot, LinearMapper, DataRange1D +from chaco.api import ( + ArrayDataSource, + ArrayPlotData, + Plot, + LinearMapper, + DataRange1D, +) class HittestTestCase(unittest.TestCase): diff --git a/chaco/tests/test_image_data.py b/chaco/tests/test_image_data.py index 2f1b442d4..bb2940a7d 100644 --- a/chaco/tests/test_image_data.py +++ b/chaco/tests/test_image_data.py @@ -37,7 +37,9 @@ def test_basic_setup(self): def test_set_data(self): new_array = arange(0, 30, 2).reshape(5, 3, 1) - with self.assertTraitChanges(self.data_source, "data_changed", count=1): + with self.assertTraitChanges( + self.data_source, "data_changed", count=1 + ): self.data_source.set_data(new_array) assert_array_equal(new_array, self.data_source.data) @@ -133,9 +135,13 @@ def test_metadata(self): ) def test_metadata_changed(self): - with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + with self.assertTraitChanges( + self.data_source, "metadata_changed", count=1 + ): self.data_source.metadata = {"new_metadata": True} def test_metadata_items_changed(self): - with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + with self.assertTraitChanges( + self.data_source, "metadata_changed", count=1 + ): self.data_source.metadata["new_metadata"] = True diff --git a/chaco/tests/test_image_plot.py b/chaco/tests/test_image_plot.py index b1a56225c..6b9dd8635 100644 --- a/chaco/tests/test_image_plot.py +++ b/chaco/tests/test_image_plot.py @@ -76,7 +76,10 @@ def rendered_image_result(image, filename=None, **plot_kwargs): data_source = ImageData(data=image) index, index_mapper = get_image_index_and_mapper(image) renderer = ImagePlot( - value=data_source, index=index, index_mapper=index_mapper, **plot_kwargs + value=data_source, + index=index, + index_mapper=index_mapper, + **plot_kwargs ) orientation = plot_kwargs.get("orientation", "h") return image_from_renderer(renderer, orientation) @@ -94,7 +97,9 @@ def calculate_rms(image_result, expected_image): abs_diff_image = abs(np.int_(expected_image) - np.int_(image_result)) histogram = np.bincount(abs_diff_image.ravel(), minlength=256) - sum_of_squares = np.sum(np.int64(histogram) * np.arange(len(histogram)) ** 2) + sum_of_squares = np.sum( + np.int64(histogram) * np.arange(len(histogram)) ** 2 + ) rms = np.sqrt(float(sum_of_squares) / num_values) return rms @@ -144,7 +149,9 @@ def test_horizontal_bottom_right(self): def test_vertical_top_left(self): # Vertical orientation with top left origin renders transposed image. - self.verify_result_image(RGB, IMAGE.T, origin="top left", orientation="v") + self.verify_result_image( + RGB, IMAGE.T, origin="top left", orientation="v" + ) def test_vertical_bottom_left(self): # Vertical orientation with bottom left origin renders transposed image diff --git a/chaco/tests/test_jitterplot.py b/chaco/tests/test_jitterplot.py index 206e397d3..95f113ef1 100644 --- a/chaco/tests/test_jitterplot.py +++ b/chaco/tests/test_jitterplot.py @@ -5,7 +5,12 @@ from enable.compiled_path import CompiledPath # Chaco imports -from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext +from chaco.api import ( + ArrayDataSource, + DataRange1D, + LinearMapper, + PlotGraphicsContext, +) from chaco.jitterplot import JitterPlot @@ -26,7 +31,9 @@ def setUp(self): def test_scatter_1d(self): self.assertEqual(self.scatterplot.origin, "bottom left") self.assertIsNone(self.scatterplot.x_mapper) - self.assertEqual(self.scatterplot.y_mapper, self.scatterplot.index_mapper) + self.assertEqual( + self.scatterplot.y_mapper, self.scatterplot.index_mapper + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -37,7 +44,9 @@ def test_scatter_1d_horizontal(self): self.scatterplot.orientation = "h" self.assertEqual(self.scatterplot.origin, "bottom left") - self.assertEqual(self.scatterplot.x_mapper, self.scatterplot.index_mapper) + self.assertEqual( + self.scatterplot.x_mapper, self.scatterplot.index_mapper + ) self.assertIsNone(self.scatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -50,7 +59,9 @@ def test_scatter_1d_flipped(self): self.assertEqual(self.scatterplot.origin, "top left") self.assertIsNone(self.scatterplot.x_mapper) - self.assertEqual(self.scatterplot.y_mapper, self.scatterplot.index_mapper) + self.assertEqual( + self.scatterplot.y_mapper, self.scatterplot.index_mapper + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -62,7 +73,9 @@ def test_scatter_1d_horizontal_flipped(self): self.scatterplot.orientation = "h" self.assertEqual(self.scatterplot.origin, "bottom right") - self.assertEqual(self.scatterplot.x_mapper, self.scatterplot.index_mapper) + self.assertEqual( + self.scatterplot.x_mapper, self.scatterplot.index_mapper + ) self.assertIsNone(self.scatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -104,10 +117,14 @@ def test_scatter_1d_map_data_horizontal(self): def test_scatter_1d_map_data_flipped(self): self.scatterplot.direction = "flipped" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), array([4.5, 9.0])) + assert_almost_equal( + self.scatterplot.map_data(points), array([4.5, 9.0]) + ) def test_scatter_1d_map_data_horizontal_flipped(self): self.scatterplot.direction = "flipped" self.scatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), array([9.0, 4.5])) + assert_almost_equal( + self.scatterplot.map_data(points), array([9.0, 4.5]) + ) diff --git a/chaco/tests/test_line_scatterplot.py b/chaco/tests/test_line_scatterplot.py index 02e00d7de..58aa5b8b0 100644 --- a/chaco/tests/test_line_scatterplot.py +++ b/chaco/tests/test_line_scatterplot.py @@ -6,7 +6,12 @@ from traits.testing.unittest_tools import UnittestTools # Chaco imports -from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext +from chaco.api import ( + ArrayDataSource, + DataRange1D, + LinearMapper, + PlotGraphicsContext, +) from chaco.line_scatterplot_1d import LineScatterPlot1D @@ -31,7 +36,8 @@ def test_linescatter_1d(self): self.linescatterplot.y_mapper, self.linescatterplot.index_mapper ) self.assertIs( - self.linescatterplot.index_range, self.linescatterplot.index_mapper.range + self.linescatterplot.index_range, + self.linescatterplot.index_mapper.range, ) gc = PlotGraphicsContext(self.size) @@ -105,23 +111,31 @@ def test_linescatter_1d_line_style(self): def test_linescatter_1d_map_data(self): points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.linescatterplot.map_data(points), array([4.5, 0])) + assert_almost_equal( + self.linescatterplot.map_data(points), array([4.5, 0]) + ) def test_linescatter_1d_map_data_horizontal(self): self.linescatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.linescatterplot.map_data(points), array([0, 4.5])) + assert_almost_equal( + self.linescatterplot.map_data(points), array([0, 4.5]) + ) def test_linescatter_1d_map_data_flipped(self): self.linescatterplot.direction = "flipped" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.linescatterplot.map_data(points), array([4.5, 9.0])) + assert_almost_equal( + self.linescatterplot.map_data(points), array([4.5, 9.0]) + ) def test_linescatter_1d_map_data_horizontal_flipped(self): self.linescatterplot.direction = "flipped" self.linescatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.linescatterplot.map_data(points), array([9.0, 4.5])) + assert_almost_equal( + self.linescatterplot.map_data(points), array([9.0, 4.5]) + ) def test_linescatter_1d_selection(self): self.linescatterplot.index.metadata["selections"] = [ @@ -165,7 +179,9 @@ def test_linescatter_1d_set_index_range(self): def test_linescatter_1d_set_index_mapper_notifies_index_range(self): new_range = DataRange1D(low=0.42, high=1.42) - with self.assertTraitChanges(self.linescatterplot, "index_range", count=1): + with self.assertTraitChanges( + self.linescatterplot, "index_range", count=1 + ): self.linescatterplot.index_mapper = LinearMapper(range=new_range) self.assertIs(self.linescatterplot.index_range, new_range) diff --git a/chaco/tests/test_linearmapper.py b/chaco/tests/test_linearmapper.py index 60a4166e3..f587a636c 100644 --- a/chaco/tests/test_linearmapper.py +++ b/chaco/tests/test_linearmapper.py @@ -70,7 +70,9 @@ def test_update_screen_bounds_stretch_data(self): mapper.screen_bounds = (50.0, 100.0) mapper.screen_bounds = (40.0, 120.0) result = mapper.map_screen(ary) - assert_array_almost_equal(result, array([40.0, 56.0, 72.0, 88.0, 104.0, 120.0])) + assert_array_almost_equal( + result, array([40.0, 56.0, 72.0, 88.0, 104.0, 120.0]) + ) def test_update_screen_bounds_dont_stretch_data(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -81,7 +83,9 @@ def test_update_screen_bounds_dont_stretch_data(self): mapper.screen_bounds = (50.0, 100.0) mapper.screen_bounds = (40.0, 120.0) result = mapper.map_screen(ary) - assert_array_almost_equal(result, array([40.0, 50.0, 60.0, 70.0, 80.0, 90.0])) + assert_array_almost_equal( + result, array([40.0, 50.0, 60.0, 70.0, 80.0, 90.0]) + ) def test_reversed_update_screen_bounds_stretch_data(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -92,7 +96,9 @@ def test_reversed_update_screen_bounds_stretch_data(self): mapper.screen_bounds = (100.0, 0.0) mapper.screen_bounds = (120.0, -10.0) result = mapper.map_screen(ary) - assert_array_almost_equal(result, array([120.0, 94.0, 68.0, 42.0, 16.0, -10.0])) + assert_array_almost_equal( + result, array([120.0, 94.0, 68.0, 42.0, 16.0, -10.0]) + ) def test_reversed_update_screen_bounds_dont_stretch_data(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -103,7 +109,9 @@ def test_reversed_update_screen_bounds_dont_stretch_data(self): mapper.screen_bounds = (100.0, 0.0) mapper.screen_bounds = (120.0, -10.0) result = mapper.map_screen(ary) - assert_array_almost_equal(result, array([120.0, 100.0, 80.0, 60.0, 40.0, 20.0])) + assert_array_almost_equal( + result, array([120.0, 100.0, 80.0, 60.0, 40.0, 20.0]) + ) def test_update_low_pos_stretch_data(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -202,7 +210,9 @@ def test_update_low_pos_stretch_data_with_reverse(self): mapper.screen_bounds = (50.0, 100.0) mapper.low_pos = 150.0 result = mapper.map_screen(ary) - assert_array_almost_equal(result, array([150, 140, 130, 120, 110, 100])) + assert_array_almost_equal( + result, array([150, 140, 130, 120, 110, 100]) + ) def test_update_low_pos_dont_stretch_data_with_reverse(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -213,7 +223,9 @@ def test_update_low_pos_dont_stretch_data_with_reverse(self): mapper.screen_bounds = (50.0, 100.0) mapper.low_pos = 150.0 result = mapper.map_screen(ary) - assert_array_almost_equal(result, array([150, 160, 170, 180, 190, 200])) + assert_array_almost_equal( + result, array([150, 160, 170, 180, 190, 200]) + ) def test_update_high_pos_stretch_data_with_reverse(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -246,7 +258,9 @@ def test_update_low_pos_stretch_data_with_zero(self): mapper.screen_bounds = (50.0, 100.0) mapper.low_pos = 100.0 result = mapper.map_screen(ary) - assert_array_almost_equal(result, array([100, 100, 100, 100, 100, 100])) + assert_array_almost_equal( + result, array([100, 100, 100, 100, 100, 100]) + ) def test_update_low_pos_dont_stretch_data_with_zero(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) @@ -257,7 +271,9 @@ def test_update_low_pos_dont_stretch_data_with_zero(self): mapper.screen_bounds = (50.0, 100.0) mapper.low_pos = 100.0 result = mapper.map_screen(ary) - assert_array_almost_equal(result, array([100, 100, 100, 100, 100, 100])) + assert_array_almost_equal( + result, array([100, 100, 100, 100, 100, 100]) + ) def test_update_high_pos_stretch_data_with_zero(self): ary = array([5.0, 6.0, 7.0, 8.0, 9.0, 10.0]) diff --git a/chaco/tests/test_multi_array_data_source.py b/chaco/tests/test_multi_array_data_source.py index c6a441152..854309ae2 100644 --- a/chaco/tests/test_multi_array_data_source.py +++ b/chaco/tests/test_multi_array_data_source.py @@ -35,7 +35,9 @@ def test_basic_setup(self): def test_set_data(self): new_array = arange(0, 40, 2).reshape(10, 2) - with self.assertTraitChanges(self.data_source, "data_changed", count=1): + with self.assertTraitChanges( + self.data_source, "data_changed", count=1 + ): self.data_source.set_data(new_array) assert_array_equal(new_array, self.data_source._data) @@ -51,7 +53,9 @@ def test_get_data_axes(self): def test_get_data_no_data(self): data_source = MultiArrayDataSource() - assert_array_equal(data_source.get_data(), empty(shape=(0, 1), dtype=float)) + assert_array_equal( + data_source.get_data(), empty(shape=(0, 1), dtype=float) + ) def test_get_data_mask(self): data, mask = self.data_source.get_data_mask() @@ -130,10 +134,14 @@ def test_metadata(self): @unittest.skip("change handler missing from class") def test_metadata_changed(self): - with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + with self.assertTraitChanges( + self.data_source, "metadata_changed", count=1 + ): self.data_source.metadata = {"new_metadata": True} @unittest.skip("change handler missing from class") def test_metadata_items_changed(self): - with self.assertTraitChanges(self.data_source, "metadata_changed", count=1): + with self.assertTraitChanges( + self.data_source, "metadata_changed", count=1 + ): self.data_source.metadata["new_metadata"] = True diff --git a/chaco/tests/test_plot.py b/chaco/tests/test_plot.py index 704441065..b1552c716 100644 --- a/chaco/tests/test_plot.py +++ b/chaco/tests/test_plot.py @@ -68,7 +68,9 @@ def test_segment_plot_color_width(self): w = arange(3, 8) data = ArrayPlotData(x=x, y=y, c=c, w=w) plot = Plot(data) - plot.plot(("x", "y", "c", "w"), "cmap_segment", color_mapper=viridis)[0] + plot.plot(("x", "y", "c", "w"), "cmap_segment", color_mapper=viridis)[ + 0 + ] plot.do_layout((250, 250)) gc = PlotGraphicsContext((250, 250)) diff --git a/chaco/tests/test_plotcontainer.py b/chaco/tests/test_plotcontainer.py index bb39267bb..18f62f451 100644 --- a/chaco/tests/test_plotcontainer.py +++ b/chaco/tests/test_plotcontainer.py @@ -88,13 +88,17 @@ def test_resizable_component(self): self.assert_tuple(component.position, (0.0, 0.0)) self.assert_tuple(component.bounds, (200.0, 300.0)) - comp2 = PlotComponent(resizable="h", position=[10, 20], bounds=[100, 150]) + comp2 = PlotComponent( + resizable="h", position=[10, 20], bounds=[100, 150] + ) container.add(comp2) container.do_layout() self.assert_tuple(comp2.position, (0.0, 20.0)) self.assert_tuple(comp2.bounds, (200.0, 150.0)) - comp3 = PlotComponent(resizable="v", position=[30, 40], bounds=[100, 150]) + comp3 = PlotComponent( + resizable="v", position=[30, 40], bounds=[100, 150] + ) container.add(comp3) container.do_layout() self.assert_tuple(comp3.position, (30.0, 0.0)) @@ -207,7 +211,9 @@ def test_halign(self): self.assertEqual(comp1.position, [100, 0]) def test_fit_components(self): - container = VPlotContainer(bounds=[200, 300], resizable="v", fit_components="v") + container = VPlotContainer( + bounds=[200, 300], resizable="v", fit_components="v" + ) comp1 = StaticPlotComponent([50, 100], padding=5) comp2 = StaticPlotComponent([50, 120], padding=5) container.add(comp1) diff --git a/chaco/tests/test_scatterplot_1d.py b/chaco/tests/test_scatterplot_1d.py index 6b9e6db56..a94efa271 100644 --- a/chaco/tests/test_scatterplot_1d.py +++ b/chaco/tests/test_scatterplot_1d.py @@ -7,7 +7,12 @@ from traits.testing.unittest_tools import UnittestTools # Chaco imports -from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext +from chaco.api import ( + ArrayDataSource, + DataRange1D, + LinearMapper, + PlotGraphicsContext, +) from chaco.scatterplot_1d import ScatterPlot1D @@ -28,8 +33,12 @@ def setUp(self): def test_scatter_1d(self): self.assertEqual(self.scatterplot.origin, "bottom left") self.assertIsNone(self.scatterplot.x_mapper) - self.assertEqual(self.scatterplot.y_mapper, self.scatterplot.index_mapper) - self.assertIs(self.scatterplot.index_range, self.scatterplot.index_mapper.range) + self.assertEqual( + self.scatterplot.y_mapper, self.scatterplot.index_mapper + ) + self.assertIs( + self.scatterplot.index_range, self.scatterplot.index_mapper.range + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -40,7 +49,9 @@ def test_scatter_1d_horizontal(self): self.scatterplot.orientation = "h" self.assertEqual(self.scatterplot.origin, "bottom left") - self.assertEqual(self.scatterplot.x_mapper, self.scatterplot.index_mapper) + self.assertEqual( + self.scatterplot.x_mapper, self.scatterplot.index_mapper + ) self.assertIsNone(self.scatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -53,7 +64,9 @@ def test_scatter_1d_flipped(self): self.assertEqual(self.scatterplot.origin, "top left") self.assertIsNone(self.scatterplot.x_mapper) - self.assertEqual(self.scatterplot.y_mapper, self.scatterplot.index_mapper) + self.assertEqual( + self.scatterplot.y_mapper, self.scatterplot.index_mapper + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.scatterplot) @@ -65,7 +78,9 @@ def test_scatter_1d_horizontal_flipped(self): self.scatterplot.orientation = "h" self.assertEqual(self.scatterplot.origin, "bottom right") - self.assertEqual(self.scatterplot.x_mapper, self.scatterplot.index_mapper) + self.assertEqual( + self.scatterplot.x_mapper, self.scatterplot.index_mapper + ) self.assertIsNone(self.scatterplot.y_mapper) gc = PlotGraphicsContext(self.size) @@ -107,13 +122,17 @@ def test_scatter_1d_map_data_horizontal(self): def test_scatter_1d_map_data_flipped(self): self.scatterplot.direction = "flipped" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), array([4.5, 9.0])) + assert_almost_equal( + self.scatterplot.map_data(points), array([4.5, 9.0]) + ) def test_scatter_1d_map_data_horizontal_flipped(self): self.scatterplot.direction = "flipped" self.scatterplot.orientation = "h" points = array([[0, 124.5], [124.5, 0]]) - assert_almost_equal(self.scatterplot.map_data(points), array([9.0, 4.5])) + assert_almost_equal( + self.scatterplot.map_data(points), array([9.0, 4.5]) + ) def test_scatter_1d_selection(self): # select a single point diff --git a/chaco/tests/test_serializable.py b/chaco/tests/test_serializable.py index af17f38e5..d41ddc84d 100644 --- a/chaco/tests/test_serializable.py +++ b/chaco/tests/test_serializable.py @@ -19,7 +19,9 @@ def compare_traits(self, a, b, trait_names=None): o1 = getattr(a, name) o2 = getattr(b, name) if isinstance(o1, list) or isinstance(o1, tuple): - raise RuntimeError("Warning: Cowardly refusing to do deep compares") + raise RuntimeError( + "Warning: Cowardly refusing to do deep compares" + ) else: self.assertTrue(o1 == o2) diff --git a/chaco/tests/test_speedups.py b/chaco/tests/test_speedups.py index 76114d421..c9bc54b58 100644 --- a/chaco/tests/test_speedups.py +++ b/chaco/tests/test_speedups.py @@ -39,12 +39,21 @@ def test_masked(self): value_mask = zeros(11, dtype=bool) value_mask[4:8] = 1 - points, selection = self.func(index, 0, 10, value, 0, 1, index_mask=index_mask) + points, selection = self.func( + index, 0, 10, value, 0, 1, index_mask=index_mask + ) desired = array([[2, 3, 4, 5], [0.2, 0.3, 0.4, 0.5]]).T assert_close(desired, points) points, selection = self.func( - index, 0, 10, value, 0, 1, index_mask=index_mask, value_mask=value_mask + index, + 0, + 10, + value, + 0, + 1, + index_mask=index_mask, + value_mask=value_mask, ) desired = array([[4, 0.4], [5, 0.5]]) assert_close(desired, points) diff --git a/chaco/tests/test_text_plot_1d.py b/chaco/tests/test_text_plot_1d.py index 06d768d85..2d07b8156 100644 --- a/chaco/tests/test_text_plot_1d.py +++ b/chaco/tests/test_text_plot_1d.py @@ -6,7 +6,12 @@ from traits.testing.unittest_tools import UnittestTools # Chaco imports -from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext +from chaco.api import ( + ArrayDataSource, + DataRange1D, + LinearMapper, + PlotGraphicsContext, +) from chaco.text_plot_1d import TextPlot1D @@ -43,7 +48,9 @@ def test_text_1d(self): self.assertEqual(self.textplot.origin, "bottom left") self.assertIsNone(self.textplot.x_mapper) self.assertEqual(self.textplot.y_mapper, self.textplot.index_mapper) - self.assertIs(self.textplot.index_range, self.textplot.index_mapper.range) + self.assertIs( + self.textplot.index_range, self.textplot.index_mapper.range + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.textplot) diff --git a/chaco/tests/text_plot_test_case.py b/chaco/tests/text_plot_test_case.py index 6ba414c3f..a43d6d7f3 100644 --- a/chaco/tests/text_plot_test_case.py +++ b/chaco/tests/text_plot_test_case.py @@ -3,7 +3,12 @@ from numpy import alltrue, arange, array # Chaco imports -from chaco.api import ArrayDataSource, DataRange1D, LinearMapper, PlotGraphicsContext +from chaco.api import ( + ArrayDataSource, + DataRange1D, + LinearMapper, + PlotGraphicsContext, +) from chaco.text_plot import TextPlot @@ -38,8 +43,12 @@ def test_text(self): self.assertEqual(self.text_plot.origin, "bottom left") self.assertEqual(self.text_plot.x_mapper, self.text_plot.index_mapper) self.assertEqual(self.text_plot.y_mapper, self.text_plot.value_mapper) - self.assertIs(self.text_plot.index_range, self.text_plot.index_mapper.range) - self.assertIs(self.text_plot.value_range, self.text_plot.value_mapper.range) + self.assertIs( + self.text_plot.index_range, self.text_plot.index_mapper.range + ) + self.assertIs( + self.text_plot.value_range, self.text_plot.value_mapper.range + ) gc = PlotGraphicsContext(self.size) gc.render_component(self.text_plot) diff --git a/chaco/tests_with_backend/test_2d_case.py b/chaco/tests_with_backend/test_2d_case.py index 8977b6dd0..f90c629a1 100644 --- a/chaco/tests_with_backend/test_2d_case.py +++ b/chaco/tests_with_backend/test_2d_case.py @@ -80,21 +80,27 @@ def test_process_2d_bounds_cell_plot(self): # axis are used to create equally spaced intervals. # The size of the bounds must be the same as the data array, or this # sill raise a ValueError - xbounds, ybounds = np.meshgrid(np.arange(width + 1), np.arange(height + 1)) + xbounds, ybounds = np.meshgrid( + np.arange(width + 1), np.arange(height + 1) + ) xs = plot._process_2d_bounds(xbounds, array_data, 1, cell_plot=True) self.assertEqual(xs.shape[0], width + 1) self.assertEqual(xs[0], xbounds[0, 0]) self.assertEqual(xs[-1], xbounds[0, -1]) with assert_raises(ValueError): - plot._process_2d_bounds(xbounds[:, :5], array_data, 1, cell_plot=True) + plot._process_2d_bounds( + xbounds[:, :5], array_data, 1, cell_plot=True + ) ys = plot._process_2d_bounds(ybounds, array_data, 0, cell_plot=True) self.assertEqual(ys.shape[0], height + 1) self.assertEqual(ys[0], ybounds[0, 0]) self.assertEqual(ys[-1], ybounds[-1, 0]) with assert_raises(ValueError): - plot._process_2d_bounds(ybounds[:5, :], array_data, 0, cell_plot=True) + plot._process_2d_bounds( + ybounds[:5, :], array_data, 0, cell_plot=True + ) def test_process_2d_bounds_vertex_data(self): # behavior: _process_2d_bounds accepts all possible ways to set x and y @@ -144,11 +150,15 @@ def test_process_2d_bounds_vertex_data(self): self.assertEqual(xs[0], xbounds[0, 0]) self.assertEqual(xs[-1], xbounds[0, -1]) with assert_raises(ValueError): - plot._process_2d_bounds(xbounds[:, :5], array_data, 1, cell_plot=False) + plot._process_2d_bounds( + xbounds[:, :5], array_data, 1, cell_plot=False + ) ys = plot._process_2d_bounds(ybounds, array_data, 0, cell_plot=False) self.assertEqual(ys.shape[0], height) self.assertEqual(ys[0], ybounds[0, 0]) self.assertEqual(ys[-1], ybounds[-1, 0]) with assert_raises(ValueError): - plot._process_2d_bounds(ybounds[:5, :], array_data, 0, cell_plot=False) + plot._process_2d_bounds( + ybounds[:5, :], array_data, 0, cell_plot=False + ) diff --git a/chaco/text_plot.py b/chaco/text_plot.py index 6aae72642..715924aae 100644 --- a/chaco/text_plot.py +++ b/chaco/text_plot.py @@ -74,7 +74,8 @@ def _compute_labels(self, gc): for text in self.text.get_data() ] self._label_box_cache = [ - array(label.get_bounding_box(gc), float) for label in self._label_cache + array(label.get_bounding_box(gc), float) + for label in self._label_cache ] self._label_cache_valid = True @@ -123,7 +124,9 @@ def _render(self, gc, pts): ] boxes = [ label - for label, mask in zip(self._label_box_cache, self._cached_point_mask) + for label, mask in zip( + self._label_box_cache, self._cached_point_mask + ) if mask ] offset = empty((2,), float) diff --git a/chaco/text_plot_1d.py b/chaco/text_plot_1d.py index bd4c5ffc2..9b8dd5b23 100644 --- a/chaco/text_plot_1d.py +++ b/chaco/text_plot_1d.py @@ -81,7 +81,8 @@ def _compute_labels(self, gc): for text in self.value.get_data() ] self._label_box_cache = [ - array(label.get_bounding_box(gc), float) for label in self._label_cache + array(label.get_bounding_box(gc), float) + for label in self._label_cache ] self._label_cache_valid = True diff --git a/chaco/ticks.py b/chaco/ticks.py index 021bbcf36..7c1405263 100644 --- a/chaco/ticks.py +++ b/chaco/ticks.py @@ -179,10 +179,18 @@ def get_ticks( ): if interval == "auto": # for the default interval, generate a smaller tick interval - interval = auto_interval(0, auto_interval(data_low, data_high), max_ticks=5) + interval = auto_interval( + 0, auto_interval(data_low, data_high), max_ticks=5 + ) return super(MinorTickGenerator, self).get_ticks( - data_low, data_high, bounds_low, bounds_high, interval, use_endpoints, scale + data_low, + data_high, + bounds_low, + bounds_high, + interval, + use_endpoints, + scale, ) @@ -192,7 +200,12 @@ def get_ticks( def auto_ticks( - data_low, data_high, bound_low, bound_high, tick_interval, use_endpoints=True + data_low, + data_high, + bound_low, + bound_high, + tick_interval, + use_endpoints=True, ): """Finds locations for axis tick marks. @@ -363,7 +376,9 @@ def auto_interval(data_low, data_high, max_ticks=9): # We'll choose from between 2 and 8 tick marks. # Preference is given to more ticks: # Note reverse order and see kludge below... - divisions = arange(max_ticks - 1, 2.0, -1.0) # for max_ticks=9, ( 7, 6, ..., 3 ) + divisions = arange( + max_ticks - 1, 2.0, -1.0 + ) # for max_ticks=9, ( 7, 6, ..., 3 ) # Calculate the intervals for the divisions: candidate_intervals = range / divisions @@ -454,14 +469,21 @@ def tick_intervals(data_low, data_high, intervals): while True: result = interval * factor - if (floor(data_low / result) * result) + (intervals * result) >= data_high: + if (floor(data_low / result) * result) + ( + intervals * result + ) >= data_high: return result index = (index + 1) % 4 interval *= (2.0, 1.25, 2.0, 2.0)[index] def log_auto_ticks( - data_low, data_high, bound_low, bound_high, tick_interval, use_endpoints=True + data_low, + data_high, + bound_low, + bound_high, + tick_interval, + use_endpoints=True, ): """Like auto_ticks(), but for log scales.""" tick_goal = 15 @@ -559,7 +581,9 @@ def calc_bound(end_point, tick_interval, is_upper): end of the axis. """ quotient, remainder = divmod(end_point, tick_interval) - if (remainder == 0.0) or (((tick_interval - remainder) / tick_interval) < 0.00001): + if (remainder == 0.0) or ( + ((tick_interval - remainder) / tick_interval) < 0.00001 + ): return end_point c1 = (quotient + 1.0) * tick_interval diff --git a/chaco/tools/api.py b/chaco/tools/api.py index 2354c7e1f..5ec166c43 100644 --- a/chaco/tools/api.py +++ b/chaco/tools/api.py @@ -25,7 +25,12 @@ from .scatter_inspector import ScatterInspector from .select_tool import SelectTool from .simple_inspector import SimpleInspectorTool -from .tool_states import ZoomState, PanState, GroupedToolState, SelectedZoomState +from .tool_states import ( + ZoomState, + PanState, + GroupedToolState, + SelectedZoomState, +) from .tracking_pan_tool import TrackingPanTool from .tracking_zoom import TrackingZoom from .traits_tool import TraitsTool diff --git a/chaco/tools/base_zoom_tool.py b/chaco/tools/base_zoom_tool.py index 80fc6676e..a8b138aef 100644 --- a/chaco/tools/base_zoom_tool.py +++ b/chaco/tools/base_zoom_tool.py @@ -30,7 +30,9 @@ class BaseZoomTool(HasTraits): # bounds. If None, then there is no limit. max_zoom_out_factor = Float(1e5, allow_none=True) - def _zoom_limit_reached(self, orig_low, orig_high, new_low, new_high, mapper=None): + def _zoom_limit_reached( + self, orig_low, orig_high, new_low, new_high, mapper=None + ): """Returns True if the new low and high exceed the maximum zoom limits """ diff --git a/chaco/tools/better_selecting_zoom.py b/chaco/tools/better_selecting_zoom.py index 813fb6fe9..bd3369e7b 100644 --- a/chaco/tools/better_selecting_zoom.py +++ b/chaco/tools/better_selecting_zoom.py @@ -202,11 +202,15 @@ def selecting_mouse_move(self, event): if drawn_aspect > self.aspect_ratio: # Drawn box is wider, so use its height to compute the # restricted width - x2 = x1 + height * self.aspect_ratio * (1 if x2 > x1 else -1) + x2 = x1 + height * self.aspect_ratio * ( + 1 if x2 > x1 else -1 + ) else: # Drawn box is taller, so use its width to compute the # restricted height - y2 = y1 + width / self.aspect_ratio * (1 if y2 > y1 else -1) + y2 = y1 + width / self.aspect_ratio * ( + 1 if y2 > y1 else -1 + ) self._screen_end = (x2, y2) else: self._screen_end = (event.x, event.y) @@ -320,7 +324,9 @@ def _end_select(self, event): event.handled = True return - low, high = self._map_coordinate_box(self._screen_start, self._screen_end) + low, high = self._map_coordinate_box( + self._screen_start, self._screen_end + ) x_range = self._get_x_mapper().range y_range = self._get_y_mapper().range @@ -397,8 +403,12 @@ def _overlay_range(self, component, gc): color = self._get_fill_color() gc.set_fill_color(color) gc.set_stroke_color(self.border_color_) - gc.clip_to_rect(component.x, component.y, component.width, component.height) - gc.draw_rect((lower_left[0], lower_left[1], upper_right[0], upper_right[1])) + gc.clip_to_rect( + component.x, component.y, component.width, component.height + ) + gc.draw_rect( + (lower_left[0], lower_left[1], upper_right[0], upper_right[1]) + ) def _get_fill_color(self): """Get the fill color based on the alpha and the color property""" diff --git a/chaco/tools/better_zoom.py b/chaco/tools/better_zoom.py index 24474c7be..a21c93ab3 100644 --- a/chaco/tools/better_zoom.py +++ b/chaco/tools/better_zoom.py @@ -300,9 +300,13 @@ def _zoom_limit_reached(self, factor, xy_axis): """ if xy_axis == "x": - return not (self.x_min_zoom_factor <= factor <= self.x_max_zoom_factor) + return not ( + self.x_min_zoom_factor <= factor <= self.x_max_zoom_factor + ) else: - return not (self.y_min_zoom_factor <= factor <= self.y_max_zoom_factor) + return not ( + self.y_min_zoom_factor <= factor <= self.y_max_zoom_factor + ) def _zoom_in_mapper(self, mapper, factor): @@ -313,7 +317,9 @@ def _zoom_in_mapper(self, mapper, factor): center = (low + high) / 2.0 new_range = range / factor - mapper.range.set_bounds(low=center - new_range / 2, high=center + new_range / 2) + mapper.range.set_bounds( + low=center - new_range / 2, high=center + new_range / 2 + ) def _get_x_mapper(self): if isinstance(self.component.index_mapper, GridMapper): diff --git a/chaco/tools/cursor_tool.py b/chaco/tools/cursor_tool.py index deac85221..025b90143 100644 --- a/chaco/tools/cursor_tool.py +++ b/chaco/tools/cursor_tool.py @@ -108,7 +108,10 @@ def _draw_marker(self, gc, sx, sy): # This is the fastest method - use one of the kiva built-in markers if hasattr(gc, "draw_marker_at_points") and ( - gc.draw_marker_at_points(points, marker_size, marker.kiva_marker) != 0 + gc.draw_marker_at_points( + points, marker_size, marker.kiva_marker + ) + != 0 ): pass diff --git a/chaco/tools/data_label_tool.py b/chaco/tools/data_label_tool.py index eabbe53b1..3cd5326b6 100644 --- a/chaco/tools/data_label_tool.py +++ b/chaco/tools/data_label_tool.py @@ -45,7 +45,12 @@ def is_draggable(self, x, y): """ if self.component: label = self.component - return x >= label.x and x <= label.x2 and y >= label.y and y <= label.y2 + return ( + x >= label.x + and x <= label.x2 + and y >= label.y + and y <= label.y2 + ) else: return False diff --git a/chaco/tools/drag_tool.py b/chaco/tools/drag_tool.py index dfbfe72d1..2d71835e7 100644 --- a/chaco/tools/drag_tool.py +++ b/chaco/tools/drag_tool.py @@ -5,7 +5,8 @@ import warnings warnings.warn( - "chaco.tools.DragTool has been removed." "Use enable.tools.DragTool instead.", + "chaco.tools.DragTool has been removed." + "Use enable.tools.DragTool instead.", DeprecationWarning, ) diff --git a/chaco/tools/highlight_tool.py b/chaco/tools/highlight_tool.py index a2dbe96bd..bf508a762 100644 --- a/chaco/tools/highlight_tool.py +++ b/chaco/tools/highlight_tool.py @@ -71,7 +71,9 @@ def _highlight(self, event): event.pop() elif hasattr(self.component, "hittest"): - hit_point = self.component.hittest((event.x, event.y), self.threshold) + hit_point = self.component.hittest( + (event.x, event.y), self.threshold + ) index = self.component.index if hit_point is not None: index.metadata[self.metadata_name] = ones( diff --git a/chaco/tools/image_inspector_tool.py b/chaco/tools/image_inspector_tool.py index 7aec63dfa..cb06a24cb 100644 --- a/chaco/tools/image_inspector_tool.py +++ b/chaco/tools/image_inspector_tool.py @@ -72,7 +72,9 @@ def normal_mouse_move(self, event): self.new_value = { "indices": ndx, "data_value": image_data.data[y_index, x_index], - "color_value": plot._cached_mapped_image[y_index, x_index], + "color_value": plot._cached_mapped_image[ + y_index, x_index + ], } else: diff --git a/chaco/tools/lasso_selection.py b/chaco/tools/lasso_selection.py index 6629c0f38..cab3f9209 100644 --- a/chaco/tools/lasso_selection.py +++ b/chaco/tools/lasso_selection.py @@ -166,7 +166,9 @@ def normal_mouse_down(self, event): self.selection_mode = "exclude" else: self.selection_mode = "include" - self.trait_property_changed("disjoint_selections", [], self.disjoint_selections) + self.trait_property_changed( + "disjoint_selections", [], self.disjoint_selections + ) def selecting_left_up(self, event): if self.drag_button == "left": @@ -197,7 +199,9 @@ def selecting_mouse_move(self, event): xform = self.component.get_event_transform(event) event.push_transform(xform, caller=self) new_point = self._map_data(array((event.x, event.y))) - self._active_selection = vstack((self._active_selection, array((new_point,)))) + self._active_selection = vstack( + (self._active_selection, array((new_point,))) + ) self.updated = True if self.incremental_select: self._update_selection() @@ -265,7 +269,9 @@ def _update_selection(self): if self.selection_datasource is None: return - selected_mask = zeros(self.selection_datasource._data.shape, dtype=numpy.bool) + selected_mask = zeros( + self.selection_datasource._data.shape, dtype=numpy.bool + ) data = self._get_data() # Compose the selection mask from the cached selections first, then @@ -292,9 +298,12 @@ def _update_selection(self): selected_mask |= active_selection if sometrue( - selected_mask != self.selection_datasource.metadata[self.metadata_name] + selected_mask + != self.selection_datasource.metadata[self.metadata_name] ): - self.selection_datasource.metadata[self.metadata_name] = selected_mask + self.selection_datasource.metadata[ + self.metadata_name + ] = selected_mask self.selection_changed = True def _map_screen(self, points): @@ -317,11 +326,15 @@ def _map_data(self, point): elif isinstance(self.plot, BaseXYPlot): return self.plot.map_data(point, all_values=True)[:2] else: - raise RuntimeError("LassoSelection only supports BaseXY and Base2D plots") + raise RuntimeError( + "LassoSelection only supports BaseXY and Base2D plots" + ) def _get_data(self): """Returns the datapoints in the plot, as an Nx2 array of (x,y).""" - return column_stack((self.plot.index.get_data(), self.plot.value.get_data())) + return column_stack( + (self.plot.index.get_data(), self.plot.value.get_data()) + ) # ------------------------------------------------------------------------ # Property getter/setters diff --git a/chaco/tools/legend_highlighter.py b/chaco/tools/legend_highlighter.py index 9eafb65cb..7bc77b288 100644 --- a/chaco/tools/legend_highlighter.py +++ b/chaco/tools/legend_highlighter.py @@ -57,7 +57,9 @@ class LegendHighlighter(LegendTool): _selected_renderers = List def normal_left_down(self, event): - if not self.component.visible or not self.component.is_in(event.x, event.y): + if not self.component.visible or not self.component.is_in( + event.x, event.y + ): return plots = get_hit_plots(self.component, event) @@ -70,7 +72,9 @@ def normal_left_down(self, event): self._selected_renderers.append(plot) elif plots: # User in single-select mode. - add_plot = any(plot not in self._selected_renderers for plot in plots) + add_plot = any( + plot not in self._selected_renderers for plot in plots + ) self._selected_renderers = [] if add_plot: self._selected_renderers.extend(plots) diff --git a/chaco/tools/legend_tool.py b/chaco/tools/legend_tool.py index aa1af4e91..dc0acee55 100644 --- a/chaco/tools/legend_tool.py +++ b/chaco/tools/legend_tool.py @@ -28,7 +28,12 @@ def is_draggable(self, x, y): """ if self.component: legend = self.component - return x >= legend.x and x <= legend.x2 and y >= legend.y and y <= legend.y2 + return ( + x >= legend.x + and x <= legend.x2 + and y >= legend.y + and y <= legend.y2 + ) else: return False diff --git a/chaco/tools/line_inspector.py b/chaco/tools/line_inspector.py index d3a438e35..a356a53cd 100644 --- a/chaco/tools/line_inspector.py +++ b/chaco/tools/line_inspector.py @@ -114,7 +114,9 @@ def normal_mouse_move(self, event): if isinstance(plot, BaseXYPlot): if self.write_metadata: if self.inspect_mode == "space": - index_coord, value_coord = self._map_to_data(event.x, event.y) + index_coord, value_coord = self._map_to_data( + event.x, event.y + ) plot.index.metadata[self.metadata_name] = index_coord plot.value.metadata[self.metadata_name] = value_coord else: @@ -127,15 +129,21 @@ def normal_mouse_move(self, event): elif isinstance(plot, Base2DPlot): if self.write_metadata: try: - old_x_data, old_y_data = plot.index.metadata[self.metadata_name] + old_x_data, old_y_data = plot.index.metadata[ + self.metadata_name + ] except: old_x_data, old_y_data = (None, None) if self.inspect_mode == "space": if plot.orientation == "h": - x_coord, y_coord = plot.map_data([(event.x, event.y)])[0] + x_coord, y_coord = plot.map_data( + [(event.x, event.y)] + )[0] else: - y_coord, x_coord = plot.map_data([(event.x, event.y)])[0] + y_coord, x_coord = plot.map_data( + [(event.x, event.y)] + )[0] if self.axis == "index_x": metadata = x_coord, old_y_data elif self.axis == "index_y": diff --git a/chaco/tools/line_segment_tool.py b/chaco/tools/line_segment_tool.py index 6c3eef1ff..fb0e62e4f 100644 --- a/chaco/tools/line_segment_tool.py +++ b/chaco/tools/line_segment_tool.py @@ -159,7 +159,9 @@ def normal_left_down(self, event): if event.control_down: # Delete the point self.points.pop(over) - self.line.points = list(self.component.map_screen(array(self.points))) + self.line.points = list( + self.component.map_screen(array(self.points)) + ) self.request_redraw() else: self.event_state = "dragging" @@ -283,7 +285,10 @@ def overlay(self, component, gc, view_bounds, mode="normal"): if draw_func: with gc: gc.clip_to_rect( - component.x, component.y, component.width - 1, component.height - 1 + component.x, + component.y, + component.width - 1, + component.height - 1, ) draw_func(gc) diff --git a/chaco/tools/pan_tool.py b/chaco/tools/pan_tool.py index 3cbbb9d46..db055009a 100644 --- a/chaco/tools/pan_tool.py +++ b/chaco/tools/pan_tool.py @@ -189,7 +189,9 @@ def panning_mouse_move(self, event): # linear mappers (which is used 99% of the time). data = [ arr - for arr in (source.get_data() for source in mapper.range.sources) + for arr in ( + source.get_data() for source in mapper.range.sources + ) if arr.size > 0 ] if domain_min is None: diff --git a/chaco/tools/pan_tool2.py b/chaco/tools/pan_tool2.py index 02ab7caf3..4f92c5ca0 100644 --- a/chaco/tools/pan_tool2.py +++ b/chaco/tools/pan_tool2.py @@ -73,7 +73,10 @@ def dragging(self, event): else: self.constrain_direction = "y" - for direction, bound_name, ndx in [("x", "width", 0), ("y", "height", 1)]: + for direction, bound_name, ndx in [ + ("x", "width", 0), + ("y", "height", 1), + ]: if not self.constrain or self.constrain_direction == direction: mapper = getattr(plot, direction + "_mapper") range = mapper.range @@ -99,14 +102,20 @@ def dragging(self, event): if domain_min is None: if self.restrict_to_data: domain_min = min( - [source.get_data().min() for source in range.sources] + [ + source.get_data().min() + for source in range.sources + ] ) else: domain_min = -inf if domain_max is None: if self.restrict_to_data: domain_max = max( - [source.get_data().max() for source in range.sources] + [ + source.get_data().max() + for source in range.sources + ] ) else: domain_max = inf diff --git a/chaco/tools/range_selection.py b/chaco/tools/range_selection.py index 590388077..444a94beb 100644 --- a/chaco/tools/range_selection.py +++ b/chaco/tools/range_selection.py @@ -341,7 +341,9 @@ def moving_mouse_move(self, event): cur_point = array([event.x, event.y]) cur_data_point = self.mapper.map_data(cur_point)[self.axis_index] original_selection = self._original_selection - new_selection = original_selection + (cur_data_point - self._down_data_coord) + new_selection = original_selection + ( + cur_data_point - self._down_data_coord + ) selection_data_width = original_selection[1] - original_selection[0] range = self.mapper.range @@ -601,7 +603,9 @@ def _set_selection(self, val): break # Set the selection mode on the datasource - datasource.metadata[self.selection_mode_metadata_name] = self.selection_mode + datasource.metadata[ + self.selection_mode_metadata_name + ] = self.selection_mode if val is not None: low, high = val @@ -678,6 +682,8 @@ def __mapper_changed(self, event): def _axis_changed(self, old, new): if old is not None: - self.plot.observe(self.__mapper_changed, old + "_mapper", remove=True) + self.plot.observe( + self.__mapper_changed, old + "_mapper", remove=True + ) if new is not None: self.plot.observe(self.__mapper_changed, new + "_mapper") diff --git a/chaco/tools/range_selection_2d.py b/chaco/tools/range_selection_2d.py index 9068afbf7..82834961b 100644 --- a/chaco/tools/range_selection_2d.py +++ b/chaco/tools/range_selection_2d.py @@ -263,9 +263,13 @@ def selecting_mouse_leave(self, event): pos = self._get_axis_coord(event) if pos >= high: if self.axis == "index": - selection_high = self._map_data([(high, 0)])[0][self.axis_index] + selection_high = self._map_data([(high, 0)])[0][ + self.axis_index + ] else: - selection_high = self._map_data([(0, high)])[0][self.axis_index] + selection_high = self._map_data([(0, high)])[0][ + self.axis_index + ] elif pos <= low: if self.axis == "index": selection_low = self._map_data([(low, 0)])[0][self.axis_index] @@ -296,11 +300,17 @@ def _get_selection_screencoords(self): if selection is not None and len(selection) == 2: if self.axis == "index": return [ - x for x, y in self._map_screen([(x, 0) for x in self.selection]) + x + for x, y in self._map_screen( + [(x, 0) for x in self.selection] + ) ] else: return [ - y for x, y in self._map_screen([(0, y) for y in self.selection]) + y + for x, y in self._map_screen( + [(0, y) for y in self.selection] + ) ] else: diff --git a/chaco/tools/range_selection_overlay.py b/chaco/tools/range_selection_overlay.py index 00b36bb2c..9f9a7ba62 100644 --- a/chaco/tools/range_selection_overlay.py +++ b/chaco/tools/range_selection_overlay.py @@ -89,7 +89,12 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): gc.set_line_width(self.border_width) gc.set_line_dash(self.border_style_) gc.draw_rect( - (lower_left[0], lower_left[1], upper_right[0], upper_right[1]) + ( + lower_left[0], + lower_left[1], + upper_right[0], + upper_right[1], + ) ) # ------------------------------------------------------------------------ @@ -166,7 +171,9 @@ def _attach_metadata_handler(self, old, new): self._metadata_change_handler, "metadata_changed", remove=True ) if new: - datasource.observe(self._metadata_change_handler, "metadata_changed") + datasource.observe( + self._metadata_change_handler, "metadata_changed" + ) def _metadata_change_handler(self, event): self.component.request_redraw() diff --git a/chaco/tools/rectangular_selection.py b/chaco/tools/rectangular_selection.py index 77bb7eb73..d38857050 100644 --- a/chaco/tools/rectangular_selection.py +++ b/chaco/tools/rectangular_selection.py @@ -22,7 +22,9 @@ def selecting_mouse_move(self, event): new_point = self._map_data(np.array((event.x, event.y))) if self.first_corner is None: self.first_corner = new_point - self._active_selection = self._make_rectangle(self.first_corner, new_point) + self._active_selection = self._make_rectangle( + self.first_corner, new_point + ) self.updated = True if self.incremental_select: self._update_selection() diff --git a/chaco/tools/regression_lasso.py b/chaco/tools/regression_lasso.py index a555eb142..53ef0667f 100644 --- a/chaco/tools/regression_lasso.py +++ b/chaco/tools/regression_lasso.py @@ -53,7 +53,10 @@ class RegressionOverlay(LassoOverlay): _label = Instance( Label, kw=dict( - bgcolor="white", border_color="black", font="modern 14", border_width=1 + bgcolor="white", + border_color="black", + font="modern 14", + border_width=1, ), ) @@ -94,7 +97,9 @@ def _draw_component(self, gc, view_bounds=None, mode="normal"): left_y = f(left_x) right_y = f(right_x) - left_pt, right_pt = c.map_screen([[left_x, left_y], [right_x, right_y]]) + left_pt, right_pt = c.map_screen( + [[left_x, left_y], [right_x, right_y]] + ) with gc: gc.set_line_dash(self.line_style_) diff --git a/chaco/tools/scatter_inspector.py b/chaco/tools/scatter_inspector.py index 880119b59..369680f6e 100644 --- a/chaco/tools/scatter_inspector.py +++ b/chaco/tools/scatter_inspector.py @@ -66,7 +66,9 @@ def normal_mouse_move(self, event): """ plot = self.component index = plot.map_index((event.x, event.y), threshold=self.threshold) - insp_event = ScatterInspectorEvent(event_type=HOVER_EVENT, event_index=index) + insp_event = ScatterInspectorEvent( + event_type=HOVER_EVENT, event_index=index + ) if index is not None: old = plot.index.metadata.get(self.hover_metadata_name, None) plot.index.metadata[self.hover_metadata_name] = [index] @@ -107,7 +109,9 @@ def _deselect(self, index=None): deselects all points. """ plot = self.component - insp_event = ScatterInspectorEvent(event_type=DESELECT_EVENT, event_index=index) + insp_event = ScatterInspectorEvent( + event_type=DESELECT_EVENT, event_index=index + ) for name in ("index", "value"): if not hasattr(plot, name): continue @@ -129,7 +133,9 @@ def _deselect(self, index=None): def _select(self, index, append=True): plot = self.component - insp_event = ScatterInspectorEvent(event_type=SELECT_EVENT, event_index=index) + insp_event = ScatterInspectorEvent( + event_type=SELECT_EVENT, event_index=index + ) for name in ("index", "value"): if not hasattr(plot, name): continue diff --git a/chaco/tools/select_tool.py b/chaco/tools/select_tool.py index d1de1d60a..19572befb 100644 --- a/chaco/tools/select_tool.py +++ b/chaco/tools/select_tool.py @@ -33,7 +33,9 @@ class SelectTool(BaseTool): #: The modifier key to use to multi-select points. Only used in **toggle** #: and **multi** selection modes. - multiselect_modifier = Instance(KeySpec, args=(None, "control"), allow_none=True) + multiselect_modifier = Instance( + KeySpec, args=(None, "control"), allow_none=True + ) def _get_selection_state(self, event): """Returns a tuple reflecting the current selection state diff --git a/chaco/tools/simple_zoom.py b/chaco/tools/simple_zoom.py index 7f68398a2..5cf1adc7a 100644 --- a/chaco/tools/simple_zoom.py +++ b/chaco/tools/simple_zoom.py @@ -4,7 +4,9 @@ import warnings -warnings.warn("SimpleZoom has been deprecated, use ZoomTool", DeprecationWarning) +warnings.warn( + "SimpleZoom has been deprecated, use ZoomTool", DeprecationWarning +) from numpy import array @@ -148,7 +150,10 @@ def __init__(self, component=None, *args, **kw): x_range = self.component.x_mapper.range y_range = self.component.y_mapper.range self._orig_low_setting = (x_range.low_setting, y_range.low_setting) - self._orig_high_setting = (x_range.high_setting, y_range.high_setting) + self._orig_high_setting = ( + x_range.high_setting, + y_range.high_setting, + ) component.observe(self._reset_state_to_current, "index_data_changed") def enable(self, event=None): @@ -246,8 +251,12 @@ def overlay_range(self, component, gc): gc.set_alpha(self.alpha) gc.set_fill_color(self.color_) gc.set_stroke_color(self.border_color_) - gc.clip_to_rect(component.x, component.y, component.width, component.height) - gc.rect(lower_left[0], lower_left[1], upper_right[0], upper_right[1]) + gc.clip_to_rect( + component.x, component.y, component.width, component.height + ) + gc.rect( + lower_left[0], lower_left[1], upper_right[0], upper_right[1] + ) gc.draw_path() def normal_left_down(self, event): @@ -352,7 +361,9 @@ def _end_select(self, event): if low > high: low, high = high, low else: - low, high = self._map_coordinate_box(self._screen_start, self._screen_end) + low, high = self._map_coordinate_box( + self._screen_start, self._screen_end + ) new_zoom_range = (low, high) self._append_state(new_zoom_range) @@ -391,8 +402,14 @@ def _do_zoom(self): # "box" mode; reset both axes. x_range = self.component.x_mapper.range y_range = self.component.y_mapper.range - x_range.low_setting, y_range.low_setting = self._orig_low_setting - x_range.high_setting, y_range.high_setting = self._orig_high_setting + ( + x_range.low_setting, + y_range.low_setting, + ) = self._orig_low_setting + ( + x_range.high_setting, + y_range.high_setting, + ) = self._orig_high_setting # resetting the ranges will allow 'auto' to pick the values x_range.reset() @@ -403,7 +420,9 @@ def _do_zoom(self): if self.tool_mode == "range": # "range" mode; zoom the one axis. mapper = self._get_mapper() - if self._zoom_limit_reached(orig_low, orig_high, low, high, mapper): + if self._zoom_limit_reached( + orig_low, orig_high, low, high, mapper + ): self._pop_state() return mapper.range.low = low @@ -411,9 +430,16 @@ def _do_zoom(self): else: # "box" mode; zoom both axes. for ndx in (0, 1): - mapper = (self.component.x_mapper, self.component.y_mapper)[ndx] + mapper = ( + self.component.x_mapper, + self.component.y_mapper, + )[ndx] if self._zoom_limit_reached( - orig_low[ndx], orig_high[ndx], low[ndx], high[ndx], mapper + orig_low[ndx], + orig_high[ndx], + low[ndx], + high[ndx], + mapper, ): # pop _current_state off the stack and leave the actual # bounds unmodified. @@ -486,8 +512,12 @@ def normal_mouse_wheel(self, event): for ndx, mapper in mapper_list: screenrange = mapper.screen_bounds mouse_val = mouse_pos[ndx] - newscreenlow = mouse_val + zoom * (screenlow_pt[ndx] - mouse_val) - newscreenhigh = mouse_val + zoom * (screenhigh_pt[ndx] - mouse_val) + newscreenlow = mouse_val + zoom * ( + screenlow_pt[ndx] - mouse_val + ) + newscreenhigh = mouse_val + zoom * ( + screenhigh_pt[ndx] - mouse_val + ) newlow = mapper.map_data(newscreenlow) newhigh = mapper.map_data(newscreenhigh) @@ -509,7 +539,9 @@ def normal_mouse_wheel(self, event): if newlow > newhigh: # This happens when the orientation of the axis is reversed. newlow, newhigh = newhigh, newlow - domain_min, domain_max = getattr(mapper, "domain_limits", (None, None)) + domain_min, domain_max = getattr( + mapper, "domain_limits", (None, None) + ) if domain_min is not None and newlow < domain_min: newlow = domain_min if domain_max is not None and newhigh > domain_max: diff --git a/chaco/tools/tests/test_range_selection.py b/chaco/tools/tests/test_range_selection.py index cdd579932..44357af50 100644 --- a/chaco/tools/tests/test_range_selection.py +++ b/chaco/tools/tests/test_range_selection.py @@ -20,7 +20,9 @@ def test_selecting_mouse_leave_clipping(self): for origin in ("bottom left", "top left", "bottom right", "top right"): for orientation in ("h", "v"): for axis in ("index", "value"): - plot = Plot(plot_data, orientation=orientation, origin="top right") + plot = Plot( + plot_data, orientation=orientation, origin="top right" + ) renderer = plot.plot(("x", "y"))[0] renderer.bounds = [10, 20] diff --git a/chaco/tools/tests/test_range_zoom.py b/chaco/tools/tests/test_range_zoom.py index b4eca97c3..a73c96983 100644 --- a/chaco/tools/tests/test_range_zoom.py +++ b/chaco/tools/tests/test_range_zoom.py @@ -43,7 +43,9 @@ def test_rgba_background_box(self): tool.overlay(self.plot, gc) - self.assertEqual(gc.set_fill_color.call_args, mock.call([1.0, 0.0, 0.0, 0.3])) + self.assertEqual( + gc.set_fill_color.call_args, mock.call([1.0, 0.0, 0.0, 0.3]) + ) def test_rgba_background_range(self): tool = self.tool @@ -58,4 +60,6 @@ def test_rgba_background_range(self): tool.overlay(self.plot, gc) - self.assertEqual(gc.set_fill_color.call_args, mock.call([1.0, 0.0, 0.0, 0.3])) + self.assertEqual( + gc.set_fill_color.call_args, mock.call([1.0, 0.0, 0.0, 0.3]) + ) diff --git a/chaco/tools/tests/test_scatter_inspector.py b/chaco/tools/tests/test_scatter_inspector.py index 7b6245bd2..e3ef01f86 100644 --- a/chaco/tools/tests/test_scatter_inspector.py +++ b/chaco/tools/tests/test_scatter_inspector.py @@ -131,7 +131,9 @@ def test_hover_triggers_event(self): self.assertEqual(self.insp_event.event_type, "hover") self.assertEqual(self.insp_event.event_index, 1) finally: - tool.observe(self.store_inspector_event, "inspector_event", remove=True) + tool.observe( + self.store_inspector_event, "inspector_event", remove=True + ) def test_select_triggers_event(self): tool = self.tool @@ -161,7 +163,9 @@ def test_select_triggers_event(self): self.assertEqual(self.insp_event.event_type, "deselect") self.assertEqual(self.insp_event.event_index, 1) finally: - tool.observe(self.store_inspector_event, "inspector_event", remove=True) + tool.observe( + self.store_inspector_event, "inspector_event", remove=True + ) # Helper methods ---------------------------------------------------------- diff --git a/chaco/tools/tool_history_mixin.py b/chaco/tools/tool_history_mixin.py index 1dfcc934f..1ac758c01 100644 --- a/chaco/tools/tool_history_mixin.py +++ b/chaco/tools/tool_history_mixin.py @@ -113,16 +113,22 @@ def normal_key_pressed(self, event): self._history_handle_key(event) def _history_handle_key(self, event): - if self.reset_state_key is not None and self.reset_state_key.match(event): + if self.reset_state_key is not None and self.reset_state_key.match( + event + ): self._history_index = 0 self._reset_state_pressed() event.handled = True - elif self.prev_state_key is not None and self.prev_state_key.match(event): + elif self.prev_state_key is not None and self.prev_state_key.match( + event + ): if self._history_index > 0: self._history_index -= 1 self._prev_state_pressed() event.handled = True - elif self.next_state_key is not None and self.next_state_key.match(event): + elif self.next_state_key is not None and self.next_state_key.match( + event + ): if self._history_index <= len(self._history) - 2: self._history_index += 1 self._next_state_pressed() diff --git a/chaco/tools/toolbars/plot_toolbar.py b/chaco/tools/toolbars/plot_toolbar.py index 12ed2bcbc..fcc99e4cb 100644 --- a/chaco/tools/toolbars/plot_toolbar.py +++ b/chaco/tools/toolbars/plot_toolbar.py @@ -148,7 +148,11 @@ def overlay(self, other_component, gc, view_bounds=None, mode="normal"): gc.begin_path() gc.move_to(x + self.end_radius, y) gc.arc_to( - x + self.width, y, x + self.width, y + self.end_radius, self.end_radius + x + self.width, + y, + x + self.width, + y + self.end_radius, + self.end_radius, ) gc.arc_to( x + self.width, @@ -157,16 +161,28 @@ def overlay(self, other_component, gc, view_bounds=None, mode="normal"): y + height, self.end_radius, ) - gc.arc_to(x, y + height, x, y + height - self.end_radius, self.end_radius) + gc.arc_to( + x, y + height, x, y + height - self.end_radius, self.end_radius + ) gc.arc_to(x, y, x + self.end_radius, y, self.end_radius) if self.location in ["top", "bottom"]: gc.linear_gradient( - x, y, x, y + 100, numpy.array([starting_color, ending_color]), "pad" + x, + y, + x, + y + 100, + numpy.array([starting_color, ending_color]), + "pad", ) else: gc.linear_gradient( - x, y, x + 100, y, numpy.array([starting_color, ending_color]), "pad" + x, + y, + x + 100, + y, + numpy.array([starting_color, ending_color]), + "pad", ) gc.draw_path() @@ -188,14 +204,22 @@ def _do_layout(self, component=None): if self.hiding: self.height = height = 10 else: - tallest_button = max([button.height for button in self.components]) - self.height = height = tallest_button + self.vertical_padding * 2 + tallest_button = max( + [button.height for button in self.components] + ) + self.height = height = ( + tallest_button + self.vertical_padding * 2 + ) else: if self.hiding: self.width = width = 10 else: - widest_button = max([button.width for button in self.components]) - self.width = width = widest_button + self.horizontal_padding * 2 + widest_button = max( + [button.width for button in self.components] + ) + self.width = width = ( + widest_button + self.horizontal_padding * 2 + ) if component is not None: # Overlay positions are not relative to the component's position, @@ -203,23 +227,39 @@ def _do_layout(self, component=None): cx, cy = component.outer_position if self.location is "top": self.x = ( - cx + (component.width - self.width) / 2 + component.padding_left + cx + + (component.width - self.width) / 2 + + component.padding_left + ) + self.y = ( + cy + + component.height + + component.padding_bottom + - height + - 2 ) - self.y = cy + component.height + component.padding_bottom - height - 2 elif self.location is "bottom": self.x = ( - cx + (component.width - self.width) / 2 + component.padding_left + cx + + (component.width - self.width) / 2 + + component.padding_left ) self.y = cy + component.padding_bottom + 2 elif self.location is "left": self.x = cx + component.padding_left + 2 self.y = ( - cy + (component.height - self.height) / 2 + component.padding_bottom + cy + + (component.height - self.height) / 2 + + component.padding_bottom ) else: # 'right' - self.x = cx + component.width + component.padding_left - width - 2 + self.x = ( + cx + component.width + component.padding_left - width - 2 + ) self.y = ( - cy + (component.height - self.height) / 2 + component.padding_bottom + cy + + (component.height - self.height) / 2 + + component.padding_bottom ) if self.location in ["top", "bottom"]: @@ -236,7 +276,9 @@ def _do_layout(self, component=None): # location is 'left' or 'right' h_position = self.x + self.horizontal_padding - last_button_position = self.y + self.vertical_padding + self.button_spacing + last_button_position = ( + self.y + self.vertical_padding + self.button_spacing + ) for button in reversed(self.components): h_offset = (self.width - button.width) / 2 button.y = last_button_position diff --git a/chaco/tools/toolbars/toolbar_buttons.py b/chaco/tools/toolbars/toolbar_buttons.py index 5f46ff49c..f4689b829 100644 --- a/chaco/tools/toolbars/toolbar_buttons.py +++ b/chaco/tools/toolbars/toolbar_buttons.py @@ -7,7 +7,15 @@ from kiva.image import Image from pyface.image_resource import ImageResource from pyface.api import FileDialog, OK, error -from traits.api import Instance, Str, Property, cached_property, List, Int, Enum +from traits.api import ( + Instance, + Str, + Property, + cached_property, + List, + Int, + Enum, +) class ToolbarButton(Button): @@ -178,7 +186,9 @@ def perform(self, event): def _perform_wx(self, width, height, gc): import wx - bitmap = wx.BitmapFromBufferRGBA(width + 1, height + 1, gc.bmp_array.flatten()) + bitmap = wx.BitmapFromBufferRGBA( + width + 1, height + 1, gc.bmp_array.flatten() + ) data = wx.BitmapDataObject() data.SetBitmap(bitmap) if wx.TheClipboard.Open(): diff --git a/chaco/tools/tracking_pan_tool.py b/chaco/tools/tracking_pan_tool.py index 8054ae0bc..cce1e50f9 100644 --- a/chaco/tools/tracking_pan_tool.py +++ b/chaco/tools/tracking_pan_tool.py @@ -20,11 +20,15 @@ def _end_pan(self, event): high = xrange.high low = xrange.low if xrange.default_state == "low_track": - hi_val = max([source.get_bounds()[1] for source in xrange.sources]) + hi_val = max( + [source.get_bounds()[1] for source in xrange.sources] + ) if hi_val >= low and hi_val <= high: xrange.set_bounds("track", "auto") elif xrange.default_state == "high_track": - lo_val = min([source.get_bounds()[0] for source in xrange.sources]) + lo_val = min( + [source.get_bounds()[0] for source in xrange.sources] + ) if lo_val >= low and lo_val <= high: xrange.set_bounds("auto", "track") @@ -32,11 +36,15 @@ def _end_pan(self, event): high = yrange.high low = yrange.low if yrange.default_state == "low_track": - hi_val = max([source.get_bounds()[1] for source in yrange.sources]) + hi_val = max( + [source.get_bounds()[1] for source in yrange.sources] + ) if hi_val >= low and hi_val <= high: yrange.set_bounds("track", "auto") elif yrange.default_state == "high_track": - lo_val = min([source.get_bounds()[0] for source in yrange.sources]) + lo_val = min( + [source.get_bounds()[0] for source in yrange.sources] + ) if lo_val >= low and lo_val <= high: yrange.set_bounds("auto", "track") diff --git a/chaco/tools/tracking_zoom.py b/chaco/tools/tracking_zoom.py index 05d4ba4b9..a134df727 100644 --- a/chaco/tools/tracking_zoom.py +++ b/chaco/tools/tracking_zoom.py @@ -33,11 +33,18 @@ def normal_mouse_wheel(self, event): # then zoom in while trying to maintain the mouse screen coordinates # in the new range. c = self.component - low_pt, high_pt = self._map_coordinate_box((c.x, c.y), (c.x2, c.y2)) - mouse_pos = (c.x_mapper.map_data(event.x), c.y_mapper.map_data(event.y)) + low_pt, high_pt = self._map_coordinate_box( + (c.x, c.y), (c.x2, c.y2) + ) + mouse_pos = ( + c.x_mapper.map_data(event.x), + c.y_mapper.map_data(event.y), + ) if self.tool_mode == "range": - datarange_list = [(self._determine_axis(), self._get_mapper().range)] + datarange_list = [ + (self._determine_axis(), self._get_mapper().range) + ] else: datarange_list = [(0, c.x_mapper.range), (1, c.y_mapper.range)] @@ -57,7 +64,12 @@ def normal_mouse_wheel(self, event): return if datarange.default_state == "low_track": - hi = max([source.get_bounds()[1] for source in datarange.sources]) + hi = max( + [ + source.get_bounds()[1] + for source in datarange.sources + ] + ) # is hi in the current view? if hi >= low_pt[ndx] and hi <= high_pt[ndx]: datarange.scale_tracking_amount(zoom) @@ -65,7 +77,12 @@ def normal_mouse_wheel(self, event): newlow = "track" elif datarange.default_state == "high_track": - lo = min([source.get_bounds()[0] for source in datarange.sources]) + lo = min( + [ + source.get_bounds()[0] + for source in datarange.sources + ] + ) # is lo in the current view? if lo >= low_pt[ndx] and lo <= high_pt[ndx]: datarange.scale_tracking_amount(zoom) diff --git a/chaco/tools/traits_tool.py b/chaco/tools/traits_tool.py index 9c1a86091..a602980bc 100755 --- a/chaco/tools/traits_tool.py +++ b/chaco/tools/traits_tool.py @@ -101,7 +101,9 @@ def _dispatch_stateful_event(self, event, suffix): # then that is the only candidate. If our component is a container, # then we add its non-container components to the list of candidates; # any nested containers are lower priority than primary plot components. - candidates = get_nested_components(self.component, [Container] + self.classes) + candidates = get_nested_components( + self.component, [Container] + self.classes + ) # Hittest against all the candidate and take the first one item = None diff --git a/chaco/tooltip.py b/chaco/tooltip.py index 61192b929..a64f6ce4d 100644 --- a/chaco/tooltip.py +++ b/chaco/tooltip.py @@ -151,7 +151,9 @@ def _recompute_text(self): for line in self.lines ] dummy_gc = self._font_metrics_provider - line_sizes = array([label.get_width_height(dummy_gc) for label in labels]) + line_sizes = array( + [label.get_width_height(dummy_gc) for label in labels] + ) self._cached_labels = labels self._cached_line_sizes = line_sizes self._max_line_width = max(line_sizes[:, 0]) diff --git a/chaco/transform_color_mapper.py b/chaco/transform_color_mapper.py index e229baf7b..8f18ad44e 100644 --- a/chaco/transform_color_mapper.py +++ b/chaco/transform_color_mapper.py @@ -29,7 +29,9 @@ class TransformColorMapper(ColorMapper): unit_func = Trait(None, None, Callable) - transformed_bounds = Tuple(Trait(None, None, Float), Trait(None, None, Float)) + transformed_bounds = Tuple( + Trait(None, None, Float), Trait(None, None, Float) + ) # ------------------------------------------------------------------- # Trait handlers @@ -60,7 +62,9 @@ def _unit_func_changed(self): # ------------------------------------------------------------------- @classmethod - def from_color_mapper(cls, color_mapper, data_func=None, unit_func=None, **traits): + def from_color_mapper( + cls, color_mapper, data_func=None, unit_func=None, **traits + ): """Create a TransformColorMapper from an existing ColorMapper instance.""" segdata = color_mapper._segmentdata return cls.from_segment_map( @@ -72,7 +76,9 @@ def from_color_mapper(cls, color_mapper, data_func=None, unit_func=None, **trait ) @classmethod - def from_color_map(cls, color_map, data_func=None, unit_func=None, **traits): + def from_color_map( + cls, color_map, data_func=None, unit_func=None, **traits + ): """Create a TransformColorMapper from a colormap generator function. The return value is an instance of TransformColorMapper, *not* a factory @@ -109,7 +115,10 @@ def factory_from_color_map( def factory(range, **traits): tcm = cls.from_color_mapper( - color_mapper, data_func=data_func, unit_func=unit_func, **traits + color_mapper, + data_func=data_func, + unit_func=unit_func, + **traits ) return tcm diff --git a/examples/demo/advanced/asynchronous_updates.py b/examples/demo/advanced/asynchronous_updates.py index 0a3a6208b..2896d67a3 100644 --- a/examples/demo/advanced/asynchronous_updates.py +++ b/examples/demo/advanced/asynchronous_updates.py @@ -13,7 +13,15 @@ # Enthought library imports from enable.api import Component, ComponentEditor -from traits.api import Array, Bool, DelegatesTo, HasTraits, Instance, Range, observe +from traits.api import ( + Array, + Bool, + DelegatesTo, + HasTraits, + Instance, + Range, + observe, +) from traits.trait_notifiers import ui_dispatch from traitsui.api import Item, Group, View @@ -74,7 +82,9 @@ def _recalculate_blurred_image(self, event): # the asynchronizer's current job (if any) is complete. If another # job (presumably with a different blur_level) comes in before this # happens, this job will never be executed. - self._asynchronizer.submit(self._blur_and_notify_plot, image, blur_level) + self._asynchronizer.submit( + self._blur_and_notify_plot, image, blur_level + ) else: # This happens on the calling thread, which is the GUI thread when # a change in 'blur_level' comes from the GUI (as in this demo). @@ -93,7 +103,9 @@ def _blur_and_notify_plot(self, image, blur_level): # thread. Since this call is being executed on one of the executor's # worker threads, we must re-dispatch the data update to the UI thread # or suffer undefined consequences (possibly crashes). - ui_dispatch(self.plot_data.set_data, "blurred_image", self.blurred_image) + ui_dispatch( + self.plot_data.set_data, "blurred_image", self.blurred_image + ) # ========================================================================== # Visualization logic - useful, but not the point of the demo @@ -196,8 +208,16 @@ class Demo(HasTraits): traits_view = View( Group( - Item("component", editor=ComponentEditor(size=size), show_label=False), - Group(Item("asynchronous"), Item("blur_level"), orientation="horizontal"), + Item( + "component", + editor=ComponentEditor(size=size), + show_label=False, + ), + Group( + Item("asynchronous"), + Item("blur_level"), + orientation="horizontal", + ), orientation="vertical", ), resizable=True, diff --git a/examples/demo/advanced/data_cube.py b/examples/demo/advanced/data_cube.py index eec1ccd28..d8419575f 100644 --- a/examples/demo/advanced/data_cube.py +++ b/examples/demo/advanced/data_cube.py @@ -22,7 +22,13 @@ from numpy import arange, linspace, nanmin, nanmax, newaxis, pi, sin, cos # Enthought library imports -from chaco.api import ArrayPlotData, Plot, GridPlotContainer, BaseTool, DataRange1D +from chaco.api import ( + ArrayPlotData, + Plot, + GridPlotContainer, + BaseTool, + DataRange1D, +) from chaco.default_colormaps import * from chaco.tools.api import LineInspector, ZoomTool from enable.example_support import DemoFrame, demo_main @@ -176,7 +182,9 @@ def normal_mouse_move(self, event): def _update_slices(self, event): plot = self.component - ndx = plot.map_index((event.x, event.y), threshold=5.0, index_only=True) + ndx = plot.map_index( + (event.x, event.y), threshold=5.0, index_only=True + ) if ndx: self.callback(self, *ndx) @@ -312,7 +320,10 @@ def _add_plot_tools(self, imgplot, token): imgplot.overlays.append( ZoomTool( - component=imgplot, tool_mode="box", enable_wheel=False, always_on=False + component=imgplot, + tool_mode="box", + enable_wheel=False, + always_on=False, ) ) imgplot.overlays.append( @@ -345,9 +356,13 @@ def _add_plot_tools(self, imgplot, token): ) def _update_model(self, cmap): - range = DataRange1D(low=amin(self.model.vals), high=amax(self.model.vals)) + range = DataRange1D( + low=amin(self.model.vals), high=amax(self.model.vals) + ) self.colormap = cmap(range) - self.colorcube = (self.colormap.map_screen(self.model.vals) * 255).astype(uint8) + self.colorcube = ( + self.colormap.map_screen(self.model.vals) * 255 + ).astype(uint8) def _update_images(self): """Updates the image data in self.plotdata to correspond to the @@ -366,7 +381,9 @@ def download_data(): global dl_path, run_cleanup print('Please enter the location of the "voldata" subdirectory containing') - print("the data files for this demo, or enter a path to download to (7.8MB).") + print( + "the data files for this demo, or enter a path to download to (7.8MB)." + ) print("Press to download to the current directory.") dl_path = input("Path: ").strip().rstrip("/").rstrip("\\") @@ -379,7 +396,9 @@ def download_data(): data_good = True try: for i in range(1, 110): - if not os.path.isfile(os.path.join(voldata_path, "MRbrain.%d" % i)): + if not os.path.isfile( + os.path.join(voldata_path, "MRbrain.%d" % i) + ): data_good = False break else: diff --git a/examples/demo/advanced/data_stream.py b/examples/demo/advanced/data_stream.py index 6cec0f23c..111e704fb 100644 --- a/examples/demo/advanced/data_stream.py +++ b/examples/demo/advanced/data_stream.py @@ -15,7 +15,16 @@ import numpy as np # Enthought imports -from traits.api import Array, Callable, Enum, Float, HasTraits, Instance, Int, Trait +from traits.api import ( + Array, + Callable, + Enum, + Float, + HasTraits, + Instance, + Int, + Trait, +) from traitsui.api import Group, HGroup, Item, View, spring, Handler from pyface.timer.api import Timer @@ -109,7 +118,9 @@ def timer_tick(self, *args): # This isn't the most efficient thing in the world but it works. cur_data = self.viewer.data new_data = np.hstack((cur_data[-self.max_num_points + 1 :], [new_val])) - new_index = np.arange(self.num_ticks - len(new_data) + 1, self.num_ticks + 0.01) + new_index = np.arange( + self.num_ticks - len(new_data) + 1, self.num_ticks + 0.01 + ) self.viewer.index = new_index self.viewer.data = new_data diff --git a/examples/demo/advanced/javascript_hover_tools.py b/examples/demo/advanced/javascript_hover_tools.py index dc1b20004..681be3ba8 100644 --- a/examples/demo/advanced/javascript_hover_tools.py +++ b/examples/demo/advanced/javascript_hover_tools.py @@ -429,7 +429,9 @@ def write_hover_coords(container, array_id, script_filename=None): if not isinstance(renderer, LinePlot): data_points = [data_points] for segment in data_points: - segment_data.append(get_pixel_data(segment, renderer, screen_width)) + segment_data.append( + get_pixel_data(segment, renderer, screen_width) + ) colors.append(renderer.color_) if len(segment_data) > 0: @@ -529,7 +531,9 @@ def make_palettized_png_str(gc): format = gc.format()[:-2].upper() if format != "RGBA": gc = gc.convert_pixel_format("rgba32") - img = Image.fromstring("RGBA", (gc.width(), gc.height()), gc.bmp_array.tostring()) + img = Image.fromstring( + "RGBA", (gc.width(), gc.height()), gc.bmp_array.tostring() + ) img2 = img.convert("P") output_buf = io.StringIO() img2.save(output_buf, "png") diff --git a/examples/demo/advanced/scalar_image_function_inspector.py b/examples/demo/advanced/scalar_image_function_inspector.py index c7de5dba0..1d1a47e2f 100644 --- a/examples/demo/advanced/scalar_image_function_inspector.py +++ b/examples/demo/advanced/scalar_image_function_inspector.py @@ -79,10 +79,12 @@ class Model(HasTraits): Item("npts_y", label="Number Y Points"), ), HGroup( - Item("min_x", label="Min X value"), Item("max_x", label="Max X value") + Item("min_x", label="Min X value"), + Item("max_x", label="Max X value"), ), HGroup( - Item("min_y", label="Min Y value"), Item("max_y", label="Max Y value") + Item("min_y", label="Min Y value"), + Item("max_y", label="Max Y value"), ), ), buttons=["OK", "Cancel"], @@ -153,7 +155,15 @@ def compute_model(self): self._function = self.function def _anytrait_changed(self, name, value): - if name in ["function", "npts_x", "npts_y", "min_x", "max_x", "min_y", "max_y"]: + if name in [ + "function", + "npts_x", + "npts_y", + "min_x", + "max_x", + "min_y", + "max_y", + ]: self.compute_model() @@ -254,7 +264,9 @@ def create_plot(self): self.polyplot.overlays.append(bottom) # Add some tools to the plot - self.polyplot.tools.append(PanTool(self.polyplot, constrain_key="shift")) + self.polyplot.tools.append( + PanTool(self.polyplot, constrain_key="shift") + ) self.polyplot.overlays.append( ZoomTool(component=self.polyplot, tool_mode="box", always_on=False) ) @@ -349,7 +361,10 @@ def create_plot(self): # Create a container and add components self.container = HPlotContainer( - padding=40, fill_padding=True, bgcolor="white", use_backbuffer=False + padding=40, + fill_padding=True, + bgcolor="white", + use_backbuffer=False, ) inner_cont = VPlotContainer(padding=0, use_backbuffer=True) inner_cont.add(self.cross_plot) @@ -393,10 +408,18 @@ def _metadata_changed(self, event): line_value2=self._image_value.data[:, x_ndx], scatter_index=array([xdata[x_ndx]]), scatter_index2=array([ydata[y_ndx]]), - scatter_value=array([self._image_value.data[y_ndx, x_ndx]]), - scatter_value2=array([self._image_value.data[y_ndx, x_ndx]]), - scatter_color=array([self._image_value.data[y_ndx, x_ndx]]), - scatter_color2=array([self._image_value.data[y_ndx, x_ndx]]), + scatter_value=array( + [self._image_value.data[y_ndx, x_ndx]] + ), + scatter_value2=array( + [self._image_value.data[y_ndx, x_ndx]] + ), + scatter_color=array( + [self._image_value.data[y_ndx, x_ndx]] + ), + scatter_color2=array( + [self._image_value.data[y_ndx, x_ndx]] + ), ) else: self.pd.update_data( @@ -417,8 +440,12 @@ def _colormap_changed(self): self.cross_plot.color_mapper = self._cmap(value_range) # FIXME: change when we decide how best to update plots using # the shared colormap in plot object - self.cross_plot.plots["dot"][0].color_mapper = self._cmap(value_range) - self.cross_plot2.plots["dot"][0].color_mapper = self._cmap(value_range) + self.cross_plot.plots["dot"][0].color_mapper = self._cmap( + value_range + ) + self.cross_plot2.plots["dot"][0].color_mapper = self._cmap( + value_range + ) self.container.request_redraw() def _num_levels_changed(self): @@ -507,18 +534,26 @@ def randomize(new_direction=1, color_change=False): y += self.y_delta if y < 0: y = 0 - self.y_delta, self.x_delta = randomize(1, self.animate_bottom) + self.y_delta, self.x_delta = randomize( + 1, self.animate_bottom + ) elif y >= ylim: y = ylim - 1 - self.y_delta, self.x_delta = randomize(-1, self.animate_top) + self.y_delta, self.x_delta = randomize( + -1, self.animate_top + ) else: x += self.x_delta if x < 0: x = 0 - self.x_delta, self.y_delta = randomize(1, self.animate_left) + self.x_delta, self.y_delta = randomize( + 1, self.animate_left + ) elif x >= xlim: x = xlim - 1 - self.x_delta, self.y_delta = randomize(-1, self.animate_right) + self.x_delta, self.y_delta = randomize( + -1, self.animate_right + ) else: x, y = 0, 0 @@ -551,7 +586,9 @@ class ModelView(HasTraits): UItem("edit_view"), Item("animated"), Item( - "animate_left", enabled_when="animated", label="Change colors at: Left" + "animate_left", + enabled_when="animated", + label="Change colors at: Left", ), Item("animate_right", enabled_when="animated", label="Right"), Item("animate_top", enabled_when="animated", label="Top"), @@ -642,7 +679,9 @@ def main(argv=None): parser.error("Incorrect number of arguments") show_plot( - colormap=opts.colormap, num_levels=opts.num_levels, function=opts.function + colormap=opts.colormap, + num_levels=opts.num_levels, + function=opts.function, ) diff --git a/examples/demo/advanced/scalar_image_function_inspector_old.py b/examples/demo/advanced/scalar_image_function_inspector_old.py index 9def269b8..660d682b4 100644 --- a/examples/demo/advanced/scalar_image_function_inspector_old.py +++ b/examples/demo/advanced/scalar_image_function_inspector_old.py @@ -59,7 +59,14 @@ observe, ) from traitsui.api import Group, Handler, HGroup, Item, View -from traitsui.menu import Action, CloseAction, Menu, MenuBar, NoButtons, Separator +from traitsui.menu import ( + Action, + CloseAction, + Menu, + MenuBar, + NoButtons, + Separator, +) class Model(HasTraits): @@ -73,10 +80,12 @@ class Model(HasTraits): Item("npts_y", label="Number Y Points"), ), HGroup( - Item("min_x", label="Min X value"), Item("max_x", label="Max X value") + Item("min_x", label="Min X value"), + Item("max_x", label="Max X value"), ), HGroup( - Item("min_y", label="Min Y value"), Item("max_y", label="Max Y value") + Item("min_y", label="Min Y value"), + Item("max_y", label="Max Y value"), ), ), buttons=["OK", "Cancel"], @@ -116,8 +125,12 @@ def compute_model(self): # min/max values (which are edges) xstep = (self.max_x - self.min_x) / self.npts_x ystep = (self.max_y - self.min_y) / self.npts_y - gridx = linspace(self.min_x + xstep / 2, self.max_x - xstep / 2, self.npts_x) - gridy = linspace(self.min_y + xstep / 2, self.max_y - xstep / 2, self.npts_y) + gridx = linspace( + self.min_x + xstep / 2, self.max_x - xstep / 2, self.npts_x + ) + gridy = linspace( + self.min_y + xstep / 2, self.max_y - xstep / 2, self.npts_y + ) x, y = meshgrid(gridx, gridy) try: d = dict(x=x, y=y) @@ -132,7 +145,15 @@ def compute_model(self): self.trait_setq(function=self._function) def _anytrait_changed(self, name, value): - if name in ["function", "npts_x", "npts_y", "min_x", "max_x", "min_y", "max_y"]: + if name in [ + "function", + "npts_x", + "npts_y", + "min_x", + "max_x", + "min_y", + "max_y", + ]: self.compute_model() @@ -141,7 +162,11 @@ class PlotUI(HasTraits): # Traits view definitions: traits_view = View( Group( - Item("container", editor=ComponentEditor(size=(800, 600)), show_label=False) + Item( + "container", + editor=ComponentEditor(size=(800, 600)), + show_label=False, + ) ), buttons=NoButtons, resizable=True, @@ -218,7 +243,9 @@ def create_plot(self): self.polyplot.overlays.append(bottom) # Add some tools to the plot - self.polyplot.tools.append(PanTool(self.polyplot, constrain_key="shift")) + self.polyplot.tools.append( + PanTool(self.polyplot, constrain_key="shift") + ) self.polyplot.overlays.append( ZoomTool(component=self.polyplot, tool_mode="box", always_on=False) ) @@ -313,7 +340,10 @@ def create_plot(self): # Create a container and add components self.container = HPlotContainer( - padding=40, fill_padding=True, bgcolor="white", use_backbuffer=False + padding=40, + fill_padding=True, + bgcolor="white", + use_backbuffer=False, ) inner_cont = VPlotContainer(padding=0, use_backbuffer=True) inner_cont.add(self.cross_plot) @@ -351,23 +381,31 @@ def _metadata_changed(self, event): if "selections" in self._image_index.metadata: x_ndx, y_ndx = self._image_index.metadata["selections"] if y_ndx and x_ndx: - self.pd.set_data("line_value", self._image_value.data[y_ndx, :]) - self.pd.set_data("line_value2", self._image_value.data[:, x_ndx]) + self.pd.set_data( + "line_value", self._image_value.data[y_ndx, :] + ) + self.pd.set_data( + "line_value2", self._image_value.data[:, x_ndx] + ) xdata, ydata = self._image_index.get_data() xdata, ydata = xdata.get_data(), ydata.get_data() self.pd.set_data("scatter_index", array([xdata[x_ndx]])) self.pd.set_data("scatter_index2", array([ydata[y_ndx]])) self.pd.set_data( - "scatter_value", array([self._image_value.data[y_ndx, x_ndx]]) + "scatter_value", + array([self._image_value.data[y_ndx, x_ndx]]), ) self.pd.set_data( - "scatter_value2", array([self._image_value.data[y_ndx, x_ndx]]) + "scatter_value2", + array([self._image_value.data[y_ndx, x_ndx]]), ) self.pd.set_data( - "scatter_color", array([self._image_value.data[y_ndx, x_ndx]]) + "scatter_color", + array([self._image_value.data[y_ndx, x_ndx]]), ) self.pd.set_data( - "scatter_color2", array([self._image_value.data[y_ndx, x_ndx]]) + "scatter_color2", + array([self._image_value.data[y_ndx, x_ndx]]), ) else: self.pd.set_data("scatter_value", array([])) @@ -384,8 +422,12 @@ def _colormap_changed(self): self.cross_plot.color_mapper = self._cmap(value_range) # FIXME: change when we decide how best to update plots using # the shared colormap in plot object - self.cross_plot.plots["dot"][0].color_mapper = self._cmap(value_range) - self.cross_plot2.plots["dot"][0].color_mapper = self._cmap(value_range) + self.cross_plot.plots["dot"][0].color_mapper = self._cmap( + value_range + ) + self.cross_plot2.plots["dot"][0].color_mapper = self._cmap( + value_range + ) self.container.request_redraw() def _num_levels_changed(self): @@ -518,7 +560,9 @@ def main(argv=None): parser.error("Incorrect number of arguments") show_plot( - colormap=opts.colormap, num_levels=opts.num_levels, function=opts.function + colormap=opts.colormap, + num_levels=opts.num_levels, + function=opts.function, ) diff --git a/examples/demo/advanced/spec_waterfall.py b/examples/demo/advanced/spec_waterfall.py index dcdf2c047..4f6c9331a 100644 --- a/examples/demo/advanced/spec_waterfall.py +++ b/examples/demo/advanced/spec_waterfall.py @@ -59,12 +59,17 @@ def _gather_points(self): self._cached_data_pts = [] self._cache_valid = True - self._cached_data_pts = [transpose(array((index, v))) for v in values] + self._cached_data_pts = [ + transpose(array((index, v))) for v in values + ] self._cache_value = True def get_screen_points(self): self._gather_points() - return [self.map_screen(pts, i) for i, pts in enumerate(self._cached_data_pts)] + return [ + self.map_screen(pts, i) + for i, pts in enumerate(self._cached_data_pts) + ] def map_screen(self, data_array, data_offset=None): """data_offset, if provided, is a float that will be mapped @@ -106,7 +111,9 @@ def _create_plot_component(obj): )[0] obj.spectrum_plot.padding = 50 obj.spectrum_plot.title = "Spectrum" - spec_range = list(obj.spectrum_plot.plots.values())[0][0].value_mapper.range + spec_range = list(obj.spectrum_plot.plots.values())[0][ + 0 + ].value_mapper.range spec_range.low = 0.0 spec_range.high = 5.0 obj.spectrum_plot.index_axis.title = "Frequency (hz)" @@ -134,7 +141,9 @@ def _create_plot_component(obj): index=spec_renderer.index, values=values, index_mapper=LinearMapper(range=obj.spectrum_plot.index_mapper.range), - value_mapper=LinearMapper(range=DataRange1D(low=0, high=SPECTROGRAM_LENGTH)), + value_mapper=LinearMapper( + range=DataRange1D(low=0, high=SPECTROGRAM_LENGTH) + ), y2_mapper=LinearMapper( low_pos=0, high_pos=8, range=DataRange1D(low=0, high=15) ), diff --git a/examples/demo/advanced/spectrum.py b/examples/demo/advanced/spectrum.py index 7b09f5a14..a74bdf0cf 100644 --- a/examples/demo/advanced/spectrum.py +++ b/examples/demo/advanced/spectrum.py @@ -43,10 +43,14 @@ def _create_plot_component(obj): obj.spectrum_data.set_data("amplitude", empty_amplitude) obj.spectrum_plot = Plot(obj.spectrum_data) - obj.spectrum_plot.plot(("frequency", "amplitude"), name="Spectrum", color="red") + obj.spectrum_plot.plot( + ("frequency", "amplitude"), name="Spectrum", color="red" + ) obj.spectrum_plot.padding = 50 obj.spectrum_plot.title = "Spectrum" - spec_range = list(obj.spectrum_plot.plots.values())[0][0].value_mapper.range + spec_range = list(obj.spectrum_plot.plots.values())[0][ + 0 + ].value_mapper.range spec_range.low = 0.0 spec_range.high = 5.0 obj.spectrum_plot.index_axis.title = "Frequency (Hz)" @@ -131,7 +135,9 @@ def onTimer(self, *args): self.spectrum_data.set_data("amplitude", spectrum) self.time_data.set_data("amplitude", time) spectrogram_data = self.spectrogram_plotdata.get_data("imagedata") - spectrogram_data = hstack((spectrogram_data[:, 1:], transpose([spectrum]))) + spectrogram_data = hstack( + (spectrogram_data[:, 1:], transpose([spectrum])) + ) self.spectrogram_plotdata.set_data("imagedata", spectrogram_data) self.spectrum_plot.request_redraw() diff --git a/examples/demo/aspect_ratio.py b/examples/demo/aspect_ratio.py index 9163c6ba8..0539398e9 100644 --- a/examples/demo/aspect_ratio.py +++ b/examples/demo/aspect_ratio.py @@ -56,7 +56,11 @@ class MyPlot(HasTraits): Item("fixed_x", label="Data X fixed"), Item("fixed_y", label="Data Y fixed"), ), - Item("plot", editor=ComponentEditor(size=(100, 100)), show_label=False), + Item( + "plot", + editor=ComponentEditor(size=(100, 100)), + show_label=False, + ), ), width=600, height=600, @@ -67,7 +71,9 @@ class MyPlot(HasTraits): def __init__(self, *args, **kw): HasTraits.__init__(self, *args, **kw) numpoints = 200 - plotdata = ArrayPlotData(x=sort(random(numpoints)), y=random(numpoints)) + plotdata = ArrayPlotData( + x=sort(random(numpoints)), y=random(numpoints) + ) plot = Plot(plotdata) plot.plot(("x", "y"), type="scatter") plot.tools.append(PanTool(plot)) diff --git a/examples/demo/basic/bar_plot_stacked.py b/examples/demo/basic/bar_plot_stacked.py index d036b4a61..8105d7ced 100644 --- a/examples/demo/basic/bar_plot_stacked.py +++ b/examples/demo/basic/bar_plot_stacked.py @@ -35,7 +35,9 @@ def __init__(self, index, series_a, series_b, series_c, **kw): plot_data.set_data("series_b", series_b) plot_data.set_data("series_c", series_c) self.plot = Plot(plot_data) - self.plot.plot(("index", "series_a"), type="bar", bar_width=0.8, color="auto") + self.plot.plot( + ("index", "series_a"), type="bar", bar_width=0.8, color="auto" + ) self.plot.plot( ("index", "series_b"), type="bar", diff --git a/examples/demo/basic/cmap_image_select.py b/examples/demo/basic/cmap_image_select.py index 46e7a1264..b6c82eb59 100644 --- a/examples/demo/basic/cmap_image_select.py +++ b/examples/demo/basic/cmap_image_select.py @@ -27,7 +27,12 @@ LinearMapper, Plot, ) -from chaco.tools.api import PanTool, RangeSelection, RangeSelectionOverlay, ZoomTool +from chaco.tools.api import ( + PanTool, + RangeSelection, + RangeSelectionOverlay, + ZoomTool, +) # =============================================================================== # # Create the Chaco plot. @@ -87,7 +92,10 @@ def _create_plot_component(): colorbar.tools.append(range_selection) colorbar.overlays.append( RangeSelectionOverlay( - component=colorbar, border_color="white", alpha=0.8, fill_color="lightgray" + component=colorbar, + border_color="white", + alpha=0.8, + fill_color="lightgray", ) ) diff --git a/examples/demo/basic/cmap_scatter.py b/examples/demo/basic/cmap_scatter.py index 920d5039a..3a17f5e40 100644 --- a/examples/demo/basic/cmap_scatter.py +++ b/examples/demo/basic/cmap_scatter.py @@ -28,7 +28,12 @@ LinearMapper, Plot, ) -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, RangeSelectionOverlay +from chaco.tools.api import ( + PanTool, + ZoomTool, + RangeSelection, + RangeSelectionOverlay, +) # =============================================================================== # # Create the Chaco plot. @@ -109,7 +114,10 @@ def create_colorbar(colormap): colorbar.tools.append(RangeSelection(component=colorbar)) colorbar.overlays.append( RangeSelectionOverlay( - component=colorbar, border_color="white", alpha=0.8, fill_color="lightgray" + component=colorbar, + border_color="white", + alpha=0.8, + fill_color="lightgray", ) ) return colorbar diff --git a/examples/demo/basic/cmap_segment_plot.py b/examples/demo/basic/cmap_segment_plot.py index f56a4bee8..3afec6072 100644 --- a/examples/demo/basic/cmap_segment_plot.py +++ b/examples/demo/basic/cmap_segment_plot.py @@ -28,7 +28,12 @@ LinearMapper, Plot, ) -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, RangeSelectionOverlay +from chaco.tools.api import ( + PanTool, + ZoomTool, + RangeSelection, + RangeSelectionOverlay, +) # =============================================================================== # # Create the Chaco plot. diff --git a/examples/demo/basic/contour_cmap_plot.py b/examples/demo/basic/contour_cmap_plot.py index 345d8e97f..66e201766 100644 --- a/examples/demo/basic/contour_cmap_plot.py +++ b/examples/demo/basic/contour_cmap_plot.py @@ -55,7 +55,9 @@ def _create_plot_component(): ybounds=y_extents, colormap=gmt_drywet, ) - lplot.contour_plot("imagedata", type="line", xbounds=x_extents, ybounds=y_extents) + lplot.contour_plot( + "imagedata", type="line", xbounds=x_extents, ybounds=y_extents + ) # Tweak some of the plot properties lplot.title = "Colormap and contours" diff --git a/examples/demo/basic/contour_plot.py b/examples/demo/basic/contour_plot.py index e013232ab..e3433f6a3 100644 --- a/examples/demo/basic/contour_plot.py +++ b/examples/demo/basic/contour_plot.py @@ -47,7 +47,9 @@ def _create_plot_component(): # Create a contour polygon plot of the data plot = Plot(pd, default_origin="bottom left") - plot.contour_plot("imagedata", type="poly", poly_cmap=viridis, xbounds=x, ybounds=y) + plot.contour_plot( + "imagedata", type="poly", poly_cmap=viridis, xbounds=x, ybounds=y + ) # Create a contour line plot for the data, too plot.contour_plot("imagedata", type="line", xbounds=x, ybounds=y) diff --git a/examples/demo/basic/discrete_cmap_scatter.py b/examples/demo/basic/discrete_cmap_scatter.py index 274d35e06..9bcd8e690 100644 --- a/examples/demo/basic/discrete_cmap_scatter.py +++ b/examples/demo/basic/discrete_cmap_scatter.py @@ -29,7 +29,12 @@ Plot, ) from chaco.default_colormaps import accent -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, RangeSelectionOverlay +from chaco.tools.api import ( + PanTool, + ZoomTool, + RangeSelection, + RangeSelectionOverlay, +) # =============================================================================== # # Create the Chaco plot. @@ -112,7 +117,10 @@ def create_colorbar(colormap): colorbar.tools.append(RangeSelection(component=colorbar)) colorbar.overlays.append( RangeSelectionOverlay( - component=colorbar, border_color="white", alpha=0.8, fill_color="lightgray" + component=colorbar, + border_color="white", + alpha=0.8, + fill_color="lightgray", ) ) return colorbar diff --git a/examples/demo/basic/draw_layers.py b/examples/demo/basic/draw_layers.py index 9ad376d0b..c7f93e427 100644 --- a/examples/demo/basic/draw_layers.py +++ b/examples/demo/basic/draw_layers.py @@ -39,7 +39,9 @@ def _create_plot_component(): for i in range(3): y_name = "struve" + str(i) pd.set_data(y_name, struve(i, x)) - renderer = plot.plot(("x", y_name), color="blue", name=y_name, line_width=2)[0] + renderer = plot.plot( + ("x", y_name), color="blue", name=y_name, line_width=2 + )[0] renderer.draw_layer = "struve" renderer.unified_draw = True @@ -47,7 +49,9 @@ def _create_plot_component(): for i in range(3): y_name = "bessel" + str(i) pd.set_data(y_name, jn(i, x)) - renderer = plot.plot(("x", y_name), color="green", name=y_name, line_width=2)[0] + renderer = plot.plot( + ("x", y_name), color="green", name=y_name, line_width=2 + )[0] renderer.draw_layer = "bessel" renderer.unified_draw = True @@ -55,7 +59,9 @@ def _create_plot_component(): for i in range(3): y_name = "sine" + str(i) pd.set_data(y_name, sin(x * (i + 1) / 1.5)) - renderer = plot.plot(("x", y_name), color="red", name=y_name, line_width=2)[0] + renderer = plot.plot( + ("x", y_name), color="red", name=y_name, line_width=2 + )[0] renderer.draw_layer = "sine" renderer.unified_draw = True diff --git a/examples/demo/basic/grid_container.py b/examples/demo/basic/grid_container.py index ca57d0cd5..c004d04ee 100644 --- a/examples/demo/basic/grid_container.py +++ b/examples/demo/basic/grid_container.py @@ -80,7 +80,9 @@ def _create_plot_component(): ul_plot = container.components[0] ul_plot.resizable = "v" ul_plot.width = 200 - ul_plot.overlays.append(PlotLabel("Not horizontally resizable", component=ul_plot)) + ul_plot.overlays.append( + PlotLabel("Not horizontally resizable", component=ul_plot) + ) # Set the bottom center plot to have a fixed width and height. # This also constrains the height of the bottom row and the width of @@ -93,7 +95,8 @@ def _create_plot_component(): container.padding_top = 50 container.overlays.append( PlotLabel( - "Resize the window - some plots resize, others cannot " "(see source code)", + "Resize the window - some plots resize, others cannot " + "(see source code)", component=container, font="swiss 16", overlay_position="top", diff --git a/examples/demo/basic/hittest_tool.py b/examples/demo/basic/hittest_tool.py index d2bd08cf7..4f45db75c 100644 --- a/examples/demo/basic/hittest_tool.py +++ b/examples/demo/basic/hittest_tool.py @@ -96,7 +96,9 @@ class Demo(HasTraits): plot = Instance(Component) traits_view = View( - UItem("plot", editor=ComponentEditor(size=size)), resizable=True, title=title + UItem("plot", editor=ComponentEditor(size=size)), + resizable=True, + title=title, ) def _plot_default(self): diff --git a/examples/demo/basic/horizon_plot.py b/examples/demo/basic/horizon_plot.py index dcd2c4efd..8c9f890c7 100644 --- a/examples/demo/basic/horizon_plot.py +++ b/examples/demo/basic/horizon_plot.py @@ -73,7 +73,9 @@ def _create_plot_components(): value_ds = ArrayDataSource(changes, sort_order="none") value_range = DataRange1D(value_ds, low=-high, high=high) - index_mapper = LinearMapper(range=DataRange1D(index_ds), stretch_data=False) + index_mapper = LinearMapper( + range=DataRange1D(index_ds), stretch_data=False + ) horizon = HorizonPlot( bands=4, @@ -83,7 +85,9 @@ def _create_plot_components(): value_mapper=BandedMapper(range=DataRange1D(low=0, high=high)), color_mapper=cmap(range=value_range), ) - horizon.tools.append(PanTool(horizon, constrain=True, constrain_direction="x")) + horizon.tools.append( + PanTool(horizon, constrain=True, constrain_direction="x") + ) axis = PlotAxis( mapper=horizon.value_mapper, component=horizon, @@ -107,7 +111,9 @@ def _create_plot_components(): fill_color=(0.81960784, 0.89803922, 0.94117647), edge_color="transparent", ) - filled.tools.append(PanTool(filled, constrain=True, constrain_direction="x")) + filled.tools.append( + PanTool(filled, constrain=True, constrain_direction="x") + ) axis = PlotAxis( mapper=filled.value_mapper, component=filled, @@ -136,7 +142,9 @@ def _create_plot_components(): ) padding = (40, 20, 0, 0) - over1 = HPlotContainer(use_backbuffer=True, padding=padding, padding_top=20) + over1 = HPlotContainer( + use_backbuffer=True, padding=padding, padding_top=20 + ) over1.add(filled) over1.add(colorbar) @@ -159,9 +167,15 @@ class Demo(HasTraits): traits_view = View( Group( - Item("filled", editor=ComponentEditor(size=filled_size), show_label=False), Item( - "horizon", editor=ComponentEditor(size=horizon_size), show_label=False + "filled", + editor=ComponentEditor(size=filled_size), + show_label=False, + ), + Item( + "horizon", + editor=ComponentEditor(size=horizon_size), + show_label=False, ), orientation="vertical", ), diff --git a/examples/demo/basic/image_from_file.py b/examples/demo/basic/image_from_file.py index 8e46f4911..7e187b614 100644 --- a/examples/demo/basic/image_from_file.py +++ b/examples/demo/basic/image_from_file.py @@ -18,7 +18,14 @@ from traits.util.resource import find_resource from traits.api import File, HasTraits, Instance from traitsui.api import Handler, Item, View -from traitsui.menu import Action, CloseAction, Menu, MenuBar, OKCancelButtons, Separator +from traitsui.menu import ( + Action, + CloseAction, + Menu, + MenuBar, + OKCancelButtons, + Separator, +) # Chaco imports from chaco.api import ArrayPlotData, ImageData, Plot, PlotGraphicsContext @@ -109,7 +116,9 @@ def default_traits_view(self): ), menubar=MenuBar( Menu( - Action(name="Save Plot", action="save"), # see Controller for + Action( + name="Save Plot", action="save" + ), # see Controller for Action(name="Load Plot", action="load"), # these callbacks Separator(), CloseAction, diff --git a/examples/demo/basic/image_inspector.py b/examples/demo/basic/image_inspector.py index 8f4d4f587..427c92c5d 100644 --- a/examples/demo/basic/image_inspector.py +++ b/examples/demo/basic/image_inspector.py @@ -24,7 +24,10 @@ # Chaco imports from chaco.api import ArrayPlotData, viridis, Plot from chaco.tools.api import PanTool, ZoomTool -from chaco.tools.image_inspector_tool import ImageInspectorTool, ImageInspectorOverlay +from chaco.tools.image_inspector_tool import ( + ImageInspectorTool, + ImageInspectorOverlay, +) # =============================================================================== # # Create the Chaco plot. diff --git a/examples/demo/basic/image_lasso.py b/examples/demo/basic/image_lasso.py index 5ae3bfad4..1b916c1e6 100644 --- a/examples/demo/basic/image_lasso.py +++ b/examples/demo/basic/image_lasso.py @@ -67,7 +67,9 @@ def _create_plot_component(): # Create a scalar field to colormap lasso_selection = LassoSelection(component=img_plot) lasso_selection.observe(lasso_updated, "disjoint_selections") - lasso_overlay = LassoOverlay(lasso_selection=lasso_selection, component=img_plot) + lasso_overlay = LassoOverlay( + lasso_selection=lasso_selection, component=img_plot + ) img_plot.tools.append(lasso_selection) img_plot.overlays.append(lasso_overlay) return plot diff --git a/examples/demo/basic/image_plot.py b/examples/demo/basic/image_plot.py index f27e413d9..7d5050ddb 100644 --- a/examples/demo/basic/image_plot.py +++ b/examples/demo/basic/image_plot.py @@ -20,7 +20,10 @@ # Chaco imports from chaco.api import ArrayPlotData, Plot from chaco.tools.api import PanTool, ZoomTool -from chaco.tools.image_inspector_tool import ImageInspectorTool, ImageInspectorOverlay +from chaco.tools.image_inspector_tool import ( + ImageInspectorTool, + ImageInspectorOverlay, +) # =============================================================================== # # Create the Chaco plot. @@ -48,7 +51,9 @@ def _create_plot_component(): # Attach some tools to the plot plot.tools.append(PanTool(plot, constrain_key="shift")) - plot.overlays.append(ZoomTool(component=plot, tool_mode="box", always_on=False)) + plot.overlays.append( + ZoomTool(component=plot, tool_mode="box", always_on=False) + ) imgtool = ImageInspectorTool(img_plot) img_plot.tools.append(imgtool) diff --git a/examples/demo/basic/line_plot1.py b/examples/demo/basic/line_plot1.py index d2d7af6d9..4e377a1d9 100644 --- a/examples/demo/basic/line_plot1.py +++ b/examples/demo/basic/line_plot1.py @@ -48,7 +48,11 @@ def _create_plot_component(): # Create a second scatter plot of one of the datasets, linking its # range to the first plot plot2 = Plot( - pd, range2d=plot1.range2d, title="Scatter plot", padding=60, border_visible=True + pd, + range2d=plot1.range2d, + title="Scatter plot", + padding=60, + border_visible=True, ) plot2.plot(("index", "y3"), type="scatter", color="blue", marker="circle") diff --git a/examples/demo/basic/line_plot_hold.py b/examples/demo/basic/line_plot_hold.py index 3b8cef479..0bc2cc346 100644 --- a/examples/demo/basic/line_plot_hold.py +++ b/examples/demo/basic/line_plot_hold.py @@ -41,7 +41,9 @@ def _create_plot_component(): overlay_border=True, ) plot1.legend.visible = True - lineplot = plot1.plot(("index", "y0"), name="j_0", color="red", render_style="hold") + lineplot = plot1.plot( + ("index", "y0"), name="j_0", color="red", render_style="hold" + ) # Attach some tools to the plot attach_tools(plot1) diff --git a/examples/demo/basic/minard_napoleon.py b/examples/demo/basic/minard_napoleon.py index 9f21e4e02..8f96b169d 100644 --- a/examples/demo/basic/minard_napoleon.py +++ b/examples/demo/basic/minard_napoleon.py @@ -120,8 +120,12 @@ def _create_plot_component(): - army_lat = np.column_stack([army["start_lat"], army["end_lat"]]).reshape(-1) - army_lon = np.column_stack([army["start_lon"], army["end_lon"]]).reshape(-1) + army_lat = np.column_stack([army["start_lat"], army["end_lat"]]).reshape( + -1 + ) + army_lon = np.column_stack([army["start_lon"], army["end_lon"]]).reshape( + -1 + ) plot_data = ArrayPlotData( army_lon=army_lon, diff --git a/examples/demo/basic/nans_plot.py b/examples/demo/basic/nans_plot.py index 4b77a3ff9..9d3d6ca62 100644 --- a/examples/demo/basic/nans_plot.py +++ b/examples/demo/basic/nans_plot.py @@ -41,7 +41,11 @@ def _create_plot_component(): plot = Plot(pd) plot.plot(("index", "value1"), name="j_0(x)", color="red", width=2.0) plot.plot( - ("index", "value2"), type="scatter", marker_size=1, name="j_1(x)", color="green" + ("index", "value2"), + type="scatter", + marker_size=1, + name="j_1(x)", + color="green", ) # Tweak some of the plot properties diff --git a/examples/demo/basic/pandas_data.py b/examples/demo/basic/pandas_data.py index e77a484bf..cf7b4ce8e 100644 --- a/examples/demo/basic/pandas_data.py +++ b/examples/demo/basic/pandas_data.py @@ -28,7 +28,11 @@ class Demo(HasTraits): traits_view = View( Group( - Item("plot", editor=ComponentEditor(size=(900, 500)), show_label=False), + Item( + "plot", + editor=ComponentEditor(size=(900, 500)), + show_label=False, + ), orientation="vertical", ), resizable=True, diff --git a/examples/demo/basic/regression.py b/examples/demo/basic/regression.py index fef43e776..85e36bb1d 100644 --- a/examples/demo/basic/regression.py +++ b/examples/demo/basic/regression.py @@ -21,7 +21,12 @@ # Chaco imports from chaco.api import ArrayPlotData, Plot -from chaco.tools.api import PanTool, ZoomTool, RegressionLasso, RegressionOverlay +from chaco.tools.api import ( + PanTool, + ZoomTool, + RegressionLasso, + RegressionOverlay, +) # =============================================================================== # # Create the Chaco plot. @@ -45,7 +50,9 @@ def _create_plot_component(): # Add the regression tool and overlay. These need to be added # directly to the scatterplot instance (and not the Plot instance). - regression = RegressionLasso(scatterplot, selection_datasource=scatterplot.index) + regression = RegressionLasso( + scatterplot, selection_datasource=scatterplot.index + ) scatterplot.tools.append(regression) scatterplot.overlays.append( RegressionOverlay(scatterplot, lasso_selection=regression) diff --git a/examples/demo/basic/scatter_1d.py b/examples/demo/basic/scatter_1d.py index eff9b6703..6cc065107 100644 --- a/examples/demo/basic/scatter_1d.py +++ b/examples/demo/basic/scatter_1d.py @@ -46,7 +46,11 @@ def _create_plot_component(): ) plot.plot_1d( - "index", type="scatter_1d", orientation="h", marker="plus", alignment="bottom" + "index", + type="scatter_1d", + orientation="h", + marker="plus", + alignment="bottom", ) plot.plot_1d( @@ -58,7 +62,11 @@ def _create_plot_component(): ) plot.plot_1d( - "value", type="scatter_1d", orientation="v", marker="plus", alignment="left" + "value", + type="scatter_1d", + orientation="v", + marker="plus", + alignment="left", ) plot.plot( diff --git a/examples/demo/basic/scatter_inspector2.py b/examples/demo/basic/scatter_inspector2.py index 5d1befbd4..a1f2a6ef8 100644 --- a/examples/demo/basic/scatter_inspector2.py +++ b/examples/demo/basic/scatter_inspector2.py @@ -6,7 +6,12 @@ from traits.api import Callable, Enum, HasTraits, Instance, observe, Str from traitsui.api import View, Item from enable.api import ComponentEditor -from chaco.api import Plot, ArrayPlotData, ScatterInspectorOverlay, TextBoxOverlay +from chaco.api import ( + Plot, + ArrayPlotData, + ScatterInspectorOverlay, + TextBoxOverlay, +) from chaco.api import DataFramePlotData from chaco.tools.api import ScatterInspector diff --git a/examples/demo/basic/scatter_rect_select.py b/examples/demo/basic/scatter_rect_select.py index 134c3a129..d2bb95630 100644 --- a/examples/demo/basic/scatter_rect_select.py +++ b/examples/demo/basic/scatter_rect_select.py @@ -20,7 +20,12 @@ from traitsui.api import Item, Group, View # Chaco imports -from chaco.api import ArrayPlotData, Plot, LassoOverlay, ScatterInspectorOverlay +from chaco.api import ( + ArrayPlotData, + Plot, + LassoOverlay, + ScatterInspectorOverlay, +) from chaco.tools.api import RectangularSelection, ScatterInspector @@ -71,7 +76,9 @@ def _create_plot_component(): my_plot.tools.append(ScatterInspector(my_plot, selection_mode="toggle")) my_plot.active_tool = rect_selection - lasso_overlay = LassoOverlay(lasso_selection=rect_selection, component=my_plot) + lasso_overlay = LassoOverlay( + lasso_selection=rect_selection, component=my_plot + ) my_plot.overlays.append(lasso_overlay) scatter_overlay = ScatterInspectorOverlay( diff --git a/examples/demo/basic/scatter_select.py b/examples/demo/basic/scatter_select.py index 4e7192f12..e602b0033 100644 --- a/examples/demo/basic/scatter_select.py +++ b/examples/demo/basic/scatter_select.py @@ -65,12 +65,16 @@ def _create_plot_component(): # Attach some tools to the plot lasso_selection = LassoSelection( - component=my_plot, selection_datasource=my_plot.index, drag_button="left" + component=my_plot, + selection_datasource=my_plot.index, + drag_button="left", ) # drag_button="right") my_plot.active_tool = lasso_selection my_plot.tools.append(ScatterInspector(my_plot)) - lasso_overlay = LassoOverlay(lasso_selection=lasso_selection, component=my_plot) + lasso_overlay = LassoOverlay( + lasso_selection=lasso_selection, component=my_plot + ) my_plot.overlays.append(lasso_overlay) # Uncomment this if you would like to see incremental updates: diff --git a/examples/demo/basic/scatter_toggle.py b/examples/demo/basic/scatter_toggle.py index 49ef4f433..7fbce9f3c 100644 --- a/examples/demo/basic/scatter_toggle.py +++ b/examples/demo/basic/scatter_toggle.py @@ -24,7 +24,12 @@ from traitsui.api import Item, VGroup, View, Label, HGroup, spring # Chaco imports -from chaco.api import AbstractDataSource, ArrayPlotData, Plot, ScatterInspectorOverlay +from chaco.api import ( + AbstractDataSource, + ArrayPlotData, + Plot, + ScatterInspectorOverlay, +) from chaco.tools.api import ScatterInspector, PanTool, ZoomTool # =============================================================================== @@ -66,7 +71,9 @@ def _create_plot_component(): # Attach some tools to the plot my_plot.tools.append( - ScatterInspector(my_plot, selection_mode="toggle", persistent_hover=False) + ScatterInspector( + my_plot, selection_mode="toggle", persistent_hover=False + ) ) my_plot.overlays.append( ScatterInspectorOverlay( @@ -127,7 +134,9 @@ def _plot_default(self): # Set up the trait handler for the selection self.index_datasource = my_plot.index - self.index_datasource.observe(self._metadata_handler, "metadata_changed") + self.index_datasource.observe( + self._metadata_handler, "metadata_changed" + ) return plot diff --git a/examples/demo/basic/scrollbar.py b/examples/demo/basic/scrollbar.py index 40670f12b..bab266584 100644 --- a/examples/demo/basic/scrollbar.py +++ b/examples/demo/basic/scrollbar.py @@ -46,7 +46,9 @@ def _create_plot_component(): plot1.overlays.append(zoom) # Add the scrollbar - hscrollbar = PlotScrollBar(component=plot1, axis="index", resizable="h", height=15) + hscrollbar = PlotScrollBar( + component=plot1, axis="index", resizable="h", height=15 + ) plot1.padding_top = 0 hscrollbar.force_data_update() diff --git a/examples/demo/basic/tabbed_plots.py b/examples/demo/basic/tabbed_plots.py index 822ff2cc0..a0ead7e05 100644 --- a/examples/demo/basic/tabbed_plots.py +++ b/examples/demo/basic/tabbed_plots.py @@ -61,7 +61,9 @@ def create_plot(self, data, name, color): def create_plots(self): self.plot_sin = self.create_plot(("x", "ysin"), "sin plot", "red") self.plot_tan = self.create_plot(("x", "ytan"), "tan plot", "blue") - self.plot_mixed = self.create_plot(("x", "ymix"), "mixed plot", "green") + self.plot_mixed = self.create_plot( + ("x", "ymix"), "mixed plot", "green" + ) # The mixed plot will share both x and y ranges with the sin plot. # This 2d range is a single object shared by both plots. For its @@ -85,7 +87,9 @@ def _data_changed(self): # =============================================================================== x = linspace(-2 * pi, 2 * pi, 100) demo = TabbedPlots( - data=ArrayPlotData(x=x, ysin=sin(x), ytan=tan(x), ymix=sin(x) ** 2 + cos(x)) + data=ArrayPlotData( + x=x, ysin=sin(x), ytan=tan(x), ymix=sin(x) ** 2 + cos(x) + ) ) if __name__ == "__main__": diff --git a/examples/demo/basic/zoomable_colorbar.py b/examples/demo/basic/zoomable_colorbar.py index fd7019a85..7f2c979a4 100644 --- a/examples/demo/basic/zoomable_colorbar.py +++ b/examples/demo/basic/zoomable_colorbar.py @@ -91,14 +91,22 @@ def _create_plot_component(): colorbar.padding_bottom = plot.padding_bottom # Add pan and zoom tools to the colorbar - colorbar.tools.append(PanTool(colorbar, constrain_direction="y", constrain=True)) + colorbar.tools.append( + PanTool(colorbar, constrain_direction="y", constrain=True) + ) zoom_overlay = ZoomTool( - colorbar, axis="index", tool_mode="range", always_on=True, drag_button="right" + colorbar, + axis="index", + tool_mode="range", + always_on=True, + drag_button="right", ) colorbar.overlays.append(zoom_overlay) # Create a container to position the plot and the colorbar side-by-side - container = HPlotContainer(plot, colorbar, use_backbuffer=True, bgcolor="lightgray") + container = HPlotContainer( + plot, colorbar, use_backbuffer=True, bgcolor="lightgray" + ) return container diff --git a/examples/demo/bigdata.py b/examples/demo/bigdata.py index 8fa355cea..2e0d09abc 100644 --- a/examples/demo/bigdata.py +++ b/examples/demo/bigdata.py @@ -58,7 +58,9 @@ def _create_plot_component(use_downsampling=True): index_mapper = None for i in range(10): y = jn(i, x) - plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[i]), width=2.0) + plot = create_line_plot( + (x, y), color=tuple(COLOR_PALETTE[i]), width=2.0 + ) plot.use_downsampling = use_downsampling if value_mapper is None: diff --git a/examples/demo/canvas/axis_tool.py b/examples/demo/canvas/axis_tool.py index 12fa84700..b6f52e682 100644 --- a/examples/demo/canvas/axis_tool.py +++ b/examples/demo/canvas/axis_tool.py @@ -1,5 +1,15 @@ from enable.api import BaseTool, ColorTrait -from traits.api import Any, Bool, Dict, Enum, HasTraits, Int, List, Trait, Tuple +from traits.api import ( + Any, + Bool, + Dict, + Enum, + HasTraits, + Int, + List, + Trait, + Tuple, +) class RangeController(HasTraits): @@ -29,7 +39,9 @@ def notify(self, axistool, rangename, type, event): return True def link(self, src_range, dst_plot, dst_rangename): - self._ranges[(dst_plot, dst_rangename)] = getattr(dst_plot, dst_rangename) + self._ranges[(dst_plot, dst_rangename)] = getattr( + dst_plot, dst_rangename + ) setattr(dst_plot, dst_rangename, src_range) dst_plot.request_redraw() @@ -88,7 +100,9 @@ def normal_left_down(self, event): # If we have a controller, we let it decide whether # or not we get to handle the event. if self.range_controller is not None: - should_handle = self.range_controller.notify(self, rangename, "down", event) + should_handle = self.range_controller.notify( + self, rangename, "down", event + ) if not should_handle: return @@ -117,7 +131,9 @@ def normal_left_up(self, event): return if self.range_controller is not None: - should_handle = self.range_controller.notify(self, rangename, "up", event) + should_handle = self.range_controller.notify( + self, rangename, "up", event + ) if not should_handle: return @@ -138,7 +154,9 @@ def normal_blob_down(self, event): if self.cur_bid == -1: self.cur_bid = event.bid if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, event.net_transform()) + event.window.capture_blob( + self, event.bid, event.net_transform() + ) self.normal_left_down(event) self._last_blob_pos = (event.x, event.y) diff --git a/examples/demo/canvas/canvas.py b/examples/demo/canvas/canvas.py index ccebbbc7b..ac34c7b74 100644 --- a/examples/demo/canvas/canvas.py +++ b/examples/demo/canvas/canvas.py @@ -47,7 +47,13 @@ # Multitouch imports if MULTITOUCH: - from mptools import MPPanTool, MPDragZoom, MPLegendTool, MPPanZoom, MPRangeSelection + from mptools import ( + MPPanTool, + MPDragZoom, + MPLegendTool, + MPPanZoom, + MPRangeSelection, + ) # AxisTool = MPAxisTool PlotCloneTool = MPPlotCloneTool @@ -335,13 +341,20 @@ def make_toolbar(canvas): else: plot.tools.append( PanTool( - plot, drag_button="right", constrain=True, constrain_direction="x" + plot, + drag_button="right", + constrain=True, + constrain_direction="x", ) ) plot.tools.append( - ZoomTool(plot, tool_mode="range", axis="index", always_on=False) + ZoomTool( + plot, tool_mode="range", axis="index", always_on=False + ) ) - plot.overlays.append(PlotCloneTool(plot, dest=canvas, plot_cloner=clone_plot)) + plot.overlays.append( + PlotCloneTool(plot, dest=canvas, plot_cloner=clone_plot) + ) plot_overlay = TransientPlotOverlay( component=toolbar, overlay_component=plot, @@ -381,7 +394,9 @@ def _create_viewport(self): if MULTITOUCH: viewport.tools.append(MPViewportPanTool(viewport)) else: - viewport.tools.append(ViewportPanTool(viewport, drag_button="right")) + viewport.tools.append( + ViewportPanTool(viewport, drag_button="right") + ) return viewport def _create_window_mt(self): @@ -397,7 +412,9 @@ def _create_window_mt(self): tconf = cfg.tconf tconf.from_arguments(args) - provider = NetworkBlobProvider(host=tconf.Server.host, port=tconf.Server.port) + provider = NetworkBlobProvider( + host=tconf.Server.host, port=tconf.Server.port + ) provider.start() return BlobWindow(self, -1, component=viewport, blob_provider=provider) diff --git a/examples/demo/canvas/cliptest.py b/examples/demo/canvas/cliptest.py index 9fc1163e1..8b2a8abdc 100644 --- a/examples/demo/canvas/cliptest.py +++ b/examples/demo/canvas/cliptest.py @@ -75,11 +75,18 @@ def _create_window(self): b = Box(bounds=[75, 75], position=[200, 50], fill_color=(0, 1, 0, 1)) c = Box(bounds=[75, 75], position=[50, 200], fill_color=(0, 0, 1, 1)) cont = Container( - a, b, c, bounds=[400, 400], border_visible=True, bgcolor="lightgray" + a, + b, + c, + bounds=[400, 400], + border_visible=True, + bgcolor="lightgray", ) # cont.unified_draw = True # cont.draw_layer = "background" - cont2 = Container(bounds=[300, 300], border_visible=True, bgcolor="cyan") + cont2 = Container( + bounds=[300, 300], border_visible=True, bgcolor="cyan" + ) cont.tools.append(MoveTool(cont, drag_button="left")) cont2.tools.append(MoveTool(cont2, drag_button="left")) outer = Container(cont, cont2, fit_window=True) diff --git a/examples/demo/canvas/data_source_button.py b/examples/demo/canvas/data_source_button.py index 237b7cdbd..7b2a3e559 100644 --- a/examples/demo/canvas/data_source_button.py +++ b/examples/demo/canvas/data_source_button.py @@ -167,7 +167,9 @@ def normal_blob_down(self, event): self.cur_bid = event.bid self.normal_left_down(event) if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, event.net_transform()) + event.window.capture_blob( + self, event.bid, event.net_transform() + ) def normal_blob_up(self, event): if event.bid == self.cur_bid: diff --git a/examples/demo/canvas/mp_viewport_pan_tool.py b/examples/demo/canvas/mp_viewport_pan_tool.py index b302f2d9e..d40ca181b 100644 --- a/examples/demo/canvas/mp_viewport_pan_tool.py +++ b/examples/demo/canvas/mp_viewport_pan_tool.py @@ -27,7 +27,9 @@ def drag_start(self, event): if self.component: self.original_padding = self.component.padding if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, event.net_transform()) + event.window.capture_blob( + self, event.bid, event.net_transform() + ) else: event.window.set_mouse_owner(self, event.net_transform()) self._last_blob_pos = (event.x, event.y) diff --git a/examples/demo/canvas/mptools.py b/examples/demo/canvas/mptools.py index c81dcef90..ba4097486 100644 --- a/examples/demo/canvas/mptools.py +++ b/examples/demo/canvas/mptools.py @@ -125,7 +125,9 @@ def drag_start(self, event, capture_mouse=False): def normal_blob_down(self, event): if len(self._blobs) < 2: self._blobs[event.bid] = (event.x, event.y) - event.window.capture_blob(self, event.bid, transform=event.net_transform()) + event.window.capture_blob( + self, event.bid, transform=event.net_transform() + ) event.handled = True def normal_blob_up(self, event): @@ -167,7 +169,10 @@ def dragging_blob_frame_end(self, event): for ndx in (0, 1): if self._zoom_limit_reached( - orig_screen_low[ndx], orig_screen_high[ndx], new_low[ndx], new_high[ndx] + orig_screen_low[ndx], + orig_screen_high[ndx], + new_low[ndx], + new_high[ndx], ): return @@ -265,7 +270,9 @@ def drag_start(self, event): if self.component: self.original_padding = self.component.padding if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, event.net_transform()) + event.window.capture_blob( + self, event.bid, event.net_transform() + ) else: event.window.set_mouse_owner(self, event.net_transform()) self.mouse_down_position = (event.x, event.y) @@ -314,7 +321,9 @@ def _get__axis_moves(self): def normal_blob_down(self, event): if len(self._blobs) < 2: self._blobs[event.bid] = (event.x, event.y) - event.window.capture_blob(self, event.bid, transform=event.net_transform()) + event.window.capture_blob( + self, event.bid, transform=event.net_transform() + ) event.handled = True def normal_blob_up(self, event): @@ -363,7 +372,9 @@ def selecting_blob_frame_end(self, event): def selected_blob_down(self, event): if len(self._blobs) < 2: self._blobs[event.bid] = (event.x, event.y) - event.window.capture_blob(self, event.bid, transform=event.net_transform()) + event.window.capture_blob( + self, event.bid, transform=event.net_transform() + ) event.handled = True def selected_blob_move(self, event): diff --git a/examples/demo/canvas/plot_clone_tool.py b/examples/demo/canvas/plot_clone_tool.py index a5371a869..96d2d652e 100644 --- a/examples/demo/canvas/plot_clone_tool.py +++ b/examples/demo/canvas/plot_clone_tool.py @@ -120,7 +120,9 @@ def drag_start(self, event): if self.component: self.original_padding = self.component.padding if hasattr(event, "bid"): - event.window.capture_blob(self, event.bid, event.net_transform()) + event.window.capture_blob( + self, event.bid, event.net_transform() + ) else: event.window.set_mouse_owner(self, event.net_transform()) self.mouse_down_position = (event.x, event.y) @@ -137,6 +139,10 @@ def drag_end(self, event): drop_position = self._last_blob_pos if len(drop_position) == 2: self.plot_cloner( - self, (drop_position[0] - offset[0], drop_position[1] - offset[1]) + self, + ( + drop_position[0] - offset[0], + drop_position[1] - offset[1], + ), ) self._offset = None diff --git a/examples/demo/chaco_trait_editor.py b/examples/demo/chaco_trait_editor.py index 6eded502d..ba52f376a 100644 --- a/examples/demo/chaco_trait_editor.py +++ b/examples/demo/chaco_trait_editor.py @@ -87,7 +87,10 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): gc.set_line_width(self.border_width) gc.rect( - start + self.radius, mid_y - 1, (end - start - 2 * self.radius), 2 + start + self.radius, + mid_y - 1, + (end - start - 2 * self.radius), + 2, ) gc.draw_path() @@ -114,7 +117,9 @@ class IntervalEditorImpl(Editor): def init(self, parent): factory = self.factory - container = OverlayPlotContainer(bgcolor="transparent", padding=0, spacing=0) + container = OverlayPlotContainer( + bgcolor="transparent", padding=0, spacing=0 + ) window = Window(parent, component=container) @@ -178,7 +183,9 @@ def update_editor(self): class IntervalTest(HasTraits): interval = Interval(low=0, high=1) - traits_view = View(Item("interval", editor=IntervalEditor()), resizable=True) + traits_view = View( + Item("interval", editor=IntervalEditor()), resizable=True + ) it = IntervalTest() it.configure_traits() diff --git a/examples/demo/cursor_tool_demo.py b/examples/demo/cursor_tool_demo.py index 9d65adcc5..79ae5ef2e 100644 --- a/examples/demo/cursor_tool_demo.py +++ b/examples/demo/cursor_tool_demo.py @@ -119,7 +119,9 @@ def __init__(self): ), springy=True, ), - HGroup(Item("cursor1pos", width=300), Item("cursor2pos", width=300)), + HGroup( + Item("cursor1pos", width=300), Item("cursor2pos", width=300) + ), ), title="Cursor Tool Demo", resizable=True, diff --git a/examples/demo/data_labels.py b/examples/demo/data_labels.py index 833fc29b9..555fef1d7 100644 --- a/examples/demo/data_labels.py +++ b/examples/demo/data_labels.py @@ -53,7 +53,10 @@ class PlotExample(HasTraits): def _plot_default(self): container = OverlayPlotContainer( - padding=50, fill_padding=True, bgcolor="lightgray", use_backbuffer=True + padding=50, + fill_padding=True, + bgcolor="lightgray", + use_backbuffer=True, ) # Create the initial X-series of data @@ -62,7 +65,9 @@ def _plot_default(self): high = self.high x = linspace(low, high, numpoints + 1) y = jn(0, x) - plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[0]), width=2.0) + plot = create_line_plot( + (x, y), color=tuple(COLOR_PALETTE[0]), width=2.0 + ) plot.index.sort_order = "ascending" plot.bgcolor = "white" plot.border_visible = True @@ -131,7 +136,9 @@ def _plot_default(self): bgcolor=(1, 1, 0.75, 1), ) plot.overlays.append(label4) - tool4 = DataLabelTool(label4, drag_button="right", auto_arrow_root=True) + tool4 = DataLabelTool( + label4, drag_button="right", auto_arrow_root=True + ) label4.tools.append(tool4) # Another 'bubble' label. This one sets arrow_min_length=20, so @@ -152,7 +159,9 @@ def _plot_default(self): bgcolor=(0.75, 0.75, 0.75, 1), ) plot.overlays.append(label5) - tool5 = DataLabelTool(label5, drag_button="right", auto_arrow_root=True) + tool5 = DataLabelTool( + label5, drag_button="right", auto_arrow_root=True + ) label5.tools.append(tool5) container.add(plot) diff --git a/examples/demo/data_view.py b/examples/demo/data_view.py index b11150879..65279e6ea 100644 --- a/examples/demo/data_view.py +++ b/examples/demo/data_view.py @@ -5,7 +5,13 @@ from numpy import linspace, sin, cos # Enthought library imports. -from chaco.api import DataView, ArrayDataSource, ScatterPlot, LinePlot, LinearMapper +from chaco.api import ( + DataView, + ArrayDataSource, + ScatterPlot, + LinePlot, + LinearMapper, +) from chaco.tools.api import PanTool, ZoomTool from enable.api import Component, ComponentEditor from traits.api import HasTraits, Instance diff --git a/examples/demo/depth.py b/examples/demo/depth.py index 892523f37..358e209a2 100644 --- a/examples/demo/depth.py +++ b/examples/demo/depth.py @@ -18,7 +18,10 @@ class MyPlot(HasTraits): plot = Instance(ToolbarPlot) traits_view = View( - UItem("plot", editor=ComponentEditor()), width=600, height=600, resizable=True + UItem("plot", editor=ComponentEditor()), + width=600, + height=600, + resizable=True, ) def __init__(self, depth, data_series, **kw): diff --git a/examples/demo/domain_limits.py b/examples/demo/domain_limits.py index 2adc4139d..39d1fded6 100644 --- a/examples/demo/domain_limits.py +++ b/examples/demo/domain_limits.py @@ -18,7 +18,13 @@ class ExamplePlotApp(HasTraits): plot = Instance(Plot) traits_view = View( - Item("plot", editor=ComponentEditor(), width=600, height=600, show_label=False), + Item( + "plot", + editor=ComponentEditor(), + width=600, + height=600, + show_label=False, + ), resizable=True, ) diff --git a/examples/demo/edit_line.py b/examples/demo/edit_line.py index 0614f9e49..b76359da4 100644 --- a/examples/demo/edit_line.py +++ b/examples/demo/edit_line.py @@ -79,7 +79,10 @@ def drag_start(self, event): if ndx is None: return self._drag_index = ndx - self._orig_value = (plot.index.get_data()[ndx], plot.value.get_data()[ndx]) + self._orig_value = ( + plot.index.get_data()[ndx], + plot.value.get_data()[ndx], + ) def dragging(self, event): plot = self.component @@ -125,7 +128,9 @@ def _lookup_point(self, x, y): if hasattr(self.component, "get_closest_point"): # This is on BaseXYPlots - return self.component.get_closest_point((x, y), threshold=self.threshold) + return self.component.get_closest_point( + (x, y), threshold=self.threshold + ) return None @@ -146,7 +151,9 @@ def _create_plot_component(): x = linspace(low, high, numpoints) y = jn(0, x) - lineplot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[0]), width=2.0) + lineplot = create_line_plot( + (x, y), color=tuple(COLOR_PALETTE[0]), width=2.0 + ) lineplot.selected_color = "none" scatter = ScatterPlot( index=lineplot.index, @@ -179,7 +186,10 @@ def _create_plot_component(): # Add the title at the top container.overlays.append( PlotLabel( - "Line Editor", component=container, font="swiss 16", overlay_position="top" + "Line Editor", + component=container, + font="swiss 16", + overlay_position="top", ) ) diff --git a/examples/demo/financial/correlations.py b/examples/demo/financial/correlations.py index 2ca7e45dc..d134846d8 100644 --- a/examples/demo/financial/correlations.py +++ b/examples/demo/financial/correlations.py @@ -71,7 +71,10 @@ class PlotApp(HasTraits): Item("sym2", width=-225), ), Item( - "corr_plot", editor=ComponentEditor(), show_label=False, width=-275 + "corr_plot", + editor=ComponentEditor(), + show_label=False, + width=-275, ), ), ), @@ -106,14 +109,19 @@ def _create_returns_plot(self): if name == "times": continue renderer = plot.plot( - ("times", name), type="line", name=name, color=tuple(COLOR_PALETTE[i]) + ("times", name), + type="line", + name=name, + color=tuple(COLOR_PALETTE[i]), )[0] # Tricky: need to set auto_handle_event on the RangeSelection # so that it passes left-clicks to the PanTool # FIXME: The range selection is still getting the initial left down renderer.tools.append( - RangeSelection(renderer, left_button_selects=False, auto_handle_event=False) + RangeSelection( + renderer, left_button_selects=False, auto_handle_event=False + ) ) plot.tools.append( PanTool( @@ -126,7 +134,10 @@ def _create_returns_plot(self): ) plot.overlays.append( ZoomTool( - plot, tool_mode="range", max_zoom_out=1.0, x_min_zoom_factor=float(1e-3) + plot, + tool_mode="range", + max_zoom_out=1.0, + x_min_zoom_factor=float(1e-3), ) ) # Attach the range selection to the last renderer; any one will do @@ -193,7 +204,9 @@ def _update_corr_symbols(self, event): (self.sym1, self.sym2), type="scatter", color="blue" )[0] self.corr_renderer.overlays.append( - ScatterInspectorOverlay(self.corr_renderer, selection_color="lightgreen") + ScatterInspectorOverlay( + self.corr_renderer, selection_color="lightgreen" + ) ) plot.request_redraw() diff --git a/examples/demo/financial/stock_prices.py b/examples/demo/financial/stock_prices.py index 58ddec1d9..77351ef67 100644 --- a/examples/demo/financial/stock_prices.py +++ b/examples/demo/financial/stock_prices.py @@ -31,7 +31,12 @@ FilledLinePlot, add_default_grids, ) -from chaco.tools.api import PanTool, ZoomTool, RangeSelection, RangeSelectionOverlay +from chaco.tools.api import ( + PanTool, + ZoomTool, + RangeSelection, + RangeSelectionOverlay, +) from chaco.scales.api import CalendarScaleSystem from chaco.scales_tick_generator import ScalesTickGenerator @@ -114,7 +119,9 @@ def _create_price_plots(self, times, prices, mini_height=75): # of the main price_plot range_tool = RangeSelection(miniplot) miniplot.tools.append(range_tool) - range_overlay = RangeSelectionOverlay(miniplot, metadata_name="selections") + range_overlay = RangeSelectionOverlay( + miniplot, metadata_name="selections" + ) miniplot.overlays.append(range_overlay) range_tool.observe(self._range_selection_handler, "selection") @@ -194,7 +201,9 @@ def _create_component(self): # Set the plot's bottom axis to use the Scales ticking system ticker = ScalesTickGenerator(scale=CalendarScaleSystem()) for plot in price_plot, mini_plot, vol_plot: - bottom_axis = PlotAxis(plot, orientation="bottom", tick_generator=ticker) + bottom_axis = PlotAxis( + plot, orientation="bottom", tick_generator=ticker + ) plot.overlays.append(bottom_axis) plot.overlays.append(PlotAxis(plot, orientation="left")) hgrid, vgrid = add_default_grids(plot) @@ -211,4 +220,6 @@ def _create_component(self): if __name__ == "__main__": # Save demo so that it doesn't get garbage collected when run within # existing event loop (i.e. from ipython). - demo = demo_main(PlotFrame, size=(800, 600), title="Stock price and volume") + demo = demo_main( + PlotFrame, size=(800, 600), title="Stock price and volume" + ) diff --git a/examples/demo/financial_plot.py b/examples/demo/financial_plot.py index e97bbfece..fa50611d5 100644 --- a/examples/demo/financial_plot.py +++ b/examples/demo/financial_plot.py @@ -90,7 +90,9 @@ def _create_plot_component(): add_default_grids(vol_plot) vol_plot.underlays.append(PlotAxis(vol_plot, orientation="left")) - vol_plot.tools.append(PanTool(vol_plot, constrain=True, constrain_direction="x")) + vol_plot.tools.append( + PanTool(vol_plot, constrain=True, constrain_direction="x") + ) container = VPlotContainer( bgcolor="lightblue", spacing=20, padding=50, fill_padding=False diff --git a/examples/demo/financial_plot_dates.py b/examples/demo/financial_plot_dates.py index 8da3089cf..eb5f66526 100644 --- a/examples/demo/financial_plot_dates.py +++ b/examples/demo/financial_plot_dates.py @@ -98,7 +98,10 @@ def _create_plot_component(): price_plot.tools.append( PanTool( - price_plot, constrain=True, constrain_direction="x", restrict_to_data=True + price_plot, + constrain=True, + constrain_direction="x", + restrict_to_data=True, ) ) price_plot.overlays.append( @@ -133,7 +136,9 @@ def _create_plot_component(): # Use the same tick generator as the x-axis on the price plot vgrid.tick_generator = bottom_axis.tick_generator vol_plot.underlays.append(PlotAxis(vol_plot, orientation="left")) - vol_plot.tools.append(PanTool(vol_plot, constrain=True, constrain_direction="x")) + vol_plot.tools.append( + PanTool(vol_plot, constrain=True, constrain_direction="x") + ) container = VPlotContainer( bgcolor="lightblue", spacing=40, padding=50, fill_padding=False diff --git a/examples/demo/functionplotter.py b/examples/demo/functionplotter.py index 604f726ff..2b06ed557 100644 --- a/examples/demo/functionplotter.py +++ b/examples/demo/functionplotter.py @@ -130,7 +130,9 @@ def _plot_default(self): ) container.add(plot2, plot) - plot.tools.append(PanTool(plot, constrain_direction="x", constrain=True)) + plot.tools.append( + PanTool(plot, constrain_direction="x", constrain=True) + ) plot.tools.append(ZoomTool(plot, axis="index", tool_mode="range")) return container diff --git a/examples/demo/image_plot_origin_and_orientation.py b/examples/demo/image_plot_origin_and_orientation.py index cf5aabb4c..7802c3e28 100644 --- a/examples/demo/image_plot_origin_and_orientation.py +++ b/examples/demo/image_plot_origin_and_orientation.py @@ -40,7 +40,10 @@ class Demo(HasTraits): def _plot_default(self): # Create a GridContainer to hold all of our plots: 2 rows, 4 columns: container = GridContainer( - fill_padding=True, bgcolor="lightgray", use_backbuffer=True, shape=(2, 4) + fill_padding=True, + bgcolor="lightgray", + use_backbuffer=True, + shape=(2, 4), ) arrangements = [ diff --git a/examples/demo/logo.py b/examples/demo/logo.py index c2e789e56..43b2496cc 100644 --- a/examples/demo/logo.py +++ b/examples/demo/logo.py @@ -60,10 +60,14 @@ def render_turtle(self, gc, component): def render(self, gc, component): # Uses the component to map our path into screen space nan_mask = invert(isnan(self.path[:, 0])).astype(int) - blocks = [b for b in arg_find_runs(nan_mask, "flat") if nan_mask[b[0]] != 0] + blocks = [ + b for b in arg_find_runs(nan_mask, "flat") if nan_mask[b[0]] != 0 + ] screen_pts = component.map_screen(self.path) with gc: - gc.clip_to_rect(component.x, component.y, component.width, component.height) + gc.clip_to_rect( + component.x, component.y, component.width, component.height + ) gc.set_stroke_color(self.line_color_) for start, end in blocks: gc.begin_path() diff --git a/examples/demo/multi_line_plot.py b/examples/demo/multi_line_plot.py index 07a2efe51..6a7d06906 100644 --- a/examples/demo/multi_line_plot.py +++ b/examples/demo/multi_line_plot.py @@ -20,7 +20,10 @@ class MyPlot(HasTraits): plot = Instance(Plot) traits_view = View( - UItem("plot", editor=ComponentEditor()), width=700, height=600, resizable=True + UItem("plot", editor=ComponentEditor()), + width=700, + height=600, + resizable=True, ) def __init__(self, x_index, y_index, data, **kw): diff --git a/examples/demo/multi_line_plot_demo.py b/examples/demo/multi_line_plot_demo.py index 8fd875c56..317feac07 100644 --- a/examples/demo/multi_line_plot_demo.py +++ b/examples/demo/multi_line_plot_demo.py @@ -12,7 +12,13 @@ from enable.api import ComponentEditor -from chaco.api import LinearMapper, Plot, ArrayDataSource, DataRange1D, PlotAxis +from chaco.api import ( + LinearMapper, + Plot, + ArrayDataSource, + DataRange1D, + PlotAxis, +) from chaco.multi_array_data_source import MultiArrayDataSource from chaco.multi_line_plot import MultiLinePlot @@ -56,7 +62,9 @@ class MultiLinePlotDemo(HasTraits): ), HGroup( Item("object.multi_line_plot_renderer.color", springy=True), - Item("object.multi_line_plot_renderer.line_style", springy=True), + Item( + "object.multi_line_plot_renderer.line_style", springy=True + ), springy=True, ), ), diff --git a/examples/demo/multiaxis.py b/examples/demo/multiaxis.py index 838197b6b..74780fa23 100644 --- a/examples/demo/multiaxis.py +++ b/examples/demo/multiaxis.py @@ -63,7 +63,9 @@ def _create_plot_component(): broadcaster = BroadcasterTool() for i in range(4): y = jn(i, x) - plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[i]), width=2.0) + plot = create_line_plot( + (x, y), color=tuple(COLOR_PALETTE[i]), width=2.0 + ) if i == 0: add_default_grids(plot) left_axis, _ = add_default_axes(plot) @@ -138,7 +140,9 @@ class Demo(HasTraits): plot = Instance(Component) traits_view = View( - VGroup(Item("plot", editor=ComponentEditor(size=size), show_label=False)), + VGroup( + Item("plot", editor=ComponentEditor(size=size), show_label=False) + ), resizable=True, title=title, width=size[0], diff --git a/examples/demo/multiaxis_using_Plot.py b/examples/demo/multiaxis_using_Plot.py index aca3c90ab..313def22e 100644 --- a/examples/demo/multiaxis_using_Plot.py +++ b/examples/demo/multiaxis_using_Plot.py @@ -48,7 +48,9 @@ def _create_plot_component(): x = linspace(-5, 15.0, 100) y = jn(5, x) - foreign_plot = create_line_plot((x, y), color=tuple(COLOR_PALETTE[0]), width=2.0) + foreign_plot = create_line_plot( + (x, y), color=tuple(COLOR_PALETTE[0]), width=2.0 + ) left, bottom = add_default_axes(foreign_plot) left.orientation = "right" bottom.orientation = "top" diff --git a/examples/demo/noninteractive.py b/examples/demo/noninteractive.py index e2836d35b..a78ad98ee 100644 --- a/examples/demo/noninteractive.py +++ b/examples/demo/noninteractive.py @@ -75,7 +75,9 @@ def draw_pdf(filename, size=(800, 600)): container = create_plot() container.outer_bounds = list(size) container.do_layout(force=True) - gc = PdfPlotGraphicsContext(filename=filename, dest_box=(0.5, 0.5, 5.0, 5.0)) + gc = PdfPlotGraphicsContext( + filename=filename, dest_box=(0.5, 0.5, 5.0, 5.0) + ) for i in range(2): # draw the plot diff --git a/examples/demo/nonlinear_color_mapping.py b/examples/demo/nonlinear_color_mapping.py index f9243fd2a..31a1dfce2 100644 --- a/examples/demo/nonlinear_color_mapping.py +++ b/examples/demo/nonlinear_color_mapping.py @@ -134,16 +134,27 @@ def _create_plot_component(model): domain_limits=(renderer.value_range.low, renderer.value_range.high), ) colorbar = ColorBar( - index_mapper=lm, plot=plot, orientation="v", resizable="v", width=30, padding=20 + index_mapper=lm, + plot=plot, + orientation="v", + resizable="v", + width=30, + padding=20, ) colorbar.padding_top = plot.padding_top colorbar.padding_bottom = plot.padding_bottom # Add pan and zoom tools to the colorbar. - colorbar.tools.append(PanTool(colorbar, constrain_direction="y", constrain=True)) + colorbar.tools.append( + PanTool(colorbar, constrain_direction="y", constrain=True) + ) zoom_overlay = ZoomTool( - colorbar, axis="index", tool_mode="range", always_on=True, drag_button="right" + colorbar, + axis="index", + tool_mode="range", + always_on=True, + drag_button="right", ) colorbar.overlays.append(zoom_overlay) @@ -218,25 +229,37 @@ def _colormap_scale_changed(self): self.img_renderer.color_mapper.data_func = log10 self.img_renderer.color_mapper.unit_func = None elif self.colormap_scale == "power [data_func]": - self.img_renderer.color_mapper.data_func = lambda x: x ** self.power + self.img_renderer.color_mapper.data_func = ( + lambda x: x ** self.power + ) self.img_renderer.color_mapper.unit_func = None elif self.colormap_scale == "power [unit_func]": self.img_renderer.color_mapper.data_func = None - self.img_renderer.color_mapper.unit_func = lambda x: x ** self.power + self.img_renderer.color_mapper.unit_func = ( + lambda x: x ** self.power + ) elif self.colormap_scale == "cos [unit_func]": self.img_renderer.color_mapper.data_func = None - self.img_renderer.color_mapper.unit_func = lambda x: cos(0.5 * pi * x) + self.img_renderer.color_mapper.unit_func = lambda x: cos( + 0.5 * pi * x + ) elif self.colormap_scale == "sin [unit_func]": self.img_renderer.color_mapper.data_func = None - self.img_renderer.color_mapper.unit_func = lambda x: sin(0.5 * pi * x) + self.img_renderer.color_mapper.unit_func = lambda x: sin( + 0.5 * pi * x + ) # FIXME: This call to request_redraw() should not be necessary. self.img_renderer.request_redraw() def _power_changed(self): if self.colormap_scale == "power [data_func]": - self.img_renderer.color_mapper.data_func = lambda x: x ** self.power + self.img_renderer.color_mapper.data_func = ( + lambda x: x ** self.power + ) elif self.colormap_scale == "power [unit_func]": - self.img_renderer.color_mapper.unit_func = lambda x: x ** self.power + self.img_renderer.color_mapper.unit_func = ( + lambda x: x ** self.power + ) self.img_renderer.request_redraw() def _colorbar_scale_changed(self): diff --git a/examples/demo/quiver.py b/examples/demo/quiver.py index e8eb5419a..8b94f7e5c 100644 --- a/examples/demo/quiver.py +++ b/examples/demo/quiver.py @@ -34,7 +34,9 @@ class PlotExample(HasTraits): vectorlen = Int(15) traits_view = View( - Item("plot", editor=ComponentEditor(), show_label=False), width=600, height=600 + Item("plot", editor=ComponentEditor(), show_label=False), + width=600, + height=600, ) def _plot_default(self): @@ -45,7 +47,9 @@ def _plot_default(self): # Create vectors. vectorlen = self.vectorlen - vectors = array((random(numpts) * vectorlen, random(numpts) * vectorlen)).T + vectors = array( + (random(numpts) * vectorlen, random(numpts) * vectorlen) + ).T data = ArrayPlotData() data.set_data("index", x) diff --git a/examples/demo/scales_test.py b/examples/demo/scales_test.py index 35bace1fa..ac6cd8f20 100644 --- a/examples/demo/scales_test.py +++ b/examples/demo/scales_test.py @@ -61,7 +61,9 @@ def add_default_axes(plot, orientation="normal", vtitle="", htitle=""): v_mapper = plot.index_mapper h_mapper = plot.value_mapper - left = PlotAxis(orientation="left", title=vtitle, mapper=v_mapper, component=plot) + left = PlotAxis( + orientation="left", title=vtitle, mapper=v_mapper, component=plot + ) bottom = PlotAxis( orientation="bottom", title=htitle, mapper=h_mapper, component=plot @@ -134,7 +136,9 @@ def _create_plot_component(): ) plot.index.sort_order = "ascending" else: - plot = create_scatter_plot((timex, y), color=tuple(COLOR_PALETTE[i])) + plot = create_scatter_plot( + (timex, y), color=tuple(COLOR_PALETTE[i]) + ) plot.bgcolor = "white" plot.border_visible = True if i == 0: @@ -142,7 +146,9 @@ def _create_plot_component(): index_mapper = plot.index_mapper left, bottom = add_default_axes(plot) left.tick_generator = ScalesTickGenerator() - bottom.tick_generator = ScalesTickGenerator(scale=CalendarScaleSystem()) + bottom.tick_generator = ScalesTickGenerator( + scale=CalendarScaleSystem() + ) add_default_grids(plot, tick_gen=bottom.tick_generator) else: plot.value_mapper = value_mapper diff --git a/examples/demo/simple_line.py b/examples/demo/simple_line.py index 30fd82874..3d146cbf6 100644 --- a/examples/demo/simple_line.py +++ b/examples/demo/simple_line.py @@ -54,7 +54,11 @@ def __init__(self, *args, **kws): def _setup_plots(self): """Creates series of Bessel function plots""" plots = {} - x = arange(self.low, self.high + 0.001, (self.high - self.low) / self.numpoints) + x = arange( + self.low, + self.high + 0.001, + (self.high - self.low) / self.numpoints, + ) for i in range(self.num_funs): y = jn(i, x) @@ -63,10 +67,14 @@ def _setup_plots(self): (x, y), color=tuple(COLOR_PALETTE[i]), width=2.0 ) else: - plot = create_scatter_plot((x, y), color=tuple(COLOR_PALETTE[i])) + plot = create_scatter_plot( + (x, y), color=tuple(COLOR_PALETTE[i]) + ) if i == 0: - value_mapper, index_mapper, legend = self._setup_plot_tools(plot) + value_mapper, index_mapper, legend = self._setup_plot_tools( + plot + ) else: self._setup_mapper(plot, value_mapper, index_mapper) @@ -150,7 +158,10 @@ class PlotExample(HasTraits): def _plot_default(self): return OverlappingPlotContainer( - padding=50, fill_padding=True, bgcolor="lightgray", use_backbuffer=True + padding=50, + fill_padding=True, + bgcolor="lightgray", + use_backbuffer=True, ) diff --git a/examples/demo/simple_polar.py b/examples/demo/simple_polar.py index 7a943be6d..6559e4874 100644 --- a/examples/demo/simple_polar.py +++ b/examples/demo/simple_polar.py @@ -28,7 +28,9 @@ def _create_plot_component(): radius = cos(3 * theta) # Create a new polar plot with radius and theta data - plot = create_polar_plot((radius, theta), color=(0.0, 0.0, 1.0, 1), width=4.0) + plot = create_polar_plot( + (radius, theta), color=(0.0, 0.0, 1.0, 1), width=4.0 + ) return plot diff --git a/examples/demo/stacked_axis.py b/examples/demo/stacked_axis.py index 093d6f1cb..0f51c7bbc 100644 --- a/examples/demo/stacked_axis.py +++ b/examples/demo/stacked_axis.py @@ -62,7 +62,9 @@ def _create_plot_component(): # Use the last plot's X mapper to create an X axis and a # vertical grid x_axis = PlotAxis( - orientation="bottom", component=renderer, mapper=renderer.x_mapper + orientation="bottom", + component=renderer, + mapper=renderer.x_mapper, ) renderer.overlays.append(x_axis) grid = PlotGrid( diff --git a/examples/demo/status_overlay.py b/examples/demo/status_overlay.py index 4ec65aac5..02f7d5a87 100644 --- a/examples/demo/status_overlay.py +++ b/examples/demo/status_overlay.py @@ -23,7 +23,11 @@ class MyPlot(HasTraits): no_problem_button = Button("No problem") traits_view = View( - HGroup(UItem("error_button"), UItem("warn_button"), UItem("no_problem_button")), + HGroup( + UItem("error_button"), + UItem("warn_button"), + UItem("no_problem_button"), + ), UItem("plot", editor=ComponentEditor()), width=700, height=600, diff --git a/examples/demo/toolbar_plot.py b/examples/demo/toolbar_plot.py index 0f4ce2232..7c47753f5 100644 --- a/examples/demo/toolbar_plot.py +++ b/examples/demo/toolbar_plot.py @@ -24,7 +24,13 @@ class ExamplePlotApp(HasTraits): plot = Instance(Plot) traits_view = View( - Item("plot", editor=ComponentEditor(), width=600, height=600, show_label=False), + Item( + "plot", + editor=ComponentEditor(), + width=600, + height=600, + show_label=False, + ), resizable=True, ) diff --git a/examples/demo/tornado.py b/examples/demo/tornado.py index 08c54caeb..e296f1e6a 100644 --- a/examples/demo/tornado.py +++ b/examples/demo/tornado.py @@ -60,7 +60,10 @@ def _plot_default(self): labels=label_list, ) vertical2_axis = LabelAxis( - plot, orientation="right", positions=list(range(1, 10)), labels=label_list + plot, + orientation="right", + positions=list(range(1, 10)), + labels=label_list, ) plot.underlays.append(vertical_axis) @@ -97,7 +100,11 @@ def _make_curves(self): # Create the value range value_range = DataRange1D( - vals, vals2, low_setting="auto", high_setting="auto", tight_bounds=False + vals, + vals2, + low_setting="auto", + high_setting="auto", + tight_bounds=False, ) value_mapper = LinearMapper(range=value_range, tight_bounds=False) diff --git a/examples/demo/two_plots.py b/examples/demo/two_plots.py index 610d70ffc..e33fb2172 100644 --- a/examples/demo/two_plots.py +++ b/examples/demo/two_plots.py @@ -32,12 +32,18 @@ def _create_plot_component(): left_plot = Plot(plotdata) left_plot.x_axis.title = "X" left_plot.y_axis.title = "j0(x)" - renderer = left_plot.plot(("x", "y1"), type="line", color="blue", width=2.0)[0] + renderer = left_plot.plot( + ("x", "y1"), type="line", color="blue", width=2.0 + )[0] renderer.overlays.append( - LineInspector(renderer, axis="value", write_metadata=True, is_listener=True) + LineInspector( + renderer, axis="value", write_metadata=True, is_listener=True + ) ) renderer.overlays.append( - LineInspector(renderer, axis="index", write_metadata=True, is_listener=True) + LineInspector( + renderer, axis="index", write_metadata=True, is_listener=True + ) ) left_plot.overlays.append(ZoomTool(left_plot, tool_mode="range")) left_plot.tools.append(PanTool(left_plot)) @@ -48,12 +54,16 @@ def _create_plot_component(): right_plot.orientation = "v" right_plot.x_axis.title = "j1(x)" right_plot.y_axis.title = "X" - renderer2 = right_plot.plot(("x", "y2"), type="line", color="red", width=2.0)[0] + renderer2 = right_plot.plot( + ("x", "y2"), type="line", color="red", width=2.0 + )[0] renderer2.index = renderer.index renderer2.overlays.append( LineInspector(renderer2, write_metadata=True, is_listener=True) ) - renderer2.overlays.append(LineInspector(renderer2, axis="value", is_listener=True)) + renderer2.overlays.append( + LineInspector(renderer2, axis="value", is_listener=True) + ) right_plot.overlays.append(ZoomTool(right_plot, tool_mode="range")) right_plot.tools.append(PanTool(right_plot)) diff --git a/examples/demo/updating_plot/updating_plot1.py b/examples/demo/updating_plot/updating_plot1.py index 6821eeb82..08e5ed180 100644 --- a/examples/demo/updating_plot/updating_plot1.py +++ b/examples/demo/updating_plot/updating_plot1.py @@ -58,7 +58,9 @@ def _create_window(self): self.plot = plot plot.tools.append(PanTool(component=plot)) - plot.overlays.append(ZoomTool(component=plot, tool_mode="box", always_on=False)) + plot.overlays.append( + ZoomTool(component=plot, tool_mode="box", always_on=False) + ) self.timer = Timer(50.0, self.onTimer) return Window(self, -1, component=plot) diff --git a/examples/demo/updating_plot/updating_plot5.py b/examples/demo/updating_plot/updating_plot5.py index a1a4588c1..2e5857915 100644 --- a/examples/demo/updating_plot/updating_plot5.py +++ b/examples/demo/updating_plot/updating_plot5.py @@ -106,7 +106,9 @@ def _create_window(self): plot.index_mapper.range = index_range plot.value_mapper.range = value_range else: - animated_plot = AnimatedPlot(x, jn(i, x), color, orientation="v") + animated_plot = AnimatedPlot( + x, jn(i, x), color, orientation="v" + ) plot = animated_plot.plot container.add(plot) diff --git a/examples/demo/vertical_plot.py b/examples/demo/vertical_plot.py index b073e0a47..c6ff1d1c2 100644 --- a/examples/demo/vertical_plot.py +++ b/examples/demo/vertical_plot.py @@ -17,7 +17,12 @@ from enable.api import Component, ComponentEditor from traits.api import HasTraits, Instance from traitsui.api import Item, Group, View -from chaco.api import PlotLabel, VPlotContainer, HPlotContainer, create_line_plot +from chaco.api import ( + PlotLabel, + VPlotContainer, + HPlotContainer, + create_line_plot, +) # ====================================================================== # Change one or both of these to experiment with different orientations diff --git a/examples/demo/vtk/cmap_scatter.py b/examples/demo/vtk/cmap_scatter.py index a17edcd6d..a0a868fcc 100644 --- a/examples/demo/vtk/cmap_scatter.py +++ b/examples/demo/vtk/cmap_scatter.py @@ -111,7 +111,10 @@ def create_colorbar(colormap): colorbar.tools.append(RangeSelection(component=colorbar)) colorbar.overlays.append( RangeSelectionOverlay( - component=colorbar, border_color="white", alpha=0.8, fill_color="lightgray" + component=colorbar, + border_color="white", + alpha=0.8, + fill_color="lightgray", ) ) colorbar.tools.append(MoveTool(colorbar, drag_button="left")) diff --git a/examples/demo/vtk/spectrum.py b/examples/demo/vtk/spectrum.py index 7ae224d3a..b96ea341e 100644 --- a/examples/demo/vtk/spectrum.py +++ b/examples/demo/vtk/spectrum.py @@ -31,10 +31,14 @@ def create_plot_component(obj): obj.spectrum_data.set_data("amplitude", empty_amplitude) obj.spectrum_plot = Plot(obj.spectrum_data) - obj.spectrum_plot.plot(("frequency", "amplitude"), name="Spectrum", color="red") + obj.spectrum_plot.plot( + ("frequency", "amplitude"), name="Spectrum", color="red" + ) obj.spectrum_plot.padding = 50 obj.spectrum_plot.title = "Spectrum" - spec_range = list(obj.spectrum_plot.plots.values())[0][0].value_mapper.range + spec_range = list(obj.spectrum_plot.plots.values())[0][ + 0 + ].value_mapper.range spec_range.low = 0.0 spec_range.high = 5.0 obj.spectrum_plot.index_axis.title = "Frequency (hz)" @@ -66,7 +70,9 @@ def create_plot_component(obj): float(SPECTROGRAM_LENGTH * NUM_SAMPLES) / float(SAMPLING_RATE), num=SPECTROGRAM_LENGTH, ) - spectrogram_freq = linspace(0.0, float(SAMPLING_RATE / 2), num=NUM_SAMPLES / 2) + spectrogram_freq = linspace( + 0.0, float(SAMPLING_RATE / 2), num=NUM_SAMPLES / 2 + ) xbounds = (spectrogram_time[0], spectrogram_time[-1]) ybounds = (spectrogram_freq[0], spectrogram_freq[-1]) spectrogram_plot.img_plot( @@ -120,7 +126,9 @@ def on_timer(self, vtk_obj=None, eventname=""): self.spectrum_data.set_data("amplitude", spectrum) self.time_data.set_data("amplitude", time) spectrogram_data = self.spectrogram_plotdata.get_data("imagedata") - spectrogram_data = hstack((spectrogram_data[:, 1:], transpose([spectrum]))) + spectrogram_data = hstack( + (spectrogram_data[:, 1:], transpose([spectrum])) + ) self.spectrogram_plotdata.set_data("imagedata", spectrogram_data) self.spectrum_plot.request_redraw() diff --git a/examples/demo/world_map.py b/examples/demo/world_map.py index 312fa549a..783e293e6 100644 --- a/examples/demo/world_map.py +++ b/examples/demo/world_map.py @@ -33,7 +33,9 @@ class WorldMapPlot(HasTraits): plot = Instance(Plot) # The URL which points to the world map image to be downloaded - image_url = Str("http://eoimages.gsfc.nasa.gov/ve//2433/land_shallow_topo_2048.jpg") + image_url = Str( + "http://eoimages.gsfc.nasa.gov/ve//2433/land_shallow_topo_2048.jpg" + ) ### Private Traits ######################################################### @@ -42,7 +44,13 @@ class WorldMapPlot(HasTraits): # The view traits_view = View( - Item("plot", editor=ComponentEditor(), width=800, height=400, show_label=False), + Item( + "plot", + editor=ComponentEditor(), + width=800, + height=400, + show_label=False, + ), resizable=True, ) diff --git a/examples/demo/xray_plot.py b/examples/demo/xray_plot.py index b51552081..d31f7fe14 100644 --- a/examples/demo/xray_plot.py +++ b/examples/demo/xray_plot.py @@ -152,7 +152,9 @@ class PlotExample(HasTraits): plot = Instance(Plot) - traits_view = View(Item("plot", editor=ComponentEditor()), width=600, height=600) + traits_view = View( + Item("plot", editor=ComponentEditor()), width=600, height=600 + ) def __init__(self, index, value, *args, **kw): super(PlotExample, self).__init__(*args, **kw) diff --git a/examples/demo/zoomed_plot/wav_to_numeric.py b/examples/demo/zoomed_plot/wav_to_numeric.py index 80928a3be..f4b82228a 100644 --- a/examples/demo/zoomed_plot/wav_to_numeric.py +++ b/examples/demo/zoomed_plot/wav_to_numeric.py @@ -24,7 +24,9 @@ def wav_to_numeric(fname, max_frames=-1): 2 ** 15 - 0.5 ) else: - data = numpy.fromstring(frames, numpy.uint8).astype(numpy.float64) - 127.5 + data = ( + numpy.fromstring(frames, numpy.uint8).astype(numpy.float64) - 127.5 + ) if channels == 2: left = data[0::2] @@ -40,7 +42,9 @@ def wav_to_numeric(fname, max_frames=-1): def test(): sample_path = os.path.join("examples", "data", "sample.wav") alt_path = os.path.join("..", "data", "sample.wav") - fname = find_resource("Chaco", sample_path, alt_path=alt_path, return_path=True) + fname = find_resource( + "Chaco", sample_path, alt_path=alt_path, return_path=True + ) index, data = wav_to_numeric(fname) print(data[:100]) return index, data diff --git a/examples/demo/zoomed_plot/zoom_overlay.py b/examples/demo/zoomed_plot/zoom_overlay.py index 895d7d340..1c141f0f6 100644 --- a/examples/demo/zoomed_plot/zoom_overlay.py +++ b/examples/demo/zoomed_plot/zoom_overlay.py @@ -45,7 +45,9 @@ def calculate_points(self, component): left_end = array([self.destination.x, y]) right_end = array([self.destination.x2, y]) - polygon = array((left_top, left_mid, left_end, right_end, right_mid, right_top)) + polygon = array( + (left_top, left_mid, left_end, right_end, right_mid, right_top) + ) left_line = array((left_top, left_mid, left_end)) right_line = array((right_end, right_mid, right_top)) diff --git a/examples/demo/zoomed_plot/zoom_plot.py b/examples/demo/zoomed_plot/zoom_plot.py index 40ad6a7ea..a0249eeee 100644 --- a/examples/demo/zoomed_plot/zoom_plot.py +++ b/examples/demo/zoomed_plot/zoom_plot.py @@ -28,7 +28,9 @@ sample_path = os.path.join("examples", "data", "sample.wav") alt_path = os.path.join("..", "data", "sample.wav") -fname = find_resource("Chaco", sample_path, alt_path=alt_path, return_path=True) +fname = find_resource( + "Chaco", sample_path, alt_path=alt_path, return_path=True +) numpts = 3000 diff --git a/examples/tutorials/scipy2008/custom_overlay.py b/examples/tutorials/scipy2008/custom_overlay.py index dee80a346..76bd6c41d 100644 --- a/examples/tutorials/scipy2008/custom_overlay.py +++ b/examples/tutorials/scipy2008/custom_overlay.py @@ -5,14 +5,26 @@ from enable.component_editor import ComponentEditor from enable.api import ColorTrait from traits.api import Button, Float, Range, HasTraits, Instance -from traitsui.api import Item, View, Group, HGroup, RangeEditor, spring, Handler +from traitsui.api import ( + Item, + View, + Group, + HGroup, + RangeEditor, + spring, + Handler, +) class CustomOverlay(AbstractOverlay): x = Float(10, editor=RangeEditor(low=1.0, high=600, mode="slider")) y = Float(10, editor=RangeEditor(low=1.0, high=500, mode="slider")) - width = Range(10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider")) - height = Range(10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider")) + width = Range( + 10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider") + ) + height = Range( + 10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider") + ) color = ColorTrait("red") traits_view = View( diff --git a/examples/tutorials/scipy2008/custom_overlay_dataspace.py b/examples/tutorials/scipy2008/custom_overlay_dataspace.py index 7fea3692a..f9354ad40 100644 --- a/examples/tutorials/scipy2008/custom_overlay_dataspace.py +++ b/examples/tutorials/scipy2008/custom_overlay_dataspace.py @@ -5,14 +5,26 @@ from enable.component_editor import ComponentEditor from enable.api import ColorTrait from traits.api import Button, CArray, Bool, Float, Range, HasTraits, Instance -from traitsui.api import Item, View, Group, RangeEditor, HGroup, Handler, spring +from traitsui.api import ( + Item, + View, + Group, + RangeEditor, + HGroup, + Handler, + spring, +) class CustomOverlay(AbstractOverlay): x = Float(10, editor=RangeEditor(low=1.0, high=600, mode="slider")) y = Float(10, editor=RangeEditor(low=1.0, high=500, mode="slider")) - width = Range(10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider")) - height = Range(10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider")) + width = Range( + 10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider") + ) + height = Range( + 10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider") + ) color = ColorTrait("red") dataspace = Bool(False) diff --git a/examples/tutorials/scipy2008/custom_overlay_movetool.py b/examples/tutorials/scipy2008/custom_overlay_movetool.py index c6b9d20c8..b7429e905 100644 --- a/examples/tutorials/scipy2008/custom_overlay_movetool.py +++ b/examples/tutorials/scipy2008/custom_overlay_movetool.py @@ -4,15 +4,36 @@ from chaco.tools.api import PanTool, MoveTool from enable.component_editor import ComponentEditor from enable.api import ColorTrait -from traits.api import Button, CArray, Bool, Float, Range, HasTraits, Instance, Property -from traitsui.api import Item, View, Group, RangeEditor, HGroup, Handler, spring +from traits.api import ( + Button, + CArray, + Bool, + Float, + Range, + HasTraits, + Instance, + Property, +) +from traitsui.api import ( + Item, + View, + Group, + RangeEditor, + HGroup, + Handler, + spring, +) class CustomOverlay(AbstractOverlay): x = Float(10, editor=RangeEditor(low=1.0, high=600, mode="slider")) y = Float(10, editor=RangeEditor(low=1.0, high=500, mode="slider")) - width = Range(10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider")) - height = Range(10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider")) + width = Range( + 10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider") + ) + height = Range( + 10.0, 300, editor=RangeEditor(low=10.0, high=300, mode="slider") + ) color = ColorTrait("red") dataspace = Bool(False) position = Property diff --git a/examples/tutorials/scipy2008/tool_chooser.py b/examples/tutorials/scipy2008/tool_chooser.py index 5a7b4753f..5620b852d 100644 --- a/examples/tutorials/scipy2008/tool_chooser.py +++ b/examples/tutorials/scipy2008/tool_chooser.py @@ -10,7 +10,9 @@ class ToolChooserExample(HasTraits): plot = Instance(Plot) - tools = List(editor=CheckListEditor(values=["PanTool", "ZoomTool", "DragZoom"])) + tools = List( + editor=CheckListEditor(values=["PanTool", "ZoomTool", "DragZoom"]) + ) traits_view = View( Item("tools", label="Tools", style="custom"), Item("plot", editor=ComponentEditor(), show_label=False), diff --git a/examples/tutorials/scipy2008/traits_image.py b/examples/tutorials/scipy2008/traits_image.py index 418117bb7..35a4c3ac5 100644 --- a/examples/tutorials/scipy2008/traits_image.py +++ b/examples/tutorials/scipy2008/traits_image.py @@ -36,7 +36,11 @@ def __init__(self): plot = Plot(plotdata) # Create an image plot in the Plot self.renderer = plot.img_plot( - "imagedata", name="plot1", xbounds=xgrid, ybounds=ygrid, colormap=viridis + "imagedata", + name="plot1", + xbounds=xgrid, + ybounds=ygrid, + colormap=viridis, )[0] self.plot = plot diff --git a/examples/tutorials/tutorial1.py b/examples/tutorials/tutorial1.py index c557b9425..e105390fc 100644 --- a/examples/tutorials/tutorial1.py +++ b/examples/tutorials/tutorial1.py @@ -19,7 +19,9 @@ # plot types (line, scatter, etc.). In later tutorials we'll see what the # factories are actually doing, and how to manually assemble plotting # primitives in more powerful ways. For now, factories suit our needs. -myplot = chaco.create_line_plot((x, y), bgcolor="white", add_grid=True, add_axis=True) +myplot = chaco.create_line_plot( + (x, y), bgcolor="white", add_grid=True, add_axis=True +) # We now need to set the plot's size, and add a little padding for the axes. # (Normally, when Chaco plots are placed inside WX windows, the bounds are diff --git a/examples/tutorials/tutorial10.py b/examples/tutorials/tutorial10.py index 52c2fa228..447cf1265 100644 --- a/examples/tutorials/tutorial10.py +++ b/examples/tutorials/tutorial10.py @@ -12,10 +12,14 @@ def _container_default(self): rplot, lplot = self.right_plot, self.left_plot lplot.overlays.append( - LineInspector(component=lplot, write_metadata=True, is_listener=True) + LineInspector( + component=lplot, write_metadata=True, is_listener=True + ) ) rplot.overlays.append( - LineInspector(component=rplot, write_metadata=True, is_listener=True) + LineInspector( + component=rplot, write_metadata=True, is_listener=True + ) ) return container diff --git a/examples/tutorials/tutorial10b.py b/examples/tutorials/tutorial10b.py index e89e6d127..9d23556e0 100644 --- a/examples/tutorials/tutorial10b.py +++ b/examples/tutorials/tutorial10b.py @@ -12,10 +12,14 @@ def _container_default(self): rplot, lplot = self.right_plot, self.left_plot lplot.overlays.append( - LineInspector(component=lplot, write_metadata=True, is_listener=True) + LineInspector( + component=lplot, write_metadata=True, is_listener=True + ) ) rplot.overlays.append( - LineInspector(component=rplot, write_metadata=True, is_listener=True) + LineInspector( + component=rplot, write_metadata=True, is_listener=True + ) ) rplot.index = lplot.index diff --git a/examples/tutorials/tutorial2.py b/examples/tutorials/tutorial2.py index 550419eea..cab3636f8 100644 --- a/examples/tutorials/tutorial2.py +++ b/examples/tutorials/tutorial2.py @@ -16,7 +16,8 @@ class PlotExample(HasTraits): plot = myplot traits_view = View( - Item("plot", editor=ComponentEditor(), show_label=False), title="Chaco Tutorial" + Item("plot", editor=ComponentEditor(), show_label=False), + title="Chaco Tutorial", ) diff --git a/examples/tutorials/tutorial9b.py b/examples/tutorials/tutorial9b.py index 43dd54ddc..4b3fd5917 100644 --- a/examples/tutorials/tutorial9b.py +++ b/examples/tutorials/tutorial9b.py @@ -14,8 +14,12 @@ def _container_default(self): rplot.index_mapper.range = lplot.index_mapper.range rplot.value_mapper.range = lplot.value_mapper.range - lplot.overlays.append(ZoomTool(lplot, tool_mode="box", always_on=False)) - rplot.overlays.append(ZoomTool(rplot, tool_mode="box", always_on=False)) + lplot.overlays.append( + ZoomTool(lplot, tool_mode="box", always_on=False) + ) + rplot.overlays.append( + ZoomTool(rplot, tool_mode="box", always_on=False) + ) return container diff --git a/examples/user_guide/grid_plot_container.py b/examples/user_guide/grid_plot_container.py index 040324fd2..cd0b40e38 100644 --- a/examples/user_guide/grid_plot_container.py +++ b/examples/user_guide/grid_plot_container.py @@ -37,7 +37,9 @@ def _plot_default(self): pd.set_data(data_name, jn(i, x)) plot = Plot(pd) - plot.plot(("index", data_name), color=COLOR_PALETTE[i], line_width=3.0) + plot.plot( + ("index", data_name), color=COLOR_PALETTE[i], line_width=3.0 + ) # Set each plot's aspect based on its position in the grid plot.height = ((i % 3) + 1) * 50.0 diff --git a/examples/user_guide/h_plot_container_add_multiple_times.py b/examples/user_guide/h_plot_container_add_multiple_times.py index d65be0209..afb2ff5fc 100644 --- a/examples/user_guide/h_plot_container_add_multiple_times.py +++ b/examples/user_guide/h_plot_container_add_multiple_times.py @@ -15,7 +15,8 @@ class ContainerExample(HasTraits): plot = Instance(VPlotContainer) traits_view = View( - Item("plot", editor=ComponentEditor(), show_label=False), resizable=True + Item("plot", editor=ComponentEditor(), show_label=False), + resizable=True, ) def __init__(self): diff --git a/examples/user_guide/h_plot_container_colorbar.py b/examples/user_guide/h_plot_container_colorbar.py index 5b74f9714..6968a0147 100644 --- a/examples/user_guide/h_plot_container_colorbar.py +++ b/examples/user_guide/h_plot_container_colorbar.py @@ -32,7 +32,9 @@ def __init__(self): # Create the plot plot = Plot(data) plot.plot( - ("index", "value", "color"), type="cmap_scatter", color_mapper=viridis + ("index", "value", "color"), + type="cmap_scatter", + color_mapper=viridis, ) # Create the colorbar, handing in the appropriate range and colormap diff --git a/examples/user_guide/overlay_container_inset.py b/examples/user_guide/overlay_container_inset.py index 77e297ab7..1474969a8 100644 --- a/examples/user_guide/overlay_container_inset.py +++ b/examples/user_guide/overlay_container_inset.py @@ -33,7 +33,9 @@ def _plot_default(self): ) # Attach tools to the plot - zoom = ZoomTool(component=zoomable_plot, tool_mode="box", always_on=False) + zoom = ZoomTool( + component=zoomable_plot, tool_mode="box", always_on=False + ) zoomable_plot.overlays.append(zoom) zoomable_plot.tools.append(PanTool(zoomable_plot)) diff --git a/examples/user_guide/plot_types/create_plot_snapshots.py b/examples/user_guide/plot_types/create_plot_snapshots.py index 6384f261c..509ea62df 100644 --- a/examples/user_guide/plot_types/create_plot_snapshots.py +++ b/examples/user_guide/plot_types/create_plot_snapshots.py @@ -182,7 +182,9 @@ def get_cmap_scatter_plot(): x_mapper, y_mapper = get_mappers(x, y) color_source = ArrayDataSource(nox) - color_mapper = dc.reverse(dc.RdYlGn)(DataRange1D(low=nox.min(), high=nox.max())) + color_mapper = dc.reverse(dc.RdYlGn)( + DataRange1D(low=nox.min(), high=nox.max()) + ) scatter_plot = ColormappedScatterPlot( index=x, @@ -217,7 +219,9 @@ def get_4d_scatter_plot(): x_mapper, y_mapper = get_mappers(x, y) color_source = ArrayDataSource(nox) - color_mapper = dc.reverse(dc.RdYlGn)(DataRange1D(low=nox.min(), high=nox.max())) + color_mapper = dc.reverse(dc.RdYlGn)( + DataRange1D(low=nox.min(), high=nox.max()) + ) # normalize between 0 and 10 marker_size = tax / tax.max() * 10.0 @@ -232,7 +236,8 @@ def get_4d_scatter_plot(): fill_alpha=0.8, marker="circle", marker_size=marker_size, - title="Size represents property-tax rate, " "color nitric oxides concentration", + title="Size represents property-tax rate, " + "color nitric oxides concentration", render_method="bruteforce", **PLOT_DEFAULTS ) @@ -414,7 +419,10 @@ def get_image_plot(): image_source = ImageData(data=image, value_depth=4) image_plot = ImagePlot( - index=index, value=image_source, index_mapper=index_mapper, **PLOT_DEFAULTS + index=index, + value=image_source, + index_mapper=index_mapper, + **PLOT_DEFAULTS ) add_axes(image_plot, x_label="x", y_label="y") @@ -430,7 +438,9 @@ def get_image_from_file(): w, h = image_source.get_width(), image_source.get_height() index = GridDataSource(np.arange(w), np.arange(h)) - index_mapper = GridMapper(range=DataRange2D(low=(0, 0), high=(w - 1, h - 1))) + index_mapper = GridMapper( + range=DataRange2D(low=(0, 0), high=(w - 1, h - 1)) + ) image_plot = ImagePlot( index=index, From b5833f240feb052f22a58eaed35488092b5587f6 Mon Sep 17 00:00:00 2001 From: aaronayres35 <36972686+aaronayres35@users.noreply.github.com> Date: Mon, 5 Apr 2021 05:47:37 -0700 Subject: [PATCH 4/7] Update examples/demo/advanced/asynchronous_updates.py Co-authored-by: Poruri Sai Rahul --- examples/demo/advanced/asynchronous_updates.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/demo/advanced/asynchronous_updates.py b/examples/demo/advanced/asynchronous_updates.py index 2896d67a3..31bdf3294 100644 --- a/examples/demo/advanced/asynchronous_updates.py +++ b/examples/demo/advanced/asynchronous_updates.py @@ -172,14 +172,14 @@ def blur_image(image, blur_level): blurred_image = image.copy() for _ in range(blur_level ** 2): blurred_image[1:-1, 1:-1] += ( - blurred_image[:-2, 1:-1] - + blurred_image[2:, 1:-1] # top - + blurred_image[1:-1, :-2] # bottom - + blurred_image[1:-1, 2:] # left - + blurred_image[:-2, :-2] # right - + blurred_image[:-2, 2:] # top-left - + blurred_image[2:, :-2] # top-right - + blurred_image[2:, 2:] # bottom-left # bottom-right + blurred_image[:-2, 1:-1] # top + + blurred_image[2:, 1:-1] # bottom + + blurred_image[1:-1, :-2] # left + + blurred_image[1:-1, 2:] # right + + blurred_image[:-2, :-2] # top-left + + blurred_image[:-2, 2:] # top-right + + blurred_image[2:, :-2] # bottom-left + + blurred_image[2:, 2:] # bottom-right ) blurred_image /= 9 From 40f40f02e533e8ffdb565299025173dbdc9764dc Mon Sep 17 00:00:00 2001 From: aaronayres35 <36972686+aaronayres35@users.noreply.github.com> Date: Mon, 5 Apr 2021 05:58:13 -0700 Subject: [PATCH 5/7] Apply suggestions from code review Co-authored-by: Poruri Sai Rahul --- chaco/barplot.py | 8 ++++---- chaco/data_frame_plot_data.py | 3 +-- chaco/data_range_2d.py | 2 +- chaco/multi_line_plot.py | 3 +-- chaco/pdf_graphics_context.py | 14 ++------------ chaco/plot_template.py | 12 ++---------- chaco/scales/formatters.py | 5 +---- chaco/scales/tests/test_scales.py | 9 ++------- chaco/shell/plot_maker.py | 2 +- chaco/tests/test_image_utils.py | 8 ++++---- chaco/tests/test_plot.py | 4 +--- chaco/tools/range_selection.py | 5 ++--- chaco/tools/simple_zoom.py | 10 ++-------- examples/demo/basic/minard_napoleon.py | 8 ++------ 14 files changed, 26 insertions(+), 67 deletions(-) diff --git a/chaco/barplot.py b/chaco/barplot.py index 6e36884db..e495eea72 100644 --- a/chaco/barplot.py +++ b/chaco/barplot.py @@ -262,10 +262,10 @@ def _gather_points(self): # TODO: Until we code up a better handling of value-based culling that # takes into account starting_value and dataspace bar widths, just use # the index culling for now. - # value_range_mask = self.value_mapper.range.mask_data(value) - # nan_mask = invert(isnan(index_mask)) & invert(isnan(value_mask)) - # point_mask = index_mask & value_mask & nan_mask & \ - # index_range_mask & value_range_mask + # value_range_mask = self.value_mapper.range.mask_data(value) + # nan_mask = invert(isnan(index_mask)) & invert(isnan(value_mask)) + # point_mask = index_mask & value_mask & nan_mask & \ + # index_range_mask & value_range_mask index_range_mask = self.index_mapper.range.mask_data(index) nan_mask = invert(isnan(index_mask)) diff --git a/chaco/data_frame_plot_data.py b/chaco/data_frame_plot_data.py index 89d4b3a64..ba897df82 100644 --- a/chaco/data_frame_plot_data.py +++ b/chaco/data_frame_plot_data.py @@ -87,8 +87,7 @@ def del_data(self, name): def set_data(self, name, new_data, generate_name=False): """Sets the specified index or column as the value for either the - specified - name or a generated name. + specified name or a generated name. If the instance's `writable` attribute is True, then this method sets the data associated with the given name to the new value, otherwise it diff --git a/chaco/data_range_2d.py b/chaco/data_range_2d.py index be4f9e9ac..d58d50525 100644 --- a/chaco/data_range_2d.py +++ b/chaco/data_range_2d.py @@ -93,7 +93,7 @@ def mask_data(self, data): def bound_data(self, data): """Not implemented for this class.""" raise NotImplementedError( - "bound_data() has not been implemented " "for 2d pointsets." + "bound_data() has not been implemented for 2d pointsets." ) def set_bounds(self, low, high): diff --git a/chaco/multi_line_plot.py b/chaco/multi_line_plot.py index 4ae14aa3e..46e3c1a4b 100644 --- a/chaco/multi_line_plot.py +++ b/chaco/multi_line_plot.py @@ -317,8 +317,7 @@ def _gather_points(self): ) slice_max = min( varray.shape[0], - 1 - + floor( + 1 + floor( (varray.shape[0] - 1) * (self.value_range.high - coord_min) / (coord_max - coord_min) diff --git a/chaco/pdf_graphics_context.py b/chaco/pdf_graphics_context.py index 3da9217fa..af112df81 100644 --- a/chaco/pdf_graphics_context.py +++ b/chaco/pdf_graphics_context.py @@ -197,12 +197,7 @@ def save(self, filename=None): def _create_new_canvas(self): """Create the PDF canvas context.""" - ( - x, - y, - w, - h, - ) = self._get_bounding_box() + x, y, w, h = self._get_bounding_box() if w < 0 or h < 0: self.gc = None return @@ -235,12 +230,7 @@ def _get_bounding_box(self): def _initialize_page(self, gc): """Make sure the origin is set to something consistent.""" - ( - x, - y, - w, - h, - ) = self._get_bounding_box() + x, y, w, h = self._get_bounding_box() gc.translate(x, y) diff --git a/chaco/plot_template.py b/chaco/plot_template.py index 560d3d45b..13d370990 100644 --- a/chaco/plot_template.py +++ b/chaco/plot_template.py @@ -61,10 +61,7 @@ class Templatizable(HasTraits): Primarily defines the protocol used to query the class for its contents. """ - def templatize( - self, - my_name, - ): + def templatize(self, my_name): """Returns a dict mapping the name of the child in the local name space to a Templatizable object reference. """ @@ -73,8 +70,6 @@ def templatize( def __gettemplate__(self): """Returns a templatized version of the object.""" - # def bind(self, - def rebind(self, obj): """Replaces this object with the state in peer object *obj*. @@ -195,10 +190,7 @@ def create_global(self, name_hint): """ pass - def create_import( - self, - import_line, - ): + def create_import(self, import_line): """Adds another import line, verbatim, to the top of the output code. No order of imports is guaranteed. diff --git a/chaco/scales/formatters.py b/chaco/scales/formatters.py index e50c79a81..daf05993a 100644 --- a/chaco/scales/formatters.py +++ b/chaco/scales/formatters.py @@ -464,10 +464,7 @@ class TimeFormatter(object): "minutes": ("%Mm",), "hourmin": ("%H:%M",), #'%Hh%M', '%Hh%Mm', '%H:%M:%S','%Hh %Mm %Ss'), "hours": ("%Hh", "%H:%M"), - "days": ( - "%m/%d", - "%a%d", - ), + "days": ("%m/%d", "%a%d"), "months": ("%m/%Y", "%b%y"), "years": (_two_digit_year, _four_digit_year), } diff --git a/chaco/scales/tests/test_scales.py b/chaco/scales/tests/test_scales.py index 6fa526794..aba50675c 100644 --- a/chaco/scales/tests/test_scales.py +++ b/chaco/scales/tests/test_scales.py @@ -26,10 +26,7 @@ def check_ticks(self, ticks1, ticks2): def check_labels(self, labels1, labels2): self.assertEqual(len(labels1), len(labels2)) - for ( - t1, - t2, - ) in zip(labels1, labels2): + for t1, t2 in zip(labels1, labels2): self.assertEqual(t1, t2) @@ -224,9 +221,7 @@ def test_estimate_default_scale(self): (3e8, 6e8, 8), ) for start, end, numlabels in test_intervals: - estimate = fmt.estimate_width(start, end, numlabels, ticker=scale)[ - 1 - ] + estimate = fmt.estimate_width(start, end, numlabels, ticker=scale)[1] ticks = scale.ticks(start, end, numlabels) labels = fmt.format(ticks, numlabels, None) actual = sum(map(len, labels)) diff --git a/chaco/shell/plot_maker.py b/chaco/shell/plot_maker.py index 93d36bbce..4d4f9488d 100644 --- a/chaco/shell/plot_maker.py +++ b/chaco/shell/plot_maker.py @@ -251,7 +251,7 @@ def _process_group(group, plot_data=None): x, y, plotinfo = group else: raise ChacoShellError( - "Found too many elements in group while" " constructing plot." + "Found too many elements in group while constructing plot." ) return x, y, plotinfo diff --git a/chaco/tests/test_image_utils.py b/chaco/tests/test_image_utils.py index 53a8e967a..2889ba380 100644 --- a/chaco/tests/test_image_utils.py +++ b/chaco/tests/test_image_utils.py @@ -47,8 +47,8 @@ def test_viewer_zoomed_into_four_pixel_intersection(self): view_rectangles = ( [49, 49, 2, 2], # Centered pixel intersection [49, 49, 3, 3], # Intersection at 1/3 of view - [49, 49, 2, 3], - ) # Intersection at 1/2, 1/3 of view + [49, 49, 2, 3], # Intersection at 1/2, 1/3 of view + ) for view_rect in view_rectangles: new_rect = trim_screen_rect(screen_rect, view_rect, FOUR_PIXELS) assert_midpoints_equal((new_rect, screen_rect)) @@ -58,8 +58,8 @@ def test_viewer_at_corner_of_four_pixel_image(self): screen_rect = [1, 1, 1, 1] view_rectangles = ( [1 + offset, 1 + offset, 1, 1], # Shifted down and right - [1 - offset, 1 - offset, 1, 1], - ) # Shifted up and left + [1 - offset, 1 - offset, 1, 1], # Shifted up and left + ) for view_rect in view_rectangles: new_rect = trim_screen_rect(screen_rect, view_rect, FOUR_PIXELS) assert_equal(new_rect, screen_rect) diff --git a/chaco/tests/test_plot.py b/chaco/tests/test_plot.py index b1552c716..704441065 100644 --- a/chaco/tests/test_plot.py +++ b/chaco/tests/test_plot.py @@ -68,9 +68,7 @@ def test_segment_plot_color_width(self): w = arange(3, 8) data = ArrayPlotData(x=x, y=y, c=c, w=w) plot = Plot(data) - plot.plot(("x", "y", "c", "w"), "cmap_segment", color_mapper=viridis)[ - 0 - ] + plot.plot(("x", "y", "c", "w"), "cmap_segment", color_mapper=viridis)[0] plot.do_layout((250, 250)) gc = PlotGraphicsContext((250, 250)) diff --git a/chaco/tools/range_selection.py b/chaco/tools/range_selection.py index 444a94beb..d9c67131f 100644 --- a/chaco/tools/range_selection.py +++ b/chaco/tools/range_selection.py @@ -603,9 +603,8 @@ def _set_selection(self, val): break # Set the selection mode on the datasource - datasource.metadata[ - self.selection_mode_metadata_name - ] = self.selection_mode + datasource.metadata[self.selection_mode_metadata_name] = \ + self.selection_mode if val is not None: low, high = val diff --git a/chaco/tools/simple_zoom.py b/chaco/tools/simple_zoom.py index 5cf1adc7a..3d08951f2 100644 --- a/chaco/tools/simple_zoom.py +++ b/chaco/tools/simple_zoom.py @@ -402,14 +402,8 @@ def _do_zoom(self): # "box" mode; reset both axes. x_range = self.component.x_mapper.range y_range = self.component.y_mapper.range - ( - x_range.low_setting, - y_range.low_setting, - ) = self._orig_low_setting - ( - x_range.high_setting, - y_range.high_setting, - ) = self._orig_high_setting + x_range.low_setting, y_range.low_setting = self._orig_low_setting + x_range.high_setting, y_range.high_setting = self._orig_high_setting # resetting the ranges will allow 'auto' to pick the values x_range.reset() diff --git a/examples/demo/basic/minard_napoleon.py b/examples/demo/basic/minard_napoleon.py index 8f96b169d..9f21e4e02 100644 --- a/examples/demo/basic/minard_napoleon.py +++ b/examples/demo/basic/minard_napoleon.py @@ -120,12 +120,8 @@ def _create_plot_component(): - army_lat = np.column_stack([army["start_lat"], army["end_lat"]]).reshape( - -1 - ) - army_lon = np.column_stack([army["start_lon"], army["end_lon"]]).reshape( - -1 - ) + army_lat = np.column_stack([army["start_lat"], army["end_lat"]]).reshape(-1) + army_lon = np.column_stack([army["start_lon"], army["end_lon"]]).reshape(-1) plot_data = ArrayPlotData( army_lon=army_lon, From fd8f2b41e947df3226fd31a874671d043a310ac6 Mon Sep 17 00:00:00 2001 From: aaronayres35 <36972686+aaronayres35@users.noreply.github.com> Date: Mon, 5 Apr 2021 05:59:24 -0700 Subject: [PATCH 6/7] Update chaco/lineplot.py Co-authored-by: Poruri Sai Rahul --- chaco/lineplot.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/chaco/lineplot.py b/chaco/lineplot.py index 3c0916a79..c904e7817 100644 --- a/chaco/lineplot.py +++ b/chaco/lineplot.py @@ -152,13 +152,7 @@ def hittest(self, screen_pt, threshold=7.0, return_distance=False): self.index.get_data(), dmax, self.index.sort_order ) - start_ndx = max( - 0, - min( - ndx1 - 1, - ndx2 - 1, - ), - ) + start_ndx = max(0, min(ndx1-1, ndx2-1)) end_ndx = min( len(self.value.get_data()) - 1, max(ndx1 + 1, ndx2 + 1) ) From a6befa27fd0090baf5b2f944a00cb561089ac9c5 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Mon, 5 Apr 2021 09:44:21 -0500 Subject: [PATCH 7/7] more suggested changes, but watching line length --- chaco/contour_line_plot.py | 5 ++--- chaco/contour_poly_plot.py | 5 ++--- chaco/layers/svg_range_selection_overlay.py | 8 ++++---- chaco/plot_containers.py | 10 ++++------ examples/demo/advanced/spec_waterfall.py | 5 ++--- examples/demo/advanced/spectrum.py | 5 ++--- 6 files changed, 16 insertions(+), 22 deletions(-) diff --git a/chaco/contour_line_plot.py b/chaco/contour_line_plot.py index ddbd15087..7851cd792 100644 --- a/chaco/contour_line_plot.py +++ b/chaco/contour_line_plot.py @@ -103,9 +103,8 @@ def _render(self, gc): if self.orientation == "h": strace = self.index_mapper.map_screen(trace) else: - strace = array(self.index_mapper.map_screen(trace))[ - :, ::-1 - ] + rev_strace = self.index_mapper.map_screen(trace) + strace = array(rev_strace)[:, ::-1] gc.begin_path() gc.lines(strace) gc.stroke_path() diff --git a/chaco/contour_poly_plot.py b/chaco/contour_poly_plot.py index 820d7c1da..df6c7edb9 100644 --- a/chaco/contour_poly_plot.py +++ b/chaco/contour_poly_plot.py @@ -60,9 +60,8 @@ def _render(self, gc): if self.orientation == "h": spoly = self.index_mapper.map_screen(poly) else: - spoly = array(self.index_mapper.map_screen(poly))[ - :, ::-1 - ] + rev_spoly = self.index_mapper.map_screen(poly) + spoly = array(rev_spoly)[:, ::-1] gc.lines(spoly) gc.close_path() gc.draw_path() diff --git a/chaco/layers/svg_range_selection_overlay.py b/chaco/layers/svg_range_selection_overlay.py index 6c9625a22..718c82622 100644 --- a/chaco/layers/svg_range_selection_overlay.py +++ b/chaco/layers/svg_range_selection_overlay.py @@ -65,12 +65,12 @@ def overlay(self, component, gc, view_bounds=None, mode="normal"): if self.axis == "index": if isinstance(self.mapper, GridMapper): scale_width = ( - coords[-1][0] - coords[0][0] - ) / self.doc_width + (coords[-1][0] - coords[0][0]) / self.doc_width + ) else: scale_width = ( - coords[0][-1] - coords[0][0] - ) / self.doc_width + (coords[0][-1] - coords[0][0]) / self.doc_width + ) scale_height = float(plot_height) / self.doc_height gc.translate_ctm(coords[0][0], origin_y + plot_height) else: diff --git a/chaco/plot_containers.py b/chaco/plot_containers.py index 3420d0f5c..41b288ed1 100644 --- a/chaco/plot_containers.py +++ b/chaco/plot_containers.py @@ -691,12 +691,10 @@ def _do_layout(self): # to be aligned in H and V. summed_widths = cumsum(hstack(([0], widths[:-1]))) summed_heights = cumsum(hstack(([0], heights[-1:0:-1]))) - h_positions = (2 * (arange(self._grid.shape[1]) + 1) - 1) * spacing[ - 0 - ] + summed_widths - v_positions = (2 * (arange(self._grid.shape[0]) + 1) - 1) * spacing[ - 1 - ] + summed_heights + h_positions = (2 * (arange(self._grid.shape[1]) + 1) - 1) \ + * spacing[0] + summed_widths + v_positions = (2 * (arange(self._grid.shape[0]) + 1) - 1) \ + * spacing[1] + summed_heights v_positions = v_positions[::-1] # Loop over all rows and columns, assigning position, setting bounds for diff --git a/examples/demo/advanced/spec_waterfall.py b/examples/demo/advanced/spec_waterfall.py index 4f6c9331a..27a56b5ea 100644 --- a/examples/demo/advanced/spec_waterfall.py +++ b/examples/demo/advanced/spec_waterfall.py @@ -111,9 +111,8 @@ def _create_plot_component(obj): )[0] obj.spectrum_plot.padding = 50 obj.spectrum_plot.title = "Spectrum" - spec_range = list(obj.spectrum_plot.plots.values())[0][ - 0 - ].value_mapper.range + plot_rends = list(obj.spectrum_plot.plots.values()) + spec_range = plot_rends[0][0].value_mapper.range spec_range.low = 0.0 spec_range.high = 5.0 obj.spectrum_plot.index_axis.title = "Frequency (hz)" diff --git a/examples/demo/advanced/spectrum.py b/examples/demo/advanced/spectrum.py index a74bdf0cf..a1c4386ce 100644 --- a/examples/demo/advanced/spectrum.py +++ b/examples/demo/advanced/spectrum.py @@ -48,9 +48,8 @@ def _create_plot_component(obj): ) obj.spectrum_plot.padding = 50 obj.spectrum_plot.title = "Spectrum" - spec_range = list(obj.spectrum_plot.plots.values())[0][ - 0 - ].value_mapper.range + plot_rends = list(obj.spectrum_plot.plots.values()) + spec_range = plot_rends[0][0].value_mapper.range spec_range.low = 0.0 spec_range.high = 5.0 obj.spectrum_plot.index_axis.title = "Frequency (Hz)"