# plasma_plots.desc

*module*

Evaluate DESC equilibria into Datasets in plasma-plots' conventions.

`DESC <https://desc-docs.readthedocs.io>`_ computes a quantity of an equilibrium on a grid of
flux coordinates, ``eq.compute(names, grid)``, and returns flat arrays over the grid's nodes.
[`from_desc()`][plasma_plots.desc.from_desc] evaluates an equilibrium on a tensor-product grid and returns an
``xarray.Dataset`` that the rest of plasma-plots reads the way it reads GVEC's:

* the dimensions are the flux coordinates ``rho``, ``theta`` (DESC's poloidal angle, or the PEST
  angle ``theta_P`` with ``sfl="pest"``) and ``zeta`` (the cylindrical toroidal angle), so
  ``rho=0.5`` selects and ``x="zeta"`` draws;
* ``X``, ``Y``, ``Z`` are coordinates of every variable (for ``coords="physical"``, 3-D views and
  the vector calculus on the mapped domain), and ``theta_P`` too when ``"theta_PEST"`` is among
  the names (for the ``coordinate_lines`` overlay);
* vectors, which DESC gives in cylindrical components, are Cartesian ``(x, y, z)`` along
  ``component``, as on every other grid;
* profiles (DESC's quantities over ``rho`` only) are over ``rho``, and global quantities such as
  ``"V"`` are scalars;
* each quantity keeps DESC's name (``ds["|B|"]``) and gets DESC's LaTeX ``label``, its ``units``
  and its description as ``long_name``;
* the angles get a ``period`` attribute (2π, and 2π/nfp toroidally), from which the mode spectra
  take their periods and full-torus mode numbers, and the ``coordinate_lines`` overlay its lines;
* the number of field periods is the ``nfp`` attribute of the Dataset and of every variable.

Integrals over the grid cover the sampled toroidal range, one field period by default, as for
GVEC: multiply by nfp for the device. DESC's Jacobian is ``"sqrt(g)"``. Unlike GVEC's, the
evaluation needs DESC itself (``pip install desc-opt``); the Dataset it returns does not
(``to_netcdf`` saves it).

**Examples**

```pycon
>>> import desc.examples
>>> import plasma_plots
>>> eq = desc.examples.get("W7-X")
>>> ev = plasma_plots.from_desc(
...     eq, ["|B|", "iota", "sqrt(g)"], rho=11, theta=64, zeta=40
... )
>>> ev["|B|"].plasma.plot.slice(
...     coords="physical",
...     plane="RZ",
...     zeta=0.0,
...     overlays={"coordinate_lines": {"rho": 5, "theta": 8}},
... )
>>> ev.iota.plasma.plot.lineout(rationals=4)
```

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

## plasma_plots.desc.CARTESIAN

*attribute* · *module attribute*

```python
CARTESIAN = ['x', 'y', 'z']
```

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

## plasma_plots.desc.GEOMETRY

*attribute* · *module attribute*

```python
GEOMETRY = ('X', 'Y', 'Z', 'phi', 'rho', 'zeta')
```

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

## plasma_plots.desc.GRID_QUANTITIES

*attribute* · *module attribute*

```python
GRID_QUANTITIES = {'theta_PEST': 'theta_P'}
```

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

## plasma_plots.desc.POLOIDAL

*attribute* · *module attribute*

```python
POLOIDAL = {None: 'theta', 'pest': 'theta_P'}
```

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

## plasma_plots.desc.from_desc

*function*

```python
def from_desc(eq, names: str | Sequence[str], *, rho: int | float | Sequence[float] = 11, theta: int | float | Sequence[float] = 32, zeta: int | float | Sequence[float] = 24, sfl: str | None = None) -> xr.Dataset
```

Evaluate DESC quantities on a grid, as a Dataset in plasma-plots' conventions.

See [`plasma_plots.desc`][plasma_plots.desc] for what the Dataset contains.

**Parameters**

- `eq` (`desc.equilibrium.Equilibrium`) — The equilibrium, e.g. ``desc.io.load("eq.h5")`` or ``desc.examples.get("W7-X")``.
- `names` (`str or sequence of str`) — DESC's names of the quantities (``"|B|"``, ``"iota"``, ``"sqrt(g)"``, ``"B"``, ``"J"``, ``"p"``, ``"D_Mercier"``, ``"V"``, ...; see DESC's list of variables). ``"theta_PEST"`` becomes the coordinate ``theta_P``. Quantities that are not scalars, profiles, fields or 3-vectors (such as ``"grad(B)"``) are not supported, nor ``"x"``: the position is ``X``, ``Y``, ``Z``.
- `rho` (`int, float or sequence of float`) (default: `11`) — The flux surfaces: an integer as that many points from 0 to 1, a float or a sequence as the values. Default: 11 points.
- `theta` (`int, float or sequence of float`) (default: `32`) — The poloidal angles (PEST angles with ``sfl="pest"``): an integer as that many points over ``[0, 2π)``, else the values. Default: 32 points.
- `zeta` (`int, float or sequence of float`) (default: `24`) — The toroidal angles: an integer as that many points over one field period ``[0, 2π/nfp)``, else the values, which may cover the whole torus. Default: 24 points.
- `sfl` (`(None, 'pest')`) (default: `None`) — ``"pest"`` for a grid in the straight-field-line PEST angle ``theta_P`` (DESC's own ``theta`` becomes a coordinate, found by ``eq.map_coordinates``) rather than in DESC's poloidal angle. Default: ``None``.

**Returns**

- (`xarray.Dataset`) — The quantities over ``rho``, ``theta`` (or ``theta_P``) and ``zeta``, vectors along ``component``, with the coordinates ``X``, ``Y``, ``Z``, labels, units, the angles' ``period`` and the ``nfp`` attribute.

**Raises**

- `ValueError` — For an unknown ``sfl``, a name DESC doesn't know, a quantity of an unsupported shape or a
coordinate triplet such as ``"x"``.

**Examples**

```pycon
>>> ev = from_desc(eq, ["|B|", "iota", "sqrt(g)"], rho=11, theta=64, zeta=40)
>>> ev["|B|"].plasma.plot.panels(
...     sweep="zeta", coords="physical", plane="RZ", nrows=1, ncols=3
... )
>>> pest = from_desc(eq, "|B|", rho=[0.5], theta=64, zeta=48, sfl="pest")
>>> pest["|B|"].plasma.plot.slice(x="zeta", y="theta_P", rho=0.5)
```

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