# Canvas LayoutΒΆ

In Toyplot, `coordinate systems`

(including
Cartesian Coordinates, Numberline Coordinates,
Table Coordinates, and others) are used to map data values into
canvas coordinates. The coordinate system *ranges* (the area on the
canvas that they occupy) is specified when they are created. By default,
cartesian and table coordinates are sized to fill the entire canvas:

```
import numpy
y = numpy.linspace(0, 1, 20) ** 2
```

```
import toyplot
toyplot.plot(y, width=300);
```

If you need greater control over their positioning within the canvas, or
want to add multiple coordinate systems to one canvas, it’s necessary to
create the canvas and coordinate systems explicitly, then use the
coordinate systems to plot your data. For example, you can use the
*bounds* argument to specify explicit (xmin, xmax, ymin, ymax) bounds
for cartesian axes using canvas coordinates (note that canvas
coordinates always *increase* from top to bottom, unlike cartesian
coordinates):

```
canvas = toyplot.Canvas(width=600, height=300)
axes1 = canvas.cartesian(bounds=(30, 270, 30, 270))
axes1.plot(y)
axes2 = canvas.cartesian(bounds=(330, 570, 30, 270))
axes2.plot(1 - y);
```

You can also use *negative* values to specify values relative to the
right and bottom sides of the canvas, instead of the (default) left and
top sides, greatly simplifying the layout:

```
canvas = toyplot.Canvas(width=600, height=300)
axes1 = canvas.cartesian(bounds=(30, 270, 30, -30))
axes1.plot(y)
axes2 = canvas.cartesian(bounds=(-270, -30, 30, -30))
axes2.plot(1 - y);
```

Furthermore, the bounds parameters can use any Units, including “%” units, so you can use real-world units and relative dimensioning in any combination that makes sense:

```
canvas = toyplot.Canvas(width="20cm", height="2in")
axes1 = canvas.cartesian(bounds=("1cm", "5cm", "10%", "80%"))
axes1.plot(y)
axes2 = canvas.cartesian(bounds=("6cm", "-1cm", "10%", "80%"))
axes2.plot(1 - y);
```

Of course, most of the time this level of control isn’t necessary.
Instead, the *grid* argument allows us to easily position each set of
axes on a regular grid that covers the canvas. Note that you can control
the axes position on the grid in a variety of ways:

- (rows, columns, n)
- fill cell \(n\) (in left-to-right, top-to-bottom order) of an \(M \times N\) grid.

- (rows, columns, i, j)
- fill cell \(i,j\) of an \(M \times N\) grid.

- (rows, columns, i, rowspan, j, colspan)
- fill cells \([i, i + rowspan), [j, j + colspan)\) of an \(M \times N\) grid.

```
canvas = toyplot.Canvas(width=600, height=300)
axes1 = canvas.cartesian(grid=(1, 2, 0))
axes1.plot(y)
axes2 = canvas.cartesian(grid=(1, 2, 1))
axes2.plot(1 - y);
```

You can also use the *gutter* argument to control the space between
cells in the grid:

```
canvas = toyplot.Canvas(width=600, height=300)
axes1 = canvas.cartesian(grid=(1, 2, 0), gutter=25)
axes1.plot(y)
axes2 = canvas.cartesian(grid=(1, 2, 1), gutter=25)
axes2.plot(1 - y);
```

Sometimes, particularly when embedding axes to produce a
figure-within-a-figure, the *corner* argument can be used to position
axes relative to one of eight “corner” positions within the canvas. The
corner argument takes a (position, inset, width, height) tuple:

```
x = numpy.random.normal(size=100)
y = numpy.random.normal(size=100)
```

```
canvas = toyplot.Canvas(width="5in")
canvas.cartesian().plot(numpy.linspace(0, 1) ** 0.5)
canvas.cartesian(corner=("bottom-right", "1in", "1.5in", "1.5in")).scatterplot(x, y);
```

Here are all the positions supported by the *corner* argument:

```
canvas = toyplot.Canvas(width="12cm")
for position in [
"top-left",
"top",
"top-right",
"right",
"bottom-right",
"bottom",
"bottom-left",
"left",
]:
canvas.cartesian(corner=(position, "1cm", "2cm", "2cm"), label=position)
```