clophfit.fitting.bayes_config ============================= .. py:module:: clophfit.fitting.bayes_config .. autoapi-nested-parse:: Configuration objects for the PyMC binding-fit entry points. These frozen dataclasses group the many keyword parameters of :func:`clophfit.fitting.bayes.fit_binding_pymc` into cohesive, self-documenting bundles. They live in a dedicated module (importing only from :mod:`clophfit.fitting.data_structures`) so :mod:`clophfit.fitting.bayes` can re-export them without a circular import. Classes ------- .. autoapisummary:: clophfit.fitting.bayes_config.SamplerConfig clophfit.fitting.bayes_config.RobustConfig clophfit.fitting.bayes_config.InitConfig clophfit.fitting.bayes_config.XPrior clophfit.fitting.bayes_config.NoiseConfig Module Contents --------------- .. py:class:: SamplerConfig NUTS sampling controls forwarded to ``pm.sample``. :param n_samples: Number of posterior draws per chain. :type n_samples: int :param nuts_sampler: NUTS backend. Defaults to ``"nutpie"`` — its warmup/mass-matrix adaptation is robust on the multi-well latent-x geometry. ``"pymc"`` (built-in NUTS, Numba backend) is fine and marginally faster on simple deterministic-x fits. ``"default"`` lets PyMC auto-select whatever is installed; ``"numpyro"``/``"blackjax"`` (JAX/GPU) request those explicitly but are unusable here (numpyro lacks an ``erfcx`` implementation; blackjax is incompatible with PyMC 6.1). :type nuts_sampler: str :param n_tune: Number of tuning draws. ``None`` uses ``n_samples // 2``. :type n_tune: int | None :param target_accept: Target acceptance probability. ``None`` selects a latent-x-aware default. :type target_accept: float | None :param max_treedepth: Maximum NUTS tree depth. ``None`` uses the backend default. :type max_treedepth: int | None :param random_seed: Seed forwarded to ``pm.sample`` for reproducible draws. ``None`` (the default) leaves sampling nondeterministic. :type random_seed: int | None :param chains: Number of MCMC chains. ``None`` uses the PyMC default (4). :type chains: int | None :param cores: Number of CPU cores for parallel chains. ``None`` uses the PyMC default (min of chains and available cores). Set to 1 on a laptop to avoid multiprocessing overhead, or higher on a many-core server. :type cores: int | None :param chain_method: Chain execution strategy for the JAX backends (``"blackjax"``, ``"numpyro"``). ``"auto"`` selects ``"vectorized"`` so all chains run on a single GPU (``jax.vmap``); ``"parallel"`` maps chains across devices (``jax.pmap``). Ignored by CPU backends. :type chain_method: ChainMethod :param compute_log_likelihood: Compute the per-observation ``log_likelihood`` group after sampling. Disabled by default because it adds a full post-sampling pass and is only needed for out-of-sample model comparison (``az.loo`` / ``az.compare``). Enable it when a downstream comparison requires it. :type compute_log_likelihood: bool :param backend: Compilation backend forwarded to ``pm.sample(backend=...)``, e.g. ``"jax"`` to JIT-compile the model's logp/dlogp through JAX (GPU) or ``"numba"``. ``None`` uses the sampler's default. Cannot be combined with ``compile_kwargs={"mode": ...}``. :type backend: str | None :param compile_kwargs: Extra keyword arguments forwarded to the functions compiled by the step methods (``pm.sample(compile_kwargs=...)``), e.g. a custom ``{"mode": ...}``. ``None`` uses the default. Note: use *backend* to select JAX/Numba — ``"backend"`` is not a valid ``compile_kwargs`` key. :type compile_kwargs: Mapping[str, typing.Any] | None .. py:class:: RobustConfig Robust-likelihood configuration. :param enabled: Use a robust likelihood instead of a plain Normal. :type enabled: bool :param likelihood: ``"student_t"`` heavy-tailed likelihood or ``"mixture"`` Normal/outlier contamination mixture. :type likelihood: RobustLikelihood :param nu: Student-t degrees of freedom. Positive values are fixed; ``None`` infers ``student_t_nu`` with support above 2. :type nu: float | None :param contamination_frac_prior: Prior mean for per-label outlier fractions when ``likelihood="mixture"``. A mapping supplies label-specific means. Each value must be between 0.001 and 0.5. :type contamination_frac_prior: ContaminationFracPrior .. py:class:: InitConfig Prior-initialization strategy for the binding parameters. :param strategy: ``"lmfit"`` fits a raw ``Dataset`` with LMFit first and centers PyMC priors on that result. ``"data_priors"`` skips LMFit and derives weak priors directly from the observed titration endpoints and midpoint. :type strategy: InitStrategy :param edge_points: Number of active points averaged at each titration edge to initialize ``S0``/``S1`` when ``strategy="data_priors"``. :type edge_points: int :param signal_sigma_scale: Prior sigma for ``S0``/``S1`` as a fraction of each label's observed signal range when ``strategy="data_priors"``. :type signal_sigma_scale: float :param k_prior: K prior family for ``strategy="data_priors"``. :type k_prior: DataKPrior :param k_bounds: Lower and upper K bounds for data-derived priors. ``None`` resolves to ``(4.5, 9.0)`` for pH datasets or ``(1e-6, 1e6)`` otherwise. :type k_bounds: tuple[float, float] | None :param k_sigma: Truncated-Normal K prior sigma for data-derived priors. :type k_sigma: float .. py:class:: XPrior An informed prior for the latent pH axis, from a previous plate fit. ``create_x_true`` normally derives the pipetting random walk from the measured ``x`` and its per-point SD. A two-stage fit instead estimates the plate's pH axis once with all wells pooled, then hands that estimate to per-well fits so each well refines a shared axis rather than rediscovering it alone. Only plate-level quantities belong here. A well's *own* deviation must not be fed back to it: stage one inferred that deviation from that well's fluorescence, so reusing it as a prior would put the same measurements into both prior and likelihood and shrink the resulting K interval below what the evidence supports. The shared anchor is diluted across every well, so its contamination by any single well is of order ``1/n_wells``. :param x_start_mu: Prior mean for the titration's starting x. :type x_start_mu: float :param x_start_sigma: Prior SD for the starting x. Must be positive. :type x_start_sigma: float :param step_mu: Prior mean per addition step, length ``len(x) - 1``. :type step_mu: ArrayF :param step_sigma: Prior SD per addition step, same length as *step_mu*. Must be positive. :type step_sigma: ArrayF .. py:class:: NoiseConfig Observation-noise configuration. Prefer the :meth:`ye_mag` and :meth:`structured` factories over the raw constructor. ``NoiseConfig()`` is equivalent to :meth:`ye_mag`. Two mutually exclusive noise families are supported, selected by *kind*: - ``"ye_mag"`` scales each label's supplied ``y_err`` by a learned multiplier (``sigma = ye_mag * y_err``). - ``"structured"`` builds a floor-plus-Poisson-plus-proportional noise model. When *noise_model* is ``None`` the model is synthesized from the data using the *floor*/*gain*/*alpha* scale hints, so the ``*_mode`` selectors work without hand-building a :class:`~clophfit.fitting.data_structures.PlateNoiseModel`. .. rubric:: Notes A ``*_mode`` of ``None`` resolves at fit time to ``"centered"`` for pre-fit ``FitResult`` input and ``"free"`` for raw ``Dataset`` input. .. py:method:: ye_mag(*, shared = False, prior = 'lognormal', mu = 0.0, sigma = 1.5) :classmethod: Scale supplied ``y_err`` by a learned ``ye_mag`` multiplier. .. py:method:: structured(*, noise_model = None, floor_mode = None, gain_mode = None, alpha_mode = None, shared_alpha = False, shared_gain = False, shared_floor = False, floor = None, gain = 0.0, alpha = 0.02, learn_ye_mags = False, shared_ye_mags = False) :classmethod: Floor-plus-Poisson-plus-proportional noise model. When *noise_model* is ``None`` the model is synthesized from the data: each label gets ``sigma_floor`` from *floor* (fallback: the label's ``y_err`` scale), plus *gain* and *alpha*. Setting ``gain_mode="free"`` or ``alpha_mode="free"`` activates those terms. The *alpha* hint is the prior mean, not a hard value: it is the ``TruncatedNormal`` centre in ``"centered"`` mode, and in ``"free"`` mode the ``HalfNormal`` sigma is scaled so the mean matches the hint. It defaults to ``0.02`` (a weak 2% prior); pass ``alpha=0`` for the tightest around-zero prior (the width is floored at ``1e-3``; in ``"free"`` mode that gives a sigma of ``1e-3 * sqrt(pi/2)`` ~= ``1.253e-3`` and a mean of ``1e-3``, while in ``"centered"`` mode the term becomes ``HalfNormal(sigma=1e-3)`` whose mean is ``~7.98e-4``), a larger value to widen it, or ``alpha_mode="fixed"`` to pin/disable the term.