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:
objectHigh-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_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:
objectContainer 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.
- 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,
energymay be scalar. If optical constants are arrays,energymust 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_lengthis provided instead ofbeta.beta (float or array_like, optional) – Refractive index decrement and absorption index. Both must be provided together, unless
attenuation_lengthis provided instead ofbeta.attenuation_length (float or array_like, optional) – Attenuation length in meters. May be provided together with
deltainstead ofbeta. 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
weightsis 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
weightsis 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
weightsis 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 == 0before computing the focal distance. If theintensitycolumn 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 == 0before computing stats. All statistical observables are weighted by theintensitycolumn.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_beamfor 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.