Show the code
from IPython.display import Markdown
from tabulate import tabulate
from astropy.table import Table
from types import MethodType
from format_multiple_errors import format_multiple_errors
from numbers import Real
import numpy as np
import math
def format_cell(x,
exponential=False,
digits=2):
"""
Render a single table cell in latex depending on the type of x:
- scalar -> single value
- 1-tuple/list/np.array (value,) -> treat like scalar
- 2-tuple/list/np.array (value, err) -> value ± err
- 3-tuple/list/np.array (value, err_minus, err_plus) -> value_{-err_minus}^{+err_plus}
Formatted as exponential if exponential = True, with the indicated number of digits.
Format overrides may also be specified in a dictionary at the end of the tuple.
Non-numerical values are returned as string unchanged.
"""
# TODO: improve automatic choice of exponential and digits value when unspecified
# Missing value
if x is None:
return "—"
list_formats = (list, tuple, np.ndarray)
numeric_formats = (Real, np.floating, np.integer)
# Scalar number
fmt = f".{digits}{'e' if exponential else 'f'}" # Format
if isinstance(x, np.ndarray) and x.ndim == 0: # Regularize potential ndarray 0D (e.g. np.array(value)) to python scalars
x = x.item()
if isinstance(x, numeric_formats): # Plain scalar value
return fr"${x:{fmt}}$"
if isinstance(x, list_formats) and len(x) == 1: # Or 1-tuple -> treat like scalar
value = x[0]
if isinstance(value, numeric_formats):
return fr"${value:{fmt}}$"
# Significant figures given digits
def sigfig(digits, value):
e = 0 if value == 0 else int(math.floor(math.log10(abs(value))))
return max(1, digits + e + 1) if not exponential else digits + 1
# 2-tuple symmetric uncertainty
if isinstance(x, list_formats) and len(x) == 2 and all(isinstance(v, numeric_formats) for v in x):
value, err = x
return rf"${format_multiple_errors(value, err, exponential=exponential, significant_figures=sigfig(digits, value), length_control='central', latex=True)}$"
# 3-tuple asymmetric uncertainty
if isinstance(x, list_formats) and len(x) == 3 and all(isinstance(v, numeric_formats) for v in x):
value, err_lower, err_upper, = x
return rf"${format_multiple_errors(value, (err_upper, err_lower), exponential=exponential, significant_figures=sigfig(digits, value), length_control='central', latex=True)}$"
# Special case: entry includes explicit format overrides as a dictionary in the last element of the tuple
if isinstance(x, list_formats) and isinstance(x[-1], dict):
*values, fmt_overrides = x
note = fmt_overrides.pop("note", "") # Return value associated to the key and remove entry from dictionary (otherwise format_cell() produces an error)
fmt_merged = {
"exponential": exponential,
"digits": digits,
**fmt_overrides
} # Shallow merge: if duplicate key in dictionary, take the last one, effectively overriding the specified format parameters
values_unpacked = values[0] if len(values) == 1 else tuple(values)
return format_cell(values_unpacked, **fmt_merged) + note
# Fallback: try to convert to string, or raise exception
try:
return str(x)
except:
raise ValueError(f"Unrecognized cell format for entry {x}")
def table_to_markdown(tbl,
exponential=False,
digits=2,
col_fmt_overrides=None,
headers=None,
**kwargs):
"""
Convert an Astropy Table into a Markdown table, formatting every cell through the format_cell() function.
Formatting instructions passed to format_cell() can be overridden for specific columns through the col_fmt_overrides field
"""
default_fmt = {
"exponential": exponential,
"digits": digits
}
rows = []
for r in tbl:
row = []
for c in tbl.colnames:
if col_fmt_overrides is None:
fmt = default_fmt # Default format
else:
fmt = {**default_fmt, **col_fmt_overrides.get(c, {})} # Shallow merge: if duplicate key, take the last one, overriding the specified format parameters for current column
row.append(format_cell(r[c], **fmt))
rows.append(row)
if headers is None:
headers = tbl.colnames
md = tabulate(
rows,
headers,
**kwargs
)
return md
# ---------------- Example usage ----------------
# Map column name --> (header, units); TODO: units using astropy.units and converting when formatting header
colmap = {
"ID": ("Name", None),
"redshift": ("Redshift", None),
"OtoH": ("12 + log(O/H)", None),
"metallicity": ("Metallicity", r"Z$_\odot$"),
"MIII": (r"$M_\mathrm{III}$", r"M$_\odot$"),
"Mstar": (r"$M_\star$", r"M$_\odot$"),
"SFR": ("SFR", r"M$_\odot$yr$^{-1}$"),
"magnification": ("Lensed", None),
"MUV": (r"$M_{\rm UV}$", None),
"beta": (r"$\beta$-slope", None),
"HeII1640_flux": ("HeII1640 flux", r"erg s$^{-1}$ cm$^{-2}$"),
"HeII1640_EW": ("HeII1640 EW", "Å"),
"HeII1640_FWHM": ("HeII1640 FWHM", r"km s$^{-1}$"),
"HeII4686_flux": ("HeII4686 flux", r"erg s$^{-1}$ cm$^{-2}$"),
"HeII4686_EW": ("HeII4686 EW", "Å"),
"HeII4686_FWMH": ("HeII4686 FWHM", r"km s$^{-1}$"),
"OIII5007_flux": ("[OIII]5007 flux", r"erg s$^{-1}$ cm$^{-2}$"),
"OIII5007_EW": ("[OIII]5007 EW", "Å"),
"OIII5007_FWHM": ("[OIII]5007 FWHM", r"km s$^{-1}$"),
"OIIItoHb": (r"[OIII]/H$\beta$", None),
"Lya_flux": (r"Ly$\alpha$ flux", r"erg s$^{-1}$ cm$^{-2}$"),
"Lya_EW": (r"Ly$\alpha$ EW", "Å"),
"Lya_FWHM": (r"Ly$\alpha$ FWHM", r"km s$^{-1}$"),
"Ha_flux": (r"H$\alpha$ flux", r"erg s$^{-1}$ cm$^{-2}$"),
"Ha_EW": (r"H$\alpha$ EW", "Å"),
"Ha_FWHM": (r"H$\alpha$ FWHM", r"km s$^{-1}$"),
"Hb_flux": (r"H$\beta$ flux", r"erg s$^{-1}$ cm$^{-2}$"),
"Hb_EW": (r"H$\beta$ EW", "Å"),
"Hb_FWHM": (r"H$\beta$ FWHM", r"km s$^{-1}$"),
"Hg_flux": (r"H$\gamma$ flux", r"erg s$^{-1}$ cm$^{-2}$"),
"Hg_EW": (r"H$\gamma$ EW", "Å"),
"reference": ("References", None),
}
names = tuple(colmap.keys())
headers = tuple(
(fr"{label}<br>[{unit}]" if unit else f"{label}<br> ")
for (label, unit) in colmap.values()
)
# Setup table
table = Table(
names=names,
dtype=("object",)*len(names),
masked=True
)
# Minor patch of astropy table add_row method, so that missing values are set to None by default instead of 0
defaults = {c: None for c in table.colnames}
def add_row_with_defaults(self, row=None, *args, **kwargs):
if isinstance(row, dict):
row = {**defaults, **row}
return Table.add_row(self, row, *args, **kwargs)
table.add_row = MethodType(add_row_with_defaults, table)
# Column format overrides
col_fmt_overrides = {
"Mstar": {"exponential": True},
"MIII": {"exponential": True},
"Lya_flux": {"exponential": True},
"Ha_flux": {"exponential": True},
"Hb_flux": {"exponential": True},
"Hg_flux": {"exponential": True},
"HeII1640_flux": {"exponential": True},
"HeII4686_flux": {"exponential": True},
"OIII5007_flux": {"exponential": True},
}
# Notes style
class NoteManager:
def __init__(self):
self.map = {}
self.notes = []
def _label(self, i):
label = ""
while True:
label = chr(ord('a') + i % 26) + label
i = i // 26 - 1
if i < 0:
break
return label
def get_index(self, text):
if text not in self.map:
idx = len(self.notes)
self.map[text] = idx
self.notes.append(text)
return self.map[text]
def mark(self, text, color="red"):
idx = self.get_index(text)
label = self._label(idx)
return (
f'<a href="#note-{idx}" id="ref-{idx}">'
f'$^{{\\textcolor{{{color}}}{{({label})}}}}$'
f'</a>'
)
def render_notes_markdown(self):
blocks = []
for i, text in enumerate(self.notes):
label = self._label(i)
blocks.append(
f'<span id="note-{i}" style="font-size:75%">\n'
f'<a href="#ref-{i}">$^{{({label})}}$</a> {text}\n'
f'</span>\n'
)
return "\n".join(blocks)
nm = NoteManager()
def note(text):
return nm.mark(text)
# Fill table
table.add_row(dict(
ID="GNHeII J1236+6215",
redshift=(2.9803, 0.0010, {"digits": 4}),
magnification="No",
MUV=(-22.09, 0.02, {"digits": 2}),
beta=(-2.18, 0.06, {"digits": 2}),
Lya_flux=(23.0e-18, 5.4e-18, {"digits": 2}),
Lya_EW=(19.2),
Lya_FWHM=(758, 90, {"digits": 0}), # Note that values for the FWHMs are also given in A in Tab. 4
Ha_flux=(16.46e-18, 0.32e-18, {"digits": 3}),
Ha_EW=166.5,
Ha_FWHM=(268, 41, {"digits": 0}),
Hb_flux=(5.44e-18, 0.37e-18, {"digits": 2}),
Hb_EW=(26.6),
Hb_FWHM=(320, 137, {"digits": 0}),
HeII1640_flux=(8.8e-18, 1.8e-18),
HeII1640_EW=8.3,
HeII1640_FWHM=(573, 191, {"digits": 0}),
Mstar=(7.8e8, 3.1e8),
SFR=(12.2, 2.0, {"note": note(r"From photometric analysis, averaged over the last 10 Myr; from spectroscopic analysis: $\mathrm{SFR}_\mathrm{UV} = (9.8 \pm 0.1) ~\mathrm{M_\odot yr^{-1}}$, $\mathrm{SFR}_\mathrm{H\beta} = (7.6 \pm 0.4) ~\mathrm{M_\odot yr^{-1}}$, $\mathrm{SFR}_\mathrm{H\alpha} = (7.5 \pm 0.1) ~\mathrm{M_\odot yr^{-1}}$, $\mathrm{SFR}_\mathrm{Pa\beta} = (6.40 \pm 0.03) ~\mathrm{M_\odot yr^{-1}}$.")}), # From SED, i.e. the value reported in the abstract
OIII5007_flux=(59.6e-18, 2.2e-18, {"digits": 2}),
OIII5007_EW=248.8,
OIIItoHb=(5.45, 0.32, {"digits": 2}), # They also give HeII/Hbeta = 1.96 \pm 0.30, and HeII/Halpha = 0.69, 0.10, reported to closely match with the candidate from Wang+24
OtoH=(7.85, 0.22, {"digits": 2}),
metallicity=(0.003, 0.002, {"digits": 3}),
reference="@mondal2025"
))
table.add_row(dict(
ID="MPG-CR3",
redshift=(3.193, 0.016, {"digits": 3}),
magnification="No",
Lya_flux=(5.8e-17, 0.7e-17),
Lya_EW=(822, 101, {"digits": 0}),
Ha_flux=(4.2e-18, 0.6e-18, {"note": note("Includes a rescaling to account for potential flux losses, as the source lies near the edge of the MSA shutter.")}),
Ha_EW=(2814, 327, {"digits": 0}),
Hb_flux=(6.3e-19, 0.7e-19),
HeII1640_flux=(None, {"note": note("HeII1640 line coinciding with strong OH skyline for this object.")}),
MIII=6.1e5,
OIII5007_flux=r"$< 5.6 \times 10^{-19}$", # At 2sigma
OtoH=r"$< 6.52$",
metallicity=r"$< 8 \times 10^{-3}$",
reference="@cai2025"
))
table.add_row(dict(
ID="LAP2",
redshift=(4.189, 0.003, {"digits": 3}),
magnification=("Yes", {"note": note(r"The UV magnitude at 1700 Å for this source is de-lensed, while fluxes are not corrected for lensing. De-lensed fluxes were obtained by dividing by $\mu_\mathrm{tot}$, assuming a total magnification factor of $\mu_\mathrm{tot} = 50 \pm 5$.")}), # mu_tot = 50 \pm 5, mu_tang = 20 \pm 3
MUV=(r"$\approx -12.2$"), # M_1700
Mstar=r"$\approx (1.2 - 5.0) \times 10^4$",
Ha_flux=(1.68e-19, 0.30e-19, {"digits": 2}),
OIII5007_flux=r"$< 5 \times 10^{-20}$", # 2sigma upper limit
Hb_flux=(0.72e-19, 0.26e-19, {"digits": 1}),
Lya_flux=(26.4e-19, 3.8e-19, 3.7e-19, {"digits": 2, "note": note(r"From independent VLT/MUSE measure, $f_\mathrm{Ly\alpha} = (5.50 \pm 0.58) \times 10^{-18} ~\mathrm{erg \, s^{-1} \, cm^{-1}}$.")}),
Ha_EW=(647, 220, 302, {"digits": 0}),
metallicity=r"$< 0.006$",
OtoH=r"$< 6.5$",
HeII1640_EW=r"$< 80$", # 2sigma upper limit
reference="@vanzella2026"
))
table.add_row(dict(
ID=("CAPERS-UDS-32520", {"note": note(r"The authors also examined a companion that serendipitously lies across the slit mask (therefore dubbing the whole system \"banana and blueberry\" due to its morphology, possibly hinting to a disturbed, merger-like origin), finding clear signatures of H$\alpha$ emission, as well as potential HeI and HeII emission lines; however, they caution that photometric data for the \"blueberry\" system from the Minerva survey (@muzzin2025) strongly favor a lower-redshift solution at $z \sim 0.7$ (Willot, priv. comm.).")}),
redshift=(5.1240, 0.0002, {"digits": 4}),
magnification="No",
MUV=(-20.95, 0.05, {"digits": 2}),
beta=(-1.68, 0.05, {"digits": 2}),
Hg_flux=(2.8e-18, 0.3e-18, {"digits": 1}),
Hg_EW=(35, 4, {"digits": 0}),
Hb_flux=(4.3e-18, 0.3e-18, {"digits": 1}),
Hb_EW=(137, 13, {"digits": 0}),
OIII5007_flux=(29.6e-18, 0.4e-18, {"digits": 2}),
OIII5007_EW=(946, 46, {"digits": 0}),
Ha_flux=(13.8e-18, 0.2e-18, {"digits": 2}),
Ha_EW=(734, 33, {"digits": 0}),
OtoH=(7.88, 0.07, {"digits": 2}),
metallicity=r"$< 0.15$",
Mstar=r"$\sim 10^9$",
reference="@reumert2026"
))
table.add_row(dict(
ID="AMORE6",
redshift=(5.7253, 0.00005, {"digits": 4}),
magnification=("Yes", {"note": note("Properties for the stacked spectrum of the two images in the doubly lensed system, normalizing by the magnification factor of each image.")}), # $\mu = 39.32_{-3.48}^{+3.73}$ for AMORE6-A, vs $\mu = 77.69_{-5.92}^{+8.37}$ for AMORE6-B
MUV=(-14.52, 0.08, 0.07, {"digits": 2, "note": note(r"The absolute UV magnitude and the physical properties of AMORE6 from SED fitting are reported for only one of the two images (AMORE6-B), as the other one (AMORE6-A) suffers from large uncertainties, likely due to its location near bright galaxies as well as its smaller magnification factor ($\mu = 39.32_{-3.48}^{+3.73}$, vs $\mu = 77.69_{-5.92}^{+8.37}$ for AMORE6-B).")}),
beta=(-2.77, 0.09, 0.07, {"digits": 2}),
Lya_flux= (4.95e-19, 0.92e-19, {"digits": 2}), # From Lyalpha-to-Hbeta ratio = 10.01 \pm 1.4, propagating uncertainties
Hb_flux=(0.49e-19, 0.06e-19),
Hb_EW=(1594.7, 206.9),
Mstar=(4.37e5, 0.73e5, 2.24e5, {"digits": 2}),
SFR=(0.35, 0.06, {"digits": 2, "note": note(r"SFR inferred from H$\beta$, larger than the value inferred from rest-frame UV luminosity -- $(0.0186_{-0.0035}^{+0.0033}) ~\mathrm{M_\odot yr^{-1}}$ -- or from averaging over the last 100 Myr of the best-fit star-formation history -- $(0.0038_{-0.0007}^{+0.0017}) ~\mathrm{M_\odot yr^{-1}}$ --, suporting the presence of a very young burst.")}), # From Hbeta, converting from log to linear
OIII5007_flux=r"$< 1.1 \times 10^{-20}$", # Upper limits at 2sigma
OtoH=r"$< 5.78$",
metallicity=r"$< 0.0012$",
reference="@morishita2025"
))
'''
# Originally proposed by https://ui.adsabs.harvard.edu/abs/2025ApJ...989...46F/abstract, but fails two of the three updated color–color criteria of https://ui.adsabs.harvard.edu/abs/2025arXiv251211790F/abstract
table.add_row(dict(
ID="JOF-21739",
redshift=(6.17, 0.19, 0.06, {"digits": 2}),
magnification="Yes", # Value of magnification not indicated
MUV=(-17.62, 0.15, 0.17, {"digits": 2}),
beta=(-2.79, 0.05, {"digits": 2}),
Ha_EW=(3600, 430, {"digits": 0}),
MIII=r"$\sim 10^5 - 10^6$",
OIIItoHb=r"$< 0.32$",
OtoH=r"$< 6.2$",
metallicity=r"$< 0.003$",
reference="@fujimoto2025"
))
'''
'''
# Originally proposed by https://ui.adsabs.harvard.edu/abs/2025ApJ...989...46F/abstract, but rejected due to [OIII] detection in the spectrum (https://ui.adsabs.harvard.edu/abs/2025arXiv251211790F/abstract)
table.add_row(dict(
ID="GLIMPSE-1604",
redshift=(6.50, 0.24, 0.03, {"digits": 2}),
magnification="Yes", # mu = (2.9, 0.2, 0.1),
MUV=(-15.89, 0.14, 0.12, {"digits": 2}),
beta=(-2.34, 0.36, {"digits": 2}),
Ha_EW=(2810, 550, {"digits": 0}),
MIII=r"$\sim 10^5$",
OIIItoHb=r"$< 0.44$",
OtoH=r"$< 6.4$",
metallicity=r"$< 0.005$",
reference="@fujimoto2025"
))
'''
table.add_row(dict(
ID="LAP1",
redshift=(6.625, 0.001, {"digits": 3}),
magnification="Yes", # mu = 98
MUV=r"$> -10.4$",
Mstar=r"$\lesssim 2700$",
Lya_flux=(6.08e-19, 1.70e-19, {"digits": 2}), # All fluxes from tab. 1
Lya_EW=r"$> 250$",
Ha_flux=(2.07e-19, 0.25e-19, {"digits": 2}),
Ha_EW=r"$> 1800$", # at 3sigma, 880 at 5sigma
Hb_flux=(0.73e-19, 0.20e-19, {"digits": 1}),
Hb_EW=r"$> 340$", # at 3sigma, 170 at 5sigma
HeII1640_flux=(r"$\lesssim 1.85 \times 10^{-19}$", {"note": note(r"@vanzella2023 previously estimated a line flux for HeII1640 of $(7.96 \pm 2.07) \times 10^{-19} ~\mathrm{erg \, s^{-1} \, cm^{-2}}$; however, the reliability of the HeII line detection was hampered by the presence of a small blueshift relative to the Balmer lines, and by the extreme required EW ($\gtrsim 200$ Å), therefore the authors safely considered the line undetected, placing a $1\sigma$ upper limit of $2.7 \times 10^{-19} ~\mathrm{erg \, s^{-1} \, cm^{-2}}$. While @nakajima2025 also report no clear detection of the line, they provide an upper limit that remains within the range expected for zero-metallicity stellar populations. Also note that the stellar continuum is undetected for this source.")}),
OIII5007_flux=(0.50e-19, 0.15e-19, {"digits": 1}), # I could not find a constraint on the EW for the [OIII]5007 line
OIIItoHb=(0.69, 0.28, {"digits": 2}),
OtoH=(6.31, 0.23, 0.15, {"digits": 2}),
metallicity=(4.2e-3, 1.8e-3, {"exponential": True, "digits": 1, "note": note(r"The authors further highlighted an elevated carbon-to-oxygen ratio of $\sim 1 - 2$ times higher than the solar value, consistent with Pop III nucleosynthetic yields. This observation, together with the exceptionally hard ionizing radiation field, inconsistent with chemically enriched stellar populations or accreting black holes, establishes LAP1 as a candidate 'self-enriched' Pop III system or 'fossil in the making'.")}),
reference="@nakajima2025"
))
'''
# LAP1 properties from previous measure of Vanzella+23 (https://ui.adsabs.harvard.edu/abs/2023A%26A...678A.173V/abstract)
table.add_row(dict(
ID="LAP1",
redshift=(6.639, 0.004, {"digits": 3}),
magnification="Yes", # mu_tot(median) = (120, 9), mu_tang(median) = (55, 6, 2), mu_tot > 500 for images A1,A2, mu_tot=98,99 for B1,B2
MUV=r"$> -11.2$",
Mstar=r"$\lesssim 10^4$",
Lya_flux=(369.2e-20, 29.3e-20, {"digits": 3}),
Lya_EW=r"$> 370$",
Ha_flux=(69.4e-20, 5.5e-20, {"digits": 2}),
Ha_EW=r"$> 2020$",
Hb_flux=(26.3e-20, 2.7e-20, {"digits": 2}),
Hb_EW=r"$> 420$",
HeII1640_flux=(79.6e-20, 20.7e-20, {"digits": 2, "note": note("g")}),
OIII5007_flux=(14.5e-20, 3.4e-20, {"digits": 2}),
OIII5007_EW=r"$> 246$",
OIIItoHb=(0.55, 0.14, 0.15, {"digits": 2}),
OtoH=r"$< 6.3$",
metallicity=r"$< 0.004$",
reference="@vanzella2023"
))
'''
table.add_row(dict(
ID="RX J2129-z8HeII",
redshift=(8.1623, 0.0007, {"digits": 4}),
magnification="Yes", # mu = (2.26, 0.14),
MUV=(-19.58, 0.02, 0.03, {"digits": 2}),
beta=(-2.53, 0.07, 0.06, {"digits": 2}),
Mstar=(5.6e7, 0.7e7, 0.8e7), # Tot. stellar mass of the system LogM*/Msun = 7.75 \pm 0.06 from Tab. 1
MIII=(7.8e5, 1.4e5), # Mass of the putative Pop III component estimated from the HeII luminosity
SFR=(9.56, 1.70, 4.51, {"digits": 2}),
Hb_flux=(71e-20, 10e-20, {"note": note("Intrinsic line fluxes and upper limits are reported after applying corrections for lensing magnification and dust extinction, adopting $A_\mathrm{V} = 0.12 \pm 0.04$ from their spectro-photometric analysis.")}),
Hb_EW=(202, 34, {"digits": 0}),
HeII1640_flux=(120e-20, 22e-20, {"digits": 2}),
HeII1640_EW=(21, 4, {"digits": 0}),
HeII4686_flux=r"$< 1.6 \times 10^{-19}$", # 2sigma upper limits
HeII4686_EW=r"$< 49$",
OIII5007_flux=(390e-20, 10e-20, {"digits": 2}),
OIII5007_EW=(1015, 83, {"digits": 0}),
OIIItoHb=(5.5, 0.8),
OtoH=(7.63, 0.09, 0.14, {"digits": 2}),
metallicity=r"$\sim 0.1$", # Log(Zstar/Zsun) ~ -0.9
reference="@wang2024"
))
table.add_row(dict(
ID="EXCELS-63107",
redshift=(8.271, {"digits": 3}),
magnification="No",
MUV=(-19.9, 0.1),
beta=(-3.3, 0.3),
Mstar=(3.72e8, 3.36e8, 4.05e8, {"digits": 2, "note": note(r"Assuming an extended star-formation history in which the stellar mass is built up steadily, but with a recent ~3 Myr burst of star formation, forming a mass of $(2.24_{-2.13}^{+1.48}) \times 10^7 ~\mathrm{M_\odot}$.")}), # Assuming extended SF + recent burst model and converting from log to linear --> LogMstar/Msun = 8.57 -1.03 +0.32 to linear, with mass of the burst LogMburst/Msun = 7.35 -1.30 +0.22 (see Sec. 3.3 and Tab. 3)
SFR=(7.8, 0.6), # From Hbeta
Hb_flux=(10.69e-19, 0.84e-19, {"digits": 3}),
OIII5007_flux=(38.54e-19, 1.20e-19, {"digits": 3}),
OIIItoHb=(3.61, 0.30, {"digits": 2}),
OtoH=(6.89, 0.21, 0.26, {"digits": 2, "note": note("Though this system is not metal-free, the authors suggest that an effective temperature $\gtrsim 80000$ K for the ionizing source is necessary (with no obvious sign of AGN heating), hardly explained with a standard IMF, and that exotic scenarios such as Pop III star formation within a mildly enriched halo would be consistent with the observation.")}), # The authors report that this is one of the lowest directly constrained oxygen abundances measured in any galaxy to date, and $\sim 10 \times$ lower than is typical for $z \simeq 8$ galaxies with the same stellar mass
metallicity=(0.016, {"digits": 3}),
reference="@cullen2025"
))
table.add_row(dict(
ID="Hebe (GN-z11)",
redshift=(10.5862, 0.003, {"digits": 4}), # From Ubler+26
magnification=("No", {"note": note("Although measured fluxes need to be corrected for a small magnification factor of 1.42, which is not accounted for in the reported line fluxes; see table 1 of @maiolino2026 for the corresponding de-lensed line luminosities.")}),
MIII=r"$\sim 2 \times 10^4 - 6 \times 10^5$", # From Rusta+26
OtoH=r"$< 6.96$", # 3sigma upper limits on 12+log(O/H) and Zgas from Ubler+26
metallicity=(r"$< 0.019$", {"digits": 4}),
HeII1640_flux=(1.11e-19, 0.17e-19, {"digits": 2}), # Total fluxes and EWs from Tab. 1 of Maiolino+26
HeII1640_EW=r"$> 47$",
Lya_flux=r"$< 1.5 \times 10^{-18}$", # 3sigma upper limit from Sec. 8 of Maiolino+26
Hg_flux=(4.1e-20, 0.7e-20, {"digits": 1}), # Hg flux and EW from Ubler+26
Hg_EW=r"$> 350$",
reference="@maiolino2026, @ubler2026, @rusta2026"
))
'''
TODO:
- add Balmer jump to the table, where available
- check objects from Tiger's table https://docs.google.com/spreadsheets/d/1fUcRK6AGNtIf2qHyW31bLb2BuDMquJHNq7YIJ3zk8yc/edit?gid=0#gid=0 --> other page with possible Pop III descendants?
'''
# Markdown table
md = table_to_markdown(table, tablefmt="github", headers=headers, exponential=False, digits=1, col_fmt_overrides=col_fmt_overrides)
# Rendering including footnotes (we create two separate div for table and notes, so that the scrollable bar is immediately after the table instead of after the note list)
html = f"""
<div style="overflow-x: auto; width: 100%;">
{md}
</div>
{nm.render_notes_markdown()}
"""
Markdown(html)| Name |
Redshift |
12 + log(O/H) |
Metallicity [Z\(_\odot\)] |
\(M_\mathrm{III}\) [M\(_\odot\)] |
\(M_\star\) [M\(_\odot\)] |
SFR [M\(_\odot\)yr\(^{-1}\)] |
Lensed |
\(M_{\rm UV}\) |
\(\beta\)-slope |
HeII1640 flux [erg s\(^{-1}\) cm\(^{-2}\)] |
HeII1640 EW [Å] |
HeII1640 FWHM [km s\(^{-1}\)] |
HeII4686 flux [erg s\(^{-1}\) cm\(^{-2}\)] |
HeII4686 EW [Å] |
HeII4686 FWHM [km s\(^{-1}\)] |
[OIII]5007 flux [erg s\(^{-1}\) cm\(^{-2}\)] |
[OIII]5007 EW [Å] |
[OIII]5007 FWHM [km s\(^{-1}\)] |
[OIII]/H\(\beta\) |
Ly\(\alpha\) flux [erg s\(^{-1}\) cm\(^{-2}\)] |
Ly\(\alpha\) EW [Å] |
Ly\(\alpha\) FWHM [km s\(^{-1}\)] |
H\(\alpha\) flux [erg s\(^{-1}\) cm\(^{-2}\)] |
H\(\alpha\) EW [Å] |
H\(\alpha\) FWHM [km s\(^{-1}\)] |
H\(\beta\) flux [erg s\(^{-1}\) cm\(^{-2}\)] |
H\(\beta\) EW [Å] |
H\(\beta\) FWHM [km s\(^{-1}\)] |
H\(\gamma\) flux [erg s\(^{-1}\) cm\(^{-2}\)] |
H\(\gamma\) EW [Å] |
References |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| GNHeII J1236+6215 | \(2.9803 \pm 0.0010\) | \(7.85 \pm 0.22\) | \(0.003 \pm 0.002\) | — | \((7.8 \pm 3.1) \times 10^{8}\) | \(12.2 \pm 2.0\)\(^{\textcolor{red}{(a)}}\) | No | \(-22.09 \pm 0.02\) | \(-2.18 \pm 0.06\) | \((8.8 \pm 1.8) \times 10^{-18}\) | \(8.3\) | \(573 \pm 191\) | — | — | — | \((5.96 \pm 0.22) \times 10^{-17}\) | \(248.8\) | — | \(5.45 \pm 0.32\) | \((2.30 \pm 0.54) \times 10^{-17}\) | \(19.2\) | \(758 \pm 90\) | \((1.646 \pm 0.032) \times 10^{-17}\) | \(166.5\) | \(268 \pm 41\) | \((5.44 \pm 0.37) \times 10^{-18}\) | \(26.6\) | \(320 \pm 137\) | — | — | Mondal et al. (2025) |
| MPG-CR3 | \(3.193 \pm 0.016\) | \(< 6.52\) | \(< 8 \times 10^{-3}\) | \(6.1e+05\) | — | — | No | — | — | —\(^{\textcolor{red}{(c)}}\) | — | — | — | — | — | \(< 5.6 \times 10^{-19}\) | — | — | — | \((5.8 \pm 0.7) \times 10^{-17}\) | \(822 \pm 101\) | — | \((4.2 \pm 0.6) \times 10^{-18}\)\(^{\textcolor{red}{(b)}}\) | \(2814 \pm 327\) | — | \((6.3 \pm 0.7) \times 10^{-19}\) | — | — | — | — | Cai et al. (2025) |
| LAP2 | \(4.189 \pm 0.003\) | \(< 6.5\) | \(< 0.006\) | — | \(\approx (1.2 - 5.0) \times 10^4\) | — | Yes\(^{\textcolor{red}{(d)}}\) | \(\approx -12.2\) | — | — | \(< 80\) | — | — | — | — | \(< 5 \times 10^{-20}\) | — | — | — | \((2.64 {}^{+0.37}_{-0.38}) \times 10^{-18}\)\(^{\textcolor{red}{(e)}}\) | — | — | \((1.68 \pm 0.30) \times 10^{-19}\) | \(647 {}^{+302}_{-220}\) | — | \((7.2 \pm 2.6) \times 10^{-20}\) | — | — | — | — | Vanzella et al. (2026) |
| CAPERS-UDS-32520\(^{\textcolor{red}{(f)}}\) | \(5.1240 \pm 0.0002\) | \(7.88 \pm 0.07\) | \(< 0.15\) | — | \(\sim 10^9\) | — | No | \(-20.95 \pm 0.05\) | \(-1.68 \pm 0.05\) | — | — | — | — | — | — | \((2.96 \pm 0.04) \times 10^{-17}\) | \(946 \pm 46\) | — | — | — | — | — | \((1.38 \pm 0.02) \times 10^{-17}\) | \(734 \pm 33\) | — | \((4.3 \pm 0.3) \times 10^{-18}\) | \(137 \pm 13\) | — | \((2.8 \pm 0.3) \times 10^{-18}\) | \(35 \pm 4\) | Reumert et al. (2026) |
| AMORE6 | \(5.7253 \pm 0.0001\) | \(< 5.78\) | \(< 0.0012\) | — | \((4.37 {}^{+2.24}_{-0.73}) \times 10^{5}\) | \(0.35 \pm 0.06\)\(^{\textcolor{red}{(i)}}\) | Yes\(^{\textcolor{red}{(g)}}\) | \(-14.52 {}^{+0.07}_{-0.08}\)\(^{\textcolor{red}{(h)}}\) | \(-2.77 {}^{+0.07}_{-0.09}\) | — | — | — | — | — | — | \(< 1.1 \times 10^{-20}\) | — | — | — | \((4.95 \pm 0.92) \times 10^{-19}\) | — | — | — | — | — | \((4.9 \pm 0.6) \times 10^{-20}\) | \(1594.7 \pm 206.9\) | — | — | — | Morishita et al. (2025) |
| LAP1 | \(6.625 \pm 0.001\) | \(6.31 {}^{+0.15}_{-0.23}\) | \((4.2 \pm 1.8) \times 10^{-3}\)\(^{\textcolor{red}{(k)}}\) | — | \(\lesssim 2700\) | — | Yes | \(> -10.4\) | — | \(\lesssim 1.85 \times 10^{-19}\)\(^{\textcolor{red}{(j)}}\) | — | — | — | — | — | \((5.0 \pm 1.5) \times 10^{-20}\) | — | — | \(0.69 \pm 0.28\) | \((6.08 \pm 1.70) \times 10^{-19}\) | \(> 250\) | — | \((2.07 \pm 0.25) \times 10^{-19}\) | \(> 1800\) | — | \((7.3 \pm 2.0) \times 10^{-20}\) | \(> 340\) | — | — | — | Nakajima et al. (2025) |
| RX J2129-z8HeII | \(8.1623 \pm 0.0007\) | \(7.63 {}^{+0.14}_{-0.09}\) | \(\sim 0.1\) | \((7.8 \pm 1.4) \times 10^{5}\) | \((5.6 {}^{+0.8}_{-0.7}) \times 10^{7}\) | \(9.56 {}^{+4.51}_{-1.70}\) | Yes | \(-19.58 {}^{+0.03}_{-0.02}\) | \(-2.53 {}^{+0.06}_{-0.07}\) | \((1.20 \pm 0.22) \times 10^{-18}\) | \(21 \pm 4\) | — | \(< 1.6 \times 10^{-19}\) | \(< 49\) | — | \((3.90 \pm 0.10) \times 10^{-18}\) | \(1015 \pm 83\) | — | \(5.5 \pm 0.8\) | — | — | — | — | — | — | \((7.1 \pm 1.0) \times 10^{-19}\)\(^{\textcolor{red}{(l)}}\) | \(202 \pm 34\) | — | — | — | Wang et al. (2024) |
| EXCELS-63107 | \(8.271\) | \(6.89 {}^{+0.26}_{-0.21}\)\(^{\textcolor{red}{(n)}}\) | \(0.016\) | — | \((3.72 {}^{+4.05}_{-3.36}) \times 10^{8}\)\(^{\textcolor{red}{(m)}}\) | \(7.8 \pm 0.6\) | No | \(-19.9 \pm 0.1\) | \(-3.3 \pm 0.3\) | — | — | — | — | — | — | \((3.854 \pm 0.120) \times 10^{-18}\) | — | — | \(3.61 \pm 0.30\) | — | — | — | — | — | — | \((1.069 \pm 0.084) \times 10^{-18}\) | — | — | — | — | Cullen et al. (2025) |
| Hebe (GN-z11) | \(10.5862 \pm 0.0030\) | \(< 6.96\) | \(< 0.019\) | \(\sim 2 \times 10^4 - 6 \times 10^5\) | — | — | No\(^{\textcolor{red}{(o)}}\) | — | — | \((1.11 \pm 0.17) \times 10^{-19}\) | \(> 47\) | — | — | — | — | — | — | — | — | \(< 1.5 \times 10^{-18}\) | — | — | — | — | — | — | — | — | \((4.1 \pm 0.7) \times 10^{-20}\) | \(> 350\) | Maiolino et al. (2026), Übler et al. (2026), Rusta et al. (2026) |
\(^{(a)}\) From photometric analysis, averaged over the last 10 Myr; from spectroscopic analysis: \(\mathrm{SFR}_\mathrm{UV} = (9.8 \pm 0.1) ~\mathrm{M_\odot yr^{-1}}\), \(\mathrm{SFR}_\mathrm{H\beta} = (7.6 \pm 0.4) ~\mathrm{M_\odot yr^{-1}}\), \(\mathrm{SFR}_\mathrm{H\alpha} = (7.5 \pm 0.1) ~\mathrm{M_\odot yr^{-1}}\), \(\mathrm{SFR}_\mathrm{Pa\beta} = (6.40 \pm 0.03) ~\mathrm{M_\odot yr^{-1}}\).
\(^{(b)}\) Includes a rescaling to account for potential flux losses, as the source lies near the edge of the MSA shutter.
\(^{(c)}\) HeII1640 line coinciding with strong OH skyline for this object.
\(^{(d)}\) The UV magnitude at 1700 Å for this source is de-lensed, while fluxes are not corrected for lensing. De-lensed fluxes were obtained by dividing by \(\mu_\mathrm{tot}\), assuming a total magnification factor of \(\mu_\mathrm{tot} = 50 \pm 5\).
\(^{(e)}\) From independent VLT/MUSE measure, \(f_\mathrm{Ly\alpha} = (5.50 \pm 0.58) \times 10^{-18} ~\mathrm{erg \, s^{-1} \, cm^{-1}}\).
\(^{(f)}\) The authors also examined a companion that serendipitously lies across the slit mask (therefore dubbing the whole system "banana and blueberry" due to its morphology, possibly hinting to a disturbed, merger-like origin), finding clear signatures of H\(\alpha\) emission, as well as potential HeI and HeII emission lines; however, they caution that photometric data for the "blueberry" system from the Minerva survey (Muzzin et al. (2025)) strongly favor a lower-redshift solution at \(z \sim 0.7\) (Willot, priv. comm.).
\(^{(g)}\) Properties for the stacked spectrum of the two images in the doubly lensed system, normalizing by the magnification factor of each image.
\(^{(h)}\) The absolute UV magnitude and the physical properties of AMORE6 from SED fitting are reported for only one of the two images (AMORE6-B), as the other one (AMORE6-A) suffers from large uncertainties, likely due to its location near bright galaxies as well as its smaller magnification factor (\(\mu = 39.32_{-3.48}^{+3.73}\), vs \(\mu = 77.69_{-5.92}^{+8.37}\) for AMORE6-B).
\(^{(i)}\) SFR inferred from H\(\beta\), larger than the value inferred from rest-frame UV luminosity – \((0.0186_{-0.0035}^{+0.0033}) ~\mathrm{M_\odot yr^{-1}}\) – or from averaging over the last 100 Myr of the best-fit star-formation history – \((0.0038_{-0.0007}^{+0.0017}) ~\mathrm{M_\odot yr^{-1}}\) –, suporting the presence of a very young burst.
\(^{(j)}\) Vanzella et al. (2023) previously estimated a line flux for HeII1640 of \((7.96 \pm 2.07) \times 10^{-19} ~\mathrm{erg \, s^{-1} \, cm^{-2}}\); however, the reliability of the HeII line detection was hampered by the presence of a small blueshift relative to the Balmer lines, and by the extreme required EW (\(\gtrsim 200\) Å), therefore the authors safely considered the line undetected, placing a \(1\sigma\) upper limit of \(2.7 \times 10^{-19} ~\mathrm{erg \, s^{-1} \, cm^{-2}}\). While Nakajima et al. (2025) also report no clear detection of the line, they provide an upper limit that remains within the range expected for zero-metallicity stellar populations. Also note that the stellar continuum is undetected for this source.
\(^{(k)}\) The authors further highlighted an elevated carbon-to-oxygen ratio of \(\sim 1 - 2\) times higher than the solar value, consistent with Pop III nucleosynthetic yields. This observation, together with the exceptionally hard ionizing radiation field, inconsistent with chemically enriched stellar populations or accreting black holes, establishes LAP1 as a candidate ‘self-enriched’ Pop III system or ‘fossil in the making’.
\(^{(l)}\) Intrinsic line fluxes and upper limits are reported after applying corrections for lensing magnification and dust extinction, adopting \(A_\mathrm{V} = 0.12 \pm 0.04\) from their spectro-photometric analysis.
\(^{(m)}\) Assuming an extended star-formation history in which the stellar mass is built up steadily, but with a recent ~3 Myr burst of star formation, forming a mass of \((2.24_{-2.13}^{+1.48}) \times 10^7 ~\mathrm{M_\odot}\).
\(^{(n)}\) Though this system is not metal-free, the authors suggest that an effective temperature \(\gtrsim 80000\) K for the ionizing source is necessary (with no obvious sign of AGN heating), hardly explained with a standard IMF, and that exotic scenarios such as Pop III star formation within a mildly enriched halo would be consistent with the observation.
\(^{(o)}\) Although measured fluxes need to be corrected for a small magnification factor of 1.42, which is not accounted for in the reported line fluxes; see table 1 of Maiolino et al. (2026) for the corresponding de-lensed line luminosities.