binny.nz_tomo.bin_stats module#

Basic statistics of binned redshift distributions.

This module provides two families of diagnostics for tomographic bin curves:

  • Shape statistics: summaries that depend only on the shape of each bin curve (moments, quantiles, peaks, centers, in-range fractions). These are safe to compute even when each bin curve is individually normalized.

  • Population statistics: quantities that depend on relative bin populations (fractions, optional surface densities and counts). In Binny, these should be taken from tomographic-builder metadata (photo-z / spec-z), not inferred from normalized bin curves.

The public entry points are shape_stats() and population_stats().

binny.nz_tomo.bin_stats.bin_centers(z: Any, bins: Mapping[int, Any], *, method: str = 'mean', decimal_places: int | None = 2) dict[int, float]#

Compute one center value per tomographic bin.

Supported methods:
  • "mean": weighted mean redshift.

  • "median": weighted median redshift.

  • "mode": grid-point mode.

  • "pXX": weighted percentile, where XX is between 0 and 100

    (e.g. "p50").

Parameters:
  • z – One-dimensional redshift grid shared by all bins.

  • bins – Mapping from bin index to bin curves evaluated on z.

  • method – Center definition.

  • decimal_places – If not None, round each returned center to this many decimal places. If None, return full-precision floats.

Returns:

Mapping from bin index to the chosen center value.

Raises:
  • ValueError – If method is invalid.

  • ValueError – If any bin has non-positive total weight when needed.

binny.nz_tomo.bin_stats.bin_moments(z: Any, nz_bin: Any) dict[str, float]#

Compute standard shape summaries for a single bin curve.

The input is a redshift grid z and a corresponding bin curve nz_bin evaluated on that grid. The curve is treated as a nonnegative weight function; it does not need to be normalized.

Returned keys:
  • "mean": weighted mean redshift.

  • "median": weighted median redshift.

  • "mode": redshift value on the input grid where nz_bin is maximal.

  • "std": weighted standard deviation.

  • "skewness": standardized third central moment (dimensionless).

  • "kurtosis": standardized fourth central moment minus 3 (dimensionless).

  • "iqr": interquartile range (q75 - q25).

  • "width_68": central 68% interval width (q84 - q16).

Notes

  • Percentile-based summaries depend on the sampling of the grid.

  • The mode is grid-dependent by definition.

Parameters:
  • z – One-dimensional redshift grid.

  • nz_bin – Bin curve values evaluated on z.

Returns:

Dictionary of summary statistics.

Raises:

ValueError – If the total weight (integral of nz_bin) is not positive.

binny.nz_tomo.bin_stats.bin_quantiles(z: Any, nz_bin: Any, qs: Sequence[float]) dict[float, float]#

Compute weighted quantiles of a single bin curve.

The curve nz_bin is treated as a nonnegative weight curve evaluated on z. For each requested quantile q in [0, 1], this returns the redshift value where the cumulative integral reaches q of the total weight.

Parameters:
  • z – One-dimensional redshift grid.

  • nz_bin – Bin curve values evaluated on z.

  • qs – Quantiles to compute, as fractions between 0 and 1.

Returns:

Mapping from each requested quantile to the corresponding redshift value.

Raises:
  • ValueError – If any q is outside [0, 1].

  • ValueError – If the total weight is not positive.

binny.nz_tomo.bin_stats.galaxy_count_per_bin(density_per_bin: Mapping[int, float], survey_area: float) dict[int, float]#

Convert per-bin surface densities to effective counts using a survey area.

Conventions:
  • density_per_bin values are in galaxies per square arcminute.

  • survey_area is in square arcminutes.

  • returned counts are dimensionless effective counts.

Parameters:
  • density_per_bin – Mapping from bin index to surface density (gal/arcmin^2).

  • survey_area – Survey area (arcmin^2).

Returns:

Mapping from bin index to effective counts.

Raises:
  • ValueError – If survey_area is not positive.

  • ValueError – If any density is negative.

binny.nz_tomo.bin_stats.galaxy_density_per_bin(metadata: Mapping[str, Any], density_total: float) dict[int, float]#

Computes per-bin surface densities from tomo metadata and total effective density..

Parameters:
  • metadata – Tomography metadata containing "frac_per_bin".

  • density_total – Total effective surface density (gal/arcmin^2).

Returns:

gal/arcmin^2}.

Return type:

Mapping {bin_idx

Raises:
  • ValueError – If density_total is negative.

  • ValueError – If metadata does not contain valid fractions.

binny.nz_tomo.bin_stats.galaxy_fraction_per_bin(meta: Mapping[str, Any]) dict[int, float]#

Extract and normalize per-bin population fractions from tomo metadata.

binny.nz_tomo.bin_stats.in_range_fraction(z: Any, nz_bin: Any, z_min: float, z_max: float) float#

Compute the fraction of a bin curve contained in a redshift range.

This integrates nz_bin over the full grid and over [z_min, z_max] and returns inside / total.

Parameters:
  • z – One-dimensional redshift grid.

  • nz_bin – Bin curve values evaluated on z.

  • z_min – Lower bound of the range.

  • z_max – Upper bound of the range.

Returns:

Fraction of the total bin weight contained in [z_min, z_max].

Raises:
  • ValueError – If z_max <= z_min.

  • ValueError – If the total weight is not positive.

binny.nz_tomo.bin_stats.in_range_fraction_per_bin(z: Any, bins: Mapping[int, Any], bin_edges: Mapping[int, tuple[float, float]] | Sequence[float]) dict[int, float]#

Compute the in-range fraction for each bin given nominal edges.

bin_edges can be either:
  • mapping {bin_idx: (z_min, z_max)}, or

  • a sequence of edges [e0, e1, ..., eN] where bin i uses [e_i, e_{i+1}].

Parameters:
  • z – One-dimensional redshift grid shared by all bins.

  • bins – Mapping from bin index to bin curves evaluated on z.

  • bin_edges – Nominal edges mapping or edge sequence.

Returns:

Mapping from bin index to fraction of its weight inside its nominal range.

Raises:

ValueError – If required edges are missing or malformed.

binny.nz_tomo.bin_stats.peak_flags(z: Any, nz_bin: Any, *, min_rel_height: float = 0.1) dict[str, float | None]#

Compute simple peak diagnostics for a single bin curve.

A point is treated as a peak if it is greater than its immediate neighbors. Peaks below min_rel_height * global_max are ignored.

Returned keys:
  • "mode": redshift of the global maximum on the grid.

  • "mode_height": curve value at the mode.

  • "num_peaks": number of detected peaks passing the height cut.

  • "second_peak_ratio": second-highest peak height divided by the highest (None if no second peak).

binny.nz_tomo.bin_stats.peak_flags_per_bin(z: Any, bins: Mapping[int, Any], *, min_rel_height: float = 0.1) dict[int, dict[str, float | None]]#

Compute peak diagnostics for each bin curve.

binny.nz_tomo.bin_stats.population_stats(bins: Mapping[int, Any], metadata: Mapping[str, Any], *, density_total: float | None = None, survey_area: float | None = None, normalize_frac: bool = True, rtol: float = 0.01, atol: float = 0.001, decimal_places: int | None = 2) dict[str, Any]#

Compute population / normalization statistics for tomographic bins.

This function computes quantities that depend on relative bin populations, using metadata produced by Binny’s tomo builders (photo-z / spec-z).

The primary input is metadata["frac_per_bin"] (mapping bin index -> fraction). Fractions are always checked against the bin indices present in bins.

Optional survey-level allocation:

  • If density_total (gal/arcmin^2) is provided, return per-bin allocated surface densities.

  • If survey_area (arcmin^2) is also provided, return per-bin effective counts.

Parameters:
  • bins – Mapping from bin index to bin curves.

  • metadata – Tomography metadata containing "frac_per_bin".

  • density_total – Optional total effective surface density (gal/arcmin^2).

  • survey_area – Optional survey area (arcmin^2). Requires density_total.

  • normalize_frac – If True, renormalize metadata fractions to sum to 1. If False, require they sum to 1 within (rtol, atol).

  • rtol – Relative tolerance for sum-to-one checks when normalize_frac=False.

  • atol – Absolute tolerance for sum-to-one checks when normalize_frac=False.

  • decimal_places – Rounding precision for returned values.

Returns:

  • "fractions": {bin_idx: fraction}

And optionally:

  • "density_total": float

  • "density_per_bin": {bin_idx: gal/arcmin^2}

  • "survey_area": float

  • "count_per_bin": {bin_idx: effective count}

Return type:

Mapping with keys

Raises:
  • ValueError – If bins is empty.

  • ValueError – If metadata does not contain "frac_per_bin".

  • ValueError – If metadata fractions are missing any bin index.

  • ValueError – If survey_area is provided without density_total.

  • ValueError – If fractions cannot be normalized or validated.

binny.nz_tomo.bin_stats.shape_stats(z: Any, bins: Mapping[int, Any], *, center_method: str = 'mean', decimal_places: int | None = 2, quantiles: Sequence[float] = (0.16, 0.5, 0.84), min_rel_height: float = 0.1, bin_edges: Mapping[int, tuple[float, float]] | Sequence[float] | None = None) dict[str, Any]#

Compute shape-only summary statistics for tomographic bin curves.

This function computes redshift-shape diagnostics that depend only on the per-bin curve shapes, not on relative bin populations. It is safe to call on individually normalized bin PDFs.

Per bin, it returns:

Optionally, if bin_edges are supplied, it also returns the fraction of each bin curve contained within its nominal redshift range via in_range_fraction_per_bin().

Parameters:
  • z – One-dimensional redshift grid shared by all bins.

  • bins – Mapping from bin index to bin curves evaluated on z.

  • center_method – Center definition (“mean”, “median”, “mode”, or “pXX”).

  • decimal_places – If not None, round centers to this many decimal places.

  • quantiles – Quantiles to compute per bin (fractions in [0, 1]).

  • min_rel_height – Peak height threshold relative to the global maximum.

  • bin_edges – Optional nominal edges for in-range fractions.

Returns:

  • "centers": {bin_idx: center}

  • "peaks": {bin_idx: peak_flags_dict}

  • "per_bin": {bin_idx: {“moments”: …, “center”: …,

    ”quantiles”: …, “peaks”: …}}

  • "in_range_fraction": {bin_idx: fraction} if bin_edges

    is not None

Return type:

Nested mapping with keys

Raises:
  • ValueError – If bins is empty.

  • ValueError – If any bin has non-positive total weight.

  • ValueError – If center_method is invalid.

  • ValueError – If quantiles are outside [0, 1].

  • ValueError – If bin_edges are malformed when provided.