Getting Started#

Installation#

Important

To install this package, ensure that you are using one of the supported Python versions Supported Python versions

Install sdf-xarray from PyPI with:

pip install sdf-xarray

or download this code locally:

git clone --recursive https://github.com/epochpic/sdf-xarray.git
cd sdf-xarray
pip install .

Note

When loading SDF files, variables related to boundaries, cpu and output file are excluded as they are problematic. If you wish to load these in please use the Loading raw files approach.

Tip

All code examples throughout this documentation are visualised using Jupyter notebooks so that you can interactively explore xarray.Dataset objects. To do this on your machine make sure that you have the necessary dependencies installed:

pip install "sdf-xarray[jupyter]"

Usage#

sdf-xarray is a backend for xarray, and so is usable directly from xarray. There are several ways to load SDF files:

Loading single files#

import xarray as xr

xr.open_dataset("tutorial_dataset_1d/0010.sdf")
<xarray.Dataset> Size: 341kB
Dimensions:                                       (X_Grid_mid: 200,
                                                   Px_px_py_Electron: 200,
                                                   Py_px_py_Electron: 200,
                                                   X_Grid: 201,
                                                   Px_px_py_Electron_mid: 199,
                                                   Py_px_py_Electron_mid: 199)
Coordinates:
  * X_Grid_mid                                    (X_Grid_mid) float64 2kB -4...
  * Px_px_py_Electron                             (Px_px_py_Electron) float64 2kB ...
  * Py_px_py_Electron                             (Py_px_py_Electron) float64 2kB ...
  * X_Grid                                        (X_Grid) float64 2kB -5e-06...
  * Px_px_py_Electron_mid                         (Px_px_py_Electron_mid) float64 2kB ...
  * Py_px_py_Electron_mid                         (Py_px_py_Electron_mid) float64 2kB ...
Data variables: (12/15)
    Wall_time                                     float64 8B ...
    Electric_Field_Ex                             (X_Grid_mid) float64 2kB ...
    Electric_Field_Ey                             (X_Grid_mid) float64 2kB ...
    Magnetic_Field_Bz                             (X_Grid_mid) float64 2kB ...
    Total_Particle_Energy_Electron                float64 8B ...
    Total_Particle_Energy_Ion                     float64 8B ...
    ...                                            ...
    Derived_Number_Density_Ion                    (X_Grid_mid) float64 2kB ...
    Derived_Temperature_Electron                  (X_Grid_mid) float64 2kB ...
    Derived_Temperature_Ion                       (X_Grid_mid) float64 2kB ...
    dist_fn_px_py_Electron                        (Px_px_py_Electron, Py_px_py_Electron) float64 320kB ...
    Absorption_Total_Laser_Energy_Injected        float64 8B ...
    Absorption_Fraction_of_Laser_Energy_Absorbed  float64 8B ...
Attributes: (12/21)
    filename:         tutorial_dataset_1d/0010.sdf
    file_version:     1
    file_revision:    4
    code_name:        Epoch1d
    step:             188
    time:             5.016803991780179e-14
    ...               ...
    compile_machine:  uoy24x520
    compile_flags:    unknown
    defines:          50364612
    compile_date:     Wed May 14 13:13:41 2025
    run_date:         Wed Nov 12 12:44:42 2025
    io_date:          Wed Nov 12 12:44:42 2025

Alternatively, you can load the data in as a xarray.DataTree, which organises the data hierarchically into groups (for example grouping related quantities such as the individual components of the electric and magnetic fields) while keeping each item as a xarray.Dataset.

import sdf_xarray as sdfxr

sdfxr.open_datatree("tutorial_dataset_1d/0010.sdf")
<xarray.DataTree>
Group: /
│   Dimensions:                              ()
│   Data variables:
│       Wall-time                            float64 8B ...
│       Total_Particle_Energy_in_Simulation  float64 8B ...
│       Total_Field_Energy_in_Simulation     float64 8B ...
│   Attributes: (12/21)
│       filename:         tutorial_dataset_1d/0010.sdf
│       file_version:     1
│       file_revision:    4
│       code_name:        Epoch1d
│       step:             188
│       time:             5.016803991780179e-14
│       ...               ...
│       compile_machine:  uoy24x520
│       compile_flags:    unknown
│       defines:          50364612
│       compile_date:     Wed May 14 13:13:41 2025
│       run_date:         Wed Nov 12 12:44:42 2025
│       io_date:          Wed Nov 12 12:44:42 2025
├── Group: /Electric_Field
│       Dimensions:     (X_Grid_mid: 200)
│       Coordinates:
│         * X_Grid_mid  (X_Grid_mid) float64 2kB -4.95e-06 -4.85e-06 ... 1.495e-05
│       Data variables:
│           Ex          (X_Grid_mid) float64 2kB ...
│           Ey          (X_Grid_mid) float64 2kB ...
├── Group: /Magnetic_Field
│       Dimensions:     (X_Grid_mid: 200)
│       Coordinates:
│         * X_Grid_mid  (X_Grid_mid) float64 2kB -4.95e-06 -4.85e-06 ... 1.495e-05
│       Data variables:
│           Bz          (X_Grid_mid) float64 2kB ...
├── Group: /Total_Particle_Energy
│       Dimensions:   ()
│       Data variables:
│           Electron  float64 8B ...
│           Ion       float64 8B ...
├── Group: /Absorption
│       Dimensions:                            ()
│       Data variables:
│           Total_Laser_Energy_Injected        float64 8B ...
│           Fraction_of_Laser_Energy_Absorbed  float64 8B ...
├── Group: /Derived
│   ├── Group: /Derived/Number_Density
│   │       Dimensions:     (X_Grid_mid: 200)
│   │       Coordinates:
│   │         * X_Grid_mid  (X_Grid_mid) float64 2kB -4.95e-06 -4.85e-06 ... 1.495e-05
│   │       Data variables:
│   │           Electron    (X_Grid_mid) float64 2kB ...
│   │           Ion         (X_Grid_mid) float64 2kB ...
│   └── Group: /Derived/Temperature
│           Dimensions:     (X_Grid_mid: 200)
│           Coordinates:
│             * X_Grid_mid  (X_Grid_mid) float64 2kB -4.95e-06 -4.85e-06 ... 1.495e-05
│           Data variables:
│               Electron    (X_Grid_mid) float64 2kB ...
│               Ion         (X_Grid_mid) float64 2kB ...
└── Group: /dist_fn
    └── Group: /dist_fn/px_py
            Dimensions:            (Px_px_py_Electron: 200, Py_px_py_Electron: 200)
            Coordinates:
              * Px_px_py_Electron  (Px_px_py_Electron) float64 2kB -1.492e-21 ... 1.492e-21
              * Py_px_py_Electron  (Py_px_py_Electron) float64 2kB -1.492e-21 ... 1.492e-21
            Data variables:
                Electron           (Px_px_py_Electron, Py_px_py_Electron) float64 320kB ...

Loading multiple files#

import sdf_xarray as sdfxr

sdfxr.open_mfdataset("tutorial_dataset_1d/*.sdf")
<xarray.Dataset> Size: 14MB
Dimensions:                                       (time: 41, X_Grid_mid: 200,
                                                   Px_px_py_Electron: 200,
                                                   Py_px_py_Electron: 200,
                                                   X_Grid: 201,
                                                   Px_px_py_Electron_mid: 199,
                                                   Py_px_py_Electron_mid: 199)
Coordinates:
  * time                                          (time) float64 328B 1.334e-...
  * X_Grid_mid                                    (X_Grid_mid) float64 2kB -4...
  * Px_px_py_Electron                             (Px_px_py_Electron) float64 2kB ...
  * Py_px_py_Electron                             (Py_px_py_Electron) float64 2kB ...
  * X_Grid                                        (X_Grid) float64 2kB -5e-06...
  * Px_px_py_Electron_mid                         (Px_px_py_Electron_mid) float64 2kB ...
  * Py_px_py_Electron_mid                         (Py_px_py_Electron_mid) float64 2kB ...
Data variables: (12/15)
    Wall_time                                     (time) float64 328B 0.00419...
    Electric_Field_Ex                             (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
    Electric_Field_Ey                             (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
    Magnetic_Field_Bz                             (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
    Total_Particle_Energy_Electron                (time) float64 328B 3.639e+...
    Total_Particle_Energy_Ion                     (time) float64 328B 3.57e+0...
    ...                                            ...
    Derived_Number_Density_Ion                    (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
    Derived_Temperature_Electron                  (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
    Derived_Temperature_Ion                       (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
    dist_fn_px_py_Electron                        (time, Px_px_py_Electron, Py_px_py_Electron) float64 13MB dask.array<chunksize=(1, 200, 200), meta=np.ndarray>
    Absorption_Total_Laser_Energy_Injected        (time) float64 328B 1.416e+...
    Absorption_Fraction_of_Laser_Energy_Absorbed  (time) float64 328B 0.0 ......
Attributes: (12/21)
    filename:         /home/docs/checkouts/readthedocs.org/user_builds/sdf-xa...
    file_version:     1
    file_revision:    4
    code_name:        Epoch1d
    step:             0
    time:             1.3342563807926084e-16
    ...               ...
    compile_machine:  uoy24x520
    compile_flags:    unknown
    defines:          50364612
    compile_date:     Wed May 14 13:13:41 2025
    run_date:         Wed Nov 12 12:44:42 2025
    io_date:          Wed Nov 12 12:44:42 2025

Alternatively, you can load the data in as a xarray.DataTree, which organises the data hierarchically into groups (for example grouping related quantities such as the individual components of the electric and magnetic fields) while keeping each item as a xarray.Dataset.

import sdf_xarray as sdfxr

sdfxr.open_mfdatatree("tutorial_dataset_1d/*.sdf")
<xarray.DataTree>
Group: /
│   Dimensions:                              (time: 41)
│   Coordinates:
│     * time                                 (time) float64 328B 1.334e-16 ... 2....
│   Data variables:
│       Wall-time                            (time) float64 328B 0.004197 ... 1.028
│       Total_Particle_Energy_in_Simulation  (time) float64 328B 7.209e+06 ... 1....
│       Total_Field_Energy_in_Simulation     (time) float64 328B 0.0 ... 1.25e+09
│   Attributes: (12/21)
│       filename:         /home/docs/checkouts/readthedocs.org/user_builds/sdf-xa...
│       file_version:     1
│       file_revision:    4
│       code_name:        Epoch1d
│       step:             0
│       time:             1.3342563807926084e-16
│       ...               ...
│       compile_machine:  uoy24x520
│       compile_flags:    unknown
│       defines:          50364612
│       compile_date:     Wed May 14 13:13:41 2025
│       run_date:         Wed Nov 12 12:44:42 2025
│       io_date:          Wed Nov 12 12:44:42 2025
├── Group: /Electric_Field
│       Dimensions:     (time: 41, X_Grid_mid: 200)
│       Coordinates:
│         * X_Grid_mid  (X_Grid_mid) float64 2kB -4.95e-06 -4.85e-06 ... 1.495e-05
│       Data variables:
│           Ex          (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
│           Ey          (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
├── Group: /Magnetic_Field
│       Dimensions:     (time: 41, X_Grid_mid: 200)
│       Coordinates:
│         * X_Grid_mid  (X_Grid_mid) float64 2kB -4.95e-06 -4.85e-06 ... 1.495e-05
│       Data variables:
│           Bz          (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
├── Group: /Total_Particle_Energy
│       Dimensions:   (time: 41)
│       Data variables:
│           Electron  (time) float64 328B 3.639e+06 3.601e+06 ... 1.083e+10 1.07e+10
│           Ion       (time) float64 328B 3.57e+06 3.57e+06 ... 1.301e+09 1.313e+09
├── Group: /Absorption
│       Dimensions:                            (time: 41)
│       Data variables:
│           Total_Laser_Energy_Injected        (time) float64 328B 1.416e+06 ... 1.70...
│           Fraction_of_Laser_Energy_Absorbed  (time) float64 328B 0.0 0.9661 ... 0.5871
├── Group: /Derived
│   ├── Group: /Derived/Number_Density
│   │       Dimensions:     (time: 41, X_Grid_mid: 200)
│   │       Coordinates:
│   │         * X_Grid_mid  (X_Grid_mid) float64 2kB -4.95e-06 -4.85e-06 ... 1.495e-05
│   │       Data variables:
│   │           Electron    (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
│   │           Ion         (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
│   └── Group: /Derived/Temperature
│           Dimensions:     (time: 41, X_Grid_mid: 200)
│           Coordinates:
│             * X_Grid_mid  (X_Grid_mid) float64 2kB -4.95e-06 -4.85e-06 ... 1.495e-05
│           Data variables:
│               Electron    (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
│               Ion         (time, X_Grid_mid) float64 66kB dask.array<chunksize=(1, 200), meta=np.ndarray>
└── Group: /dist_fn
    └── Group: /dist_fn/px_py
            Dimensions:            (time: 41, Px_px_py_Electron: 200, Py_px_py_Electron: 200)
            Coordinates:
              * Px_px_py_Electron  (Px_px_py_Electron) float64 2kB -1.492e-21 ... 1.492e-21
              * Py_px_py_Electron  (Py_px_py_Electron) float64 2kB -1.492e-21 ... 1.492e-21
            Data variables:
                Electron           (time, Px_px_py_Electron, Py_px_py_Electron) float64 13MB dask.array<chunksize=(1, 200, 200), meta=np.ndarray>

Loading raw files#

import sdf_xarray as sdfxr

raw_ds = sdfxr.SDFFile("tutorial_dataset_1d/0010.sdf")
raw_ds.variables.keys()
dict_keys(['Wall-time', 'Electric Field/Ex', 'Electric Field/Ey', 'Magnetic Field/Bz', 'Total Particle Energy/Electron', 'Total Particle Energy/Ion', 'Total Particle Energy in Simulation', 'Total Field Energy in Simulation', 'Derived/Number_Density/Electron', 'Derived/Number_Density/Ion', 'Derived/Temperature/Electron', 'Derived/Temperature/Ion', 'dist_fn/px_py/Electron', 'Electron_Probe/Px', 'Electron_Probe/Py', 'Electron_Probe/Pz', 'Electron_Probe/weight', 'Absorption/Total Laser Energy Injected', 'Absorption/Fraction of Laser Energy Absorbed', 'CPUs/Original rank', 'CPUs/Current rank'])