API reference

This section documents the public Python API of barc4beams. Most users will interact primarily with the barc4beams.beam.Beam container and a few high-level helper functions, but all modules are listed for completeness.

Beam container

beam.py — unified interface classes for standardized beams.

Beam

Single standardized photon beam.

BeamEnsemble

Collection of comparable beam realizations, typically repeated seeds/runs of the same simulation setup, used for ensemble statistics.

class barc4beams.beam.Beam(obj: Any, code: str | None = None)

Bases: object

High-level container for one standardized photon beam.

Wraps a validated beam DataFrame and exposes core analysis, propagation, sampling, saving, and visualization methods.

apply_transmission_element(*, thickness: dict, energy: float | Sequence[float], n: float | complex | Sequence[float | complex] | None = None, delta: float | Sequence[float] | None = None, beta: float | Sequence[float] | None = None, attenuation_length: float | Sequence[float] | None = None, verbose: bool = False) Beam

Return a new Beam after applying a thin transmission element.

See sampling.apply_transmission_element.

apply_wavefront(*, wavefront: dict, energy: float | None = None, wavelength: float | None = None, threshold: float | None = None, verbose: bool = False) Beam

Returns a new Beam instance with updated intensity, slopes, and lost-ray flags.

caustic(*, n_points: int = 501, start: float = -0.5, finish: float = 0.5) dict

Compute the free-space caustic of this Beam.

See propagation.caustic.

property df: DataFrame

Standardized beam DataFrame.

classmethod from_df(df: DataFrame) Beam

Create a Beam directly from a standard DataFrame.

classmethod from_h5(path: str) Beam

Load a Beam from an HDF5 file written by io.save_beam.

classmethod from_intensity(*, far_field: dict, near_field: dict | None = None, n_rays: int, energy: float | None = None, wavelength: float | None = None, jitter: bool = True, threshold: float | None = None, seed: int | None = 42, z0: float = 0.0, polarization_degree: float = 1.0) Beam

Build a Beam by sampling 2D intensity maps.

See sampling.beam_from_intensity.

classmethod from_wavefront(*, wavefront: dict, n_rays: int, energy: float | None = None, wavelength: float | None = None, jitter: bool = True, threshold: float | None = None, seed: int | None = 42, z0: float = 0.0, polarization_degree: float = 1.0) Beam

Build a Beam by sampling a spatial wavefront map.

See sampling.beam_from_wavefront.

plot_beam(*, mode: str = 'hist', aspect_ratio: bool = True, color: int = 1, x_range: tuple[float | None, float | None] | None = None, y_range: tuple[float | None, float | None] | None = None, bins: int | Tuple[int, int] | None = None, bin_width: float | None = None, bin_method: int = 0, dpi: int = 100, path: str | None = None, showXhist: bool = True, showYhist: bool = True, envelope: bool = False, envelope_method: str = 'edgeworth', apply_style: bool = True, k: float = 1.0, z_offset: float = 0.0, scatter_weight_mode: str = 'auto', plot: bool = True)

Plot the spatial footprint X vs Y with optional propagation offset.

plot_caustic(*, which: Literal['x', 'y', 'both'] = 'both', aspect_ratio: bool = False, color: int | None = 5, z_range: tuple[float | None, float | None] | None = None, xy_range: tuple[float | None, float | None] | None = None, bins: int | tuple[int | None, int] | None = None, bin_width: float | None = None, dpi: int = 100, path: str | None = None, apply_style: bool = True, k: float = 1.0, top_stat: str | None = None, n_points: int = 501, start: float = -0.5, finish: float = 0.5, plot: bool = True)

Plot the caustic map computed from self.caustic().

plot_divergence(*, mode: str = 'hist', aspect_ratio: bool = False, color: int = 2, x_range: tuple[float | None, float | None] | None = None, y_range: tuple[float | None, float | None] | None = None, bins: int | tuple[int, int] | None = None, bin_width: float | None = None, bin_method: int = 0, dpi: int = 100, path: str | None = None, showXhist: bool = True, showYhist: bool = True, envelope: bool = False, envelope_method: str = 'edgeworth', apply_style: bool = True, k: float = 1.0, scatter_weight_mode: str = 'auto', plot: bool = True)

Plot the angular distribution dX vs dY.

plot_energy(*, bins: int | tuple[int, int] | None = None, bin_width: float | None = None, bin_method: int = 0, dpi: int = 100, path: str | None = None, apply_style: bool = True, k: float = 1.0, plot: bool = True)

Plot the energy distribution of the beam.

plot_energy_vs_intensity(*, mode: str = 'hist', aspect_ratio: bool = False, color: int | None = 3, x_range: tuple[float | None, float | None] | None = None, y_range: tuple[float | None, float | None] | None = None, bins: int | tuple[int, int] | None = None, bin_width: float | None = None, bin_method: int = 0, dpi: int = 100, path: str | None = None, showXhist: bool = True, showYhist: bool = True, envelope_method: str = 'edgeworth', apply_style: bool = True, k: float = 1.0, scatter_weight_mode: str = 'auto', plot: bool = True)

Plot beam intensity as a function of photon energy.

plot_intensity(*, bins: int | tuple[int, int] | None = None, bin_width: float | None = None, bin_method: int = 0, dpi: int = 100, path: str | None = None, apply_style: bool = True, k: float = 1.0, plot: bool = True)

Plot the intensity distribution of the beam.

plot_phase_space(*, direction: str = 'both', mode: str = 'hist', aspect_ratio: bool = False, color: int = 3, x_range: tuple[float | None, float | None] | None = None, y_range: tuple[float | None, float | None] | None = None, bins: int | tuple[int, int] | None = None, bin_width: float | None = None, bin_method: int = 0, dpi: int = 100, path: str | None = None, showXhist: bool = True, showYhist: bool = True, envelope: bool = False, envelope_method: str = 'edgeworth', apply_style: bool = True, k: float = 1.0, z_offset: float = 0.0, scatter_weight_mode: str = 'auto', plot: bool = True)

Plot phase-space diagrams X vs dX and/or Y vs dY.

propagate(z_offset: float, *, verbose: bool = False) Beam

Return a new Beam propagated through free space by z_offset [m].

save(path: str, *, meta: dict[str, Any] | None = None) None

Save beam to HDF5 and stats to JSON.

The HDF5 file contains the beam. A sibling JSON file with the same base name contains the statistics.

save_beam(path: str) None

Save the beam only to HDF5.

save_stats(path: str, *, meta: dict[str, Any] | None = None) None

Save statistics only to JSON.

stats(*, verbose: bool = False) dict

Compute descriptive beam statistics.

See stats.get_statistics.

wave_metrics(*, max_focal_distance: float = 1000.0, verbose: bool = False) dict

Estimate Gaussian-equivalent wave-optics metrics.

See wave.get_wave_metrics.

class barc4beams.beam.BeamEnsemble(beams: Sequence[Beam | DataFrame | Any], code: str | None = None)

Bases: object

Container for comparable standardized beam realizations.

This is intended for repeated runs/seeds of the same beamline setup. It owns ensemble-level statistics, saving, and merging. Single-beam operations such as plotting, propagation, and caustic calculation remain on Beam.

classmethod from_dfs(beams: Sequence[DataFrame]) BeamEnsemble

Create a BeamEnsemble directly from standard DataFrames.

classmethod from_h5(path: str) BeamEnsemble

Load a BeamEnsemble from an HDF5 file written by io.save_beam_ensemble.

merge() Beam

Merge all ensemble runs into a single Beam.

The returned object is a Beam instance.

property n_runs: int

Number of beam realizations in the ensemble.

property runs: Sequence[DataFrame]

Standardized beam DataFrames.

save(path: str, *, meta: dict[str, Any] | None = None) None

Save ensemble beams to HDF5 and ensemble stats to JSON.

The HDF5 file contains all runs. A sibling JSON file with the same base name contains ensemble statistics.

save_beams(path: str) None

Save ensemble beams only to HDF5.

save_stats(path: str, *, meta: dict[str, Any] | None = None) None

Save ensemble statistics only to JSON.

stats(*, verbose: bool = False) dict

Compute ensemble statistics over all runs.

See stats.get_statistics.

wave_metrics(*, max_focal_distance: float = 1000.0, verbose: bool = False) dict

Estimate ensemble Gaussian-equivalent wave-optics metrics.

See wave.get_wave_metrics.

Propagation

propagation.py - free space ray tracing.

barc4beams.propagation.caustic(beam: DataFrame, *, n_points: int = 501, start: float = -0.5, finish: float = 0.5) dict

Compute free-space caustics for a standard beam.

Ray positions are propagated in free space. Ray intensity weights are not modified by propagation and are used for all per-plane statistics.

barc4beams.propagation.propagate(beam: DataFrame, z_offset: float) DataFrame

Compute free-space propagation for a standard beam

Performs:

X <- X + z_offset * dX Y <- Y + z_offset * dY

Parameters:
  • beam (pandas.DataFrame) – Standardized beam. Validated via schema.validate_beam(beam).

  • z_offset (float) – Propagation distance in meters (positive downstream).

Returns:

Standard beam at the propagated plane.

Return type:

pandas.DataFrame

Sampling

sampling.py — generate a standardized beam by sampling 2D intensity maps.

barc4beams.sampling.apply_transmission_element(*, standard_beam: DataFrame, thickness: dict, energy: float | ndarray, n: float | complex | ndarray | None = None, delta: float | ndarray | None = None, beta: float | ndarray | None = None, attenuation_length: float | ndarray | None = None) DataFrame

Apply a thin transmission element to an existing standard beam.

The input beam is copied. Ray positions are preserved. The element thickness is interpolated at each ray position and used to attenuate the ray intensity according to Beer-Lambert absorption:

I_out = I_in * exp(-2 * k * beta * t)

The local thickness gradients are interpolated at each ray position and applied as refractive angular kicks:

dX_out = dX_in - delta * dt/dx dY_out = dY_in - delta * dt/dy

where k = 2*pi / wavelength and n = 1 - delta + 1j*beta.

Rays outside the thickness grid, rays landing on invalid thickness support, and rays landing where thickness gradients are invalid are marked as lost and assigned zero intensity.

Parameters:
  • standard_beam (pandas.DataFrame) – Standard beam DataFrame.

  • thickness (dict) –

    Flat dict with keys:
    • ”profile”: 2D array t[y, x] in meters.

    • ”x_axis”: 1D array of x in meters.

    • ”y_axis”: 1D array of y in meters.

  • energy (float or array_like) – Photon energy grid in eV associated with the optical constants. If optical constants are scalar, energy may be scalar. If optical constants are arrays, energy must be a 1D array with matching length and must cover the full energy range of the input beam.

  • n (float, complex or array_like, optional) – Complex refractive index, using the convention n = 1 - delta + 1j*beta. May be scalar or tabulated against energy.

  • delta (float or array_like, optional) – Refractive index decrement and absorption index. Both must be provided together, unless attenuation_length is provided instead of beta.

  • beta (float or array_like, optional) – Refractive index decrement and absorption index. Both must be provided together, unless attenuation_length is provided instead of beta.

  • attenuation_length (float or array_like, optional) – Attenuation length in meters. May be provided together with delta instead of beta. Internally converted using beta = wavelength / (4*pi*attenuation_length).

Returns:

New standard beam DataFrame with updated intensity, slopes, and lost-ray flags.

Return type:

pandas.DataFrame

Raises:

ValueError – If the input beam, thickness map, or optical constants are invalid.

barc4beams.sampling.apply_wavefront(*, standard_beam: DataFrame, wavefront: dict, energy: float | None = None, wavelength: float | None = None, threshold: float | None = None) DataFrame

Apply a spatial wavefront map to an existing standard beam.

The input beam is copied. Ray positions are preserved. The wavefront intensity is interpolated at each ray position and applied as a multiplicative transmission factor. The wavefront phase gradient is interpolated at each ray position and applied as an angular kick:

dX_out = dX_in + (1 / k) * dphi/dx dY_out = dY_in + (1 / k) * dphi/dy

with k = 2*pi / wavelength.

Rays outside the wavefront grid, rays landing on zero/invalid transmission, and rays landing where the phase-gradient support is invalid are marked as lost and assigned zero intensity.

Parameters:
  • standard_beam (pandas.DataFrame) – Standard beam DataFrame.

  • wavefront (dict) –

    Flat dict with keys:
    • ”intensity”: 2D array I[y, x].

    • ”phase”: 2D array of unwrapped phase in radians.

    • ”x_axis”: 1D array of x in meters.

    • ”y_axis”: 1D array of y in meters.

  • energy (float, optional) – Exactly one must be provided. The other is computed using misc.energy_wavelength(…). If ‘energy’ is given, wavelength is computed in meters; if ‘wavelength’ is given, energy is computed in eV.

  • wavelength (float, optional) – Exactly one must be provided. The other is computed using misc.energy_wavelength(…). If ‘energy’ is given, wavelength is computed in meters; if ‘wavelength’ is given, energy is computed in eV.

  • threshold (float or None, optional) – Relative cutoff in [0, 1]. Pixels below threshold * max(intensity) are treated as invalid support.

Returns:

New standard beam DataFrame with updated intensity, slopes, and lost-ray flags.

Return type:

pandas.DataFrame

Raises:

ValueError – If the input beam or wavefront is invalid.

barc4beams.sampling.beam_from_intensity(*, far_field: dict, near_field: dict | None = None, n_rays: int, energy: float | None = None, wavelength: float | None = None, jitter: bool = True, threshold: float | None = None, seed: int | None = 42, z0: float = 0.0, polarization_degree: float = 1.0) DataFrame

Build a standard beam by sampling intensity maps (SI units only).

Parameters:
  • far_field (dict) – Flat dict with keys: {“intensity”, “x_axis”, “y_axis”}. - “intensity”: 2D array Iff[y, x] (already per pixel; no unit conversion here) - “x_axis”: 1D array of xp in radians (strictly monotonic) - “y_axis”: 1D array of yp in radians (strictly monotonic) This is REQUIRED and defines (dX, dY).

  • near_field (dict or None, optional) – Flat dict with keys: {“intensity”, “x_axis”, “y_axis”}. - “intensity”: 2D array Inf[y, x] (already per pixel) - “x_axis”: 1D array of x in meters (strictly monotonic) - “y_axis”: 1D array of y in meters (strictly monotonic) If provided, defines (X, Y); otherwise X=Y=0 (point source at z0).

  • n_rays (int) – Number of rays to sample.

  • energy (float, optional) – Exactly one must be provided. The other is computed using misc.energy_wavelength(…). If ‘energy’ is given, wavelength is computed in meters; if ‘wavelength’ is given, energy is computed in eV.

  • wavelength (float, optional) – Exactly one must be provided. The other is computed using misc.energy_wavelength(…). If ‘energy’ is given, wavelength is computed in meters; if ‘wavelength’ is given, energy is computed in eV.

  • jitter (bool, optional) – Sub-pixel jitter for both FF and NF maps (if NF present).

  • threshold (float or None, optional) – Relative cutoff in [0, 1] applied independently to each map.

  • seed (int | None, optional) – RNG seed. If both FF and NF are sampled, NF uses (seed+1) for decorrelation.

  • z0 (float, default 0.0) – Source plane position assigned to all rays (Z=z0, dZ=0).

  • polarization_degree (float, default 1.0) – Value in [0,1] is the s-polarization fraction: Is = pdeg, Ip = 1-pdeg

Returns:

Standard beam DataFrame ready for plotting/propagation/caustic.

Return type:

pandas.DataFrame

Notes

The sampling algorithm implemented here follows the strategy described in Rebuffi et al., J. Synchrotron Rad. 27, 1108–1120 (2020).

barc4beams.sampling.beam_from_wavefront(*, wavefront: dict, n_rays: int, energy: float | None = None, wavelength: float | None = None, jitter: bool = True, threshold: float | None = None, seed: int | None = 42, z0: float = 0.0, polarization_degree: float = 1.0) DataFrame

Build a standard beam by sampling a spatial wavefront map (SI units only).

The ray positions (X, Y) are sampled from the wavefront intensity map. The local ray angles (dX, dY) are obtained from the phase gradient:

dX = (1 / k) * dphi/dx dY = (1 / k) * dphi/dy

with k = 2*pi / wavelength.

Parameters:
  • wavefront (dict) –

    Flat dict with keys:
    • ”intensity”: 2D array I[y, x].

    • ”phase”: 2D array of unwrapped phase in radians.

    • ”x_axis”: 1D array of x in meters.

    • ”y_axis”: 1D array of y in meters.

  • n_rays (int) – Number of rays to sample.

  • energy (float, optional) – Exactly one must be provided. The other is computed using misc.energy_wavelength(…). If ‘energy’ is given, wavelength is computed in meters; if ‘wavelength’ is given, energy is computed in eV.

  • wavelength (float, optional) – Exactly one must be provided. The other is computed using misc.energy_wavelength(…). If ‘energy’ is given, wavelength is computed in meters; if ‘wavelength’ is given, energy is computed in eV.

  • jitter (bool, optional) – Sub-pixel jitter for the sampled (X, Y) coordinates.

  • threshold (float or None, optional) – Relative cutoff in [0, 1]. Pixels below threshold * max(intensity) are excluded both from position sampling and from phase-gradient support.

  • seed (int | None, optional) – RNG seed for reproducibility. Use an int for deterministic draws; use None for non-deterministic sampling.

  • z0 (float, default 0.0) – Source plane position assigned to all rays (Z=z0, dZ=0).

  • polarization_degree (float, default 1.0) – Value in [0, 1] is the s-polarization fraction: Is = pdeg, Ip = 1-pdeg.

Returns:

Standard beam DataFrame ready for plotting/propagation/caustic.

Return type:

pandas.DataFrame

Notes

This function samples ray positions from a spatial intensity map and assigns local propagation angles from the phase gradient.

Low-intensity or invalid pixels are masked internally before gradient evaluation. This avoids differentiating noisy finite phase values outside the useful wavefront support.

Statistics

stats.py - beam statistics and 1D profile metrics.

barc4beams.stats.calc_centroid_from_particle_distribution(profile: ndarray, weights: ndarray | None = None) float

Compute the centroid (center of mass) of a 1D particle-position distribution.

This treats profile as Monte Carlo samples of positions (each sample has equal weight by default). If weights are provided (e.g., per-ray intensities), a weighted centroid is computed.

Parameters:
  • profile (np.ndarray) – 1D array of particle positions (e.g., X or Y).

  • weights (np.ndarray, optional) – Non-negative weights for each sample (same shape as profile). If None, all samples are equally weighted.

Returns:

Centroid in the same units as profile, or np.nan if it cannot be computed (e.g., empty or all-nonfinite inputs, or zero total weight).

Return type:

float

barc4beams.stats.calc_envelope_from_moments(mean: float, std: float, skewness: float, kurtosis_excess: float, axis: ndarray, method: str = 'edgeworth', clip_negative: bool = True, maxent_iters: int = 2000, maxent_lr: float = 0.001, seed: int | None = None) Dict

Construct an approximate 1D PDF envelope consistent with the first four moments.

Parameters:
  • mean (float) – Mean (μ) of the target distribution.

  • std (float) – Standard deviation (σ > 0).

  • skewness (float) – Standardized 3rd moment γ1.

  • kurtosis_excess (float) – Excess kurtosis γ2 (kurtosis − 3).

  • axis (np.ndarray) – 1D grid where the envelope is evaluated.

  • method ({'edgeworth', 'pearson', 'maxent'}, default 'edgeworth') –

    • ‘edgeworth’: Gram–Charlier/Edgeworth expansion around N(μ, σ²) up to H6.

    • ’pearson’ : Pearson Type III (Gamma) matched to γ1; reflect for γ1<0.

    • ’maxent’Discrete maximum-entropy pdf ~ exp(a0 + a1 x + … + a4 x^4)

      fitted so moments up to order 4 match on the given axis.

  • clip_negative (bool, default True) – If True, clip negative pdf values to 0 and renormalize (useful for ‘edgeworth’).

  • maxent_iters (int, default 2000) – Iterations for the ‘maxent’ solver.

  • maxent_lr (float, default 1e-3) – Learning rate for the ‘maxent’ solver.

  • seed (int or None) – RNG seed (used only by ‘maxent’ initialization).

Returns:

{‘envelope’: pdf_vals, ‘axis’: axis}

Return type:

dict

Notes

  • Edgeworth (default) is fastest and smooth for |skew|≲1 and |excess kurtosis|≲2. Negative lobes can appear when moments are large; keep clip_negative=True to force a valid PDF.

  • Pearson Type III guarantees positivity and matches mean/σ/skewness exactly. The implied excess kurtosis is γ₂ = 1.5·γ₁²; the supplied kurtosis is ignored if inconsistent.

  • Maximum entropy finds the least-assumptive distribution subject to the moment constraints. It needs a wide, dense axis (e.g. μ±6σ) and is slower; increase maxent_iters or reduce maxent_lr if convergence is poor.

  • The four moments do not uniquely define a distribution. The returned envelope is only one of many possible PDFs consistent with them.

barc4beams.stats.calc_focal_distance_from_particle_distribution(position: ndarray, divergence: ndarray, weights: ndarray | None = None, *, eps: float = 1e-16, ridge: float = 0.0, huge_m: float = 1e+26) float

Compute the signed focal distance minimizing the weighted variance of position + x * divergence.

If weights is None, all particles are assigned unit weight.

Parameters:
  • position (np.ndarray) – 1D array of transverse positions, e.g. X or Y [m].

  • divergence (np.ndarray) – 1D array of corresponding angular components, e.g. dX or dY [rad].

  • weights (np.ndarray, optional) – 1D array of statistical ray weights. If None, unit weights are used.

  • eps (float, optional) – Numerical floor for denominator stability.

  • ridge (float, optional) – Extra ridge term added to the divergence variance.

  • huge_m (float, optional) – Finite surrogate distance for an effectively infinite focus.

Returns:

Signed focal distance in meters.

Return type:

float

barc4beams.stats.calc_fwhm_from_particle_distribution(profile: ndarray, weights: ndarray | None = None, bins: int | None = None) float

Calculate the FWHM of a 1D particle distribution.

If weights is None, all particles are assigned unit weight. If weights are provided, the FWHM is computed from a weighted histogram.

Parameters:
  • profile (np.ndarray) – 1D array representing particle positions, divergences, or energies.

  • weights (np.ndarray, optional) – 1D array of statistical ray weights. If None, unit weights are used.

  • bins (int or None, optional) – Number of histogram bins. If None, an adaptive rule is used.

Returns:

FWHM value in the same units as profile. Returns -1.0 if computation fails.

Return type:

float

barc4beams.stats.calc_moments_from_particle_distribution(profile: ndarray, weights: ndarray | None = None) Tuple[float, float, float, float]

Return (mean, std, skewness, kurtosis_excess) using population definitions.

If weights is None, all particles are assigned unit weight. If weights are provided, the moments are intensity-weighted.

Parameters:
  • profile (np.ndarray) – 1D array representing particle positions, divergences, or energies.

  • weights (np.ndarray, optional) – 1D array of statistical ray weights. If None, unit weights are used.

Returns:

Mean, standard deviation, skewness, and excess kurtosis.

Return type:

tuple[float, float, float, float]

barc4beams.stats.get_focal_distance(beam: DataFrame, verbose: bool = False, direction: str = 'both', eps: float = 1e-16, ridge: float = 0.0, huge_m: float = 1e+23) Dict[str, float]

Calculate the intensity-weighted focal distance along X and Y.

Lost rays are removed via lost_ray_flag == 0 before computing the focal distance. If the intensity column is present, it is used as the ray weight. Otherwise, all rays are assigned unit weight.

Uses the closed-form weighted least-squares expression:

x* = -Cov_w(axis, d_axis) / (Var_w(d_axis) + ridge)

Parameters:
  • beam (pandas.DataFrame) – Beam dataframe containing X/dX and/or Y/dY columns.

  • verbose (bool, optional) – If True, prints diagnostic information.

  • direction ({'x', 'y', 'both'}, optional) – Direction to optimize.

  • eps (float, optional) – Numerical floor for denominator stability.

  • ridge (float, optional) – Extra ridge term added to the divergence variance.

  • huge_m (float, optional) – Finite surrogate distance for an effectively infinite focus.

Returns:

Dictionary with keys 'fx' and 'fy'.

Return type:

dict

barc4beams.stats.get_statistics(beams: DataFrame | List[DataFrame], *, verbose: bool = False) dict

Compute intensity-weighted beam statistics for X/Y, dX/dY, and energy.

Lost rays are removed via lost_ray_flag == 0 before computing stats. All statistical observables are weighted by the intensity column.

With unit intensities, the weighted formulas reduce to the unweighted case.

Inputs

beamspd.DataFrame or list[pd.DataFrame]

One or multiple barc4beams beam DataFrames.

keyword verbose:

If True, print a human-readable summary.

kwtype verbose:

bool, optional

returns:
{
“meta”: {

“n_rays”: int, “n_repetitions”: int, “good_rays”: [mean, std], “transmission”: [mean%, std%],

}, “energy”: {“mean”:[val,std], “std”:[val,std], “fwhm”:[val,std]}, “X”: {“mean”:[val,std], “std”:[val,std],

“fwhm”:[val,std], “skewness”:[val,std], “kurtosis”:[val,std]},

“Y”: { … same keys as X … }, “dX”: { … same keys as X … }, “dY”: { … same keys as X … }, “fx”: [val,std], “fy”: [val,std],

}

Only keys for columns actually present in the input are included.

rtype:

dict

I/O utilities

io.py - saving and loading of standardised beams and stats.

barc4beams.io.read_beam(path: str) DataFrame

Read a standardized beam from an HDF5 file.

Parameters:

path (str) – Input HDF5 file path.

Returns:

Beam as a DataFrame.

Return type:

pandas.DataFrame

Raises:
  • KeyError – If the ‘beam’ group or required datasets are missing.

  • ValueError – If the reconstructed DataFrame fails validation.

barc4beams.io.read_beam_ensemble(path: str) list[DataFrame]

Read an ensemble of standardized beams from an HDF5 file.

Parameters:

path (str) – Input HDF5 file path.

Returns:

List of standardized beams, one DataFrame per run.

Return type:

list[pandas.DataFrame]

Raises:
  • KeyError – If the ensemble groups or beam datasets are missing.

  • ValueError – If any reconstructed beam fails validation.

barc4beams.io.read_json_stats(path: str) Dict[str, Any]

Load a JSON file saved by save_json_stats.

Returns:

Record with keys: created_utc, meta, stats

Return type:

dict

barc4beams.io.save_beam(obj: Any, path: str, *, code: str | None = None, overwrite: bool = True, chunks: bool = True) None

Save a standardized beam to an HDF5 file.

Parameters:
  • obj (Any) – Beam-like object. If a pandas.DataFrame, it is assumed to be already standardized. Otherwise it is converted via adapters.to_standard_beam(obj, code=code).

  • path (str) – Output HDF5 file path.

  • code (str, optional) – Backend hint for conversion (passed to to_standard_beam).

  • overwrite (bool, optional) – If False and path exists, raise an error. Default is True.

  • chunks (bool, optional) – Enable chunked datasets (recommended). Default True.

Raises:
  • ValueError – If standardization/validation fails or no numeric columns found.

  • FileExistsError – If overwrite is False and file already exists.

barc4beams.io.save_beam_ensemble(objs: list[Any], path: str, *, code: str | None = None, overwrite: bool = True, chunks: bool = True) None

Save an ensemble of standardized beams to an HDF5 file.

Parameters:
  • objs (list[Any]) – Beam-like objects. Each item may be a standardized pandas.DataFrame or any object accepted by adapters.to_standard_beam(obj, code=code).

  • path (str) – Output HDF5 file path.

  • code (str, optional) – Backend hint for conversion, passed to to_standard_beam for non-DataFrame objects.

  • overwrite (bool, optional) – If False and path exists, raise an error. Default is True.

  • chunks (bool, optional) – Enable chunked datasets. Default True.

Raises:
  • ValueError – If the ensemble is empty, standardization/validation fails, or a beam has no numeric columns.

  • FileExistsError – If overwrite is False and file already exists.

barc4beams.io.save_json_stats(stats: Dict[str, Any], path: str, *, meta: Dict[str, Any] | None = None) str

Save a get_statistics() dictionary to JSON.

Parameters:
  • stats (dict) – The dictionary returned by get_statistics(…).

  • path (str) – Target JSON file path.

  • meta (dict, optional) – Extra metadata to embed (e.g., n_seeds, n_rays, code_sha, settings).

Returns:

The path written.

Return type:

str

Visualization

viz.py - plotting routines for beams and beamline layouts.

barc4beams.viz.plot() None

Show all pending figures.

barc4beams.viz.plot_beam(df: DataFrame, *, mode: str = 'scatter', aspect_ratio: bool = True, color=1, x_range=None, y_range=None, bins=None, bin_width=None, bin_method=0, dpi: int = 100, path: str | None = None, showXhist=True, showYhist=True, envelope=False, envelope_method='edgeworth', weight_by_intensity: bool = True, apply_style: bool = True, k: float = 1.0, plot: bool = True, z_offset: float = 0.0, scatter_weight_mode: Literal['auto', 'none', 'resample', 'color', 'alpha', 'threshold'] | str = 'auto', scatter_sample_size: int | None = None, scatter_seed: int | None = 12345, scatter_threshold: float = 0.0)

Plot the spatial footprint of a standardized beam (X vs Y), with optional marginals and moment-matched envelope overlays.

Parameters:
  • df (pandas.DataFrame) – Standardized beam with columns: ‘X’,’Y’,’dX’,’dY’,’lost_ray_flag’ (0=alive). Units expected in meters (pos) and radians (angles). This function scales to µm/µrad.

  • mode ({'scatter','histo2d', ...}, default 'scatter') – Plot style. Aliases like ‘s’/’h’ are accepted and normalized.

  • aspect_ratio (bool, default True) – If True, main axes uses equal aspect.

  • color (int or None, default 1) – Legacy color scheme index. 0/None → monochrome points; 1..4 → colormaps.

  • x_range ((min, max) or None) – Data limits. If None/partial, auto-detected with a small padding.

  • y_range ((min, max) or None) – Data limits. If None/partial, auto-detected with a small padding.

  • bins (int or (x_bins, y_bins) or None) – Histogram binning for the marginals and hist2d. Auto if None.

  • bin_width (float or None) – If given, overrides bin count as ceil(range/bin_width).

  • bin_method (int, default 0) – Auto-binning rule: 0=sqrt, 1=Sturges, 2=Rice, 3=Doane.

  • dpi (int, default 300)

  • path (str or None) – If provided, the figure is saved.

  • showXhist (bool, default True) – Whether to show X/Y marginals.

  • showYhist (bool, default True) – Whether to show X/Y marginals.

  • envelope (bool, default True) – Overlay envelope curve on the 1D marginals using moments from the data.

  • envelope_method ({'edgeworth','pearson','maxent'}, default 'edgeworth') – Reconstruction method passed to stats.calc_envelope_from_moments.

  • apply_style (bool, default True) – Call start_plotting(k) before plotting.

  • k (float, default 1.0) – Global style scale factor.

Returns:

The Matplotlib figure and axes.

Return type:

fig, (ax_image, ax_histx, ax_histy)

barc4beams.viz.plot_caustic(caustic: dict, *, which: Literal['x', 'y', 'both'] = 'both', aspect_ratio: bool = False, color: int | None = 5, z_range: Tuple[int | float | None, int | float | None] | None = None, xy_range: Tuple[int | float | None, int | float | None] | None = None, bins: int | Tuple[int, int] | None = None, bin_width: int | float | None = None, dpi: int = 100, path: str | None = None, apply_style: bool = True, k: float = 1.0, plot: bool = True, top_stat: str | None = None)

Plane-centered 2D histogram caustic (no other modes allowed).

  • Z is binned with one contiguous column per plane (no gaps).

  • X/Y use fixed bin width (if bin_width) or a fixed number of bins (bins).

  • Optional top panel shows FWHM or sigma (STD) vs z.

Notes

  • Units: position on the map is in µm (input arrays in meters are scaled by 1e6).

  • Large beams are safe: uses numpy.histogram2d + pcolormesh (no KDE, no scatter).

barc4beams.viz.plot_divergence(df: DataFrame, *, mode: str = 'scatter', aspect_ratio: bool = False, color=2, x_range=None, y_range=None, bins=None, bin_width=None, bin_method=0, dpi: int = 100, path: str | None = None, showXhist=True, showYhist=True, envelope=False, envelope_method='edgeworth', weight_by_intensity: bool = True, apply_style: bool = True, k: float = 1.0, plot: bool = True, z_offset: float = 0.0, scatter_weight_mode: Literal['auto', 'none', 'resample', 'color', 'alpha', 'threshold'] | str = 'auto', scatter_sample_size: int | None = None, scatter_seed: int | None = 12345, scatter_threshold: float = 0.0)

Plot the beam divergence (dX vs dY) in µrad with optional marginals and envelopes. (See plot_beam for parameter semantics.)

Return type:

fig, (ax_image, ax_histx, ax_histy)

barc4beams.viz.plot_energy(df: DataFrame, *, bins: int | Tuple[int, int] | None = None, bin_width: int | float | None = None, bin_method: int = 0, dpi: int = 100, path: str | None = None, weight_by_intensity: bool = True, apply_style: bool = True, k: float = 1.0, plot: bool = True) Tuple[Figure, Axes]

Energy distribution vs E (eV), optionally intensity-weighted.

barc4beams.viz.plot_energy_vs_intensity(df: DataFrame, *, mode: str = 'scatter', aspect_ratio: bool = False, color: int | None = 3, x_range: Tuple[int | float | None, int | float | None] | None = None, y_range: Tuple[int | float | None, int | float | None] | None = None, bins: int | Tuple[int, int] | None = None, bin_width: int | float | None = None, bin_method: int = 0, dpi: int = 100, path: str | None = None, showXhist: bool = True, showYhist: bool = True, envelope_method: str = 'edgeworth', weight_by_intensity: bool = True, apply_style: bool = True, k: float = 1.0, plot: bool = True, scatter_weight_mode: Literal['auto', 'none', 'resample', 'color', 'alpha', 'threshold'] | str = 'auto', scatter_sample_size: int | None = None, scatter_seed: int | None = 12345, scatter_threshold: float = 0.0) Tuple[Figure, Tuple[Axes, Axes | None, Axes | None]]

2D plot with X=energy [eV], Y=Intensity [arb], with optional marginals/envelopes; never silently shows.

barc4beams.viz.plot_intensity(df: DataFrame, *, bins: int | Tuple[int, int] | None = None, bin_width: int | float | None = None, bin_method: int = 0, dpi: int = 100, path: str | None = None, weight_by_intensity: bool = False, apply_style: bool = True, k: float = 1.0, plot: bool = True) Tuple[Figure, Axes]

Intensity distribution vs I, optionally intensity-weighted.

barc4beams.viz.plot_phase_space(df: DataFrame, *, direction: str = 'both', mode: str = 'scatter', aspect_ratio: bool = False, color=3, x_range=None, y_range=None, bins=None, bin_width=None, bin_method=0, dpi: int = 100, path: str | None = None, showXhist=True, showYhist=True, envelope=False, envelope_method='edgeworth', weight_by_intensity: bool = True, apply_style: bool = True, k: float = 1.0, plot: bool = True, z_offset: float = 0.0, scatter_weight_mode: Literal['auto', 'none', 'resample', 'color', 'alpha', 'threshold'] | str = 'auto', scatter_sample_size: int | None = None, scatter_seed: int | None = 12345, scatter_threshold: float = 0.0)

Plot phase space for one or both planes: (X vs dX) and/or (Y vs dY), in µm/µrad.

Returns:

  • (fig_x, axes_x), (fig_y, axes_y) if direction=’both’

  • or

  • fig, (ax_image, ax_histx, ax_histy)

barc4beams.viz.plotting_style(k: float = 1.0)

Temporary plotting style (restores previous rcParams on exit).

Examples

>>> with plotting_style(1.2):
...     plot_beam(df)
barc4beams.viz.start_plotting(k: float = 1.0) None

Set global Matplotlib plot parameters scaled by factor k.

Parameters:

k (float, optional) – Scaling factor for font sizes (1.0 = baseline).

Adapters

adapters.py - conversion of external beam data (PyOptiX, SHADOW3, SHADOW4) into the standard beam schema.

barc4beams.adapters.merge_standard_beams(beams: List[DataFrame]) DataFrame

Merge multiple standard photon beams (pandas DataFrames) into a single combined beam. Each input beam should already be standardized via to_standard_beam, The merge is performed by simple row-wise concatenation of all beams.

Args:

beams (list of pd.DataFrame): List of DataFrames to merge.

Returns:
pd.DataFrame: A single DataFrame containing all rows from the input beams.

Columns are the union of all input columns;

barc4beams.adapters.to_standard_beam(beam, code: str | None = None) DataFrame

Convert an external beam representation into the standard schema.

Supported inputs

  • PyOptiX beam (pd.DataFrame): typically from: OpticalElement.get_diagram(…) OpticalElement.get_impacts(…).

  • Shadow3 beam (code in {‘shadow3’,’s3’}):
    Uses beam.getshcol([…]) with indices:

    [11, 1, 3, 2, 4, 6, 5, 19, 23, 10, 24, 25]

    and returns a DataFrame with columns:
    [“energy”,”X”,”Y”,”Z”,”dX”,”dY”,”dZ”,”wavelength”,

    “intensity”,”lost_ray_flag”,”intensity_s-pol”,”intensity_p-pol”]

  • Shadow4 beam (code in {‘shadow4’,’s4’,’shadow’}):
    Uses beam.get_columns([…]) with indices:

    [26, 1, 3, 2, 4, 6, 5, 19, 23, 10, 24, 25]

    with the same output columns and clipping as Shadow3.

param beam:

PyOptiX DataFrame OR Shadow3/4 beam object.

type beam:

object

param code:

Explicit backend. If None, auto-detect.

type code:

{“pyoptix”, “shadow3”, “shadow4”, “s3”, “s4”}, optional

rtype:

pandas.DataFrame

Schema

schema.py - definition and validation of the standard beam format.

barc4beams.schema.validate_beam(df: DataFrame) None

Validate a standardized beam DataFrame.

Parameters:

df (pandas.DataFrame) – Beam after to_standard_beam(…). Columns may appear in any order.

Raises:

ValueError – If required columns are missing, intensity columns are out of [0, 1], lost-ray flags are not {0, 1}, or a lost ray has nonzero intensity.

Miscellaneous helpers

misc.py - optical design and other auxiliary functions.

barc4beams.misc.energy_wavelength(value: float, unit: str) float

Converts energy to wavelength and vice versa.

Parameters:

value (float or array-like): The value of either energy or wavelength. unity (str): {‘eV’,’meV’,’keV’,’m’, ‘um’,’µm’, ‘nm’,’A’,’Å’,’Angstrom’,} (case-insensitive)

Returns:

float: Converted value in meters if the input is energy, or in eV if the input is wavelength.

Raises:

ValueError: If an invalid unit is provided.