Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

DOC: re-arrange the sections in the tutorial to make it more consistent

  • Loading branch information...
commit ba3d7069aa511f2a610964baddb4e6c8a8aa99b1 1 parent 0a80951
@pberkes pberkes authored
View
BIN  docs/source/user_manual/images/data_chooser_example.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
372 docs/source/user_manual/tutorial_1.rst
@@ -23,7 +23,8 @@ for the last portion of the tutorial, but it is not required.
This tutorial demonstrates using Chaco with Traits UI, so knowledge of the
Traits framework is also helpful. We don't use very many sophisticated aspects
of Traits or Traits UI, and it is entirely possible to pick it up as you go
-through the tutorial. This tutorial applies to Enthought Tool Suite version 3.x.
+through the tutorial. This tutorial applies to Enthought Tool Suite
+version 4.x.
It's also worth pointing out that you don't *have* to use Traits UI in order to
use Chaco --- you can integrate Chaco directly with Qt or wxPython --- but for
@@ -54,12 +55,14 @@ both static plots and dynamic data visualizations that let you
interactively explore your data. Here are four basic examples of Chaco plots:
.. image:: images/tornado.png
+ :height: 300pt
This plot shows a static "tornado plot" with a categorical Y axis and continuous
X axis. The plot is resizable, but the user cannot interact or explore the data
in any way.
.. image:: images/simple_line.png
+ :height: 300pt
This is an overlaid composition of line and scatter plots with a legend. Unlike
the previous plot, the user can pan and zoom this plot, exploring the
@@ -69,12 +72,13 @@ and as they resize the plot, the legend maintains the same screen-space
separation relative to its closest corner.
.. image:: images/regression.png
+ :height: 300pt
-This example starts to demonstrate interacting with the dataset in an
+This example starts to demonstrate interacting with the data set in an
exploratory way. Whereas interactivity in the previous example was limited to
basic pan and zoom (which are fairly common in most plotting libraries), this is
an example of a more advanced interaction that allows a level of data
-exploration beyond the standard view manipuations.
+exploration beyond the standard view manipulations.
With this example, the user can select a region of data space, and a simple
line fit is applied to the selected points. The equation of the line is
@@ -85,6 +89,7 @@ but they serve an additional purpose of demonstrating how one can build complex
data-centric interactions and displays on top of the Chaco framework.
.. image:: ../images/scalar_function.png
+ :height: 350pt
This is a much more complex demonstration of Chaco's capabilities. The user
can view the cross sections of a 2-D scalar-valued function. The cross sections
@@ -118,7 +123,10 @@ MATLAB, or Matplotlib::
ytitle("sin(x)")
show()
+This creates this plot:
+
.. image:: images/script_oriented.png
+ :height: 300pt
The basic structure of this example is that we generate some data, then we call
functions to plot the data and configure the plot. There is a global concept of
@@ -132,8 +140,8 @@ does have some basic interactivity. You can pan and zoom, and even move forwards
and backwards through your zoom history. But ultimately it's a pretty static
view into the data.
-.. _line_plot_example:
+.. _line_plot_example:
Application-oriented plotting
=============================
@@ -141,7 +149,7 @@ Application-oriented plotting
The second approach to plotting can be thought of as "application-oriented", for
lack of a better term. There is definitely a bit more code, and the plot
initially doesn't look much different, but it sets us up to do more interesting
-things, as you'll see later on::
+things, as you will see later on::
from traits.api import HasTraits, Instance
from traitsui.api import View, Item
@@ -176,14 +184,15 @@ things, as you'll see later on::
This produces a plot similar to the previous script-oriented code snippet:
.. image:: images/first_plot.png
+ :height: 300pt
-So, this is our first "real" Chaco plot. We'll walk through this code and
+So, this is our first "real" Chaco plot. We will walk through this code and
look at what each bit does. This example serves as the basis for many of the
later examples.
-Understanding the first plot
-============================
+Application-oriented plotting, step by step
+===========================================
Let's start with the basics. First, we declare a class to represent our
plot, called :class:`LinePlot`::
@@ -334,6 +343,7 @@ and the name of the class from :class:`LinePlot` to :class:`ScatterPlot`. This
produces the following:
.. image:: images/scatter.png
+ :height: 300pt
Image plots
===========
@@ -378,6 +388,7 @@ right now; this is just to demonstrate how we can apply the same basic pattern
from the "first plot" example above to do other kinds of plots.
.. image:: images/image_plot.png
+ :height: 300pt
Multiple plots
@@ -421,8 +432,10 @@ array from the ArrayPlotData::
if __name__ == "__main__":
OverlappingPlot().configure_traits()
+This code generates the following plot:
.. image:: images/overlapping_plot.png
+ :height: 300pt
Containers
@@ -433,19 +446,23 @@ by side. Chaco uses various subclasses of :class:`Container` to do layout.
Horizontal containers (:class:`HPlotContainer`) place components horizontally:
.. image:: images/hplotcontainer.png
+ :height: 350pt
Vertical containers (:class:`VPlotContainer`) array component vertically:
.. image:: images/vplotcontainer.png
+ :height: 350pt
Grid container (:class:`GridPlotContainer`) lays plots out in a grid:
.. image:: images/gridcontainer.png
+ :height: 350pt
Overlay containers (:class:`OverlayPlotContainer`) just overlay plots on top of
each other:
.. image:: images/simple_line.png
+ :height: 350pt
You've actually already seen OverlayPlotContainer --- the Plot
class is actually a special subclass of OverlayPlotContainer. All of
@@ -454,6 +471,7 @@ is not a requirement of the container. For instance, the following plot shows
plots sharing only the X-axis:
.. image:: images/multiyaxis.png
+ :height: 350pt
Using a container
@@ -499,19 +517,25 @@ plot, and adds them both to the HPlotContainer object::
This produces the following plot:
.. image:: images/container_example.png
+ :height: 300pt
There are many parameters you can configure on a container, like background
color, border thickness, spacing, and padding. We insert some more
lines between lines 20 and 21 of the previous example to make the two plots
-touch in the middle::
+touch in the middle:
+
+.. code-block:: python
+
+ container = HPlotContainer(scatter, line)
+ container.spacing = 0
+
+ scatter.padding_right = 0
- container = HPlotContainer(scatter, line)
- container.spacing = 0
- scatter.padding_right = 0
- line.padding_left = 0
- line.y_axis.orientation = "right"
- self.plot = container
+ line.padding_left = 0
+ line.y_axis.orientation = "right"
+
+ self.plot = container
Something to note here is that all Chaco components have both bounds and
padding (or margin). In order to make our plots touch, we need to zero out the
@@ -521,10 +545,11 @@ line plot (which is on the right hand side) to the right side.
This produces the following:
.. image:: images/container_nospace.png
+ :height: 300pt
-Dynamically changing plot attributes
-====================================
+Dynamically changing plots
+==========================
So far, the stuff you've seen is pretty standard: building up a plot of some
sort and doing some layout on them. Now we start taking advantage
@@ -652,15 +677,17 @@ Now we do the same thing for the marker type and marker size traits::
Running the code produces an app that looks like this:
.. image:: images/traits.png
+ :height: 350pt
Depending on your platform, the color editor/swatch at the top may look different.
This is how it looks on Mac OS X. All of the controls here are "live". If you
modify them, the plot updates.
+
.. _data_chooser_example:
-Using traits: switching between data sets
-=========================================
+Dynamically changing plot content
+=================================
Traits are not just useful for tweaking visual features. For instance, you can
use them to select among several data items. This next example is based on
@@ -737,150 +764,7 @@ numpy references.
The final plot looks like this:
.. image:: images/data_chooser_example.png
- :width: 350pt
-
-
-Plot tools: adding interactivity
-================================
-
-An important feature of Chaco is that it is possible to write re-usable
-tools to interact directly with the plots.
-
-Chaco takes a modular approach to interactivity. Instead of begin hard-coded
-into specific plot types or plot renderers,
-the interaction logic is factored out into classes we call *tools*.
-An advantage of this approach is that we can add new plot types
-and container types and still use the old interactions, as long as we
-adhere to certain basic interfaces.
-
-Thus far, none of the example plots we’ve built are truly interactive,
-e.g., you cannot pan or zoom them. In the next example, we will modify
-the :ref:`LinePlot example <line_plot_example>` so that we can pan and zoom. ::
-
- from chaco.tools.api import PanTool, ZoomTool, DragZoom
-
- class ToolsExample(HasTraits):
-
- plot = Instance(Plot)
-
- traits_view = View(
- Item('plot',editor=ComponentEditor(), show_label=False),
- width=500, height=500,
- resizable=True,
- title="Chaco Plot")
-
- def __init__(self):
- x = linspace(-14, 14, 100)
- y = sin(x) * x**3
- plotdata = ArrayPlotData(x = x, y = y)
- plot = Plot(plotdata)
- plot.plot(("x", "y"), type="line", color="blue")
-
- # append tools to pan, zoom, and drag
- plot.tools.append(PanTool(plot))
- plot.tools.append(ZoomTool(plot))
- plot.tools.append(DragZoom(plot, drag_button="right"))
-
- self.plot = plot
-
-
-The example illustrates the general usage pattern: we create a new instance of
-a Tool, giving it a reference
-to the Plot, and then we append that tool to a list of tools on the plot.
-This looks a little redundant, but there is a reason why the tools
-need a reference back to the plot: the tools use methods and attributes
-of the plot
-to transform and interpret the events that it receives, as well as act
-on those events. Most tools will also modify the attributes on the plot.
-The pan and zoom tools, for instance, modify the data ranges on the
-component handed in to it.
-
-Dynamically controlling interactions
-====================================
-
-One of the nice things about having interactivity bundled up into modular
-tools is that one can dynamically control when the interaction are allowed
-and when they are not.
-
-We will modify the previous example so that we can externally control
-what interactions are available on a plot.
-
-First, we add a new trait to hold a list of names of the tools.
-This is similar to adding a list of data items
-in the :ref:`DataChooser example <data_chooser_example>`.
-However, instead of a drop-down (which is the default editor
-for an Enumeration trait), we tell Traits that we would like a
-check list by creating a :class:`CheckListEditor`, so that we will be able
-to select multiple tools. We give the CheckListEditor a list of possible
-values, which are just the names of the tools. Notice that these are
-strings, and not the tool classes themselves.
-
-.. code-block:: python
- :linenos:
-
- from enthought.traits.ui.api import CheckListEditor
-
- class ToolsExample(HasTraits):
-
- plot = Instance(Plot)
-
- tools = List(editor=CheckListEditor(values = ["PanTool",
- "SimpleZoom", "DragZoom"]))
-
-
-In the constructor, we do not add the interactive tools:
-
-.. code-block:: python
- :linenos:
-
- def __init__(self):
- x = linspace(-14, 14, 100)
- y = sin(x) * x**3
- plotdata = ArrayPlotData(x = x, y = y)
- plot = Plot(plotdata)
- plot.plot(("x", "y"), type="line", color="blue")
- self.plot = plot
-
-Instead, we write a trait event handler for the ``tools`` trait:
-
-.. code-block:: python
- :linenos:
-
- def _tools_changed(self):
- classes = [eval(class_name) for class_name in self.tools]
-
- # Remove all tools from the plot
- plot_tools = self.plot.tools
- for tool in plot_tools:
- plot_tools.remove(tool)
-
- # Create new instances for the selected tool classes
- for cls in classes:
- self.plot.tools.append(cls(self.plot))
-
-The first line, ::
-
- classes = [eval(class_name) for class_name in self.tools]
-
-converts the value of the ``tools`` trait (a string) to a Tool class. In the
-of the method, we remove all the existing tools from the plot ::
-
- # Remove all tools from the plot
- plot_tools = self.plot.tools
- for tool in plot_tools:
- plot_tools.remove(tool)
-
-and create new ones for the selected items: ::
-
- # Create new instances for the selected tool classes
- for cls in classes:
- self.plot.tools.append(cls(self.plot))
-
-
-Here is a screenshot of the final result:
-
-.. image:: images/tool_chooser_example.png
- :width: 350pt
+ :height: 300pt
.. _connected_plots_example:
@@ -958,11 +842,11 @@ or zooming one of the plots
will result in the same transformation in the other:
.. image:: images/connected_range_example.png
- :height: 250pt
+ :height: 300pt
-Plots orientation: index and value ranges
-=========================================
+Plot orientation, index and value
+=================================
We can modify the :ref:`connected plots example <connected_plots_example>`
such that the two plots only share one of the axes. The 2D data range
@@ -1003,7 +887,7 @@ scatter plot index axis (the *x* axis) produces equivalent changes in the
line plot index axis (the *y* axis):
.. image:: images/connected_index_example.png
- :height: 250pt
+ :height: 300pt
Multiple windows
@@ -1114,7 +998,150 @@ on all but the last one.
Here is a screenshot of the two windows in action:
.. image:: images/connected_windows_example.png
- :height: 300pt
+ :height: 350pt
+
+
+Plot tools: adding interactions
+===============================
+
+An important feature of Chaco is that it is possible to write re-usable
+tools to interact directly with the plots.
+
+Chaco takes a modular approach to interactivity. Instead of begin hard-coded
+into specific plot types or plot renderers,
+the interaction logic is factored out into classes we call *tools*.
+An advantage of this approach is that we can add new plot types
+and container types and still use the old interactions, as long as we
+adhere to certain basic interfaces.
+
+Thus far, none of the example plots we’ve built are truly interactive,
+e.g., you cannot pan or zoom them. In the next example, we will modify
+the :ref:`LinePlot example <line_plot_example>` so that we can pan and zoom. ::
+
+ from chaco.tools.api import PanTool, ZoomTool, DragZoom
+
+ class ToolsExample(HasTraits):
+
+ plot = Instance(Plot)
+
+ traits_view = View(
+ Item('plot',editor=ComponentEditor(), show_label=False),
+ width=500, height=500,
+ resizable=True,
+ title="Chaco Plot")
+
+ def __init__(self):
+ x = linspace(-14, 14, 100)
+ y = sin(x) * x**3
+ plotdata = ArrayPlotData(x = x, y = y)
+ plot = Plot(plotdata)
+ plot.plot(("x", "y"), type="line", color="blue")
+
+ # append tools to pan, zoom, and drag
+ plot.tools.append(PanTool(plot))
+ plot.tools.append(ZoomTool(plot))
+ plot.tools.append(DragZoom(plot, drag_button="right"))
+
+ self.plot = plot
+
+
+The example illustrates the general usage pattern: we create a new instance of
+a Tool, giving it a reference
+to the Plot, and then we append that tool to a list of tools on the plot.
+This looks a little redundant, but there is a reason why the tools
+need a reference back to the plot: the tools use methods and attributes
+of the plot
+to transform and interpret the events that it receives, as well as act
+on those events. Most tools will also modify the attributes on the plot.
+The pan and zoom tools, for instance, modify the data ranges on the
+component handed in to it.
+
+Dynamically controlling interactions
+====================================
+
+One of the nice things about having interactivity bundled up into modular
+tools is that one can dynamically control when the interaction are allowed
+and when they are not.
+
+We will modify the previous example so that we can externally control
+what interactions are available on a plot.
+
+First, we add a new trait to hold a list of names of the tools.
+This is similar to adding a list of data items
+in the :ref:`DataChooser example <data_chooser_example>`.
+However, instead of a drop-down (which is the default editor
+for an Enumeration trait), we tell Traits that we would like a
+check list by creating a :class:`CheckListEditor`, so that we will be able
+to select multiple tools. We give the CheckListEditor a list of possible
+values, which are just the names of the tools. Notice that these are
+strings, and not the tool classes themselves.
+
+.. code-block:: python
+ :linenos:
+
+ from enthought.traits.ui.api import CheckListEditor
+
+ class ToolsExample(HasTraits):
+
+ plot = Instance(Plot)
+
+ tools = List(editor=CheckListEditor(values = ["PanTool",
+ "SimpleZoom", "DragZoom"]))
+
+
+In the constructor, we do not add the interactive tools:
+
+.. code-block:: python
+ :linenos:
+
+ def __init__(self):
+ x = linspace(-14, 14, 100)
+ y = sin(x) * x**3
+ plotdata = ArrayPlotData(x = x, y = y)
+ plot = Plot(plotdata)
+ plot.plot(("x", "y"), type="line", color="blue")
+ self.plot = plot
+
+Instead, we write a trait event handler for the ``tools`` trait:
+
+.. code-block:: python
+ :linenos:
+
+ def _tools_changed(self):
+ classes = [eval(class_name) for class_name in self.tools]
+
+ # Remove all tools from the plot
+ plot_tools = self.plot.tools
+ for tool in plot_tools:
+ plot_tools.remove(tool)
+
+ # Create new instances for the selected tool classes
+ for cls in classes:
+ self.plot.tools.append(cls(self.plot))
+
+The first line, ::
+
+ classes = [eval(class_name) for class_name in self.tools]
+
+converts the value of the ``tools`` trait (a string) to a Tool class. In the
+of the method, we remove all the existing tools from the plot ::
+
+ # Remove all tools from the plot
+ plot_tools = self.plot.tools
+ for tool in plot_tools:
+ plot_tools.remove(tool)
+
+and create new ones for the selected items: ::
+
+ # Create new instances for the selected tool classes
+ for cls in classes:
+ self.plot.tools.append(cls(self.plot))
+
+
+Here is a screenshot of the final result:
+
+.. image:: images/tool_chooser_example.png
+ :width: 350pt
Writing a custom tool
@@ -1187,7 +1214,7 @@ a mouse move event looks for a ``mousedown_mouse_move`` callback method.
We can write an implementation for it that maps the screen coordinates in
data space:
-.. code-block:
+.. code-block:: python
def mousedown_mouse_move(self, event):
print "Data:", self.component.map_data((event.x, event.y))
@@ -1200,3 +1227,10 @@ they are constructed: almost all tools need to use some capabilities
.. image:: images/custom_tool_stateful_example.png
:height: 250pt
+
+
+Final words
+===========
+
+This concludes this tutorial. For further information, please refer
+to the :ref:`Resources` page, or visit the :ref:`User guide`.
Please sign in to comment.
Something went wrong with that request. Please try again.