# plasma_plots.fieldline_plots

*module*

Plots of traced field lines, from [`plasma_plots.fieldlines`][plasma_plots.fieldlines].

Poincaré sections, projections, footprints, connection lengths, profiles along the lines, and
unfolded flux surfaces with field lines.

Each returns a [`PlotResult`][plasma_plots.plotting.PlotResult], whose ``data`` holds what was drawn.

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

## plasma_plots.fieldline_plots.LINE_CLASS_COLORS

*attribute* · *module attribute*

```python
LINE_CLASS_COLORS = {'surface': 'C0', 'island': 'C3', 'chaotic': '0.55'}
```

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

## plasma_plots.fieldline_plots.PLANES_2D

*attribute* · *module attribute*

```python
PLANES_2D = {'RZ': ('R', 'z'), 'XY': ('x', 'y'), 'XZ': ('x', 'z'), 'YZ': ('y', 'z')}
```

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

## plasma_plots.fieldline_plots.plot_along_field_lines

*function*

```python
def plot_along_field_lines(samples: xr.DataArray, *, k_parallel: bool = False, method: str = 'fft', max_lines: int = 12, ax=None, title: str | None = None)
```

A field along traced field lines, one curve per line against the arc length.

**Parameters**

- `samples` (`xarray.DataArray`) — The field along the lines, from [`sample_along()`][plasma_plots.fieldlines.sample_along], over ``(s, line)`` (every other dimension selected).
- `k_parallel` (`bool`) (default: `False`) — Estimate each line's parallel wavenumber (see [`parallel_wavenumber()`][plasma_plots.fieldlines.parallel_wavenumber]) and put it in the legend. Default: False.
- `method` (`('fft', 'crossings')`) (default: `"fft"`) — The estimate's method. Default: ``"fft"``.
- `max_lines` (`int`) (default: `12`) — Draw only the first ``max_lines`` lines. Default: 12.
- `ax` (`matplotlib.axes.Axes`) (default: `None`) — The axes to draw into. Default: a new figure.
- `title` (`str`) (default: `None`) — The title. Default: the samples' label.

**Returns**

- (`PlotResult`) — The figure, the axes and the lines; with ``k_parallel``, ``data["k_parallel"]`` holds the estimates over ``line``.

**Raises**

- `ValueError` — If dimensions other than ``s`` and ``line`` remain.

> **See Also**
>
> [`plasma_plots.fieldlines.sample_along()`][plasma_plots.fieldlines.sample_along] : The samples.

**Examples**

```pycon
>>> plot_along_field_lines(
...     sample_along(phi.isel(t=-1), lines), k_parallel=True
... )
```

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

## plasma_plots.fieldline_plots.plot_connection_length

*function*

```python
def plot_connection_length(lines: xr.Dataset, *, log: bool = True, cmap=None, s: float = 14.0, ax=None, title: str | None = None)
```

The connection length of each field line over its seed.

Seeds that form a grid of two coordinates (a dict of two arrays in
[`trace_field_lines()`][plasma_plots.fieldlines.trace_field_lines]) give a map over them; other seeds a
scatter over their two varying coordinates (the radial and poloidal ones by default).

**Parameters**

- `lines` (`xarray.Dataset`) — The lines of [`trace_field_lines()`][plasma_plots.fieldlines.trace_field_lines], traced with ``direction="both"`` for the full connection length.
- `log` (`bool`) (default: `True`) — Show the decimal logarithm of the connection length. Default: True.
- `cmap` (`str or matplotlib colormap`) (default: `None`) — The colormap. Default: ``"viridis"``.
- `s` (`float`) (default: `14.0`) — The marker size of a scatter, in points². Default: 14.
- `ax` (`matplotlib.axes.Axes`) (default: `None`) — The axes to draw into. Default: a new figure.
- `title` (`str`) (default: `None`) — The title. Default: ``"connection length"``.

**Returns**

- (`PlotResult`) — The figure, the axes and the mesh or scatter; ``data["connection_length"]`` holds the values over the seeds.

**Raises**

- `ValueError` — If no line left the grid.

> **See Also**
>
> [`plasma_plots.fieldlines.seed_grid()`][plasma_plots.fieldlines.seed_grid] : The map's values.
> [`plot_footprint()`][plasma_plots.fieldline_plots.plot_footprint] : Where the lines leave.

**Examples**

```pycon
>>> plot_connection_length(edge)
```

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

## plasma_plots.fieldline_plots.plot_field_lines

*function*

```python
def plot_field_lines(lines: xr.Dataset, *, plane: str = 'RZ', color_by: str | None = 'line', max_lines: int = 200, cmap=None, boundary: xr.DataArray | None = None, ax=None, title: str | None = None)
```

Traced field lines projected onto a plane, or in 3-D.

**Parameters**

- `lines` (`xarray.Dataset`) — The lines of [`trace_field_lines()`][plasma_plots.fieldlines.trace_field_lines].
- `plane` (`('RZ', 'XY', 'XZ', 'YZ', '3d')`) (default: `"RZ"`) — The projection: the poloidal plane ``R``-``z`` (default), a Cartesian plane, or a 3-D axes.
- `color_by` (`('line', 'iota', 'absB', 's', None)`) (default: `"line"`) — One color per line (cycling), each line colored by its rotational transform, or each line colored along its path by ``|B|`` or the arc length ``s`` (with a color bar; 2-D planes only); ``None`` for one color. Default: ``"line"``.
- `max_lines` (`int`) (default: `200`) — Draw only the first ``max_lines`` lines. Default: 200.
- `cmap` (`str or matplotlib colormap`) (default: `None`) — The colormap. Default: ``"viridis"``.
- `boundary` (`xarray.DataArray`) (default: `None`) — A field with physical coordinates whose outermost surface is drawn in the ``RZ`` plane.
- `ax` (`matplotlib.axes.Axes`) (default: `None`) — The axes to draw into (a 3-D axes for ``plane="3d"``). Default: a new figure.
- `title` (`str`) (default: `None`) — The title. Default: the lines' label.

**Returns**

- (`PlotResult`) — The figure, the axes and the drawn lines.

**Raises**

- `ValueError` — If ``plane`` or ``color_by`` is unknown.

> **See Also**
>
> [`plot_poincare()`][plasma_plots.fieldline_plots.plot_poincare] : The punctures of a poloidal plane.

**Examples**

```pycon
>>> plot_field_lines(lines, plane="RZ", color_by="iota")
>>> plot_field_lines(lines, plane="3d", max_lines=20)
```

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

## plasma_plots.fieldline_plots.plot_footprint

*function*

```python
def plot_footprint(lines: xr.Dataset, *, log: bool = True, s: float = 14.0, cmap=None, ax=None, title: str | None = None)
```

Where open field lines leave the grid, over the two angles, colored by connection length.

**Parameters**

- `lines` (`xarray.Dataset`) — The lines of [`trace_field_lines()`][plasma_plots.fieldlines.trace_field_lines] (or their [`footprint()`][plasma_plots.fieldlines.footprint]), traced with ``direction="both"`` for the full connection length.
- `log` (`bool`) (default: `True`) — Color by the decimal logarithm of the connection length. Default: True.
- `s` (`float`) (default: `14.0`) — The marker size, in points². Default: 14.
- `cmap` (`str or matplotlib colormap`) (default: `None`) — The colormap. Default: ``"viridis"``.
- `ax` (`matplotlib.axes.Axes`) (default: `None`) — The axes to draw into. Default: a new figure.
- `title` (`str`) (default: `None`) — The title. Default: how many lines left the grid.

**Returns**

- (`PlotResult`) — The figure, the axes and the scatter; ``data["footprint"]`` holds the exit points.

> **See Also**
>
> [`plot_connection_length()`][plasma_plots.fieldline_plots.plot_connection_length] : The connection lengths over the seeds.
> [`plasma_plots.fieldlines.footprint()`][plasma_plots.fieldlines.footprint] : The exit points.

**Examples**

```pycon
>>> plot_footprint(edge)
```

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

## plasma_plots.fieldline_plots.plot_poincare

*function*

```python
def plot_poincare(section: xr.Dataset, *, coords: str = 'physical', color_by: str | None = 'line', s: float = 3.0, cmap=None, islands_: bool = False, boundary: xr.DataArray | None = None, max_lines: int | None = None, ax=None, title: str | None = None, **classification)
```

A Poincaré plot: the punctures of a poloidal plane by traced field lines.

Each line's punctures trace a closed curve on a flux surface, a chain of ``m`` loops in an
island, and a cloud where the field is chaotic.

**Parameters**

- `section` (`xarray.Dataset`) — A [`poincare_section()`][plasma_plots.fieldlines.poincare_section], or the lines of [`trace_field_lines()`][plasma_plots.fieldlines.trace_field_lines] (cut at their section).
- `coords` (`('physical', 'logical')`) (default: `"physical"`) — Draw ``R`` against ``z`` (physical), or the poloidal angle against the radial logical coordinate (logical). Default: ``"physical"``.
- `color_by` (`('line', 'iota', 'classification', 'connection_length', None)`) (default: `"line"`) — One color per line (cycling), a color bar over each line's rotational transform or connection length, or the classes of [`classify_field_lines()`][plasma_plots.fieldlines.classify_field_lines] (surface, island, chaotic) with a legend; ``None`` for one color. Default: ``"line"``.
- `s` (`float`) (default: `3.0`) — The marker size, in points². Default: 3.
- `cmap` (`str or matplotlib colormap`) (default: `None`) — The colormap of ``"iota"`` and ``"connection_length"``. Default: ``"viridis"``.
- `islands_` (`bool`) (default: `False`) — Find the island chains ([`islands()`][plasma_plots.fieldlines.islands]) and label each with its ``n/m`` and width near one of its O-points. Default: False.
- `boundary` (`xarray.DataArray`) (default: `None`) — A field with physical coordinates whose outermost surface is drawn at the section (physical coordinates only).
- `max_lines` (`int`) (default: `None`) — Draw only the first ``max_lines`` lines. Default: all.
- `ax` (`matplotlib.axes.Axes`) (default: `None`) — The axes to draw into. Default: a new figure.
- `title` (`str`) (default: `None`) — The title. Default: the section's label and angle.
- `**classification` (default: `{}`) — Options of [`classify_field_lines()`][plasma_plots.fieldlines.classify_field_lines] (``max_denominator``, ``tolerance``, ``threshold``, ``min_spread``), for ``color_by="classification"`` and ``islands_``.

**Returns**

- (`PlotResult`) — The figure, the axes and the scatters (one per line, or one per class); ``data`` holds the ``section``, and with ``islands_`` the ``islands`` Dataset and the ``classification``.

**Raises**

- `ValueError` — If ``coords`` or ``color_by`` is unknown.

> **See Also**
>
> [`plasma_plots.fieldlines.poincare_section()`][plasma_plots.fieldlines.poincare_section] : The punctures.
> [`plasma_plots.fieldlines.islands()`][plasma_plots.fieldlines.islands] : The island chains.

**Examples**

```pycon
>>> plot_poincare(lines, color_by="iota")
>>> plot_poincare(
...     poincare_section(lines, angle=0.3),
...     color_by="classification",
...     islands_=True,
... )
```

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

## plasma_plots.fieldline_plots.plot_surface_map

*function*

```python
def plot_surface_map(data: xr.DataArray, *, x: str | None = None, y: str | None = None, iota=None, lines: xr.Dataset | None = None, count: int = 6, start: float = 0.0, turns: float | None = 2.0, line_color: str = 'w', ax=None, **options)
```

A quantity on a flux surface, unfolded over the toroidal and poloidal angles, with field lines.

The surface is a slice of the field at one radius; field lines on it are drawn either as
straight lines of slope ι (in straight-field-line angles, e.g. GVEC's Boozer or PEST
angles, where ``θ = θ₀ + ι ζ``), or as traced lines, or both (the straight ones dashed
then). Where a line leaves the plot through a periodic edge it continues from the opposite
one.

**Parameters**

- `data` (`xarray.DataArray`) — The quantity on the surface, with the two angles as its only dimensions (every other dimension selected, e.g. ``ev.mod_B.sel(rho=0.5)``).
- `x` (`str`) (default: `None`) — The toroidal angle. Default: the toroidal logical dimension.
- `y` (`str`) (default: `None`) — The poloidal angle. Default: the poloidal logical dimension.
- `iota` (`float or xarray.DataArray`) (default: `None`) — The rotational transform of the surface, or its profile over the radial coordinate, at whose value in ``data``'s coordinates it is interpolated. Draws ``count`` straight field lines. Default: none.
- `lines` (`xarray.Dataset`) (default: `None`) — Traced lines ([`trace_field_lines()`][plasma_plots.fieldlines.trace_field_lines]), drawn over the angles as they are, every line in the Dataset. Default: none.
- `count` (`int`) (default: `6`) — The number of straight lines, equally spaced in the poloidal angle. Default: 6.
- `start` (`float`) (default: `0.0`) — The poloidal angle of the first straight line at the left edge. Default: 0.
- `turns` (`float`) (default: `2.0`) — How many toroidal transits of each traced line to draw (a long line covers an irrational surface completely); ``None`` for all. Default: 2.
- `line_color` (`str`) (default: `'w'`) — The color of the field lines. Default: white.
- `ax` (`matplotlib.axes.Axes`) (default: `None`) — The axes to draw into. Default: a new figure.
- `**options` (default: `{}`) — Options of [`plot_slice()`][plasma_plots.plotting.plot_slice] (``cmap``, ``levels``, ``symmetric``, ``overlays``, ...).

**Returns**

- (`PlotResult`) — The figure, the axes, the mesh and the lines; ``data["iota"]`` holds the ι drawn.

**Raises**

- `ValueError` — If ``data`` does not have exactly the two angles, or a profile ``iota`` cannot be
interpolated because ``data`` has no scalar radial coordinate.

> **See Also**
>
> [`plasma_plots.plotting.plot_slice()`][plasma_plots.plotting.plot_slice] : The surface itself.

**Examples**

```pycon
>>> plot_surface_map(boozer.mod_B.sel(rho=0.5), iota=boozer.iota, count=8)
>>> plot_surface_map(phi.isel(t=-1).sel(eta1=0.5), lines=lines)
```

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