Skip to content
Open
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
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The published limits are included in human-readable yaml files in the data folde

To use the code, check out the _Usage and examples_. For users who want to quickly explore the limits and make plots without needing to install anything, check out the new online interface: [eorlimits.streamlit.app](https://eorlimits.streamlit.app/)!

![Example EoR Limit plot](docs/source/_static/eor_limits.png)
![Example EoR Limit plot](docs/source/_static/test_lib_plot_vs_k_basic.png)

## Installation and dependencies

Expand All @@ -32,25 +32,25 @@ To use the code, check out the _Usage and examples_. For users who want to quick

## Usage and examples

There are three main ways to use the code: through the online interface, as a library within a notebook or python script, or through the command line interface (CLI).
There are three main ways to use `eor-limits`: through the online graphical user interface (GUI), through the Python API in a notebook or script, or through the command line interface (CLI).

### Using the online interface
### Using the online GUI

We recommend using the online interface for users who just want to explore the limits and make plots without needing to install anything. The interface is built using [Streamlit](https://streamlit.io/) and provides an easy-to-use interface for selecting which limits to include in the plot, filtering them in various ways, and downloading the data and the plot. You can access the online interface at [eorlimits.streamlit.app](https://eorlimits.streamlit.app/).
The online GUI is the quickest way to explore published limits and generate plots without installing anything locally. It is built with [Streamlit](https://streamlit.io/) and lets you select data sets, apply filters, customize the display, and download both the data and resulting figures. You can access it at [eorlimits.streamlit.app](https://eorlimits.streamlit.app/).

### Using the library
### Using the Python API

The library also allows you to load, slice and dice the data in various ways, and also includes plotting functionality. For a detailed tutorial on how to use the library, see the _Tutorial notebook_. Here we just give a brief overview of how to make plots. To make the default plot of all the limits as a function of scale $k$, run:
The Python API provides tools for loading, filtering, and plotting the included data sets. For a more complete walkthrough, see the _Tutorial notebook_. Here we just give a brief overview of how to make plots. The two main plotting functions are `plot_vs_k` and `plot_vs_z`, which show limits as a function of scale $k$ and redshift $z$, respectively. To make the default plot versus $k$, run:

```python
from eor_limits import plot_vs_k
from eor_limits import plot_vs_k, plot_vs_z
plot_vs_k()
```

A more customized plot can be also be made. For example, we can plot the HERA limits, shading the 2023 ones and bolding the legend item, and Mesinger2016Faint and Mesinger2016Bright simulations with different colors and shaded regions:
The plotting functions accept keyword arguments to choose which limits and simulations to include, customize their styles, and save the output. For example, the following code plots the HERA limits, shades the 2023 result, bolds the HERA 2026 legend item, and adds the `Mesinger2016Faint` and `Mesinger2016Bright` simulations with custom colors and shaded regions:

```python
from eor_limits import plot_vs_k
from eor_limits import plot_vs_k, plot_vs_z
plot_vs_k(
limits=["HERA2022", "HERA2023", "HERA2026"],
bold_limits=["HERA2026"],
Expand All @@ -72,13 +72,15 @@ plot_vs_k(

### Using the CLI

After installation, you can also use the `eor-limits` command from the terminal to make plots. In the terminal, you can run ```eor-limits -h``` or ```eor-limits plot-vs-k -h``` to see the various options for customizing the plot. The CLI provides the same functionality as the library, but allows you to make plots without needing to write any code. For the default plot of all the limits as a function of scale $k$, you can simply run:
After installation, you can use the `eor-limits` command to make plots from the terminal. Run `eor-limits -h`, `eor-limits plot-vs-k -h`, or `eor-limits plot-vs-z -h` to see the available options.

For the default plot of all limits as a function of scale $k$, run:

```bash
eor-limits plot-vs-k --out=MyPlot.pdf
```

To make the same customized plot as in the library example, the command allows for JSON dictionaries as arguments for the various `-style` options, so you can run:
The CLI exposes the same plotting options as the Python API. Dictionary-style options, such as custom limit or theory styles, can be passed as JSON strings:

```bash
eor-limits plot-vs-k \
Expand Down
15 changes: 15 additions & 0 deletions agents.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Environment

- Use the `uv` python environment to run code.

## Tests

- Write tests using the pytest framework, in `tests/`
- Run narrow tests based on implemented features first, using `uv run pytest -k "test-identifier"`
- Always write a failing test before fixing a bug.
- Write tests of intended behaviour before implementing a feature.

## Style

- Prefer adding type annotations for new parameters and functions, wherever reasonable.
- Always run `uv run ruff format` and `ruff check --fix` before closing the loop.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@

# Autosummary
autosummary_generate = True # Automatically generate summary files for documented items
# nbsphinx
nbsphinx_kernel_name = "python3" # Use the standard Python kernel for notebook builds
# Autodoc
autodoc_typehints = "none" # No type hints, let numpydoc handle them in the docstrings
# Numpydoc
Expand Down
181 changes: 109 additions & 72 deletions docs/source/tutorial.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
" KNOWN_LIMITS,\n",
" KNOWN_THEORIES,\n",
" load_limit_data,\n",
" load_theory_model,\n",
" plot_vs_k,\n",
" plot_vs_z,\n",
")\n",
"\n",
"# KNOWN_LIMITS and KNOWN_THEORIES are both dictionaries with the keys being the names\n",
Expand Down Expand Up @@ -100,7 +100,7 @@
"id": "ef476426",
"metadata": {},
"source": [
"What about looking at a specific $k$-bin or $z$-bin? Let's try selecting the redshift bin closest to $z=7$ and also, separately, the $k$-bin closest to $k=0.1$ h/Mpc."
"Similarly, we can try selecting the redshift bin closest to $z=7$ and, separately, the $k$-bin closest to $k=0.1$ h/Mpc."
]
},
{
Expand All @@ -127,93 +127,56 @@
},
{
"cell_type": "markdown",
"id": "8b5df718",
"id": "d37e130a",
"metadata": {},
"source": [
"## Custom plotting\n",
"\n",
"Let's plot the limits, now including other HERA limits and some theoretical models for comparison. The theory models are loaded in the same manner as the limits so we can filter and plot them all together as shown in the next cell."
"Finally, let's select the lowest limits, first per redshift bin (`per_z=True, per_tag=False` which is default), and then across all redshift bins (`per_z=False, per_tag=False`)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "963e30b5",
"id": "db12d2e0",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))\n",
"\n",
"datasets = [\n",
" load_limit_data(\"HERA2022\"),\n",
" load_limit_data(\"HERA2023\"),\n",
" load_limit_data(\"HERA2026\"),\n",
" load_theory_model(\"Mesinger2016Faint\"),\n",
" load_theory_model(\"Mesinger2016Bright\"),\n",
"]\n",
"labels = [\n",
" \"Phase 1 preliminary\",\n",
" \"Phase 1 final\",\n",
" \"Phase 2 preliminary\",\n",
" \"Faint galaxies\",\n",
" \"Bright galaxies\",\n",
"]\n",
"colors = [\"C0\", \"C1\", \"C2\", \"C3\", \"C4\"]\n",
"markers = [\"v\", \"v\", \"v\", \"none\", \"none\"]\n",
"\n",
"for dataset, label, color, marker in zip(\n",
" datasets, labels, colors, markers, strict=True\n",
"):\n",
" # Plotting the limits for the redshift bin closest to z=7\n",
" # (k range included to limit the theory models to the data range)\n",
" data_z7 = dataset.select_closest_z(7).select_k_range(1e-1, 5).data\n",
" ax1.plot(\n",
" data_z7.k[0],\n",
" data_z7.delta_squared[0],\n",
" marker=marker,\n",
" color=color,\n",
" label=label + f\" (z={data_z7.z[0]:.2f})\",\n",
" )\n",
"\n",
" # Plotting the limits for the k-bin closest to k=0.1 h/Mpc\n",
" # (z range included to limit the theory models to the data range)\n",
" data_k02 = dataset.select_closest_k(0.1).select_z_range(6, 30).data\n",
" ax2.plot(\n",
" data_k02.z, data_k02.delta_squared, marker=marker, color=color, label=label\n",
" )\n",
"\n",
" # Some shading for the theory models\n",
" if \"galaxies\" in label:\n",
" ax1.fill_between(data_z7.k[0], data_z7.delta_squared[0], alpha=0.1, color=color)\n",
"\n",
"# Some plot formatting\n",
"ax1.set_title(r\"at $z \\approx 7$\")\n",
"ax1.set_xlabel(r\"Scale $k$ (h/Mpc)\")\n",
"ax1.set_xscale(\"log\")\n",
"ax2.set_title(r\"at $k \\approx 0.1$ h/Mpc\")\n",
"ax2.set_xlabel(r\"Redshift $z$\")\n",
"ax1.legend()\n",
"ax2.legend()\n",
"for ax in [ax1, ax2]:\n",
" ax.set_ylabel(r\"$\\Delta_{21}^2$ (mK$^2$)\")\n",
" ax.set_yscale(\"log\")\n",
" ax.grid()\n",
"\n",
"fig.suptitle(\"HERA Power Spectrum Limits\")\n",
"fig.tight_layout()\n",
"fig.show()"
"hera2026_lowest = hera2026.select_lowest_delta_squared()\n",
"hera2026_lowest.data.as_pandas_df()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "148b9b31",
"metadata": {},
"outputs": [],
"source": [
"hera2026_lowest = hera2026.select_lowest_delta_squared(per_z=False, per_tag=False)\n",
"hera2026_lowest.data.as_pandas_df()"
]
},
{
"cell_type": "markdown",
"id": "535aa0c4",
"metadata": {},
"source": [
"## In-built plotting\n",
"\n",
"A similar plot can be made using the in-built plotting function `plot_vs_k()`, which takes care of all the slicing and styling for you. This plot differs slightly, in that we are not making narrow selection cuts but plotting all the data within $z=7-8$ coloured by redshift bins."
"## In-built plotting"
]
},
{
"cell_type": "markdown",
"id": "368850b5",
"metadata": {},
"source": [
"### Plot vs k"
]
},
{
"cell_type": "markdown",
"id": "85c9934c",
"metadata": {},
"source": [
"Let's plot the HERA limits, including ome theoretical models for comparison, using the in-built plotting function `plot_vs_k()`. The function includes various options for slicing and styling, and color-codes the limits by redshift bin. For example:"
]
},
{
Expand Down Expand Up @@ -242,6 +205,80 @@
")\n",
"fig.show()"
]
},
{
"cell_type": "markdown",
"id": "a3920635",
"metadata": {},
"source": [
"### Plot vs redshift"
]
},
{
"cell_type": "markdown",
"id": "1493f8c6",
"metadata": {},
"source": [
"Similarly, the in-built function `plot_vs_z()` allows you to plot the lowest limits (across $k$-bins) as a function of redshift. The function includes similar options for slicing and styling, and color-codes the limits by year of publication. For example:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7025f243",
"metadata": {},
"outputs": [],
"source": [
"fig = plot_vs_z(\n",
" fig_width=20.0,\n",
" fontsize=20,\n",
" legend_ncols=3,\n",
" theories=[\"Mesinger2016Faint\", \"Mesinger2016Bright\"],\n",
" z_range=(5.5, 15),\n",
" limit_styles={\n",
" \"HERA2022\": {\"s\": 500},\n",
" \"HERA2023\": {\"s\": 500},\n",
" \"HERA2026\": {\"s\": 500},\n",
" },\n",
")\n",
"fig.show()"
]
},
{
"cell_type": "markdown",
"id": "4a284a87",
"metadata": {},
"source": [
"You can even combine the limit styling with custom legends to accentuate a particular set of observations."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3e1861af",
"metadata": {},
"outputs": [],
"source": [
"fig = plot_vs_z(\n",
" fig_width=20.0,\n",
" fontsize=20,\n",
" legend_ncols=2,\n",
" theories=[\"Mesinger2016Faint\", \"Mesinger2016Bright\"],\n",
" z_range=(5.5, 15),\n",
" base_limit_style={\"s\": 200, \"marker\": \"o\", \"color\": \"gray\"},\n",
" limit_styles={\n",
" \"Nunhokee2025\": {\"s\": 300, \"linewidth\": 5, \"marker\": \"s\", \"color\": \"magenta\"},\n",
" \"Trott2025\": {\"s\": 300, \"linewidth\": 5, \"marker\": \"s\", \"color\": \"blue\"},\n",
" },\n",
" legend_labeler={\n",
" \"Nunhokee2025\": \"Nunhokee et al. 2025\",\n",
" \"Trott2025\": \"Trott et al. 2025\",\n",
" \"Mesinger2016Faint\": \"Mesinger et al. 2016 faint\",\n",
" \"Mesinger2016Bright\": \"Mesinger et al. 2016 bright\",\n",
" },\n",
")\n",
"fig.show()"
]
}
],
"metadata": {
Expand Down
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies = [
"pandas>=3.0.0",
"pyyaml>=6.0.3",
"rich>=14.3.1",
"scipy>=1.14.0",
]
urls = { Repository = "https://github.com/EoRImaging/eor_limits"}
license = { file = "LICENSE" }
Expand All @@ -44,6 +45,8 @@ source = "uv-dynamic-versioning"
[dependency-groups]
dev = [
"coverage>=7.13.2",
"ipykernel>=7.3.0",
"pip>=26.1.2",
Comment on lines +48 to +49

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are these being added to the dev group? Surely pip is installed already since uv uses it. And why ipykernel vs jupyter?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uv actually does not use pip so it needs to be installed explicitly if you want it. I added these so that I could use the uv environment as a jupyter kernel in VSCode. I wasn't entirely sure if this is a good idea to add here. They are dev requirements, but only because I was developing in a particular modality. I can remove them if we think that's better.

"pre-commit>=4.5.1",
"pytest>=9.0.2",
"pytest-cov>=7.0.0",
Expand Down
3 changes: 2 additions & 1 deletion src/eor_limits/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
load_theory_model,
)
from ._datatypes import Data, DataSet
from ._plot import plot_vs_k, plot_vs_z
from ._plot import get_latex_label, plot_vs_k, plot_vs_z
from .data import KNOWN_LIMITS
from .theory import KNOWN_THEORIES

Expand All @@ -19,6 +19,7 @@
"KNOWN_THEORIES",
"Data",
"DataSet",
"get_latex_label",
"load_limit_data",
"load_theory_model",
"plot_vs_k",
Expand Down
Loading
Loading