# Examples

## Data series

### Simple pairs

    import leather

    data = [
        (0, 3),
        (4, 5),
        (7, 9),
        (8, 4)
    ]

    chart = leather.Chart('Simple pairs')
    chart.add_dots(data)
    chart.to_svg('examples/charts/simple_pairs.svg')

### Table from csv.reader

Sequence row data, such as is returned by `csv.reader()` can be accessed by specifying the indices of the columns containing the `x` and `y` values.

Note that leather does not automatically convert numerical strings, such as those stored in a CSV. If you want that you’ll need to use a smarter table reader, such as agate

    import csv

    import leather

    with open('examples/realdata/gii.csv') as f:
        reader = csv.reader(f)
        next(reader)
        data = list(reader)[:10]

        for row in data:
            row[1] = float(row[1]) if row[1] is not None else None

    chart = leather.Chart('Data from CSV reader')
    chart.add_bars(data, x=1, y=0)
    chart.to_svg('examples/charts/csv_reader.svg')

### Table from csv.DictReader

Dict row data, such as is returned by `csv.DictReader` can be accessed by specifying the indices of the columns containing the `x` and `y` values.

See previous example for note on strings from CSVs.

    import csv

    import leather

    with open('examples/realdata/gii.csv') as f:
        reader = csv.DictReader(f)
        data = list(reader)[:10]

        for row in data:
            mmr = row['Maternal mortality ratio']
            row['Maternal mortality ratio'] = float(mmr) if mmr is not None else None

    chart = leather.Chart('Data from CSV reader')
    chart.add_bars(data, x='Maternal mortality ratio', y='Country')
    chart.to_svg('examples/charts/csv_dict_reader.svg')

### Custom data

Completely custom data formats are also supported via accessor functions.

    import leather

    data = [
        { 'x': 0, 'q': { 'y': [3] } },
        { 'x': 4, 'q': { 'y': [5] } },
        { 'x': 7, 'q': { 'y': [9] } },
        { 'x': 8, 'q': { 'y': [4] } }
    ]

    def x(row, index):
        return row['x']

    def y(row, index):
        return row['q']['y'][0]

    chart = leather.Chart('Line')
    chart.add_line(data, x=x, y=y)
    chart.to_svg('examples/charts/custom_data.svg')

### Multiple series

Multiple data series can be displayed on a single chart so long as they all use the same type of `Scale`.

    import leather

    data1    = [
        (0, 3),
        (4, 5),
        (7, 9),
        (8, 4)
    ]

    data2 = [
        (2, 4),
        (7, 3),
        (6, 2),
        (5, 9)
    ]

    chart = leather.Chart('Multiple series')
    chart.add_dots(data1)
    chart.add_dots(data2)
    chart.to_svg('examples/charts/multiple_series.svg')

## Shapes

### Bars

    import leather

    data = [
        (3, 'Hello'),
        (5, 'How'),
        (9, 'Are'),
        (4, 'You')
    ]

    chart = leather.Chart('Bars')
    chart.add_bars(data)
    chart.to_svg('examples/charts/bars.svg')

### Columns

    import leather

    data = [
        ('Hello', 3),
        ('How', 5),
        ('Are', 9),
        ('You', 4)
    ]

    chart = leather.Chart('Columns')
    chart.add_columns(data)
    chart.to_svg('examples/charts/columns.svg')

### Dots

    import leather

    data = [
        (0, 3),
        (4, 5),
        (7, 9),
        (8, 4)
    ]

    chart = leather.Chart('Dots')
    chart.add_dots(data)
    chart.to_svg('examples/charts/dots.svg')

### Lines

    import leather

    data = [
        (0, 3),
        (4, 5),
        (7, 9),
        (8, 4)
    ]

    chart = leather.Chart('Line')
    chart.add_line(data)
    chart.to_svg('examples/charts/lines.svg')

### Mixing shapes

You can mix different shapes for different series on the same chart.

    import leather

    line_data = [
        (0, 1),
        (2, 5),
        (4, 4),
        (8, 3)
    ]

    dot_data = [
        (1, 3),
        (2, 5),
        (6, 9),
        (10, 4)
    ]

    chart = leather.Chart('Mixed shapes')
    chart.add_line(line_data)
    chart.add_dots(dot_data)
    chart.to_svg('examples/charts/mixed_shapes.svg')

## Scales

### Linear

When using numerical data `Linear` scales are created automatically and by default. You may override the domain by adding a scale manually.

    import leather

    data = [
        (0, 3),
        (4, 5),
        (7, 9),
        (8, 4)
    ]

    chart = leather.Chart('Linear')
    chart.add_x_scale(0, 20)
    chart.add_y_scale(-10, 10)
    chart.add_line(data)
    chart.to_svg('examples/charts/linear.svg')

### Ordinal

When using text data `Ordinal` scales are created automatically and by default. It is generally not useful to override these defaults.

    import leather

    data = [
        ('Hello', 3),
        ('How', 5,),
        ('Are', 9),
        ('You', 4)
    ]

    chart = leather.Chart('Ordinal')
    chart.add_columns(data)
    chart.to_svg('examples/charts/ordinal.svg')

### Temporal

When using date/time data `Temporal` scales are created automatically and by default. You may override the domain by adding a scale manually.

    from datetime import date

    import leather

    data = [
        (date(2015, 1, 1), 3),
        (date(2015, 3, 1), 5),
        (date(2015, 6, 1), 9),
        (date(2015, 9, 1), 4)
    ]

    chart = leather.Chart('Temporal')
    chart.add_x_scale(date(2014, 1, 1), date(2016, 1, 1))
    chart.add_line(data)
    chart.to_svg('examples/charts/temporal.svg')

## Axes

### Changing tick values

You can change the list of ticks that are displayed using `Chart.add_x_axis()` and `Chart.add_y_axis()` methods. This will not adjust automatically adjust the scale, so it is possible to pick tick values that are not displayed.

    import leather

    data = [
        (0, 3),
        (4, 5),
        (7, 9),
        (8, 4)
    ]

    chart = leather.Chart('Line')
    chart.add_x_scale(0, 10)
    chart.add_x_axis(ticks=[0, 10])
    chart.add_line(data)
    chart.to_svg('examples/charts/ticks.svg')

### Customizing tick format

You can provide a tick formatter method to change how ticks are displayed using the `Chart.add_x_axis()` and `Chart.add_y_axis()` methods.

    import leather

    data = [
        (0, 3),
        (4, 5),
        (7, 9),
        (8, 4)
    ]

    def tick_formatter(value, index, tick_count):
        return '%i (%i/%i)' % (value, index, tick_count)

    chart = leather.Chart('Line')
    chart.add_x_axis(tick_formatter=tick_formatter)
    chart.add_line(data)
    chart.to_svg('examples/charts/tick_format.svg')

## Styling

### Changing theme values

Chart styles are set using a dead simple `theme` system. Leather is meant for making quick and dirty charts. It is neither expected nor recommended for user’s to customize these styles.

    import leather

    line_data = [
        (0, 1),
        (2, 5),
        (4, 4),
        (8, 3)
    ]

    dot_data = [
        (1, 3),
        (2, 5),
        (6, 9),
        (10, 4)
    ]

    leather.theme.title_font_family = 'Comic Sans MS'
    leather.theme.legend_font_family = 'Comic Sans MS'
    leather.theme.tick_font_family = 'Comic Sans MS'
    leather.theme.default_series_colors = ['#ff0000', '#00ff00']

    chart = leather.Chart('Theme')
    chart.add_line(line_data)
    chart.add_dots(dot_data)
    chart.to_svg('examples/charts/theme.svg')

### Changing series colors

More practically, individual default `Series` colors can be overriden when they are created.

    import leather

    data = [
        ('Hello', 3),
        ('How', 5),
        ('Are', 9),
        ('You', 4)
    ]

    chart = leather.Chart('Series color')
    chart.add_columns(data, fill_color='#000000')
    chart.to_svg('examples/charts/series_color.svg')

### Styling data based on value

Style attributes of individual data points can be set by value using a `style_function()`.

    import random

    import leather

    dot_data = [(random.randint(0, 250), random.randint(0, 250)) for i in range(100)]

    def colorizer(d):
        return 'rgb(%i, %i, %i)' % (d.x, d.y, 150)

    chart = leather.Chart('Colorized dots')
    chart.add_dots(dot_data, fill_color=colorizer)
    chart.to_svg('examples/charts/colorized_dots.svg')

## Chart grids

### With mixed scales

You can add charts of completely different types to a single graphic by using `Grid`.

    import leather

    data1 = [
        (0, 3),
        (4, 5),
        (7, 9),
        (8, 4)
    ]

    data2 = [
        (3, 4),
        (5, 6),
        (7, 10),
        (8, 2)
    ]

    chart1 = leather.Chart('Dots')
    chart1.add_dots(data1)

    chart2 = leather.Chart('Lines')
    chart2.add_line(data2)

    grid = leather.Grid()
    grid.add_one(chart1)
    grid.add_one(chart2)
    grid.to_svg('examples/charts/grid.svg')

### With consistent scales

A grid of charts can automatically be synchronized to a consistent view using `Lattice`.

    import leather

    data1 = [
        (0, 3),
        (4, 5),
        (7, 9),
        (8, 4)
    ]

    data2 = [
        (3, 4),
        (3, 4),
        (5, 6),
        (7, 10),
        (8, 2)
    ]

    data3 = [
        (2, 4),
        (3, 5),
        (6, 2),
        (8, 3),
        (10, 5)
    ]

    lattice = leather.Lattice()
    lattice.add_many([data1, data2, data3], titles=['First', 'Second', 'Third'])
    lattice.to_svg('examples/charts/lattice.svg')