# plasma_plots.plotly_backend

*module*

Interactive Plotly versions of the plots: ``backend="plotly"``.

Every accessor plot that draws with Matplotlib (``array.plasma.plot.*``,
``dataset.plasma.plot.*``, ``out.plot.*``) takes ``backend="plotly"``. The plot is drawn with
Matplotlib as usual, off screen, and the drawn figure is converted into a Plotly figure: the same
data, color limits, fits, reference curves, labels and layout, but with hover values, zoom and,
for animations and viewers, a slider in the browser. The two backends cannot disagree about what
they show, because there is only one drawing code path.

>>> result = phi.plasma.plot.slice(
...     coords="physical", plane="XY", t=-1, eta3=0, backend="plotly"
... )
>>> result.fig  # a plotly.graph_objects.Figure
>>> result.save("phi.html")  # a standalone page; .png/.pdf/.svg need kaleido
>>> # the default for every plot from now on
>>> plasma_plots.set_backend("plotly")

Plots return a [`PlotResult`][plasma_plots.plotting.PlotResult] with either backend (``fit_results``
and ``data`` included); animations and viewers return one too, whose figure has a slider. Plotly
is optional: ``pip install "plasma-plots[plotly]"``.

The conversion itself is also available for any Matplotlib figure drawn with the plotting
functions: [`to_plotly()`][to_plotly], [`animation_to_plotly()`][animation_to_plotly] and
[`to_plotly()`][plasma_plots.plotting.PlotResult.to_plotly].

What converts: lines, markers and scatters (also colored by a value), meshes (heatmaps on
rectilinear grids; on mapped, curvilinear grids an image of the mesh with the values under the
cursor), contour lines, quivers, colored line collections, horizontal and vertical lines and
bands, annotations, colorbars, legends, log axes, twin axes, 3-D lines and scatters, shared and
equal-aspect axes, and titles. Mathtext labels (``$\omega$``, ``$p_0$``) become Unicode and
sub/superscripts. Anything else is left out with a [`ConversionWarning`][ConversionWarning].

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L1-L1)

## plasma_plots.plotly_backend.BACKENDS

*attribute* · *module attribute*

```python
BACKENDS = ('matplotlib', 'plotly', 'tikz')
```

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L47-L47)

## plasma_plots.plotly_backend.IMAGE_PIXELS

*attribute* · *module attribute*

```python
IMAGE_PIXELS = 1200
```

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L52-L52)

## plasma_plots.plotly_backend.PX_PER_INCH

*attribute* · *module attribute*

```python
PX_PER_INCH = 100.0
```

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L48-L48)

## plasma_plots.plotly_backend.PX_PER_PT

*attribute* · *module attribute*

```python
PX_PER_PT = PX_PER_INCH / 72.0
```

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L49-L49)

## plasma_plots.plotly_backend.ConversionWarning

*class*

```python
class ConversionWarning(UserWarning)
```

Bases: `UserWarning`

A part of a Matplotlib figure that has no Plotly counterpart here and is left out.

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L63-L64)

## plasma_plots.plotly_backend.animation_to_plotly

*function*

```python
def animation_to_plotly(animation, *, labels=None, prefix: str | None = None, play: bool = True, strict: bool = False)
```

Convert a Matplotlib animation of the plotting functions into a Plotly figure with frames.

Every frame is drawn by the animation's own update function and converted like a figure, so
the frames show exactly what the Matplotlib animation shows; a slider (and Play/Pause buttons)
steps through them.

**Parameters**

- `animation` (`matplotlib.animation.FuncAnimation`) — The animation, e.g. from [`animate_slices()`][plasma_plots.plotting.animate_slices].
- `labels` (`sequence of str`) (default: `None`) — One slider label per frame. Default: the sweep values the animation was made for (for the animations of this package), else the frame numbers.
- `prefix` (`str`) (default: `None`) — Shown before the current label, e.g. ``"t = "``. Default: the sweep's name.
- `play` (`bool`) (default: `True`) — Add Play and Pause buttons. Default: ``True``.
- `strict` (`bool`) (default: `False`) — Raise instead of warning when a part of a frame cannot be converted. Default: ``False``.

**Returns**

- (`plotly.graph_objects.Figure`) — The first frame, with every frame in ``figure.frames``.

**Raises**

- `ValueError` — If the frames do not all have the same kinds of traces.

> **See Also**
>
> [`to_plotly()`][plasma_plots.plotly_backend.to_plotly] : The conversion of one figure.

**Examples**

```pycon
>>> animation = animate_slices(phi.isel(eta3=0), step=2)
>>> animation_to_plotly(animation).write_html("phi.html")
```

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L1763-L1941)

## plasma_plots.plotly_backend.get_backend

*function*

```python
def get_backend() -> str
```

Return the backend of plots that do not pass ``backend=`` themselves.

**Returns**

- (`str`) — ``"matplotlib"`` (the default), ``"plotly"`` or ``"tikz"``.

> **See Also**
>
> [`set_backend()`][plasma_plots.plotly_backend.set_backend] : Changes it.

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L103-L115)

## plasma_plots.plotly_backend.plotly_text

*function*

```python
def plotly_text(text) -> str
```

Turn a Matplotlib label into Plotly text.

Mathtext (``$\omega$``, ``$p_0$``) becomes Unicode and <sub>/<sup>; other ``<``, ``>`` and
``&`` are escaped, newlines become <br>.

**Parameters**

- `text` (`str or None`) — The label.

**Returns**

- (`str`) — The Plotly text; ``""`` for ``None``.

**Examples**

```pycon
>>> plotly_text(r"fit: $\gamma$ = 0.1")
'fit: γ = 0.1'
>>> plotly_text("$p_0$")
'p<sub>0</sub>'
```

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L415-L447)

## plasma_plots.plotly_backend.resolve_backend

*function*

```python
def resolve_backend(backend: str | None) -> str
```

The backend a plot draws with: ``backend``, or the default if it is ``None``.

Inside another plot (e.g. ``ArrayPlots.slice`` calling ``SliceView.slice``) it is always
``"matplotlib"``: the outermost call converts the finished figure.

**Parameters**

- `backend` (`('matplotlib', 'plotly', 'tikz')`) (default: `"matplotlib"`) — The backend asked for.

**Returns**

- (`str`) — ``"matplotlib"``, ``"plotly"`` or ``"tikz"``.

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L124-L142)

## plasma_plots.plotly_backend.set_backend

*function*

```python
def set_backend(backend: str) -> str
```

Set the backend of every plot that does not pass ``backend=`` itself.

**Parameters**

- `backend` (`('matplotlib', 'plotly', 'tikz')`) (default: `"matplotlib"`) — The new default (``"tikz"``: see [`plasma_plots.tikz_backend`][plasma_plots.tikz_backend]).

**Returns**

- (`str`) — The previous default, e.g. to restore it afterwards.

**Raises**

- `ValueError` — If ``backend`` is not ``"matplotlib"``, ``"plotly"`` or ``"tikz"``.

> **See Also**
>
> [`get_backend()`][plasma_plots.plotly_backend.get_backend] : The current default.

**Examples**

```pycon
>>> previous = plasma_plots.set_backend("plotly")
>>> phi.plasma.plot.slice(t=-1, eta3=0)  # a Plotly figure
>>> plasma_plots.set_backend(previous)
```

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L70-L100)

## plasma_plots.plotly_backend.to_plotly

*function*

```python
def to_plotly(figure, *, strict: bool = False)
```

Convert a drawn Matplotlib figure into an interactive Plotly figure.

**Parameters**

- `figure` (`matplotlib.figure.Figure`) — A figure drawn by one of the plotting functions (or any figure with the artists they use, see [`plasma_plots.plotly_backend`][plasma_plots.plotly_backend]).
- `strict` (`bool`) (default: `False`) — Raise instead of warning when a part of the figure cannot be converted. Default: ``False``.

**Returns**

- (`plotly.graph_objects.Figure`) — The same content: traces for the data, shapes for lines and bands spanning an axes, annotations for text, a colorbar per Matplotlib colorbar.

**Raises**

- `ImportError` — If plotly is not installed.

> **See Also**
>
> [`animation_to_plotly()`][plasma_plots.plotly_backend.animation_to_plotly] : The same for an animation.
> [`plasma_plots.plotting.PlotResult.to_plotly()`][plasma_plots.plotting.PlotResult.to_plotly] : The same for a plot result.

**Examples**

```pycon
>>> result = plot_slice(phi.isel(t=-1, eta3=0))
>>> to_plotly(result.fig).write_html("phi.html")
```

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L585-L623)

## plasma_plots.plotly_backend.viewer_to_plotly

*function*

```python
def viewer_to_plotly(viewer)
```

Convert a slider viewer into a Plotly figure with one slider.

The Matplotlib viewer has one slider per remaining dimension; a Plotly figure can combine only
one, so exactly one dimension besides the two drawn may be left with more than one value.

**Parameters**

- `viewer` (`plasma_plots.plotting.InteractiveSliceViewer`) — The viewer (drawn or not).

**Returns**

- (`PlotResult`) — The Plotly figure, with a slider over the remaining dimension (a static slice if there is none).

**Raises**

- `ValueError` — If more than one dimension remains to slide over.

> **See Also**
>
> [`animation_to_plotly()`][plasma_plots.plotly_backend.animation_to_plotly] : The conversion behind this one.

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L2042-L2100)

## plasma_plots.plotly_backend.with_backend

*function*

```python
def with_backend(method)
```

Give an accessor plot method the ``backend`` option.

The decorated method declares ``backend=None`` in its signature (so that its docs and
``help()`` show it) and draws with Matplotlib as before; with ``backend="plotly"`` or
``backend="tikz"`` (or that default, see [`set_backend()`][plasma_plots.plotly_backend.set_backend]) the decorator draws off screen
and returns the converted result instead (see [`plasma_plots.tikz_backend`][plasma_plots.tikz_backend]). An ``ax``
given with either raises ``TypeError``, since such a figure cannot be drawn into a
Matplotlib axes.

**Parameters**

- `method` (`callable`) — A method returning a ``PlotResult``, a ``FuncAnimation`` or an ``InteractiveSliceViewer``.

**Returns**

- (`callable`) — The method with the ``backend`` option.

[View source](https://github.com/max-models/plasma-plots/blob/devel/src/plasma_plots/plotly_backend.py#L155-L205)
