---
title: "Band structure and DOS format"
description: "The .bandstructure and .dos file formats Ouro renders as interactive electronic structure plots"
date: "2026-09-24"
last_updated: "2026-09-25"
---

Ouro renders any file ending in `.bandstructure` as an interactive electronic
band structure, and any file ending in `.dos` as an interactive density of
states. The formats are open: any service, script, or agent that writes a file
following this page gets the same viewer that Ouro's DFT routes use.

Both files carry energies you already computed. The viewer plots them as given
and derives only what follows directly from them, such as the band gap.

## What the viewer shows

A `.bandstructure` file draws its bands along the high-symmetry path, with
labeled k-points and the Fermi level marked. When the file also carries a
density of states, the DOS is drawn beside the bands on the same energy axis.
Spin-polarized bands are drawn in two colors, one per spin channel.

The viewer reports whether the structure is metallic, a half-metal, or gapped.
For a gapped structure it gives the gap, whether it is direct or indirect, and
marks the band edges, and it measures energies from the valence band maximum
rather than the Fermi level. It estimates carrier effective masses at the band
edges along each path direction that leaves them. With a spin-polarized DOS it
gives the magnetic moment, and for metals the spin polarization at the Fermi
level.

Readers can hover a band to read its energy and, with
[band projections](#band-projections), the orbital character of that state.
Projections also let readers choose an element or orbital and see the bands
thicken where it sits. Readers can narrow the energy window and break the DOS
down by element or by orbital.

A `.dos` file on its own is drawn with energy along the horizontal axis, spin
down mirrored below spin up. Embedded in a post, either file shows with a
compact hover card.

## Encoding

Both files are a single UTF-8 JSON object. Upload them with the
`.bandstructure` or `.dos` extension; the content type is `application/json`.

- Energies are absolute, in eV, as your code reports them. Each file gives its
  own Fermi level, and the viewer plots energies relative to it, or to the
  valence band maximum when there is a gap.
- Arrays with a spin dimension have one entry for a non-spin-polarized
  calculation and two, spin up then spin down, for a spin-polarized one.

## Band structure files

| Field          | Type         | Required | Meaning                                                                                               |
| -------------- | ------------ | -------- | ----------------------------------------------------------------------------------------------------- |
| `format`       | string       | Yes      | Always `"ouro.band-structure"`                                                                        |
| `version`      | integer      | Yes      | Always `1` for the format on this page                                                                |
| `fermi_energy` | number       | Yes      | Fermi level in eV                                                                                     |
| `kpoints`      | object       | Yes      | The path, described under [K-points](#k-points)                                                       |
| `bands`        | number[][][] | Yes      | Eigenvalues in eV, indexed `[spin][band][k-point]`                                                    |
| `projections`  | object[]     | No       | Orbital character of each state, described under [Band projections](#band-projections)                |
| `dos`          | object       | No       | A density of states to draw beside the bands, described under [Density of states](#density-of-states) |
| `energy_model` | string       | No       | Label for the method behind the energies, such as `"PBE"` or `"PBE+U"`                                |

Each band is a list with one energy per k-point, in path order. Bands may
cross; the viewer draws each band index as one line and doesn't reorder them.

Take the Fermi level from a calculation that samples the whole Brillouin
zone, such as the self-consistent run the bands started from. Occupations along
a path don't.

### K-points

| Field       | Type     | Required | Meaning                                                          |
| ----------- | -------- | -------- | ---------------------------------------------------------------- |
| `distances` | number[] | Yes      | Cumulative distance along the path in Å⁻¹, one per k-point       |
| `labels`    | object[] | Yes      | High-symmetry points, each `{"index": integer, "label": string}` |

`distances` starts at 0 and never decreases. Its units only set the relative
widths of the path's segments, so any consistent convention works, with or
without the 2π factor.

The path can jump between points that aren't connected, as the usual FCC path
does from U to K. At a jump, the last k-point before it and the first after it
share the same distance, and each carries its own label. The viewer breaks the
lines there and labels the tick `U|K`. A point repeated where two segments meet
can also be listed twice at one distance with the same label; the viewer shows
it once.

`index` refers into `distances`. Write labels as readers should see them, such
as `"Γ"`, `"X"`, or `"Σ₁"`, rather than as LaTeX.

### Band projections

Each projection gives how much of every state lies on one element, or on one
orbital of one element, such as the Mulliken weights your code reports.

| Field     | Type         | Required | Meaning                                                            |
| --------- | ------------ | -------- | ------------------------------------------------------------------ |
| `element` | string       | Yes      | Element symbol, such as `"Fe"`                                     |
| `orbital` | string       | No       | `"s"`, `"p"`, `"d"`, or `"f"`; leave out for the element's total   |
| `weights` | number[][][] | Yes      | Weights from 0 to 1, indexed like `bands`: `[spin][band][k-point]` |

Normalize each state so that its weights, across one complete breakdown, sum
to 1. The orbital projections of all elements are one complete breakdown; the
element totals are another. Two decimals are enough and keep the file small.
As with the DOS, an element given only by orbital is summed by the viewer.

## Density of states files

| Field          | Type    | Required | Meaning                                  |
| -------------- | ------- | -------- | ---------------------------------------- |
| `format`       | string  | Yes      | Always `"ouro.dos"`                      |
| `version`      | integer | Yes      | Always `1` for the format on this page   |
| `energy_model` | string  | No       | Label for the method behind the energies |

Every other field is described under [Density of states](#density-of-states),
at the top level of the file.

### Density of states

A density of states is the same set of fields wherever it appears: at the top
level of a `.dos` file, or as the `dos` object of a `.bandstructure` file.

| Field          | Type       | Required | Meaning                                                               |
| -------------- | ---------- | -------- | --------------------------------------------------------------------- |
| `fermi_energy` | number     | Yes      | Fermi level in eV                                                     |
| `energies`     | number[]   | Yes      | Energy grid in eV, ascending                                          |
| `total`        | number[][] | Yes      | Total DOS in states/eV, indexed `[spin][energy]`, all values positive |
| `projections`  | object[]   | No       | Projected DOS, described under [Projections](#projections)            |

Write spin down as positive values; the viewer mirrors it. The DOS carries its
own Fermi level because it usually comes from a different calculation than the
bands, on a denser mesh.

### Projections

Each projection is the DOS on one element, or on one orbital of one element,
on the same energy grid as `total`.

| Field     | Type       | Required | Meaning                                                          |
| --------- | ---------- | -------- | ---------------------------------------------------------------- |
| `element` | string     | Yes      | Element symbol, such as `"Fe"`                                   |
| `orbital` | string     | No       | `"s"`, `"p"`, `"d"`, or `"f"`; leave out for the element's total |
| `values`  | number[][] | Yes      | DOS in states/eV, indexed `[spin][energy]`                       |

Readers can view the DOS by element or by orbital within one element. When an
element has orbital projections but no total, the viewer sums its orbitals.

## Example

A spin-polarized band structure along a three-point path with one jump, and a
DOS beside it. A real file has many more k-points, bands, and energies:

```json
{
  "format": "ouro.band-structure",
  "version": 1,
  "energy_model": "PBE",
  "fermi_energy": 8.12,
  "kpoints": {
    "distances": [0, 0.5, 1.0, 1.0, 1.4],
    "labels": [
      { "index": 0, "label": "Γ" },
      { "index": 2, "label": "U" },
      { "index": 3, "label": "K" },
      { "index": 4, "label": "Γ" }
    ]
  },
  "bands": [
    [
      [5.1, 6.0, 7.2, 7.0, 5.1],
      [9.4, 8.8, 8.6, 8.9, 9.4]
    ],
    [
      [5.9, 6.8, 7.9, 7.7, 5.9],
      [10.0, 9.5, 9.2, 9.6, 10.0]
    ]
  ],
  "dos": {
    "fermi_energy": 8.1,
    "energies": [5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
    "total": [
      [0.4, 1.2, 1.6, 0.3, 1.1, 0.5],
      [0.1, 0.8, 1.4, 0.2, 0.6, 0.9]
    ],
    "projections": [
      {
        "element": "Fe",
        "orbital": "d",
        "values": [
          [0.3, 1.0, 1.3, 0.2, 0.9, 0.3],
          [0.1, 0.6, 1.1, 0.1, 0.4, 0.6]
        ]
      }
    ]
  }
}
```

Both spin channels have their highest occupied band below 8.12 eV and their
lowest empty band above it, so the viewer reports a gap: from the spin-down
valence maximum of 7.9 eV at U to the spin-up conduction minimum of 8.6 eV at
U, a direct gap of 0.7 eV.

## Returning files from a route

A [route](/docs/concepts/routes) that produces band structures or densities of
states declares its output as a file with the `bandstructure` or `dos`
extension, and the result renders with the viewer wherever the route's output
appears. See [route input and output assets](/guides/route-input-output-assets)
for how to declare outputs.

## Versioning

The `version` field changes only for changes that would break existing readers.
Readers should reject versions they don't know, as Ouro's viewer does, and
ignore fields they don't recognize, so optional fields can be added within a
version.
