# Layer plots

To “layer” or “stack” multiple plots on top of each other, use the `layer` function. This is useful if you want to combine multiple plots of different types into a single visualization, such as a [scatter plot](scatter.md) and a [line plot](line.md). This is distinct from [sub-plots](sub-plots.md), which present multiple plots side-by-side. By default, the stacked plot will use the layout (axis labels, axis ranges, and title) from the last plot in the sequence. The `which_layout` parameter can be used to specify which plot’s layout should be used.

## Examples

### Layering two plots

Use a [candlestick plot](candlestick.md) and a [line plot](line.md) for two different perspectives on the same data.

```python order=financial_plot,dog_prices,dog_ohlc,stocks
import deephaven.plot.express as dx
import deephaven.agg as agg
stocks = dx.data.stocks()  # import the example stock market data set

# select only DOG prices and compute ohlc
dog_prices = stocks.where("Sym == `DOG`")
dog_ohlc = dog_prices.update_view(
    "BinnedTimestamp = lowerBin(Timestamp, 'PT1m')"
).agg_by(
    [
        agg.first("Open=Price"),
        agg.max_("High=Price"),
        agg.min_("Low=Price"),
        agg.last("Close=Price"),
    ],
    by="BinnedTimestamp",
)

# layer a line plot and a candlestick plot by passing both to layer()
financial_plot = dx.layer(
    dx.line(
        dog_prices, x="Timestamp", y="Price"),
    dx.candlestick(
        dog_ohlc, x="BinnedTimestamp",
        open="Open", high="High", low="Low", close="Close")
)
```

## API Reference

Layers the provided figures. Be default, the layouts are sequentially
applied, so the layouts of later figures will override the layouts of early
figures.

**Returns:** `DeephavenFigure` The layered chart

<ParamTable param={{"module_name": "deephaven.plot.express.", "name": "layer", "parameters": [{"name": "*figs", "type": "DeephavenFigure | Figure", "description": "The charts to layer"}, {"name": "which_layout", "type": "int | None", "description": "None to layer layouts, or an index of which arg to take the layout from. Currently only valid if domains are not specified.", "default": "None"}, {"name": "specs", "type": "list[LayerSpecDict] | None", "description": "A list of dictionaries that contains keys of \"x\" and \"y\" that have values that are lists of two floats from 0 to 1. The chart that corresponds with a domain will be resized to that domain. Either x or y can be excluded if only resizing on one axis. Can also specify \"xaxis_update\" or \"yaxis_update\" with a dictionary value to update all axes with that dict. Can also specify \"matched_xaxis\" or \"matched_yaxis\" to add this figure to a match group. All figures with the same value of this group will have matching axes.", "default": "None"}, {"name": "unsafe_update_figure", "type": "Callable", "description": "An update function that takes a plotly figure as an argument and optionally returns a plotly figure. If a figure is not returned, the plotly figure passed will be assumed to be the return value. Used to add any custom changes to the underlying plotly figure. Note that the existing data traces should not be removed. This may lead to unexpected behavior if traces are modified in a way that break data mappings.", "default": "<function default_callback>"}, {"name": "title", "type": "str | None", "description": "Overall title to set for the figure. If an empty string, no overall title is shown.", "default": "None"}, {"name": "on_click", "type": "Callable[..., bool | None] | None", "description": "A callback function that is called when a point is clicked. The function receives a dict with 'points' (list of clicked point data) and 'modifiers' (keyboard state). On hierarchical charts (sunburst, treemap, icicle), return False to prevent drill-down. The return value is ignored on other chart types.", "default": "None"}, {"name": "on_press", "type": "Callable[..., bool | None] | None", "description": "Alias for on_click.", "default": "None"}, {"name": "on_double_click", "type": "Callable[..., None] | None", "description": "A callback function that is called on double-click. The function receives a dict with 'modifiers' (keyboard state). Fires in zoom/pan mode only; in select mode, on_deselect fires instead.", "default": "None"}, {"name": "on_double_press", "type": "Callable[..., None] | None", "description": "Alias for on_double_click.", "default": "None"}, {"name": "on_selected", "type": "Callable[..., None] | None", "description": "A callback function that is called when a box or lasso selection completes. The function receives a dict with 'points' (list of selected point data), 'range' (for box select), and 'modifiers'.", "default": "None"}, {"name": "on_deselect", "type": "Callable[..., None] | None", "description": "A callback function that is called when the selection is cleared (e.g., by double-clicking on an empty area).", "default": "None"}, {"name": "on_relayout", "type": "Callable[..., None] | None", "description": "A callback function that is called when the chart layout changes due to user interaction (pan, zoom, axis reset, etc.). The function receives a dict of the layout keys that changed.", "default": "None"}, {"name": "on_legend_click", "type": "Callable[..., bool | None] | None", "description": "A callback function that is called when a legend item is clicked. Return False to prevent the default trace visibility toggle. Return True or None to allow it.", "default": "None"}, {"name": "on_legend_double_click", "type": "Callable[..., bool | None] | None", "description": "A callback function that is called when a legend item is double-clicked. Return False to prevent the default isolate/show-all toggle. Return True or None to allow it.", "default": "None"}, {"name": "on_click_annotation", "type": "Callable[..., None] | None", "description": "A callback function that is called when an annotation is clicked. The function receives a dict with 'index', 'annotation', and 'modifiers'.", "default": "None"}, {"name": "on_web_gl_context_lost", "type": "Callable[..., None] | None", "description": "A callback function that is called when the WebGL rendering context is lost (e.g., GPU reclaims resources).", "default": "None"}]}} />
