bossanova 0.1.0.dev13__tar.gz → 0.1.0.dev15__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/.gitignore +1 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/PKG-INFO +1 -1
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/__init__.py +4 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/builders/specs.py +12 -52
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/builders/state.py +2 -1
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/schemas.py +36 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/structs/data.py +3 -0
- bossanova-0.1.0.dev15/bossanova/internal/containers/structs/explore.py +205 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/structs/state.py +20 -4
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/__init__.py +3 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/config.py +56 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/contrasts.py +107 -7
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/multiplicity.py +3 -2
- bossanova-0.1.0.dev15/bossanova/internal/maths/rounding.py +89 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/bundle.py +77 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/common/__init__.py +14 -0
- bossanova-0.1.0.dev15/bossanova/internal/operations/common/contrast_registry.py +61 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/common/formula_utils.py +43 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/compare/compare.py +11 -7
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/parse.py +127 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/__init__.py +12 -0
- bossanova-0.1.0.dev15/bossanova/internal/operations/marginal/bracket_contrasts.py +565 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/compute.py +258 -14
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/conditions.py +47 -4
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/contrasts.py +150 -27
- bossanova-0.1.0.dev15/bossanova/internal/operations/marginal/explore.py +173 -0
- bossanova-0.1.0.dev15/bossanova/internal/operations/marginal/explore_parser.py +754 -0
- bossanova-0.1.0.dev15/bossanova/internal/operations/marginal/explore_scanner.py +81 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/inference.py +11 -8
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/__init__.py +10 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/harness.py +211 -118
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/metrics.py +29 -0
- bossanova-0.1.0.dev15/bossanova/internal/operations/simulation/power.py +244 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/mem.py +1 -4
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/model/core.py +366 -32
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/model/summary.py +53 -39
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/pyproject.toml +1 -1
- bossanova-0.1.0.dev13/bossanova/internal/containers/structs/explore.py +0 -96
- bossanova-0.1.0.dev13/bossanova/internal/operations/marginal/explore.py +0 -354
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/LICENSE +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/README.md +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/README.md +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/advertising.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/cake.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/chickweight.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/credit.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/gammas.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/mtcars.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/penguins.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/poker.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/sleep.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/titanic.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/titanic_test.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/data/titanic_train.csv +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/distributions/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/distributions/continuous.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/distributions/discrete.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/distributions/varying.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/expressions.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/builders/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/builders/data.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/builders/dataframes.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/builders/resamples.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/builders/results.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/structs/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/structs/display.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/structs/formula.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/structs/specs.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/validators.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/backend/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/backend/dispatch.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/backend/jax.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/backend/numpy.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/backend/protocol.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/batching.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/convergence.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/design/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/design/coding.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/design/names.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/design/reference.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/design/z_matrix.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/differentiation.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/distributions/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/distributions/algebra.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/distributions/base.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/distributions/core.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/distributions/derived.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/distributions/factories.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/distributions/plotting.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/distributions/probability.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/binomial.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/create.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/gamma.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/gaussian.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/links.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/poisson.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/response.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/schema.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/family/tdist.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/diagnostics.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/estimation.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/hypothesis.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/information_criteria.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/profile.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/sandwich.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/satterthwaite.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/wald_variance.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/inference/welch.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/linalg/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/linalg/qr.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/linalg/schur.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/linalg/sparse.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/linalg/svd.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/predict.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/rng.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/glm.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/glmer.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/heuristics.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/initialization.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/lambda_builder.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/lambda_sparse.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/lambda_template.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/lmer.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/optimize.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/pirls_sparse.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/solvers/quadrature.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/tolerances.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/transforms.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/variance.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/maths/weights.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/common/data_utils.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/common/factors.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/compare/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/compare/cv.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/compare/deviance.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/compare/f_test.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/compare/helpers.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/compare/lrt.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/compare/lrt_compare.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/compare/refit.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/contrasts.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/convergence.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/diagnostics.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/fit/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/fit/dispatch.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/fit/glm.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/fit/glmer.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/fit/lmer.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/fit/ols.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/fit/rank.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/design.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/encoding.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/evaluate.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/evaluate_newdata.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/evaluate_transforms.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/helpers.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/parser/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/parser/expr.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/parser/parser.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/parser/scanner.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/parser/token.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/formula/random_effects.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/asymptotic.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/bootstrap.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/cv.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/mee.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/params.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/permutation.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/prediction.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/profile.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/resample_bundle.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/satterthwaite_emm.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/infer/simulation.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/emm.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/grid.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/joint_tests.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/slopes.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/marginal/validation.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/predict.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/profile.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/rendering/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/rendering/latex.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/common.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/core.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/glm.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/glmer.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/lm.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/lm_bca.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/lm_operators.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/lmer.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/mixed.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/results.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/resample/utils.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/dgp/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/dgp/generate.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/dgp/glm.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/dgp/glmer.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/dgp/lm.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/dgp/lmer.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/simulation/model_sim.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/transforms.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/operations/varying.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/README.md +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/cognition.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/compare.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/core.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/core_data.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/core_protocols.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/core_sizing.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/core_viz.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/dag.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/design.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/fit.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/fit_builders.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/fit_layers.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/helpers.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/lattice.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/layout.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/params.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/predict.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/profile.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/ranef.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/relationships.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/resamples.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/resid.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/viz/vif.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/model/__init__.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/model/guards.py +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/py.typed +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/tests/bossanova_benchmarks/bootstrap/data/README.md +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/tests/bossanova_benchmarks/insteval/data/README.md +0 -0
- {bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/tests/bossanova_tests/hypothesis/README.md +0 -0
|
@@ -15,7 +15,9 @@ except (ImportError, AttributeError):
|
|
|
15
15
|
|
|
16
16
|
# Configuration
|
|
17
17
|
from bossanova.internal.maths.config import ( # noqa: E402
|
|
18
|
+
get_display_digits,
|
|
18
19
|
get_singular_tolerance,
|
|
20
|
+
set_display_digits,
|
|
19
21
|
set_singular_tolerance,
|
|
20
22
|
)
|
|
21
23
|
|
|
@@ -42,11 +44,13 @@ __all__ = [
|
|
|
42
44
|
"compare",
|
|
43
45
|
"expressions",
|
|
44
46
|
"get_backend",
|
|
47
|
+
"get_display_digits",
|
|
45
48
|
"get_singular_tolerance",
|
|
46
49
|
"load_dataset",
|
|
47
50
|
"lrt",
|
|
48
51
|
"model",
|
|
49
52
|
"set_backend",
|
|
53
|
+
"set_display_digits",
|
|
50
54
|
"set_singular_tolerance",
|
|
51
55
|
"show_datasets",
|
|
52
56
|
"viz",
|
{bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/builders/specs.py
RENAMED
|
@@ -145,9 +145,9 @@ def build_model_spec_from_formula(
|
|
|
145
145
|
) -> ModelSpec:
|
|
146
146
|
"""Build ModelSpec by parsing a formula string and resolving defaults.
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
Parses the formula into an AST to extract response variable, fixed terms,
|
|
149
149
|
and random effect terms without requiring data. Validates formula syntax
|
|
150
|
-
|
|
150
|
+
and resolves estimation method from family and RE presence.
|
|
151
151
|
|
|
152
152
|
Args:
|
|
153
153
|
formula: R-style model formula (e.g., ``"y ~ x + (1|group)"``).
|
|
@@ -173,67 +173,27 @@ def build_model_spec_from_formula(
|
|
|
173
173
|
if "~" not in formula:
|
|
174
174
|
raise ValueError(f"Invalid formula: {formula!r}. Formula must contain '~'.")
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
response = strip_backticks(lhs.strip())
|
|
178
|
-
|
|
179
|
-
# Handle LHS transforms like rank(y), log(y), zscore(rank(y)) — unwrap all layers
|
|
180
|
-
while True:
|
|
181
|
-
lhs_func_match = re.match(r"^([a-zA-Z_]\w*)\((.+)\)$", response)
|
|
182
|
-
if not lhs_func_match:
|
|
183
|
-
break
|
|
184
|
-
response = strip_backticks(lhs_func_match.group(2).strip())
|
|
185
|
-
|
|
186
|
-
if not response:
|
|
187
|
-
raise ValueError(
|
|
188
|
-
f"Invalid formula: {formula!r}. No response variable specified."
|
|
189
|
-
)
|
|
190
|
-
|
|
191
|
-
# Expand || and / syntax before validation (these are valid lme4 syntax
|
|
192
|
-
# that the Scanner/Parser doesn't handle directly)
|
|
193
|
-
from bossanova.internal.operations.formula.parse import (
|
|
194
|
-
expand_double_verts,
|
|
195
|
-
expand_nested_syntax,
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
expanded, _ = expand_double_verts(formula)
|
|
199
|
-
expanded, _ = expand_nested_syntax(expanded)
|
|
200
|
-
|
|
201
|
-
# Validate expanded formula syntax via the real parser
|
|
202
|
-
from bossanova.internal.operations.formula.parser import Parser, Scanner
|
|
176
|
+
from bossanova.internal.operations.formula.parse import extract_formula_structure
|
|
203
177
|
|
|
204
178
|
try:
|
|
205
|
-
|
|
206
|
-
Parser(tokens).parse()
|
|
179
|
+
structure = extract_formula_structure(formula)
|
|
207
180
|
except Exception as exc:
|
|
208
181
|
raise ValueError(f"Invalid formula: {formula!r}. {exc}") from exc
|
|
209
182
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
re_pattern = r"\([^)]*\|[^)]*\)"
|
|
215
|
-
random_terms = tuple(re.findall(re_pattern, expanded_rhs))
|
|
216
|
-
has_re = len(random_terms) > 0
|
|
217
|
-
|
|
218
|
-
# Extract fixed terms by removing random effects from RHS
|
|
219
|
-
fixed_rhs = re.sub(re_pattern, "", expanded_rhs)
|
|
220
|
-
raw_terms = [strip_backticks(t.strip()) for t in fixed_rhs.split("+") if t.strip()]
|
|
221
|
-
|
|
222
|
-
# Build fixed terms list (add Intercept unless suppressed with 0 or -1)
|
|
223
|
-
has_intercept = not any(t in ("0", "-1") for t in raw_terms)
|
|
224
|
-
fixed_terms: list[str] = ["Intercept"] if has_intercept else []
|
|
225
|
-
fixed_terms.extend(t for t in raw_terms if t not in ("0", "-1", "1"))
|
|
226
|
-
fixed_terms_tuple = tuple(fixed_terms) if fixed_terms else ("Intercept",)
|
|
183
|
+
if structure.response_var is None:
|
|
184
|
+
raise ValueError(
|
|
185
|
+
f"Invalid formula: {formula!r}. No response variable specified."
|
|
186
|
+
)
|
|
227
187
|
|
|
228
188
|
return build_model_spec(
|
|
229
189
|
formula=formula,
|
|
230
190
|
family=family,
|
|
231
191
|
link=link,
|
|
232
192
|
method=method,
|
|
233
|
-
has_random_effects=
|
|
234
|
-
response_var=
|
|
235
|
-
fixed_terms=
|
|
236
|
-
random_terms=
|
|
193
|
+
has_random_effects=structure.has_random_effects,
|
|
194
|
+
response_var=strip_backticks(structure.response_var),
|
|
195
|
+
fixed_terms=structure.fixed_term_names,
|
|
196
|
+
random_terms=structure.random_terms_raw,
|
|
237
197
|
)
|
|
238
198
|
|
|
239
199
|
|
{bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/builders/state.py
RENAMED
|
@@ -222,7 +222,8 @@ def build_mee_state(
|
|
|
222
222
|
L_matrix: Design matrix for delta method inference (optional).
|
|
223
223
|
Shape (n_estimates, n_coef). For EMMs this is X_ref.
|
|
224
224
|
contrast_method: Original contrast type for multiplicity adjustment
|
|
225
|
-
("pairwise", "
|
|
225
|
+
("pairwise", "sequential", "poly", "treatment", "sum",
|
|
226
|
+
"helmert", or None).
|
|
226
227
|
n_contrast_levels: Number of EMM levels before contrasting (family size).
|
|
227
228
|
link: Link function name for response-scale CI back-transformation.
|
|
228
229
|
L_matrix_link: Link-scale L_matrix for CI back-transformation.
|
|
@@ -34,6 +34,7 @@ __all__ = [
|
|
|
34
34
|
"ParamsBoot",
|
|
35
35
|
"ParamsCv",
|
|
36
36
|
"ParamsPerm",
|
|
37
|
+
"PowerSummaryCols",
|
|
37
38
|
"PredictionsAsymp",
|
|
38
39
|
"PredictionsBase",
|
|
39
40
|
"PredictionsCv",
|
|
@@ -164,6 +165,20 @@ class Col:
|
|
|
164
165
|
SIM_MEAN: str = "sim_mean"
|
|
165
166
|
SIM_SD: str = "sim_sd"
|
|
166
167
|
|
|
168
|
+
# -- Power analysis --
|
|
169
|
+
POWER: str = "power"
|
|
170
|
+
POWER_CI_LOWER: str = "power_ci_lower"
|
|
171
|
+
POWER_CI_UPPER: str = "power_ci_upper"
|
|
172
|
+
TRUE_VALUE: str = "true_value"
|
|
173
|
+
COVERAGE: str = "coverage"
|
|
174
|
+
BIAS: str = "bias"
|
|
175
|
+
RMSE: str = "rmse"
|
|
176
|
+
MEAN_SE: str = "mean_se"
|
|
177
|
+
EMPIRICAL_SE: str = "empirical_se"
|
|
178
|
+
N_SIMS: str = "n_sims"
|
|
179
|
+
N_FAILED: str = "n_failed"
|
|
180
|
+
N: str = "n"
|
|
181
|
+
|
|
167
182
|
# -- CV diagnostics --
|
|
168
183
|
CV_RMSE: str = "cv_rmse"
|
|
169
184
|
CV_MAE: str = "cv_mae"
|
|
@@ -277,6 +292,27 @@ AugmentedDataCols = (Col.FITTED, Col.RESID, Col.HAT, Col.STD_RESID, Col.COOKSD)
|
|
|
277
292
|
SimulationsInferCols = (Col.SIM_MEAN, Col.SIM_SD, "sim_q025", "sim_q975")
|
|
278
293
|
|
|
279
294
|
|
|
295
|
+
# =============================================================================
|
|
296
|
+
# Power analysis columns (rows = grid points × terms)
|
|
297
|
+
# =============================================================================
|
|
298
|
+
|
|
299
|
+
# Note: Grid columns (n, sigma, coef values) are dynamic — only metric columns are fixed
|
|
300
|
+
PowerSummaryCols = (
|
|
301
|
+
Col.TERM,
|
|
302
|
+
Col.TRUE_VALUE,
|
|
303
|
+
Col.POWER,
|
|
304
|
+
Col.POWER_CI_LOWER,
|
|
305
|
+
Col.POWER_CI_UPPER,
|
|
306
|
+
Col.COVERAGE,
|
|
307
|
+
Col.BIAS,
|
|
308
|
+
Col.RMSE,
|
|
309
|
+
Col.MEAN_SE,
|
|
310
|
+
Col.EMPIRICAL_SE,
|
|
311
|
+
Col.N_SIMS,
|
|
312
|
+
Col.N_FAILED,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
|
|
280
316
|
# =============================================================================
|
|
281
317
|
# .effects Schemas (rows = grid points for EMM/marginal effects)
|
|
282
318
|
# =============================================================================
|
{bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/structs/data.py
RENAMED
|
@@ -196,6 +196,9 @@ class DataBundle:
|
|
|
196
196
|
# Random effects metadata
|
|
197
197
|
re_metadata: REMetadata | None = field(default=None)
|
|
198
198
|
|
|
199
|
+
# Binary response level mapping (e.g. ("No", "Yes") means No→0, Yes→1)
|
|
200
|
+
response_levels: tuple[str, ...] | None = field(default=None)
|
|
201
|
+
|
|
199
202
|
# Rank deficiency info (None means full rank or not yet checked)
|
|
200
203
|
rank_info: RankInfo | None = field(default=None)
|
|
201
204
|
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"""Parsing result containers for explore formulas."""
|
|
2
|
+
|
|
3
|
+
from attrs import field, frozen, validators
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"Condition",
|
|
7
|
+
"ContrastExpr",
|
|
8
|
+
"ContrastItem",
|
|
9
|
+
"ContrastOperand",
|
|
10
|
+
"ExploreFormula",
|
|
11
|
+
"ExploreFormulaError",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# =====================================================================
|
|
16
|
+
# Bracket contrast expression containers
|
|
17
|
+
# =====================================================================
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@frozen
|
|
21
|
+
class ContrastOperand:
|
|
22
|
+
"""One side of a bracket contrast item.
|
|
23
|
+
|
|
24
|
+
Represents a single operand in a contrast like ``A - B`` or
|
|
25
|
+
``(A + B) - C``.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
levels: Level names for this operand. Empty tuple for wildcard.
|
|
29
|
+
Multiple levels indicate a grouped mean (e.g., ``(A + B)``
|
|
30
|
+
produces ``levels=("A", "B")``).
|
|
31
|
+
is_wildcard: True for the ``*`` operator, which expands to all
|
|
32
|
+
levels not mentioned on the other side.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
levels: tuple[str, ...] = field(factory=tuple, converter=tuple)
|
|
36
|
+
is_wildcard: bool = field(default=False, validator=validators.instance_of(bool))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@frozen
|
|
40
|
+
class ContrastItem:
|
|
41
|
+
"""A single contrast: left operand minus right operand.
|
|
42
|
+
|
|
43
|
+
Represents one ``left - right`` comparison in a bracket contrast
|
|
44
|
+
expression like ``Drug[Active - Placebo]``.
|
|
45
|
+
|
|
46
|
+
Attributes:
|
|
47
|
+
left: Left operand (positive side).
|
|
48
|
+
right: Right operand (negative side).
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
left: ContrastOperand = field(validator=validators.instance_of(ContrastOperand))
|
|
52
|
+
right: ContrastOperand = field(validator=validators.instance_of(ContrastOperand))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@frozen
|
|
56
|
+
class ContrastExpr:
|
|
57
|
+
"""Bracket contrast expression: ``Drug[A - B, C - D]``.
|
|
58
|
+
|
|
59
|
+
Represents a complete bracket contrast specification parsed from
|
|
60
|
+
explore formula syntax.
|
|
61
|
+
|
|
62
|
+
Attributes:
|
|
63
|
+
var: Variable name (e.g., ``"Drug"``).
|
|
64
|
+
items: Tuple of contrast items to compute.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
var: str = field(validator=validators.instance_of(str))
|
|
68
|
+
items: tuple[ContrastItem, ...] = field(converter=tuple)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@frozen
|
|
72
|
+
class Condition:
|
|
73
|
+
"""A conditioning specification in explore formula.
|
|
74
|
+
|
|
75
|
+
Represents a variable to condition on, optionally with specific values,
|
|
76
|
+
a method for generating values, or a bracket contrast expression.
|
|
77
|
+
|
|
78
|
+
Attributes:
|
|
79
|
+
var: Variable name to condition on.
|
|
80
|
+
at_values: Specific values to evaluate at (e.g., (50.0,) or ("A", "B")).
|
|
81
|
+
at_range: Number of evenly-spaced values across the variable's range.
|
|
82
|
+
at_quantile: Number of quantile values to use.
|
|
83
|
+
contrast_expr: Bracket contrast expression on this condition variable
|
|
84
|
+
(e.g., from ``Dose[High - Low]`` on the RHS). When set, the
|
|
85
|
+
variable is treated as a grid categorical during condition
|
|
86
|
+
resolution, and the contrast is applied as a post-processing step.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
var: str = field(validator=validators.instance_of(str))
|
|
90
|
+
at_values: tuple | None = field(default=None)
|
|
91
|
+
at_range: int | None = field(default=None)
|
|
92
|
+
at_quantile: int | None = field(default=None)
|
|
93
|
+
contrast_expr: ContrastExpr | None = field(default=None)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@frozen
|
|
97
|
+
class ExploreFormula:
|
|
98
|
+
"""Parsed explore formula.
|
|
99
|
+
|
|
100
|
+
Represents a parsed explore formula with focal variable, optional contrast
|
|
101
|
+
type, and conditioning specifications.
|
|
102
|
+
|
|
103
|
+
Attributes:
|
|
104
|
+
focal_var: The variable to compute marginal effects for.
|
|
105
|
+
contrast_type: Type of contrast (pairwise, sequential, poly, treatment,
|
|
106
|
+
sum, helmert, custom) or None for simple EMMs. Set to ``"custom"``
|
|
107
|
+
for bracket contrast expressions.
|
|
108
|
+
contrast_degree: Degree parameter for polynomial contrasts (default None
|
|
109
|
+
means use n_levels - 1, i.e., maximum degree).
|
|
110
|
+
contrast_ref: Reference level for treatment/dummy contrasts
|
|
111
|
+
(e.g., ``"Placebo"`` from ``treatment(Drug, ref=Placebo)``).
|
|
112
|
+
contrast_expr: Bracket contrast expression AST (e.g., from
|
|
113
|
+
``Drug[Active - Placebo]`` syntax). None for named contrast
|
|
114
|
+
functions or simple EMMs.
|
|
115
|
+
conditions: Tuple of Condition objects specifying conditioning variables.
|
|
116
|
+
focal_at_values: Specific values to evaluate the focal variable at
|
|
117
|
+
(e.g., from ``Days@[0, 3, 6, 9]`` syntax). None means use all levels.
|
|
118
|
+
focal_at_range: Number of evenly-spaced values across the focal variable's
|
|
119
|
+
range (e.g., from ``Days@range(5)`` syntax). None means not set.
|
|
120
|
+
focal_at_quantile: Number of quantile values for the focal variable
|
|
121
|
+
(e.g., from ``Days@quantile(3)`` syntax). None means not set.
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
focal_var: str = field(validator=validators.instance_of(str))
|
|
125
|
+
contrast_type: str | None = field(default=None)
|
|
126
|
+
contrast_degree: int | None = field(default=None)
|
|
127
|
+
contrast_ref: str | None = field(default=None)
|
|
128
|
+
contrast_expr: ContrastExpr | None = field(default=None)
|
|
129
|
+
conditions: tuple[Condition, ...] = field(factory=tuple, converter=tuple)
|
|
130
|
+
focal_at_values: tuple[float | str, ...] | None = field(default=None)
|
|
131
|
+
focal_at_range: int | None = field(default=None)
|
|
132
|
+
focal_at_quantile: int | None = field(default=None)
|
|
133
|
+
|
|
134
|
+
def __attrs_post_init__(self) -> None:
|
|
135
|
+
"""Validate at most one focal at-spec is set."""
|
|
136
|
+
n_set = sum(
|
|
137
|
+
x is not None
|
|
138
|
+
for x in (self.focal_at_values, self.focal_at_range, self.focal_at_quantile)
|
|
139
|
+
)
|
|
140
|
+
if n_set > 1:
|
|
141
|
+
raise ValueError(
|
|
142
|
+
"At most one of focal_at_values, focal_at_range, focal_at_quantile "
|
|
143
|
+
"may be set."
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
@property
|
|
147
|
+
def has_focal_at(self) -> bool:
|
|
148
|
+
"""Return True if any focal at-spec is set."""
|
|
149
|
+
return (
|
|
150
|
+
self.focal_at_values is not None
|
|
151
|
+
or self.focal_at_range is not None
|
|
152
|
+
or self.focal_at_quantile is not None
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def has_contrast(self) -> bool:
|
|
157
|
+
"""Return True if any contrast is specified (named function or bracket expr)."""
|
|
158
|
+
return self.contrast_type is not None or self.contrast_expr is not None
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def has_contrast_expr(self) -> bool:
|
|
162
|
+
"""Return True if a bracket contrast expression is specified."""
|
|
163
|
+
return self.contrast_expr is not None
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def has_conditions(self) -> bool:
|
|
167
|
+
"""Return True if conditioning variables are specified."""
|
|
168
|
+
return len(self.conditions) > 0
|
|
169
|
+
|
|
170
|
+
@property
|
|
171
|
+
def has_rhs_contrasts(self) -> bool:
|
|
172
|
+
"""Return True if any RHS condition has a bracket contrast expression."""
|
|
173
|
+
return any(c.contrast_expr is not None for c in self.conditions)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class ExploreFormulaError(ValueError):
|
|
177
|
+
"""Error in explore formula syntax.
|
|
178
|
+
|
|
179
|
+
Provides helpful error messages with position indicators for syntax errors.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
message: Error description.
|
|
183
|
+
formula: The formula that caused the error.
|
|
184
|
+
position: Character position of the error (optional).
|
|
185
|
+
"""
|
|
186
|
+
|
|
187
|
+
def __init__(
|
|
188
|
+
self,
|
|
189
|
+
message: str,
|
|
190
|
+
formula: str,
|
|
191
|
+
position: int | None = None,
|
|
192
|
+
) -> None:
|
|
193
|
+
"""Initialize ExploreFormulaError.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
message: Error description.
|
|
197
|
+
formula: The formula that caused the error.
|
|
198
|
+
position: Character position of the error.
|
|
199
|
+
"""
|
|
200
|
+
self.formula = formula
|
|
201
|
+
self.position = position
|
|
202
|
+
if position is not None:
|
|
203
|
+
pointer = " " * position + "^"
|
|
204
|
+
message = f"{message}\n {formula}\n {pointer}"
|
|
205
|
+
super().__init__(message)
|
{bossanova-0.1.0.dev13 → bossanova-0.1.0.dev15}/bossanova/internal/containers/structs/state.py
RENAMED
|
@@ -219,13 +219,18 @@ class MeeState:
|
|
|
219
219
|
explore_formula: The explore formula string that generated this result.
|
|
220
220
|
focal_var: The primary variable being explored.
|
|
221
221
|
type: Type of marginal effect ("means", "slopes", "contrasts").
|
|
222
|
+
weights: Averaging philosophy used: ``"equal"`` (balanced reference grid,
|
|
223
|
+
emmeans-style) or ``"observed"`` (g-computation over observed data).
|
|
222
224
|
L_matrix: Design matrix for delta method inference. Shape (n_estimates, n_coef).
|
|
223
225
|
For EMMs, this is X_ref; for slopes, a coefficient selector row.
|
|
224
226
|
contrast_method: Original contrast type for multiplicity adjustment
|
|
225
|
-
("pairwise", "
|
|
227
|
+
("pairwise", "sequential", "poly", "treatment", "sum",
|
|
228
|
+
"helmert", or None).
|
|
226
229
|
n_contrast_levels: Number of EMM levels before contrasting (family size for Tukey).
|
|
227
|
-
link: Link function name for response-scale back-transformation (set when units="data"
|
|
228
|
-
|
|
230
|
+
link: Link function name for response-scale back-transformation (set when units="data"
|
|
231
|
+
and weights="equal").
|
|
232
|
+
L_matrix_link: Link-scale L_matrix for CI back-transformation (set when units="data"
|
|
233
|
+
and weights="equal").
|
|
229
234
|
inference_method: Inference method used (``"asymp"``, ``"boot"``,
|
|
230
235
|
``"perm"``, or ``None``). Controls which columns appear in
|
|
231
236
|
the ``.effects`` DataFrame.
|
|
@@ -253,6 +258,7 @@ class MeeState:
|
|
|
253
258
|
focal_var: str = field(validator=validators.instance_of(str))
|
|
254
259
|
type: str = field(validator=validators.in_(("means", "slopes", "contrasts")))
|
|
255
260
|
units: str = field(default="link", validator=validators.in_(("link", "data")))
|
|
261
|
+
weights: str = field(default="equal", validator=validators.in_(("equal", "observed")))
|
|
256
262
|
|
|
257
263
|
# Design matrix for delta method inference (optional)
|
|
258
264
|
# Shape: (n_estimates, n_coef). For EMMs, this is X_ref; for slopes, a selector row.
|
|
@@ -264,7 +270,17 @@ class MeeState:
|
|
|
264
270
|
contrast_method: str | None = field(
|
|
265
271
|
default=None,
|
|
266
272
|
validator=validators.optional(
|
|
267
|
-
validators.in_(
|
|
273
|
+
validators.in_(
|
|
274
|
+
(
|
|
275
|
+
"pairwise",
|
|
276
|
+
"sequential",
|
|
277
|
+
"poly",
|
|
278
|
+
"treatment",
|
|
279
|
+
"sum",
|
|
280
|
+
"helmert",
|
|
281
|
+
"custom",
|
|
282
|
+
)
|
|
283
|
+
)
|
|
268
284
|
),
|
|
269
285
|
)
|
|
270
286
|
n_contrast_levels: int | None = field(default=None)
|
|
@@ -28,6 +28,7 @@ from bossanova.internal.maths.batching import (
|
|
|
28
28
|
get_available_memory_gb,
|
|
29
29
|
)
|
|
30
30
|
from bossanova.internal.maths.config import is_singular
|
|
31
|
+
from bossanova.internal.maths.rounding import round_float_columns, round_sigfigs
|
|
31
32
|
from bossanova.internal.maths.inference import (
|
|
32
33
|
Chi2TestResult,
|
|
33
34
|
FTestResult,
|
|
@@ -240,6 +241,8 @@ __all__ = [
|
|
|
240
241
|
"poly_numeric",
|
|
241
242
|
"poly_numeric_labels",
|
|
242
243
|
"qr_solve",
|
|
244
|
+
"round_float_columns",
|
|
245
|
+
"round_sigfigs",
|
|
243
246
|
"sequential_contrast",
|
|
244
247
|
"sequential_labels",
|
|
245
248
|
"sum_contrast",
|
|
@@ -12,15 +12,71 @@ if TYPE_CHECKING:
|
|
|
12
12
|
import numpy as np
|
|
13
13
|
|
|
14
14
|
__all__ = [
|
|
15
|
+
"get_display_digits",
|
|
15
16
|
"get_singular_tolerance",
|
|
16
17
|
"is_singular",
|
|
18
|
+
"set_display_digits",
|
|
17
19
|
"set_singular_tolerance",
|
|
18
20
|
]
|
|
19
21
|
|
|
22
|
+
# Default significant figures for DataFrame display output.
|
|
23
|
+
# Matches R's summary() convention of 4 significant digits.
|
|
24
|
+
_DISPLAY_DIGITS: int = 4
|
|
25
|
+
|
|
20
26
|
# Default singular tolerance matches lme4's default (utilities.R:924-928)
|
|
21
27
|
_SINGULAR_TOLERANCE: float = 1e-4
|
|
22
28
|
|
|
23
29
|
|
|
30
|
+
def get_display_digits() -> int:
|
|
31
|
+
"""Get the number of significant figures for DataFrame display output.
|
|
32
|
+
|
|
33
|
+
Controls how many significant figures are shown in user-facing
|
|
34
|
+
DataFrames returned by model properties (``.params``, ``.effects``,
|
|
35
|
+
``.diagnostics``, etc.) and ``compare()``. Matches R's ``signif()``
|
|
36
|
+
convention.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Current display digits setting (default 4).
|
|
40
|
+
|
|
41
|
+
Examples:
|
|
42
|
+
```python
|
|
43
|
+
from bossanova import get_display_digits
|
|
44
|
+
get_display_digits()
|
|
45
|
+
# 4
|
|
46
|
+
```
|
|
47
|
+
"""
|
|
48
|
+
return _DISPLAY_DIGITS
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def set_display_digits(digits: int) -> None:
|
|
52
|
+
"""Set the number of significant figures for DataFrame display output.
|
|
53
|
+
|
|
54
|
+
Controls how many significant figures are shown in user-facing
|
|
55
|
+
DataFrames returned by model properties (``.params``, ``.effects``,
|
|
56
|
+
``.diagnostics``, etc.) and ``compare()``. Matches R's ``signif()``
|
|
57
|
+
convention.
|
|
58
|
+
|
|
59
|
+
The ``summary()`` method has its own ``digits`` parameter and is
|
|
60
|
+
unaffected by this setting.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
digits: Number of significant figures. Must be >= 1.
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
ValueError: If digits is less than 1.
|
|
67
|
+
|
|
68
|
+
Examples:
|
|
69
|
+
```python
|
|
70
|
+
from bossanova import set_display_digits
|
|
71
|
+
set_display_digits(6) # Show 6 significant figures
|
|
72
|
+
```
|
|
73
|
+
"""
|
|
74
|
+
global _DISPLAY_DIGITS
|
|
75
|
+
if digits < 1:
|
|
76
|
+
raise ValueError(f"digits must be >= 1, got {digits}")
|
|
77
|
+
_DISPLAY_DIGITS = digits
|
|
78
|
+
|
|
79
|
+
|
|
24
80
|
def get_singular_tolerance() -> float:
|
|
25
81
|
"""Get the current singular tolerance for mixed models.
|
|
26
82
|
|