Skip to content

gp3bayespy.prior_posterior_bridge

10 public functions in this module.

← API reference hub

Source code in src/gp3bayespy/prior_posterior_bridge.py
314
315
316
317
318
319
320
321
def plot_prior_posterior_contraction(x: PriorPosteriorBridge):
    d = x.summary
    plt = _mpl()
    fig, ax = plt.subplots()
    ax.barh(d["variable"], d["contraction"])
    ax.axvline(0, linestyle="--")
    ax.set_xlabel("1 - posterior SD / prior SD")
    return fig
Source code in src/gp3bayespy/prior_posterior_bridge.py
274
275
276
277
278
279
280
281
282
283
284
285
286
def plot_prior_posterior_density(x: PriorPosteriorBridge, max_draws: int = 1000):
    d = prior_posterior_draws_long(x, max_draws=max_draws)
    plt = _mpl()
    variables = list(dict.fromkeys(d["variable"]))
    fig, axes = plt.subplots(len(variables), 1, squeeze=False, figsize=(7, 3 * len(variables)))
    for ax, variable in zip(axes[:, 0], variables, strict=True):
        for label, frame in d[d["variable"] == variable].groupby("distribution", sort=False):
            values = frame["value"].to_numpy(float)
            ax.hist(values, bins=40, density=True, histtype="step", label=str(label))
        ax.set_title(str(variable))
        ax.legend()
    fig.tight_layout()
    return fig
Source code in src/gp3bayespy/prior_posterior_bridge.py
289
290
291
292
293
294
295
296
297
298
299
300
301
def plot_prior_posterior_intervals(x: PriorPosteriorBridge):
    d = x.summary
    plt = _mpl()
    fig, ax = plt.subplots()
    y = np.arange(len(d))
    ax.hlines(y - 0.12, d["prior_lower"], d["prior_upper"])
    ax.scatter(d["prior_median"], y - 0.12, label="Prior")
    ax.hlines(y + 0.12, d["posterior_lower"], d["posterior_upper"])
    ax.scatter(d["posterior_median"], y + 0.12, label="Posterior")
    ax.set_yticks(y, d["variable"])
    ax.legend()
    ax.set_title("Declared prior vs posterior intervals")
    return fig
Source code in src/gp3bayespy/prior_posterior_bridge.py
304
305
306
307
308
309
310
311
def plot_prior_posterior_shift(x: PriorPosteriorBridge):
    d = x.summary
    plt = _mpl()
    fig, ax = plt.subplots()
    ax.barh(d["variable"], d["standardized_location_shift"])
    ax.axvline(0, linestyle="--")
    ax.set_xlabel("Standardized median shift")
    return fig

Declared-prior versus fitted-posterior bridges.

Source code in src/gp3bayespy/prior_posterior_bridge.py
247
248
249
250
def prior_posterior_distance_table(x: PriorPosteriorBridge) -> pd.DataFrame:
    if not isinstance(x, PriorPosteriorBridge):
        raise GP3BayesError("`x` must be a PriorPosteriorBridge.")
    return x.distances.copy()
Source code in src/gp3bayespy/prior_posterior_bridge.py
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
def prior_posterior_draws_long(
    x: PriorPosteriorBridge,
    max_draws: int = 1000,
    seed: int = 1,
) -> pd.DataFrame:
    if not isinstance(x, PriorPosteriorBridge) or max_draws < 50:
        raise GP3BayesError("A PriorPosteriorBridge and `max_draws >= 50` are required.")
    pieces = []
    for offset, (label, frame) in enumerate(
        (("prior", x.prior_draws), ("posterior", x.posterior_draws))
    ):
        sample = frame
        if len(sample) > max_draws:
            sample = sample.sample(max_draws, random_state=seed + offset).sort_index()
        long = sample.reset_index(drop=True).melt(var_name="variable", value_name="value")
        long.insert(0, "draw", np.tile(np.arange(1, len(sample) + 1), sample.shape[1]))
        long.insert(2, "distribution", label)
        pieces.append(long)
    return pd.concat(pieces, ignore_index=True)
Source code in src/gp3bayespy/prior_posterior_bridge.py
241
242
243
244
def prior_posterior_summary_table(x: PriorPosteriorBridge) -> pd.DataFrame:
    if not isinstance(x, PriorPosteriorBridge):
        raise GP3BayesError("`x` must be a PriorPosteriorBridge.")
    return x.summary.copy()
Source code in src/gp3bayespy/prior_posterior_bridge.py
52
53
def prior_specification_table(x: Any) -> pd.DataFrame:
    return _prior_object(x).table.copy()
Source code in src/gp3bayespy/prior_posterior_bridge.py
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
def simulate_declared_prior_draws(
    x: Any,
    variables: Sequence[str] | str | None = None,
    regex: str | None = None,
    ndraws: int = 4000,
    seed: int = 1,
) -> pd.DataFrame:
    if ndraws < 50 or seed < 0:
        raise GP3BayesError("`ndraws` must be >= 50 and `seed` non-negative.")
    priors = _prior_object(x)
    if variables is None:
        if not getattr(x, "fit_performed", False):
            raise GP3BayesError("`variables` is required when `x` is not a fitted model.")
        posterior = extract_posterior_draws(x, format="matrix")
        variables = list(getattr(posterior, "columns", []))
        if not variables and isinstance(posterior, np.ndarray):
            # Canonical extractor returns a DataFrame-like matrix in current port.
            raise GP3BayesError("Posterior variable names are required to infer declared priors.")
        variables = [v for v in variables if _class_for_variable(str(v)) is not None]
    requested = [variables] if isinstance(variables, str) else list(variables)
    if regex is not None:
        import re

        pattern = re.compile(regex)
        requested = [v for v in requested if pattern.search(v)]
    if not requested:
        raise GP3BayesError("No supported prior variables remain.")
    rng = np.random.default_rng(seed)
    table = priors.table
    out: dict[str, np.ndarray] = {}
    for variable in dict.fromkeys(requested):
        cls = _class_for_variable(variable)
        if cls is None:
            raise GP3BayesError(f"Unsupported variable: {variable}.")
        rows = table.loc[table["parameter_class"] == cls]
        if len(rows) != 1:
            raise GP3BayesError(f"No unique declared prior for class {cls!r}.")
        out[str(variable)] = _sample_prior(rows.iloc[0], ndraws, rng)
    return pd.DataFrame(out)