# Slope Chart
A slope chart (also called a dumbbell plot or connected dot plot) displays how a numeric value changes between two timepoints or conditions for a set of labelled entities. Each row shows:
- A dot at the **before** (left) value
- A dot at the **after** (right) value
- A connecting horizontal segment
By default, the segment and dots are coloured **green** when the value increases and **red** when it decreases, making trends immediately apparent at a glance.
Slope charts are a compact alternative to grouped bar charts when you want to emphasise change rather than absolute magnitude.
**Import path:** `kuva::plot::slope::{SlopePlot, SlopePoint, SlopeValueFormat}`
---
## Basic usage
```rust,no_run
use kuva::plot::slope::SlopePlot;
use kuva::backend::svg::SvgBackend;
use kuva::render::render::render_multiple;
use kuva::render::layout::Layout;
use kuva::render::plots::Plot;
let sp = SlopePlot::new()
.with_before_label("2015")
.with_after_label("2023")
.with_point("Germany", 68.2, 71.5)
.with_point("France", 70.1, 68.9)
.with_point("Italy", 65.3, 69.1)
.with_point("Spain", 72.4, 74.8)
.with_point("Poland", 58.6, 63.2)
.with_point("Netherlands", 74.3, 76.1)
.with_legend("Direction");
let plots = vec![Plot::Slope(sp)];
let layout = Layout::auto_from_plots(&plots)
.with_title("Employment Rate 2015–2023")
.with_x_label("Employment rate (%)");
let scene = render_multiple(plots, layout);
let svg = SvgBackend.render_scene(&scene);
std::fs::write("slope.svg", svg).unwrap();
```
<img src="../assets/slope/basic.svg" alt="Basic slope chart" width="560">
The legend shows "Increase" and "Decrease" entries when `color_by_direction` is enabled (the default).
---
## Showing numeric labels
Use `.with_values(true)` to render a label beside each dot showing the raw value.
```rust,no_run
# use kuva::plot::slope::SlopePlot;
# use kuva::render::plots::Plot;
let sp = SlopePlot::new()
.with_before_label("2015")
.with_after_label("2023")
.with_point("Germany", 68.2, 71.5)
// ... more rows ...
.with_values(true);
```
<img src="../assets/slope/with_values.svg" alt="Slope chart with value labels" width="560">
The default format (`SlopeValueFormat::Auto`) shows integers without a decimal point and drops trailing zeros for fractional values. Use `SlopeValueFormat::Fixed(n)` for a fixed number of decimal places or `SlopeValueFormat::Integer` to always round to the nearest integer.
---
## Bioinformatics example: gene expression
Slope charts are well-suited to before/after comparisons in differential expression data.
```rust,no_run
# use kuva::plot::slope::SlopePlot;
# use kuva::render::plots::Plot;
let sp = SlopePlot::new()
.with_before_label("Control")
.with_after_label("Treatment")
.with_point("BRCA1", 4.2, 7.8)
.with_point("TP53", 6.1, 5.4)
.with_point("MYC", 3.3, 8.9)
.with_point("EGFR", 7.5, 6.2)
.with_point("VEGFA", 2.8, 5.1)
.with_point("CDKN2A", 5.9, 4.3)
.with_legend("Direction");
```
<img src="../assets/slope/gene_expression.svg" alt="Gene expression slope chart" width="560">
---
## Uniform color
Turn off direction-based coloring with `.with_direction_colors(false)` and supply a single CSS color via `.with_color()`.
```rust,no_run
# use kuva::plot::slope::SlopePlot;
# use kuva::render::plots::Plot;
let sp = SlopePlot::new()
.with_direction_colors(false)
.with_color("steelblue")
.with_point("Germany", 68.2, 71.5)
.with_point("France", 70.1, 68.9);
```
<img src="../assets/slope/uniform_color.svg" alt="Slope chart with uniform color" width="560">
---
## Per-group color override
Supply one color per row via `.with_group_colors()`. When set, these take precedence over both direction coloring and the uniform `color` field.
```rust,no_run
# use kuva::plot::slope::SlopePlot;
# use kuva::render::plots::Plot;
let sp = SlopePlot::new()
.with_group_colors(["#e41a1c", "#377eb8", "#4daf4a"])
.with_point("A", 10.0, 15.0)
.with_point("B", 20.0, 18.0)
.with_point("C", 30.0, 35.0);
```
---
## API reference
### `SlopePlot` builder methods
| `with_point(label, before, after)` | — | Add a single row. |
| `with_points(iter)` | — | Add rows from an iterator of `(label, before, after)`. |
| `with_before_label(s)` | `None` | Column header for the left endpoint, drawn above the plot. |
| `with_after_label(s)` | `None` | Column header for the right endpoint, drawn above the plot. |
| `with_color_up(s)` | `"#2ca02c"` | Color when `after > before` (direction mode). |
| `with_color_down(s)` | `"#d62728"` | Color when `after < before` (direction mode). |
| `with_color_flat(s)` | `"#aaaaaa"` | Color when `after == before` (direction mode). |
| `with_direction_colors(bool)` | `true` | Toggle direction-based coloring. |
| `with_color(s)` | `"steelblue"` | Uniform color used when `color_by_direction = false`. |
| `with_group_colors(iter)` | `None` | Per-row color overrides. Indexed by row order. |
| `with_dot_radius(f64)` | `6.0` | Dot radius in pixels. |
| `with_line_width(f64)` | `2.5` | Connecting segment stroke width in pixels. |
| `with_dot_opacity(f64)` | `1.0` | Dot fill opacity. |
| `with_line_opacity(f64)` | `0.7` | Connecting segment stroke opacity. |
| `with_values(bool)` | `false` | Show numeric labels beside each dot. |
| `with_value_format(fmt)` | `Auto` | Format for value labels. |
| `with_legend(s)` | `None` | Enable legend; title string is passed as the trigger. |
### `SlopeValueFormat` variants
| `Auto` | Integers displayed without decimal point; trailing zeros stripped for floats. |
| `Fixed(n)` | Exactly `n` decimal places. |
| `Integer` | Round to the nearest integer (`{:.0}` format). |