JAX backend#
The differentiable forward model, metrics and pulse parameterisation. These share the core conventions with the NumPy ForwardModel, croak.metrics and
ArrayPulse, and back the JAX-native solvers —
LBFGSAD, LM,
LBFGSHand, COPRAJax,
OptxLBFGS, OptxLM and
CMAES.
This is the general gradient route: it supplies the derivatives for geometric smearing and the fitted extras that the closed-form adjoint does not cover, the Jacobians Levenberg–Marquardt and the Laplace covariance need, derivatives for interactions implemented in the JAX forward path, and on-device execution of a whole loop or population. It also serves as the independent oracle the analytic adjoints are tested against. See Gradients.
JAX forward model#
JAX/autodiff twin of croak.forward.
This module re-implements the nonlinear-process forward model of
croak.forward.ForwardModel in JAX, so that gradients and Jacobians of the
trace (and of any error metric built on it) can be obtained by automatic
differentiation. This is the general gradient route: it reaches model features
the hand-derived Wirtinger adjoints in croak.forward do not cover
(geometric smearing, fitted thickness/delay-zero/smearing width) and supplies the
Jacobians that Levenberg–Marquardt and croak.covariance need. It backs the
LBFGSAD, LM,
OptxLM and CMAES retrievers,
and serves as an independent oracle in the tests that cross-check the analytic
adjoints.
The core local/slab map follows croak.forward.ForwardModel.signal_single().
Additional paths implement chromatic focusing and coherent collection. The module
enables 64-bit JAX (
jax_enable_x64) at import — single precision would not match the~1e-10agreement the tests assert;works internally in DFT-bin order (
ifftshifton input,fftshifton output), using the unnormalised forward DFT for spectrum→time and the1/Ninverse DFT for time→spectrum, exactly ascroak.grid.raw_fft()/_ifft0;treats the slab propagation constant \(\beta(\omega)\) as a static constant: it does not depend on the optimisation variables, so it is built once with the numpy
croak.materials.beta()and captured (no need to evaluate the refractive-index models in JAX).
See croak.forward.ForwardModel for the physical model and notation.
- croak.forward_jax.make_signal_fn(omega, delays, interaction, *, material=None, thickness=0.0, npoints=1, omega0=0.0, quadrature='gausslegendre')[source]#
Build the single-delay signal map \(\tilde E \mapsto \psi(\omega)\).
JAX twin of
croak.forward.ForwardModel.signal_single(). The returned functionsignal(ew, tau)takes a centred complex spectrumewand a delaytauand returns the centred frequency-domain signalpsi. It is differentiable andvmap/jit-friendly; the static problem geometry (grid, delays, interaction, dispersion) is captured in the closure.- Parameters:
omega (array_like) – Centred angular-frequency grid (rad/s), relative to
omega0.delays (array_like) – Delay axis (s); only its length/values inform the closure,
tauis a runtime argument (kept for signature parity with the numpy model).interaction (str) –
"shg","sd"or"pg".material (str | None) – Dispersive-slab parameters; see
croak.forward.ForwardModel.thickness (float) – Dispersive-slab parameters; see
croak.forward.ForwardModel.npoints (int) – Dispersive-slab parameters; see
croak.forward.ForwardModel.omega0 (float) – Dispersive-slab parameters; see
croak.forward.ForwardModel.quadrature (str) – Dispersive-slab parameters; see
croak.forward.ForwardModel.
- Returns:
callable –
signal(ew, tau) -> psi(centred order).- Return type:
Callable[[Array, Array | float], Array]
- croak.forward_jax.make_trace_fn(omega, delays, interaction, *, material=None, thickness=0.0, npoints=1, omega0=0.0, quadrature='gausslegendre', smearing=None, focal=None, normalize=False)[source]#
Build the full-trace map \(\tilde E \mapsto T(\omega,\tau)\).
JAX twin of
croak.forward.ForwardModel.trace(). The returnedtrace(ew)maps a centred spectrum to an(Nomega, Ndelay)intensity trace \(|\psi|^2\), vectorising the single-delay signal overdelayswithjax.vmap(). It is differentiable andjit-friendly.- Parameters:
smearing (SmearingKernel or None, optional) – Geometric time-smearing kernel (see
croak.smearing). Because the delay offset acts across the whole delay axis, the smeared model has no single-delay form; this simply delegates tomake_param_trace_fn()with the slab thickness and delay zero held fixed. The same applies tofocal.focal (FocalMixture or None, optional) – Chromatic focal mixture, optionally carrying a collection aperture. As for
make_param_trace_fn(), to which this delegates when either it orsmearingis set.normalize (bool, optional) – Scale the trace to unit maximum (default
False; retrieval works with the unnormalised trace and absorbs the scale throughmu).parameters (other) – As
make_signal_fn().omega (ArrayLike)
delays (ArrayLike)
interaction (str)
material (str | None)
thickness (float)
npoints (int)
omega0 (float)
quadrature (str)
- Returns:
callable –
trace(ew) -> Tof shape(Nomega, Ndelay).- Return type:
Callable[[Array], Array]
- croak.forward_jax.make_param_trace_fn(omega, delays, interaction, *, depth_weight=None, depth_node_phase=None, material=None, thickness=0.0, npoints=1, omega0=0.0, quadrature='gausslegendre', smearing=None, focal=None, depth_transverse=False, fit_thickness=False, fit_tau0=False, fit_smearing=False, normalize=False)[source]#
Build a trace map that also takes the slab thickness and a delay-zero shift.
Like
make_trace_fn(), but the returnedtrace(ew, thickness, tau0)is differentiable in the slab thicknessLand a delay-zero offsettau0as well as in the spectrum, so the AD retrievers (LBFGSAD,LM) and the covariance estimator can fit them alongside the pulse. Seecroak._jax_pulse.augment()for the parameter packing.The delay-zero offset enters as a shift of the gate’s delay phase, \(e^{i\omega(\tau-\tau_0)}\) — it slides the simulated trace along the delay axis (for SHG, its symmetry centre), correcting a mis-set time zero.
When
fit_thicknessis set the depth quadrature uses normalised Gauss–Legendre nodes \(\xi\in[0,1]\) and weights \(\hat w\) (\(\sum\hat w=1\)) so that, at call time, the depth nodes are \(z_q=L\,\xi_q\), the weights are \(L\,\hat w_q\), and the propagation phases \(e^{i\beta L\xi_q}\), \(e^{i\beta L(1-\xi_q)}\) are differentiable inL. When it is not set, the nodes/weights are baked once fromquadrature_nodes_weights()(so the thin-medium single-node casematerial=Noneis preserved for atau0-only fit).- Parameters:
fit_thickness (bool, optional) – Make the trace differentiable in
thickness. Requires a dispersive slab (materialset andthickness > 0); raises otherwise.fit_tau0 (bool, optional) – Make the trace differentiable in the delay-zero offset
tau0. Marker only —tau0is always a runtime argument; the flag documents intent and parallelsfit_thickness.smearing (SmearingKernel or None, optional) – Geometric time-smearing kernel (see
croak.smearing). When set, the returned trace also accepts a fourth argumentsmear_scale(default1.0) that multiplies the kernel widths, so the smearing strength — equivalently the mask ratiod/D— can be fitted. A scalar scales both channels together; a length-2 vector(scale_p, scale_delta)scales the gate-shape (p) and delay (delta) channels independently (see_smear_scale_pair).None(default) leaves the model untouched.focal (FocalMixture or None, optional) –
Chromatic focal mixture (
croak.focal) in place ofsmearing: the focal average is carried explicitly, each node applying its own \(A(r,\omega)\) and its own definite(p, theta)rather than a Gaussian distribution over them. Mutually exclusive withsmearing.If the mixture carries a
collection(croak.collection.CollectionAperture) the per-node fields are transformed to transverse wavevector and integrated over the aperture instead of summed incoherently — the difference between an instrument that collects the whole signal beam and one that collects it through a hole. PG (TG) only; seecroak.collection.If the mixture carries an
evolvespec (fc-z,croak.focal.evolved_arm_filters()), each of the three arms at each depth node applies its own linearly evolved complex profile at the arm’s walked radius, in place of the single shared entrance-face filter. The spec’s slab parameters must match this function’smaterial/thickness/npoints/quadrature(verified; the filters must sit on the same depth nodes as the propagation phases). PG only; fitting thickness with evolved profiles is unsupported because the table is built for fixed depth nodes. Cost is close to the entrance mixture’s: the depth axis is already batched, only the build-time table is new.fit_smearing (bool, optional) – Make the trace differentiable in the smearing scale. Marker only, for the same reason as
fit_tau0; it does requiresmearingto be set.depth_weight (array_like or None, optional) – Complex generation-envelope weights, one per quadrature node, multiplying the depth-quadrature weights: models the transverse geometry a 1D depth integral cannot see (focal-spot evolution across the slab, beamlet walk-through, Gouy phase), which enters as a smooth per-depth factor \(g(z_q)\) on the locally generated signal. The overall scale is irrelevant (absorbed by \(\mu\)); only the shape matters. Requires a dispersive slab and length
npoints. Withfit_thicknessthe envelope is pinned to the normalised nodes (it rescales with the fitted slab rather than staying fixed in absolute \(z\)).None(default) is the uniform-generation model. Negligible for slabs much thinner than the beams’ Rayleigh range.depth_node_phase (array_like or None, optional) – Complex multiplicative factors of shape
(focal.nodes, npoints)applied to each focal/depth contribution. Requiresfocal. Use for explicit model diagnostics; these factors are not fitted automatically.depth_transverse (bool, optional) –
Model the transverse decoherence of the depth integral. croak’s depth quadrature normally adds the signal generated at every depth with the same transverse phase — fully coherently in transverse wavevector. Real propagation dephases the angular spectrum: signal born at depth \(z_q\) accumulates, over the remaining slab, the extra phase
\[\phi_{jq}(\omega) = \bigl[k_z(\omega, k_{\perp j}) - k_z(\omega, 0)\bigr]\, (L - z_q),\]applied per aperture node \(j\) inside the collection transform, before the coherent depth sum (see
_depth_phase_ratefor \(k_{\perp j}\) and the exact \(k_z\) used). Parameter-free and opt-in; the defaultFalseomits this transverse exit phase. Requiresfocalwith acollectionand a dispersive slab. For a full-collection variant use a collection window much wider than the signal footprint (a large chromatic hole, or a widechromatic=Falsek window) — there is deliberately no separate path. Costs one aperture-transform contraction per depth node instead of one total; withdepth_weightanddepth_node_phaseit composes (both keep their existing meaning). See Modelling the collection aperture for when the missing physics matters (it grows with slab thickness).parameters (other) – As
make_trace_fn().omega (ArrayLike)
delays (ArrayLike)
interaction (str)
material (str | None)
thickness (float)
npoints (int)
omega0 (float)
quadrature (str)
normalize (bool)
- Returns:
callable –
trace(ew, thickness, tau0, smear_scale=1.0) -> Tof shape(Nomega, Ndelay).thickness/tau0/smear_scalemay be Python floats (held fixed) or JAX scalars (differentiated);smear_scalemay also be a length-2 vector for split channel scaling.- Return type:
Callable[[…], Array]
- croak.forward_jax.make_forward_adjoint_fns(omega, delays, interaction, *, material=None, thickness=0.0, npoints=1, omega0=0.0, quadrature='gausslegendre')[source]#
Build the matched JAX forward (with tape) and hand-derived adjoint.
JAX twin of the forward/adjoint pair on
croak.forward.ForwardModel(signal_single()+adjoint_single()). Both share one set of static constants and arevmap/jit-friendly, so a caller can backpropagate a trace cotangent without automatic differentiation — the basis ofLBFGSHandandCOPRAJax.- Returns:
signal_tape (callable) –
signal_tape(ew, tau) -> (psi, test, gate)(centredpsi;test/gateare the time-domain fields the adjoint reuses).adjoint (callable) –
adjoint(psi_bar, test, gate, tau) -> ew_bar(centred), the Wirtinger adjoint mapping \(\partial L/\partial\psi^*\) to \(\partial L/\partial\tilde E^*\).
- Parameters:
omega (ArrayLike)
delays (ArrayLike)
interaction (str)
material (str | None)
thickness (float)
npoints (int)
omega0 (float)
quadrature (str)
- Return type:
tuple[Callable[[Array, Array | float], tuple[Array, Array, Array]], Callable[[Array, Array, Array, Array | float], Array]]
- croak.forward_jax.maketrace_jax(omega, delays, ew, interaction, *, material=None, thickness=0.0, npoints=1, omega0=0.0, quadrature='gausslegendre', smearing=None, normalize=True)[source]#
Generate a (normalised) trace with the JAX model, returned as numpy.
Convenience wrapper around
make_trace_fn()parallelingcroak.forward.maketrace(), for tests and examples.- Parameters:
omega (ArrayLike)
delays (ArrayLike)
ew (NDArray[complex128])
interaction (str)
material (str | None)
thickness (float)
npoints (int)
omega0 (float)
quadrature (str)
smearing (SmearingKernel | None)
normalize (bool)
- Return type:
NDArray[float64]
JAX metrics#
JAX/autodiff twin of croak.metrics plus the solver objective pieces.
These are JAX clones of the trace-error metrics in croak.metrics, written
so that the FROG error (and the least-squares residual vector) is a
differentiable function of the pulse parameters. They back
LBFGSAD (which minimises the scalar frog_error())
and LM (which drives residual_vector() to zero), and are
checked against the numpy metrics in the tests.
Conventions match croak.metrics and croak.lbfgs:
t_meas/t_simare(Nomega, Ndelay)intensity traces;weightsis the per-frequency weight vector of lengthNomega(broadcast along the delay axis), as passed by the solvers;the scalar error is \(R=\sqrt{\sum\mathrm{resid}^2/\mathrm{denom}}\) with \(\mathrm{denom}=MN\,\max(T_\mathrm{meas}w)^2\) — identical to
croak.metrics.compute_R()and to the value minimised incroak.lbfgs.LBFGS.
The second-difference smoothness penalties mirror
croak.pulses._second_diff_penalty so regularised retrieval matches the
analytic-gradient solver.
- croak.metrics_jax.mu_global(t_meas, t_sim, weights)[source]#
Compute the optimal global trace scale factor with JAX.
Mirrors
croak.metrics.compute_mu().weightsis a per-frequency vector broadcast along the delay axis.- Parameters:
t_meas (Array)
t_sim (Array)
weights (Array)
- Return type:
Array
- croak.metrics_jax.mu_per_freq(t_meas, t_sim, weights)[source]#
Compute the optimal scale factor for each frequency row with JAX.
Mirrors
croak.metrics.compute_mu_per_freq()withfreq_axis=0(sum over delays). As there, the weights cancel between numerator and denominator — the factors are weight-independent, and a zero-weight row falls back to1.0. Returns one factor per frequency row.- Parameters:
t_meas (Array)
t_sim (Array)
weights (Array)
- Return type:
Array
- croak.metrics_jax.frog_error(t_meas, t_sim, weights, *, R_omega=False)[source]#
Normalised FROG error \(R\) minimised by the gradient solvers.
Identical to the value computed in
croak.lbfgs.LBFGS(and tocroak.metrics.frog_error()): the optimal scalemuis applied, the weighted residual is formed, and \(R=\sqrt{\sum\mathrm{resid}^2/ \mathrm{denom}}\) is returned.- Parameters:
R_omega (bool, optional) – Use per-frequency adaptive scaling factors instead of a single global
mu.t_meas (Array)
t_sim (Array)
weights (Array)
- Return type:
Array
- croak.metrics_jax.residual_vector(t_meas, t_sim, weights, *, R_omega=False)[source]#
Flattened least-squares residual for
LM.Returns \((T_\mathrm{meas}-\mu T_\mathrm{sim})\,w/\sqrt{\mathrm{denom}}\) flattened to 1-D, so that its Euclidean norm equals the FROG error
frog_error(). The least-squares solvers minimise its squared norm, with any penalty rows appended separately.- Parameters:
t_meas (Array)
t_sim (Array)
weights (Array)
R_omega (bool)
- Return type:
Array
- croak.metrics_jax.amplitude_penalty(amp_params)[source]#
Amplitude smoothness penalty (max-normalised), as in
ArrayPulse.- Parameters:
amp_params (Array)
- Return type:
Array
- croak.metrics_jax.phase_penalty(phase_params)[source]#
Phase smoothness penalty (mean squared curvature), as in
ArrayPulse.- Parameters:
phase_params (Array)
- Return type:
Array
- croak.metrics_jax.spectral_penalty(amp_params, target)[source]#
Relative spectral-amplitude mismatch
‖a - target‖² / ‖target‖².JAX twin of
croak.pulses.ArrayPulse.spectral_penalty().targetis the target spectral amplitude over the optimised support (same length asamp_params).- Parameters:
amp_params (Array)
target (Array)
- Return type:
Array
JAX pulse parameterisation#
The differentiable u → spectrum map shared by the JAX solvers, the reduced
cubic-B-spline phase basis, and the smoothness / spectral / temporal penalties.
Shared parameterisation helper for the JAX retrievers.
Both LBFGSAD and LM optimise the same
real parameter vector as croak.lbfgs.LBFGS: the spectral amplitude and
phase over an optional support window (u = [A; phi]), or just the phase when
phase_only holds the amplitude fixed. This module provides the single
differentiable map from those parameters to a complex spectrum, mirroring
croak.pulses.ArrayPulse.spectrum()/set_params so the AD solvers share
the analytic solver’s exact parameterisation (and are directly comparable to it).
- croak._jax_pulse.make_spectrum_fn(amplitude, phase, *, support=None, phase_only=False)[source]#
Build the differentiable map
u -> spectrumand its initial parameters.JAX twin of
croak.pulses.ArrayPulse. Parameters outside the support window keep the seedamplitude/phaseand are not optimised.- Parameters:
amplitude (array_like) – Seed spectral amplitude \(|\tilde E|\) and phase (length
N).phase (array_like) – Seed spectral amplitude \(|\tilde E|\) and phase (length
N).support (tuple of int, optional) – Half-open
(start, stop)index range of the optimised window; the full grid by default.phase_only (bool, optional) – Optimise only the phase, holding
amplitudefixed.
- Returns:
spectrum_fn (callable) –
spectrum_fn(u) -> ewreturning the centred complex spectrum \(A\,e^{i\phi}\).u0 (numpy.ndarray) – Initial parameter vector (
[A[support]; phi[support]]or, forphase_only,phi[support]).nidcs (int) – Number of optimised frequency indices — the split point between the amplitude and phase blocks of
u(for the regularisation penalties).
- Return type:
tuple[Callable[[Array], Array], NDArray[float64], int]
- croak._jax_pulse.make_param_grad_fns(amplitude, phase, *, support=None, phase_only=False)[source]#
Build the hand-derived parameter-space adjoints for
u.Same
uasmake_spectrum_fn(). JAX twin of the adjoint side ofcroak.pulses.ArrayPulse(ew_vjp()and the*_penalty_gradmethods). The parameterisation (support window,phase_only) matchesmake_spectrum_fn()exactly so the two are used together.- Parameters:
amplitude (ArrayLike)
phase (ArrayLike)
support (tuple[int, int] | None)
phase_only (bool)
- Return type:
- class croak._jax_pulse.ParamGradFns(ew_vjp, amplitude_penalty_grad, phase_penalty_grad, spectral_penalty_grad)[source]#
Bases:
NamedTupleHand-derived parameter-space adjoints, the JAX twin of
ArrayPulse.These mirror
croak.pulses.ArrayPulse.ew_vjp()and the regularisation gradients, expressed injnp(no autodiff). They let the non-AD retriever map a spectral cotangentew_barand the parametersutodL/du.- Parameters:
ew_vjp (Callable[[Array, Array], Array])
amplitude_penalty_grad (Callable[[Array], Array])
phase_penalty_grad (Callable[[Array], Array])
spectral_penalty_grad (Callable[[Array, Array], Array])
- ew_vjp: Callable[[Array, Array], Array]#
spectral cotangent → parameter gradient.
- Type:
ew_vjp(u, ew_bar) -> du
- amplitude_penalty_grad: Callable[[Array], Array]#
amplitude_penalty_grad(u) -> du(full-length; phase block zero).
- phase_penalty_grad: Callable[[Array], Array]#
phase_penalty_grad(u) -> du(full-length; amplitude block zero).
- spectral_penalty_grad: Callable[[Array, Array], Array]#
spectral_penalty_grad(u, target_support) -> du(amplitude block; zero in phase-only mode).target_supportis the target amplitude over the optimised support (lengthnidcs).
- croak._jax_pulse.make_spline_phase_basis(amplitude, phase, omega, *, n_nodes, degree=3, support=None, support_threshold=0.001)[source]#
Phase-only basis whose phase is a cubic B-spline over the spectrum support.
The spectral phase on the support window is a fixed linear map \(\phi = B\,c\) of
n_nodescontrol pointsc(the optimised parameters), with the amplitude held at the seedamplitude. BecauseB(thescipy.interpolate.BSpline.design_matrix()) is a constant, the map is exactly \(C^2\) (cubic) and trivially AD-differentiable. Knots are clamped over the non-zero-spectrum window only, so nodes don’t waste degrees of freedom where there is no signal.Returns
(spectrum_fn, c0, phase_penalty, support)wherec0fits the seed phase andphase_penalty(c)is the P-spline roughness penalty \(\mathrm{mean}((D_2 c)^2)\) (a 2nd-difference on the coefficients).- Parameters:
amplitude (ArrayLike)
phase (ArrayLike)
omega (ArrayLike)
n_nodes (int)
degree (int)
support (tuple[int, int] | None)
support_threshold (float)
- Return type:
tuple[Callable[[Array], Array], NDArray[float64], Callable, tuple[int, int]]
- croak._jax_pulse.build_parameterisation(ew0, omega, *, phase_only, phase_basis='pointwise', n_nodes=20, support_threshold=0.001, spectral_target=None, time_mask=None)[source]#
Build the
u -> spectrummap shared by the AD retrievers.phase_basis="pointwise"is the existing per-frequency parameterisation (amplitude+phase, or phase-only);"bspline"is the reduced cubic B-spline phase basis (implies phase-only). The returnedPenaltiesalready handle slicing/mode so each solver just weights them by itsreg_*.time_mask(lengthn, on the centredgrid.taxis) enables the temporal penalty: the energy fraction ofE(t) = ifft(spectrum)falling where the mask is non-zero — a self-consistent, mode-agnostic alternative to the post-retrieval temporal filter. Seetime_window_mask().- Parameters:
ew0 (NDArray[complex128])
omega (ArrayLike)
phase_only (bool)
phase_basis (str)
n_nodes (int)
support_threshold (float)
spectral_target (NDArray[float64] | None)
time_mask (NDArray[float64] | None)
- Return type:
- croak._jax_pulse.ls_parameterisation(ew0, omega, *, phase_only, phase_basis='pointwise', n_nodes=20, support_threshold=0.001)[source]#
Build the least-squares (LM) solver parameterisation.
The LM solvers add penalties as residual rows rather than scalar terms. Returns
(spectrum_fn, u0, nidcs, phase_only_eff). For the B-spline basisnidcs=0andphase_only_eff=True(no amplitude block) — and the LM solvers’ 2nd-difference phase rows onuthen are the P-spline penalty on the spline coefficients.- Parameters:
ew0 (NDArray[complex128])
omega (ArrayLike)
phase_only (bool)
phase_basis (str)
n_nodes (int)
support_threshold (float)
- Return type:
tuple[Callable[[Array], Array], NDArray[float64], int, bool]
- class croak._jax_pulse.Parameterisation(spectrum_fn, u0, penalties)[source]#
Bases:
NamedTupleA differentiable
u -> spectrummap plus its initial parameters/penalties.- Parameters:
spectrum_fn (Callable[[Array], Array])
u0 (NDArray[float64])
penalties (Penalties)
- spectrum_fn: Callable[[Array], Array]#
Alias for field number 0
- u0: NDArray[float64]#
Alias for field number 1
- class croak._jax_pulse.Penalties(phase, amplitude, spectral, temporal)[source]#
Bases:
NamedTupleRegularisation terms for a parameterisation (each maps
u -> scalar).- Parameters:
phase (Callable[[Array], Array])
amplitude (Callable[[Array], Array])
spectral (Callable[[Array], Array])
temporal (Callable[[Array], Array])
- phase: Callable[[Array], Array]#
Alias for field number 0
- amplitude: Callable[[Array], Array]#
Alias for field number 1
- spectral: Callable[[Array], Array]#
Alias for field number 2
- temporal: Callable[[Array], Array]#
Alias for field number 3
- croak._jax_pulse.time_window_mask(t, win_lo, win_hi, dt)[source]#
Weight (in
[0, 1]) that penalises field energy outside a window.The complement of a Planck taper over
[win_lo, win_hi](roll-off20*dteach side, mirroringcroak.processing.post_filter()):0inside the window, rising smoothly to1outside it. Multiplied against|E(t)|^2by the temporal regularisation penalty.- Parameters:
t (ArrayLike)
win_lo (float)
win_hi (float)
dt (float)
- Return type:
NDArray[float64]
- class croak._jax_pulse.ExtraParamSpec(fit_thickness=False, thickness0=0.0, scale_L=0.0, fit_tau0=False, tau0_0=0.0, scale_tau=0.0, fit_smearing=False, smear_scale0=1.0, scale_smear=1.0, fit_smearing_split=False, smear_delta0=1.0)[source]#
Bases:
objectSpecification of the optional scalar parameters fitted with the pulse.
The slab thickness
Land a delay-zero offset \(\tau_0\) are optimised as dimensionless, O(1)-scaled offsets appended to the pulse parameter vector, so the augmented problem stays well-conditioned for NLopt / SciPytrfdespite the tiny physical scales (L ~ 1e-5 m, \(\tau_0 \sim 10^{-15}\) s):\[L = L_0 + \delta_L\,s_L, \qquad \tau_0 = \tau_{0,0} + \delta_\tau\,s_\tau\]with the optimised variables \(\delta_L, \delta_\tau\) initialised at zero. The returned lower bound \(-L_0/s_L\) keeps
Lnon-negative for the bounded solvers (the Optimistix solvers ignore it). The centres \(L_0\), \(\tau_{0,0}\) are the priors: the nominal values for a cold-started retrieval, the previous fit’s values when warm-starting (seecroak.pipeline.retrieve_from_tracedata()), and the fitted values when re-linearising for covariance. An extra whosefit_*flag is off is held at its centre.- Parameters:
fit_thickness (bool, optional) – Fit the slab thickness (requires a dispersive slab;
thickness0 > 0).thickness0 (float, optional) – Centre thickness \(L_0\) (m) — the prior/held value.
scale_L (float, optional) – Normalisation \(s_L\) (m) for \(\delta_L\); defaults to
thickness0(so \(\delta_L\) is the fractional change).fit_tau0 (bool, optional) – Fit the delay-zero offset.
tau0_0 (float, optional) – Centre delay-zero offset \(\tau_{0,0}\) (s);
0for retrieval.scale_tau (float, optional) – Normalisation \(s_\tau\) (s) for \(\delta_\tau\); typically one delay step. Required when
fit_tau0is set.fit_smearing (bool, optional) – Fit the geometric-smearing strength as a dimensionless multiplier on both kernel widths — equivalently, the mask ratio
d/D, the only geometric lever on the effect in the reduced model. A fitted value can also absorb omitted physics. Requires a smearing kernel.smear_scale0 (float, optional) – Centre multiplier (
1.0= the kernel as supplied). For a split fit this is thep-channel centre.scale_smear (float, optional) – Normalisation for the multiplier offset. It is already
O(1), so the default1.0is almost always right.fit_smearing_split (bool, optional) – Fit the gate-shape (
p) and delay (delta) kernel widths as two independent multipliers instead of one joint one — the diagnostic for which channel deviates from the geometric prediction. Requiresfit_smearing.smear_delta0 (float, optional) – Centre multiplier of the delay channel for a split fit (
1.0= the kernel as supplied).
- property any: bool#
Whether any extra parameter is fitted.
- class croak._jax_pulse.Augmentation(n_pulse, u0, unpack, physical, lower_bounds, idx_thickness, idx_tau0, idx_smear, idx_smear_delta, scales)[source]#
Bases:
NamedTupleThe augmented parameter vector plus its (un)packing maps.
See
augment().unpackis differentiable (used inside the JAX objective/Jacobian);physicalreturns plain floats for reporting; the scales convert a covariance σ on \(\delta\) back to physical units.- Parameters:
n_pulse (int)
u0 (NDArray[float64])
unpack (Callable[[Array], tuple[Array, Array | float, Array | float, Array | float]])
physical (Callable[[ArrayLike], tuple[float, float, float | tuple[float, float]]])
lower_bounds (NDArray[float64])
idx_thickness (int | None)
idx_tau0 (int | None)
idx_smear (int | None)
idx_smear_delta (int | None)
scales (tuple[float, float, float])
- n_pulse: int#
Alias for field number 0
- u0: NDArray[float64]#
Augmented vector
[u_pulse; delta_L?; delta_tau?; delta_smear?; delta_smear_d?].
- unpack: Callable[[Array], tuple[Array, Array | float, Array | float, Array | float]]#
unpack(u_ext) -> (u_pulse, thickness, tau0, smear_scale)(JAX-friendly).smear_scaleis a scalar for a joint fit and a length-2 vector(scale_p, scale_delta)when the channels are fitted separately.
- physical: Callable[[ArrayLike], tuple[float, float, float | tuple[float, float]]]#
physical(u_ext) -> (thickness, tau0, smear_scale)as floats;smear_scaleis a(scale_p, scale_delta)tuple for a split fit.
- lower_bounds: NDArray[float64]#
Per-component lower bounds (
-inffor the pulse block andtau0).
- idx_thickness: int | None#
Index of the thickness offset in
u_ext(Nonewhen not fitted).
- idx_tau0: int | None#
Index of the delay-zero offset in
u_ext(Nonewhen not fitted).
- idx_smear: int | None#
Index of the smearing-scale offset in
u_ext(Nonewhen not fitted). For a split fit this is thep-channel scale.
- idx_smear_delta: int | None#
Index of the delay-channel scale offset (
Noneunless split-fitted).
- scales: tuple[float, float, float]#
Resolved scales
(scale_L, scale_tau, scale_smear)(0 where not fitted). The split delay-channel offset sharesscale_smear.
- croak._jax_pulse.augment(u0_pulse, spec)[source]#
Append the fitted extra scalars to a pulse parameter vector.
- Parameters:
u0_pulse (numpy.ndarray) – The pulse-only initial parameter vector (from
build_parameterisation()/ls_parameterisation()).spec (ExtraParamSpec) – Which extras to fit and their scales.
- Returns:
Augmentation – The augmented vector and its packing maps (see the class docstring).
- Raises:
ValueError – If a fitted extra has a non-positive scale.
- Return type: