Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions doc/user-guide/complex-numbers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
.. currentmodule:: xarray

.. _complex:

Complex Numbers
===============

Xarray leverages NumPy to seamlessly handle complex numbers in :py:class:`~xarray.DataArray` and :py:class:`~xarray.Dataset` objects.

In the examples below, we are using a DataArray named ``da`` with complex elements (of :math:`\mathbb{C}`):

.. ipython:: python

import xarray as xr
import numpy as np

data = np.array([[1 + 2j, 3 + 4j], [5 + 6j, 7 + 8j]])
da = xr.DataArray(
data,
dims=["x", "y"],
coords={"x": ["a", "b"], "y": [1, 2]},
name="complex_nums",
)


Operations on Complex Data
--------------------------
You can access real and imaginary components using the ``.real`` and ``.imag`` attributes. Most NumPy universal functions (ufuncs) like :py:doc:`numpy.abs <numpy:reference/generated/numpy.absolute>` or :py:doc:`numpy.angle <numpy:reference/generated/numpy.angle>` work directly.

.. ipython:: python

da.real
np.abs(da)

.. note::
Like NumPy, ``.real`` and ``.imag`` typically return *views*, not copies, of the original data.


Reading and Writing Complex Data
--------------------------------

Writing complex data to NetCDF files (see :ref:`io.netcdf`) is supported via :py:meth:`~xarray.DataArray.to_netcdf` using specific backend engines that handle complex types:


.. tab:: h5netcdf

This requires the `h5netcdf <https://h5netcdf.org>`_ library to be installed.

.. ipython:: python
:okwarning:

# write the data to disk
da.to_netcdf("complex_nums_h5.nc", engine="h5netcdf")
# read the file back into memory
ds_h5 = xr.open_dataset("complex_nums_h5.nc", engine="h5netcdf")
# check the dtype
ds_h5[da.name].dtype


.. tab:: netcdf4

Requires the `netcdf4-python (>= 1.7.1) <https://github.com/Unidata/netcdf4-python>`_ library and you have to enable ``auto_complex=True``.

.. ipython:: python
:okwarning:

# write the data to disk
da.to_netcdf("complex_nums_nc4.nc", engine="netcdf4", auto_complex=True)
# read the file back into memory
ds_nc4 = xr.open_dataset(
"complex_nums_nc4.nc", engine="netcdf4", auto_complex=True
)
# check the dtype
ds_nc4[da.name].dtype


.. warning::
The ``scipy`` engine only supports NetCDF V3 and does *not* support complex arrays; writing with ``engine="scipy"`` raises a ``TypeError``.


Alternative: Manual Handling
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

If direct writing is not supported (e.g., targeting NetCDF3), you can manually
split the complex array into separate real and imaginary variables before saving:

.. ipython:: python

# Write data to file
ds_manual = xr.Dataset(
{
f"{da.name}_real": da.real,
f"{da.name}_imag": da.imag,
}
)
ds_manual.to_netcdf("complex_manual.nc", engine="scipy") # Example

# Read data from file
ds = xr.open_dataset("complex_manual.nc", engine="scipy")
reconstructed = ds[f"{da.name}_real"] + 1j * ds[f"{da.name}_imag"]

Recommendations
^^^^^^^^^^^^^^^

- Use ``engine="netcdf4"`` with ``auto_complex=True`` for full compliance and ease.
- Use ``h5netcdf`` for HDF5-based storage when interoperability with HDF5 is desired.
- For maximum legacy support (NetCDF3), manually handle real/imaginary components.

.. ipython:: python
:suppress:

# Cleanup
import os

for f in ["complex_nums_nc4.nc", "complex_nums_h5.nc", "complex_manual.nc"]:
if os.path.exists(f):
os.remove(f)



See also
--------
- :ref:`io.netcdf` — full NetCDF I/O guide
- `NumPy complex numbers <https://numpy.org/doc/stable/user/basics.types.html#complex>`__
1 change: 1 addition & 0 deletions doc/user-guide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ examples that describe many common tasks that you can accomplish with Xarray.
:caption: I/O

io
complex-numbers

.. toctree::
:maxdepth: 2
Expand Down
3 changes: 3 additions & 0 deletions doc/whats-new.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ Documentation
- Switch to `pydata-sphinx-theme <https://github.com/pydata/pydata-sphinx-theme>`_ from `sphinx-book-theme <https://github.com/executablebooks/sphinx-book-theme>`_ (:pull:`8708`).
By `Scott Henderson <https://github.com/scottyhq>`_.

- Add a dedicated 'Complex Numbers' sections to the User Guide (:issue:`10213`, :pull:`10235`).
By `Andre Wendlinger <https://github.com/andrewendlinger>`_.

Internal Changes
~~~~~~~~~~~~~~~~
- Avoid stacking when grouping by a chunked array. This can be a large performance improvement.
Expand Down
Loading