---
title: "Recompute HERA's upper limits and compare a model through its window"
description: "Rebuild seven Field 1 upper limits from the public HERA files, pass two model histories through the window rows and check five common mistakes."
canonical_url: "https://sandboxphysics.com/stories/cosmic-dawn-21cm/recompute-hera-window-comparison/"
language: "en"
page_type: "story"
alternate_languages:
  zh-CN: "https://sandboxphysics.com/zh/stories/cosmic-dawn-21cm/recompute-hera-window-comparison/"
last_modified: "2026-11-12"
---

[Hearing the first stars in 21 cm hydrogen](https://sandboxphysics.com/stories/cosmic-dawn-21cm/)

# Recompute HERA's upper limits and compare a model through its window

Sandbox Physics · 2026-11-12

With one short Python script and the public HERA Phase I files you can rebuild all seven Field 1 upper limits between $k=0.19$ and $0.58\,h\,\mathrm{Mpc^{-1}}$, digit for digit, and then compare two model histories with them the way the paper says a model should be compared: through the window functions. This guide gives the files, the command, the expected output and five mistakes that change the answer.

You should know what a bandpower, a window function and the rule $U=\max(\hat\Delta^2,0)+2\sigma$ are. The chapter [turning delay power into a bandpower](https://sandboxphysics.com/stories/cosmic-dawn-21cm/power-spectrum-window-and-signal-loss/) explains them.

## The files and what each one is

All files are in one folder and can be downloaded individually.

**Table 5.1** The tutorial files, their content and their label.

| File | What it holds | Label |
| --- | --- | --- |
| [hera-h1c-idr2-window-extract.json](https://sandboxphysics.com/stories/cosmic-dawn-21cm/materials/hera-h1c-idr2-window-extract.json) | HERA bandpowers, $1\sigma$, window rows and neighbour covariance, all three fields, both bands, $0.15\le k\le0.6$ | Real observation, derived extract |
| [model-spectra.json](https://sandboxphysics.com/stories/cosmic-dawn-21cm/materials/model-spectra.json) | Density-only prediction on HERA's window grid for a heated and a cold history | Ideal reference |
| [recompute\_window\_comparison.py](https://sandboxphysics.com/stories/cosmic-dawn-21cm/materials/recompute_window_comparison.py) | The script, standard library only | Method |
| [expected-output.json](https://sandboxphysics.com/stories/cosmic-dawn-21cm/materials/expected-output.json) | What the script should write | Check |
| [MANIFEST.json](https://sandboxphysics.com/stories/cosmic-dawn-21cm/materials/MANIFEST.json) | Byte counts, SHA-256 hashes, versions and units | Provenance |
| [NOTICE.txt](https://sandboxphysics.com/stories/cosmic-dawn-21cm/materials/NOTICE.txt) | Source, citation and reuse terms | Provenance |

The extract comes from the three UVPSpec files in the HERA Collaboration's public release, HERA\_2021\_pspec\_data.zip, retrieved on 12 November 2026 with SHA-256 1c98d163...388d2c. The paper states that the data behind its Tables 3 and 4 and Figures 17 and 18 are public. [HERA Collaboration 2022, Data section](https://arxiv.org/abs/2108.02263v1) The release page names no licence, so the extract is shared for teaching and verification with a request to cite the paper. The extraction script that reads the HDF5 files with h5py and numpy is kept in this site's source repository. It writes out the delay-to-$k$ conversion from hera\_pspec at the git hash recorded in the files. [hera\_pspec conversions.py](https://github.com/HERA-Team/hera_pspec/blob/30c77f02567e87a2db36cdc2f92adef4552a43f1/hera_pspec/conversions.py)

The model file is not a HERA product and was not fitted to HERA data. It is the Lab's linear prediction $\Delta^2_{21}=\bar T_{\mathrm b}^2(1+\mu^2)^2\Delta^2_m$ with $\mu=1$, an Eisenstein-Hu no-wiggle transfer function and Planck 2018 parameters. [Eisenstein and Hu 1998](https://arxiv.org/abs/astro-ph/9709112v1) The heated history has $\bar T_{\mathrm b}=16.2\,\mathrm{mK}$ at $z=7.93$, the cold one $-221\,\mathrm{mK}$.

## Run it

From the folder that holds the files:

```
python3 -I recompute_window_comparison.py hera-h1c-idr2-window-extract.json model-spectra.json my-output.json
```

The flag keeps Python from importing anything from the current folder. The script prints:

```
redshift 10.38
  k=0.256  U=(95.74)^2 mK^2  heated/U=0.0032  cold/U=0.375
  k=0.384  U=(178.23)^2 mK^2  heated/U=0.0014  cold/U=0.163
  k=0.512  U=(296.30)^2 mK^2  heated/U=0.0006  cold/U=0.076
redshift 7.93
  k=0.192  U=(30.76)^2 mK^2  heated/U=0.0168  cold/U=3.132
  k=0.320  U=(49.60)^2 mK^2  heated/U=0.0110  cold/U=2.063
  k=0.448  U=(113.39)^2 mK^2  heated/U=0.0029  cold/U=0.542
  k=0.576  U=(148.85)^2 mK^2  heated/U=0.0021  cold/U=0.389
```

Then compare my-output.json with expected-output.json. The only field allowed to differ is the Python version. The reference run used Python 3.9.6; the model file was exported with Node v26.11.1.

The script stops with an error when a window row's sum differs from one by more than $10^{-6}$, or when the model grid differs from the window grid.

## Step 1: rebuild the limits

The files hold bandpowers on a grid of $\Delta k=0.064\,h\,\mathrm{Mpc^{-1}}$. HERA's public notebook recommends either the single lowest limit in each band or every other bin, because neighbouring bins are correlated. The script takes every other bin, starting at $0.256$ in Band 1 and $0.192$ in Band 2 as the notebook does. [HERA Public Data Release 1, notebook](https://reionization.org/science/public-data-release-1/)

**Table 5.2** Field 1 bandpowers, errors and upper limits rebuilt from the public files.

| Band, redshift | $k$ | $\hat\Delta^2$ | $\sigma$ | $U$ | $\sqrt U$ |
| --- | --- | --- | --- | --- | --- |
| 1, $z=10.4$ | 0.256 | 1708.7 | 3729.0 | 9166.8 | 95.74 |
| 1, $z=10.4$ | 0.384 | 6829.8 | 12467.4 | 31764.6 | 178.23 |
| 1, $z=10.4$ | 0.512 | 27953.9 | 29918.7 | 87791.2 | 296.30 |
| 2, $z=7.9$ | 0.192 | 211.7 | 367.3 | 946.4 | 30.76 |
| 2, $z=7.9$ | 0.320 | $-516.0$ | 1229.8 | 2459.7 | 49.60 |
| 2, $z=7.9$ | 0.448 | 5974.1 | 3441.1 | 12856.3 | 113.39 |
| 2, $z=7.9$ | 0.576 | 7409.6 | 7373.1 | 22155.8 | 148.85 |

Powers are in $\mathrm{mK^2}$ and $\sqrt U$ in $\mathrm{mK}$. The two headline limits, $(95.74)^2$ at $z=10.4$ and $(30.76)^2$ at $z=7.9$, are the values printed in the paper. [HERA Collaboration 2022, §4.4](https://arxiv.org/abs/2108.02263v1) Reproducing them exactly checks both the extract and the rule.

## Step 2: pass the models through the windows

For each kept bin the script multiplies the model on HERA's full window grid by that bin's window row and sums. It also reports the model at the bin centre, so you can see how much the window matters. At $z=7.9$ the cold history exceeds the limit in the first two bins, by factors $3.13$ and $2.06$. The heated history stays below $0.017$ of every limit. At $z=10.4$ neither history is excluded.

What this does and does not show: a density-only model of fully coupled, unheated gas at $z=7.9$ is ruled out by HERA's Field 1 data. It says nothing about models with strong spin-temperature or ionization fluctuations, which this model leaves out.

## Five mistakes that change the answer

The script computes each of these on purpose and writes it next to the correct value.

1. Keeping a negative estimate. At $k=0.320$ the estimate is $-516.0$. Adding $2\sigma$ to it gives $1943.7$ instead of $2459.7\,\mathrm{mK^2}$, a limit 21 % tighter than the data support.
2. Using $1\sigma$. At $k=0.192$ the limit drops from $946.4$ to $579.0\,\mathrm{mK^2}$. That is no longer a 95 % limit.
3. Skipping the window. At $k=0.192$ the cold model is $2893$ at the bin centre and $2964\,\mathrm{mK^2}$ through the window; the heated model is $15.49$ against $15.87$. Small here, but it biases every comparison in the same direction.
4. Converting $h$ twice. HERA's $k$ is already in $h\,\mathrm{Mpc^{-1}}$. Dividing it by $h=0.6736$ again moves every point to $1.48$ times larger $k$, and the windowed cold model at $0.192$ rises from $2964$ to $4604\,\mathrm{mK^2}$, 55 % too high.
5. Treating every native bin as independent. The extract carries the covariance between neighbouring bins. Their correlation coefficient is $0.25$ to $0.31$ in Band 2 and $0.32$ to $0.33$ in Band 1. Combining all seven native bins as if independent would overstate how much the data constrain.

## Units, conventions and limits of this check

The $k$ values in the files use HERA's cosmology, with $H_0=67.27\,\mathrm{km\,s^{-1}\,Mpc^{-1}}$. [HERA Collaboration 2022, §4](https://arxiv.org/abs/2108.02263v1) The model uses Planck 2018, $h=0.6736$. The 0.13 % difference in $h$ moves a model point by far less than the window width of $0.031\,h\,\mathrm{Mpc^{-1}}$, so it is ignored here and recorded in the manifest.

The estimates are the real part of the cross-power spectrum, in $\mathrm{mK^2}$. The errors are the square root of the covariance diagonal stored in the file; because the seven limits match the paper, these are the error bars behind its Tables 3 and 4. The extract also holds Fields 2 and 3; the comparison uses Field 1 only, as the paper's headline limits do. This is not a likelihood analysis. A proper constraint would treat the correlated limits in a statistical model.

## Checklist

- Check the SHA-256 of each file against MANIFEST.json before running.
- Run with python3 -I and compare your output with expected-output.json.
- Confirm the seven limits, and especially the two headline values, against the paper.
- Keep negative estimates at zero, add $2\sigma$, and use every other bin.
- Pass models through the window rows and keep $k$ in $h\,\mathrm{Mpc^{-1}}$ once.
- Label HERA numbers as real observation and model numbers as ideal reference wherever you plot them.

## Try it in the Lab

[21 cm cosmic dawn and radio foregrounds](https://sandboxphysics.com/labs/cosmic-dawn-21cm-foregrounds/): Try the cold-hydrogen preset and compare its HERA ratio with your script's output.

## Sources

1. [HERA Collaboration 2022, Data section](https://arxiv.org/abs/2108.02263v1)
2. [hera\_pspec conversions.py](https://github.com/HERA-Team/hera_pspec/blob/30c77f02567e87a2db36cdc2f92adef4552a43f1/hera_pspec/conversions.py)
3. [Eisenstein and Hu 1998](https://arxiv.org/abs/astro-ph/9709112v1)
4. [HERA Public Data Release 1, notebook](https://reionization.org/science/public-data-release-1/)

## Keep reading

Hearing the first stars in 21 cm hydrogen · Reading path

### From hydrogen brightness to a HERA upper limit

1. [Article **Finding faint early hydrogen under a bright radio sky**](https://sandboxphysics.com/stories/cosmic-dawn-21cm/finding-hydrogen-under-radio-foregrounds/)
2. [Article **Why early hydrogen glows or casts a shadow at 21 cm**](https://sandboxphysics.com/stories/cosmic-dawn-21cm/spin-temperature-and-21cm-brightness/)
3. [Article **How one baseline separates smooth foregrounds from hydrogen**](https://sandboxphysics.com/stories/cosmic-dawn-21cm/delay-spectrum-and-foreground-wedge/)
4. [Article **Turning delay power into a bandpower without losing the signal**](https://sandboxphysics.com/stories/cosmic-dawn-21cm/power-spectrum-window-and-signal-loss/)
5. [You are here **Recompute HERA's upper limits and compare a model through its window**](https://sandboxphysics.com/stories/cosmic-dawn-21cm/recompute-hera-window-comparison/)
6. [Article **Reading how HERA kept foregrounds out of its first limits**](https://sandboxphysics.com/stories/cosmic-dawn-21cm/reading-hera-foreground-avoidance/)
