---
title: Custom Graph Reference
description: Complete list of available Geometries and Statistics in Custom Graph.
priority: 0.5
---

# Custom Graph Reference {#custom-graph-reference}

A complete list of Geometries and Statistics available in [Custom Graph](custom-graph). Click the help button (?) in the layer settings for details on each item.

## Geometry {#geometry}

<!-- AUTO_GENERATED:GEOM_TABLE -->
| Geometry | Description |
|----------|-------------|
| Point (Scatter) | Displays data as individual points. |
| Line | Connects data points with lines. Draws an interval band automatically when ymin/ymax are present. |
| Bar | Vertical bars for categorical data. Use Fill (not Color) to change bar color. |
| Area | Filled area under line. |
| Tile (Heatmap) | Grid of colored cells. Use Fill to set cell colors. |
| Step (Kaplan-Meier) | Stair-step line pattern. Used for Kaplan-Meier curves and ECDF. |
| Ribbon (Confidence Band) | Shaded area between ymin and ymax (confidence bands). |
| Error Bar | Error bars showing ymin to ymax range with caps. |
| Vertical Line (Reference) | Fixed vertical reference line. Configure style in the layer settings. |
| Horizontal Line (Reference) | Fixed horizontal reference line. Configure style in the layer settings. |
| Contour | Draws a curve from a series of points. Used for Cook's distance contours in regression diagnostics. |
| Density 2D | 2D kernel density estimation as contour lines. For 1D density curves, use the Density (KDE) statistic. |
| Text (Label) | Displays text labels at data points. Requires the Label aesthetic. |
| Label (Annotation) | Displays text boxes with leader lines at data points. Includes automatic collision avoidance. |
<!-- /AUTO_GENERATED:GEOM_TABLE -->

### Geometry–aesthetic compatibility {#geom-aes}

Each geometry accepts a specific set of [aesthetics](custom-graph#aesthetics---mapping-visual-elements) — visual mappings such as position, color, and size. Mapping an unsupported aesthetic to a geometry has no effect.

| Geometry | x | y | color | fill | stroke | size | shape | alpha | linetype | ymin | ymax | label |
|----------|:-:|:-:|:-----:|:----:|:------:|:----:|:-----:|:-----:|:--------:|:----:|:----:|:-----:|
| point    | **R** | **R** | • |   | • | • | • | • |   |   |   |   |
| line     | **R** | **R** | • |   |   | • |   | • | • | ○ | ○ |   |
| bar      | **R** | **R** |   | • |   |   |   | • |   |   |   |   |
| area     | **R** | **R** | • | • |   |   |   | • |   |   |   |   |
| tile     | **R** | **R** |   | • |   |   |   | • |   |   |   |   |
| step     | **R** | **R** | • |   |   | • |   | • | • |   |   |   |
| ribbon   | **R** |       | • | • |   |   |   | • |   | **R** | **R** |   |
| errorbar | **R** |       | • |   |   |   |   | • |   | **R** | **R** |   |
| vline    | • |       | • |   |   |   |   |   |   |   |   |   |
| hline    |   | •     | • |   |   |   |   |   |   |   |   |   |
| contour  | **R** | **R** | • |   |   |   |   | • |   |   |   |   |
| density2d| **R** | **R** |   |   |   |   |   | • |   |   |   |   |
| text     | **R** | **R** | • |   |   | • |   | • |   |   |   | • |
| label    | **R** | **R** | • |   |   |   |   | • |   |   |   | • |

**R** = required, ○ = optional (triggers additional behavior when present), • = supported.

- **Required** aesthetics must be mapped to a column or provided by a statistic.
- **color** vs **fill**: Bar and Tile use `fill` for their interior color, not `color`. Area accepts both — `color` for the outline and `fill` for the interior. Ribbon draws no outline; `color` sets its fill color, and Ribbon's `fill` is only used with a threshold color scale.
- **stroke**: Only Point supports `stroke`, which sets a separate outline color.
- **ymin / ymax**: Line draws an interval band when both are present. Ribbon and Errorbar require them.

## Statistics {#statistics}

<!-- AUTO_GENERATED:STAT_TABLE -->
| Statistics | Description |
|------------|-------------|
| Identity (No transformation) | Passes data through without transformation. |
| Bin (Histogram) | Groups numeric data into bins and counts occurrences. |
| Time Bin (Datetime Histogram) | Groups datetime data into time intervals. |
| Smooth (Regression) | Fits a smoothing curve with linear regression or LOESS. Optionally computes ymin/ymax as either a prediction interval for a new individual observation or a confidence interval for the mean response; Line geom draws the band automatically, Ribbon geom can also be used. |
| Count (Aggregation) | Counts occurrences for each X value. |
| Density (KDE) | Estimates probability density using kernel density estimation. |
| Summary (Aggregation) | Aggregates Y values by X using mean, sum, median, min, max, standard deviation, or variance. |
| Survival (Kaplan-Meier) | Computes Kaplan-Meier survival estimates. |
| X Mean | Calculates the mean of X values. Use with vline geom to draw a vertical reference line. |
| X Median | Calculates the median of X values. Use with vline geom to draw a vertical reference line. |
| Y Mean | Calculates the mean of Y values. Use with hline geom to draw a horizontal reference line. |
| Cumulative Sum (Pareto) | Computes cumulative sum of Y values. Combine with Sort and Bar + Line to create Pareto charts. |
| Sort (Pareto) | Sorts data by Y values in descending order. Combine with Cumulative Sum to create Pareto charts. |
| ECDF (Empirical CDF) | Computes empirical cumulative distribution function. |
| QQ (Normal Q-Q Plot) | Computes quantiles for a normal Q-Q plot, using Hazen plotting positions ((i + 0.5) / n) for the theoretical quantiles. |
| Transform (Linear) | Applies linear transformation (multiply and add) to Y values. |
<!-- /AUTO_GENERATED:STAT_TABLE -->

## Statistics parameters {#stat-params}

Each Statistic accepts a `params` object in the `stats` array passed to [`tabs.addGraphLayer` / `tabs.updateGraphLayer`](agent-api#tabsaddgraphlayertabid-layer). The tables below list the parameter name, TypeScript type, default value, and a short description for every Statistic.

```javascript
await window.midas.tabs.addGraphLayer('tab_001', {
  geom: { type: 'point' },
  stats: [
    { type: 'smooth', params: { method: 'loess', span: 0.5, interval: 'confidence' } }
  ],
  aes: { x: 'weight', y: 'mpg' }
});
```

In the type column: `A | B` means either value is accepted, `T[]` means an array of `T`, and a trailing `?` on a field name (e.g. `p?`) marks it as optional. For the full behavior of each Statistic — assumptions, limits, and worked examples — see [Custom Graph](custom-graph).

<!-- AUTO_GENERATED:STAT_PARAMS -->
### Identity (No transformation) {#stat-params-identity}

No parameters.

### Bin (Histogram) {#stat-params-bin}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `bins` | `number` | `30` | Number of bins (5-100). Ignored when binwidth is specified. |
| `binwidth` | `number` | — | Width of each bin in X-axis units. Takes precedence over bins. |
| `yScale` | `'count' \| 'density'` | `'count'` | Y-axis scale: 'count' reports bin counts, 'density' reports probability density (bin counts divided by the number of non-missing observations × binwidth, so the total area over equal-width bins equals 1). |
| `boundary` | `number` | — | Position of a bin edge in X-axis units. Bins are aligned so that one edge falls on this value. |
| `center` | `number` | — | Position of a bin center in X-axis units. Takes precedence over boundary. |

### Time Bin (Datetime Histogram) {#stat-params-timebin}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `interval` | `'auto' \| '1min' \| '5min' \| '15min' \| '30min' \| '1hour' \| '6hour' \| '12hour' \| '1day' \| '1week' \| '1month' \| '3month' \| '1year'` | `'auto'` | Time interval for bins. 'auto' chooses based on data range. |
| `yScale` | `'count' \| 'density'` | `'count'` | Y-axis scale: 'count' reports bin counts, 'density' reports probability density. |

### Smooth (Regression) {#stat-params-smooth}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `method` | `'lm' \| 'loess'` | `'loess'` | Smoothing method: 'lm' for ordinary least squares, 'loess' for locally weighted regression (tricube kernel, local linear). When a grouping aesthetic (color, fill, etc.) is mapped, a separate curve is fit per group. |
| `se` | `boolean` | `true` | When true, emits ymin/ymax for an interval band (Line geom draws the band automatically). The name follows ggplot2's se argument, but the emitted values are the interval endpoints (ymin/ymax), not a standard error. |
| `span` | `number` | `0.75` | LOESS span: fraction of points in each local neighborhood (0.1-1.0). Larger values produce smoother curves. Ignored when method is lm. |
| `level` | `number` | `0.95` | Interval level (0-1). For example, 0.95 for a 95% interval. |
| `interval` | `'confidence' \| 'prediction'` | `'prediction'` | Interval type. 'prediction' (the default) is for a new individual observation (wider, includes residual variance); 'confidence' is for the mean response (narrower). See Custom Graph for assumptions and limits. |

### Count (Aggregation) {#stat-params-count}

No parameters.

### Density (KDE) {#stat-params-density}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `bandwidth` | `number` | — | Kernel bandwidth in X-axis units. When omitted, bandwidth is selected automatically by Silverman's rule of thumb (0.9 × min(SD, IQR/1.34) × n^(-1/5)), which assumes a roughly normal shape and can oversmooth multimodal data. |
| `kernel` | `'gaussian'` | `'gaussian'` | Kernel function. Only Gaussian is supported. |
| `yScale` | `'density' \| 'count'` | `'density'` | Y-axis scale: 'density' reports probability density (total area equals 1). 'count' scales density by n × binwidth, where binwidth is computed internally (via Sturges) and may not match a co-plotted Bin layer's Y scale exactly; to overlay a histogram and a density curve on a common scale, set both layers to 'density'. |

### Summary (Aggregation) {#stat-params-summary}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `outputs` | `SummaryOutputDef[]` | `[{ fun: 'mean', to: 'y' }]` | Output definitions. Each entry is { fun, to, p?, k? }. fun selects the aggregation: 'mean', 'sum', 'median', 'min', 'max', 'sd' (sample SD, n-1 denominator), 'var' (sample variance), 'lower_se' (mean - SE, where SE = SD / sqrt(n)), 'upper_se' (mean + SE), 'lower_sd' (mean - SD), 'upper_sd' (mean + SD), 'quantile' (p-quantile with linear interpolation), 'mean_plus_k_sd' (mean + k * SD), 'mean_minus_k_sd' (mean - k * SD). to is the target position aesthetic ('y', 'ymin', or 'ymax'). p (0-1) is required for 'quantile'. k (default 1) is the SD multiplier for 'mean_plus_k_sd' / 'mean_minus_k_sd'. |
| `complete` | `boolean` | `false` | When true, fills missing X × Y combinations with 0 before aggregation. Intended for count-like aggregations; with 'mean' or 'median' the zero-fill biases the result. |

### Survival (Kaplan-Meier) {#stat-params-survival}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `confLevel` | `number` | `0.95` | Confidence level (0-1) for the pointwise confidence interval of S(t): each interval holds at a single time point and is not a simultaneous band covering the whole curve. Variance is estimated with Greenwood's formula and the interval is constructed on the log scale (so the bounds stay inside [0, 1]). |

### X Mean {#stat-params-xmean}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `label` | `string` | `'Mean: {value}'` | Label template for the reference line. {value} is replaced with the computed mean. |

### X Median {#stat-params-xmedian}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `label` | `string` | `'Median: {value}'` | Label template for the reference line. {value} is replaced with the computed median. |

### Y Mean {#stat-params-ymean}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `offset` | `number` | `0` | Number of sample SDs added to the mean; not a raw offset on the Y-axis. SD is the sample standard deviation (n-1) of the plotted Y values (computed per group when a grouping aesthetic is mapped), not a within-subgroup SD. For example, 3 draws a line at mean + 3 × SD (upper control limit, UCL), and -3 at mean − 3 × SD (lower control limit, LCL). |
| `label` | `string` | `'Mean: {value}'` | Label template for the reference line. {value} is replaced with the computed value. |

### Cumulative Sum (Pareto) {#stat-params-cumsum}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `normalize` | `boolean` | `false` | When true, scales the cumulative sum so the total equals 100 (percent). |

### Sort (Pareto) {#stat-params-sort}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `order` | `'ascending' \| 'descending'` | `'descending'` | Sort direction applied to Y values. |
| `limit` | `number` | — | Keep only the top N categories after sorting. Omit to keep all categories. |
| `displayOrder` | `'alphabetical'` | — | Controls the display order of the kept categories. Only 'alphabetical' is supported; omit to keep the sort order selected by 'order'. |

### ECDF (Empirical CDF) {#stat-params-ecdf}

No parameters.

### QQ (Normal Q-Q Plot) {#stat-params-qq}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `showReferenceLine` | `boolean` | `true` | When true, draws a reference line to assess deviation from normality. |
| `referenceLineType` | `'q1q3' \| 'identity'` | `'q1q3'` | Reference line type. 'q1q3' passes through the first and third quartiles, taken as order statistics without interpolation (so they can differ from the interpolated 'quantile' summary); use it for raw data on its original scale. 'identity' is y = x; use it only when the input is already standardized (e.g., z-scores centered at 0 and scaled by SD). |

### Transform (Linear) {#stat-params-transform}

| Name | Type | Default | Description |
|------|------|---------|-------------|
| `multiply` | `number` | `1` | Multiplier applied to Y. For example, -1 flips a histogram for a population pyramid. |
| `add` | `number` | `0` | Offset added after multiplication. |
<!-- /AUTO_GENERATED:STAT_PARAMS -->

## Palettes {#palettes}

Available values for `paletteId` in the `color` / `fill` channel of `layers[].scales`. See [Agent API](agent-api#tabsconfiguregraphtabid-config) for how to set palettes via API.

### Categorical {#palettes-categorical}

For coloring by categorical variables. Use with `scaleType: 'categorical'`.

| ID | Name | Colors |
|---|---|---|
| `midas-default` | MIDAS Default | 12 |
| `tableau10` | Tableau 10 | 10 |
| `d3-category10` | D3 Category10 | 10 |

Default: `midas-default`.

### Sequential {#palettes-sequential}

For continuous or ordinal variables. Use with `scaleType: 'sequential'`.

Also usable with `scaleType: 'categorical'` and `'threshold'`. In those modes, one color per category or threshold region is sampled at equal intervals across the full palette range.

| ID | Name | Colors |
|---|---|---|
| `blues` | Blues | 9 |
| `greens` | Greens | 9 |
| `greys` | Greys | 9 |
| `purples` | Purples | 9 |
| `ylorrd` | Yellow-Orange-Red | 9 |
| `viridis` | Viridis | 10 |
| `plasma` | Plasma | 10 |
| `inferno` | Inferno | 10 |
| `magma` | Magma | 10 |

Default: `blues`. Viridis, Plasma, Inferno, and Magma are perceptually uniform and accommodate color vision diversity.

### Diverging {#palettes-diverging}

For variables that diverge in both directions from a center value. Use with `scaleType: 'diverging'`.

Also usable with `scaleType: 'threshold'`. In that mode, one color per threshold region is sampled at equal intervals across the full palette range.

| ID | Name | Colors |
|---|---|---|
| `rdbu` | Red-Blue | 11 |
| `brbg` | Brown-Teal | 11 |

Default: `rdbu`.

### scaleType and paletteId compatibility {#palette-compatibility}

| scaleType | Accepted paletteId |
|---|---|
| `categorical` | Categorical + Sequential palettes |
| `sequential` | Sequential palettes only |
| `diverging` | Diverging palettes only |
| `threshold` | Sequential + Diverging palettes |

With `threshold`, you can also specify colors directly via `thresholdColors`. When `thresholdColors` is set, it takes precedence; when omitted, one color per threshold region is sampled at equal intervals across the `paletteId` palette.

In the Graph Builder UI, switching the scale type automatically resets an incompatible palette to that scale type's default, and the graph keeps rendering. When an incompatible `paletteId` is set directly via the API, the graph fails to render at draw time.

## Aesthetic fixed values {#aesthetic-fixed-values}

In the [Agent API](agent-api#tabsaddgraphlayertabid-layer), aesthetic properties normally map a column to a visual channel. To use a constant value instead of a column mapping:

- **Fixed color**: Set `color`, `fill`, or `stroke` to `{ fixedColor: '#FF0000' }` (any CSS color string)
- **Fixed size**: Set `size` to a positive number (e.g., `5`). Zero or negative values are ignored with a warning
- **Fixed alpha**: Set `alpha` to a number between 0 (fully transparent) and 1 (fully opaque). Out-of-range values are ignored with a warning

```javascript
await window.midas.tabs.addGraphLayer(tabId, {
  geom: { type: 'point' },
  aes: { x: 'weight', y: 'height', color: { fixedColor: '#3366CC' }, size: 8, alpha: 0.5 }
});
```

### Multiple layers with different fixed colors {#fixed-color-multi-layer}

Add each series as a separate layer with its own `fixedColor`:

```javascript
// Layer 1: actual values in blue
await window.midas.tabs.addGraphLayer(tabId, {
  geom: { type: 'line' },
  aes: { x: 'date', y: 'actual', color: { fixedColor: '#3366CC' } }
});

// Layer 2: predicted values in red
await window.midas.tabs.addGraphLayer(tabId, {
  geom: { type: 'line' },
  aes: { x: 'date', y: 'predicted', color: { fixedColor: '#CC3333' } }
});
```

### Alternative: categorical color mapping {#color-categorical-alternative}

When data is in long format (one row per observation with a grouping column), map the grouping column to `color` instead of using `fixedColor`. The palette assigns a distinct color to each group automatically.

```javascript
// Long format: each row has a "series" column ("actual" or "predicted")
await window.midas.tabs.addGraphLayer(tabId, {
  geom: { type: 'line' },
  aes: { x: 'date', y: 'value', color: 'series' }
});
```

This approach works well when the number of series is dynamic or when you want consistent palette colors across multiple graphs.

## Using labels with statistics {#label-with-stats}

When a layer uses a statistic (Count, Summary, Bin, etc.), the stat replaces original column values with aggregated results. An `aes.label` column mapping cannot reference the original data after transformation. To display stat-computed values as labels, set `geom.defaults.labelContent` instead of `aes.label`.

`labelContent` references stat output variables with the `$` prefix:

| Variable | Description |
|----------|-------------|
| `$y` | Y value after stat transformation (count, mean, etc.) |
| `$x` | X value (bin center, category name) |
| `$n` | Observation count (Bin and Count stats) |
| `$xmin` | Bin lower bound (Bin stat) |
| `$xmax` | Bin upper bound (Bin stat) |
| `$ymin` | Lower bound of interval |
| `$ymax` | Upper bound of interval |

```javascript
// Show mean values as labels on a summary chart
await window.midas.tabs.addGraphLayer(tabId, {
  geom: {
    type: 'label',
    defaults: {
      labelContent: { field: '$y', format: '.1f' }
    }
  },
  stats: [{ type: 'summary', params: { outputs: [{ fun: 'mean', to: 'y' }] } }],
  aes: { x: 'category', y: 'value' }
});
```

The `labelContent` object accepts these properties:

| Property | Type | Description |
|----------|------|-------------|
| `field` | `string` | A `$`-prefixed variable (see table above) or a column ID |
| `format` | `string` | [d3-format](https://d3js.org/d3-format) specifier (optional; auto-detected when omitted). Common patterns: `.1f` (1 decimal), `.0%` (percent, no decimals), `,.0f` (thousands separator) |
| `prefix` | `string` | Text prepended to the formatted value |
| `suffix` | `string` | Text appended to the formatted value |

## Coordinates {#coordinates}

The coordinate system is a graph-level setting, specified in the `coordinates` field of [`tabs.configureGraph`](agent-api#tabsconfiguregraphtabid-config) or [`reports.addGraph`](agent-api#reportsaddgraphreportid-config). Available values:

- `'cartesian'` (default) — Standard Cartesian coordinates
- `'flipped'` — Swaps X and Y axes. Useful for horizontal bar charts with long category labels

In the GUI, this corresponds to the **Coordinate System** section in Graph Builder. See [Custom Graph: Flipping Axes](custom-graph#flipping-axes) for a visual example.

### scales.x / scales.y in flipped coordinates {#flipped-scales}

In flipped coordinates, `aes.y` data appears on the physical X axis (horizontal) and `aes.x` data on the physical Y axis (vertical). Which axis a `scales.x` / `scales.y` setting applies to depends on the setting:

- Scale type and tick settings (`type`, `domain`, `ticks`, `zoomEnabled`) apply to the physical screen axes: `scales.x` controls the horizontal axis and `scales.y` the vertical axis, even when flipped
- `title` follows the data axis: `scales.x.title` labels the axis showing `aes.x` data (the vertical axis when flipped), and `scales.y.title` labels the axis showing `aes.y` data (the horizontal axis when flipped)

```javascript
// Horizontal bar chart: aes.x mapped to categories, aes.y to values
await window.midas.tabs.configureGraph(tabId, {
  coordinates: 'flipped',
  scales: {
    x: { title: 'Product' },      // axis for aes.x data — vertical when flipped
    y: { title: 'Sales (USD)' }   // axis for aes.y data — horizontal when flipped
  }
});
```

The secondary Y axis (`scales.y2`) is disabled in flipped coordinates.

## See also {#see-also}

- **[Advanced Graph Creation](custom-graph)** - Custom Graph usage and tutorial
- **[Creating Graphs](graph-basics)** - Graph Builder basics
