# How to Create Line Charts Using the Outfancy LineChart Class

> Learn to create terminal line charts with Outfancy's LineChart class. This guide covers data validation, scaling, and rendering using plot() and render() methods.

- Repository: [Carlos A. Planchón/outfancy](https://github.com/carlosplanchon/outfancy)
- Tags: how-to-guide
- Published: 2026-02-26

---

**Outfancy renders terminal-based line charts through the `LineChart` class defined in [`outfancy/chart.py`](https://github.com/carlosplanchon/outfancy/blob/main/outfancy/chart.py), which manages data validation, coordinate scaling, and ASCII/Unicode rendering via the `plot()` and `render()` methods.**

The outfancy library provides a lightweight solution for visualizing data directly in terminal environments. To create line charts using the outfancy LineChart class, you instantiate the class, feed datasets via the `plot()` method, and generate output through `render()`. This workflow separates data ingestion from rendering, allowing you to customize symbols, colors, and margins without modifying the core algorithm.

## Instantiating the Chart Object

The `LineChart` class is implemented in [`outfancy/chart.py`](https://github.com/carlosplanchon/outfancy/blob/main/outfancy/chart.py) (line 11). When instantiated, it initializes storage for global extrema (`x_min`, `x_max`, `y_min`, `y_max`) and maintains a `dataset_space` list to hold plotted series. This state management enables automatic scaling across multiple data series without manual coordinate transformation.

## Ingesting Data via the plot() Method

To add data, pass a list of (x, y) tuples to the `plot(dataset)` method. Internally, `plot()` validates the input through `check_data_integrity` (chart.py line 27) and extracts coordinate lists using `get_list_of_elements`. The method automatically updates the global minima and maxima, ensuring the subsequent rendering phase can scale the chart to fit the terminal dimensions precisely.

## The Rendering Pipeline

The `render()` method orchestrates terminal output by executing a multi-stage pipeline:

- **Terminal sizing**: Queries the current terminal dimensions using `shutil.get_terminal_size()` (chart.py line 16) to compute conversion factors (`x_points_per_x_pixel`, `y_points_per_y_pixel`).
- **Drawing surface**: Instantiates a `Window` object from [`outfancy/window.py`](https://github.com/carlosplanchon/outfancy/blob/main/outfancy/window.py) (line 6) to provide a mutable matrix representing the drawing surface.
- **Coordinate transformation**: Transforms data series into screen coordinates, applying optional down-sampling via `remove_unnecesary_points_before_plotting` and gap-filling through linear `interpolation` when enabled.
- **Character selection**: When `slope_based_characters` is True, `get_char_slope` (chart.py line 50) selects line characters (`|`, `/`, `\`, `—`) based on local slope, optionally wrapped in ANSI color codes.
- **Margin assembly**: Constructs top, left, and bottom margins using `create_top_margin`, `create_left_margin`, and `create_down_margin`, which utilize `widgets.create_matrix` from [`outfancy/widgets.py`](https://github.com/carlosplanchon/outfancy/blob/main/outfancy/widgets.py) (line 56) to generate axis grids.

The assembled `Window` renders to a final string via `window.render()` and returns to the caller.

## Customization Options

The separation of concerns between `LineChart`, `Window`, and `widgets` allows extensive customization without core algorithm changes. Key configuration parameters include:

- **Point symbols**: Override default characters using the `point_list` parameter in `render()`.
- **Colorization**: Enable ANSI colors with `color=True` and specify series-specific codes via `color_number_list` (e.g., 34 for blue, 31 for red).
- **Interpolation**: Control automatic gap filling with the boolean `interpolation` parameter.
- **Slope-based rendering**: Toggle `slope_based_characters` to replace custom symbols with slope-appropriate line art.
- **Margins**: Adjust layout using `left_margin_width`, `margin_down_height`, and `margin_top_height`.

## Practical Code Examples

### Basic Single-Series Chart

Create a simple line chart by instantiating the class, plotting a dataset, and rendering:

```python
from outfancy.chart import LineChart

# 1️⃣ Create the chart object

chart = LineChart()

# 2️⃣ Provide a dataset – list of (x, y) tuples

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

# 3️⃣ Plot the data (you can call plot multiple times for more series)

chart.plot(dataset)

# 4️⃣ Render to a string and print

print(chart.render(plot_name='Demo Line Chart'))

```

### Multi-Series with Custom Symbols and Colors

Plot multiple series with distinct visual styling:

```python
from outfancy.chart import LineChart

chart = LineChart()

# Series A – blue circles

series_a = [(x, x**0.5) for x in range(0, 11)]
chart.plot(series_a)

# Series B – red triangles

series_b = [(x, 5 - 0.5 * x) for x in range(0, 11)]
chart.plot(series_b)

# Render with custom point characters and colourisation

print(
    chart.render(
        plot_name='Two Series',
        point_list=['⊙', '△'],          # custom symbols per series

        color=True,                    # enable ANSI colours

        color_number_list=[34, 31],    # 34=blue, 31=red

        interpolation=False,           # disable automatic gap filling

        slope_based_characters=False  # keep the chosen symbols unchanged

    )
)

```

### Advanced Margin and Slope Configuration

Adjust layout dimensions and enable slope-based character replacement:

```python
from outfancy.chart import LineChart

chart = LineChart()
chart.plot([(i, i*i) for i in range(0, 21)])

print(
    chart.render(
        plot_name='Quadratic',
        left_margin_width=10,
        margin_down_height=4,
        margin_top_height=2,
        slope_based_characters=True,   # let the class replace symbols by slopes

        background_point='·'           # light-dot background

    )
)

```

## Summary

- The `LineChart` class in [`outfancy/chart.py`](https://github.com/carlosplanchon/outfancy/blob/main/outfancy/chart.py) provides the primary interface for creating terminal-based line charts.
- **Data ingestion** occurs through `plot()`, which validates input via `check_data_integrity` and updates global extrema for automatic scaling.
- **Rendering** happens through `render()`, which calculates terminal-relative coordinates, manages a `Window` drawing surface from [`outfancy/window.py`](https://github.com/carlosplanchon/outfancy/blob/main/outfancy/window.py), and assembles margins using utilities from [`outfancy/widgets.py`](https://github.com/carlosplanchon/outfancy/blob/main/outfancy/widgets.py).
- Customization options include slope-based character selection (`|`, `/`, `\`, `—`), ANSI color codes, interpolation control, and adjustable margin widths.
- The architecture separates chart logic from terminal rendering, enabling flexible visual customization without core algorithm modification.

## Frequently Asked Questions

### How does LineChart handle automatic scaling?

The class tracks global minima and maxima (`x_min`, `x_max`, `y_min`, `y_max`) across all plotted series. During rendering, it queries the terminal size via `shutil.get_terminal_size()` and computes conversion factors (`x_points_per_x_pixel`, `y_points_per_y_pixel`) to map data coordinates to screen pixels automatically.

### Can I plot multiple data series on the same chart?

Yes. Call `plot(dataset)` multiple times on the same `LineChart` instance before invoking `render()`. Each call appends to the internal `dataset_space` list. You can differentiate series using the `point_list` and `color_number_list` parameters in `render()` to assign unique symbols and colors per series.

### What are slope-based characters and when should I use them?

When `slope_based_characters=True`, the `get_char_slope` method (chart.py line 50) analyzes the local slope between points and selects appropriate line drawing characters: vertical bars (`|`), forward slashes (`/`), backslashes (`\`), or horizontal em-dashes (`—`). This creates smoother visual connections between points compared to static symbols, especially for steep gradients.

### How do I disable interpolation between data points?

Pass `interpolation=False` to the `render()` method. By default, the renderer may fill gaps linearly, but setting this parameter to False ensures the chart displays only the exact data points provided without generating intermediate coordinate values.