From f4f9827815921f031c9aae5901cd6ff51d1af051 Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Mon, 20 May 2019 09:36:01 +0100 Subject: [PATCH 01/68] Update configuration; use Enthought sphinx template if available. --- docs/source/conf.py | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index b1584e0cc..d55cf46c4 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -29,7 +29,12 @@ def get_build_docset(): # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'traits.util.trait_documenter'] +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'sphinx.ext.graphviz', + 'traits.util.trait_documenter', +] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -96,23 +101,23 @@ def get_build_docset(): # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. -html_style = 'default.css' +#html_style = 'default.css' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -html_title = "Chaco {}".format(version) +#html_title = "Chaco {}".format(version) # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (within the static path) to place at the top of # the sidebar. -html_logo = '_static/e-logo-rev.png' +#html_logo = '_static/e-logo-rev.png' # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -html_favicon = 'et.ico' +#html_favicon = 'et.ico' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -157,7 +162,25 @@ def get_build_docset(): # Output file base name for HTML help builder. htmlhelp_basename = 'Chacodoc' -html_theme='classic' +try: + import enthought_sphinx_theme + + html_theme_path = [enthought_sphinx_theme.theme_path] + html_theme = 'enthought' +except ImportError as exc: + import warnings + msg = '''Can't find Enthought Sphinx Theme, using default. + Exception was: {} + Enthought Sphinx Theme can be downloaded from + https://github.com/enthought/enthought-sphinx-theme''' + warnings.warn(RuntimeWarning(msg.format(exc))) + + # old defaults + html_logo = "e-logo-rev.jpg" + html_favicon = "et.png" + html_style = 'default.css' + html_theme = 'classic' + # Options for LaTeX output # ------------------------ From df6b032347f910577d6ed4b503825707f5fac0f2 Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Mon, 20 May 2019 09:37:28 +0100 Subject: [PATCH 02/68] [WIP] new content, some re-organizaition of existing content --- docs/source/index.rst | 83 +- docs/source/quickstart.rst | 159 ++-- .../basic_elements/data_ranges.rst | 4 +- .../basic_elements/data_sources.rst | 5 +- docs/source/user_manual/containers.rst | 2 - docs/source/user_manual/faq.rst | 92 +-- docs/source/user_manual/fundamentals.rst | 745 ++++++++++++++++++ docs/source/user_manual/how_do_i.rst | 16 +- .../images/power_function_example.png | Bin 0 -> 322308 bytes docs/source/user_manual/index.rst | 22 +- docs/source/user_manual/installation.rst | 152 ++++ docs/source/user_manual/introduction.rst | 28 +- docs/source/user_manual/plots.rst | 254 ++++++ examples/user_guide/power_function_example.py | 91 +++ 14 files changed, 1442 insertions(+), 211 deletions(-) create mode 100644 docs/source/user_manual/fundamentals.rst create mode 100644 docs/source/user_manual/images/power_function_example.png create mode 100644 docs/source/user_manual/installation.rst create mode 100644 docs/source/user_manual/plots.rst create mode 100644 examples/user_guide/power_function_example.py diff --git a/docs/source/index.rst b/docs/source/index.rst index f510743ce..a2a0dc766 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -2,14 +2,17 @@ Chaco |version| =============== Chaco is a Python package for building interactive and custom 2-D plots and -visualizations. -Chaco facilitates writing -plotting applications at all levels of complexity, from simple scripts with -hard-coded data to large plotting programs with complex data interrelationships -and a multitude of interactive tools. While Chaco generates attractive static -plots for publication and presentation, it also works well for interactive -data visualization and exploration. -Chaco is part of the `Enthought Tool Suite `_. +visualizations. Chaco facilitates writing plotting applications at all levels +of complexity, from simple scripts with hard-coded data to large plotting +programs with complex data interrelationships and a multitude of interactive +tools. While Chaco generates attractive static plots for publication and +presentation, Chaco differs from tools like MatPlotLib in that it also works +well for dynamic interactive data visualization and exploration. Chaco is part +of the Enthought Tool Suite. + +.. image:: images/chaco_show.png + :width: 800 px + :align: center Chaco includes renderers for many popular plot types, built-in implementations of common interactions with those plots, and a framework for extending and @@ -17,33 +20,61 @@ customizing plots and interactions. Chaco can also render graphics in a non-interactive fashion to images, in either raster or vector formats, and it has a subpackage for doing command-line plotting or simple scripting. -For a quick sample of Chaco's features, see the -`gallery `_, the -:ref:`annotated examples ` page, the -:ref:`tutorial and examples ` -and the :ref:`resources ` page. +Installation +------------ +Chaco and all of its dependencies (including the PyQt backend) can be +installed using the `Enthought Deployment Manager +`_ (formerly +EPD): +.. code-block:: console + + edm install chaco pyqt + +For full installation options, including installation from source, see the +:ref:`installation instructions ` Documentation ------------- -.. toctree:: - :maxdepth: 1 +For developers exploring Chaco for the first time, these tutorials and examples +give a good overview of the capabilities of Chaco: - Installation and quickstart guide - user_manual/tutorials_and_examples.rst - user_manual/index.rst - user_manual/resources.rst - programmers_reference.rst - tech_notes.rst +* :ref:`Sample Plot Gallery ` +* :ref:`Tutorial: Interactive plotting with Chaco ` +* Examples: ------------- + - :ref:`Modeling Van del Waal's Equations ` + - :ref:`Creating an interactive Hyetograph ` -.. image:: images/chaco_show.png - :width: 800 px - :align: center +There is also a :ref:`FAQ ` which provides answers to issues and common +tricks that help when building Chaco applications. ------------- +For comprehensive documentation, we have: +* :ref:`User Reference ` +* Developer Reference * :ref:`search` + +Reporting bugs and contributing +------------------------------- + +Since Chaco is open source and hosted on +`Github `_, the development version can +always be checked out from Github, forked, and modified at will. When a bug is +found, please submit an issue in the +`issue page `_. If you would like to +share a bug fix or a new feature, simply submit a Pull Request from your fork. +Don't forget to specify very clearly what code to run to reproduce the issue, +what the logic of the fix is and to add one or more unit tests to ensure future +stability. The Pull Request description can and often needs to contain +screenshots of the issue or the fix. + +License +------- + +As part of the `Enthought Tool Suite `_, Chaco is +free and open source under a BSD license: + +.. include:: ../../LICENSE.txt diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 92854b8d1..973419c99 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -2,7 +2,6 @@ Quickstart ########## - +----------------------------------------+--------------------------------------+ |.. image:: images/simple_line.png |.. image:: images/scalar_function.png| | :height: 300 px | :height: 300 px | @@ -12,91 +11,6 @@ Quickstart This section is meant to help users on well-supported platforms and common Python environments get started using Chaco as quickly as possible. -Installation -============ - -There are several ways to get Chaco. The easiest way is through `Enthought -Canopy (Canopy) `_ (formerly EPD) -which is available for Windows, Linux and Mac OSX and also provides many other -useful packages. Chaco may also be available through a package manager on your -platform, such as apt on Ubuntu, yum on Redhat or -`MacPorts `_ on OS X. You can also build Chaco from -its `source code `_, but because of the -dependencies, the easiest way by far is to install Canopy. - -.. _dependencies: - -Dependencies ------------- - -* `Python `_ 2.7 or later - -* `Traits `_, an event notification - framework - -* `Kiva `_, part of the enable project, - for rendering 2-D graphics to a variety of backends across platforms - -* `Enable `_, a framework for writing - interactive visual components, and for abstracting away GUI-toolkit-specific - details of mouse and keyboard handling. - -* `NumPy `_, for dealing efficiently with large - datasets - -* Either `wxPython `_, `PyQt - `_ (GPL or - Commercial license) or `PySide `_ (LGPL license) to - display interactive plots. - -Installing Chaco with Canopy ----------------------------- - -Chaco, the rest of the `Enthought Tool Suite `_, -and a lot more are bundled with Enthought Canopy (formerly EPD). Getting -Canopy gives you a one-click install of Chaco -and all its dependencies at once; however, these packages will be linked to a -new instance of Python. Canopy Express is free for all users and -contains all that you need to use Chaco. - -To get Canopy, go to the `Canopy download page -`_, select the desired bundle (Express, Full, -TriplePlay) and get the appropriate version for your platform. After running -the installer, you will have a working version of Chaco and several examples. - -Building Chaco ---------------- - -Building Chaco on your machine requires you to build Chaco and each of its -dependencies, but it has the advantage of installing Chaco on top of the Python -instance you already have installed. The build process may be challenging and -will require you to have a C compiler, SWIG, Cython and several development -libraries installed. - -To do this, you can either: - -1. Install Chaco and its :ref:`dependencies` from `PyPI - `_ using - `pip `_ or using `easy_install - `_ (part of - setuptools). For example - - :command:`pip install chaco` - -.. note:: - If you have already installed Chaco and just want to update to the newest - version, use - - :command:`pip install --upgrade chaco` - -2. Or, download the source from the `Chaco GitHub repository - `_ or alternatively as a part of the - full `Enthought Tool Suite `_. - -.. Please refer to the :ref:`installation` section for more detailed -.. instructions. -.. TODO This 'installation' section does not currently exist - Built-in Examples ================= @@ -272,7 +186,7 @@ Chaco plot embedded in a Traits application =========================================== The previous section showed how Chaco can be used interactively similarly to -`Matlab` or Matplotlib's `pyplot` package +`Matlab` or Matplotlib's `pyplot` package. Now, let's create, from scratch, the simplest possible Chaco plot which is embedded inside a `Traits`_ application. This will require more work but will @@ -281,11 +195,11 @@ client application. this is really what Chaco has been written for. First, some imports to bring in necessary components:: - from chaco.api import ArrayPlotData, Plot - from enable.component_editor import ComponentEditor + from chaco.api import ArrayPlotData, Plot + from enable.component_editor import ComponentEditor - from traits.api import HasTraits, Instance - from traitsui.api import View, Item + from traits.api import HasTraits, Instance + from traitsui.api import View, Item The imports from :mod:`chaco` and :mod:`enable` support the creation of the plot. The imports from :mod:`traits` bring in components to embed the plot @@ -295,11 +209,19 @@ interactive application using Traits.) Now let's create a Traits class with a view that contains only one element: a Chaco plot inside a slightly customized window:: - class MyPlot(HasTraits): - plot = Instance(Plot) - traits_view = View(Item('plot', editor = ComponentEditor(), show_label = False), - width = 500, height = 500, - resizable = True, title = "My line plot") + class MyPlot(HasTraits): + plot = Instance(Plot) + traits_view = View( + Item( + 'plot', + editor=ComponentEditor(), + show_label=False + ), + width=500, + height=500, + resizable=True, + title="My line plot" + ) A few options have been set to control the window containing the plot. Now, when the plot is created, we would like to pass in our data. Let's assume the @@ -307,19 +229,27 @@ data is a set of points with coordinates contained in two NumPy arrays ``x`` and `y`. So, adding an ``__init__`` method to create the Plot object looks as follows:: - class MyPlot(HasTraits): - plot = Instance(Plot) - traits_view = View(Item('plot', editor = ComponentEditor(), show_label = False), - width = 500, height = 500, - resizable = True, title = "My line plot") - - def __init__(self, x, y, *args, **kw): - super(MyPlot, self).__init__(*args, **kw) - plotdata = ArrayPlotData(x=x,y=y) - plot = Plot(plotdata) - plot.plot(("x","y"), type = "line", color = "blue") - plot.title = "sin(x)*x**3" - self.plot = plot + class MyPlot(HasTraits): + plot = Instance(Plot) + traits_view = View( + Item( + 'plot', + editor=ComponentEditor(), + show_label=False + ), + width=500, + height=500, + resizable=True, + title="My line plot" + ) + + def __init__(self, x, y, *args, **kw): + super(MyPlot, self).__init__(*args, **kw) + plotdata = ArrayPlotData(x=x,y=y) + plot = Plot(plotdata) + plot.plot(("x","y"), type = "line", color = "blue") + plot.title = "sin(x)*x**3" + self.plot = plot Since it inherits from HasTraits, the new class can use all the power of Traits, and the call to super() in its ``__init__`` method makes sure this @@ -327,11 +257,11 @@ object possesses the attributes and methods of its parent class. Now let's use our Traits object. Below, we generate some data, pass it to an instance of MyPlot and call configure_traits to create the UI:: - import numpy as np - x = np.linspace(-14,14,100) - y = np.sin(x)*x**3 - lineplot = MyPlot(x,y) - lineplot.configure_traits() + import numpy as np + x = np.linspace(-14,14,100) + y = np.sin(x)*x**3 + lineplot = MyPlot(x,y) + lineplot.configure_traits() The result should look like @@ -345,7 +275,6 @@ UI with very little work, and add listeners to update the plot when the data changes. Chaco also allows you to create custom tools to interact with the plot and overlays that make these tools intuitive and visually appealing. - .. rubric:: Footnotes .. [#guiqt] Starting from IPython 0.12, it is possible to use the Qt backend diff --git a/docs/source/user_manual/basic_elements/data_ranges.rst b/docs/source/user_manual/basic_elements/data_ranges.rst index 89fde57b6..de433a8ef 100644 --- a/docs/source/user_manual/basic_elements/data_ranges.rst +++ b/docs/source/user_manual/basic_elements/data_ranges.rst @@ -1,3 +1,5 @@ +.. _data_ranges: + =========== Data ranges =========== @@ -138,7 +140,7 @@ for 2D ranges: :class:`~chaco.data_range_2d.DataRange2D` :class:`~chaco.data_range_2d.DataRange2D` represents a 2D data range. - Under the hood, it is implemented using two + Internally, it is implemented using two :class:`~chaco.data_range_1d.DataRange1D` objects, one for each dimension, which are stored in the diff --git a/docs/source/user_manual/basic_elements/data_sources.rst b/docs/source/user_manual/basic_elements/data_sources.rst index 50ae4ceaf..c2d07567f 100644 --- a/docs/source/user_manual/basic_elements/data_sources.rst +++ b/docs/source/user_manual/basic_elements/data_sources.rst @@ -1,4 +1,7 @@ -Data sources +.. _data_sources: + +============ +Data Sources ============ A data source is a wrapper object for the actual data that the plot will be diff --git a/docs/source/user_manual/containers.rst b/docs/source/user_manual/containers.rst index 868862449..94c0d3471 100644 --- a/docs/source/user_manual/containers.rst +++ b/docs/source/user_manual/containers.rst @@ -1,5 +1,3 @@ -.. highlight:: python - :linenothreshold: 10 ********************* Containers and Layout diff --git a/docs/source/user_manual/faq.rst b/docs/source/user_manual/faq.rst index 7693688fb..4e8c25261 100644 --- a/docs/source/user_manual/faq.rst +++ b/docs/source/user_manual/faq.rst @@ -1,3 +1,5 @@ +.. _faq: + ########################## Frequently Asked Questions ########################## @@ -63,61 +65,61 @@ Peter Wang's response (excerpt):: On May 11, 2007, at 8:03 AM, Bill Baxter wrote: > Just curious. What are the pros and cons of chaco vs matplotlib? - - You had to go and ask, didn't you? :) There are many more folks here - who have used MPL more extensively than myself, so I'll defer the - comparisons to them. (Gael, as always, thanks for your comments and + + You had to go and ask, didn't you? :) There are many more folks here + who have used MPL more extensively than myself, so I'll defer the + comparisons to them. (Gael, as always, thanks for your comments and feedback!) I can comment, however, on the key goals of Chaco. - Chaco is a plotting toolkit targeted towards developers for building - interactive visualizations. You hook up pieces to build a plot that - is then easy to inspect, interact with, add configuration UIs for - (using Traits UI), etc. The layout of plot areas, the multiplicity - and types of renderers within those windows, the appearance and - locations of axes, etc. are all completely configurable since these - are all first-class objects participating in a visual canvas. They - can all receive mouse and keyboard events, and it's easy to subclass - them (or attach tools to them) to achieve new kinds of behavior. - We've tried to make all the plot renderers adhere to a standard - interface, so that tools and interactors can easily inspect data and - map between screen space and data space. Once these are all hooked + Chaco is a plotting toolkit targeted towards developers for building + interactive visualizations. You hook up pieces to build a plot that + is then easy to inspect, interact with, add configuration UIs for + (using Traits UI), etc. The layout of plot areas, the multiplicity + and types of renderers within those windows, the appearance and + locations of axes, etc. are all completely configurable since these + are all first-class objects participating in a visual canvas. They + can all receive mouse and keyboard events, and it's easy to subclass + them (or attach tools to them) to achieve new kinds of behavior. + We've tried to make all the plot renderers adhere to a standard + interface, so that tools and interactors can easily inspect data and + map between screen space and data space. Once these are all hooked up, you can swap out or update the data independently of the plots. - One of the downsides we had a for a while was that this rich set of - objects required the programmer to put several different classes - together just to make a basic plot. To solve this problem, we've - assembled some higher-level classes that have the most common - behaviors built-in by default, but which can still be easily - customized or extended. It's clear to me that this is a good general + One of the downsides we had a for a while was that this rich set of + objects required the programmer to put several different classes + together just to make a basic plot. To solve this problem, we've + assembled some higher-level classes that have the most common + behaviors built-in by default, but which can still be easily + customized or extended. It's clear to me that this is a good general approach to preserving flexibility while reducing verbosity. - At this point, Chaco is definitely capable of handling a large number - of different plotting tasks, and a lot of them don't require too much - typing or hacking skills. (Folks will probably require more - documentation, however, but I'm working on that. :) I linked to the - source for all of the screenshots in the gallery to demonstrate that - you can do a lot of things with Chaco in a few dozen lines of code. - (For instance, the audio spectrogram at the bottom of the gallery is + At this point, Chaco is definitely capable of handling a large number + of different plotting tasks, and a lot of them don't require too much + typing or hacking skills. (Folks will probably require more + documentation, however, but I'm working on that. :) I linked to the + source for all of the screenshots in the gallery to demonstrate that + you can do a lot of things with Chaco in a few dozen lines of code. + (For instance, the audio spectrogram at the bottom of the gallery is just a little over 100 lines.) - Fundamentally, I like the Chaco model of plots as compositions of - interactive components. This really helps me think about - visualization apps in a modular way, and it "fits my head". (Of - course, the fact that I wrote much of it might have something to do - with that as well. ;) The goal is to have data-related operations - clearly happen in one set of objects, the view layout and - configuration happen in another, and the interaction controls fit - neatly into a third. IMHO a good toolkit should help me design/ - architect my application better, and we definitely aspire to make + Fundamentally, I like the Chaco model of plots as compositions of + interactive components. This really helps me think about + visualization apps in a modular way, and it "fits my head". (Of + course, the fact that I wrote much of it might have something to do + with that as well. ;) The goal is to have data-related operations + clearly happen in one set of objects, the view layout and + configuration happen in another, and the interaction controls fit + neatly into a third. IMHO a good toolkit should help me design/ + architect my application better, and we definitely aspire to make Chaco meet that criterion. - Finally, one major perk is that since Chaco is built completely on - top of traits and its event-based component model, you can call - edit_traits() on any visual component from within your app (or - ipython) and get a live GUI that lets you tweak all of its various - parameters in realtime. This applies to the axis, grid, renderers, - etc. This seems so natural to me that I sometimes forget what an - awesome feature it is. :) + Finally, one major perk is that since Chaco is built completely on + top of traits and its event-based component model, you can call + edit_traits() on any visual component from within your app (or + ipython) and get a live GUI that lets you tweak all of its various + parameters in realtime. This applies to the axis, grid, renderers, + etc. This seems so natural to me that I sometimes forget what an + awesome feature it is. :) diff --git a/docs/source/user_manual/fundamentals.rst b/docs/source/user_manual/fundamentals.rst new file mode 100644 index 000000000..6c4418a7c --- /dev/null +++ b/docs/source/user_manual/fundamentals.rst @@ -0,0 +1,745 @@ +.. _fundamentals: + +================== +Chaco Fundamentals +================== + +While you can go a long way using the high-level APIs provided by the +:py:class:`~chaco.plot.Plot` class, to use Chaco to its full potential +it helps to have a deeper understanding of the building blocks of the +library. + +Foundations +=========== + +Chaco relies on a number of underlying libraries for core capabilities. +Understanding these libraries is important for writing heavily interactive +visualizations, as well as new tools, overlays and plot renderers. + +Traits +------ + +Chaco is written using `Traits `_ which not +only provides basic type-checking of data, particularly provides attribute +change notification which is key to the interactive updating of Chaco. + +You should be comfortable with Traits when writing any significant +Chaco-based application or when extending Chaco's capabilities. + +TraitsUI +-------- + +`TraitsUI `_ is a rapid GUI application +development library build on top of Traits. While it is not required for +the development of applications that use Chaco, it is the most natural way +of providing other UI elements for your users to interact with your +visualizations; or alternatively the most natural environment for writing +applications which embed Chaco plots. Chaco also provides TraitsUI +views for configuring some Chaco objects. + +You will need at least a basic familiarity with TraitsUI for most Chaco +use cases. + +Kiva +---- + +`Kiva `_ provides an abstracted 2D drawing +API and a number of back-end implementations. This permits writing of +drawing code that can be used almost un-modified when rendering to a screen, +to a vector document format (such as PDF or PostScript), or to a raster file +format (such as PNG). + +The core object for Kiva code is the "graphics context" which represents a +a 2D drawing surface and the current state of the drawing environment. When +Chaco classes need to do any drawing they will usually be supplied with an +appropriate graphics context to render into, but very occasionally (such as +when saving a plot out to a file) you may want to create your own context to +draw into. + +If you want to write new Chaco overlays or plot renderers you should develop +an understanding of Kiva. + +Enable +------ + +`Enable `_ provides interactivity and layout +on top of the Kiva drawing library. Enable is the library that handles the +interface between Chaco plots and the OS/windowing system, as well as the +basic hierarchical layout and layering of visible components of a plot. + +Enable provides two base classes that are at the root of much of the Chaco +code: + +:py:class:`~enable.component.Component` + An object that occupies a rectangular region of the window and knows how + to + draw itself and dispatch user interactions. The + :py:class:`~enable.container.Container` class is a subclass of + :py:class:`~enable.component.Component` that handles hierarchical layout + and event dispatch. + + The drawing of :py:class:`~enable.component.Component` objects is split + across a number of layers, so that overlays, underlays, borders and + background can be rendered in a coherent manner. + +:py:class:`~enable.tools.base_tool.BaseTool` + An object that handles a particular type of user interaction (eg. mouse + events or key presses). Each tool is a state machine and so the + interactions can vary depending on the state that the tool is in (eg. + "normal" vs. "dragging" state for a tool that handles moving + interactions). + +An understanding of Enable is important for writing new interactive tools, as +well as for understanding and controlling how components are layered and layed +out. + +Chaco Object Model +================== + +The :py:class:`~.chaco.plot.Plot` class provides a fairly simple API for +creating a plot in an application, but beneath that lies a set of classes +that handle converting the numbers into the numpy arrays into pixels on the +screen. Between the :py:class:`~.chaco.array_plot_data.ArrayPlotData` and the +:py:class:`~.chaco.plot.Plot` are a series of classes which hold state for +various operations and transformations. + +Data Flow +--------- + +The data flow between these classes can generally be sumarised as follows: + +.. graphviz:: + + digraph dataflow { + rankdir=LR; + node [shape=plaintext]; + "Plot Data" -> "Data sources" -> "Ranges" -> "Mappers" -> "Renderers" -> "Plot"; + "Data sources" -> "Renderers"; + "Mappers" -> "Axes and Grids"; + "Pan and Zoom" -> "Ranges"; + } + +Data sources + These hold individual data sets from the plot data (ie. something that + looks like a single NumPy array) and update when the data changes. + + Examples: :py:class:`~chaco.array_data_source.ArrayDataSource`, + :py:class:`~chaco.image_data.ImageData`, + :py:class:`~chaco.grid_data_source.GridData`. + +Ranges + These hold a range of displayed data values and can be updated either + by changes to the data or changes in the state of pan or zoom tools. + + Examples: :py:class:`~chaco.data_range_1d.DataRange1D`, + :py:class:`~chaco.data_range_2d.DataRange2D`. + +Mappers + These are responsible for mapping data values to screen (or color) values. + + Examples: :py:class:`~chaco.linear_mapper.LinearMapper`, + :py:class:`~chaco.log_mapper.LogMapper`, + :py:class:`~chaco.grid_mapper.GridMapper`. + +Renderers + These are the objects responsible for rendering plot data, such as line + plots or scatter plots. They need to be update either when the data they + are displaying changes, or the mapping from data space to screen space + changes. + + Examples: :py:class:`~chaco.lineplot.LinePlot`, + :py:class:`~chaco.scatterplot.ScatterPlot`, + :py:class:`~chaco.cmap_image_plot.CMapImagePlot`, + :py:class:`~chaco.text_plot_1d.TextPlot1D`. + +Axes and Grids + These are the objects responsible for drawing axes ticks and grid lines, + and need to know the mapping between data space and screen space. Axes + and Grids are examples of Overlays (although they are technically + underlays). + + Examples: :py:class:`~chaco.axis.PlotAxis`, + :py:class:`~chaco.label_axis.LabelAxis`, + :py:class:`~chaco.grid.Grid`. + +Pan and Zoom + These are pan and zoom commands that come from user interactions, such as + via a pan or zoom operation, from resizing the plot window, or from other + application-based setting of the range of values to display. Pan and zoom + are commonly initated via Tools. + + Examples: :py:class:`~chaco.tools.pan_tool.PanTool`, + :py:class:`~chaco.tools.zoom_tool.ZoomTool`. + +Data Flow Examples +~~~~~~~~~~~~~~~~~~ + +Consider the following example:: + + def create_plot(): + t = np.linspace(0, 2*np.pi, 100) + amplitude1 = 2*np.sin(t) + amplitude2 = np.cos(2*t) + plot_data = ArrayPlotData( + t=t, + amplitude1=amplitude1, + amplitude2=amplitude2, + ) + plot = Plot(plot_data) + plot.plot(('t', 'amplitude1'), type='line') + plot.plot(('t', 'amplitude2'), type='scatter') + return plot + +This sets up a number of objects and connects them together, so that data +flows roughly as follows: + +.. graphviz:: + + digraph dataflow { + + subgraph cluster_level { + node [shape=plaintext]; + style=invis; + "Data source" -> "Range" -> "Mapper" -> "Underlay" -> "Renderer" [style=invis]; + } + node [shape=rectangle]; + + subgraph index { + color=white; + "ArrayDataSource: time" -> "Range1D: index" -> "LinearMapper: index" -> "PlotAxis: index"; + } + subgraph value { + color=white; + "ArrayDataSource: amplitude1" -> "Range1D: value"; + "ArrayDataSource: amplitude2" -> "Range1D: value"; + "Range1D: value" -> "LinearMapper: value" -> "PlotAxis: value"; + } + + {rank = same; "Data source"; "ArrayDataSource: time"; "ArrayDataSource: amplitude1"; "ArrayDataSource: amplitude2"} + {rank = same; "Range"; "Range1D: index"; "Range1D: value"} + {rank = same; "Mapper"; "LinearMapper: index"; "LinearMapper: value"} + {rank = same; "Underlay"; "PlotAxis: index"; "PlotAxis: value"} + {rank = same; "Renderer"; "LinePlot"; "ScatterPlot"} + + "ArrayPlotData" -> "ArrayDataSource: time"; + "ArrayPlotData" -> "ArrayDataSource: amplitude1"; + "ArrayPlotData" -> "ArrayDataSource: amplitude2"; + "ArrayDataSource: time" -> "LinePlot"; + "ArrayDataSource: time" -> "ScatterPlot"; + "ArrayDataSource: amplitude1" -> "LinePlot"; + "ArrayDataSource: amplitude2" -> "ScatterPlot"; + "LinearMapper: value" -> "LinePlot"; + "LinearMapper: value" -> "ScatterPlot"; + "LinearMapper: index" -> "LinePlot"; + "LinearMapper: index" -> "ScatterPlot"; + "PlotAxis: index" -> "Plot"; + "PlotAxis: value" -> "Plot"; + "LinePlot" -> "Plot"; + "ScatterPlot" -> "Plot"; + } + +Updates to the data stored in the array plot data object trigger updates +through the pathways indicated, first updating the data sources for each +array, upon which the data ranges depend. In turn the mappers update their +state when the data ranges update, and the underlays and plot renderers +update their state based on changes to the mappers and, for the renderers, +on the changes to the data sources. Finally the changes to the state of the +components are flagged in the Enable drawing system, which will then schedule +the plot for re-drawing during the GUI event loop's next paint event. + +Notice also how this diagram shows that mappers and ranges are shared between +renderers and underlays that share the same physical space. Plots which don't +share the same screen space shouldn't share mappers, but can share data and/or +ranges. + +For example, here are two plots which share the same array plot data:: + + def create_plot(): + t = np.linspace(0, 2*np.pi, 100) + amplitude1 = 2*np.sin(t) + amplitude2 = np.cos(2*t) + plot_data = ArrayPlotData( + t=t, + amplitude1=amplitude1, + amplitude2=amplitude2, + ) + plot_1 = Plot(plot_data) + plot_1.plot(('t', 'amplitude1'), type='line') + plot_2 = Plot(plot_data) + plot_2.plot(('t', 'amplitude2'), type='scatter') + container = HPlotContainer(plot_1, plot2) + +Which gives rise to the following data flow diagram: + +.. graphviz:: + + digraph dataflow { + + subgraph cluster_level { + node [shape=plaintext]; + style=invis; + "Data source" -> "Range" -> "Mapper" -> "Underlay" -> "Renderer" [style=invis]; + } + node [shape=rectangle]; + + subgraph index_1 { + color=white; + "Range1D: index 1" -> "LinearMapper: index 1" -> "PlotAxis: index 1"; + } + subgraph value_1 { + color=white; + "Range1D: value 1" -> "LinearMapper: value 1" -> "PlotAxis: value 1"; + } + subgraph index_2 { + color=white; + "Range1D: index 2" -> "LinearMapper: index 2" -> "PlotAxis: index 2"; + } + subgraph value_2 { + color=white; + "Range1D: value 2" -> "LinearMapper: value 2" -> "PlotAxis: value 2"; + } + + {rank = same; "Data source"; "ArrayDataSource: time"; "ArrayDataSource: amplitude1"; "ArrayDataSource: amplitude2"} + {rank = same; "Range"; "Range1D: index 1"; "Range1D: value 1"; "Range1D: index 2"; "Range1D: value 2"} + {rank = same; "Mapper"; "LinearMapper: index 1"; "LinearMapper: value 1"; "LinearMapper: index 2"; "LinearMapper: value 2"} + {rank = same; "Underlay"; "PlotAxis: index 1"; "PlotAxis: value 1"; "PlotAxis: index 2"; "PlotAxis: value 2"} + {rank = same; "Renderer"; "LinePlot"; "ScatterPlot"} + + "ArrayPlotData" -> "ArrayDataSource: time"; + "ArrayPlotData" -> "ArrayDataSource: amplitude1"; + "ArrayPlotData" -> "ArrayDataSource: amplitude2"; + "ArrayDataSource: time" -> "Range1D: index 1" + "ArrayDataSource: time" -> "Range1D: index 2" + "ArrayDataSource: time" -> "LinePlot"; + "ArrayDataSource: time" -> "ScatterPlot"; + "ArrayDataSource: amplitude1" -> "Range1D: value 1"; + "ArrayDataSource: amplitude1" -> "Range1D: value 2"; + "ArrayDataSource: amplitude1" -> "LinePlot"; + "ArrayDataSource: amplitude2" -> "Range1D: value 1"; + "ArrayDataSource: amplitude2" -> "Range1D: value 2" + "ArrayDataSource: amplitude2" -> "ScatterPlot"; + "LinearMapper: value 1" -> "LinePlot"; + "LinearMapper: value 2" -> "ScatterPlot"; + "LinearMapper: index 1" -> "LinePlot"; + "LinearMapper: index 2" -> "ScatterPlot"; + "PlotAxis: index 1" -> "Plot 1"; + "PlotAxis: value 1" -> "Plot 1"; + "PlotAxis: index 2" -> "Plot 2"; + "PlotAxis: value 2" -> "Plot 2"; + "LinePlot" -> "Plot 1"; + "ScatterPlot" -> "Plot 2"; + } + +In contrast to the previous example the ranges and mappers are not related +in any way between the two plots. This means that changes to the visible +region in data space for one plot will not affect the other, and because +the values span a different range initially they will have different value +scales. + +It is common to want to share one or both of the ranges between plots to +keep the axes synchronized in data space. + +For example, here are two plots which share the same data ranges:: + + def create_plot(): + t = np.linspace(0, 2*np.pi, 100) + amplitude1 = 2*np.sin(t) + amplitude2 = np.cos(2*t) + plot_data = ArrayPlotData( + t=t, + amplitude1=amplitude1, + amplitude2=amplitude2, + ) + plot_1 = Plot(plot_data) + plot_1.plot(('t', 'amplitude1'), type='line') + plot_2 = Plot(plot_data) + plot_2.plot(('t', 'amplitude2'), type='scatter') + plot_2.index_range = plot_1.index_range + plot_2.value_range = plot_1.value_range + container = HPlotContainer(plot_1, plot2) + +Which gives rise to the following data flow diagram: + +.. graphviz:: + + digraph dataflow { + + subgraph cluster_level { + node [shape=plaintext]; + style=invis; + "Data source" -> "Range" -> "Mapper" -> "Underlay" -> "Renderer" [style=invis]; + } + node [shape=rectangle]; + + subgraph index_1 { + color=white; + "Range1D: index" -> "LinearMapper: index 1" -> "PlotAxis: index 1"; + } + subgraph value_1 { + color=white; + "Range1D: value" -> "LinearMapper: value 1" -> "PlotAxis: value 1"; + } + subgraph index_2 { + color=white; + "Range1D: index" -> "LinearMapper: index 2" -> "PlotAxis: index 2"; + } + subgraph value_2 { + color=white; + "Range1D: value" -> "LinearMapper: value 2" -> "PlotAxis: value 2"; + } + + {rank = same; "Data source"; "ArrayDataSource: time"; "ArrayDataSource: amplitude1"; "ArrayDataSource: amplitude2"} + {rank = same; "Range"; "Range1D: index"; "Range1D: value"} + {rank = same; "Mapper"; "LinearMapper: index 1"; "LinearMapper: value 1"; "LinearMapper: index 2"; "LinearMapper: value 2"} + {rank = same; "Underlay"; "PlotAxis: index 1"; "PlotAxis: value 1"; "PlotAxis: index 2"; "PlotAxis: value 2"} + {rank = same; "Renderer"; "LinePlot"; "ScatterPlot"} + + "ArrayPlotData" -> "ArrayDataSource: time"; + "ArrayPlotData" -> "ArrayDataSource: amplitude1"; + "ArrayPlotData" -> "ArrayDataSource: amplitude2"; + "ArrayDataSource: time" -> "Range1D: index"; + "ArrayDataSource: time" -> "LinePlot"; + "ArrayDataSource: time" -> "ScatterPlot"; + "ArrayDataSource: amplitude1" -> "Range1D: value"; + "ArrayDataSource: amplitude1" -> "LinePlot"; + "ArrayDataSource: amplitude2" -> "Range1D: value"; + "ArrayDataSource: amplitude2" -> "ScatterPlot"; + "LinearMapper: value 1" -> "LinePlot"; + "LinearMapper: value 2" -> "ScatterPlot"; + "LinearMapper: index 1" -> "LinePlot"; + "LinearMapper: index 2" -> "ScatterPlot"; + "PlotAxis: index 1" -> "Plot 1"; + "PlotAxis: value 1" -> "Plot 1"; + "PlotAxis: index 2" -> "Plot 2"; + "PlotAxis: value 2" -> "Plot 2"; + "LinePlot" -> "Plot 1"; + "ScatterPlot" -> "Plot 2"; + } + +Here any change to the range will automatically update the mappers +of both, so the visible ranges will match. However since the screen +space of the two plots is different, we don't want to share mappers +(mappers can only be shared when the plots are contained in an +:py:class:`~chaco.plot_containers.OverlayPlotContainer` or a +subclass such as :py:class:`~chaco.data_view.DataView` or +:py:class:`~chaco.plot.Plot`) + +Data Sources +------------ + +At its core, Chaco is about visualizing interactive data. As such, Chaco has +a standard API for representing data: all of these classes implement the +:py:class:`~chaco.abstract_data_source.AbstractDataSource` API. This class +has methods for getting and setting the data that is provided by the data +source, as well as basic information about the data's size and (for numerical +data) the numerical bounds of the values. A data source can also hold a +dictionary of arbitrary additional metadata. + +The workhorse data source is the +:py:class:`~chaco.array_data_source.ArrayDataSource` +which holds a single NumPy of array of numerical data and which covers almost +all common use cases. In most cases where you need to work with an +:py:class:`~chaco.array_data_source.ArrayDataSource` you call +:py:meth:`~chaco.array_data_source.ArrayDataSource.set_data` to change the +stored data, listen to the +:py:attr:`~chaco.array_data_source.ArrayDataSource.data_changed` event trait +for when the data changes and call +:py:meth:`~chaco.array_data_source.ArrayDataSource.get_data` to get the +current value of the data. + +Some users of a data source only care about the range of values that are +contained in that data. In this case the data source API provides a +:py:attr:`~chaco.array_data_source.ArrayDataSource.bounds_changed` trait that +indicates that the maximum or minimum value of the data has changed, and +those values can be efficiently retrieved via the +:py:meth:`~chaco.array_data_source.ArrayDataSource.get_bounds` trait. + +Similarly there is a +:py:attr:`~chaco.abstract_data_source.AbstractDataSource.metadata_changed` +event trait that is fired when the metadata dictionary is replaced or +modified. + +A common use case for alternative data sources is to render a computed +function (such as a curve that has been fit to the data) dynamically +rather than having to sample a fixed set of points. This can be done +by supplying the plot data with an +:py:class:`~chaco.function_data_source.FunctionDataSource` and plotting +that:: + + def create_plot(): + t = np.linspace(0, 2*np.pi, 100) + amplitude = 2*np.sin(t) + numpy.random.normal(scale=0.1) + plot_data = ArrayPlotData(t=t, amplitude=amplitude) + plot = Plot(plot_data) + plot.plot(('t', 'amplitude'), type='scatter') + + def f(low, high): + return 2*np.sin(np.linspace(low, high, 100)) + + data_source = FunctionDataSource( + func=f, data_range=plot.index_range + ) + plot_data.set_data('f', data_source) + plot.plot(('t', 'f'), type='line') + + return plot + +Mappers +------- + +Data as provided by the +:py:class:`~chaco.abstract_data_source.AbstractDataSource` is not suitable +for display; it needs to be mapped to an appropriate value for rendering +into a graphics context. The most obvious mapping transforms data values +into Enable's drawing coordinates (often simply referred to as "screen" +coordinates, whether or not they are actually rendered to a screen). +However similar transformations need to be performed to map numerical data +to color values for displaying on colormapped plots. There are two +hierarchies of classes that perform these transformations. + +The abstract base class for mapping data is the +:py:class:`~chaco.abstract_mapper.AbstractMapper` and this class +specifies methods +:py:meth:`~chaco.abstract_mapper.AbstractMapper.map_screen` for +mapping data values to screen values, +:py:meth:`~chaco.abstract_mapper.AbstractMapper.map_data` for +mapping screen values back to data values, and +:py:meth:`~chaco.abstract_mapper.AbstractMapper.map_data_array` +for mapping a collection of screen values to data values. Perhaps +most importantly, the mapper fires the +:py:attr:`~chaco.abstract_mapper.AbstractMapper.updated` + +Chaco provides a number of sub-classes of the base class for various +use-cases. The most commonly used is the +:py:class:`~chaco.linear_mapper.LinearMapper` which provides a one +dimensional linear transformation between data space and screen space, +but there is also :py:class:`~chaco.log_mapper.LogMapper` which provides +one dimensional logarithmic transformation, and +:py:class:`~chaco.grid_mapper.GridMapper` which provides a mapping form +a two dimensional data source to a point in screen (x, y) coordinates +using a combination of two one dimensional mappers. + +For mapping of values to colors, there is the +:py:class:`~chaco.abstract_color_mapper.AbstractColorMapper` class and +the two sub-classes :py:class:`~chaco.color_mapper.ColorMapper` and +:py:class:`~chaco.discrete_color_mapper.DiscreteColorMapper`. These have +the same base API as +:py:class:`~chaco.abstract_mapper.AbstractMapper` but also provide +some specialized methods for converting to integer RGB values efficiently. +Chaco provides a large number of default color maps suitable for various +visualization types. + +Ranges +------ + +A common problem to many data mappers is that the range of data values +may change dynamically, and when data changes it is desirable to have +the mapper automatically update itself to ensure that the full range of +data values is mapped to the screen. This functionality is broken out +into subclasses of the +:py:class:`~chaco.abstract_data_range.AbstractDataRange` class. + +These classes track a collection of +:py:class:`~chaco.abstract_data_source.AbstractDataSource` instances via +their :py:attr:`~chaco.abstract_data_range.AbstractDataRange.sources` +trait, and when the bounds of any of those data sources change then +the range adjusts its upper and lower bound appropriately. Data mappers +then listen to the values of the upper and lower bounds of the range and +use that to adjust the transformation that they apply. The actual +values of the upper and lower bounds in data space coordinates are +provided by the :py:attr:`~chaco.abstract_data_range.AbstractDataRange.low` +and :py:attr:`~chaco.abstract_data_range.AbstractDataRange.high` traits. + +However there are situations where the behaviour of the range should +change, for example after a pan or zoom operation the value of the +bounds should remain fixed to whatever values the user panned or zoomed +to even if the underlying data changes. For these purposes, code +interacting with a data range can set the +:py:attr:`~chaco.abstract_data_range.AbstractDataRange.low_setting` and +:py:attr:`~chaco.abstract_data_range.AbstractDataRange.high_setting` traits +either to an absolute numerical value in the data space, or to a number of +other values, such as ``auto`` or ``track`` that determine the behaviour +when data changes. + +The most commonly used subclass is +:py:class:`~chaco.data_range_1d.DataRange1D` which has a number of +additional affordances to facilitate pleasant appearing plots, such as +the ability to add some padding above and below the data via the +:py:attr:`~chaco.data_range_1d.DataRange1D.margin` trait, or even +to supply a custom padding calculation function. + +It is worthwhile noting that data ranges can be shared between mappers, +and this permits linking of axes bounds or color maps ranges across +different plots. + +Axes and Grids +-------------- + +Axes and grids are auxilliary objects that draw plot decorations. +They are underlays (and so inherit from +:py:class:`~chaco.abstract_underlay.AbstractOverlay`) and are +usually drawn into the underlay layer of a :py:class:`~chaco.plot.Plot` +but they are also able to be used as stand-alone components if needed +(for example to create multi-axis plots). + +These objects present numerous options for their styling, but perhaps +more importantly allow control over the algorithm to used for determining +where tick marks and grid lines should be drawn. Both classes have a +:py:attr:`tick_generator` trait which takes an instance of an +:py:class:`~chaco.ticks.AbstractTickGenerator` which has a single +method :py:meth:`~chaco.ticks.AbstractTickGenerator.get_ticks` that +returns the tick positions for the current data and screen space bounds. + +There are several standard tick generators available for use, +but in the absence of anything else the +:py:class:`~chaco.ticks.DefaultTickGenerator` is used, which tries to +generate genererally pleasing ticks at round numbers for both linear +and logarithmic mappings. The +:py:class:`~chaco.ticks.MinorTickGenerator` is similar, but generates +generate denser ticks that are suitable for use as a minor scale. The +:py:class:`~chaco.ticks.ShowAllTickGenerator` simply shows ticks at +a list of supplied data values, giving complete control at the expense +of not being able to dynamically adapt to changes from panning and +zooming. + +For more complex tick generation, such as time axes where the "natural" +tick spacings, positions and even label formatting can change as you +zoom through different levels, the +:py:class:`~chaco.scales_tick_generator.ScalesTickGenerator` allows the +user to specify a multi-leveled +:py:class:`~chaco.scales.scales.ScaleSystem`. In particular this system +provides the :py:class:`~chaco.scales.time_scale.CalendarScaleSystem` +which by default correct ticks axes with time values ranging from microseconds +through to years. + +For example, you can create an hours, minutes, seconds time axis (ignoring +higher level calendar constructs) for a plot as follows:: + + from chaco.scales.api import ( + CalendarScaleSystem, HMSScales, ScalesTickGenerator + ) + + def create_plot(): + t = np.linspace(0, 3600, 36001) + a = np.sin(2*pi*60*t) + plot_data = ArrayPlotData(t=t, a=a) + plot = Plot(plot_data) + plot.plot(('t', 'a'), type='line') + plot.index_axis.tick_generator = ScalesTickGenerator( + scale=CalendarScaleSystem(*HMSScales) + ) + + return plot + +Plot Renderers +-------------- + +The core of the Chaco plotting library are the plot renderers which are +responsible for drawing the markings that represent the data, all of which +implement the :py:class:`~chaco.abstract_plot_renderer.AbstractPlotRenderer` +API. This ABC is a subclass of +:py:class:`~chaco.plot_component.PlotComponent`, and so all plot renderers +are expected to implement the key parts of the Enable drawing API. Most +specialized plot renderers expect a :py:meth:`render` method that performs +actual drawing of the plot into a provided Kiva graphics context. + +Most plot renders have the notion of "index" and "value" data that +they are plotting. Each item in the index has a corresponding value, so if +a function were being plotted the index are points in the domain and the +values are points in the range. For plot renderers the index usually +provides a location at which the value should be rendered, and the value +provides a position offset or color value. Importantly, the index and value +are not directly linked to horizontal or vertical screen space. + +Different subclasses of the abstract plot renderer implement common +conventions for handling index and value representation. For example: + +:py:class:`~chaco.base_xy_plot.BaseXYPlot` + This class handles plots like line plots and bar plots where the index + gives offsets along one axis and the values are along the other axis. + +:py:class:`~chaco.base_1d_plot.Base1DPlot` + This class handles plots where the index gives the offset along one + axis, and the values are displayed by markings at or near those points. + +:py:class:`~chaco.base_2d_plot.Base2DPlot` + This class handles plots like contour and image plots where the + index lies on a regular 2D grid and values are displayed by markings + at or near those points. + +There are a number of other plot types that handle special cases like +candle plots. + +Plot renderers have mappers for each of their data dimensions, but they +also express convenience APIs mapping data values to and from screen +(x, y) values using the methods +:py:meth:`~chaco.abstract_plot_renderer.AbstractPlotRenderer.map_data` +and +:py:meth:`~chaco.abstract_plot_renderer.AbstractPlotRenderer.map_screen`. +These are usually simple wrappers around the appropriate mapper calls of +the same name. + +Plot renderers also have to provide information for tools that want to +interact with the values on the plot. They are expected to provide a +:py:meth:`~chaco.abstract_plot_renderer.AbstractPlotRenderer.map_index` +method which handles mapping a screen point to an index item (ie. an +integer index into the index data source). + +Tools +----- + +Up to this point, all the classes discussed are dynamic in the sense +that if the underlying data changes then the visualization will update +appropriately. However it is often the case that you want to add other +interactions to a visualization. The most common of these is the +ability to pan or zoom the plot to focus on particular details, but +there number of ways that you might want a user to interact with the +visualization is potentially vast. As a result one of the most common +ways to customize a visualization is by writing new tools. + +Tools are technically a feature of Enable, rather than Chaco, and as +a result there are a number of tools and base classes there that can +be used as the foundation or inspiration for custom interactions. For +example, the following Enable tools may be of use: + +:py:class:`enable.tools.move_tool.MoveTool` + A tool which changes the screen location of a component by dragging + with the mouse. This can be useful for allowing the user to move + plot decorations such as legends around the plot. + +:py:class:`enable.tools.resize_tool.ResizeTool` + A tool which changes the screen size of a component by dragging + edges or corners. + +:py:class:`enable.tools.hover_tool.HoverTool` + A tool which calls a callback when the mouse hs not moved + significantly for a period of time. + +:py:class:`enable.tools.button_tool.ButtonTool` + A tool that makes a component act like a button, with a + :py:class:`enable.tools.button_tool.ButtonTool.clicked` + trait that you can react to via the usual Traits mechanisms. + +:py:class:`enable.tools.pyface.context_menu_tool.ContextMenuTool` + A tool which displays a context menu at the point where the + use right-clicks, using Pyface's menu and action classes. + +:py:class:`enable.tools.traits_tool.TraitsTool` + A tool which opens a TraitsUI dialog when a component is + double-clicked. + +:py:class:`enable.tools.pyface.base_drop_tool.BaseDropTool` + A base tool which responds to operating system drag and drop. + Must be subclassed to implement methods that indicate whether + a type of object can be dropped, and what to do if they are + dropped. + +:py:class:`enable.tools.pyface.value_drag_tool.ValueDragTool` + A base tool which changes a numeric value as the user + drags the mouse. Must be subclassed to provide methods to + get and set the value. There is a subclass + :py:class:`enable.tools.pyface.value_drag_tool.AttributeDragTool` + which sets the values of attributes on an object as the + mouse moves, which is a common use case. + + diff --git a/docs/source/user_manual/how_do_i.rst b/docs/source/user_manual/how_do_i.rst index 88317820f..f1c34510c 100644 --- a/docs/source/user_manual/how_do_i.rst +++ b/docs/source/user_manual/how_do_i.rst @@ -1,3 +1,5 @@ +.. _how_do_i: + ############ How Do I...? ############ @@ -75,7 +77,7 @@ be set to 'wx'. class MyPlot(HasTraits): plot = Instance(Plot) - traits_view = View(Item('plot', editor=ComponentEditor())) + traits_view = View(Item('plot', editor=ComponentEditor())) def __init__(self, index, data_series, **kw): super(MyPlot, self).__init__(**kw) @@ -117,7 +119,7 @@ be set to 'wx'. :: def copy_to_clipboard(plot): - # WX specific, though QT implementation is similar using + # WX specific, though QT implementation is similar using # QImage and QClipboard import wx @@ -126,10 +128,10 @@ be set to 'wx'. gc = PlotGraphicsContext((width, height), dpi=72) gc.render_component(plot_component) - # Create a bitmap the same size as the plot + # Create a bitmap the same size as the plot # and copy the plot data to it - bitmap = wx.BitmapFromBufferRGBA(width+1, height+1, + bitmap = wx.BitmapFromBufferRGBA(width+1, height+1, gc.bmp_array.flatten()) data = wx.BitmapDataObject() data.SetBitmap(bitmap) @@ -160,7 +162,7 @@ Layout and Rendering def change_bgcolor(plot): plot.bgcolor = 'black' -* turn off borders? +* turn off borders? :: @@ -183,7 +185,7 @@ Writing Components * write a custom renderer? * write a custom overlay/underlay? * write a custom tool? -* write a new container? +* write a new container? Advanced @@ -194,5 +196,5 @@ Advanced * properly change/override draw dispatch? * modify event dispatch? * customize backbuffering? -* embed custom/native WX widgets on the plot? +* embed custom/native WX widgets on the plot? diff --git a/docs/source/user_manual/images/power_function_example.png b/docs/source/user_manual/images/power_function_example.png new file mode 100644 index 0000000000000000000000000000000000000000..d98a66cb1e3d14b66ee4c2dacc6e60db33b0f346 GIT binary patch literal 322308 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ࣆ(y|GQ0~w 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 (formerly EPD) +which provides environment management and package installation tools for +Windows, Linux and Mac OS. Chaco may also be available through a package manager on your +platform, such as apt on Ubuntu, yum on Redhat or +`MacPorts `_ on OS X. You can also build Chaco from +its `source code `_, but because of the +dependencies, the easiest way by far is to install EDM. + +.. _dependencies: + +Dependencies +============ + +* `Python `_ 2.7 or 3.5+ + +* `Traits `_, an event notification + framework + +* `TraitsUI `_, a rapid GUI application + development framework + +* `Kiva `_, part of the enable project, + for rendering 2-D graphics to a variety of backends across platforms + +* `Enable `_, a framework for writing + interactive visual components, and for abstracting away GUI-toolkit-specific + details of mouse and keyboard handling. + +* `NumPy `_, for dealing efficiently with large + datasets + +* Either `wxPython `_, `PyQt + `_ (GPL or + Commercial license) or `PySide `_ (LGPL license) to + display interactive plots. + +* (optionally) `ReportLab `_ + for PDF and PostScript output, and `Pillow `_ + for raster image output. + +Installing Chaco with EDM +========================= + +To install via EDM, `download EDM +`_ +for your platform and then do (from the command line) + +.. code-block:: console + + edm install chaco pyqt + +to install Chaco, PyQt, and their dependencies and then + +.. code-block:: console + + edm shell + +to enter the Python environment with these packages installed. + +If you do not wish to use the PyQt backend then under Python 2.7 you can either +install PySide or WxPython 3. + +Installing Chaco from Source +============================ + +If you choose to build Chaco rather than installing from a package manager +you will need a build environment that includes the standard C/C++ compiler +for your platform and Python version (see the Python documentation for more +information). If you are going to build the dependencies you will also need +to install SWIG and you may want to install Cython if you want to update the +extension modules in Chaco. + +Installation via Pip +-------------------- + +Chaco itself uses standard Python packaging via a setup.py script, so once +you have your build environment set up, you can install using Pip as you would +any other Python package. + +.. code-block:: console + + $ pip install chaco + +This will download the source distribution from PyPI and automatically build +Chaco and its dependencies for you. + +.. note:: + If you have already installed Chaco and just want to update to the newest + version, use + + .. code-block:: console + + $ pip install --upgrade chaco + +Installation via setup.py +------------------------- + +Alternatively, you can download the source code from the `Chaco GitHub +repository `_ and use the standard +`setup.py` installation commands: + +.. code-block:: console + + $ python setup.py install + +This will attempt to install and build all dependencies as part of the +installation process. + +Developer Live Installation +--------------------------- + +On Python 2.7 it is possible to install a live-editable source installation +using + +.. code-block:: console + + $ pip install -e . + +at the top level of the Chaco source code. Unfortunately, this doesn't work +on Python 3 as Chaco currently uses 2to3 to convert the code from Python 2 to +Python 3. + +Extension Modules +================= + +Chaco contains a number of C extension modules used mainly for speed. In the +current version of Chaco, there following extension modules are currently used: + +``chaco/_cython_speedups.pyx`` + This is a Cython extension which speeds up a number of standard operations, + currently mainly involving color maps. If this is not available, Chaco will + fall back on slower NumPy-based algorithms. + +``chaco/contour/_cntr.c`` + Contour tracing on quadrilateral meshes. This is required for contour plots. + +``chaco/downsample/_lttb.pyx`` + Implementation of the "largest triangle three buckets" downsampling algorithm + for line plots. If this is not available, then "lttb" downsampling of line + plots will fail. + +The Chaco source code includes the generated ``*.c`` files for each of the Cython +``*.pyx`` files, so Cython is not required to build Chaco. It is needed, however +if you are going to make changes to the Cython extension modules. + diff --git a/docs/source/user_manual/introduction.rst b/docs/source/user_manual/introduction.rst index 570fcb430..a7c436bda 100644 --- a/docs/source/user_manual/introduction.rst +++ b/docs/source/user_manual/introduction.rst @@ -2,6 +2,14 @@ Introduction ************ +This guide is designed to act as a conceptual guide to Chaco, an open-source +data visualization library built and maintained by Enthought, Inc. Chaco is +a set of interactive visualization tools built on top of the Enable and Kiva +2D drawing libraries and designed to complement other Enthought rapid +application development tools including Traits and TraitsUI. This guide +discussed many, but not all of the features of Chaco. For complete details +of the Chaco API, refer to the Chaco API documentation. + ============== What is Chaco? ============== @@ -11,7 +19,7 @@ the Enthought Tools Suite. The strong points of Chaco are -1. it can be :ref:`embedded ` in any wx, Qt, or TraitsUI application +1. it can be :ref:`embedded ` in any Wx, Qt, or TraitsUI application 2. it is designed for building interactive plotting applications, rather than static 2D plots @@ -19,7 +27,6 @@ The strong points of Chaco are 3. Chaco classes can be easily extended to create new plot types, interactive tools, and plot containers - At the lowest level, Chaco is a hierarchy of classes that defines 2D plotting elements: plots, containers, interactive tools, color bars, etc. In principle, applications can create instances of these elements and lay them @@ -28,15 +35,14 @@ of several of graphical back ends `. Working at this level allows the maximum flexibility, but requires understanding :ref:`Chaco's basic elements `. -Chaco defines two abstraction layers that allow a more high-level -(albeit less flexible) plotting experience. First, Chaco contains a -:class:`~chaco.plot.Plot` -class that defines several methods that create a complete plot given one or -more data sets. In other words, :class:`~chaco.plot.Plot` knows how to -package data for the most common kinds of plots. Second, Chaco has a -:mod:`shell` module that defines high-level plotting functions. This module -allows using Chaco as an interactive plotting tool that will be familiar -to users of matplotlib. +Chaco defines two abstraction layers that allow a more high-level (albeit +less flexible) plotting experience. First, Chaco contains a +:class:`~chaco.plot.Plot` class that defines several methods that create a +complete plot given one or more data sets. In other words, +:class:`~chaco.plot.Plot` knows how to package data for the most common kinds +of plots. Second, Chaco has a :mod:`shell` module that defines high-level +plotting functions. This module allows using Chaco as an interactive plotting +tool that will be familiar to users of matplotlib. .. _basic_elements: diff --git a/docs/source/user_manual/plots.rst b/docs/source/user_manual/plots.rst new file mode 100644 index 000000000..7292212a2 --- /dev/null +++ b/docs/source/user_manual/plots.rst @@ -0,0 +1,254 @@ +.. _plots: + +=================== +Plots and Plot Data +=================== + +The primary interface that Chaco presents is the :py:class:`~chaco.plot.Plot` +class. Informally you can think of this as a single set of shared axes that +contain a collection of renderers within that view. It comes pre-configured +with most of the decorations that you might want, such as grids, titles and +legends, and those can easily be modified if desired. + +Plots Are Components +==================== + +The :py:class:`~chaco.plot.Plot` class is a subclass of the +:py:class:`~enable.component.Component` class, and so you can display a plot +in a TraitsUI using a :py:class:`~enable.component_editor.ComponentEditor` +as you would any other Enable :py:class:`~enable.component.Component`. +Usually this looks something like: + +.. literalinclude:: /../../examples/user_guide/power_function_example.py + :language: python + :lines: 12-20, 76-86 + +Because plots tend to consume a large amount of vertical space you typically +want to avoid displaying it in a group which shows labels on the left-hand +side, as this creates a lot of empty space. By grouping in a way like what +is shown above, you get the following, more pleasing layout: + +.. image:: images/power_function_example.png + :scale: 50% + +Since :py:class:`~chaco.plot.Plot` subclasses +:py:class:`~enable.component.Component`, you have the basic styling options +that :py:class:`~enable.component.Component` gives you, such as background +color, padding, borders, etc. However :py:class:`~chaco.plot.Plot` assumes +that you have substantial padding around it as the plot titles, axis ticks +and axis labels are rendered in the padding around the plot by default; but +you can frequently get more compact layout by reducing the padding on the +sides which do not have labels. + +Similarly, this means that you can use a plot in the same way that you would +any other Enable component, and it will work with Enable tools. So you could +have multiple :py:class:`~chaco.plot.Plots` inside an enable +:py:class:`~enable.container.Container` or :py:class:`~chaco.canvas.Canvas` +and attache :py:class:`~enable.tools.move_tool.MoveTool` and +:py:class:`~enable.tools.resize_tool.ResizeTool` to them to allow the user +complete control over the location and size of the plots. + +Plot Data +========= + +The data for a :py:class:`~chaco.plot.Plot` is stored in an instance of an +:py:class:`~chaco.abstract_plot_data.AbstractPlotData` (and almost always +:py:class:`~chaco.array_plot_data.ArrayPlotData`). The plot data classes +provide a namespace that maps names to data so that the +:py:class:`~chaco.plot.Plot` can refer to the data by name when constructing +and modifying plot renderers. + +Usually the raw data is added to the plot data during initialization, and +the assigned names used as the data parameters for the plot factories: + +.. literalinclude:: /../../examples/user_guide/power_function_example.py + :language: python + :lines: 12-35, 53 + +After raw data has been added to the plot, it can be updated via the +:py:meth:`~chaco.array_plot_data.ArrayPlotData.set_data` method: + +.. literalinclude:: /../../examples/user_guide/power_function_example.py + :language: python + :lines: 60-63 + +Sometimes it is convenient to update multiple data values at the same +time, and in this case there is the +:py:meth:`~chaco.array_plot_data.ArrayPlotData.update_data` method: + +.. literalinclude:: /../../examples/user_guide/power_function_example.py + :language: python + :lines: 65-68 + +Peforming an update rather than multiple individual data setting +operations is preferable, where possible, since it triggers a single +combined update on any plots that are listening for changes to the +data rather than many smaller updates. + +Plot Factory Methods +==================== + +The :py:class:`~chaco.plot.Plot` class allws you to add multiple plots +of different types to the visualization your are constructing. It does +this via a family of factory methods, the most commonly used of which is +the :py:meth:`~chaco.plot.Plot.plot` method, but which include methods +for image plots, contour plots, candle plots and so on. + +All of these methods share that they expect parameters for: + +data + Either a name or a tuple of data names from the plot data that + should be used in the plot. The exact interpretation and number + of data values expected varies from method to method. + +name + A name to be given to the renderer or renderers created by the + method. The renderer can be retrieved from the + :py:class:`~chaco.plot.Plot` using its name. If a name is not + given, one is auto-generated. + +origin + An indication of the orientation of the plot. This is the + corner of the plot where the origin is located when looking + at data in the first quadrant (positive x and y). + +**styles + Keyword arguments that are passed directly through to the + plot renderer, most commonly used to set things like colors, + line styles, marker types, and so on. + +Other common arguments that some, but not all, factory methods take +include whether to use linear or logarithmic axes, the bounds of +image or contour data in data space, and colormap information. + +The plot factory methods all return a list of plot renderers, all +of which are associated with the given name. + +The plot factory methods are: + +:py:meth:`~chaco.plot.Plot.plot` + The method for creating different types of XY plot subclasses. + In adddition to the parameters listed above, this takes a + ``type`` argument, which is a string naming the type of plot + renderer to create, such as ``line`` (the default), ``scatter``, + ``bar``, and so on. When called with many parameters, this + method may create multiple plot renderers of the same type. + +:py:meth:`~chaco.plot.Plot.img_plot` + The method for creating image plots. If the data has a shape + of (N, M, 3) or (N, M, 4) then it is treated as RGB or RGBA + data, otherwise for (N, M) shaped data a colormap will be + applied. This method can be given information about the + extent of the data in the index data space. This can come from + a named data source, from a hard-coded array of values, or from + a (low, high) tuple. If nothing is supplied then the bounds + for an image with N rows and M columns are (0, M) in the x + direction an (0, N) in the y direction. + +:py:meth:`~chaco.plot.Plot.contour_plot` + The method for creating contour plots. Like the + :py:meth:`~chaco.plot.Plot.plot` method this takes a `type` + argument to select between a ``"line"`` contour plot and a + filled ``"poly"`` polygon contour plot. This method can be + given information about the position of the data in the x and + y data spaces. This can come from a named data source, from a + hard-coded array of values, or from a (low, high) tuple. If + nothing is supplied then the locations of data points for an + image with N rows and M columns are (0, 1, ..., M-1) in the x + direction an (0, 1, ..., N-1) in the y direction. + +:py:meth:`~chaco.plot.Plot.candle_plot` + This method creates various styles of plots with error bars. + The type is inferred from the number of data values passed. + The first argument is always the index, but the remaining + arguments are variously interpreted as min and max values + for bar and whiskers, plus an optional central value. + It is up to the calling code to correctly derive the data + arrays: no aggregation is performed by the plot. + +:py:meth:`~chaco.plot.Plot.quiver_plot` + The method creates a plot that places arrows at locations + determined by a list of x and y points. It expects three + data values: two arrays of length N for the points, and + a third (N, 2) array of direction vectors for the arrows. + +:py:meth:`~chaco.plot.Plot.plot_1d` + The method for creating different types of 1D plot subclasses. + In adddition to the parameters listed above, this takes a + ``type`` argument, which is a string naming the type of plot + renderer to create, such as ``scatter_1d`` (the default), + ``line_scatter_1d``, ``textplot_1d``, and so on. + + +The plot renderers for a :py:class:`~chaco.plot.Plot` instance are +available via the :py:attr:`~chaco.plot.Plot.plot` attribute, which +is a dictionary mapping plot names to a list of plots that match +that name. Once obtained, they can have styling attributes changed +or otherwise be manipulated. In particular, since the plot renderers +are alse :py:class:`enable.component.Component` subclasses, they can +have tools attached to them and otherwise be used as a component +might be. + +Plot renderers can be removed by calling the +:py:meth:`~chaco.plot.Plot.delplot` method with arguments of the +names of the plots to be removed. All plot renderers with +matching names will be deleted. + +Plot renderers can also be shown and hidden as groups by name using +the :py:meth:`~chaco.plot.Plot.hideplot` and +:py:meth:`~chaco.plot.Plot.showplot` methods. + +Plot Configuration +================== + +Since :py:class:`~chaco.plot.Plot` is a subclass of +:py:class:`~enable.component.Component` the options for changing background +and border properties that :py:class:`~enable.component.Component` +provides are available. + +The :py:class:`~chaco.plot.Plot` class comes pre-configured to display +basic plots in a reasonably clean way: plots are provided with axes and +grids by default, but not with any other sort of decoration. However +it is straightforward to remove these, or to add other basic decoration +such as titles and legends if they are desired. + +Title characteristics can be set directly via attributes such as +:py:attr:`~chaco.plot.Plot.title_text`, +:py:attr:`~chaco.plot.Plot.title_font`, +:py:attr:`~chaco.plot.Plot.title_color`, +:py:attr:`~chaco.plot.Plot.title_angle`, and +:py:attr:`~chaco.plot.Plot.title_position`. The title text can also be set +via the convenience property :py:attr:`~chaco.plot.Plot.title`, which has the +added side-effect of hiding the title if the text is the empty string. + +.. literalinclude:: /../../examples/user_guide/power_function_example.py + :language: python + :lines: 26-36, 42-44 + +Title text and other attributes can be updated dynamically and the plot will +update correctly to display the modified label. + +.. literalinclude:: /../../examples/user_guide/power_function_example.py + :language: python + :lines: 70-72 + +The plot class also provides a :py:class:`~chaco.legend.Legend` instance +that is hidden by default. It can be shown by toggling the visibility +of the legend. The positioning of the legend relative to the plot can be +set via the :py:attr:`~chaco.plot.Plot.legend_alignment` trait. Additional +configuration can be performed via the :py:class:`~chaco.legend.Legend` class +up to and including replacing it with a custom :py:class:`~chaco.legend.Legend` +subclass. + +.. literalinclude:: /../../examples/user_guide/power_function_example.py + :language: python + :lines: 26-36, 45-48 + +Axes and grids can be accessed either as "index" and "value" or "x" and "y" +depending on how the code is working with them. In general it is preferable +to use "index" and "value" as this takes into account the orientation of the +plot. Axes and grids can be removed by setting their visibility to False, +or setting the appropriate trait to None. Axes and grids have many +configuration options, detailed in their documentation. + + diff --git a/examples/user_guide/power_function_example.py b/examples/user_guide/power_function_example.py new file mode 100644 index 000000000..23b97ac9b --- /dev/null +++ b/examples/user_guide/power_function_example.py @@ -0,0 +1,91 @@ +# (C) Copyright 2010-2019 Enthought, Inc., Austin, TX +# All rights reserved. + +import numpy as np + +from chaco.api import ArrayPlotData, Plot +from enable.api import ComponentEditor +from traits.api import Array, HasStrictTraits, Instance, Range, on_trait_change +from traitsui.api import Item, VGroup, View + + +class PowerFunctionExample(HasStrictTraits): + """ Display a plot of a power function. """ + + #: The plot holding the visualization + plot = Instance(Plot) + + #: The power of the monomial to use. + power = Range(0, 5, value=2) + + #: The x-values to plot. + x = Array(shape=(None,), dtype='float') + + # Trait defaults -------------------------------------------------------- + + def _plot_default(self): + 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' + ) + + # configure the plot + plot.padding_top = 25 + plot.border_visible = False + plot.index_grid.visible = False + plot.value_grid.visible = False + plot.title = "Power Function n={}".format(self.power) + plot.title_position = 'right' + plot.title_angle = -90 + plot.legend_alignment = 'ul' + plot.legend.border_visible = False + plot.legend.bgcolor = (0.9, 0.9, 0.9, 0.5) + plot.legend.visible = True + + plot.index_axis.title = "y" + plot.value_axis.title = "x" + + return plot + + def _x_default(self): + return np.linspace(-2.0, 2.0, 101) + + # Trait change handlers ------------------------------------------------- + + @on_trait_change('power') + def _update_y(self): + y = self.x**self.power + self.plot.data.set_data('y', y) + + @on_trait_change('x') + def _update_data(self): + y = self.x**self.power + self.plot.data.update_data(x=self.x, y=y) + + @on_trait_change('power') + def _update_title(self): + self.plot.title = "Power Function n={}".format(self.power) + + # TraitsUI view --------------------------------------------------------- + + view = View( + VGroup( + Item('plot', editor=ComponentEditor()), + VGroup( + Item('power'), + ), + show_labels=False, + ), + resizable=True, + title="Power Function Example" + ) + + +if __name__ == '__main__': + view = PowerFunctionExample() + view.configure_traits() From 791410c5146414d7e12ad42b22523a256da2e53b Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Mon, 20 May 2019 09:37:55 +0100 Subject: [PATCH 03/68] Update license dates. --- LICENSE.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 64ef4eeea..1469e40e1 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,20 +1,20 @@ This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative. -Copyright (c) 2006, Enthought, Inc. +Copyright (c) 2006-2019, Enthought, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of Enthought, Inc. nor the names of its contributors may - be used to endorse or promote products derived from this software without - specific prior written permission. +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of Enthought, Inc. nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED From 0090911bf6585cacff887e798a61b243e94b49ad Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Thu, 13 Jun 2019 09:52:37 +0100 Subject: [PATCH 04/68] [WIP] Start developer reference proper. --- .../fundamentals.rst | 15 + docs/source/developer_reference/index.rst | 16 + docs/source/index.rst | 2 +- .../source/user_manual/annotated_examples.rst | 16 +- .../basic_elements/plot_renderers.rst | 280 ++++++++---------- docs/source/user_manual/containers.rst | 102 +++---- docs/source/user_manual/how_do_i.rst | 52 ++-- docs/source/user_manual/index.rst | 2 +- docs/source/user_manual/plots.rst | 2 - docs/source/user_manual/resources.rst | 2 +- 10 files changed, 247 insertions(+), 242 deletions(-) rename docs/source/{user_manual => developer_reference}/fundamentals.rst (97%) create mode 100644 docs/source/developer_reference/index.rst diff --git a/docs/source/user_manual/fundamentals.rst b/docs/source/developer_reference/fundamentals.rst similarity index 97% rename from docs/source/user_manual/fundamentals.rst rename to docs/source/developer_reference/fundamentals.rst index 6c4418a7c..1d5e9cb2e 100644 --- a/docs/source/user_manual/fundamentals.rst +++ b/docs/source/developer_reference/fundamentals.rst @@ -742,4 +742,19 @@ example, the following Enable tools may be of use: which sets the values of attributes on an object as the mouse moves, which is a common use case. +Overlays and Underlays +---------------------- + +In some instances you want to render additional decorations that are +independent of the plot type. In a similar fashion to the Tool classes +auxilliary renderers can be attached to plots as "overlays" (and using +the same mechanism, just rendering into a different layer, as +"underlays"). Common use cases for overlays include cursor lines, +selection regions, hover text, legends and other annotations. Overlays +are frequently designed to work together with a particular Tool or class +of tools, but can frequently be used independently if desired. + +Overlays and underlays which need to render relative to points in +data space will frequently want to make use of the plot mappers to know +where in screen space to perform their drawing operations.. diff --git a/docs/source/developer_reference/index.rst b/docs/source/developer_reference/index.rst new file mode 100644 index 000000000..53b285347 --- /dev/null +++ b/docs/source/developer_reference/index.rst @@ -0,0 +1,16 @@ +.. _developer_reference: + +=================== +Developer Reference +=================== + +This guide is designed to provide a guide to developers wanting to extend +the capabilities of Chaco by writing new tools, overlays and plot renders. +For complete details of the interfaces and base classes that you will need +to use, refer to the Chaco API documentation. + +.. toctree:: + :maxdepth: 2 + + fundamentals.rst + diff --git a/docs/source/index.rst b/docs/source/index.rst index a2a0dc766..c7e14be99 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -54,7 +54,7 @@ tricks that help when building Chaco applications. For comprehensive documentation, we have: * :ref:`User Reference ` -* Developer Reference +* :ref:`Developer Reference ` * :ref:`search` Reporting bugs and contributing diff --git a/docs/source/user_manual/annotated_examples.rst b/docs/source/user_manual/annotated_examples.rst index 3c7bc278c..f71a6312c 100644 --- a/docs/source/user_manual/annotated_examples.rst +++ b/docs/source/user_manual/annotated_examples.rst @@ -110,9 +110,9 @@ source: `multiaxis.py `_ @@ -379,7 +379,7 @@ source: `polygon_plot_demo.py `_ @@ -428,7 +428,7 @@ source: `scatter_select.py it is removed - # from the first, as each plot can only have one container - h_container2.add(line_plot1) + # Add the three plots to the first container + h_container1.add(scatter_plot, line_plot1, line_plot2) - results in this layout: + # Now add the first line plot to the second container => it is removed + # from the first, as each plot can only have one container + h_container2.add(line_plot1) - .. image:: images/user_guide/one_container_per_plot.png - :height: 200pt +results in this layout: + .. image:: images/user_guide/one_container_per_plot.png + :height: 200pt .. _hv-plot-container: @@ -147,18 +145,18 @@ HPlotContainer parameters This is a list of parameters that are specific to :class:`~chaco.plot_containers.HPlotContainer` -* ``stack_order``: +:py:attr:`stack_order`: The order in which components in the plot container are laid out. The default behavior is left-to-right. :: stack_order = Enum("left_to_right", "right_to_left") -* ``spacing``: +:py:attr:`spacing`: The amount of space to put between components. :: spacing = Float(0.0) -* ``valign``: +:py:attr:`valign`: The vertical alignment of objects that don't span the full height. :: valign = Enum("bottom", "top", "center") @@ -170,18 +168,18 @@ VPlotContainer parameters This is a list of parameters that are specific to :class:`~chaco.plot_containers.VPlotContainer` -* ``stack_order``: +:py:attr:`stack_order`: The order in which components in the plot container are laid out. The default behavior is bottom-to-top. :: stack_order = Enum("bottom_to_top", "top_to_bottom") -* ``spacing``: +:py:attr:`spacing`: The amount of space to put between components.:: spacing = Float(0.0) -* ``halign``: +:py:attr:`halign`: The horizontal alignment of objects that don't span the full width.:: halign = Enum("left", "right", "center") @@ -268,18 +266,19 @@ GridPlotContainer parameters This is a list of parameters that are specific to :class:`~chaco.plot_containers.GridPlotContainer` -* ``valign``: +:py:attr:`valign`: The vertical alignment of objects that don't span the full height.:: valign = Enum("bottom", "top", "center") -* ``halign``: +:py:attr:`halign`: The horizontal alignment of objects that don't span the full width.:: halign = Enum("left", "right", "center") -* ``spacing``: A tuple or list of ``(h_spacing, v_spacing)``, +:py:attr:`spacing`: + A tuple or list of ``(h_spacing, v_spacing)``, giving spacing values for the horizontal and vertical direction. Default is (0, 0). @@ -377,22 +376,26 @@ their container to set their final aspect. The basic traits that control the layout preferences of a component are: -* :attr:`resizable`, a string indicating in which directions the component +:attr:`resizable`: + A string indicating in which directions the component can be resized. Its value is one of ``''`` (not resizable), ``'h'`` (resizable in the horizontal direction), ``'v'`` (resizable in the vertical direction), ``'hv'`` (resizable in both, default). -* :attr:`aspect_ratio`, the ratio of the component's width to its height. +:attr:`aspect_ratio`: + The ratio of the component's width to its height. This is used by the component itself to maintain bounds when the bounds are changed independently. Default is ``None``, meaning that the aspect ratio is not enforced. -* :attr:`padding_left`, :attr:`padding_right`, - :attr:`padding_top`, :attr:`padding_bottom` set the amount of padding space +:attr:`padding_left`, :attr:`padding_right`, :attr:`padding_top`, :attr:`padding_bottom`: + Set the amount of padding space to leave around the component (default is 0). The property :attr:`padding` allows to set all of them as a tuple (left, right, top, bottom). -* :attr:`auto_center`, controls the behavior when the component's bounds are +:attr:`auto_center`: + Controls the behavior when the component's bounds are set to a value that does not conform its aspect ratio. If ``True`` (default), the component centers itself in the free space. -* :attr:`fixed_preferred_size`: If the component is resizable, this attribute +:attr:`fixed_preferred_size`: + If the component is resizable, this attribute specifies the amount of space that the component would like to get in each dimension, as a tuple (width, height). This attribute can be used to establish @@ -401,18 +404,17 @@ The basic traits that control the layout preferences of a component are: specifies a fixed preferred width of 100, then the latter component will always be twice as wide as the former. -You can get access to the actual bounds of the component, (including -padding and border) using the -``outer`` properties: +You can get access to the actual bounds of the component, (including padding and border) +using the ``outer`` properties: -* :attr:`outer_position`, the x,y point of the lower left corner of the +:attr:`outer_position`: + The x,y point of the lower left corner of the padding outer box around the component. Use :meth:`set_outer_position` to change these values. -* :attr:`outer_bounds`, - the number of horizontal and vertical pixels in the padding outer box. +:attr:`outer_bounds`: + The number of horizontal and vertical pixels in the padding outer box. Use :meth:`set_outer_bounds` to change these values. -* :attr:`outer_x`, :attr:`outer_y`, :attr:`outer_x2`, :attr:`outer_y2:, - :attr:`outer_width`, :attr:`outer_height`: +:attr:`outer_x`, :attr:`outer_y`, :attr:`outer_x2`, :attr:`outer_y2:, :attr:`outer_width`, :attr:`outer_height`: coordinates of lower-left pixel of the box, coordinates of the upper-right pixel of the box, width and height of the outer box in pixels diff --git a/docs/source/user_manual/how_do_i.rst b/docs/source/user_manual/how_do_i.rst index f1c34510c..397478dba 100644 --- a/docs/source/user_manual/how_do_i.rst +++ b/docs/source/user_manual/how_do_i.rst @@ -35,30 +35,38 @@ Basics from enable.api import Window class PlotFrame(wx.Frame): - def __init__(self, *args, **kw): - kw["size"] = (850, 550) - wx.Frame.__init__( *(self,) + args, **kw ) - self.plot_window = Window(self, component=self._create_plot()) - sizer = wx.BoxSizer(wx.HORIZONTAL) - sizer.Add(self.plot_window.control, 1, wx.EXPAND) - self.SetSizer(sizer) - self.SetAutoLayout(True) - self.Show(True) - return - - def _create_plot(self): - x = arange(-5.0, 15.0, 20.0/100) - y = jn(0, x) - plot = create_line_plot((x,y), bgcolor="white", - add_grid=True, add_axis=True) - container = HPlotContainer(spacing=20, padding=50, bgcolor="lightgray") - container.add(plot) - return container + + def __init__(self, *args, **kw): + kw["size"] = (850, 550) + super(PlotFrame, self).__init__(*args, **kw) + self.plot_window = Window(self, component=self._create_plot()) + sizer = wx.BoxSizer(wx.HORIZONTAL) + sizer.Add(self.plot_window.control, 1, wx.EXPAND) + self.SetSizer(sizer) + self.SetAutoLayout(True) + self.Show(True) + + def _create_plot(self): + x = arange(-5.0, 15.0, 20.0/100) + y = jn(0, x) + plot = create_line_plot( + (x,y), + bgcolor="white", + add_grid=True, + add_axis=True, + ) + container = HPlotContainer( + spacing=20, + padding=50, + bgcolor="lightgray", + ) + container.add(plot) + return container if __name__ == "__main__": - app = wx.PySimpleApp() - frame = PlotFrame(None) - app.MainLoop() + app = wx.PySimpleApp() + frame = PlotFrame(None) + app.MainLoop() Note that this will require for the ETS_TOOLKIT environment variable to be set to 'wx'. diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index 613066b19..e38632079 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -18,7 +18,7 @@ of the Chaco API, refer to the Chaco API documentation. installation.rst plots.rst containers.rst - fundamentals.rst + basic_elements/data_sources.rst basic_elements/data_mappers.rst basic_elements/data_ranges.rst diff --git a/docs/source/user_manual/plots.rst b/docs/source/user_manual/plots.rst index 7292212a2..7554139a0 100644 --- a/docs/source/user_manual/plots.rst +++ b/docs/source/user_manual/plots.rst @@ -250,5 +250,3 @@ to use "index" and "value" as this takes into account the orientation of the plot. Axes and grids can be removed by setting their visibility to False, or setting the appropriate trait to None. Axes and grids have many configuration options, detailed in their documentation. - - diff --git a/docs/source/user_manual/resources.rst b/docs/source/user_manual/resources.rst index d2d3fbafa..15be5a909 100644 --- a/docs/source/user_manual/resources.rst +++ b/docs/source/user_manual/resources.rst @@ -59,7 +59,7 @@ each webinar covering Chaco. * The first one (April 2010) demoes how to use Chaco as your plotting tool (https://www.enthought.com/repo/epd/webinars/2010-04InteractiveChaco/ ). -* The seconds (October 2010) illustrates how to building interactive 2D visualization (see +* The second (October 2010) illustrates how to building interactive 2D visualization (see https://www.enthought.com/repo/epd/webinars/2010-10Building2DInteractiveVisualizations/ ). From 6a7240c91c251e56a110dd366193b2763fa3215a Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Sat, 13 Jul 2019 09:57:45 -0500 Subject: [PATCH 05/68] More WIP --- docs/source/api/renderers.rst | 12 ++++++++++++ docs/source/index.rst | 3 ++- docs/source/user_manual/index.rst | 2 +- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/source/api/renderers.rst b/docs/source/api/renderers.rst index 5316a1b5a..0d504e2de 100644 --- a/docs/source/api/renderers.rst +++ b/docs/source/api/renderers.rst @@ -102,6 +102,18 @@ Renderers :members: :show-inheritance: +:class:`SegmentPlot` +=================== +.. autoclass:: SegmentPlot + :members: + :show-inheritance: + +:class:`TextPlot` +=================== +.. autoclass:: TextPlot + :members: + :show-inheritance: + :class:`MultiLinePlot` ====================== .. autoclass:: MultiLinePlot diff --git a/docs/source/index.rst b/docs/source/index.rst index c7e14be99..40fdae336 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -53,8 +53,9 @@ tricks that help when building Chaco applications. For comprehensive documentation, we have: -* :ref:`User Reference ` +* :ref:`User Guide ` * :ref:`Developer Reference ` +* :ref:`API Reference ` * :ref:`search` Reporting bugs and contributing diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index e38632079..e58c730b8 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -1,7 +1,7 @@ .. _user_guide: =========== -User guide +User Guide =========== This guide is designed to act as a conceptual guide to Chaco, an open-source From 83fc339ca6d7389e890d7a2ecd2da115b8bbbc34 Mon Sep 17 00:00:00 2001 From: Corran Webster Date: Sat, 13 Jul 2019 09:58:16 -0500 Subject: [PATCH 06/68] Add index for api docs. --- docs/source/api/index.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 docs/source/api/index.rst diff --git a/docs/source/api/index.rst b/docs/source/api/index.rst new file mode 100644 index 000000000..d2559a2dc --- /dev/null +++ b/docs/source/api/index.rst @@ -0,0 +1,22 @@ +.. _api_reference: + +============= +API Reference +============= + +This guide provides in-depth API documentation for the main classes and +objects in the Chaco package. + +.. toctree:: + :maxdepth: 2 + + visual_components.rst + containers.rst + data_sources.rst + mappers.rst + data_ranges.rst + renderers.rst + plot_factories.rst + tools.rst + axis.rst + From ef505c65789b458cfcdd108f8114a2c4b36a57a4 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 10:21:33 -0500 Subject: [PATCH 07/68] FIX: Add missing imports to api Adds missing imports of SegmentPlot and TextPlot to api.py. --- chaco/api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/chaco/api.py b/chaco/api.py index e8680c141..e600bdee1 100644 --- a/chaco/api.py +++ b/chaco/api.py @@ -89,6 +89,8 @@ from .scatterplot_1d import ScatterPlot1D from .line_scatterplot_1d import LineScatterPlot1D from .text_plot_1d import TextPlot1D +from .segment_plot import SegmentPlot +from .text_plot import TextPlot # Plot factories from .plot_factory import create_bar_plot, create_line_plot, create_scatter_plot, \ From 50a5104e19f0097dba767b3905b60378ab251069 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 10:48:17 -0500 Subject: [PATCH 08/68] DOC: Fix missing link warnings --- chaco/barplot.py | 14 +++++++------- chaco/lineplot.py | 6 +++--- chaco/polygon_plot.py | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/chaco/barplot.py b/chaco/barplot.py index 6fa8c71bd..f385238a1 100644 --- a/chaco/barplot.py +++ b/chaco/barplot.py @@ -78,14 +78,14 @@ class BarPlot(AbstractPlotRenderer): #: Color to fill the bars. fill_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 line_color_, and its alpha value is the - #: alpha value of self.line_color multiplied by self.alpha. + #: 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']) - - #: The RGBA tuple for rendering the fill. It is always a tuple of length 4. - #: It has the same RGB values as fill_color_, and its alpha value is the - #: alpha value of self.fill_color multiplied by self.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']) #: Overall alpha value of the image. Ranges from 0.0 for transparent to 1.0 diff --git a/chaco/lineplot.py b/chaco/lineplot.py index 62ac17627..8d14c56b5 100644 --- a/chaco/lineplot.py +++ b/chaco/lineplot.py @@ -32,9 +32,9 @@ class LinePlot(BaseXYPlot): #: 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 color_, and its alpha value is the alpha - #: value of self.color multiplied by self.alpha. + #: 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']) #: The color to use to highlight the line when selected. diff --git a/chaco/polygon_plot.py b/chaco/polygon_plot.py index 834b1b0ed..37fa0a504 100644 --- a/chaco/polygon_plot.py +++ b/chaco/polygon_plot.py @@ -51,15 +51,15 @@ class PolygonPlot(BaseXYPlot): #: Override the hittest_type trait inherited from BaseXYPlot hittest_type = Enum("poly", "point", "line") - - #: The RGBA tuple for rendering edges. It is always a tuple of length 4. - #: It has the same RGB values as edge_color_, and its alpha value is the - #: alpha value of self.edge_color multiplied by self.alpha. + + #: 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']) - - #: The RGBA tuple for rendering the face. It is always a tuple of length 4. - #: It has the same RGB values as face_color_, and its alpha value is the - #: alpha value of self.face_color multiplied by self.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']) #---------------------------------------------------------------------- From 278d5374002022a0ca40c5da2277f76685819029 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 10:48:53 -0500 Subject: [PATCH 09/68] DOX: Fix line header length warnings --- docs/source/api/renderers.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/api/renderers.rst b/docs/source/api/renderers.rst index 0d504e2de..63bfdff95 100644 --- a/docs/source/api/renderers.rst +++ b/docs/source/api/renderers.rst @@ -103,13 +103,13 @@ Renderers :show-inheritance: :class:`SegmentPlot` -=================== +==================== .. autoclass:: SegmentPlot :members: :show-inheritance: :class:`TextPlot` -=================== +================= .. autoclass:: TextPlot :members: :show-inheritance: From c965de7fc210e190e9017596617d04ab7942fb18 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 10:52:44 -0500 Subject: [PATCH 10/68] DOC: Fix missing link to installation instructions --- docs/source/index.rst | 2 +- docs/source/user_manual/installation.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 40fdae336..38ef4318f 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -33,7 +33,7 @@ EPD): edm install chaco pyqt For full installation options, including installation from source, see the -:ref:`installation instructions ` +:ref:`installation instructions `. Documentation ------------- diff --git a/docs/source/user_manual/installation.rst b/docs/source/user_manual/installation.rst index 85dbf70f9..5da942d11 100644 --- a/docs/source/user_manual/installation.rst +++ b/docs/source/user_manual/installation.rst @@ -1,4 +1,4 @@ -.. _installation:: +.. _installation: ============ Installation From a716ad3736436177cf9146bc644e322abce021b3 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 11:02:11 -0500 Subject: [PATCH 11/68] DOC: Remove link to Enthought wiki --- .../user_manual/tutorial_van_der_waal.rst | 81 +++++++++---------- 1 file changed, 40 insertions(+), 41 deletions(-) diff --git a/docs/source/user_manual/tutorial_van_der_waal.rst b/docs/source/user_manual/tutorial_van_der_waal.rst index 7cbcffbd3..8912e4752 100644 --- a/docs/source/user_manual/tutorial_van_der_waal.rst +++ b/docs/source/user_manual/tutorial_van_der_waal.rst @@ -18,12 +18,11 @@ molecules and the attraction to each other that they experience. Development Setup ================= -In review, Traits is a manifest typing and reactive programming package for -Python. It also provides UI features that will be used to create a simple GUI. -The Traits and Traits UI user manuals are good resources for learning about the -packages and can be found on the -`Traits Wiki `_. The wiki -includes features, technical notes, cookbooks, FAQ and more. +In review, Traits is a manifest typing and reactive programming package +for Python. It also provides UI features that will be used to create a +simple GUI. The `Traits `_ and +`Traits UI `_ user manuals are good +resources for learning about the packages. You must have Chaco and its dependencies installed: @@ -37,10 +36,10 @@ Writing the Program First, define a Traits class and the elements necessary need to model the task. The following Traits class is made for the Van Der Waal -equation, whose variables can be viewed on +equation, whose variables can be viewed on `this wiki page `_. The -:attr:`volume` and :attr:`pressure` attributes hold lists of our X- and -Y-coordinates, respectively, and are defined as arrays. The attributes +:attr:`volume` and :attr:`pressure` attributes hold lists of our X- and +Y-coordinates, respectively, and are defined as arrays. The attributes :attr:`attraction` and :attr:`totVolume` are input parameters specified by the user. The type of the variables dictates their appearance in the GUI. For example, :attr:`attraction` and :attr:`totVolume` are defined as Ranges, so they @@ -52,10 +51,10 @@ list, since it is defined as an Enum. # We'll also import a few things to be used later. from traits.api \ import HasTraits, Array, Range, Float, Enum, on_trait_change, Property - from traitsui.api import View, Item + from traitsui.api import View, Item from chaco.chaco_plot_editor import ChacoPlotItem from numpy import arange - + class Data(HasTraits): volume = Array pressure = Array @@ -64,8 +63,8 @@ list, since it is defined as an Enum. temperature = Range(low=-50.0,high=50.0,value=50.0) r_constant= Float(8.314472) plot_type = Enum("line", "scatter") - - .... + + .... Creating the View @@ -75,7 +74,7 @@ The main GUI window is created by defining a Traits :class:`View` instance. This View contains all of the GUI elements, including the plot. To link a variable with a widget element on the GUI, we create a Traits :class:`Item` instance with the same name as the variable and pass it as an -argument of the Traits View instance declaration. The +argument of the Traits View instance declaration. The `Traits UI User Guide `_ discusses the View and Item objects in depth. In order to embed a Chaco plot into a Traits View, you need to import the @@ -88,7 +87,7 @@ provided to the plot for additional customization:: class Data(HasTraits): .... - + traits_view = View(ChacoPlotItem("volume", "pressure", type_trait="plot_type", resizable=True, @@ -106,7 +105,7 @@ provided to the plot for additional customization:: padding_bg_color="lightgray"), Item(name='attraction'), Item(name='totVolume'), - Item(name='temperature'), + Item(name='temperature'), Item(name='r_constant', style='readonly'), Item(name='plot_type'), resizable = True, @@ -115,7 +114,7 @@ provided to the plot for additional customization:: width=900, height=800) .... - + Updating the Plot ================= @@ -127,7 +126,7 @@ parameters are changed by the user moving the sliders in the GUI. The :attr:`volume` attribute is the independent variable and :attr:`pressure` is the dependent variable. The relationship between pressure and volume, as derived from the equation found on the wiki page, is:: - + r_constant * Temperature attraction Pressure = ------------------------ - ---------- Volume - totVolume Volume**2 @@ -149,15 +148,15 @@ The following is the code for these two needs:: def calc(self): """ Update the data based on the numbers specified by the user. """ self.volume = arange(.1, 100) - self.pressure = ((self.r_constant*self.temperature) - /(self.volume - self.totVolume) + self.pressure = ((self.r_constant*self.temperature) + /(self.volume - self.totVolume) -(self.attraction/(self.volume*self.volume))) return The :func:`calc` function computes the :attr:`pressure` array using the current values of the independent variables. Meanwhile, the :func:`@on_trait_change` decorator (provided by Traits) tells Python to call -:func:`calc` whenever any of the attributes :attr:`attraction`, +:func:`calc` whenever any of the attributes :attr:`attraction`, :attr:`totVolume`, or :attr:`temperature` changes. @@ -224,36 +223,36 @@ For the new implementation, these are the necessary changes: 1. Define the Y-coordinate array variable as a Property instead of an Array. -2. Perform the calculations in the :samp:`\_get_{trait_name}` method for the - Y-coordinate array variable, which is :meth:`_get_pressure` in this +2. Perform the calculations in the :samp:`\_get_{trait_name}` method for the + Y-coordinate array variable, which is :meth:`_get_pressure` in this example. 3. Define the :samp:`\_{trait}_default` method to set the initial value of - the X-coordinate array, so :meth:`\_get_pressure` does not have to keep + the X-coordinate array, so :meth:`\_get_pressure` does not have to keep recalculating it. -4. Remove the previous :func:`@on_trait_change` decorator and calculation +4. Remove the previous :func:`@on_trait_change` decorator and calculation method. The new pieces of code to add to the Data class are:: class Data(HasTraits): ... - pressure = Property(Array, depends_on=['temperature', - 'attraction', + pressure = Property(Array, depends_on=['temperature', + 'attraction', 'totVolume']) ... - + def _volume_default(self): return arange(.1, 100) - - # Pressure is recalculated whenever one of the elements the property + + # Pressure is recalculated whenever one of the elements the property # depends on changes. No need to use @on_trait_change. def _get_pressure(self): return ((self.r_constant*self.temperature) - /(self.volume - self.totVolume) + /(self.volume - self.totVolume) -(self.attraction/(self.volume*self.volume))) You now no longer have to call an inconvenient calculation function -before the first call to :meth:`configure_traits`! +before the first call to :meth:`configure_traits`! Source Code @@ -266,17 +265,17 @@ The final version on the program, `vanderwaals.py` :: from traitsui.api import View, Item from chaco.chaco_plot_editor import ChacoPlotItem from numpy import arange - + class Data(HasTraits): volume = Array - pressure = Property(Array, depends_on=['temperature', 'attraction', + pressure = Property(Array, depends_on=['temperature', 'attraction', 'totVolume']) attraction = Range(low=-50.0,high=50.0,value=0.0) totVolume = Range(low=.01,high=100.0,value=0.01) temperature = Range(low=-50.0,high=50.0,value=50.0) r_constant= Float(8.314472) plot_type = Enum("line", "scatter") - + traits_view = View(ChacoPlotItem("volume", "pressure", type_trait="plot_type", resizable=True, @@ -294,25 +293,25 @@ The final version on the program, `vanderwaals.py` :: padding_bg_color="lightgray"), Item(name='attraction'), Item(name='totVolume'), - Item(name='temperature'), + Item(name='temperature'), Item(name='r_constant', style='readonly'), Item(name='plot_type'), resizable = True, buttons = ["OK"], title='Van der Waal Equation', width=900, height=800) - - + + def _volume_default(self): """ Default handler for volume Trait Array. """ return arange(.1, 100) - + def _get_pressure(self): """Recalculate when one a trait the property depends on changes.""" return ((self.r_constant*self.temperature) - /(self.volume - self.totVolume) + /(self.volume - self.totVolume) -(self.attraction/(self.volume*self.volume))) - + if __name__ == '__main__': viewer = Data() viewer.configure_traits() From 6b4284381af2152c3a9d74f72883d6b3e204acd3 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 11:27:43 -0500 Subject: [PATCH 12/68] DOC: Fix broken link to mappers --- docs/source/user_manual/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index e58c730b8..7a634c791 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -20,7 +20,7 @@ of the Chaco API, refer to the Chaco API documentation. containers.rst basic_elements/data_sources.rst - basic_elements/data_mappers.rst + basic_elements/mappers.rst basic_elements/data_ranges.rst basic_elements/plot_renderers.rst tools.rst From 3788ae87e8d6050bd76f0780f028bb6e225a4196 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 11:37:23 -0500 Subject: [PATCH 13/68] DOC: Fix broken formatting in renderer index --- docs/source/api/renderers.rst | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/source/api/renderers.rst b/docs/source/api/renderers.rst index 63bfdff95..b5ba1ca69 100644 --- a/docs/source/api/renderers.rst +++ b/docs/source/api/renderers.rst @@ -126,23 +126,23 @@ Renderers :members: :show-inheritance: -..:class:`JitterPlot` -..=================== -.... autoclass:: JitterPlot -.. :members: -.. :show-inheritance: - -..:class:`LineScatterPlot1D` -..=================== -.... autoclass:: LineScatterPlot1D -.. :members: -.. :show-inheritance: - -..:class:`TextPlot1D` -..=================== -.... autoclass:: TextPlot1D -.. :members: -.. :show-inheritance: +:class:`JitterPlot` +===================== +.. autoclass:: JitterPlot + :members: + :show-inheritance: + +:class:`LineScatterPlot1D` +============================ +.. autoclass:: LineScatterPlot1D + :members: + :show-inheritance: + +:class:`TextPlot1D` +===================== +.. autoclass:: TextPlot1D + :members: + :show-inheritance: :class:`VariableSizeScatterPlot` ================================ From f2d452b95709fca3d815d3253ef9416a54a5c1c4 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 14:09:40 -0500 Subject: [PATCH 14/68] DOC: Remove empty tutorial_wx file --- docs/source/user_manual/tutorial_wx.rst | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 docs/source/user_manual/tutorial_wx.rst diff --git a/docs/source/user_manual/tutorial_wx.rst b/docs/source/user_manual/tutorial_wx.rst deleted file mode 100644 index 7ebe785ef..000000000 --- a/docs/source/user_manual/tutorial_wx.rst +++ /dev/null @@ -1,9 +0,0 @@ - -.. _tutorial_wx: - -################# -WX-based Tutorial -################# - - - From adfe984f62243dec094fa1ab887931c48d1895a8 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 14:20:29 -0500 Subject: [PATCH 15/68] DOC: Mark already-referenced as :orphan: Mark index documents are orphans to silence warnings that they aren't included in any TOC. --- docs/source/api/index.rst | 2 ++ docs/source/developer_reference/index.rst | 2 ++ docs/source/user_manual/index.rst | 3 +++ 3 files changed, 7 insertions(+) diff --git a/docs/source/api/index.rst b/docs/source/api/index.rst index d2559a2dc..ca8770911 100644 --- a/docs/source/api/index.rst +++ b/docs/source/api/index.rst @@ -1,3 +1,5 @@ +:orphan: + .. _api_reference: ============= diff --git a/docs/source/developer_reference/index.rst b/docs/source/developer_reference/index.rst index 53b285347..d42576aab 100644 --- a/docs/source/developer_reference/index.rst +++ b/docs/source/developer_reference/index.rst @@ -1,3 +1,5 @@ +:orphan: + .. _developer_reference: =================== diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index 7a634c791..957e4429d 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -1,5 +1,8 @@ +:orphan: + .. _user_guide: + =========== User Guide =========== From 04075305fd5d9932a35b2f9e62f2757ddfc4601a Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 14:21:30 -0500 Subject: [PATCH 16/68] DOC: Fix RST link in ToolbarPlot --- chaco/toolbar_plot.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/chaco/toolbar_plot.py b/chaco/toolbar_plot.py index bb26b2ad1..dbc8b1797 100644 --- a/chaco/toolbar_plot.py +++ b/chaco/toolbar_plot.py @@ -13,10 +13,9 @@ class ToolbarPlot(Plot): toolbar_added = False #: Location of the default toolbar that is created if a toolbar - #: is not specified with the `toolbar` attribute. Changing this + #: is not specified with the :attr:`toolbar` attribute. Changing this #: attribute after the ToolbarPlot instance is created has no effect; - #: use obj.toolbar.location to dynamically change the location of the - #: instance `obj`s toolbar. + #: use obj.toolbar.location to dynamically change toolbar's location. toolbar_location = Enum('top', 'right', 'bottom', 'left') def __init__(self, *args, **kw): From 3f7fe246485d993d7b198e4c17d4238c07d79aab Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 14:59:57 -0500 Subject: [PATCH 17/68] DOC: CLN: Remove links to old webinars --- docs/source/user_manual/resources.rst | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/docs/source/user_manual/resources.rst b/docs/source/user_manual/resources.rst index 15be5a909..6d81c4908 100644 --- a/docs/source/user_manual/resources.rst +++ b/docs/source/user_manual/resources.rst @@ -47,22 +47,6 @@ Finally, it is recommended to explore the examples changes and recommended ways to use Chaco. -.. _chaco_webinars: - -Enthought webinars ------------------- -The video webinars given in as part of the Enthought webinar -series cover building interactive plotting using Chaco. If you are an -EPD user, you can find the video, the slides, and the demo code for -each webinar covering Chaco. - -* The first one (April 2010) demoes how to use Chaco as your plotting - tool (https://www.enthought.com/repo/epd/webinars/2010-04InteractiveChaco/ ). - -* The second (October 2010) illustrates how to building interactive 2D visualization (see - https://www.enthought.com/repo/epd/webinars/2010-10Building2DInteractiveVisualizations/ ). - - .. _chaco_presentations: From d640235de12877941d8daf4e8d2d81601b6ea57d Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 15:48:57 -0500 Subject: [PATCH 18/68] DOC: CLN: Remove resource.rst and move contents Remove the `user_guide/resource.rst` because it only contained redundant contents and broken links. The only relevant bit of text was about the SciPy 2008 tutorial, which is covered by `chaco_tutorial.rst` so I moved some of the text there. --- docs/source/user_manual/chaco_tutorial.rst | 10 ++- docs/source/user_manual/resources.rst | 84 ---------------------- 2 files changed, 8 insertions(+), 86 deletions(-) delete mode 100644 docs/source/user_manual/resources.rst diff --git a/docs/source/user_manual/chaco_tutorial.rst b/docs/source/user_manual/chaco_tutorial.rst index e6331fe9f..d004a5e8c 100644 --- a/docs/source/user_manual/chaco_tutorial.rst +++ b/docs/source/user_manual/chaco_tutorial.rst @@ -1247,8 +1247,14 @@ they are constructed: almost all tools need to use some capabilities Final words =========== -This concludes this tutorial. For further information, please refer -to the :ref:`Resources` page, or visit the :ref:`user_guide`. +This concludes this tutorial. For further information, visit the +:ref:`user_guide`. You can find the examples for this tutorial in the +:file:`examples/tutorials/scipy2008/` directory of the Chaco source code. You +can browse it online in the `GitHub repository +`_ if you +don't have a local copy. They are are numbered and introduce concepts one at a +time, going from a simple line plot to building a custom overlay with its own +trait editor and reusing an existing tool from the built-in set of tools. *This tutorial is based on the "Interactive plotting with Chaco" tutorial diff --git a/docs/source/user_manual/resources.rst b/docs/source/user_manual/resources.rst deleted file mode 100644 index 6d81c4908..000000000 --- a/docs/source/user_manual/resources.rst +++ /dev/null @@ -1,84 +0,0 @@ -.. _resources: - -===================== -Other Chaco resources -===================== - - -Chaco Gallery -============= -Examples of what can be done with Chaco is available in -the `Chaco gallery `_. - -.. _going_further: - -Further Reading and resources -============================= - -You can also learn more about Chaco by: - -* running :ref:`the tutorials ` included with the Chaco package, - -* following :ref:`demos of Chaco ` given during webinars Enthought to EPD subscribers, - -* reading :ref:`seminar slides ` posted on conference websites, - -* reading about :ref:`the API ` from the developer guide. - -* following the Enthought Tool Suite mailing list: enthought-dev@enthought.com - -.. _built_in_tutorials: - -Built-in tutorials ------------------- - -For more details on how to use Chaco to embed powerful plotting -functionality inside applications, refer to the :ref:`tutorials` page. -In particular, some tutorial examples were added into the -:file:`examples/tutorials/scipy2008/` directory. These examples are -numbered and introduce -concepts one at a time, going from a simple line plot to building a -custom overlay with its own trait editor and reusing an existing tool -from the built-in set of tools. You can browse them on the GitHub repository -at: -https://github.com/enthought/chaco/tree/master/examples/tutorials . -Finally, it is recommended to explore the examples -(:ref:`examples` section) as they are regularly updated to reflect the most recent -changes and recommended ways to use Chaco. - - -.. _chaco_presentations: - - -Presentations -------------- - -There have been several presentations on Chaco at previous PyCon and -SciPy conferences: - -* Video recording of the latest Chaco presentation at SciPy 2011 at - http://conference.scipy.org/scipy2011/tutorials.php#corran - -* Follow the tutorial from the Scipy 2006 conference at - http://code.enthought.com/projects/files/chaco_scipy06/chaco_talk.html , - -* Follow the presentation of Chaco at the PyCon 2007 at - http://code.enthought.com/projects/files/chaco_pycon07/ . - -* `SciPy 2008 Tutorial slides (pdf) `_ - -.. _api_docs: - -Developers references and API Docs ------------------------------------ - -For developers and architects, - -* more details about the **current architecture and API** can be found in - the :ref:`programmers_reference`, - -* the API for Chaco 3.0 (in ETS 3.0) can be found at - http://code.enthought.com/projects/files/ETS3_API/enthought.chaco.html , - -* the API for Chaco2 (in ETS 2.7.1) can be found at - http://code.enthought.com/projects/files/ets_api/enthought.chaco2.html . From 93da8fa025a99f7fe53b6173902b1b019fcfeb89 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 15:53:25 -0500 Subject: [PATCH 19/68] CLN: Remove and update links to code.enthought.com Either point to a different location if relevant, or straight out remove the link if it's broken. --- docs/source/index.rst | 2 +- docs/source/quickstart.rst | 4 ++-- docs/source/user_manual/tutorial_hyetograph.rst | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 38ef4318f..aa98363a3 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -75,7 +75,7 @@ screenshots of the issue or the fix. License ------- -As part of the `Enthought Tool Suite `_, Chaco is +As part of the `Enthought Tool Suite `_, Chaco is free and open source under a BSD license: .. include:: ../../LICENSE.txt diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 973419c99..2ed66cb3d 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -60,7 +60,7 @@ Matplotlib or Matlab users. .. note:: Some of these examples can be visualized in our - `Chaco gallery `_. + :ref:`annotated examples `. First plots from the command line @@ -292,7 +292,7 @@ applications with custom visualizations, consider going over the License ======= -As part of the `Enthought Tool Suite `_, Chaco is +As part of the `Enthought Tool Suite `_, Chaco is free and open source under the BSD license. Reporting bugs and contributing diff --git a/docs/source/user_manual/tutorial_hyetograph.rst b/docs/source/user_manual/tutorial_hyetograph.rst index f238b5f99..89b238efe 100644 --- a/docs/source/user_manual/tutorial_hyetograph.rst +++ b/docs/source/user_manual/tutorial_hyetograph.rst @@ -112,7 +112,7 @@ The above code snippet shows a number of Traits features, The Traits API Reference contains more information about the standard Trait types; see the :mod:`trait_types` module in the `Traits API Reference -`_. +`_. Setting up the User Interface (UI) From 59eb91564638ac3ea286e72e7c44ca93998272a4 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 15:59:31 -0500 Subject: [PATCH 20/68] DOC: CLN: Fix warnings to unescaped * and broken link --- docs/source/quickstart.rst | 2 +- docs/source/user_manual/plots.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 2ed66cb3d..80916bfda 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -189,7 +189,7 @@ The previous section showed how Chaco can be used interactively similarly to `Matlab` or Matplotlib's `pyplot` package. Now, let's create, from scratch, the simplest possible Chaco plot which is -embedded inside a `Traits`_ application. This will require more work but will +embedded inside a `Traits `_ application. This will require more work but will represent the basis for a potential large-scale, custom and powerful rich client application. this is really what Chaco has been written for. diff --git a/docs/source/user_manual/plots.rst b/docs/source/user_manual/plots.rst index 7554139a0..63aa65a95 100644 --- a/docs/source/user_manual/plots.rst +++ b/docs/source/user_manual/plots.rst @@ -112,7 +112,7 @@ origin corner of the plot where the origin is located when looking at data in the first quadrant (positive x and y). -**styles +\*\*styles Keyword arguments that are passed directly through to the plot renderer, most commonly used to set things like colors, line styles, marker types, and so on. From d2f251e130ff7f86f36650d4105a57a8ec4a3eb3 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 16:04:29 -0500 Subject: [PATCH 21/68] DOC: Link tutorials from User Guide --- docs/source/user_manual/chaco_tutorial.rst | 1 + docs/source/user_manual/index.rst | 1 + docs/source/user_manual/tutorial_hyetograph.rst | 1 + docs/source/user_manual/tutorial_ipython.rst | 1 + docs/source/user_manual/tutorial_van_der_waal.rst | 1 + docs/source/user_manual/tutorials_and_examples.rst | 4 ++-- 6 files changed, 7 insertions(+), 2 deletions(-) diff --git a/docs/source/user_manual/chaco_tutorial.rst b/docs/source/user_manual/chaco_tutorial.rst index d004a5e8c..a274e49b3 100644 --- a/docs/source/user_manual/chaco_tutorial.rst +++ b/docs/source/user_manual/chaco_tutorial.rst @@ -1,3 +1,4 @@ +:orphan: .. highlight:: python :linenothreshold: 10 diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index 957e4429d..a75358f9f 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -31,6 +31,7 @@ of the Chaco API, refer to the Chaco API documentation. plot_types.rst basic_elements/overlays.rst common_patterns.rst + tutorials_and_examples.rst how_do_i.rst faq.rst annotated_examples.rst diff --git a/docs/source/user_manual/tutorial_hyetograph.rst b/docs/source/user_manual/tutorial_hyetograph.rst index 89b238efe..b357e2064 100644 --- a/docs/source/user_manual/tutorial_hyetograph.rst +++ b/docs/source/user_manual/tutorial_hyetograph.rst @@ -1,3 +1,4 @@ +:orphan: .. _tutorial_hyetograph: diff --git a/docs/source/user_manual/tutorial_ipython.rst b/docs/source/user_manual/tutorial_ipython.rst index 040f4f79f..3e1b58bec 100644 --- a/docs/source/user_manual/tutorial_ipython.rst +++ b/docs/source/user_manual/tutorial_ipython.rst @@ -1,3 +1,4 @@ +:orphan: .. _tutorial_ipython: diff --git a/docs/source/user_manual/tutorial_van_der_waal.rst b/docs/source/user_manual/tutorial_van_der_waal.rst index 8912e4752..dbf8bbbe1 100644 --- a/docs/source/user_manual/tutorial_van_der_waal.rst +++ b/docs/source/user_manual/tutorial_van_der_waal.rst @@ -1,3 +1,4 @@ +:orphan: .. _tutorial_van_der_waal: diff --git a/docs/source/user_manual/tutorials_and_examples.rst b/docs/source/user_manual/tutorials_and_examples.rst index 38ae93deb..25f601c14 100644 --- a/docs/source/user_manual/tutorials_and_examples.rst +++ b/docs/source/user_manual/tutorials_and_examples.rst @@ -1,8 +1,8 @@ .. _tutorials: -Tutorials, webinars, and examples -================================= +Tutorials, and examples +======================= Tutorials --------- From 552b0fd46c2e05518925360c974afa05815f468d Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 16:23:28 -0500 Subject: [PATCH 22/68] DOC: Fix layout of modules_and_classes --- docs/source/modules_and_classes.rst | 235 ++++++++++++++-------------- 1 file changed, 117 insertions(+), 118 deletions(-) diff --git a/docs/source/modules_and_classes.rst b/docs/source/modules_and_classes.rst index f75285ab9..58dc4ba33 100644 --- a/docs/source/modules_and_classes.rst +++ b/docs/source/modules_and_classes.rst @@ -26,7 +26,7 @@ even when you have subclassed Chaco PlotComponent. If you subclass PlotComponent, you need to implement :meth:`do_layout`, if you want to size the component correctly. - + Data Objects ----------------------------------------------------------------------------- @@ -37,16 +37,16 @@ A data source is a wrapper object for the actual data that it will be handling. It provides methods for retrieving data, estimating a size of the dataset, indications about the dimensionality of the data, a place for metadata (such as selections and annotations), and events that fire when the data gets -changed. There are two primary reasons for a data source class: +changed. There are two primary reasons for a data source class: * It provides a way for different plotting objects to reference the same data. -* It defines the interface for embedding Chaco into an existing application. - In most cases, the standard ArrayDataSource will suffice. +* It defines the interface for embedding Chaco into an existing application. + In most cases, the standard ArrayDataSource will suffice. - *Interface:* :class:`AbstractDataSource` +*Interface:* :class:`AbstractDataSource` - *Subclasses:* :class:`ArrayDataSource`, :class:`MultiArrayDataSource`, - :class:`PointDataSource`, :class:`GridDataSource`, :class:`ImageData` +*Subclasses:* :class:`ArrayDataSource`, :class:`MultiArrayDataSource`, +:class:`PointDataSource`, :class:`GridDataSource`, :class:`ImageData` .. rubric:: Data Range @@ -57,41 +57,40 @@ One of the important aspects of data ranges is that their bounds can be set to datasources. (Each data source can be associated with multiple ranges, and each data range can be associated with multiple data sources.) - *Interface*: :class:`AbstractDataRange` +*Interface*: :class:`AbstractDataRange` + +*Subclasses*: :class:`BaseDataRange`, :class:`DataRange1D`, :class:`DataRange2D` - *Subclasses*: :class:`BaseDataRange`, :class:`DataRange1D`, - :class:`DataRange2D` - .. rubric:: Data Source A data source is an object that supplies data to Chaco. For the most part, a data source looks like an array of values, with an optional mask and metadata. - *Interface*: :class:AbstractDataSource` - - *Subclasses*: :class:`ArrayDataSource`, :class:`DataContextDataSource`, - :class:`GridDataSource`, :class:`ImageData`, :class:`MultiArrayDataSource`, - :class:`PointDataSource` +*Interface*: :class:`AbstractDataSource` -The :attr:`metadata` trait attribute is a dictionary where you can stick +*Subclasses*: :class:`ArrayDataSource`, :class:`DataContextDataSource`, +:class:`GridDataSource`, :class:`ImageData`, :class:`MultiArrayDataSource`, +:class:`PointDataSource` + +The :attr:`metadata` trait attribute is a dictionary where you can stick stuff for other tools to find, without inserting it in the actual data. Events that are fired on data sources are: - * :attr:`data_changed` - * :attr:`bounds_changed` - * :attr:`metadata_changed` - - +* :attr:`data_changed` +* :attr:`bounds_changed` +* :attr:`metadata_changed` + + .. rubric:: Mapper Mappers perform the job of mapping a data space region to screen space, and -vice versa. Bounds on mappers are set by data range objects. +vice versa. Bounds on mappers are set by data range objects. - *Interface*: :class:`AbstractMapper` +*Interface*: :class:`AbstractMapper` - *Subclasses*: :class:`Base1DMapper`, :class:`LinearMapper`, - :class:`LogMapper`, :class:`GridMapper`, :class:`PolarMapper` +*Subclasses*: :class:`Base1DMapper`, :class:`LinearMapper`, :class:`LogMapper`, +:class:`GridMapper`, :class:`PolarMapper` Containers @@ -105,62 +104,63 @@ dispatch. It is very similar to sizers or layout grids in GUI toolkits like WX. Containers are subclasses of PlotComponent, thus allowing them to be nested. :class:`BasePlotContainer` implements the logic to correctly render and dispatch events to sub-components, while its subclasses implement the -different layout calculations. +different layout calculations. A container gets the preferred size from its components, and tries to allocate space for them. Non-resizeable components get their required size; whatever is left over is divided among the resizeable components. -Chaco currently has three types of containers, +Chaco currently has three types of containers, described in the following sections. - *Interface*: :class:`BasePlotContainer` +*Interface*: :class:`BasePlotContainer` - *Subclasses*: :class:`OverlayPlotContainer`, :class:`HPlotContainer`, - :class:`VPlotContainer`, :class:`GridPlotContainer` +*Subclasses*: :class:`OverlayPlotContainer`, :class:`HPlotContainer`, +:class:`VPlotContainer`, :class:`GridPlotContainer` -The listed subclasses are defined in the module +The listed subclasses are defined in the module :mod:`chaco.plot_containers`. Renderers ----------------------------------------------------------------------------- -Plot renderers are the classes that actually draw a type of plot. - - *Interface*: :class:`AbstractPlotRenderer` - *Subclasses*: - - * :class:`BarPlot` - * :class:`Base2DPlot` - - * :class:`ContourLinePlot` - * :class:`ContourPolyPlot` - * :class:`ImagePlot`: displays an image file, or color-maps scalar - data to make an image - * :class:`CMapImagePlot` - - * :class:`BaseXYPlot`: This class is often emulated by writers of other - plot renderers, but renderers don't *need* to be structured this way. - By convention, many have a :meth:`hittest` method. They *do* need - to implement :meth:`map_screen`, :meth:`map_data`, and :meth:`map_index` - from :class:`AbstractPlotRenderer`. - - * :class:`LinePlot` - - * :class:`ErrorBarPlot` - - * :class:`PolygonPlot` - - * :class:`FilledLinePlot` - - * :class:`ScatterPlot` - - * :class:`ColormappedScatterPlot` - - * :class:`ColorBar` - * :class:`PolarLineRenderer`: NOTE: doesn't play well with others - +Plot renderers are the classes that actually draw a type of plot. + +*Interface*: :class:`AbstractPlotRenderer` + +*Subclasses*: + +* :class:`BarPlot` +* :class:`Base2DPlot` + + * :class:`ContourLinePlot` + * :class:`ContourPolyPlot` + * :class:`ImagePlot`: displays an image file, or color-maps scalar + data to make an image + * :class:`CMapImagePlot` + +* :class:`BaseXYPlot`: This class is often emulated by writers of other + plot renderers, but renderers don't *need* to be structured this way. + By convention, many have a :meth:`hittest` method. They *do* need + to implement :meth:`map_screen`, :meth:`map_data`, and :meth:`map_index` + from :class:`AbstractPlotRenderer`. + + * :class:`LinePlot` + + * :class:`ErrorBarPlot` + + * :class:`PolygonPlot` + + * :class:`FilledLinePlot` + + * :class:`ScatterPlot` + + * :class:`ColormappedScatterPlot` + + * :class:`ColorBar` + * :class:`PolarLineRenderer`: NOTE: doesn't play well with others + You can use these classes to compose more interesting plots. The module :mod:`chaco.plot_factory` contains various convenience @@ -170,7 +170,7 @@ The :class:`chaco.plot.Plot` class (called "capital P Plot" when speaking) represents what the user usually thinks of as a "plot": a set of data, renderers, and axes in a single screen region. It is a subclass of :class:`DataView`. - + Tools ----------------------------------------------------------------------------- @@ -181,59 +181,58 @@ All tools subclass from Enable's :class:`BaseTool`, which is in turn an Enable that. Some tool subclasses exist in both Enable and Chaco, because they were created -first in Chaco, and then moved into Enable. - - *Interface*: :class:`BaseTool` - *Subclasses*: - - * :class:`BroadcasterTool`: Keeps a list of other tools, and broadcasts - events it receives to all those tools. - * :class:`DataPrinter`: Prints the data-space position of the point - under the cursor. - * :class:`enable.tools.api.DragTool`: Enable base class - for tools that do dragging. - - * :class:`MoveTool` - * :class:`ResizeTool` - * :class:`ViewportPanTool` - - * :class:`chaco.tools.api.DragTool`: Chaco base class - for tools that do dragging. - - * :class:`BaseCursorTool` - - * :class:`CursorTool1D` - * :class:`CursorTool2D` - - * :class:`DataLabelTool` - * :class:`DragZoom` - * :class:`LegendTool` - * :class:`MoveTool` - - * :class:`DrawPointsTool` - * :class:`HighlightTool` - * :class:`HoverTool` - * :class:`ImageInspectorTool` - * :class:`LineInspector` - * :class:`PanTool` - - * :class:`TrackingPanTool` - - * :class:`PointMarker` - * :class:`SaveTool` - * :class:`SelectTool` - - * :class:`ScatterInspector` - * :class:`SelectableLegend` - - * :class:`enable.tools.api.TraitsTool` - * :class:`chaco.tools.api.TraitsTool` - - +first in Chaco, and then moved into Enable. + +*Interface*: :class:`BaseTool` + +*Subclasses*: + +* :class:`BroadcasterTool`: Keeps a list of other tools, and broadcasts + events it receives to all those tools. +* :class:`DataPrinter`: Prints the data-space position of the point + under the cursor. +* :class:`enable.tools.api.DragTool`: Enable base class + for tools that do dragging. + + * :class:`MoveTool` + * :class:`ResizeTool` + * :class:`ViewportPanTool` + +* :class:`chaco.tools.api.DragTool`: Chaco base class + for tools that do dragging. + + * :class:`BaseCursorTool` + + * :class:`CursorTool1D` + * :class:`CursorTool2D` + + * :class:`DataLabelTool` + * :class:`DragZoom` + * :class:`LegendTool` + * :class:`MoveTool` + +* :class:`DrawPointsTool` +* :class:`HighlightTool` +* :class:`HoverTool` +* :class:`ImageInspectorTool` +* :class:`LineInspector` +* :class:`PanTool` + + * :class:`TrackingPanTool` + +* :class:`PointMarker` +* :class:`SaveTool` +* :class:`SelectTool` + + * :class:`ScatterInspector` + * :class:`SelectableLegend` + +* :class:`enable.tools.api.TraitsTool` +* :class:`chaco.tools.api.TraitsTool` DragTool is a base class for tools that do dragging. -Other tools do things like panning, moving, highlighting, line segments, range selection, drag zoom, move data labels, scatter inspection, Traits UI. +Other tools do things like panning, moving, highlighting, line segments, range selection, drag zoom, move data labels, scatter inspection, Traits UI. Overlays ----------------------------------------------------------------------------- From 90140ddd2ba6b73a7400478100d00fb7951d7d40 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 16:27:52 -0500 Subject: [PATCH 23/68] DOC: Move programmers_reference documents into user guide --- docs/source/programmers_reference.rst | 21 ------------------- .../architecture_overview.rst | 0 docs/source/user_manual/index.rst | 3 +++ .../{ => user_manual}/modules_and_classes.rst | 0 4 files changed, 3 insertions(+), 21 deletions(-) delete mode 100644 docs/source/programmers_reference.rst rename docs/source/{ => user_manual}/architecture_overview.rst (100%) rename docs/source/{ => user_manual}/modules_and_classes.rst (100%) diff --git a/docs/source/programmers_reference.rst b/docs/source/programmers_reference.rst deleted file mode 100644 index aa78bf5bc..000000000 --- a/docs/source/programmers_reference.rst +++ /dev/null @@ -1,21 +0,0 @@ - -.. _programmers_reference: - -Programmer's Reference -====================== - -.. toctree:: - :maxdepth: 2 - - architecture_overview.rst - modules_and_classes.rst - api/data_sources.rst - api/data_ranges.rst - api/mappers.rst - api/containers.rst - api/visual_components.rst - api/renderers.rst - api/plot_factories.rst - api/axis.rst - api/tools.rst - \ No newline at end of file diff --git a/docs/source/architecture_overview.rst b/docs/source/user_manual/architecture_overview.rst similarity index 100% rename from docs/source/architecture_overview.rst rename to docs/source/user_manual/architecture_overview.rst diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index a75358f9f..fc988ceee 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -19,6 +19,9 @@ of the Chaco API, refer to the Chaco API documentation. :maxdepth: 2 installation.rst + introduction.rst + architecture_overview + modules_and_classes plots.rst containers.rst diff --git a/docs/source/modules_and_classes.rst b/docs/source/user_manual/modules_and_classes.rst similarity index 100% rename from docs/source/modules_and_classes.rst rename to docs/source/user_manual/modules_and_classes.rst From c8cdd0dd7174a9675fd74d8e5d612c9a99857bdb Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 16:43:57 -0500 Subject: [PATCH 24/68] DOC: Clean up quickstart for formatting and links --- docs/source/quickstart.rst | 69 ++++++++++----------------- examples/demo/depth.py | 4 ++ examples/demo/domain_limits.py | 5 ++ examples/demo/multi_line_plot.py | 4 ++ examples/demo/multi_line_plot_demo.py | 13 ++--- examples/demo/status_overlay.py | 4 +- examples/demo/vtk_example.py | 3 ++ 7 files changed, 51 insertions(+), 51 deletions(-) diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 80916bfda..cef2d97de 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -23,40 +23,20 @@ you may or may not have the examples already. Location -------- -1. If you installed Chaco as part of Canopy, the location of the examples depends - on your platform: - - * On Windows, they are in the Examples\\ subdirectory of your installation - location. This is typically - :file:`C:\\Users\\\\AppData\\Local\\Enthought\\Canopy\\User\\Examples\\Chaco-`. - These examples can be browsed from the start menu, by clicking - :menuselection:`Start --> Applications --> Enthought Canopy --> Example Browser`. - - * On Linux, they are in the - :file:`Enthought/Canopy_XXbit/User/Examples/Chaco-` - subdirectory of your installation location. - - * On Mac OS X, they are in the - :file:`/Library/Enthought/Canopy_XXbit/User/Examples/chaco-` - directory. - -2. If you downloaded and installed Chaco from source (from GitHub or via the - PyPI tar.gz file), the examples are located in the :file:`examples/` - subdirectory inside the root of the Chaco source tree, next to :file:`docs/` - and the :file:`chaco/` directories. - -3. If you don't know how Chaco was installed, you can download the latest - versions of examples individually from github: - - https://github.com/enthought/chaco/tree/master/examples - -Chaco examples can be found in the :file:`examples/demo/` and -:file:`examples/tutorials/` directories. Some are classified by themes and +The examples are located in the :file:`examples/` subdirectory inside the root +of the Chaco source tree, next to :file:`docs/` and the :file:`chaco/` +directories. You can download the source code available on +`Github `_ or download a source +distribution from PyPi. If you don't want a local copy of the Chaco codebase, +you can browse the +`examples on GitHub `_. + +In the :file:`examples/demo/` directory, examples are classified by themes and located in separate directories. Almost all of the Chaco examples are standalone files that can be run individually. We will first show how to execute them from the command line, and then we will show how to run Chaco in an interactive way from IPython. This "shell" mode will be more familiar to -Matplotlib or Matlab users. +Matplotlib or MATLAB users. .. note:: Some of these examples can be visualized in our @@ -66,9 +46,9 @@ Matplotlib or Matlab users. First plots from the command line --------------------------------- -From the :file:`examples/demo` directory, run the ``simple_line`` example: +From the :file:`examples/demo` directory, run the ``simple_line`` example:: - :command:`python simple_line.py` + python simple_line.py This opens a plot of several Bessel functions with a legend. @@ -133,9 +113,9 @@ command-line plotting like Matlab or Matplotlib. The examples in the particularly amenable to exploration with IPython. The first example we'll look at is the :file:`lines.py` example. First, we'll -run it using the standard Python interpreter: +run it using the standard Python interpreter:: - :command:`python lines.py` + python lines.py This shows two overlapping line plots. @@ -144,9 +124,9 @@ This shows two overlapping line plots. You can interact with this plot just as in the previous section. Now close the plot, and start IPython with the ``--gui=qt`` [#guiqt]_ or -``--gui=wx`` option: +``--gui=wx`` option:: - :command:`ipython --gui=qt` + ipython --gui=qt This tells IPython to start a Qt or Wx mainloop in a background thread. Now run the previous example again:: @@ -189,9 +169,10 @@ The previous section showed how Chaco can be used interactively similarly to `Matlab` or Matplotlib's `pyplot` package. Now, let's create, from scratch, the simplest possible Chaco plot which is -embedded inside a `Traits `_ application. This will require more work but will -represent the basis for a potential large-scale, custom and powerful rich -client application. this is really what Chaco has been written for. +embedded inside a `Traits `_ application. +This will require more work but will represent the basis for a potential +large-scale, custom and powerful rich client application. this is really what +Chaco has been written for. First, some imports to bring in necessary components:: @@ -203,11 +184,11 @@ First, some imports to bring in necessary components:: The imports from :mod:`chaco` and :mod:`enable` support the creation of the plot. The imports from :mod:`traits` bring in components to embed the plot -inside a Traits application. (Refer to the `Traits documentation -`_ for more details about building an -interactive application using Traits.) Now let's create a Traits class with a -view that contains only one element: a Chaco plot inside a slightly customized -window:: +inside a Traits application. (Refer to the +`Traits documentation `_ for more details +about building an interactive application using Traits.) Now let's create a +Traits class with a view that contains only one element: a Chaco plot inside a +slightly customized window:: class MyPlot(HasTraits): plot = Instance(Plot) diff --git a/examples/demo/depth.py b/examples/demo/depth.py index 92bbca62e..771522eb4 100644 --- a/examples/demo/depth.py +++ b/examples/demo/depth.py @@ -1,3 +1,7 @@ +""" +Plot where depth is the index such that the plot is vertical and the origin is +the upper left +""" import numpy from chaco.api import ToolbarPlot, ArrayPlotData from chaco.tools.api import LineInspector diff --git a/examples/demo/domain_limits.py b/examples/demo/domain_limits.py index 59efa48ca..17fd3e0a4 100644 --- a/examples/demo/domain_limits.py +++ b/examples/demo/domain_limits.py @@ -1,3 +1,8 @@ +""" +Domain Limits +============= +""" + import numpy from chaco.plot import Plot, ArrayPlotData diff --git a/examples/demo/multi_line_plot.py b/examples/demo/multi_line_plot.py index 3a267c69d..dc5a2d8c0 100644 --- a/examples/demo/multi_line_plot.py +++ b/examples/demo/multi_line_plot.py @@ -1,3 +1,7 @@ +""" Displays a plot with a few buttons to control which overlay + to display +""" + import numpy as np from chaco.api import LinearMapper, Plot, ArrayDataSource, DataRange1D diff --git a/examples/demo/multi_line_plot_demo.py b/examples/demo/multi_line_plot_demo.py index b4eed6952..848b9c415 100644 --- a/examples/demo/multi_line_plot_demo.py +++ b/examples/demo/multi_line_plot_demo.py @@ -1,3 +1,10 @@ +""" +Demonstrates the MultiLinePlot. + +This demo assumes that 'model', an instance of DataModel containing the 2D +data to be plotted, will be given to the constructor, and will not change +later. +""" import numpy as np from traits.api import Instance, HasTraits, Range, Array @@ -24,12 +31,6 @@ class DataModel(HasTraits): class MultiLinePlotDemo(HasTraits): - """Demonstrates the MultiLinePlot. - - This demo assumes that 'model', an instance of DataModel containing the 2D - data to be plotted, will be given to the constructor, and will not change - later. - """ model = Instance(DataModel) diff --git a/examples/demo/status_overlay.py b/examples/demo/status_overlay.py index f4bbd3c26..8e2527471 100644 --- a/examples/demo/status_overlay.py +++ b/examples/demo/status_overlay.py @@ -1,4 +1,6 @@ - +""" +Displays a plot with a few buttons to control which overlay to display +""" import numpy from chaco.api import Plot, ArrayPlotData diff --git a/examples/demo/vtk_example.py b/examples/demo/vtk_example.py index b82c76ed5..068403386 100644 --- a/examples/demo/vtk_example.py +++ b/examples/demo/vtk_example.py @@ -1,3 +1,6 @@ +""" +VTK Example +""" from numpy import linspace from scipy.special import jn From 763d6351cbefd192d4012bdb30c533697fd22043 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 16:53:33 -0500 Subject: [PATCH 25/68] DOC: Use proper TOC for How do I --- docs/source/user_manual/how_do_i.rst | 30 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/docs/source/user_manual/how_do_i.rst b/docs/source/user_manual/how_do_i.rst index 397478dba..6639be9d5 100644 --- a/docs/source/user_manual/how_do_i.rst +++ b/docs/source/user_manual/how_do_i.rst @@ -7,13 +7,14 @@ How Do I...? .. note:: This section is currently under active development. + +.. contents:: Basics ====== -*How do I...* - -* render data to an image file? +Render data to an image file? +----------------------------- :: @@ -24,7 +25,8 @@ Basics gc.render_component(plot) gc.save(filename) -* integrate a Chaco plot into my WX app? +Integrate a Chaco plot into my WX app? +-------------------------------------- :: @@ -72,7 +74,9 @@ Note that this will require for the ETS_TOOLKIT environment variable to be set to 'wx'. * integrate a Chaco plot into my QT app? -* integrate a Chaco plot into my Traits UI? + +Integrate a Chaco plot into my Traits UI? +----------------------------------------- :: @@ -102,7 +106,8 @@ be set to 'wx'. my_plot.configure_traits() -* make an application to render many streams of data? +Make an application to render many streams of data? +--------------------------------------------------- :: @@ -115,14 +120,16 @@ be set to 'wx'. plot_data.set_data(series_name, data_series) plot.plot(('index', series_name)) -* make a plot the right size? +Make a plot the right size? +--------------------------- :: def resize_plot(plot, width, height): plot.outer_bounds = [width, height] -* copy a plot the the clipboard? +Copy a plot the the clipboard? +------------------------------ :: @@ -157,7 +164,9 @@ Layout and Rendering *How do I...* * put multiple plots in a single window? -* change the background color? + +Change the background color? +---------------------------- :: @@ -170,7 +179,8 @@ Layout and Rendering def change_bgcolor(plot): plot.bgcolor = 'black' -* turn off borders? +Turn off borders? +----------------- :: From 7afaef809eeed43def0f65632c7ebbe8c2fe0b93 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 16:58:54 -0500 Subject: [PATCH 26/68] DOC: Fix indentation in quickstart --- docs/source/quickstart.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index cef2d97de..b1a056ef2 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -1,3 +1,6 @@ +.. _quickstart: + + ########## Quickstart ########## @@ -52,7 +55,7 @@ From the :file:`examples/demo` directory, run the ``simple_line`` example:: This opens a plot of several Bessel functions with a legend. - .. image:: images/simple_line.png +.. image:: images/simple_line.png You can interact with the plot in several ways: From 0a41feee78f1905fc50bb06dbd31c78dbc2c321f Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 17:17:38 -0500 Subject: [PATCH 27/68] DOC: Move architecture_overview to dev reference Move the architecture_overview doc to developer_reference, and move some of the contents into the introduction document. --- .../architecture_overview.rst | 57 +++++-------------- docs/source/developer_reference/index.rst | 1 + docs/source/user_manual/index.rst | 2 +- docs/source/user_manual/introduction.rst | 30 +++++++--- 4 files changed, 38 insertions(+), 52 deletions(-) rename docs/source/{user_manual => developer_reference}/architecture_overview.rst (87%) diff --git a/docs/source/user_manual/architecture_overview.rst b/docs/source/developer_reference/architecture_overview.rst similarity index 87% rename from docs/source/user_manual/architecture_overview.rst rename to docs/source/developer_reference/architecture_overview.rst index 391104e10..17d0c6c45 100644 --- a/docs/source/user_manual/architecture_overview.rst +++ b/docs/source/developer_reference/architecture_overview.rst @@ -1,3 +1,6 @@ +.. _architecture: + + ********************* Architecture Overview ********************* @@ -8,43 +11,6 @@ Architecture Overview .. contents:: - - -Core Ideas -========== - -The Chaco toolkit is defined by a few core architectural ideas: - -* **Plots are compositions of visual components** - - Everything you see in a plot is some sort of graphical widget, - with position, shape, and appearance attributes, and with an - opportunity to respond to events. - -* **Separation between data and screen space** - - Although everything in a plot eventually ends up rendering into a common - visual area, there are aspects of the plot which are intrinsically - screen-space, and some which are fundamentally data-space. Preserving - the distinction between these two domains allows us to think about - visualizations in a structured way. - -* **Modular design and extensible classes** - - Chaco is meant to be used for writing tools and applications, and code - reuse and good class design are important. We use the math behind the - data and visualizations to give us architectural direction and conceptual - modularity. The Traits framework allows us to use events to couple - disjoint components at another level of modularity. - - Also, rather than building super-flexible core objects with myriad - configuration attributes, Chaco's classes are written with subclassing in - mind. While they are certainly configurable, the classes themselves are - written in a modular way so that subclasses can easily customize - particular aspects of a visual component's appearance or a tool's - behavior. - - .. _chaco_enable_kiva: The Relationship Between Chaco, Enable, and Kiva @@ -182,6 +148,18 @@ Chaco classes, and illustrates some sample usages. For a more detailed list of the class hierarchy, please see :ref:`modules_and_classes`. +Chaco is meant to be used for writing tools and applications, and code reuse +and good class design are important. We use the math behind the data and +visualizations to give us architectural direction and conceptual modularity. +The Traits framework allows us to use events to couple disjoint components at +another level of modularity. + +Also, rather than building super-flexible core objects with myriad +configuration attributes, Chaco's classes are written with subclassing in mind. +While they are certainly configurable, the classes themselves are written in a +modular way so that subclasses can easily customize particular aspects of a +visual component's appearance or a tool's behavior. + At the highest level, Chaco consists of: * Visual components that render to screen or an output device @@ -224,8 +202,3 @@ vertical grids. These other visuals are embodied as separate, distinct components: axes are drawn by the :class:`PlotAxis` component, and grids are drawn by the :class:`PlotGrid` component. Both of these overlays require a mapper in order to know where on the screen they should draw. - -.. So, the pipeline looks like: - - - diff --git a/docs/source/developer_reference/index.rst b/docs/source/developer_reference/index.rst index d42576aab..ad0e14595 100644 --- a/docs/source/developer_reference/index.rst +++ b/docs/source/developer_reference/index.rst @@ -15,4 +15,5 @@ to use, refer to the Chaco API documentation. :maxdepth: 2 fundamentals.rst + architecture_overview diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index fc988ceee..db79ded47 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -19,8 +19,8 @@ of the Chaco API, refer to the Chaco API documentation. :maxdepth: 2 installation.rst + quickstart introduction.rst - architecture_overview modules_and_classes plots.rst containers.rst diff --git a/docs/source/user_manual/introduction.rst b/docs/source/user_manual/introduction.rst index a7c436bda..8e2208db1 100644 --- a/docs/source/user_manual/introduction.rst +++ b/docs/source/user_manual/introduction.rst @@ -46,9 +46,9 @@ tool that will be familiar to users of matplotlib. .. _basic_elements: -============== -Basic elements -============== +========== +Core Ideas +========== To venture deeper in Chaco's architecture it is useful to understand a few basic ideas on which Chaco is based: @@ -81,6 +81,20 @@ basic ideas on which Chaco is based: interactive tools that add graphical elements to a plot without having to modify the drawing logic. +* **Modular design and extensible classes** + + Chaco is meant to be used for writing tools and applications, and code + reuse and good class design are important. We use the math behind the + data and visualizations to give us architectural direction and conceptual + modularity. The Traits framework allows us to use events to couple + disjoint components at another level of modularity. + + Also, rather than building super-flexible core objects with myriad + configuration attributes, Chaco's classes are written with subclassing in + mind. While they are certainly configurable, the classes themselves are + written in a modular way so that subclasses can easily customize + particular aspects of a visual component's appearance or a tool's + behavior. These pages describe in detail the basic building blocks of Chaco plots, and the classes that implement them: @@ -96,11 +110,11 @@ Chaco plots, and the classes that implement them: basic_elements/overlays.rst -TODO: find out how the selection features are organized +.. comment: TODO: find out how the selection features are organized -TODO: to see how these elements collaborate to build an interactive plot, -give complete low-level example of line plot with simple tool and -describe the exchange of information +.. comment: TODO: to see how these elements collaborate to build an interactive + plot, give complete low-level example of line plot with simple tool and + describe the exchange of information Tools @@ -137,8 +151,6 @@ Low-level Chaco plotting Plots can be rendered in a traitsui, wx, or qt window - - .. _embedding: ===================== From 2d460d520e10e72f5c295e4e2b1b212526ab1af1 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 17:25:06 -0500 Subject: [PATCH 28/68] DOC: Fix RST in data_sources --- .../basic_elements/data_sources.rst | 142 +++++++----------- 1 file changed, 58 insertions(+), 84 deletions(-) diff --git a/docs/source/user_manual/basic_elements/data_sources.rst b/docs/source/user_manual/basic_elements/data_sources.rst index c2d07567f..a65eff552 100644 --- a/docs/source/user_manual/basic_elements/data_sources.rst +++ b/docs/source/user_manual/basic_elements/data_sources.rst @@ -34,60 +34,51 @@ The basic interface for data sources is defined in Here is a summary of the most important attributes and methods (see the docstrings of this class for more details): - :attr:`~chaco.abstract_data_source.AbstractDataSource.value_dimension` - - The dimensionality of the data value at each point. It is defined - as a :class:`DimensionTrait`, i.e., one of - "scalar", "point", "image", or "cube". For example, - a :class:`GridDataSource` represents data in a 2D array and thus its - :attr:`value_dimension` is "scalar". - - :attr:`~chaco.abstract_data_source.AbstractDataSource.index_dimension` - - The dimensionality of the data value at each point. It is defined - as a :class:`DimensionTrait`, i.e., one of - "scalar", "point", "image", or "cube". For example, - a :class:`GridDataSource` represents data in a 2D array and thus its - :attr:`index_dimension` is "image". - - :attr:`~chaco.abstract_data_source.AbstractDataSource.metadata` - - A dictionary that maps strings to arbitrary data. Usually, the mapped - data is a set of indices, as in the case of selections and annotations. - By default, :attr:`metadata` contains the keys *"selections"* (representing - indices that are currently selected by some tool) - and *"annotations"*, both initialized to an empty list. - - :attr:`~chaco.abstract_data_source.AbstractDataSource.persist_data` - - If True (default), the data that this data source refers to is serialized - when the data source is. - - :meth:`~chaco.abstract_data_source.AbstractDataSource.get_data()` - - Returns a data array containing the data referred to by the data source. - Treat the returned array as read-only. - - :meth:`~chaco.abstract_data_source.AbstractDataSource.is_masked()` - - Returns True if this data source's data uses a mask. In this case, - to retrieve the data, call ``get_data_mask()`` instead of ``get_data()``. - - :meth:`~chaco.abstract_data_source.AbstractDataSource.get_data_mask()` - - Returns the full, raw, source data array and a corresponding binary - mask array. Treat both arrays as read-only. - - :meth:`~chaco.abstract_data_source.AbstractDataSource.get_size()` - - Returns the size of the data. - - :meth:`~chaco.abstract_data_source.AbstractDataSource.get_bounds()` - - Returns a tuple (min, max) of the bounding values for the data source. - In the case of 2-D data, min and max are 2-D points that represent the - bounding corners of a rectangle enclosing the data set. - If data is the empty set, then the min and max vals are 0.0. +:attr:`~chaco.abstract_data_source.AbstractDataSource.value_dimension` + The dimensionality of the data value at each point. It is defined + as a :class:`DimensionTrait`, i.e., one of + "scalar", "point", "image", or "cube". For example, + a :class:`GridDataSource` represents data in a 2D array and thus its + :attr:`value_dimension` is "scalar". + +:attr:`~chaco.abstract_data_source.AbstractDataSource.index_dimension` + The dimensionality of the data value at each point. It is defined + as a :class:`DimensionTrait`, i.e., one of + "scalar", "point", "image", or "cube". For example, + a :class:`GridDataSource` represents data in a 2D array and thus its + :attr:`index_dimension` is "image". + +:attr:`~chaco.abstract_data_source.AbstractDataSource.metadata` + A dictionary that maps strings to arbitrary data. Usually, the mapped + data is a set of indices, as in the case of selections and annotations. + By default, :attr:`metadata` contains the keys *"selections"* (representing + indices that are currently selected by some tool) + and *"annotations"*, both initialized to an empty list. + +:attr:`~chaco.abstract_data_source.AbstractDataSource.persist_data` + If True (default), the data that this data source refers to is serialized + when the data source is. + +:meth:`~chaco.abstract_data_source.AbstractDataSource.get_data()` + Returns a data array containing the data referred to by the data source. + Treat the returned array as read-only. + +:meth:`~chaco.abstract_data_source.AbstractDataSource.is_masked()` + Returns True if this data source's data uses a mask. In this case, + to retrieve the data, call ``get_data_mask()`` instead of ``get_data()``. + +:meth:`~chaco.abstract_data_source.AbstractDataSource.get_data_mask()` + Returns the full, raw, source data array and a corresponding binary + mask array. Treat both arrays as read-only. + +:meth:`~chaco.abstract_data_source.AbstractDataSource.get_size()` + Returns the size of the data. + +:meth:`~chaco.abstract_data_source.AbstractDataSource.get_bounds()` + Returns a tuple (min, max) of the bounding values for the data source. + In the case of 2-D data, min and max are 2-D points that represent the + bounding corners of a rectangle enclosing the data set. + If data is the empty set, then the min and max vals are 0.0. Events ------ @@ -95,25 +86,22 @@ Events :class:`~chaco.abstract_data_source.AbstractDataSource` defines three events that can be used in Traits applications to react to changes in the data source: - :attr:`~chaco.abstract_data_source.AbstractDataSource.data_changed` +:attr:`~chaco.abstract_data_source.AbstractDataSource.data_changed` + Fired when the data values change. - Fired when the data values change. - - .. note:: - - The majority of concrete data sources do not fire this event when - the data values change. Rather, the event is usually fired when new - data or a new mask is assigned through setter methods (see - notes below). - - :attr:`~chaco.abstract_data_source.AbstractDataSource.bounds_changed` + .. note:: - Fired when the data bounds change. + The majority of concrete data sources do not fire this event when + the data values change. Rather, the event is usually fired when new + data or a new mask is assigned through setter methods (see + notes below). - :attr:`~chaco.abstract_data_source.AbstractDataSource.metadata_changed` +:attr:`~chaco.abstract_data_source.AbstractDataSource.bounds_changed` + Fired when the data bounds change. - Fired when the content of :attr:`metadata` changes (both the - :attr:`metadata` dictionary object or any of its items). +:attr:`~chaco.abstract_data_source.AbstractDataSource.metadata_changed` + Fired when the content of :attr:`metadata` changes (both the + :attr:`metadata` dictionary object or any of its items). List of Chaco data sources @@ -123,7 +111,6 @@ This is a list of all concrete implementations of data sources in Chaco: :class:`~chaco.array_data_source.ArrayDataSource` - A data source representing a single, continuous array of numerical data. This is the most common data source for Chaco plots. @@ -131,13 +118,11 @@ This is a list of all concrete implementations of data sources in Chaco: interface: :attr:`~chaco.abstract_data_source.ArrayDataSource.sort_order` - The sort order of the data, one of 'ascending', 'descending', or 'none'. If the underlying data is sorted, and this attribute is set appropriately, Chaco is able to use shortcuts and optimizations in many places. :attr:`~chaco.abstract_data_source.ArrayDataSource.reverse_map(pt)` - Returns the index of *pt* in the data source (optimized if :attr:`sort_order` is set). @@ -151,7 +136,6 @@ This is a list of all concrete implementations of data sources in Chaco: :class:`~chaco.image_data.ImageData` - Represents a 2D grid of image data. The underlying data array is 3D, where the third dimension is either @@ -177,18 +161,14 @@ This is a list of all concrete implementations of data sources in Chaco: Noteworthy methods of this class are: :attr:`~chaco.image_data.ImageData.fromfile(filename)` - Factory method that creates an :class:`ImageData` instance from an image file. *filename* can be either a file path or a file object. - :meth:`~chaco.image_data.ImageData.get_width`, - :meth:`~chaco.image_data.ImageData.get_height` - + :meth:`~chaco.image_data.ImageData.get_width`, :meth:`~chaco.image_data.ImageData.get_height` Return the width or the height of the image (takes the value of :attr:`transposed` into account). :meth:`~chaco.image_data.ImageData.get_array_bounds` - Return ((0, width), (0, height)). .. note:: @@ -204,7 +184,6 @@ This is a list of all concrete implementations of data sources in Chaco: :class:`~chaco.grid_data_source.GridDataSource` - Data source representing the coordinates of a 2D grid. It is used, for example, as a source for the index data in an :class:`ImagePlot`. @@ -212,7 +191,6 @@ This is a list of all concrete implementations of data sources in Chaco: It defines these attributes: :attr:`~chaco.abstract_data_source.GridDataSource.sort_order` - Similar to the :attr:`sort_order` attribute for the :class:`ArrayDataSource` class above, but this is a tuple with two elements, one per dimension. @@ -230,7 +208,6 @@ This is a list of all concrete implementations of data sources in Chaco: :class:`~chaco.multi_array_data_source.MultiArrayDataSource` - A data source representing a single, continuous array of multidimensional numerical data. @@ -261,7 +238,6 @@ This is a list of all concrete implementations of data sources in Chaco: :class:`~chaco.point_data_source.PointDataSource` - A data source representing a set of (X,Y) points. This is a subclass of :class:`ArrayDataSource`, and inherits its methods @@ -278,7 +254,6 @@ This is a list of all concrete implementations of data sources in Chaco: :class:`~chaco.function_data_source.FunctionDataSource` - A subclass of :class:`~chaco.array_data_source.ArrayDataSource` that sets the values of the underlying data array based on a function (defined in the callable attribute @@ -288,7 +263,6 @@ This is a list of all concrete implementations of data sources in Chaco: :class:`~chaco.function_data_source.FunctionImageData` - A subclass of :class:`~chaco.array_data_source.ImageData` that sets the values of the underlying data array based on a 2D function (defined in the callable attribute From 20ce8c5d4cec9253649ca5562ffb17c7e5d6064d Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 17:52:24 -0500 Subject: [PATCH 29/68] FIX: Fix circular import in transform_color_mapper The fix is to import ColorMapper directly from chaco.color_mapper --- chaco/transform_color_mapper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chaco/transform_color_mapper.py b/chaco/transform_color_mapper.py index 52acadff7..d547ed64e 100644 --- a/chaco/transform_color_mapper.py +++ b/chaco/transform_color_mapper.py @@ -1,6 +1,6 @@ from numpy import clip, isinf, ones_like, empty -from chaco.api import ColorMapper +from chaco.color_mapper import ColorMapper from traits.api import Trait, Callable, Tuple, Float, on_trait_change from .speedups import map_colors, map_colors_uint8 From 0fb7d048eb6624137e7f978ce769aa0997f8da5c Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 17:57:14 -0500 Subject: [PATCH 30/68] DOC:CLN: Remove mention of PolarMapper --- docs/source/user_manual/basic_elements/mappers.rst | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/docs/source/user_manual/basic_elements/mappers.rst b/docs/source/user_manual/basic_elements/mappers.rst index 891e9e506..a6c1ed6d1 100644 --- a/docs/source/user_manual/basic_elements/mappers.rst +++ b/docs/source/user_manual/basic_elements/mappers.rst @@ -122,16 +122,4 @@ List of Chaco data mappers :class:`~chaco.grid_mapper.GridMapper(x_type="linear", y_type="linear", range=None, **kwargs)` ``x_type`` and ``y_type`` can be either 'linear' or 'log', which will - create a corresponding :class:`LinearMapper` or :class:`LogMapper` classes. - - -:class:`~chaco.polar_mapper.PolarMapper` - - This class should map data polar coordinates to screen cartesian coordinates, - to use for example with a :class:`~chaco.polar_line_renderer.PolarLineRenderer`, - but at the moment it is a copy of :class:`~chaco.linear_mapper.LinearMapper`. - - .. warning:: - - The implementation of this mapper is under construction. - + create a corresponding :class:`~.LinearMapper` or :class:`~.LogMapper` classes. \ No newline at end of file From 3280b0b3a9d1a2df6b4e477975b3f18fe9b34828 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 17:58:09 -0500 Subject: [PATCH 31/68] DOC: Fix RST links for data sources --- docs/source/api/data_sources.rst | 12 +++++++++++- .../user_manual/basic_elements/data_sources.rst | 15 ++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/docs/source/api/data_sources.rst b/docs/source/api/data_sources.rst index edfb16c5f..a8383e9a2 100644 --- a/docs/source/api/data_sources.rst +++ b/docs/source/api/data_sources.rst @@ -4,7 +4,7 @@ Data Sources ------------ -.. currentmodule:: chaco.api +.. currentmodule:: chaco.abstract_data_source :class:`AbstractDataSource` =========================== @@ -12,30 +12,40 @@ Data Sources :members: :show-inheritance: +.. currentmodule:: chaco.array_data_source + :class:`ArrayDataSource` ======================== .. autoclass:: ArrayDataSource :members: :show-inheritance: +.. currentmodule:: chaco.multi_array_data_source + :class:`MultiArrayDataSource` ============================= .. autoclass:: MultiArrayDataSource :members: :show-inheritance: +.. currentmodule:: chaco.point_data_source + :class:`PointDataSource` ======================== .. autoclass:: PointDataSource :members: :show-inheritance: +.. currentmodule:: chaco.grid_data_source + :class:`GridDataSource` ======================= .. autoclass:: GridDataSource :members: :show-inheritance: +.. currentmodule:: chaco.image_data + :class:`ImageData` ================== .. autoclass:: ImageData diff --git a/docs/source/user_manual/basic_elements/data_sources.rst b/docs/source/user_manual/basic_elements/data_sources.rst index a65eff552..59f106506 100644 --- a/docs/source/user_manual/basic_elements/data_sources.rst +++ b/docs/source/user_manual/basic_elements/data_sources.rst @@ -161,8 +161,9 @@ This is a list of all concrete implementations of data sources in Chaco: Noteworthy methods of this class are: :attr:`~chaco.image_data.ImageData.fromfile(filename)` - Factory method that creates an :class:`ImageData` instance from an image - file. *filename* can be either a file path or a file object. + Factory method that creates an :class:`~chaco.image_data.ImageData` + instance from an image file. *filename* can be either a file path or a file + object. :meth:`~chaco.image_data.ImageData.get_width`, :meth:`~chaco.image_data.ImageData.get_height` Return the width or the height of the image (takes the value @@ -186,13 +187,13 @@ This is a list of all concrete implementations of data sources in Chaco: :class:`~chaco.grid_data_source.GridDataSource` Data source representing the coordinates of a 2D grid. It is used, for example, as a source for the index data in an - :class:`ImagePlot`. + :class:`~.ImagePlot`. It defines these attributes: :attr:`~chaco.abstract_data_source.GridDataSource.sort_order` Similar to the :attr:`sort_order` attribute for the - :class:`ArrayDataSource` class above, but this is a tuple + :class:`~.ArrayDataSource` class above, but this is a tuple with two elements, one per dimension. .. note:: @@ -216,13 +217,13 @@ This is a list of all concrete implementations of data sources in Chaco: or to represent multiple values for each index (as in :class:`~chaco.multi_line_plot.MultiLinePlot`). - As :class:`ArrayDataSource`, this data source defines a + As :class:`~.ArrayDataSource`, this data source defines a :attr:`~chaco.abstract_data_source.MultiArrayDataSource.sort_order` attribute for its index dimension. .. warning:: - In :class:`MultiArrayDataSource`, + In :class:`~.MultiArrayDataSource`, the :attr:`index_dimension` and :attr:`value_dimension` attributes are integers that define which dimension of the data array correspond to indices and which @@ -240,7 +241,7 @@ This is a list of all concrete implementations of data sources in Chaco: :class:`~chaco.point_data_source.PointDataSource` A data source representing a set of (X,Y) points. - This is a subclass of :class:`ArrayDataSource`, and inherits its methods + This is a subclass of :class:`~.ArrayDataSource`, and inherits its methods and attributes. The attribute :attr:`~chaco.point_data_source.PointDataSource.sort_index` defines whether the data is sorted along the X's or the Y's (as specified From ce22da3d6753d31486428535bf227d63ca337f6b Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 17:58:21 -0500 Subject: [PATCH 32/68] DOC: Fix RST links for mappers --- docs/source/api/mappers.rst | 19 +++- .../user_manual/basic_elements/mappers.rst | 93 ++++++++----------- 2 files changed, 54 insertions(+), 58 deletions(-) diff --git a/docs/source/api/mappers.rst b/docs/source/api/mappers.rst index 191493e47..c04780526 100644 --- a/docs/source/api/mappers.rst +++ b/docs/source/api/mappers.rst @@ -4,7 +4,7 @@ Mappers ------- -.. currentmodule:: chaco.api +.. currentmodule:: chaco.abstract_mapper :class:`AbstractMapper` ======================= @@ -12,45 +12,58 @@ Mappers :members: :show-inheritance: +.. currentmodule:: chaco.base_1d_mapper + :class:`Base1DMapper` ===================== .. autoclass:: Base1DMapper :members: :show-inheritance: +.. currentmodule:: chaco.linear_mapper + :class:`LinearMapper` ===================== .. autoclass:: LinearMapper :members: :show-inheritance: +.. currentmodule:: chaco.log_mapper + :class:`LogMapper` ================== .. autoclass:: LogMapper :members: :show-inheritance: +.. currentmodule:: chaco.grid_mapper + :class:`GridMapper` =================== .. autoclass:: GridMapper :members: :show-inheritance: +.. currentmodule:: chaco.color_mapper + :class:`ColorMapper` ==================== .. autoclass:: ColorMapper :members: :show-inheritance: +.. currentmodule:: chaco.color_mapper + :class:`ColorMapTemplate` ========================= .. autoclass:: ColorMapTemplate :members: :show-inheritance: +.. currentmodule:: chaco.transform_color_mapper + :class:`TransformColorMapper` ============================= .. autoclass:: TransformColorMapper :members: - :show-inheritance: - + :show-inheritance: \ No newline at end of file diff --git a/docs/source/user_manual/basic_elements/mappers.rst b/docs/source/user_manual/basic_elements/mappers.rst index a6c1ed6d1..c983ce8d4 100644 --- a/docs/source/user_manual/basic_elements/mappers.rst +++ b/docs/source/user_manual/basic_elements/mappers.rst @@ -15,45 +15,37 @@ The general interface for mappers is defined in :class:`~chaco.abstract_mapper.AbstractMapper` and defines only a few methods: - :attr:`~chaco.abstract_mapper.AbstractMapper.map_screen(data_value)`, - :attr:`~chaco.abstract_mapper.AbstractMapper.map_data(screen_value)` +:attr:`~chaco.abstract_mapper.AbstractMapper.map_screen(data_value)`, :attr:`~chaco.abstract_mapper.AbstractMapper.map_data(screen_value)` + Maps a vector of data coordinates to screen coordinates, and vice versa. - Maps a vector of data coordinates to screen coordinates, and vice versa. - - :attr:`~chaco.abstract_mapper.AbstractMapper.map_data_array(screen_value_array)` - - Maps an array of points in data coordinates to screen coordinates. - By default, this method just loops over the points, calling :attr:`map_data()` - on each one. For vectorizable mapping functions, this - implementation is overridden with a faster one. +:attr:`~chaco.abstract_mapper.AbstractMapper.map_data_array(screen_value_array)` + Maps an array of points in data coordinates to screen coordinates. + By default, this method just loops over the points, calling :attr:`map_data()` + on each one. For vectorizable mapping functions, this + implementation is overridden with a faster one. Mappers for 1D data have a slightly larger interface, defined in :class:`~chaco.base_1d_mapper.Base1DMapper`. These mappers rely on a :class:`~chaco.data_range_1d.DataRange1D` object to find the bounds on the data domain. - :attr:`~chaco.abstract_mapper.AbstractMapper.range` - - A :class:`~chaco.data_range_1d.DataRange1D` instance to define the - data-space bounds of the mapper. The mapper listens to the - :attr:`updated` event of the range and re-fires it as its - own :attr:`updated` event (see below). - - :attr:`~chaco.abstract_mapper.AbstractMapper.low_pos`, - :attr:`~chaco.abstract_mapper.AbstractMapper.high_pos`, - :attr:`~chaco.abstract_mapper.AbstractMapper.screen_bounds`, +:attr:`~chaco.abstract_mapper.AbstractMapper.range` + A :class:`~chaco.data_range_1d.DataRange1D` instance to define the + data-space bounds of the mapper. The mapper listens to the + :attr:`updated` event of the range and re-fires it as its + own :attr:`updated` event (see below). - The screen space position of the lower/upper bound of the data space. - :attr:`screen_bounds` is a convenience property to set/get the screen - bounds with a single attribute. +:attr:`~chaco.abstract_mapper.AbstractMapper.low_pos`, :attr:`~chaco.abstract_mapper.AbstractMapper.high_pos`, :attr:`~chaco.abstract_mapper.AbstractMapper.screen_bounds` + The screen space position of the lower/upper bound of the data space. + :attr:`screen_bounds` is a convenience property to set/get the screen + bounds with a single attribute. - :attr:`~chaco.abstract_mapper.AbstractMapper.stretch_data` - - When the screen bounds change (in response, for instance, to the - window resizing) one could either fit more data space on the screen, or - stretch the data space to the new bounds. - If :attr:`stretch_data` is True (default), the data is stretched; - if it is False, the mapper preserves the screen-to-data ratio. +:attr:`~chaco.abstract_mapper.AbstractMapper.stretch_data` + When the screen bounds change (in response, for instance, to the + window resizing) one could either fit more data space on the screen, or + stretch the data space to the new bounds. + If :attr:`stretch_data` is True (default), the data is stretched; + if it is False, the mapper preserves the screen-to-data ratio. Events @@ -75,12 +67,10 @@ List of Chaco data mappers -------------------------- :class:`~chaco.linear_mapper.LinearMapper` (subclass of :class:`~chaco.base_1d_mapper.Base1DMapper`) - This mapper transforms a 1D data space range linearly to a fixed 1D range in screen space. :class:`~chaco.log_mapper.LogMapper` (subclass of :class:`~chaco.base_1d_mapper.Base1DMapper`) - Maps a 1D data space range to a 1D range in screen space through a logarithmic transform. Data values smaller than or equal to 0.0 are @@ -88,28 +78,21 @@ List of Chaco data mappers (default is 1.0) before the logarithmic transformation. :class:`~chaco.grid_mapper.GridMapper` - Same as :class:`~chaco.linear_mapper.LinearMapper` for 2D ranges. This class - replaces the :class:`Base1DMapper` attributes with analogous ones: - - :attr:`~chaco.grid_mapper.GridMapper.range` - - A :class:`~chaco.data_range_2d.DataRange2D` instance to define the - data-space bounds of the mapper. - - :attr:`~chaco.grid_mapper.GridMapper.x_low_pos`, - :attr:`~chaco.grid_mapper.GridMapper.y_low_pos`, - :attr:`~chaco.grid_mapper.GridMapper.x_high_pos`, - :attr:`~chaco.grid_mapper.GridMapper.y_high_pos` - - Screen space positions for the lower and upper bounds of the x and - y axes. - - :attr:`~chaco.grid_mapper.GridMapper.screen_bounds` - - Convenience property to set/get the screen bounds with a single attribute. - The value of this attribute is a 4-element tuple - ``(x_low_pos, x_high_pos, y_low_pos, y_high_pos)``. + replaces the :class:`~.Base1DMapper` attributes with analogous ones: + + :attr:`~chaco.grid_mapper.GridMapper.range` + A :class:`~chaco.data_range_2d.DataRange2D` instance to define the + data-space bounds of the mapper. + + :attr:`~chaco.grid_mapper.GridMapper.x_low_pos`, :attr:`~chaco.grid_mapper.GridMapper.y_low_pos`, :attr:`~chaco.grid_mapper.GridMapper.x_high_pos`, :attr:`~chaco.grid_mapper.GridMapper.y_high_pos` + Screen space positions for the lower and upper bounds of the x and + y axes. + + :attr:`~chaco.grid_mapper.GridMapper.screen_bounds` + Convenience property to set/get the screen bounds with a single attribute. + The value of this attribute is a 4-element tuple + ``(x_low_pos, x_high_pos, y_low_pos, y_high_pos)``. :class:`~chaco.grid_mapper.GridMapper` uses two :class:`~chaco.base_1d_mapper.Base1DMapper` instances to define mappers for @@ -117,9 +100,9 @@ List of Chaco data mappers :attr:`_xmapper` and :attr:`_ymapper`). It thus possible to set them to be linear or logarithmic mappers. This is best made using the class constructor, which has - this signature: + this signature:: - :class:`~chaco.grid_mapper.GridMapper(x_type="linear", y_type="linear", range=None, **kwargs)` + GridMapper(x_type="linear", y_type="linear", range=None, **kwargs) ``x_type`` and ``y_type`` can be either 'linear' or 'log', which will create a corresponding :class:`~.LinearMapper` or :class:`~.LogMapper` classes. \ No newline at end of file From 672de1f7d67ca52afb8782065acffe1372b7a547 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sat, 13 Jul 2019 18:09:38 -0500 Subject: [PATCH 33/68] DOC: Fix RST links for data ranges --- docs/source/api/data_ranges.rst | 8 +- .../basic_elements/data_ranges.rst | 98 +++++++++---------- 2 files changed, 51 insertions(+), 55 deletions(-) diff --git a/docs/source/api/data_ranges.rst b/docs/source/api/data_ranges.rst index 8b1527a0b..ccb5eeb04 100644 --- a/docs/source/api/data_ranges.rst +++ b/docs/source/api/data_ranges.rst @@ -4,7 +4,7 @@ Data Ranges ----------- -.. currentmodule:: chaco.api +.. currentmodule:: chaco.abstract_data_range :class:`AbstractDataRange` ========================== @@ -12,18 +12,24 @@ Data Ranges :members: :show-inheritance: +.. currentmodule:: chaco.base_data_range + :class:`BaseDataRange` ====================== .. autoclass:: BaseDataRange :members: :show-inheritance: +.. currentmodule:: chaco.data_range_1d + :class:`DataRange1D` ==================== .. autoclass:: DataRange1D :members: :show-inheritance: +.. currentmodule:: chaco.data_range_2d + :class:`DataRange2D` ==================== .. autoclass:: DataRange2D diff --git a/docs/source/user_manual/basic_elements/data_ranges.rst b/docs/source/user_manual/basic_elements/data_ranges.rst index de433a8ef..0cfb18cad 100644 --- a/docs/source/user_manual/basic_elements/data_ranges.rst +++ b/docs/source/user_manual/basic_elements/data_ranges.rst @@ -25,70 +25,62 @@ and This is a summary of the most important attributes and methods (see the docstrings of this class for more details): -**Attributes** +Attributes +^^^^^^^^^^ - :attr:`~chaco.abstract_data_range.AbstractDataRange.sources` +:attr:`~chaco.abstract_data_range.AbstractDataRange.sources` + A list of data sources associated to the data range. Concrete implementations + of data range listen to the event + :attr:`~chaco.abstract_data_source.AbstractDataSource.data_changed` + and refresh their bounds as appropriate (e.g., when the bounds are + set to ``auto``). - A list of data sources associated to the data range. Concrete implementations - of data range listen to the event - :attr:`~chaco.abstract_data_source.AbstractDataSource.data_changed` - and refresh their bounds as appropriate (e.g., when the bounds are - set to ``auto``). +:attr:`~chaco.abstract_data_range.AbstractDataRange.low` + The actual value of the lower bounds of the range. The correct way + to set it is to use the :attr:`low_setting` attribute. - :attr:`~chaco.abstract_data_range.AbstractDataRange.low` +:attr:`~chaco.abstract_data_range.AbstractDataRange.high` + The actual value of the upper bounds of the range. The correct way + to set it is to use the :attr:`high_setting` attribute. - The actual value of the lower bounds of the range. The correct way - to set it is to use the :attr:`low_setting` attribute. +:attr:`~chaco.abstract_data_range.AbstractDataRange.low_setting` + Setting for the lower bound of the range. This can either be a valid + lower bound value, or ``auto`` (default), in which case the + lower bound is set automatically from the associated data sources. - :attr:`~chaco.abstract_data_range.AbstractDataRange.high` +:attr:`~chaco.abstract_data_range.AbstractDataRange.high_setting` + Setting for the upper bound of the range. This can either be a valid + upper bound value, or ``auto`` (default), in which case the + upper bound is set automatically from the associated data sources. - The actual value of the upper bounds of the range. The correct way - to set it is to use the :attr:`high_setting` attribute. - :attr:`~chaco.abstract_data_range.AbstractDataRange.low_setting` +Methods +^^^^^^^ - Setting for the lower bound of the range. This can either be a valid - lower bound value, or ``auto`` (default), in which case the - lower bound is set automatically from the associated data sources. +:meth:`~chaco.base_data_range.BaseDataRange.add` + Convenience method to associate one or more data sources to the range. + The method avoids adding the same data source twice. - :attr:`~chaco.abstract_data_range.AbstractDataRange.high_setting` +:meth:`~chaco.base_data_range.BaseDataRange.remove` + Convenience method to remove one or more data sources from the range. + If one of the data sources is not associated with the range, + it is ignored. - Setting for the upper bound of the range. This can either be a valid - upper bound value, or ``auto`` (default), in which case the - upper bound is set automatically from the associated data sources. +:meth:`~chaco.abstract_data_range.AbstractDataRange.clip_data` + Given an array of data values of the same dimensionality as the range, + return a list of data values that are inside the range. +:meth:`~chaco.abstract_data_range.AbstractDataRange.mask_data` + Given an array of data values of the same dimensionality as the range, + this method returns a mask array of the same length as data, filled + with 1s and 0s corresponding to whether the data value at that index + is inside or outside the range. -**Methods** - - :attr:`~chaco.base_data_range.BaseDataRange.add(*datasources)` - - Convenience method to associate one or more data sources to the range. - The method avoids adding the same data source twice. - - :attr:`~chaco.base_data_range.BaseDataRange.remove(*datasources)` - - Convenience method to remove one or more data sources from the range. - If one of the data sources is not associated with the range, - it is ignored. - - :attr:`~chaco.abstract_data_range.AbstractDataRange.clip_data(data)` - - Given an array of data values of the same dimensionality as the range, - return a list of data values that are inside the range. - - :attr:`~chaco.abstract_data_range.AbstractDataRange.mask_data(data)` - - Given an array of data values of the same dimensionality as the range, - this method returns a mask array of the same length as data, filled - with 1s and 0s corresponding to whether the data value at that index - is inside or outside the range. - - :attr:`~chaco.abstract_data_range.AbstractDataRange.bound_data(data)` - - Given an array of *monotonic* data values of the same dimensionality - as the range, - returns a tuple of indices (start, end) corresponding to the first and - last elements that fall within the range. +:meth:`~chaco.abstract_data_range.AbstractDataRange.bound_data` + Given an array of *monotonic* data values of the same dimensionality + as the range, + returns a tuple of indices (start, end) corresponding to the first and + last elements that fall within the range. Events @@ -106,7 +98,6 @@ There are two data range implementations in Chaco, one for 1D and one for 2D ranges: :class:`~chaco.data_range_1d.DataRange1D` - :class:`~chaco.data_range_1d.DataRange1D` represents a 1D data range. This subclass adds several more ways to control the bound of the range given the associated data sources. @@ -138,7 +129,6 @@ for 2D ranges: :class:`~chaco.data_range_2d.DataRange2D` - :class:`~chaco.data_range_2d.DataRange2D` represents a 2D data range. Internally, it is implemented using two :class:`~chaco.data_range_1d.DataRange1D` objects, From 32e715a305dc02f914e4b93f4d27da2f88a290c4 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:02:01 -0500 Subject: [PATCH 34/68] DOC: Fix RST links for plot types and renderers --- docs/source/api/renderers.rst | 52 ++- docs/source/user_manual/plot_types.rst | 458 ++++++++++++------------- 2 files changed, 272 insertions(+), 238 deletions(-) diff --git a/docs/source/api/renderers.rst b/docs/source/api/renderers.rst index b5ba1ca69..e9360019c 100644 --- a/docs/source/api/renderers.rst +++ b/docs/source/api/renderers.rst @@ -4,7 +4,7 @@ Renderers ---------- -.. currentmodule:: chaco.api +.. currentmodule:: chaco.barplot :class:`BarPlot` ================ @@ -12,144 +12,192 @@ Renderers :members: :show-inheritance: +.. currentmodule:: chaco.base_1d_plot + :class:`Base1DPlot` =================== .. autoclass:: Base1DPlot :members: :show-inheritance: +.. currentmodule:: chaco.base_2d_plot + :class:`Base2DPlot` =================== .. autoclass:: Base2DPlot :members: :show-inheritance: +.. currentmodule:: chaco.base_xy_plot + :class:`BaseXYPlot` =================== .. autoclass:: BaseXYPlot :members: :show-inheritance: +.. currentmodule:: chaco.scatterplot + :class:`ScatterPlot` ==================== .. autoclass:: ScatterPlot :members: :show-inheritance: +.. currentmodule:: chaco.image_plot + :class:`ImagePlot` ================== .. autoclass:: ImagePlot :members: :show-inheritance: +.. currentmodule:: chaco.cmap_image_plot + :class:`CMapImagePlot` ====================== .. autoclass:: CMapImagePlot :members: :show-inheritance: +.. currentmodule:: chaco.contour_line_plot + :class:`ContourLinePlot` ======================== .. autoclass:: ContourLinePlot :members: :show-inheritance: +.. currentmodule:: chaco.lineplot + :class:`LinePlot` ======================== .. autoclass:: LinePlot :members: :show-inheritance: +.. currentmodule:: chaco.colormapped_scatterplot + :class:`ColormappedScatterPlot` =============================== .. autoclass:: ColormappedScatterPlot :members: :show-inheritance: +.. currentmodule:: chaco.colormapped_selection_overlay + :class:`ColormappedSelectionOverlay` ==================================== .. autoclass:: ColormappedSelectionOverlay :members: :show-inheritance: +.. currentmodule:: chaco.polygon_plot + :class:`PolygonPlot` ==================== .. autoclass:: PolygonPlot :members: :show-inheritance: +.. currentmodule:: chaco.errorbar_plot + :class:`ErrorBarPlot` ===================== .. autoclass:: ErrorBarPlot :members: :show-inheritance: +.. currentmodule:: chaco.filled_line_plot + :class:`FilledLinePlot` ======================= .. autoclass:: FilledLinePlot :members: :show-inheritance: +.. currentmodule:: chaco.quiverplot + :class:`QuiverPlot` =================== .. autoclass:: QuiverPlot :members: :show-inheritance: +.. currentmodule:: chaco.candle_plot + :class:`CandlePlot` =================== .. autoclass:: CandlePlot :members: :show-inheritance: +.. currentmodule:: chaco.segment_plot + :class:`SegmentPlot` ==================== .. autoclass:: SegmentPlot :members: :show-inheritance: +.. currentmodule:: chaco.text_plot + :class:`TextPlot` ================= .. autoclass:: TextPlot :members: :show-inheritance: +.. currentmodule:: chaco.multi_line_plot + :class:`MultiLinePlot` ====================== .. autoclass:: MultiLinePlot :members: :show-inheritance: +.. currentmodule:: chaco.scatterplot_1d + :class:`ScatterPlot1D` ====================== -.. autoclass:: ScatterPlot +.. autoclass:: ScatterPlot1D :members: :show-inheritance: +.. currentmodule:: chaco.jitterplot + :class:`JitterPlot` ===================== .. autoclass:: JitterPlot :members: :show-inheritance: +.. currentmodule:: chaco.line_scatterplot_1d + :class:`LineScatterPlot1D` ============================ .. autoclass:: LineScatterPlot1D :members: :show-inheritance: +.. currentmodule:: chaco.text_plot_1d + :class:`TextPlot1D` ===================== .. autoclass:: TextPlot1D :members: :show-inheritance: +.. currentmodule:: chaco.variable_size_scatterplot + :class:`VariableSizeScatterPlot` ================================ .. autoclass:: VariableSizeScatterPlot :members: :show-inheritance: +.. currentmodule:: chaco.horizon_plot + :class:`HorizonPlot` ==================== .. autoclass:: HorizonPlot diff --git a/docs/source/user_manual/plot_types.rst b/docs/source/user_manual/plot_types.rst index 539294f7f..00102a695 100644 --- a/docs/source/user_manual/plot_types.rst +++ b/docs/source/user_manual/plot_types.rst @@ -41,33 +41,33 @@ Line Plot Standard line plot implementation. The aspect of the line is controlled by the parameters - :attr:`~chaco.lineplot.LinePlot.line_width` - The width of the line (default is 1.0) +:attr:`~chaco.lineplot.LinePlot.line_width` + The width of the line (default is 1.0) - :attr:`~chaco.lineplot.LinePlot.line_style` - The style of the line, one of 'solid' (default), 'dot dash', 'dash', 'dot', - or 'long dash'. +:attr:`~chaco.lineplot.LinePlot.line_style` + The style of the line, one of 'solid' (default), 'dot dash', 'dash', 'dot', + or 'long dash'. - :attr:`~chaco.lineplot.LinePlot.render_style` - The rendering style of the line plot, one of - 'connectedpoints' (default), 'hold', or 'connectedhold' +:attr:`~chaco.lineplot.LinePlot.render_style` + The rendering style of the line plot, one of + 'connectedpoints' (default), 'hold', or 'connectedhold' These images illustrate the differences in rendering style: * ``renderstyle='connectedpoints'`` - .. image:: images/user_guide/line_plot.png - :width: 500px +.. image:: images/user_guide/line_plot.png + :width: 500px * ``renderstyle='hold'`` - .. image:: images/user_guide/line_hold_plot.png - :width: 500px +.. image:: images/user_guide/line_hold_plot.png + :width: 500px * ``renderstyle='connectedhold'`` - .. image:: images/user_guide/line_connectedhold_plot.png - :width: 500px +.. image:: images/user_guide/line_connectedhold_plot.png + :width: 500px .. _scatter_plot: @@ -78,28 +78,28 @@ Scatter Plot Standard scatter plot implementation. The aspect of the markers is controlled by the parameters - :attr:`~chaco.scatterplot.ScatterPlot.marker` - The marker type, one of 'square'(default), 'circle', 'triangle', - 'inverted_triangle', 'plus', 'cross', 'diamond', 'dot', or 'pixel'. - One can also define a new marker shape by setting this parameter to 'custom', - and set the :attr:`~chaco.scatterplot.custom_symbol` parameter to - a :class:`CompiledPath` instance (see the file - ``demo/basic/scatter_custom_marker.py`` in the Chaco examples directory). +:attr:`~chaco.scatterplot.ScatterPlot.marker` + The marker type, one of 'square'(default), 'circle', 'triangle', + 'inverted_triangle', 'plus', 'cross', 'diamond', 'dot', or 'pixel'. + One can also define a new marker shape by setting this parameter to 'custom', + and set the :attr:`~chaco.scatterplot.custom_symbol` parameter to + a :class:`CompiledPath` instance (see the file + ``demo/basic/scatter_custom_marker.py`` in the Chaco examples directory). - :attr:`~chaco.scatterplot.ScatterPlot.marker_size` - Size of the marker in pixels, not including the outline. This can be - either a scalar (default is 4.0), or an array with one size per data - point. +:attr:`~chaco.scatterplot.ScatterPlot.marker_size` + Size of the marker in pixels, not including the outline. This can be + either a scalar (default is 4.0), or an array with one size per data + point. - :attr:`~chaco.scatterplot.ScatterPlot.line_width` - Width of the outline around the markers (default is 1.0). If this is 0.0, - no outline is drawn. +:attr:`~chaco.scatterplot.ScatterPlot.line_width` + Width of the outline around the markers (default is 1.0). If this is 0.0, + no outline is drawn. - :attr:`~chaco.scatterplot.ScatterPlot.color` - The fill color of the marker (default is black). +:attr:`~chaco.scatterplot.ScatterPlot.color` + The fill color of the marker (default is black). - :attr:`~chaco.scatterplot.ScatterPlot.outline_color` - The color of the outline to draw around the marker (default is black). +:attr:`~chaco.scatterplot.ScatterPlot.outline_color` + The color of the outline to draw around the marker (default is black). This is an example with fixed point size: @@ -129,24 +129,24 @@ In addition to the parameters supported by a :ref:`scatter plot `, a colormapped scatter plot defines these attributes: - :attr:`~chaco.colormapped_scatterplot.ColormappedScatterPlot.fill_alpha` - Set the alpha value of the points. +:attr:`~chaco.colormapped_scatterplot.ColormappedScatterPlot.fill_alpha` + Set the alpha value of the points. - :attr:`~chaco.colormapped_scatterplot.ColormappedScatterPlot.render_method` - Set the sequence in which the points are drawn. It is one of +:attr:`~chaco.colormapped_scatterplot.ColormappedScatterPlot.render_method` + Set the sequence in which the points are drawn. It is one of - 'banded' - draw points by color band; this is more efficient but some colors - will appear more prominently if there are a lot of overlapping points + 'banded' + draw points by color band; this is more efficient but some colors + will appear more prominently if there are a lot of overlapping points - 'bruteforce' - set the stroke color before drawing each marker + 'bruteforce' + set the stroke color before drawing each marker - 'auto' (default) - the approach is selected based on the number of points + 'auto' (default) + the approach is selected based on the number of points - In practice, there is not much performance difference between the two - methods. + In practice, there is not much performance difference between the two + methods. In this example plot, color represents nitric oxides concentration (green is low, red is high): @@ -173,40 +173,40 @@ and two stems (usually indicating the maximum and minimum values). The positions of the centers, and of the extrema of the bar and stems are set with the following data sources - :attr:`~chaco.candle_plot.CandlePlot.center_values` - Value of the centers. It can be set to ``None``, in which case the center is - not plotted. +:attr:`~chaco.candle_plot.CandlePlot.center_values` + Value of the centers. It can be set to ``None``, in which case the center is + not plotted. - :attr:`~chaco.candle_plot.CandlePlot.bar_min` and :attr:`~chaco.candle_plot.CandlePlot.bar_max` - Lower and upper values of the bar. +:attr:`~chaco.candle_plot.CandlePlot.bar_min` and :attr:`~chaco.candle_plot.CandlePlot.bar_max` + Lower and upper values of the bar. - :attr:`~chaco.candle_plot.CandlePlot.min_values` and :attr:`~chaco.candle_plot.CandlePlot.max_values` - Lower and upper values of the stem. They can be set to ``None``, in - which case the stems are not plotted. +:attr:`~chaco.candle_plot.CandlePlot.min_values` and :attr:`~chaco.candle_plot.CandlePlot.max_values` + Lower and upper values of the stem. They can be set to ``None``, in + which case the stems are not plotted. It is possible to customize the appearance of the candle plot with these parameters - :attr:`~chaco.candle_plot.CandlePlot.bar_color` (alias of :attr:`~chaco.candle_plot.CandlePlot.color`) - Fill color of the bar (default is black). +:attr:`~chaco.candle_plot.CandlePlot.bar_color` (alias of :attr:`~chaco.candle_plot.CandlePlot.color`) + Fill color of the bar (default is black). - :attr:`~chaco.candle_plot.CandlePlot.bar_line_color` (alias of :attr:`~chaco.candle_plot.CandlePlot.outline_color`) - Color of the box forming the bar (default is black). +:attr:`~chaco.candle_plot.CandlePlot.bar_line_color` (alias of :attr:`~chaco.candle_plot.CandlePlot.outline_color`) + Color of the box forming the bar (default is black). - :attr:`~chaco.candle_plot.CandlePlot.center_color` - Color of the line indicating the center. If ``None``, it defaults to - :attr:`~chaco.candle_plot.CandlePlot.bar_line_color`. +:attr:`~chaco.candle_plot.CandlePlot.center_color` + Color of the line indicating the center. If ``None``, it defaults to + :attr:`~chaco.candle_plot.CandlePlot.bar_line_color`. - :attr:`~chaco.candle_plot.CandlePlot.stem_color` - Color of the stems and endcaps. If ``None``, it defaults to - :attr:`~chaco.candle_plot.CandlePlot.bar_line_color`. +:attr:`~chaco.candle_plot.CandlePlot.stem_color` + Color of the stems and endcaps. If ``None``, it defaults to + :attr:`~chaco.candle_plot.CandlePlot.bar_line_color`. - :attr:`~chaco.candle_plot.CandlePlot.line_width`, :attr:`~chaco.candle_plot.CandlePlot.center_width`, and :attr:`~chaco.candle_plot.CandlePlot.stem_width` - Thickness in pixels of the lines drawing the corresponding elements. - If ``None``, they default to :attr:`~chaco.candle_plot.CandlePlot.line_width`. +:attr:`~chaco.candle_plot.CandlePlot.line_width`, :attr:`~chaco.candle_plot.CandlePlot.center_width`, and :attr:`~chaco.candle_plot.CandlePlot.stem_width` + Thickness in pixels of the lines drawing the corresponding elements. + If ``None``, they default to :attr:`~chaco.candle_plot.CandlePlot.line_width`. - :attr:`~chaco.candle_plot.CandlePlot.end_cap` - If ``False``, the end caps are not plotted (default is ``True``). +:attr:`~chaco.candle_plot.CandlePlot.end_cap` + If ``False``, the end caps are not plotted (default is ``True``). At the moment, it is not possible to control the width of the central bar @@ -232,11 +232,11 @@ In addition to the parameters supported by a :ref:`line plot `, an errorbar plot defines these attributes: - :attr:`~chaco.errorbar_plot.endcap_size` - The width of the endcap bars in pixels. +:attr:`~chaco.errorbar_plot.endcap_size` + The width of the endcap bars in pixels. - :attr:`~chaco.errorbar_plot.endcap_style` - Either 'bar' (default) or 'none', in which case no endcap bars are plotted. +:attr:`~chaco.errorbar_plot.endcap_style` + Either 'bar' (default) or 'none', in which case no endcap bars are plotted. .. image:: images/user_guide/errorbar_plot.png :width: 500px @@ -250,18 +250,18 @@ A line plot filled with color to the axis. :class:`~chacho.filled_line_plot.FilledLinePlot` defines the following parameters: - :attr:`~chaco.filled_line_plot.FilledLinePlot.fill_color` - The color used to fill the plot. +:attr:`~chaco.filled_line_plot.FilledLinePlot.fill_color` + The color used to fill the plot. - :attr:`~chaco.filled_line_plot.FilledLinePlot.fill_direction` - Fill the plot toward the origin ('down', default) ot towards the axis - maximum ('up'). +:attr:`~chaco.filled_line_plot.FilledLinePlot.fill_direction` + Fill the plot toward the origin ('down', default) ot towards the axis + maximum ('up'). - :attr:`~chaco.lineplot.LinePlot.render_style` - The rendering style of the line plot, one of - 'connectedpoints' (default), 'hold', or 'connectedhold' (see - :ref:`line plot ` for a description of the different - rendering styles). +:attr:`~chaco.lineplot.LinePlot.render_style` + The rendering style of the line plot, one of + 'connectedpoints' (default), 'hold', or 'connectedhold' (see + :ref:`line plot ` for a description of the different + rendering styles). :attr:`~chaco.filled_line_plot.FilledLinePlot` is a subclass of :attr:`~chaco.filled_line_plot.PolygonPlot`, so to set the thickness of the @@ -286,66 +286,53 @@ crossing each other. The relative displacement and rescaling of the lines is controlled by these attributes of :class:`~chaco.multi_line_plot.MultiLinePlot`: - :attr:`~chaco.multi_line_plot.MultiLinePlot.index` - - The usual array data source for the index data. - - :attr:`~chaco.multi_line_plot.MultiLinePlot.yindex` +:attr:`~chaco.multi_line_plot.MultiLinePlot.index` + The usual array data source for the index data. - Array data source for the starting point of each line. Typically, this - is set to ``numpy.arange(n_lines)``, so that each line is displaced - by one unit from the others (the other default parameters are set to - work well with this arrangement). +:attr:`~chaco.multi_line_plot.MultiLinePlot.yindex` + Array data source for the starting point of each line. Typically, this + is set to ``numpy.arange(n_lines)``, so that each line is displaced + by one unit from the others (the other default parameters are set to + work well with this arrangement). - :attr:`~chaco.multi_line_plot.MultiLinePlot.use_global_bounds`, - :attr:`~chaco.multi_line_plot.MultiLinePlot.global_min`, - :attr:`~chaco.multi_line_plot.MultiLinePlot.global_max`, +:attr:`~chaco.multi_line_plot.MultiLinePlot.use_global_bounds`, :attr:`~chaco.multi_line_plot.MultiLinePlot.global_min`, :attr:`~chaco.multi_line_plot.MultiLinePlot.global_max`, + These attributes are used to compute an "amplitude scale" which that + the largest trace deviation from its base y-coordinate will be equal + to the y-coordinate spacing. - These attributes are used to compute an "amplitude scale" which that - the largest trace deviation from its base y-coordinate will be equal - to the y-coordinate spacing. + If :attr:`use_global_bounds` is set to False, the maximum of the + absolute value of the full data is used as the largest trace deviation. + Otherwise, the largest between the absolute value of :attr:`global_min` + and :attr:`global_max` is used instead. - If :attr:`use_global_bounds` is set to False, the maximum of the - absolute value of the full data is used as the largest trace deviation. - Otherwise, the largest between the absolute value of :attr:`global_min` - and :attr:`global_max` is used instead. + By default, :attr:`use_global_bounds` is set to False and + :attr:`global_min` and :attr:`global_max` to 0.0, which means that one + of these value has to be set to create a meaningful plot. - By default, :attr:`use_global_bounds` is set to False and - :attr:`global_min` and :attr:`global_max` to 0.0, which means that one - of these value has to be set to create a meaningful plot. - - :attr:`~chaco.multi_line_plot.MultiLinePlot.scale`, - :attr:`~chaco.multi_line_plot.MultiLinePlot.offset`, - :attr:`~chaco.multi_line_plot.MultiLinePlot.normalized_amplitude` - - In addition to the rescaling done using the global bounds (see above), - each line is individually scaled by :attr:`normalized_amplitude` - (by default this is -0.5, but is normally it should be something like 1.0). - Finally, all the lines are moved by :attr:`offset` and multiplied by - :attr:`scale` (default are 0.0 and 1.0, respectively). +:attr:`~chaco.multi_line_plot.MultiLinePlot.scale`, :attr:`~chaco.multi_line_plot.MultiLinePlot.offset`, :attr:`~chaco.multi_line_plot.MultiLinePlot.normalized_amplitude` + In addition to the rescaling done using the global bounds (see above), + each line is individually scaled by :attr:`normalized_amplitude` + (by default this is -0.5, but is normally it should be something like 1.0). + Finally, all the lines are moved by :attr:`offset` and multiplied by + :attr:`scale` (default are 0.0 and 1.0, respectively). :class:`~chaco.multi_line_plot.MultiLinePlot` also defines the following parameters: - :attr:`~chaco.multi_line_plot.MultiLinePlot.line_width`, - :attr:`~chaco.multi_line_plot.MultiLinePlot.line_style` - - Control the thickness and style of the lines, as for - :ref:`line plots `. - - :attr:`~chaco.multi_line_plot.MultiLinePlot.color`, - :attr:`~chaco.multi_line_plot.MultiLinePlot.color_func` - - If :attr:`color_func` is None, all lines have the color defined - in :attr:`color`. Otherwise, :attr:`color_func` is a function - (or, more in general, a callable) that accept a single argument corresponding - to the index of the line and returns a RGBA 4-tuple. +:attr:`~chaco.multi_line_plot.MultiLinePlot.line_width`, :attr:`~chaco.multi_line_plot.MultiLinePlot.line_style` + Control the thickness and style of the lines, as for + :ref:`line plots `. - :attr:`~chaco.multi_line_plot.MultiLinePlot.fast_clip` +:attr:`~chaco.multi_line_plot.MultiLinePlot.color`, :attr:`~chaco.multi_line_plot.MultiLinePlot.color_func` + If :attr:`color_func` is None, all lines have the color defined + in :attr:`color`. Otherwise, :attr:`color_func` is a function + (or, more in general, a callable) that accept a single argument corresponding + to the index of the line and returns a RGBA 4-tuple. - If True, traces whose *base* y-coordinate is outside the value axis range - are not plotted, even if some of the data in the curve extends into the plot - region. (Default is False) +:attr:`~chaco.multi_line_plot.MultiLinePlot.fast_clip` + If True, traces whose *base* y-coordinate is outside the value axis range + are not plotted, even if some of the data in the curve extends into the plot + region. (Default is False) .. image:: images/user_guide/multiline_plot.png :width: 500px @@ -474,29 +461,29 @@ in Chaco are derived from the base class :class:`~chaco.base_countour_plot.BaseContourPlot`, which defines these common attributes: - :attr:`~chaco.base_countour_plot.BaseContourPlot.levels` - :attr:`levels` is used to define the values for which to draw a contour. - It can be either a list of values (floating point numbers); - a positive integer, in which - case the range of the value is divided in the given number of equally - spaced levels; or "auto" (default), which divides the total range in - 10 equally spaced levels +:attr:`~chaco.base_countour_plot.BaseContourPlot.levels` + :attr:`levels` is used to define the values for which to draw a contour. + It can be either a list of values (floating point numbers); + a positive integer, in which + case the range of the value is divided in the given number of equally + spaced levels; or "auto" (default), which divides the total range in + 10 equally spaced levels - :attr:`~chaco.base_countour_plot.BaseContourPlot.colors` - This attribute is used to define the color of the contours. :attr:`colors` - can be given as a color name, in which case all contours have the same - color, as a list of colors, or as a colormap. If the list of colors is - shorter than the number of levels, the values are repeated from the beginning - of the list. - If left unspecified, the contours are plot in black. - Colors are associated with levels of increasing value. +:attr:`~chaco.base_countour_plot.BaseContourPlot.colors` + This attribute is used to define the color of the contours. :attr:`colors` + can be given as a color name, in which case all contours have the same + color, as a list of colors, or as a colormap. If the list of colors is + shorter than the number of levels, the values are repeated from the beginning + of the list. + If left unspecified, the contours are plot in black. + Colors are associated with levels of increasing value. - :attr:`~chaco.base_countour_plot.BaseContourPlot.color_mapper` - If present, the color mapper for the colorbar. - TODO: not sure how it works +:attr:`~chaco.base_countour_plot.BaseContourPlot.color_mapper` + If present, the color mapper for the colorbar. + TODO: not sure how it works - :attr:`~chaco.base_countour_plot.BaseContourPlot.alpha` - Global alpha level for all contours. +:attr:`~chaco.base_countour_plot.BaseContourPlot.alpha` + Global alpha level for all contours. Contour Line Plot @@ -507,26 +494,26 @@ in :class:`~chaco.base_countour_plot.BaseContourPlot`, :class:`~chaco.base_countour_plot.ContourLinePlot` defines the following parameters: - :attr:`~chaco.base_countour_plot.ContourLinePlot.widths` - The thickness of the contour lines. - It can be either a scalar value, valid for all contour lines, or a list - of widths. If the list is too short with respect to the number of - contour lines, the values are repeated from the beginning of the list. - Widths are associated with levels of increasing value. - - :attr:`~chaco.base_countour_plot.ContourLinePlot.styles` - The style of the lines. It can either be a string that specifies the - style for all lines (allowed styles are 'solid', 'dot dash', 'dash', 'dot', - or 'long dash'), or a list of styles, one for each line. - If the list is too short with respect to the number of - contour lines, the values are repeated from the beginning of the list. - The default, 'signed', sets all lines corresponding to positive values to the - style given by the attribute - :attr:`~chaco.base_countour_plot.ContourLinePlot.positive_style` (default - is 'solid'), and all lines corresponding to negative values to - the style given by - :attr:`~chaco.base_countour_plot.ContourLinePlot.negative_style` - (default is 'dash'). +:attr:`~chaco.base_countour_plot.ContourLinePlot.widths` + The thickness of the contour lines. + It can be either a scalar value, valid for all contour lines, or a list + of widths. If the list is too short with respect to the number of + contour lines, the values are repeated from the beginning of the list. + Widths are associated with levels of increasing value. + +:attr:`~chaco.base_countour_plot.ContourLinePlot.styles` + The style of the lines. It can either be a string that specifies the + style for all lines (allowed styles are 'solid', 'dot dash', 'dash', 'dot', + or 'long dash'), or a list of styles, one for each line. + If the list is too short with respect to the number of + contour lines, the values are repeated from the beginning of the list. + The default, 'signed', sets all lines corresponding to positive values to the + style given by the attribute + :attr:`~chaco.base_countour_plot.ContourLinePlot.positive_style` (default + is 'solid'), and all lines corresponding to negative values to + the style given by + :attr:`~chaco.base_countour_plot.ContourLinePlot.negative_style` + (default is 'dash'). .. image:: images/user_guide/contour_line_plot.png :width: 500px @@ -555,18 +542,18 @@ are mapped to screen coordinates by :attr:`index_mapper` and In addition, the class :class:`~chaco.base_countour_plot.PolygonPlot` defines these parameters: - :attr:`~chaco.base_countour_plot.PolygonPlot.edge_color` - The color of the line on the edge of the polygon (default is black). +:attr:`~chaco.base_countour_plot.PolygonPlot.edge_color` + The color of the line on the edge of the polygon (default is black). - :attr:`~chaco.base_countour_plot.PolygonPlot.edge_width` - The thickness of the edge of the polygon (default is 1.0). +:attr:`~chaco.base_countour_plot.PolygonPlot.edge_width` + The thickness of the edge of the polygon (default is 1.0). - :attr:`~chaco.base_countour_plot.PolygonPlot.edge_style` - The line dash style for the edge of the polygon, one of 'solid' - (default), 'dot dash', 'dash', 'dot', or 'long dash'. +:attr:`~chaco.base_countour_plot.PolygonPlot.edge_style` + The line dash style for the edge of the polygon, one of 'solid' + (default), 'dot dash', 'dash', 'dot', or 'long dash'. - :attr:`~chaco.base_countour_plot.PolygonPlot.face_color` - The color of the face of the polygon (default is transparent). +:attr:`~chaco.base_countour_plot.PolygonPlot.face_color` + The color of the face of the polygon (default is transparent). .. image:: images/user_guide/polygon_plot.png :width: 500px @@ -588,22 +575,22 @@ Draws a set of rectangular bars, mostly used to plot histograms. The class :class:`~chaco.barplot.BarPlot` defines the attributes of regular X-Y plots, plus the following parameters: - :attr:`~chaco.barplot.BarPlot.starting_value` - While :attr:`~chaco.barplot.BarPlot.value` is a data source defining - the upper limit of the bars, :attr:`~chaco.barplot.BarPlot.starting_value` - can be used to define their bottom limit. Default is 0. - (Note: "upper" and "bottom" assume a horizontal layout for the plot.) +:attr:`~chaco.barplot.BarPlot.starting_value` + While :attr:`~chaco.barplot.BarPlot.value` is a data source defining + the upper limit of the bars, :attr:`~chaco.barplot.BarPlot.starting_value` + can be used to define their bottom limit. Default is 0. + (Note: "upper" and "bottom" assume a horizontal layout for the plot.) - :attr:`~chaco.barplot.BarPlot.bar_width_type` - Determines how to interpret the :attr:`bar_width` parameter. - If 'data' (default', the width is given in the units along the index - dimension of the data space. If 'screen', the width is given in pixels. +:attr:`~chaco.barplot.BarPlot.bar_width_type` + Determines how to interpret the :attr:`bar_width` parameter. + If 'data' (default', the width is given in the units along the index + dimension of the data space. If 'screen', the width is given in pixels. - :attr:`~chaco.barplot.BarPlot.bar_width` - The width of the bars (see :attr:`bar_width_type`). +:attr:`~chaco.barplot.BarPlot.bar_width` + The width of the bars (see :attr:`bar_width_type`). - :attr:`~chaco.barplot.BarPlot.fill_color` - The color of the bars. +:attr:`~chaco.barplot.BarPlot.fill_color` + The color of the bars. .. image:: images/user_guide/bar_plot.png :width: 500px @@ -624,14 +611,14 @@ Usually, :attr:`vectors` is an instance of :class:`~chaco.quiverplot.QuiverPlot` defines these parameters: - :attr:`~chaco.quiverplot.QuiverPlot.line_width` - Width of the lines that trace the arrows (default is 1.0). +:attr:`~chaco.quiverplot.QuiverPlot.line_width` + Width of the lines that trace the arrows (default is 1.0). - :attr:`~chaco.quiverplot.QuiverPlot.line_color` - The color of the arrows (default is black). +:attr:`~chaco.quiverplot.QuiverPlot.line_color` + The color of the arrows (default is black). - :attr:`~chaco.quiverplot.QuiverPlot.arrow_size` - The length of the arrowheads in pixels. +:attr:`~chaco.quiverplot.QuiverPlot.arrow_size` + The length of the arrowheads in pixels. .. image:: images/user_guide/quiver_plot.png @@ -656,28 +643,28 @@ coordinates, and adds circular polar coordinate axes. The aspect of the polar plot can be controlled with these parameters: - :attr:`~chaco.polar_line_renderer.PolarLineRenderer.line_width` - Width of the polar plot line (default is 1.0). +:attr:`~chaco.polar_line_renderer.PolarLineRenderer.line_width` + Width of the polar plot line (default is 1.0). - :attr:`~chaco.polar_line_renderer.PolarLineRenderer.line_style` - The style of the line, one of 'solid' (default), 'dot dash', 'dash', 'dot', - or 'long dash'. +:attr:`~chaco.polar_line_renderer.PolarLineRenderer.line_style` + The style of the line, one of 'solid' (default), 'dot dash', 'dash', 'dot', + or 'long dash'. - :attr:`~chaco.polar_line_renderer.PolarLineRenderer.color` - The color of the line. +:attr:`~chaco.polar_line_renderer.PolarLineRenderer.color` + The color of the line. - :attr:`~chaco.polar_line_renderer.PolarLineRenderer.grid_style` - The style of the lines composing the axis, one of 'solid','dot dash', - 'dash', 'dot' (default), or 'long dash'. +:attr:`~chaco.polar_line_renderer.PolarLineRenderer.grid_style` + The style of the lines composing the axis, one of 'solid','dot dash', + 'dash', 'dot' (default), or 'long dash'. - :attr:`~chaco.polar_line_renderer.PolarLineRenderer.grid_visible` - If True (default), the circular part of the axes is drawn. +:attr:`~chaco.polar_line_renderer.PolarLineRenderer.grid_visible` + If True (default), the circular part of the axes is drawn. - :attr:`~chaco.polar_line_renderer.PolarLineRenderer.origin_axis_visible` - If True (default), the radial part of the axes is drawn. +:attr:`~chaco.polar_line_renderer.PolarLineRenderer.origin_axis_visible` + If True (default), the radial part of the axes is drawn. - :attr:`~chaco.polar_line_renderer.PolarLineRenderer.origin_axis_width` - Width of the radial axis in pixels (default is 2.0). +:attr:`~chaco.polar_line_renderer.PolarLineRenderer.origin_axis_width` + Width of the radial axis in pixels (default is 2.0). .. image:: images/user_guide/polar_plot.png :width: 350px @@ -689,37 +676,36 @@ Jitter Plot A plot showing 1D data by adding a random jitter around the main axis. It can be useful for visualizing dense collections of points. -This plot has got a single mapper, -called :class:`~chaco.jitterplot.JitterPlot.mapper`. +This plot has got a single mapper, called :attr:`~chaco.jitterplot.JitterPlot.mapper`. Useful parameters are: - :attr:`~chaco.jitterplot.JitterPlot.jitter_width` - The size, in pixels, of the random jitter around the axis. +:attr:`~chaco.jitterplot.JitterPlot.jitter_width` + The size, in pixels, of the random jitter around the axis. - :attr:`~chaco.jitterplot.JitterPlot.marker` - The marker type, one of 'square'(default), 'circle', 'triangle', - 'inverted_triangle', 'plus', 'cross', 'diamond', 'dot', or 'pixel'. - One can also define a new marker shape by setting this parameter to 'custom', - and set the :attr:`~chaco.scatterplot.custom_symbol` parameter to - a :class:`CompiledPath` instance (see the file - ``demo/basic/scatter_custom_marker.py`` in the Chaco examples directory). +:attr:`~chaco.jitterplot.JitterPlot.marker` + The marker type, one of 'square'(default), 'circle', 'triangle', + 'inverted_triangle', 'plus', 'cross', 'diamond', 'dot', or 'pixel'. + One can also define a new marker shape by setting this parameter to 'custom', + and set the :attr:`~chaco.scatterplot.custom_symbol` parameter to + a :class:`CompiledPath` instance (see the file + ``demo/basic/scatter_custom_marker.py`` in the Chaco examples directory). - :attr:`~chaco.jitterplot.JitterPlot.marker_size` - Size of the marker in pixels, not including the outline (default is 4.0). +:attr:`~chaco.jitterplot.JitterPlot.marker_size` + Size of the marker in pixels, not including the outline (default is 4.0). - :attr:`~chaco.jitterplot.JitterPlot.line_width` - Width of the outline around the markers (default is 1.0). If this is 0.0, - no outline is drawn. +:attr:`~chaco.jitterplot.JitterPlot.line_width` + Width of the outline around the markers (default is 1.0). If this is 0.0, + no outline is drawn. - :attr:`~chaco.jitterplot.JitterPlot.color` - The fill color of the marker (default is black). +:attr:`~chaco.jitterplot.JitterPlot.color` + The fill color of the marker (default is black). - :attr:`~chaco.jitterplot.JitterPlot.outline_color` - The color of the outline to draw around the marker (default is black). +:attr:`~chaco.jitterplot.JitterPlot.outline_color` + The color of the outline to draw around the marker (default is black). .. image:: images/user_guide/jitter_plot.png :width: 500px -TODO: add description of color bar class +.. TODO: add description of color bar class From a963fd32c492a6bb3e29eadad6387ca7fd585375 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:09:17 -0500 Subject: [PATCH 35/68] FIX: Circular import in toolbar_plot --- chaco/toolbar_plot.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chaco/toolbar_plot.py b/chaco/toolbar_plot.py index dbc8b1797..239e7369e 100644 --- a/chaco/toolbar_plot.py +++ b/chaco/toolbar_plot.py @@ -1,4 +1,4 @@ -from chaco.api import Plot +from chaco.plot import Plot from chaco.tools.toolbars.plot_toolbar import PlotToolbar from traits.api import Type, DelegatesTo, Instance, Enum, \ on_trait_change From 2a99933d304e90eb69ba0d89011257077816ae20 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:09:34 -0500 Subject: [PATCH 36/68] DOC: Fix API doc links for plot_factories --- docs/source/api/plot_factories.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/source/api/plot_factories.rst b/docs/source/api/plot_factories.rst index 927a3fce7..815740e07 100644 --- a/docs/source/api/plot_factories.rst +++ b/docs/source/api/plot_factories.rst @@ -3,7 +3,7 @@ Plot Factories -------------- -.. currentmodule:: chaco.api +.. currentmodule:: chaco.plot_factory `create_bar_plot` ================= @@ -30,24 +30,32 @@ Plot Factories .. autofunction:: add_default_grids +.. currentmodule:: chaco.abstract_plot_data + :class:`AbstractPlotData` ========================= .. autoclass:: AbstractPlotData :members: :show-inheritance: +.. currentmodule:: chaco.array_plot_data + :class:`ArrayPlotData` ====================== .. autoclass:: ArrayPlotData :members: :show-inheritance: +.. currentmodule:: chaco.plot + :class:`Plot` ============= .. autoclass:: Plot :members: :show-inheritance: +.. currentmodule:: chaco.toolbar_plot + :class:`ToolbarPlot` ==================== .. autoclass:: ToolbarPlot From d0d94b2ff950d9f7c4184216d15e20c23d9b027f Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:31:34 -0500 Subject: [PATCH 37/68] FIX: Circular imports in tools I used .imports to be consistent with other files in the chaco.tools. --- chaco/tools/legend_highlighter.py | 2 +- chaco/tools/regression_lasso.py | 2 +- chaco/tools/tracking_pan_tool.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/chaco/tools/legend_highlighter.py b/chaco/tools/legend_highlighter.py index 5ad9c3579..8d1277858 100644 --- a/chaco/tools/legend_highlighter.py +++ b/chaco/tools/legend_highlighter.py @@ -1,7 +1,7 @@ from itertools import chain # ETS imports -from chaco.tools.api import LegendTool +from .legend_tool import LegendTool from traits.api import List, Float concat = chain.from_iterable diff --git a/chaco/tools/regression_lasso.py b/chaco/tools/regression_lasso.py index 12f59aff0..63894d91e 100644 --- a/chaco/tools/regression_lasso.py +++ b/chaco/tools/regression_lasso.py @@ -12,7 +12,7 @@ # Chaco imports from chaco.api import LassoOverlay, Label -from chaco.tools.api import LassoSelection +from .lasso_selection import LassoSelection class RegressionLasso(LassoSelection): diff --git a/chaco/tools/tracking_pan_tool.py b/chaco/tools/tracking_pan_tool.py index 3b888d965..55f279275 100644 --- a/chaco/tools/tracking_pan_tool.py +++ b/chaco/tools/tracking_pan_tool.py @@ -1,7 +1,7 @@ """ Defines the TrackingPanTool class. """ # Chaco imports -from chaco.tools.api import PanTool +from .pan_tool import PanTool class TrackingPanTool(PanTool): """ Allows the user to pan around a plot. From 17f52039c4e3ef874a66404a533f73f121fd4987 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:32:25 -0500 Subject: [PATCH 38/68] DOC: Fix API doc links for tools --- docs/source/api/tools.rst | 62 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/docs/source/api/tools.rst b/docs/source/api/tools.rst index af528287d..96542146d 100644 --- a/docs/source/api/tools.rst +++ b/docs/source/api/tools.rst @@ -3,7 +3,7 @@ Tools ------ -.. currentmodule:: chaco.tools.api +.. currentmodule:: chaco.tools.better_zoom :class:`BetterZoom` ========================== @@ -11,54 +11,72 @@ Tools :members: :show-inheritance: +.. currentmodule:: chaco.tools.better_selecting_zoom + :class:`BetterSelectingZoom` ============================ .. autoclass:: BetterSelectingZoom :members: :show-inheritance: +.. currentmodule:: chaco.tools.broadcaster + :class:`BroadcasterTool` ========================== .. autoclass:: BroadcasterTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.dataprinter + :class:`DataPrinter` ========================== .. autoclass:: DataPrinter :members: :show-inheritance: +.. currentmodule:: chaco.tools.data_label_tool + :class:`DataLabelTool` ========================== .. autoclass:: DataLabelTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.drag_tool + :class:`DragTool` ========================== .. autoclass:: DragTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.draw_points_tool + :class:`DrawPointsTool` ========================== .. autoclass:: DrawPointsTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.drag_zoom + :class:`DragZoom` ========================== .. autoclass:: DragZoom :members: :show-inheritance: +.. currentmodule:: chaco.tools.highlight_tool + :class:`HighlightTool` ========================== .. autoclass:: HighlightTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.image_inspector_tool + :class:`ImageInspectorTool` =========================== .. autoclass:: ImageInspectorTool @@ -71,72 +89,96 @@ Tools :members: :show-inheritance: +.. currentmodule:: chaco.tools.lasso_selection + :class:`LassoSelection` ========================== .. autoclass:: LassoSelection :members: :show-inheritance: +.. currentmodule:: chaco.tools.legend_tool + :class:`LegendTool` ========================== .. autoclass:: LegendTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.legend_highlighter + :class:`LegendHighlighter` ========================== .. autoclass:: LegendHighlighter :members: :show-inheritance: +.. currentmodule:: chaco.tools.line_inspector + :class:`LineInspector` ========================== .. autoclass:: LineInspector :members: :show-inheritance: +.. currentmodule:: chaco.tools.line_segment_tool + :class:`LineSegmentTool` ========================== .. autoclass:: LineSegmentTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.move_tool + :class:`MoveTool` ========================== .. autoclass:: MoveTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.pan_tool + :class:`PanTool` ========================== .. autoclass:: PanTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.point_marker + :class:`PointMarker` ========================== .. autoclass:: PointMarker :members: :show-inheritance: +.. currentmodule:: chaco.tools.range_selection + :class:`RangeSelection` ========================== .. autoclass:: RangeSelection :members: :show-inheritance: +.. currentmodule:: chaco.tools.range_selection_2d + :class:`RangeSelection2D` ========================== .. autoclass:: RangeSelection2D :members: :show-inheritance: +.. currentmodule:: chaco.tools.range_selection_overlay + :class:`RangeSelectionOverlay` ============================== .. autoclass:: RangeSelectionOverlay :members: :show-inheritance: +.. currentmodule:: chaco.tools.regression_lasso + :class:`RegressionLasso` ========================== .. autoclass:: RegressionLasso @@ -149,30 +191,40 @@ Tools :members: :show-inheritance: +.. currentmodule:: chaco.tools.save_tool + :class:`SaveTool` ========================== .. autoclass:: SaveTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.scatter_inspector + :class:`ScatterInspector` ========================== .. autoclass:: ScatterInspector :members: :show-inheritance: +.. currentmodule:: chaco.tools.select_tool + :class:`SelectTool` ========================== .. autoclass:: SelectTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.simple_inspector + :class:`SimpleInspectorTool` ============================ .. autoclass:: SimpleInspectorTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.tool_states + :class:`ZoomState` ========================== .. autoclass:: ZoomState @@ -197,24 +249,32 @@ Tools :members: :show-inheritance: +.. currentmodule:: chaco.tools.tracking_pan_tool + :class:`TrackingPanTool` ========================== .. autoclass:: TrackingPanTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.tracking_zoom + :class:`TrackingZoom` ========================== .. autoclass:: TrackingZoom :members: :show-inheritance: +.. currentmodule:: chaco.tools.traits_tool + :class:`TraitsTool` ========================== .. autoclass:: TraitsTool :members: :show-inheritance: +.. currentmodule:: chaco.tools.zoom_tool + :class:`ZoomTool` ========================== .. autoclass:: ZoomTool From 4edd70918cdd7c8af280545e04599ebb86e312cf Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:35:00 -0500 Subject: [PATCH 39/68] DOC: Fix API doc links for axis.rst --- docs/source/api/axis.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/source/api/axis.rst b/docs/source/api/axis.rst index 3213a82a9..838f97bd2 100644 --- a/docs/source/api/axis.rst +++ b/docs/source/api/axis.rst @@ -3,7 +3,7 @@ Axis and Grid -------------- -.. currentmodule:: chaco.api +.. currentmodule:: chaco.axis :class:`PlotAxis` ========================== @@ -11,18 +11,24 @@ Axis and Grid :members: :show-inheritance: +.. currentmodule:: chaco.label_axis + :class:`LabelAxis` ========================== .. autoclass:: LabelAxis :members: :show-inheritance: +.. currentmodule:: chaco.grid + :class:`PlotGrid` ========================== .. autoclass:: PlotGrid :members: :show-inheritance: +.. currentmodule:: chaco.ticks + :class:`AbstractTickGenerator` =============================== .. autoclass:: AbstractTickGenerator From ebb84df8856a713e0699ce672aa044d380f373f4 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:39:47 -0500 Subject: [PATCH 40/68] DOC: Fix API doc links for visual components --- docs/source/api/visual_components.rst | 34 ++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/docs/source/api/visual_components.rst b/docs/source/api/visual_components.rst index 5396bedd6..974ed0694 100644 --- a/docs/source/api/visual_components.rst +++ b/docs/source/api/visual_components.rst @@ -3,7 +3,7 @@ Visual Components ----------------- -.. currentmodule:: chaco.api +.. currentmodule:: chaco.abstract_plot_renderer :class:`AbstractPlotRenderer` ============================= @@ -11,96 +11,128 @@ Visual Components :members: :show-inheritance: +.. currentmodule:: chaco.abstract_overlay + :class:`AbstractOverlay` ======================== .. autoclass:: AbstractOverlay :members: :show-inheritance: +.. currentmodule:: chaco.base_plot_frame + :class:`BasePlotFrame` ====================== .. autoclass:: BasePlotFrame :members: :show-inheritance: +.. currentmodule:: chaco.cross_plot_frame + :class:`CrossPlotFrame` ======================= .. autoclass:: CrossPlotFrame :members: :show-inheritance: +.. currentmodule:: chaco.data_view + :class:`DataView` ================= .. autoclass:: DataView :members: :show-inheritance: +.. currentmodule:: chaco.simple_plot_frame + :class:`SimplePlotFrame` ======================== .. autoclass:: SimplePlotFrame :members: :show-inheritance: +.. currentmodule:: chaco.plot_component + :class:`PlotComponent` ====================== .. autoclass:: PlotComponent :members: :show-inheritance: +.. currentmodule:: chaco.plot_graphics_context + :class:`PlotGraphicsContext` ============================ .. autoclass:: PlotGraphicsContext :members: :show-inheritance: +.. currentmodule:: chaco.label + :class:`Label` ============== .. autoclass:: Label :members: :show-inheritance: +.. currentmodule:: chaco.plot_label + :class:`PlotLabel` ================== .. autoclass:: PlotLabel :members: :show-inheritance: +.. currentmodule:: chaco.legend + :class:`Legend` =============== .. autoclass:: Legend :members: :show-inheritance: +.. currentmodule:: chaco.tooltip + :class:`ToolTip` ================ .. autoclass:: ToolTip :members: :show-inheritance: +.. currentmodule:: chaco.data_label + :class:`DataLabel` ================== .. autoclass:: DataLabel :members: :show-inheritance: +.. currentmodule:: chaco.lasso_overlay + :class:`LassoOverlay` ===================== .. autoclass:: LassoOverlay :members: :show-inheritance: +.. currentmodule:: chaco.color_bar + :class:`ColorBar` ================= .. autoclass:: ColorBar :members: :show-inheritance: +.. currentmodule:: chaco.text_box_overlay + :class:`TextBoxOverlay` ======================= .. autoclass:: TextBoxOverlay :members: :show-inheritance: +.. currentmodule:: chaco.scatter_inspector_overlay + :class:`ScatterInspectorOverlay` ================================ .. autoclass:: ScatterInspectorOverlay From 66ee9143a53241fe042fe383eb80fe2799291a78 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:47:10 -0500 Subject: [PATCH 41/68] DOC: Fix API doc links for containers --- docs/source/api/containers.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/source/api/containers.rst b/docs/source/api/containers.rst index 22327b7dc..bcd6422fb 100644 --- a/docs/source/api/containers.rst +++ b/docs/source/api/containers.rst @@ -4,7 +4,7 @@ Containers ---------- -.. currentmodule:: chaco.api +.. currentmodule:: chaco.base_plot_container :class:`BasePlotContainer` ========================== @@ -12,6 +12,8 @@ Containers :members: :show-inheritance: +.. currentmodule:: chaco.plot_containers + :class:`OverlayPlotContainer` ============================= .. autoclass:: OverlayPlotContainer @@ -36,6 +38,14 @@ Containers :members: :show-inheritance: +:class:`StackedPlotContainer` +============================= +.. autoclass:: StackedPlotContainer + :members: + :show-inheritance: + +.. currentmodule:: chaco.selectable_overlay_container + :class:`SelectableOverlayPlotContainer` ======================================= .. autoclass:: SelectableOverlayPlotContainer From 0d116af77e6089b1578510cb1f55653708cba9eb Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:47:28 -0500 Subject: [PATCH 42/68] DOC: Add support for intersphinx for enable --- docs/source/conf.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/source/conf.py b/docs/source/conf.py index d55cf46c4..aa802148f 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -33,6 +33,7 @@ def get_build_docset(): 'sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.graphviz', + 'sphinx.ext.intersphinx', 'traits.util.trait_documenter', ] @@ -214,3 +215,8 @@ def get_build_docset(): # If false, no module index is generated. #latex_use_modindex = True + + +intersphinx_mapping = { + 'enable': ('http://docs.enthought.com/enable', None) +} \ No newline at end of file From b57a51b1855c3fb1dbf21b59f37e9d93bf172077 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 10:53:49 -0500 Subject: [PATCH 43/68] DOC: Add missing MinorPlotAxis to API docs --- docs/source/api/axis.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/source/api/axis.rst b/docs/source/api/axis.rst index 838f97bd2..2be0d5174 100644 --- a/docs/source/api/axis.rst +++ b/docs/source/api/axis.rst @@ -11,6 +11,11 @@ Axis and Grid :members: :show-inheritance: +:class:`MinorPlotAxis` +========================== +.. autoclass:: MinorPlotAxis + :members: + :show-inheritance: .. currentmodule:: chaco.label_axis :class:`LabelAxis` From de248cc9f7df9f3eaee32c67c8f7aa7cc332c5c7 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 11:00:23 -0500 Subject: [PATCH 44/68] DOC: Fix RST formatting --- .../user_manual/basic_elements/overlays.rst | 33 ++----- .../basic_elements/plot_renderers.rst | 91 +++++++++---------- 2 files changed, 47 insertions(+), 77 deletions(-) diff --git a/docs/source/user_manual/basic_elements/overlays.rst b/docs/source/user_manual/basic_elements/overlays.rst index fa5a24e88..1723e14cb 100644 --- a/docs/source/user_manual/basic_elements/overlays.rst +++ b/docs/source/user_manual/basic_elements/overlays.rst @@ -84,12 +84,7 @@ Attributes These attributes control the appearance of the axis: -:attr:`~chaco.axis.PlotAxis.title`, -:attr:`~chaco.axis.PlotAxis.title_font`, -:attr:`~chaco.axis.PlotAxis.title_color`, -:attr:`~chaco.axis.PlotAxis.title_spacing` -:attr:`~chaco.axis.PlotAxis.title_angle` - +:attr:`~chaco.axis.PlotAxis.title`, :attr:`~chaco.axis.PlotAxis.title_font`, :attr:`~chaco.axis.PlotAxis.title_color`, :attr:`~chaco.axis.PlotAxis.title_spacing` :attr:`~chaco.axis.PlotAxis.title_angle` Define the axis label. :attr:`title` is a string or unicode object that is rendered using the given font and color. :attr:`title_font` is a string describing a font (e.g. '12 pt bold italic', @@ -101,12 +96,7 @@ These attributes control the appearance of the axis: wrt horizontal). -:attr:`~chaco.axis.PlotAxis.tick_weight`, -:attr:`~chaco.axis.PlotAxis.tick_color`, -:attr:`~chaco.axis.PlotAxis.tick_in`, -:attr:`~chaco.axis.PlotAxis.tick_out`, -:attr:`~chaco.axis.PlotAxis.tick_visible`, - +:attr:`~chaco.axis.PlotAxis.tick_weight`, :attr:`~chaco.axis.PlotAxis.tick_color`, :attr:`~chaco.axis.PlotAxis.tick_in`, :attr:`~chaco.axis.PlotAxis.tick_out`, :attr:`~chaco.axis.PlotAxis.tick_visible`, These attributes control the aspect of the ticks on the axis. If :attr:`tick_visible` is True, ticks are represented as lines of color :attr:`tick_color` (default is black) and thickness @@ -115,14 +105,7 @@ These attributes control the appearance of the axis: :attr:`tick_out` pixels (default is 5). -:attr:`~chaco.axis.PlotAxis.tick_label_font`, -:attr:`~chaco.axis.PlotAxis.tick_label_color`, -:attr:`~chaco.axis.PlotAxis.tick_label_rotate_angle`, -:attr:`~chaco.axis.PlotAxis.tick_label_alignment`, -:attr:`~chaco.axis.PlotAxis.tick_label_margin`, -:attr:`~chaco.axis.PlotAxis.tick_label_offset`, -:attr:`~chaco.axis.PlotAxis.tick_label_position`, - +:attr:`~chaco.axis.PlotAxis.tick_label_font`, :attr:`~chaco.axis.PlotAxis.tick_label_color`, :attr:`~chaco.axis.PlotAxis.tick_label_rotate_angle`, :attr:`~chaco.axis.PlotAxis.tick_label_alignment`, :attr:`~chaco.axis.PlotAxis.tick_label_margin`, :attr:`~chaco.axis.PlotAxis.tick_label_offset`, :attr:`~chaco.axis.PlotAxis.tick_label_position`, These attributes allow to fine-tune the aspect of the tick labels: first of all, the font (e.g. '12 pt bold italic') and color of the labels. The position and orientation of the label can be also be @@ -139,7 +122,6 @@ These attributes control the appearance of the axis: :attr:`~chaco.axis.PlotAxis.tick_label_formatter` - By default, tick labels are assumed to be floating point numbers, and are displayed as such after removing trailing zeros and the decimal dot if necessary (e.g., '10.000' will be displayed as '10', and '21.10' as '21.1'). @@ -148,9 +130,7 @@ These attributes control the appearance of the axis: formatted string. -:attr:`~chaco.axis.PlotAxis.tick_interval`, -:attr:`~chaco.axis.PlotAxis.tick_generator`, - +:attr:`~chaco.axis.PlotAxis.tick_interval`, :attr:`~chaco.axis.PlotAxis.tick_generator`, Locations and distances of ticks are controlled by the attribute :attr:`tick_generator` @@ -162,9 +142,8 @@ These attributes control the appearance of the axis: Events ------ -updated - -Fired when the axis's range bounds change. +:attr:`~chaco.axis.PlotAxis.updated` + Fired when the axis's range bounds change. .. _legend: diff --git a/docs/source/user_manual/basic_elements/plot_renderers.rst b/docs/source/user_manual/basic_elements/plot_renderers.rst index f826ec06a..784cf3ee8 100644 --- a/docs/source/user_manual/basic_elements/plot_renderers.rst +++ b/docs/source/user_manual/basic_elements/plot_renderers.rst @@ -159,29 +159,29 @@ The default drawing order is defined in :attr:`~chaco.plot_component.PlotComponent.draw_order` as a list of the names of the layers. The definition of the layers is as follows: -1. 'background': Background image, shading, and borders +1. **background**: Background image, shading, and borders -2. 'image': A special layer for plots that render as images. This is in a - separate layer since these plots must all render before non-image plots +2. **image**: A special layer for plots that render as images. This is in a + separate layer since these plots must all render before non-image plots -3. 'underlay': Axes and grids +3. **underlay**: Axes and grids -4. 'plot': The main plot area itself +4. **plot**: The main plot area itself -5. 'annotation': Lines and text that are conceptually part of the "plot" but - need to be rendered on top of everything else in the plot. +5. **annotation**: Lines and text that are conceptually part of the "plot" but + need to be rendered on top of everything else in the plot. -6. 'selection': Selected content are rendered above normal plot elements to - make them stand out. This can be disabled by setting :attr:`use_selection` - to False (default). +6. **selection**: Selected content are rendered above normal plot elements to + make them stand out. This can be disabled by setting :attr:`use_selection` + to False (default). -7. 'border': Plot borders +7. **border**: Plot borders -8. 'annotation': Lines and text that are conceptually part of the "plot" but - need to be rendered on top of everything else in the plot +8. **annotation**: Lines and text that are conceptually part of the "plot" but + need to be rendered on top of everything else in the plot -9. 'overlay': Legends, selection regions, and other tool-drawn visual - elements +9. **overlay**: Legends, selection regions, and other tool-drawn visual + elements Concrete plot renderers set their default draw layer in :attr:`~chaco.plot_component.PlotComponent.draw_layer` (default is 'plot'). @@ -202,7 +202,7 @@ as such are able to react to keyboard and mouse events. However, interactions are usually defined as tools and overlays. Therefore, this part of the interface is described at those pages. -TODO: add reference to interaction interface +.. TODO: add reference to interaction interface Context ------- @@ -258,18 +258,16 @@ data space: Others ------ - :attr:`use_backbuffer` +:attr:`use_backbuffer` + If True, the plot renders itself to an + offscreen buffer that is cached for later use. If False (default), then + the component will *never* render itself back-buffered, even if asked + to do so. - If True, the plot renders itself to an - offscreen buffer that is cached for later use. If False (default), then - the component will *never* render itself back-buffered, even if asked - to do so. - - :attr:`invalidate_and_redraw()` - - Convenience method to invalidate our contents and request redraw. - This method is sometimes useful when modifying a Chaco plot in an - ipython shell. +:meth:`invalidate_and_redraw` + Convenience method to invalidate our contents and request redraw. + This method is sometimes useful when modifying a Chaco plot in an + ipython shell. .. _xy_plots: @@ -316,27 +314,22 @@ Axis, labels, and grids shortcuts to find axis and grid objects in the :ref:`underlays and overlays layers ` of the plot: - :attr:`~chaco.base_xy_plot.BaseXYPlot.hgrid`, - :attr:`~chaco.base_xy_plot.BaseXYPlot.vgrid` - - Look into the underlays and overlays layers (in this order) for a - :class:`PlotGrid` object of horizontals / vertical orientation and return - it. Return None if none is found. - - :attr:`~chaco.base_xy_plot.BaseXYPlot.x_axis`, - :attr:`~chaco.base_xy_plot.BaseXYPlot.y_axis` +:attr:`~chaco.base_xy_plot.BaseXYPlot.hgrid`, :attr:`~chaco.base_xy_plot.BaseXYPlot.vgrid` + Look into the underlays and overlays layers (in this order) for a + :class:`PlotGrid` object of horizontals / vertical orientation and return + it. Return None if none is found. - Look into the underlays and overlays layers (in this order) for a - :class:`PlotAxis` object positioned to the bottom or top, or to the - left or right of plot, respectively. Return the axis, or None if - none is found. +:attr:`~chaco.base_xy_plot.BaseXYPlot.x_axis`, :attr:`~chaco.base_xy_plot.BaseXYPlot.y_axis` + Look into the underlays and overlays layers (in this order) for a + :class:`PlotAxis` object positioned to the bottom or top, or to the + left or right of plot, respectively. Return the axis, or None if + none is found. - :attr:`~chaco.base_xy_plot.BaseXYPlot.labels` +:attr:`~chaco.base_xy_plot.BaseXYPlot.labels` + Return a list of all :class:`PlotLabel` objects in the + overlays and underlays layers. - Return a list of all :class:`PlotLabel` objects in the - overlays and underlays layers. - -TODO: add links to axis and grid documentation +.. TODO: add links to axis and grid documentation Hittest ------- @@ -359,8 +352,8 @@ which is one of 'point' (default), or 'line'. If the closest point or line is further than :attr:`threshold` pixels away, the methods returns None. -Alternatively, users may call the methods :attr:`get_closest_point` -and :attr:`get_closest_line`. +Alternatively, users may call the methods :meth:`get_closest_point` +and :meth:`get_closest_line`. Others ------ @@ -368,12 +361,10 @@ Others Two more attributes are worth mentioning: :attr:`~chaco.base_xy_plot.BaseXYPlot.bgcolor` - This is inherited from the AbstractPlotRenderer interface, but is now - set to 'transparent` by default. + set to 'transparent' by default. :attr:`~chaco.base_xy_plot.BaseXYPlot.use_downsampling` - If this attribute is True, the plot uses downsampling for faster display (default is False). In other words, the number of display points depends on the plot size and range, and not on the total number of data points From a90efc209c7d9b64a17cc06bb0adedda84d2e2bf Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 11:36:00 -0500 Subject: [PATCH 45/68] DOC: Add curstor tools to API docs --- docs/source/api/tools.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/docs/source/api/tools.rst b/docs/source/api/tools.rst index 96542146d..32dd526c4 100644 --- a/docs/source/api/tools.rst +++ b/docs/source/api/tools.rst @@ -281,4 +281,26 @@ Tools :members: :show-inheritance: +.. currentmodule:: chaco.tools.cursor_tool +:class:`BaseCursorTool` +========================== +.. autoclass:: BaseCursorTool + :members: + :show-inheritance: + +`CursorTool` +============ +.. autofunction:: CursorTool + +:class:`CursorTool1D` +========================== +.. autoclass:: CursorTool1D + :members: + :show-inheritance: + +:class:`CursorTool2D` +========================== +.. autoclass:: CursorTool2D + :members: + :show-inheritance: \ No newline at end of file From bb3ae5301e0ba76b38027a2f53fc3eca294690d3 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 11:36:27 -0500 Subject: [PATCH 46/68] DOC: Add SelectableLegend to API docs --- docs/source/api/visual_components.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/source/api/visual_components.rst b/docs/source/api/visual_components.rst index 974ed0694..5226b03ba 100644 --- a/docs/source/api/visual_components.rst +++ b/docs/source/api/visual_components.rst @@ -90,6 +90,14 @@ Visual Components .. autoclass:: Legend :members: :show-inheritance: + +.. currentmodule:: chaco.selectable_legend + +:class:`SelectableLegend` +========================= +.. autoclass:: SelectableLegend + :members: + :show-inheritance: .. currentmodule:: chaco.tooltip From b29cffb0dd40572b99afd54ef0e9b4c904516315 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 11:36:45 -0500 Subject: [PATCH 47/68] DOC: Fix API links in user guide --- .../user_manual/basic_elements/overlays.rst | 2 +- .../user_manual/modules_and_classes.rst | 157 ++++++++++-------- 2 files changed, 85 insertions(+), 74 deletions(-) diff --git a/docs/source/user_manual/basic_elements/overlays.rst b/docs/source/user_manual/basic_elements/overlays.rst index 1723e14cb..e378042a9 100644 --- a/docs/source/user_manual/basic_elements/overlays.rst +++ b/docs/source/user_manual/basic_elements/overlays.rst @@ -1,5 +1,5 @@ ================================== -Overlays: axis, legend, grid, etc. +Overlays: axis, and, grid, etc. ================================== Overlays are elements that decorate plots, like for example diff --git a/docs/source/user_manual/modules_and_classes.rst b/docs/source/user_manual/modules_and_classes.rst index 58dc4ba33..726118188 100644 --- a/docs/source/user_manual/modules_and_classes.rst +++ b/docs/source/user_manual/modules_and_classes.rst @@ -9,16 +9,17 @@ Base Classes .. rubric:: Plot Component -All visual components in Chaco subclass from :class:`PlotComponent`. It defines -all of the common visual attributes like background color, border styles and -color, and whether the component is visible. (Actually, most of these visual -attributes are inherited from the Enable drawing framework.) More importantly, -it provides the base behaviors for participating in layout, handling event -dispatch to tools and overlays, and drawing various layers in the correct order. -Subclasses almost never need to override or customize these base behaviors, but -if they do, there are several easy extension points. - -PlotComponent is a subclass of Enable :class:`Component`. It has its +All visual components in Chaco subclass from +:class:`~chaco.plot_component.PlotComponent`. It defines all of the common +visual attributes like background color, border styles and color, and whether +the component is visible. (Actually, most of these visual attributes are +inherited from the Enable drawing framework.) More importantly, it provides the +base behaviors for participating in layout, handling event dispatch to tools +and overlays, and drawing various layers in the correct order. Subclasses +almost never need to override or customize these base behaviors, but if they +do, there are several easy extension points. + +PlotComponent is a subclass of Enable :class:`~enable.api.Component`. It has its own default drawing order. It redefines the inherited traits :attr:`draw_order` and :attr:`draw_layer`, but it doesn't define any new traits. Therefore, you may need to refer to the API documentation for Enable Component, @@ -43,10 +44,13 @@ changed. There are two primary reasons for a data source class: * It defines the interface for embedding Chaco into an existing application. In most cases, the standard ArrayDataSource will suffice. -*Interface:* :class:`AbstractDataSource` +*Interface:* :class:`~chaco.abstract_data_source.AbstractDataSource` -*Subclasses:* :class:`ArrayDataSource`, :class:`MultiArrayDataSource`, -:class:`PointDataSource`, :class:`GridDataSource`, :class:`ImageData` +*Subclasses:* :class:`~chaco.array_data_source.ArrayDataSource`, +:class:`~chaco.multi_array_data_source.MultiArrayDataSource`, +:class:`~chaco.point_data_source.PointDataSource`, +:class:`~chaco.grid_data_source.GridDataSource`, +:class:`~chaco.image_data.ImageData` .. rubric:: Data Range @@ -57,20 +61,24 @@ One of the important aspects of data ranges is that their bounds can be set to datasources. (Each data source can be associated with multiple ranges, and each data range can be associated with multiple data sources.) -*Interface*: :class:`AbstractDataRange` +*Interface*: :class:`~chaco.abstract_data_range.AbstractDataRange` -*Subclasses*: :class:`BaseDataRange`, :class:`DataRange1D`, :class:`DataRange2D` +*Subclasses*: :class:`~chaco.base_data_range.BaseDataRange`, +:class:`~chaco.data_range_1d.DataRange1D`, +:class:`~chaco.data_range_2d.DataRange2D` .. rubric:: Data Source A data source is an object that supplies data to Chaco. For the most part, a data source looks like an array of values, with an optional mask and metadata. -*Interface*: :class:`AbstractDataSource` +*Interface*: :class:`~chaco.abstract_data_source.AbstractDataSource` -*Subclasses*: :class:`ArrayDataSource`, :class:`DataContextDataSource`, -:class:`GridDataSource`, :class:`ImageData`, :class:`MultiArrayDataSource`, -:class:`PointDataSource` +*Subclasses*: :class:`~chaco.array_data_source.ArrayDataSource`, +:class:`~chaco.grid_data_source.GridDataSource`, +:class:`~chaco.image_data.ImageData`, +:class:`~chaco.multi_array_data_source.MultiArrayDataSource`, +:class:`~chaco.point_data_source.PointDataSource` The :attr:`metadata` trait attribute is a dictionary where you can stick stuff for other tools to find, without inserting it in the actual data. @@ -87,10 +95,12 @@ Events that are fired on data sources are: Mappers perform the job of mapping a data space region to screen space, and vice versa. Bounds on mappers are set by data range objects. -*Interface*: :class:`AbstractMapper` +*Interface*: :class:`~chaco.abstract_mapper.AbstractMapper` -*Subclasses*: :class:`Base1DMapper`, :class:`LinearMapper`, :class:`LogMapper`, -:class:`GridMapper`, :class:`PolarMapper` +*Subclasses*: :class:`~chaco.base_1d_mapper.Base1DMapper`, +:class:`~chaco.linear_mapper.LinearMapper`, +:class:`~chaco.log_mapper.LogMapper`, :class:`~chaco.grid_mapper.GridMapper`, +:class:`~chaco.polar_mapper.PolarMapper` Containers @@ -98,11 +108,11 @@ Containers .. rubric:: PlotContainer -:class:`PlotContainer` is Chaco's way of handling layout. Because it logically +:class:`~.PlotContainer` is Chaco's way of handling layout. Because it logically partitions the screen space, it also serves as a way for efficient event dispatch. It is very similar to sizers or layout grids in GUI toolkits like WX. Containers are subclasses of PlotComponent, thus allowing them to -be nested. :class:`BasePlotContainer` implements the logic to correctly render +be nested. :class:`~.BasePlotContainer` implements the logic to correctly render and dispatch events to sub-components, while its subclasses implement the different layout calculations. @@ -113,10 +123,10 @@ left over is divided among the resizeable components. Chaco currently has three types of containers, described in the following sections. -*Interface*: :class:`BasePlotContainer` +*Interface*: :class:`~.BasePlotContainer` -*Subclasses*: :class:`OverlayPlotContainer`, :class:`HPlotContainer`, -:class:`VPlotContainer`, :class:`GridPlotContainer` +*Subclasses*: :class:`~.OverlayPlotContainer`, :class:`~.HPlotContainer`, +:class:`~.VPlotContainer`, :class:`~.GridPlotContainer` The listed subclasses are defined in the module :mod:`chaco.plot_containers`. @@ -127,56 +137,56 @@ Renderers Plot renderers are the classes that actually draw a type of plot. -*Interface*: :class:`AbstractPlotRenderer` +*Interface*: :class:`~.AbstractPlotRenderer` *Subclasses*: -* :class:`BarPlot` -* :class:`Base2DPlot` +* :class:`~.BarPlot` +* :class:`~.Base2DPlot` - * :class:`ContourLinePlot` - * :class:`ContourPolyPlot` - * :class:`ImagePlot`: displays an image file, or color-maps scalar + * :class:`~.ContourLinePlot` + * :class:`~.ContourPolyPlot` + * :class:`~.ImagePlot`: displays an image file, or color-maps scalar data to make an image - * :class:`CMapImagePlot` + * :class:`~.CMapImagePlot` -* :class:`BaseXYPlot`: This class is often emulated by writers of other +* :class:`~.BaseXYPlot`: This class is often emulated by writers of other plot renderers, but renderers don't *need* to be structured this way. By convention, many have a :meth:`hittest` method. They *do* need to implement :meth:`map_screen`, :meth:`map_data`, and :meth:`map_index` - from :class:`AbstractPlotRenderer`. + from :class:`~.AbstractPlotRenderer`. - * :class:`LinePlot` + * :class:`~.LinePlot` - * :class:`ErrorBarPlot` + * :class:`~.ErrorBarPlot` - * :class:`PolygonPlot` + * :class:`~.PolygonPlot` - * :class:`FilledLinePlot` + * :class:`~.FilledLinePlot` - * :class:`ScatterPlot` + * :class:`~.ScatterPlot` - * :class:`ColormappedScatterPlot` + * :class:`~.ColormappedScatterPlot` - * :class:`ColorBar` - * :class:`PolarLineRenderer`: NOTE: doesn't play well with others + * :class:`~.ColorBar` + * :class:`~.PolarLineRenderer`: NOTE: doesn't play well with others You can use these classes to compose more interesting plots. The module :mod:`chaco.plot_factory` contains various convenience functions for creating plots, which simplify the set-up. -The :class:`chaco.plot.Plot` class (called "capital P Plot" when +The :class:`~chaco.plot.Plot` class (called "capital P Plot" when speaking) represents what the user usually thinks of as a "plot": a set of data, renderers, and axes in a single screen region. It is a subclass of -:class:`DataView`. +:class:`~.DataView`. Tools ----------------------------------------------------------------------------- Tools attach to a component, which gives events to the tool. -All tools subclass from Enable's :class:`BaseTool`, which is in turn an Enable +All tools subclass from Enable's :class:`~.BaseTool`, which is in turn an Enable :class:`Interactor`. Do not try to make tools that draw: use an overlay for that. @@ -187,48 +197,49 @@ first in Chaco, and then moved into Enable. *Subclasses*: -* :class:`BroadcasterTool`: Keeps a list of other tools, and broadcasts +* :class:`~.BroadcasterTool`: Keeps a list of other tools, and broadcasts events it receives to all those tools. -* :class:`DataPrinter`: Prints the data-space position of the point +* :class:`~.DataPrinter`: Prints the data-space position of the point under the cursor. * :class:`enable.tools.api.DragTool`: Enable base class for tools that do dragging. - * :class:`MoveTool` - * :class:`ResizeTool` - * :class:`ViewportPanTool` + * :class:`~chaco.tools.move_tool.MoveTool` + * :class:`enable.tools.api.ResizeTool` + * :class:`enable.tools.api.ViewportPanTool` -* :class:`chaco.tools.api.DragTool`: Chaco base class +* :class:`~.chaco.tools.drag_tool.DragTool`: Chaco base class for tools that do dragging. - * :class:`BaseCursorTool` + * :class:`~chaco.tools.cursor_tool.BaseCursorTool` - * :class:`CursorTool1D` - * :class:`CursorTool2D` + * :class:`~chaco.tools.cursor_tool.CursorTool1D` + * :class:`~chaco.tools.cursor_tool.CursorTool2D` - * :class:`DataLabelTool` - * :class:`DragZoom` - * :class:`LegendTool` - * :class:`MoveTool` + * :class:`~.DataLabelTool` + * :class:`~.DragZoom` + * :class:`~.LegendTool` + * :class:`~.MoveTool` -* :class:`DrawPointsTool` -* :class:`HighlightTool` -* :class:`HoverTool` -* :class:`ImageInspectorTool` -* :class:`LineInspector` -* :class:`PanTool` +* :class:`~.DrawPointsTool` +* :class:`~.HighlightTool` +* :class:`~.HoverTool` +* :class:`~.ImageInspectorTool` +* :class:`~.LineInspector` +* :class:`~.PanTool` - * :class:`TrackingPanTool` + * :class:`~.TrackingPanTool` -* :class:`PointMarker` -* :class:`SaveTool` -* :class:`SelectTool` +* :class:`~.PointMarker` +* :class:`~.SaveTool` +* :class:`~.SelectTool` - * :class:`ScatterInspector` - * :class:`SelectableLegend` + * :class:`~.ScatterInspector` + * :class:`~.SelectableLegend` * :class:`enable.tools.api.TraitsTool` -* :class:`chaco.tools.api.TraitsTool` + + * :class:`~chaco.tools.traits_tool.TraitsTool` DragTool is a base class for tools that do dragging. From 1daadab96b2bb32fd4f582169cc4fb93b4b7231b Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 11:40:33 -0500 Subject: [PATCH 48/68] DOC: Fix formatting in quickstart --- docs/source/quickstart.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index b1a056ef2..0fa81dfdb 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -66,18 +66,18 @@ You can interact with the plot in several ways: * To zoom the plot: - * Mouse wheel: scroll up to zoom in, and scroll down to zoom out (or the - reverse you're on a version of OS X with 'natural scrolling'). + * Mouse wheel: scroll up to zoom in, and scroll down to zoom out (or the + reverse you're on a version of OS X with 'natural scrolling'). - * Zoom box: Press :kbd:`z`, and then draw a box region to zoom in on. - (There is no box-based zoom out.) Press :kbd:`Ctrl-Left` and - :kbd:`Ctrl-Right` to go back and forward in your zoom box history. + * Zoom box: Press :kbd:`z`, and then draw a box region to zoom in on. + (There is no box-based zoom out.) Press :kbd:`Ctrl-Left` and + :kbd:`Ctrl-Right` to go back and forward in your zoom box history. - * Drag: hold down the right mouse button and drag the mouse up or down. Up - zooms in, and down zooms out. + * Drag: hold down the right mouse button and drag the mouse up or down. Up + zooms in, and down zooms out. - * For any of the above, press :kbd:`Escape` to reset the zoom to the - original view. + * For any of the above, press :kbd:`Escape` to reset the zoom to the + original view. * To move the legend, hold down the right mouse button inside the legend and drag it around. Note that you can move the legend outside of the plot area. From 4d60501a6895e61f57f3a5c23c3148942580b65e Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 11:40:49 -0500 Subject: [PATCH 49/68] Add Quickstart to userguide --- docs/source/user_manual/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index db79ded47..c128e4aea 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -19,7 +19,7 @@ of the Chaco API, refer to the Chaco API documentation. :maxdepth: 2 installation.rst - quickstart + ../quickstart.rst introduction.rst modules_and_classes plots.rst From f3f53ee97dd203278467856447afefdfa6f2ef8c Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 12:08:31 -0500 Subject: [PATCH 50/68] DOC: Use unique RST name for API docs --- docs/source/api/data_ranges.rst | 2 +- docs/source/api/data_sources.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/api/data_ranges.rst b/docs/source/api/data_ranges.rst index ccb5eeb04..bbb6e0aff 100644 --- a/docs/source/api/data_ranges.rst +++ b/docs/source/api/data_ranges.rst @@ -1,5 +1,5 @@ -.. _data_ranges: +.. _data_ranges_api: Data Ranges ----------- diff --git a/docs/source/api/data_sources.rst b/docs/source/api/data_sources.rst index a8383e9a2..133a5b0e8 100644 --- a/docs/source/api/data_sources.rst +++ b/docs/source/api/data_sources.rst @@ -1,5 +1,5 @@ -.. _data_sources: +.. _data_sources_api: Data Sources ------------ From 967bb84fb1afde47f2220d0691665d86b3a88cec Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Sun, 14 Jul 2019 12:23:57 -0500 Subject: [PATCH 51/68] DOC: Link to PDF version of 2008 tutorial slides --- .../{ => source/resources}/scipy08_tutorial.pdf | Bin docs/source/user_manual/chaco_tutorial.rst | 16 ++++++++-------- 2 files changed, 8 insertions(+), 8 deletions(-) rename docs/{ => source/resources}/scipy08_tutorial.pdf (100%) diff --git a/docs/scipy08_tutorial.pdf b/docs/source/resources/scipy08_tutorial.pdf similarity index 100% rename from docs/scipy08_tutorial.pdf rename to docs/source/resources/scipy08_tutorial.pdf diff --git a/docs/source/user_manual/chaco_tutorial.rst b/docs/source/user_manual/chaco_tutorial.rst index a274e49b3..ef4a10eb9 100644 --- a/docs/source/user_manual/chaco_tutorial.rst +++ b/docs/source/user_manual/chaco_tutorial.rst @@ -1248,14 +1248,14 @@ they are constructed: almost all tools need to use some capabilities Final words =========== -This concludes this tutorial. For further information, visit the -:ref:`user_guide`. You can find the examples for this tutorial in the -:file:`examples/tutorials/scipy2008/` directory of the Chaco source code. You -can browse it online in the `GitHub repository -`_ if you -don't have a local copy. They are are numbered and introduce concepts one at a -time, going from a simple line plot to building a custom overlay with its own -trait editor and reusing an existing tool from the built-in set of tools. +This concludes this tutorial. You can download :download:`a PDF version of the slides <../resources/scipy08_tutorial.pdf>` +For further information, visit the :ref:`user_guide`. You can find the examples +for this tutorial in the :file:`examples/tutorials/scipy2008/` directory of the +Chaco source code. You can browse it online in the `GitHub repository `_ +if you don't have a local copy. They are are numbered and introduce concepts +one at a time, going from a simple line plot to building a custom overlay with +its own trait editor and reusing an existing tool from the built-in set of +tools. *This tutorial is based on the "Interactive plotting with Chaco" tutorial From 19bfdddb008011a0bb5333f050706c8c86f86b48 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Wed, 24 Jul 2019 15:46:49 -0500 Subject: [PATCH 52/68] Remove duplicate entry in user_guide/index --- docs/source/user_manual/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index c128e4aea..7be036ba3 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -30,7 +30,6 @@ of the Chaco API, refer to the Chaco API documentation. basic_elements/data_ranges.rst basic_elements/plot_renderers.rst tools.rst - basic_elements/plot_renderers.rst plot_types.rst basic_elements/overlays.rst common_patterns.rst From 502023e2a2abd8163b31d79ad8cf25bf5551a8c0 Mon Sep 17 00:00:00 2001 From: Alexandre Chabot-Leclerc Date: Wed, 24 Jul 2019 15:47:00 -0500 Subject: [PATCH 53/68] FIX: Enable disabling sidebar with new theme --- docs/source/conf.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/source/conf.py b/docs/source/conf.py index aa802148f..6740bf477 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -93,12 +93,6 @@ def get_build_docset(): # Options for HTML output # ----------------------- -# When using docset browsers like Dash and Zeal the side bar is redundant. -if BUILD_DOCSET: - html_theme_options = { - 'nosidebar': 'true' - } - # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. @@ -168,6 +162,11 @@ def get_build_docset(): html_theme_path = [enthought_sphinx_theme.theme_path] html_theme = 'enthought' + # When using docset browsers like Dash and Zeal the side bar is redundant. + if BUILD_DOCSET: + html_theme_options = { + 'sidebar': 'none' + } except ImportError as exc: import warnings msg = '''Can't find Enthought Sphinx Theme, using default. @@ -181,6 +180,10 @@ def get_build_docset(): html_favicon = "et.png" html_style = 'default.css' html_theme = 'classic' + if BUILD_DOCSET: + html_theme_options = { + 'nosidebar': 'true' + } # Options for LaTeX output From c5d11d030b954f67c0e15ebf959bc0ff2f5bea5f Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 10 Mar 2021 17:37:25 -0600 Subject: [PATCH 54/68] fix broken links and typos in fundamentals.rst --- .../developer_reference/fundamentals.rst | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/docs/source/developer_reference/fundamentals.rst b/docs/source/developer_reference/fundamentals.rst index 1d5e9cb2e..2ce23c271 100644 --- a/docs/source/developer_reference/fundamentals.rst +++ b/docs/source/developer_reference/fundamentals.rst @@ -19,9 +19,9 @@ visualizations, as well as new tools, overlays and plot renderers. Traits ------ -Chaco is written using `Traits `_ which not -only provides basic type-checking of data, particularly provides attribute -change notification which is key to the interactive updating of Chaco. +Chaco is written using `Traits `_ which not +only provides basic type-checking of data, but also attribute change +notification which is key to the interactive updating of Chaco. You should be comfortable with Traits when writing any significant Chaco-based application or when extending Chaco's capabilities. @@ -29,8 +29,8 @@ Chaco-based application or when extending Chaco's capabilities. TraitsUI -------- -`TraitsUI `_ is a rapid GUI application -development library build on top of Traits. While it is not required for +`TraitsUI `_ is a rapid GUI application +development library built on top of Traits. While it is not required for the development of applications that use Chaco, it is the most natural way of providing other UI elements for your users to interact with your visualizations; or alternatively the most natural environment for writing @@ -43,14 +43,14 @@ use cases. Kiva ---- -`Kiva `_ provides an abstracted 2D drawing +`Kiva `_ provides an abstracted 2D drawing API and a number of back-end implementations. This permits writing of drawing code that can be used almost un-modified when rendering to a screen, to a vector document format (such as PDF or PostScript), or to a raster file format (such as PNG). The core object for Kiva code is the "graphics context" which represents a -a 2D drawing surface and the current state of the drawing environment. When +2D drawing surface and the current state of the drawing environment. When Chaco classes need to do any drawing they will usually be supplied with an appropriate graphics context to render into, but very occasionally (such as when saving a plot out to a file) you may want to create your own context to @@ -62,7 +62,7 @@ an understanding of Kiva. Enable ------ -`Enable `_ provides interactivity and layout +`Enable `_ provides interactivity and layout on top of the Kiva drawing library. Enable is the library that handles the interface between Chaco plots and the OS/windowing system, as well as the basic hierarchical layout and layering of visible components of a plot. @@ -82,7 +82,7 @@ code: across a number of layers, so that overlays, underlays, borders and background can be rendered in a coherent manner. -:py:class:`~enable.tools.base_tool.BaseTool` +:py:class:`~enable.base_tool.BaseTool` An object that handles a particular type of user interaction (eg. mouse events or key presses). Each tool is a state machine and so the interactions can vary depending on the state that the tool is in (eg. @@ -125,7 +125,7 @@ Data sources Examples: :py:class:`~chaco.array_data_source.ArrayDataSource`, :py:class:`~chaco.image_data.ImageData`, - :py:class:`~chaco.grid_data_source.GridData`. + :py:class:`~chaco.grid_data_source.GridDataSource`. Ranges These hold a range of displayed data values and can be updated either @@ -160,7 +160,7 @@ Axes and Grids Examples: :py:class:`~chaco.axis.PlotAxis`, :py:class:`~chaco.label_axis.LabelAxis`, - :py:class:`~chaco.grid.Grid`. + :py:class:`~chaco.grid.PlotGrid`. Pan and Zoom These are pan and zoom commands that come from user interactions, such as @@ -442,15 +442,15 @@ all common use cases. In most cases where you need to work with an :py:class:`~chaco.array_data_source.ArrayDataSource` you call :py:meth:`~chaco.array_data_source.ArrayDataSource.set_data` to change the stored data, listen to the -:py:attr:`~chaco.array_data_source.ArrayDataSource.data_changed` event trait -for when the data changes and call +:py:attr:`~chaco.abstract_data_source.AbstractDataSource.data_changed` event +trait for when the data changes and call :py:meth:`~chaco.array_data_source.ArrayDataSource.get_data` to get the current value of the data. Some users of a data source only care about the range of values that are contained in that data. In this case the data source API provides a -:py:attr:`~chaco.array_data_source.ArrayDataSource.bounds_changed` trait that -indicates that the maximum or minimum value of the data has changed, and +:py:attr:`~chaco.abstract_data_source.AbstractDataSource.bounds_changed` trait +that indicates that the maximum or minimum value of the data has changed, and those values can be efficiently retrieved via the :py:meth:`~chaco.array_data_source.ArrayDataSource.get_bounds` trait. @@ -507,7 +507,7 @@ mapping screen values back to data values, and :py:meth:`~chaco.abstract_mapper.AbstractMapper.map_data_array` for mapping a collection of screen values to data values. Perhaps most importantly, the mapper fires the -:py:attr:`~chaco.abstract_mapper.AbstractMapper.updated` +:py:attr:`~chaco.abstract_mapper.AbstractMapper.updated` event. Chaco provides a number of sub-classes of the base class for various use-cases. The most commonly used is the @@ -515,12 +515,12 @@ use-cases. The most commonly used is the dimensional linear transformation between data space and screen space, but there is also :py:class:`~chaco.log_mapper.LogMapper` which provides one dimensional logarithmic transformation, and -:py:class:`~chaco.grid_mapper.GridMapper` which provides a mapping form +:py:class:`~chaco.grid_mapper.GridMapper` which provides a mapping frrom a two dimensional data source to a point in screen (x, y) coordinates using a combination of two one dimensional mappers. For mapping of values to colors, there is the -:py:class:`~chaco.abstract_color_mapper.AbstractColorMapper` class and +:py:class:`~chaco.abstract_colormap.AbstractColorMap` class and the two sub-classes :py:class:`~chaco.color_mapper.ColorMapper` and :py:class:`~chaco.discrete_color_mapper.DiscreteColorMapper`. These have the same base API as @@ -577,7 +577,7 @@ Axes and Grids Axes and grids are auxilliary objects that draw plot decorations. They are underlays (and so inherit from -:py:class:`~chaco.abstract_underlay.AbstractOverlay`) and are +:py:class:`~chaco.abstract_overlay.AbstractOverlay`) and are usually drawn into the underlay layer of a :py:class:`~chaco.plot.Plot` but they are also able to be used as stand-alone components if needed (for example to create multi-axis plots). @@ -728,13 +728,13 @@ example, the following Enable tools may be of use: A tool which opens a TraitsUI dialog when a component is double-clicked. -:py:class:`enable.tools.pyface.base_drop_tool.BaseDropTool` +:py:class:`enable.tools.base_drop_tool.BaseDropTool` A base tool which responds to operating system drag and drop. Must be subclassed to implement methods that indicate whether a type of object can be dropped, and what to do if they are dropped. -:py:class:`enable.tools.pyface.value_drag_tool.ValueDragTool` +:py:class:`enable.tools.value_drag_tool.ValueDragTool` A base tool which changes a numeric value as the user drags the mouse. Must be subclassed to provide methods to get and set the value. There is a subclass From 0f8a0cbb6d77978c3bbdcfa4daa64283071ff7da Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 10 Mar 2021 17:47:44 -0600 Subject: [PATCH 55/68] bunch more typo and broken link fixes --- docs/source/developer_reference/index.rst | 2 +- docs/source/quickstart.rst | 4 ++-- docs/source/user_manual/chaco_tutorial.rst | 7 +++---- docs/source/user_manual/containers.rst | 2 +- docs/source/user_manual/index.rst | 2 +- docs/source/user_manual/installation.rst | 6 +++--- docs/source/user_manual/modules_and_classes.rst | 16 ++++++++-------- docs/source/user_manual/plots.rst | 8 ++++---- 8 files changed, 23 insertions(+), 24 deletions(-) diff --git a/docs/source/developer_reference/index.rst b/docs/source/developer_reference/index.rst index ad0e14595..ee22af8cb 100644 --- a/docs/source/developer_reference/index.rst +++ b/docs/source/developer_reference/index.rst @@ -9,7 +9,7 @@ Developer Reference This guide is designed to provide a guide to developers wanting to extend the capabilities of Chaco by writing new tools, overlays and plot renders. For complete details of the interfaces and base classes that you will need -to use, refer to the Chaco API documentation. +to use, refer to the Chaco :ref:`API documentation `. .. toctree:: :maxdepth: 2 diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 0fa81dfdb..aa7199f55 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -188,7 +188,7 @@ First, some imports to bring in necessary components:: The imports from :mod:`chaco` and :mod:`enable` support the creation of the plot. The imports from :mod:`traits` bring in components to embed the plot inside a Traits application. (Refer to the -`Traits documentation `_ for more details +`Traits documentation `_ for more details about building an interactive application using Traits.) Now let's create a Traits class with a view that contains only one element: a Chaco plot inside a slightly customized window:: @@ -210,7 +210,7 @@ slightly customized window:: A few options have been set to control the window containing the plot. Now, when the plot is created, we would like to pass in our data. Let's assume the data is a set of points with coordinates contained in two NumPy arrays ``x`` -and `y`. So, adding an ``__init__`` method to create the Plot object looks as +and ``y``. So, adding an ``__init__`` method to create the Plot object looks as follows:: class MyPlot(HasTraits): diff --git a/docs/source/user_manual/chaco_tutorial.rst b/docs/source/user_manual/chaco_tutorial.rst index ef4a10eb9..b0f019542 100644 --- a/docs/source/user_manual/chaco_tutorial.rst +++ b/docs/source/user_manual/chaco_tutorial.rst @@ -1252,10 +1252,9 @@ This concludes this tutorial. You can download :download:`a PDF version of the s For further information, visit the :ref:`user_guide`. You can find the examples for this tutorial in the :file:`examples/tutorials/scipy2008/` directory of the Chaco source code. You can browse it online in the `GitHub repository `_ -if you don't have a local copy. They are are numbered and introduce concepts -one at a time, going from a simple line plot to building a custom overlay with -its own trait editor and reusing an existing tool from the built-in set of -tools. +if you don't have a local copy. They are numbered and introduce concepts one at +a time, going from a simple line plot to building a custom overlay with its own +trait editor and reusing an existing tool from the built-in set of tools. *This tutorial is based on the "Interactive plotting with Chaco" tutorial diff --git a/docs/source/user_manual/containers.rst b/docs/source/user_manual/containers.rst index 47f400e60..7d0b1f06b 100644 --- a/docs/source/user_manual/containers.rst +++ b/docs/source/user_manual/containers.rst @@ -32,7 +32,7 @@ a common interface: them. :py:meth:`add`: - Append ore or more plots to the ones already present in the + Append one or more plots to the ones already present in the container. For example, this is equivalent to the code above:: container = HPlotContainer(spacing=100) diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index 7be036ba3..d3315afe3 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -7,7 +7,7 @@ User Guide =========== -This guide is designed to act as a conceptual guide to Chaco, an open-source +This guide is designed to act as a conceptual overview of Chaco, an open-source data visualization library built and maintained by Enthought, Inc. Chaco is a set of interactive visualization tools built on top of the Enable and Kiva 2D drawing libraries and designed to complement other Enthought rapid diff --git a/docs/source/user_manual/installation.rst b/docs/source/user_manual/installation.rst index 5da942d11..66e3979fe 100644 --- a/docs/source/user_manual/installation.rst +++ b/docs/source/user_manual/installation.rst @@ -7,8 +7,8 @@ Installation There are several ways to get Chaco. The easiest way is through `Enthought Deployment Manager `_ (formerly EPD) which provides environment management and package installation tools for -Windows, Linux and Mac OS. Chaco may also be available through a package manager on your -platform, such as apt on Ubuntu, yum on Redhat or +Windows, Linux and MacOS. Chaco may also be available through a package manager +on your platform, such as apt on Ubuntu, yum on Redhat or `MacPorts `_ on OS X. You can also build Chaco from its `source code `_, but because of the dependencies, the easiest way by far is to install EDM. @@ -131,7 +131,7 @@ Extension Modules ================= Chaco contains a number of C extension modules used mainly for speed. In the -current version of Chaco, there following extension modules are currently used: +current version of Chaco, the following extension modules are currently used: ``chaco/_cython_speedups.pyx`` This is a Cython extension which speeds up a number of standard operations, diff --git a/docs/source/user_manual/modules_and_classes.rst b/docs/source/user_manual/modules_and_classes.rst index 726118188..882a7178c 100644 --- a/docs/source/user_manual/modules_and_classes.rst +++ b/docs/source/user_manual/modules_and_classes.rst @@ -19,11 +19,11 @@ and overlays, and drawing various layers in the correct order. Subclasses almost never need to override or customize these base behaviors, but if they do, there are several easy extension points. -PlotComponent is a subclass of Enable :class:`~enable.api.Component`. It has its -own default drawing order. It redefines the inherited traits :attr:`draw_order` -and :attr:`draw_layer`, but it doesn't define any new traits. Therefore, you -may need to refer to the API documentation for Enable Component, -even when you have subclassed Chaco PlotComponent. +PlotComponent is a subclass of Enable :class:`~enable.component.Component`. It +has its own default drawing order. It redefines the inherited traits +:attr:`draw_order` and :attr:`draw_layer`, but it doesn't define any new +traits. Therefore, you may need to refer to the API documentation for Enable +Component, even when you have subclassed Chaco PlotComponent. If you subclass PlotComponent, you need to implement :meth:`do_layout`, if you want to size the component correctly. @@ -186,9 +186,9 @@ Tools Tools attach to a component, which gives events to the tool. -All tools subclass from Enable's :class:`~.BaseTool`, which is in turn an Enable -:class:`Interactor`. Do not try to make tools that draw: use an overlay for -that. +All tools subclass from Enable's :py:class:`~enable.base_tool.BaseTool`, which +is in turn an Enable :py:class:`~enable.interactor.Interactor`. Do not try to +make tools that draw: use an overlay for that. Some tool subclasses exist in both Enable and Chaco, because they were created first in Chaco, and then moved into Enable. diff --git a/docs/source/user_manual/plots.rst b/docs/source/user_manual/plots.rst index 63aa65a95..06e50a3c4 100644 --- a/docs/source/user_manual/plots.rst +++ b/docs/source/user_manual/plots.rst @@ -42,9 +42,9 @@ sides which do not have labels. Similarly, this means that you can use a plot in the same way that you would any other Enable component, and it will work with Enable tools. So you could -have multiple :py:class:`~chaco.plot.Plots` inside an enable +have multiple :py:class:`~chaco.plot.Plot`s inside an enable :py:class:`~enable.container.Container` or :py:class:`~chaco.canvas.Canvas` -and attache :py:class:`~enable.tools.move_tool.MoveTool` and +and attach :py:class:`~enable.tools.move_tool.MoveTool` and :py:class:`~enable.tools.resize_tool.ResizeTool` to them to allow the user complete control over the location and size of the plots. @@ -166,7 +166,7 @@ The plot factory methods are: It is up to the calling code to correctly derive the data arrays: no aggregation is performed by the plot. -:py:meth:`~chaco.plot.Plot.quiver_plot` +:py:meth:`~chaco.plot.Plot.quiverplot` The method creates a plot that places arrows at locations determined by a list of x and y points. It expects three data values: two arrays of length N for the points, and @@ -181,7 +181,7 @@ The plot factory methods are: The plot renderers for a :py:class:`~chaco.plot.Plot` instance are -available via the :py:attr:`~chaco.plot.Plot.plot` attribute, which +available via the :py:attr:`~chaco.plot.Plot.plots` attribute, which is a dictionary mapping plot names to a list of plots that match that name. Once obtained, they can have styling attributes changed or otherwise be manipulated. In particular, since the plot renderers From 36ed7f693ad634772b0b8846b622b70d446a2574 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Wed, 10 Mar 2021 18:13:13 -0600 Subject: [PATCH 56/68] more typos and links --- docs/source/developer_reference/fundamentals.rst | 4 ++-- docs/source/user_manual/modules_and_classes.rst | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/developer_reference/fundamentals.rst b/docs/source/developer_reference/fundamentals.rst index 2ce23c271..fe5d7dc70 100644 --- a/docs/source/developer_reference/fundamentals.rst +++ b/docs/source/developer_reference/fundamentals.rst @@ -520,7 +520,7 @@ a two dimensional data source to a point in screen (x, y) coordinates using a combination of two one dimensional mappers. For mapping of values to colors, there is the -:py:class:`~chaco.abstract_colormap.AbstractColorMap` class and +:py:class:`~chaco.abstract_colormap.AbstractColormap` class and the two sub-classes :py:class:`~chaco.color_mapper.ColorMapper` and :py:class:`~chaco.discrete_color_mapper.DiscreteColorMapper`. These have the same base API as @@ -738,7 +738,7 @@ example, the following Enable tools may be of use: A base tool which changes a numeric value as the user drags the mouse. Must be subclassed to provide methods to get and set the value. There is a subclass - :py:class:`enable.tools.pyface.value_drag_tool.AttributeDragTool` + :py:class:`enable.tools.value_drag_tool.AttributeDragTool` which sets the values of attributes on an object as the mouse moves, which is a common use case. diff --git a/docs/source/user_manual/modules_and_classes.rst b/docs/source/user_manual/modules_and_classes.rst index 882a7178c..38d92a2c2 100644 --- a/docs/source/user_manual/modules_and_classes.rst +++ b/docs/source/user_manual/modules_and_classes.rst @@ -193,7 +193,7 @@ make tools that draw: use an overlay for that. Some tool subclasses exist in both Enable and Chaco, because they were created first in Chaco, and then moved into Enable. -*Interface*: :class:`BaseTool` +*Interface*: :py:class:`~enable.base_tool.BaseTool` *Subclasses*: @@ -201,12 +201,12 @@ first in Chaco, and then moved into Enable. events it receives to all those tools. * :class:`~.DataPrinter`: Prints the data-space position of the point under the cursor. -* :class:`enable.tools.api.DragTool`: Enable base class +* :class:`enable.tools.drag_tool.DragTool`: Enable base class for tools that do dragging. * :class:`~chaco.tools.move_tool.MoveTool` - * :class:`enable.tools.api.ResizeTool` - * :class:`enable.tools.api.ViewportPanTool` + * :class:`enable.tools.resize_tool.ResizeTool` + * :class:`enable.tools.viewport_pan_tool.ViewportPanTool` * :class:`~.chaco.tools.drag_tool.DragTool`: Chaco base class for tools that do dragging. @@ -223,7 +223,7 @@ first in Chaco, and then moved into Enable. * :class:`~.DrawPointsTool` * :class:`~.HighlightTool` -* :class:`~.HoverTool` +* :class:`enable.tools.hover_tool.HoverTool` * :class:`~.ImageInspectorTool` * :class:`~.LineInspector` * :class:`~.PanTool` @@ -237,7 +237,7 @@ first in Chaco, and then moved into Enable. * :class:`~.ScatterInspector` * :class:`~.SelectableLegend` -* :class:`enable.tools.api.TraitsTool` +* :class:`enable.tools.traits_tool.TraitsTool` * :class:`~chaco.tools.traits_tool.TraitsTool` From 7e0c423ad14044d816a0c750c9da2b81e105ab5a Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Thu, 11 Mar 2021 13:26:59 -0600 Subject: [PATCH 57/68] more clean up, remove repeated sections --- chaco/tools/regression_lasso.py | 3 ++- .../developer_reference/fundamentals.rst | 2 +- docs/source/developer_reference/index.rst | 2 +- docs/source/quickstart.rst | 20 ------------------- docs/source/user_manual/installation.rst | 12 +++++------ 5 files changed, 9 insertions(+), 30 deletions(-) diff --git a/chaco/tools/regression_lasso.py b/chaco/tools/regression_lasso.py index 5c45646d1..8d8603df5 100644 --- a/chaco/tools/regression_lasso.py +++ b/chaco/tools/regression_lasso.py @@ -11,7 +11,8 @@ from traits.api import Any, Float, Instance # Chaco imports -from chaco.api import LassoOverlay, Label +from chaco.lasso_overlay import LassoOverlay +from chaco.label import Label from .lasso_selection import LassoSelection diff --git a/docs/source/developer_reference/fundamentals.rst b/docs/source/developer_reference/fundamentals.rst index fe5d7dc70..32d4fe67e 100644 --- a/docs/source/developer_reference/fundamentals.rst +++ b/docs/source/developer_reference/fundamentals.rst @@ -98,7 +98,7 @@ Chaco Object Model The :py:class:`~.chaco.plot.Plot` class provides a fairly simple API for creating a plot in an application, but beneath that lies a set of classes -that handle converting the numbers into the numpy arrays into pixels on the +that handle converting the numbers in the numpy arrays into pixels on the screen. Between the :py:class:`~.chaco.array_plot_data.ArrayPlotData` and the :py:class:`~.chaco.plot.Plot` are a series of classes which hold state for various operations and transformations. diff --git a/docs/source/developer_reference/index.rst b/docs/source/developer_reference/index.rst index ee22af8cb..f17868929 100644 --- a/docs/source/developer_reference/index.rst +++ b/docs/source/developer_reference/index.rst @@ -6,7 +6,7 @@ Developer Reference =================== -This guide is designed to provide a guide to developers wanting to extend +This reference is designed to provide a guide to developers wanting to extend the capabilities of Chaco by writing new tools, overlays and plot renders. For complete details of the interfaces and base classes that you will need to use, refer to the Chaco :ref:`API documentation `. diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index aa7199f55..3bc01a758 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -272,23 +272,3 @@ Where to learn more? To learn more about the power of Chaco and to build powerful rich client applications with custom visualizations, consider going over the :ref:`tutorials` section or learning from the :ref:`user_guide`. - -License -======= - -As part of the `Enthought Tool Suite `_, Chaco is -free and open source under the BSD license. - -Reporting bugs and contributing -=============================== - -Since Chaco is open source and hosted on -`Github `_, the development version can -always be checked out from Github, forked, and modified at will. When a bug is -found, please submit an issue in the -`issue page `_. If you would like to -share a bug fix or a new feature, simply submit a Pull Request from your fork. -Don't forget to specify very clearly what code to run to reproduce the issue, -what the logic of the fix is and to add one or more unit tests to ensure future -stability. The Pull Request description can and often needs to contain -screenshots of the issue or the fix. diff --git a/docs/source/user_manual/installation.rst b/docs/source/user_manual/installation.rst index 66e3979fe..cafed750a 100644 --- a/docs/source/user_manual/installation.rst +++ b/docs/source/user_manual/installation.rst @@ -54,7 +54,7 @@ for your platform and then do (from the command line) .. code-block:: console - edm install chaco pyqt + edm install chaco pyqt5 to install Chaco, PyQt, and their dependencies and then @@ -64,8 +64,8 @@ to install Chaco, PyQt, and their dependencies and then to enter the Python environment with these packages installed. -If you do not wish to use the PyQt backend then under Python 2.7 you can either -install PySide or WxPython 3. +PyQt5 is one of multiple supported backends. Other options include PyQt, +Pyside2, or wxPython. Installing Chaco from Source ============================ @@ -116,16 +116,14 @@ installation process. Developer Live Installation --------------------------- -On Python 2.7 it is possible to install a live-editable source installation +It is also possible to install a live-editable source installation using .. code-block:: console $ pip install -e . -at the top level of the Chaco source code. Unfortunately, this doesn't work -on Python 3 as Chaco currently uses 2to3 to convert the code from Python 2 to -Python 3. +at the top level of the Chaco source code. Extension Modules ================= From 31971b218bd5b25d0923436e29c272c3792f600c Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Thu, 11 Mar 2021 13:59:45 -0600 Subject: [PATCH 58/68] remove empty sections of user guide introduction (they are covered later in the user guide) --- docs/source/user_manual/introduction.rst | 53 ------------------------ 1 file changed, 53 deletions(-) diff --git a/docs/source/user_manual/introduction.rst b/docs/source/user_manual/introduction.rst index 8e2208db1..e5b83e83c 100644 --- a/docs/source/user_manual/introduction.rst +++ b/docs/source/user_manual/introduction.rst @@ -115,56 +115,3 @@ Chaco plots, and the classes that implement them: .. comment: TODO: to see how these elements collaborate to build an interactive plot, give complete low-level example of line plot with simple tool and describe the exchange of information - - -Tools -===== - - before axes (axes are overlays) - tools, overlays - - -=================== -Plotting with Chaco -=================== - -The Plot class -============== - -Plot and PlotData - -chaco.shell -=========== - -======================== -Low-level Chaco plotting -======================== - -1) create instances of PlotRenderer and add them to a Container. - There are factory functions in - plot_factory that make it simpler - -2) Create a Plot instance, use methods to create new plots of different kinds. - This automatizes 1) with an OverlayPlotContainer, i.e., it - plots multiple curves on the same element - -Plots can be rendered in a traitsui, wx, or qt window - - -.. _embedding: - -===================== -Embedding Chaco plots -===================== - -Traits UI -========= - -WxPython -======== - -Qt/PyQt -======= - - - From 22567d66ba13a39c467edc0b2cddd5f1ab467b40 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Thu, 11 Mar 2021 14:06:59 -0600 Subject: [PATCH 59/68] re-order usermanual a bit --- docs/source/user_manual/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index d3315afe3..1976959ef 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -18,20 +18,20 @@ of the Chaco API, refer to the Chaco API documentation. .. toctree:: :maxdepth: 2 + introduction.rst installation.rst ../quickstart.rst - introduction.rst modules_and_classes plots.rst containers.rst basic_elements/data_sources.rst - basic_elements/mappers.rst basic_elements/data_ranges.rst + basic_elements/mappers.rst basic_elements/plot_renderers.rst tools.rst - plot_types.rst basic_elements/overlays.rst + plot_types.rst common_patterns.rst tutorials_and_examples.rst how_do_i.rst From 6ff7f207d51845287dec884889740ea7f7994965 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Thu, 11 Mar 2021 14:15:36 -0600 Subject: [PATCH 60/68] tools and overlays are on separate pages --- .../user_manual/basic_elements/overlays.rst | 48 +++++++++++++- docs/source/user_manual/tools.rst | 63 ------------------- 2 files changed, 47 insertions(+), 64 deletions(-) diff --git a/docs/source/user_manual/basic_elements/overlays.rst b/docs/source/user_manual/basic_elements/overlays.rst index e73c781f5..e5bab7f4d 100644 --- a/docs/source/user_manual/basic_elements/overlays.rst +++ b/docs/source/user_manual/basic_elements/overlays.rst @@ -19,8 +19,11 @@ is 'transparent' by default; 3) they plot :ref:`on the 'overlay' layer ` by default. -TODO: explain how to attach an overlay to an existing plot renderer +.. TODO: explain how to attach an overlay to an existing plot renderer +============= +Core Overlays +============= There are three important classes of overlays defined in Chaco: :ref:`axes `, :ref:`legends `, and :ref:`grids `. @@ -154,3 +157,46 @@ Legend Grid ==== + +=================== +Annotation Overlays +=================== + +PointMarker +=========== + +DataBox +======= + +.. _tools/text_box_overlay: + +TextBoxOverlay +============== +The :class:`chaco.overlays.api.TextBoxOverlay` is the base class of +the overlay component of several inspector type tools (see above). It is +designed to draw a text box over the plots to display custom information. + +The rendering of the text can be customized with the following attributes: + + * :attr:`bgcolor` and :attr:`border_visible` to control the styling of the + box, + * :attr:`alpha` to control the transparency of the text box, + * :attr:`text_color` and :attr:`font` to control how the text looks like, + * :attr:`align` to control what corner of the plot the text box should + appear, + * ... + +.. note:: The overlay can also be used directly by any custom tool that needs + to display information upon an event. It should be done by + subclassing the overlay and defining a listener on the inspector's + state which will modify the overlay's :attr:`text` (and optionally + visibility) attribute(s). After a `text` update, the component's + :meth:`request_redraw` should be called. Good examples include + :class:`chaco.overlays.api.ImageInspectorOverlay`. + + +ToolTip +======= + +PlotLabel +========= diff --git a/docs/source/user_manual/tools.rst b/docs/source/user_manual/tools.rst index 89b453168..c67d3315b 100644 --- a/docs/source/user_manual/tools.rst +++ b/docs/source/user_manual/tools.rst @@ -151,66 +151,3 @@ DrawPointsTool LineSegmentTool =============== - - -================================================================ -Core Overlays -================================================================ - -Axis -==== - -Grid -==== - -Legend -====== - - -================================================================ -Annotation Overlays -================================================================ - -PointMarker -=========== - -DataBox -======= - - -.. _tools/text_box_overlay: - -TextBoxOverlay -============== -The :class:`chaco.overlays.api.TextBoxOverlay` is the base class of -the overlay component of several inspector type tools (see above). It is -designed to draw a text box over the plots to display custom information. - -The rendering of the text can be customized with the following attributes: - - * :attr:`bgcolor` and :attr:`border_visible` to control the styling of the - box, - * :attr:`alpha` to control the transparency of the text box, - * :attr:`text_color` and :attr:`font` to control how the text looks like, - * :attr:`align` to control what corner of the plot the text box should - appear, - * ... - -.. note:: The overlay can also be used directly by any custom tool that needs - to display information upon an event. It should be done by - subclassing the overlay and defining a listener on the inspector's - state which will modify the overlay's :attr:`text` (and optionally - visibility) attribute(s). After a `text` update, the component's - :meth:`request_redraw` should be called. Good examples include - :class:`chaco.overlays.api.ImageInspectorOverlay`. - - -ToolTip -======= - -PlotLabel -========= - - - - From 179f6a53f8dda9eccfca0bec86c54f2af9ad59ec Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Thu, 11 Mar 2021 14:17:42 -0600 Subject: [PATCH 61/68] tool page title fix --- docs/source/user_manual/tools.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/source/user_manual/tools.rst b/docs/source/user_manual/tools.rst index c67d3315b..edc0ad356 100644 --- a/docs/source/user_manual/tools.rst +++ b/docs/source/user_manual/tools.rst @@ -1,6 +1,6 @@ -****************** -Tools and Overlays -****************** +***** +Tools +***** ================================================================ Overview From c1eed42de7df070822f9a5046257860f1b4de073 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Thu, 11 Mar 2021 14:27:28 -0600 Subject: [PATCH 62/68] suggest pyqt5 not pyqt --- docs/source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index aa98363a3..34627bb27 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -30,7 +30,7 @@ EPD): .. code-block:: console - edm install chaco pyqt + edm install chaco pyqt5 For full installation options, including installation from source, see the :ref:`installation instructions `. From c7348323a0c469f727ebabfb403871d326eb287b Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Thu, 11 Mar 2021 14:30:37 -0600 Subject: [PATCH 63/68] remove duplicated paragraph --- docs/source/user_manual/index.rst | 8 -------- docs/source/user_manual/introduction.rst | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index 1976959ef..25c5518f6 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -7,14 +7,6 @@ User Guide =========== -This guide is designed to act as a conceptual overview of Chaco, an open-source -data visualization library built and maintained by Enthought, Inc. Chaco is -a set of interactive visualization tools built on top of the Enable and Kiva -2D drawing libraries and designed to complement other Enthought rapid -application development tools including Traits and TraitsUI. This guide -discussed many, but not all of the features of Chaco. For complete details -of the Chaco API, refer to the Chaco API documentation. - .. toctree:: :maxdepth: 2 diff --git a/docs/source/user_manual/introduction.rst b/docs/source/user_manual/introduction.rst index e5b83e83c..0a4b0b739 100644 --- a/docs/source/user_manual/introduction.rst +++ b/docs/source/user_manual/introduction.rst @@ -7,7 +7,7 @@ data visualization library built and maintained by Enthought, Inc. Chaco is a set of interactive visualization tools built on top of the Enable and Kiva 2D drawing libraries and designed to complement other Enthought rapid application development tools including Traits and TraitsUI. This guide -discussed many, but not all of the features of Chaco. For complete details +discusses many, but not all of the features of Chaco. For complete details of the Chaco API, refer to the Chaco API documentation. ============== From 4686415a91a7e2fd02748fa5897aba493cd73210 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Thu, 11 Mar 2021 14:35:46 -0600 Subject: [PATCH 64/68] have list of pages att end of intro match pages of user guide (although I'm not entirely sure we need the links in the intro at all) --- docs/source/user_manual/introduction.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/user_manual/introduction.rst b/docs/source/user_manual/introduction.rst index 0a4b0b739..511ce6795 100644 --- a/docs/source/user_manual/introduction.rst +++ b/docs/source/user_manual/introduction.rst @@ -106,8 +106,9 @@ Chaco plots, and the classes that implement them: basic_elements/data_ranges.rst basic_elements/mappers.rst basic_elements/plot_renderers.rst - plot_types.rst + tools.rst basic_elements/overlays.rst + plot_types.rst .. comment: TODO: find out how the selection features are organized From c75766b8b682231bdaf7deca2cc14e73824d1ca5 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Mon, 15 Mar 2021 13:08:47 -0500 Subject: [PATCH 65/68] move tools.rst into basic elements --- docs/source/user_manual/{ => basic_elements}/tools.rst | 0 docs/source/user_manual/index.rst | 2 +- docs/source/user_manual/introduction.rst | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename docs/source/user_manual/{ => basic_elements}/tools.rst (100%) diff --git a/docs/source/user_manual/tools.rst b/docs/source/user_manual/basic_elements/tools.rst similarity index 100% rename from docs/source/user_manual/tools.rst rename to docs/source/user_manual/basic_elements/tools.rst diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index 25c5518f6..64a3262d3 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -21,7 +21,7 @@ User Guide basic_elements/data_ranges.rst basic_elements/mappers.rst basic_elements/plot_renderers.rst - tools.rst + basic_elements/tools.rst basic_elements/overlays.rst plot_types.rst common_patterns.rst diff --git a/docs/source/user_manual/introduction.rst b/docs/source/user_manual/introduction.rst index 511ce6795..0849b9307 100644 --- a/docs/source/user_manual/introduction.rst +++ b/docs/source/user_manual/introduction.rst @@ -106,7 +106,7 @@ Chaco plots, and the classes that implement them: basic_elements/data_ranges.rst basic_elements/mappers.rst basic_elements/plot_renderers.rst - tools.rst + basic_elements/tools.rst basic_elements/overlays.rst plot_types.rst From 601c7961019a3dcd6fe38a409a2b17fe87bc84f6 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Mon, 15 Mar 2021 13:15:35 -0500 Subject: [PATCH 66/68] remove redudant tutorials_and_examples.rst from user guide. Tutorials are alrady linked from home page of docs --- docs/source/index.rst | 1 + docs/source/quickstart.rst | 7 --- docs/source/user_manual/index.rst | 1 - .../user_manual/tutorials_and_examples.rst | 45 ------------------- 4 files changed, 1 insertion(+), 53 deletions(-) delete mode 100644 docs/source/user_manual/tutorials_and_examples.rst diff --git a/docs/source/index.rst b/docs/source/index.rst index 34627bb27..0b93470dc 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -43,6 +43,7 @@ give a good overview of the capabilities of Chaco: * :ref:`Sample Plot Gallery ` * :ref:`Tutorial: Interactive plotting with Chaco ` +* :ref:`Tutorial: Using Chaco from IPython ` * Examples: - :ref:`Modeling Van del Waal's Equations ` diff --git a/docs/source/quickstart.rst b/docs/source/quickstart.rst index 3bc01a758..17ad2243f 100644 --- a/docs/source/quickstart.rst +++ b/docs/source/quickstart.rst @@ -265,10 +265,3 @@ plot and overlays that make these tools intuitive and visually appealing. with ``--gui=qt``. Make sure that the environment variable ``QT_API`` is set correctly, as described `here `_ - -Where to learn more? -==================== - -To learn more about the power of Chaco and to build powerful rich client -applications with custom visualizations, consider going over the -:ref:`tutorials` section or learning from the :ref:`user_guide`. diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index 64a3262d3..e19b485ad 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -25,7 +25,6 @@ User Guide basic_elements/overlays.rst plot_types.rst common_patterns.rst - tutorials_and_examples.rst how_do_i.rst faq.rst annotated_examples.rst diff --git a/docs/source/user_manual/tutorials_and_examples.rst b/docs/source/user_manual/tutorials_and_examples.rst deleted file mode 100644 index 2aa96ef7e..000000000 --- a/docs/source/user_manual/tutorials_and_examples.rst +++ /dev/null @@ -1,45 +0,0 @@ - -.. _tutorials: - -Tutorials and examples -====================== - -Tutorials ---------- - -* :ref:`Tutorial: Interactive plotting with Chaco ` - - This is - the main Chaco tutorial and introduces the basic concepts of - how to use Chaco and Traits UI to do basic plots, customize - layout, and add interactivity. - -* :ref:`Tutorial: Using Chaco from IPython ` - - This tutorial - explains how to use Chaco from IPython using the Chaco ``shell`` - command-line plotting interface to build plots, in - a Matlab or gnuplot-like style. - -.. the webinars section here has been removed as the hyperlinks - dont exist and/or are broken. it will be readded once we - figure out how and where to host the webinars. - - -.. tutorial_wx - -Examples --------- - -* The :ref:`annotated examples ` is a useful visual resource - presenting a set of Chaco plots together with their source code. - -* :ref:`Modeling Van del Waal's Equations ` - is a complete example of creating a data - model and then using Traits and Chaco to rapidly create interactive - plot GUIs. - -* :ref:`Creating an interactive Hyetograph ` - is an example of a hyetograph (a plot of rainfall intensity in relation - to time) application. This example introduces the ``on_trait_listener`` - decorator and uses Chaco, simple Traits views, and live GUI interaction. From 353758004924048b3f1732c216b362c064c3b367 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Mon, 15 Mar 2021 13:17:23 -0500 Subject: [PATCH 67/68] move quickstart.rst into use_manual as that is where it is now used --- docs/source/user_manual/index.rst | 2 +- docs/source/{ => user_manual}/quickstart.rst | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename docs/source/{ => user_manual}/quickstart.rst (100%) diff --git a/docs/source/user_manual/index.rst b/docs/source/user_manual/index.rst index e19b485ad..7931596d0 100644 --- a/docs/source/user_manual/index.rst +++ b/docs/source/user_manual/index.rst @@ -12,7 +12,7 @@ User Guide introduction.rst installation.rst - ../quickstart.rst + quickstart.rst modules_and_classes plots.rst containers.rst diff --git a/docs/source/quickstart.rst b/docs/source/user_manual/quickstart.rst similarity index 100% rename from docs/source/quickstart.rst rename to docs/source/user_manual/quickstart.rst From 4a31c5e23a96d8b241e9435eb6b5f3ecbb9e8be2 Mon Sep 17 00:00:00 2001 From: Aaron Ayres Date: Mon, 15 Mar 2021 13:41:13 -0500 Subject: [PATCH 68/68] make Overays page title a higherr level heading --- docs/source/user_manual/basic_elements/overlays.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/user_manual/basic_elements/overlays.rst b/docs/source/user_manual/basic_elements/overlays.rst index e5bab7f4d..5008e1af5 100644 --- a/docs/source/user_manual/basic_elements/overlays.rst +++ b/docs/source/user_manual/basic_elements/overlays.rst @@ -1,6 +1,6 @@ -========================== +########################## Overlays: Axis, Grid, etc. -========================== +########################## Overlays are elements that decorate plots, like for example axes, legends, grids, etc.