bossanova 0.1.0.dev10__tar.gz → 0.1.0.dev12__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.
Files changed (237) hide show
  1. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/.gitignore +2 -1
  2. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/PKG-INFO +1 -1
  3. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/__init__.py +2 -1
  4. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/__init__.py +6 -0
  5. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/builders/__init__.py +10 -2
  6. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/builders/dataframes.py +53 -14
  7. bossanova-0.1.0.dev12/bossanova/internal/containers/builders/resamples.py +226 -0
  8. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/builders/results.py +29 -6
  9. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/builders/state.py +14 -121
  10. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/schemas.py +30 -32
  11. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/structs/data.py +4 -4
  12. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/structs/display.py +9 -9
  13. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/structs/explore.py +3 -3
  14. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/structs/formula.py +2 -2
  15. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/structs/specs.py +2 -2
  16. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/structs/state.py +59 -21
  17. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/__init__.py +0 -4
  18. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/backend/dispatch.py +2 -6
  19. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/backend/jax.py +3 -6
  20. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/design/coding.py +1 -1
  21. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/design/reference.py +40 -8
  22. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/__init__.py +2 -1
  23. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/schema.py +7 -0
  24. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/__init__.py +12 -4
  25. bossanova-0.1.0.dev12/bossanova/internal/maths/inference/multiplicity.py +101 -0
  26. bossanova-0.1.0.dev12/bossanova/internal/maths/inference/sandwich.py +291 -0
  27. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/welch.py +70 -120
  28. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/linalg/__init__.py +4 -0
  29. bossanova-0.1.0.dev12/bossanova/internal/maths/linalg/schur.py +97 -0
  30. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/__init__.py +0 -2
  31. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/glm.py +2 -81
  32. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/lmer.py +0 -146
  33. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/__init__.py +6 -6
  34. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/common/__init__.py +4 -2
  35. bossanova-0.1.0.dev12/bossanova/internal/operations/common/data_utils.py +36 -0
  36. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/common/formula_utils.py +48 -0
  37. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/compare/helpers.py +4 -6
  38. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/diagnostics.py +2 -2
  39. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/fit/__init__.py +2 -4
  40. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/fit/dispatch.py +27 -0
  41. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/fit/glmer.py +13 -57
  42. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/fit/lmer.py +2 -52
  43. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/__init__.py +8 -0
  44. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/asymptotic.py +70 -94
  45. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/bootstrap.py +185 -3
  46. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/cv.py +265 -52
  47. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/mee.py +37 -11
  48. bossanova-0.1.0.dev12/bossanova/internal/operations/infer/params.py +160 -0
  49. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/permutation.py +15 -16
  50. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/profile.py +4 -2
  51. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/resample_bundle.py +5 -2
  52. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/__init__.py +12 -0
  53. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/compute.py +413 -74
  54. bossanova-0.1.0.dev12/bossanova/internal/operations/marginal/conditions.py +193 -0
  55. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/contrasts.py +190 -13
  56. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/emm.py +44 -1
  57. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/inference.py +212 -28
  58. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/joint_tests.py +154 -10
  59. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/slopes.py +189 -7
  60. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/core.py +2 -3
  61. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/glmer.py +3 -3
  62. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/core_data.py +100 -90
  63. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/design.py +20 -11
  64. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/mem.py +1 -4
  65. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/params.py +2 -1
  66. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/model/core.py +217 -500
  67. bossanova-0.1.0.dev12/bossanova/model/guards.py +201 -0
  68. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/model/summary.py +4 -2
  69. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/pyproject.toml +39 -32
  70. bossanova-0.1.0.dev10/bossanova/internal/maths/inference/sandwich.py +0 -115
  71. bossanova-0.1.0.dev10/bossanova/internal/operations/common/classify.py +0 -20
  72. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/LICENSE +0 -0
  73. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/README.md +0 -0
  74. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/README.md +0 -0
  75. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/__init__.py +0 -0
  76. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/advertising.csv +0 -0
  77. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/cake.csv +0 -0
  78. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/chickweight.csv +0 -0
  79. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/credit.csv +0 -0
  80. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/gammas.csv +0 -0
  81. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/mtcars.csv +0 -0
  82. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/penguins.csv +0 -0
  83. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/poker.csv +0 -0
  84. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/sleep.csv +0 -0
  85. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/titanic.csv +0 -0
  86. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/titanic_test.csv +0 -0
  87. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/data/titanic_train.csv +0 -0
  88. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/distributions/__init__.py +0 -0
  89. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/distributions/continuous.py +0 -0
  90. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/distributions/discrete.py +0 -0
  91. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/distributions/varying.py +0 -0
  92. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/expressions.py +0 -0
  93. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/__init__.py +0 -0
  94. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/builders/data.py +0 -0
  95. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/builders/specs.py +0 -0
  96. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/structs/__init__.py +0 -0
  97. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/containers/validators.py +0 -0
  98. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/backend/__init__.py +0 -0
  99. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/backend/numpy.py +0 -0
  100. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/backend/protocol.py +0 -0
  101. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/batching.py +0 -0
  102. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/config.py +0 -0
  103. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/convergence.py +0 -0
  104. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/design/__init__.py +0 -0
  105. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/design/names.py +0 -0
  106. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/design/z_matrix.py +0 -0
  107. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/differentiation.py +0 -0
  108. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/distributions/__init__.py +0 -0
  109. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/distributions/algebra.py +0 -0
  110. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/distributions/base.py +0 -0
  111. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/distributions/core.py +0 -0
  112. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/distributions/derived.py +0 -0
  113. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/distributions/factories.py +0 -0
  114. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/distributions/plotting.py +0 -0
  115. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/distributions/probability.py +0 -0
  116. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/binomial.py +0 -0
  117. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/create.py +0 -0
  118. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/gamma.py +0 -0
  119. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/gaussian.py +0 -0
  120. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/links.py +0 -0
  121. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/poisson.py +0 -0
  122. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/response.py +0 -0
  123. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/family/tdist.py +0 -0
  124. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/contrasts.py +0 -0
  125. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/diagnostics.py +0 -0
  126. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/estimation.py +0 -0
  127. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/hypothesis.py +0 -0
  128. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/information_criteria.py +0 -0
  129. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/profile.py +0 -0
  130. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/satterthwaite.py +0 -0
  131. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/inference/wald_variance.py +0 -0
  132. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/linalg/qr.py +0 -0
  133. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/linalg/sparse.py +0 -0
  134. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/linalg/svd.py +0 -0
  135. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/predict.py +0 -0
  136. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/rng.py +0 -0
  137. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/glmer.py +0 -0
  138. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/heuristics.py +0 -0
  139. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/initialization.py +0 -0
  140. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/lambda_builder.py +0 -0
  141. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/lambda_sparse.py +0 -0
  142. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/lambda_template.py +0 -0
  143. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/optimize.py +0 -0
  144. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/pirls_sparse.py +0 -0
  145. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/solvers/quadrature.py +0 -0
  146. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/tolerances.py +0 -0
  147. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/transforms.py +0 -0
  148. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/variance.py +0 -0
  149. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/maths/weights.py +0 -0
  150. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/bundle.py +0 -0
  151. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/common/factors.py +0 -0
  152. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/compare/__init__.py +0 -0
  153. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/compare/compare.py +0 -0
  154. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/compare/cv.py +0 -0
  155. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/compare/deviance.py +0 -0
  156. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/compare/f_test.py +0 -0
  157. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/compare/lrt.py +0 -0
  158. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/compare/lrt_compare.py +0 -0
  159. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/compare/refit.py +0 -0
  160. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/contrasts.py +0 -0
  161. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/convergence.py +0 -0
  162. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/fit/glm.py +0 -0
  163. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/fit/ols.py +0 -0
  164. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/fit/rank.py +0 -0
  165. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/__init__.py +0 -0
  166. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/design.py +0 -0
  167. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/encoding.py +0 -0
  168. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/evaluate.py +0 -0
  169. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/evaluate_newdata.py +0 -0
  170. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/evaluate_transforms.py +0 -0
  171. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/helpers.py +0 -0
  172. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/parse.py +0 -0
  173. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/parser/__init__.py +0 -0
  174. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/parser/expr.py +0 -0
  175. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/parser/parser.py +0 -0
  176. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/parser/scanner.py +0 -0
  177. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/parser/token.py +0 -0
  178. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/formula/random_effects.py +0 -0
  179. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/prediction.py +0 -0
  180. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/satterthwaite_emm.py +0 -0
  181. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/infer/simulation.py +0 -0
  182. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/explore.py +0 -0
  183. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/grid.py +0 -0
  184. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/marginal/validation.py +0 -0
  185. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/predict.py +0 -0
  186. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/profile.py +0 -0
  187. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/rendering/__init__.py +0 -0
  188. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/rendering/latex.py +0 -0
  189. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/__init__.py +0 -0
  190. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/common.py +0 -0
  191. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/glm.py +0 -0
  192. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/lm.py +0 -0
  193. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/lm_bca.py +0 -0
  194. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/lm_operators.py +0 -0
  195. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/lmer.py +0 -0
  196. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/mixed.py +0 -0
  197. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/results.py +0 -0
  198. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/resample/utils.py +0 -0
  199. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/__init__.py +0 -0
  200. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/dgp/__init__.py +0 -0
  201. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/dgp/generate.py +0 -0
  202. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/dgp/glm.py +0 -0
  203. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/dgp/glmer.py +0 -0
  204. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/dgp/lm.py +0 -0
  205. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/dgp/lmer.py +0 -0
  206. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/harness.py +0 -0
  207. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/metrics.py +0 -0
  208. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/simulation/model_sim.py +0 -0
  209. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/transforms.py +0 -0
  210. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/operations/varying.py +0 -0
  211. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/README.md +0 -0
  212. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/__init__.py +0 -0
  213. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/cognition.py +0 -0
  214. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/compare.py +0 -0
  215. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/core.py +0 -0
  216. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/core_protocols.py +0 -0
  217. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/core_sizing.py +0 -0
  218. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/core_viz.py +0 -0
  219. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/dag.py +0 -0
  220. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/fit.py +0 -0
  221. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/fit_builders.py +0 -0
  222. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/fit_layers.py +0 -0
  223. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/helpers.py +0 -0
  224. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/lattice.py +0 -0
  225. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/layout.py +0 -0
  226. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/predict.py +0 -0
  227. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/profile.py +0 -0
  228. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/ranef.py +0 -0
  229. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/relationships.py +0 -0
  230. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/resamples.py +0 -0
  231. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/resid.py +0 -0
  232. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/internal/viz/vif.py +0 -0
  233. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/model/__init__.py +0 -0
  234. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/bossanova/py.typed +0 -0
  235. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/tests/bossanova_benchmarks/bootstrap/data/README.md +0 -0
  236. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/tests/bossanova_benchmarks/insteval/data/README.md +0 -0
  237. {bossanova-0.1.0.dev10 → bossanova-0.1.0.dev12}/tests/bossanova_tests/hypothesis/README.md +0 -0
@@ -17,7 +17,7 @@ docs/_build/
17
17
  docs/performance/
18
18
  profile_*.py
19
19
  benchmarks/
20
- !bossanova-docs/reference/benchmarks/
20
+ !bossanova-docs/engineering/benchmarks/
21
21
  examples/
22
22
  papers/
23
23
  paper-summaries/
@@ -64,6 +64,7 @@ dist/
64
64
 
65
65
  # Logs
66
66
  *.log
67
+ logs/
67
68
 
68
69
  # Refs
69
70
  MixedModels.jl/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bossanova
3
- Version: 0.1.0.dev10
3
+ Version: 0.1.0.dev12
4
4
  Summary: Bridging statistical cultures with some jazz
5
5
  Author: Eshin Jolly
6
6
  License-Expression: MIT
@@ -1,10 +1,11 @@
1
1
  # Backend API (must be imported first, before any JAX usage)
2
2
  from bossanova.internal.maths.backend import backend, get_backend, set_backend
3
3
 
4
- # Configure JAX x64 eagerly if JAX is available
4
+ # Configure JAX x64 eagerly if JAX is available — SINGLE AUTHORITATIVE LOCATION.
5
5
  # This MUST happen before any JAX arrays are created anywhere in the codebase.
6
6
  # We cannot defer this to lazy loading because submodules (e.g., lmer_core.py)
7
7
  # import JAX at module level and would create float32 arrays otherwise.
8
+ # All other modules rely on this having run at import time.
8
9
  try:
9
10
  import jax
10
11
 
@@ -67,8 +67,11 @@ from bossanova.internal.containers.builders import (
67
67
  build_params_dataframe,
68
68
  build_prediction_state,
69
69
  build_predictions_dataframe,
70
+ build_mee_resamples,
71
+ build_params_resamples,
70
72
  build_resamples_dataframe,
71
73
  build_resamples_state,
74
+ extract_mee_names,
72
75
  build_simulation_inference_state,
73
76
  build_simulation_spec,
74
77
  build_simulation_spec_from_formula,
@@ -117,10 +120,12 @@ __all__ = [
117
120
  "build_inference_state",
118
121
  "build_joint_test_dataframe",
119
122
  "build_joint_test_state",
123
+ "build_mee_resamples",
120
124
  "build_mee_state",
121
125
  "build_model_spec",
122
126
  "build_model_spec_from_formula",
123
127
  "build_params_dataframe",
128
+ "build_params_resamples",
124
129
  "build_prediction_state",
125
130
  "build_predictions_dataframe",
126
131
  "build_resamples_dataframe",
@@ -136,5 +141,6 @@ __all__ = [
136
141
  "build_varying_spread_dataframe",
137
142
  "build_varying_spread_state",
138
143
  "build_varying_state",
144
+ "extract_mee_names",
139
145
  "get_varying_random_terms",
140
146
  ]
@@ -26,6 +26,13 @@ from bossanova.internal.containers.builders.specs import (
26
26
  build_varying_spec,
27
27
  get_varying_random_terms,
28
28
  )
29
+ from bossanova.internal.containers.builders.resamples import (
30
+ build_mee_resamples,
31
+ build_params_resamples,
32
+ build_resamples_dataframe,
33
+ build_resamples_state,
34
+ extract_mee_names,
35
+ )
29
36
  from bossanova.internal.containers.builders.state import (
30
37
  build_cv_state,
31
38
  build_fit_state,
@@ -33,8 +40,6 @@ from bossanova.internal.containers.builders.state import (
33
40
  build_joint_test_state,
34
41
  build_mee_state,
35
42
  build_prediction_state,
36
- build_resamples_dataframe,
37
- build_resamples_state,
38
43
  build_simulation_inference_state,
39
44
  build_varying_spread_state,
40
45
  build_varying_state,
@@ -48,10 +53,12 @@ __all__ = [
48
53
  "build_inference_state",
49
54
  "build_joint_test_dataframe",
50
55
  "build_joint_test_state",
56
+ "build_mee_resamples",
51
57
  "build_mee_state",
52
58
  "build_model_spec",
53
59
  "build_model_spec_from_formula",
54
60
  "build_params_dataframe",
61
+ "build_params_resamples",
55
62
  "build_prediction_state",
56
63
  "build_predictions_dataframe",
57
64
  "build_resamples_dataframe",
@@ -67,5 +74,6 @@ __all__ = [
67
74
  "build_varying_spread_dataframe",
68
75
  "build_varying_spread_state",
69
76
  "build_varying_state",
77
+ "extract_mee_names",
70
78
  "get_varying_random_terms",
71
79
  ]
@@ -19,7 +19,9 @@ from bossanova.internal.containers.schemas import (
19
19
  Col,
20
20
  ParamsAsymp,
21
21
  ParamsBase,
22
+ ParamsBoot,
22
23
  ParamsCv,
24
+ ParamsPerm,
23
25
  VaryingCorrSchema,
24
26
  )
25
27
 
@@ -56,33 +58,61 @@ def build_params_dataframe(
56
58
  ) -> pl.DataFrame:
57
59
  """Build the ``.params`` DataFrame from fit state.
58
60
 
61
+ Column set varies by inference method:
62
+
63
+ - **asymp**: all inference columns (p_value last).
64
+ - **boot**: no p_value; df = n_resamples.
65
+ - **perm**: no CIs; df = n_valid_resamples.
66
+ - **cv**: PRE columns only.
67
+ - **None**: term + estimate only.
68
+
59
69
  Args:
60
70
  bundle: Data bundle containing ``X_names`` (coefficient labels).
61
71
  fit: Fit state containing ``coef`` (coefficient estimates).
62
72
  params_inference: Optional inference state with SE, CI, p-values.
63
73
 
64
74
  Returns:
65
- DataFrame with ``term``, ``estimate``, and optional inference columns.
75
+ DataFrame with ``term``, ``estimate``, and method-appropriate
76
+ inference columns.
66
77
  """
67
78
  terms = list(bundle.X_names)
68
79
  estimates = fit.coef.tolist()
69
80
 
70
81
  data: dict[str, list] = {Col.TERM: terms, Col.ESTIMATE: estimates}
71
82
 
72
- if params_inference is not None:
73
- if params_inference.method == "cv":
74
- data[Col.PRE] = params_inference.pre.tolist()
75
- data[Col.PRE_SD] = params_inference.pre_sd.tolist()
76
- return pl.DataFrame(data, schema=ParamsCv)
83
+ if params_inference is None:
84
+ return pl.DataFrame(data, schema=ParamsBase)
85
+
86
+ method = params_inference.method
87
+
88
+ if method == "cv":
89
+ data[Col.PRE] = params_inference.pre.tolist()
90
+ data[Col.PRE_SD] = params_inference.pre_sd.tolist()
91
+ return pl.DataFrame(data, schema=ParamsCv)
92
+
93
+ if method == "boot":
94
+ data[Col.SE] = params_inference.se.tolist()
95
+ data[Col.CI_LOWER] = params_inference.ci_lower.tolist()
96
+ data[Col.CI_UPPER] = params_inference.ci_upper.tolist()
97
+ data[Col.STATISTIC] = params_inference.statistic.tolist()
98
+ data[Col.DF] = params_inference.df.tolist()
99
+ return pl.DataFrame(data, schema=ParamsBoot)
100
+
101
+ if method == "perm":
77
102
  data[Col.SE] = params_inference.se.tolist()
78
103
  data[Col.STATISTIC] = params_inference.statistic.tolist()
79
104
  data[Col.DF] = params_inference.df.tolist()
80
105
  data[Col.P_VALUE] = params_inference.p_value.tolist()
81
- data[Col.CI_LOWER] = params_inference.ci_lower.tolist()
82
- data[Col.CI_UPPER] = params_inference.ci_upper.tolist()
83
- return pl.DataFrame(data, schema=ParamsAsymp)
106
+ return pl.DataFrame(data, schema=ParamsPerm)
84
107
 
85
- return pl.DataFrame(data, schema=ParamsBase)
108
+ # Default: asymptotic (or any unknown method)
109
+ data[Col.SE] = params_inference.se.tolist()
110
+ data[Col.CI_LOWER] = params_inference.ci_lower.tolist()
111
+ data[Col.CI_UPPER] = params_inference.ci_upper.tolist()
112
+ data[Col.STATISTIC] = params_inference.statistic.tolist()
113
+ data[Col.DF] = params_inference.df.tolist()
114
+ data[Col.P_VALUE] = params_inference.p_value.tolist()
115
+ return pl.DataFrame(data, schema=ParamsAsymp)
86
116
 
87
117
 
88
118
  def build_varying_offsets_dataframe(
@@ -220,6 +250,7 @@ def build_varying_corr_dataframe(
220
250
  groups.append(group)
221
251
  corrs.append(value)
222
252
 
253
+ # TODO: are we only limited to 2 effects?
223
254
  return pl.DataFrame(
224
255
  {
225
256
  Col.GROUP: groups,
@@ -246,19 +277,27 @@ def _infer_group_from_spread(varying_spread: VaryingSpreadState) -> str:
246
277
  return ""
247
278
 
248
279
 
249
- def build_effects_dataframe(mee: MeeState) -> pl.DataFrame:
280
+ def build_effects_dataframe(
281
+ mee: MeeState,
282
+ method: str | None = None,
283
+ ) -> pl.DataFrame:
250
284
  """Build the ``.effects`` DataFrame from marginal effects state.
251
285
 
286
+ Column set varies by inference method: bootstrap excludes ``p_value``,
287
+ permutation excludes ``ci_lower``/``ci_upper``.
288
+
252
289
  Args:
253
290
  mee: MeeState with grid, estimates, and optional inference.
291
+ method: Inference method (``"asymp"``, ``"boot"``, ``"perm"``,
292
+ or ``None``). Controls which inference columns are included.
254
293
 
255
294
  Returns:
256
- DataFrame with grid columns, ``estimate``, and optional inference
257
- columns.
295
+ DataFrame with grid columns, ``estimate``, and method-appropriate
296
+ inference columns.
258
297
  """
259
298
  result = mee.grid.clone()
260
299
  result = result.with_columns(pl.Series(Col.ESTIMATE, mee.estimate))
261
- return append_inference_columns(result, mee)
300
+ return append_inference_columns(result, mee, method=method)
262
301
 
263
302
 
264
303
  def build_joint_test_dataframe(state: JointTestState) -> pl.DataFrame:
@@ -0,0 +1,226 @@
1
+ """Builder functions for resamples-related containers.
2
+
3
+ Provides constructors for ResamplesState and helpers for building
4
+ resamples from inference results. Moved from state.py to keep modules
5
+ under the 800-line limit.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from typing import TYPE_CHECKING
11
+
12
+ import numpy as np
13
+
14
+ from bossanova.internal.containers.schemas import (
15
+ Col,
16
+ ResamplesRawSchema,
17
+ )
18
+ from bossanova.internal.containers.structs.state import (
19
+ ResamplesState,
20
+ )
21
+
22
+ if TYPE_CHECKING:
23
+ import polars as pl
24
+ from numpy.typing import NDArray
25
+
26
+ from bossanova.internal.containers.structs.state import (
27
+ InferenceState,
28
+ MeeState,
29
+ )
30
+
31
+ __all__ = [
32
+ "build_mee_resamples",
33
+ "build_params_resamples",
34
+ "build_resamples_dataframe",
35
+ "build_resamples_state",
36
+ "extract_mee_names",
37
+ ]
38
+
39
+
40
+ def build_resamples_state(
41
+ *,
42
+ samples: NDArray[np.floating],
43
+ observed: NDArray[np.floating],
44
+ names: tuple[str, ...] | list[str],
45
+ method: str,
46
+ n_resamples: int,
47
+ context: str,
48
+ ) -> ResamplesState:
49
+ """Build a ResamplesState from resampling results.
50
+
51
+ Args:
52
+ samples: Resampled statistics array, shape (n_resamples, k).
53
+ observed: Observed statistics, shape (k,).
54
+ names: Term/effect names corresponding to columns of samples.
55
+ method: Resampling method (``"boot"`` or ``"perm"``).
56
+ n_resamples: Number of resamples.
57
+ context: What was resampled (``"params"`` or ``"effects"``).
58
+
59
+ Returns:
60
+ Frozen ResamplesState instance.
61
+
62
+ Examples:
63
+ >>> state = build_resamples_state(
64
+ ... samples=np.random.randn(100, 2),
65
+ ... observed=np.array([1.0, 2.0]),
66
+ ... names=("Intercept", "x"),
67
+ ... method="boot",
68
+ ... n_resamples=100,
69
+ ... context="params",
70
+ ... )
71
+ >>> state.method
72
+ 'boot'
73
+ """
74
+ if isinstance(names, list):
75
+ names = tuple(names)
76
+
77
+ return ResamplesState(
78
+ samples=samples,
79
+ observed=observed,
80
+ names=names,
81
+ method=method,
82
+ n_resamples=n_resamples,
83
+ context=context,
84
+ )
85
+
86
+
87
+ def build_resamples_dataframe(rs: ResamplesState) -> pl.DataFrame:
88
+ """Build a long-format DataFrame of raw resampled values.
89
+
90
+ Returns one row per (resample, term) combination with the raw
91
+ resampled value — coefficient estimates for bootstrap, null
92
+ t-statistics for permutation.
93
+
94
+ Columns: ``resample`` (int), ``term`` (str), ``value`` (float).
95
+
96
+ Args:
97
+ rs: Frozen ResamplesState from bootstrap or permutation inference.
98
+
99
+ Returns:
100
+ Polars DataFrame with ``n_resamples × k`` rows, where *k* is the
101
+ number of terms/effects.
102
+
103
+ Examples:
104
+ >>> df = build_resamples_dataframe(rs)
105
+ >>> df.columns
106
+ ['resample', 'term', 'value']
107
+ >>> df.shape
108
+ (1000, 3) # 100 resamples × 10 terms
109
+ """
110
+ import polars as pl
111
+
112
+ samples = np.asarray(rs.samples)
113
+ n_resamples, k = samples.shape
114
+ names = list(rs.names)
115
+
116
+ # Repeat resample indices for each term, repeat term names for each resample
117
+ resample_idx = np.repeat(np.arange(n_resamples), k)
118
+ term_names = names * n_resamples
119
+ values = samples.ravel()
120
+
121
+ return pl.DataFrame(
122
+ {
123
+ Col.RESAMPLE: resample_idx,
124
+ Col.TERM: term_names,
125
+ Col.VALUE: values.tolist(),
126
+ },
127
+ schema=ResamplesRawSchema,
128
+ )
129
+
130
+
131
+ def extract_mee_names(mee: MeeState) -> tuple[str, ...]:
132
+ """Extract human-readable names from a MeeState.
133
+
134
+ Args:
135
+ mee: The MeeState to extract names from.
136
+
137
+ Returns:
138
+ Tuple of effect names for each estimate.
139
+ """
140
+ grid = mee.grid
141
+ focal = mee.focal_var
142
+
143
+ if mee.type == "contrasts" and "contrast" in grid.columns:
144
+ return tuple(grid["contrast"].to_list())
145
+
146
+ if focal in grid.columns:
147
+ return tuple(str(v) for v in grid[focal].to_list())
148
+
149
+ # Fallback: numbered estimates
150
+ return tuple(f"estimate_{i}" for i in range(len(mee.estimate)))
151
+
152
+
153
+ def build_params_resamples(
154
+ inference: InferenceState | None,
155
+ fit_coef: np.ndarray,
156
+ x_names: tuple[str, ...],
157
+ how: str,
158
+ ) -> ResamplesState | None:
159
+ """Build ResamplesState from params inference if samples are available.
160
+
161
+ Args:
162
+ inference: The InferenceState from params inference, or None.
163
+ fit_coef: Coefficient estimates from the FitState.
164
+ x_names: Design matrix column names from the DataBundle.
165
+ how: Inference method used (``"boot"``, ``"perm"``, etc.).
166
+
167
+ Returns:
168
+ ResamplesState if boot/perm samples were saved, else None.
169
+ """
170
+ if inference is None:
171
+ return None
172
+
173
+ if how == "boot" and inference.boot_samples is not None:
174
+ return build_resamples_state(
175
+ samples=inference.boot_samples,
176
+ observed=fit_coef,
177
+ names=x_names,
178
+ method="boot",
179
+ n_resamples=inference.n_resamples,
180
+ context="params",
181
+ )
182
+
183
+ if how == "perm" and inference.perm_samples is not None:
184
+ return build_resamples_state(
185
+ samples=inference.perm_samples,
186
+ observed=inference.statistic,
187
+ names=x_names,
188
+ method="perm",
189
+ n_resamples=inference.n_resamples,
190
+ context="params",
191
+ )
192
+
193
+ return None
194
+
195
+
196
+ def build_mee_resamples(
197
+ mee: MeeState | None,
198
+ samples: np.ndarray | None,
199
+ how: str,
200
+ ) -> ResamplesState | None:
201
+ """Build ResamplesState from MEE inference if samples are available.
202
+
203
+ Args:
204
+ mee: The MeeState from explore, or None.
205
+ samples: Raw resample array from dispatch_mee_inference, or None.
206
+ how: Inference method used (``"boot"``, ``"perm"``, etc.).
207
+
208
+ Returns:
209
+ ResamplesState if boot/perm samples were saved, else None.
210
+ """
211
+ if samples is None or mee is None:
212
+ return None
213
+
214
+ names = extract_mee_names(mee)
215
+
216
+ method = "boot" if how == "boot" else "perm"
217
+ observed = mee.estimate if how == "boot" else mee.statistic
218
+
219
+ return build_resamples_state(
220
+ samples=samples,
221
+ observed=observed,
222
+ names=names,
223
+ method=method,
224
+ n_resamples=samples.shape[0],
225
+ context="effects",
226
+ )
@@ -17,29 +17,43 @@ __all__ = [
17
17
  ]
18
18
 
19
19
  # Standard inference column names, in canonical display order.
20
+ # Estimation group (se, CIs) first, then testing group (statistic, df, p_value).
20
21
  _INFERENCE_COLS: tuple[str, ...] = (
21
22
  Col.SE,
23
+ Col.CI_LOWER,
24
+ Col.CI_UPPER,
22
25
  Col.STATISTIC,
23
26
  Col.DF,
24
27
  Col.P_VALUE,
25
- Col.CI_LOWER,
26
- Col.CI_UPPER,
27
28
  )
28
29
 
30
+ # Columns excluded per inference method.
31
+ _BOOT_EXCLUDE: frozenset[str] = frozenset({Col.P_VALUE})
32
+ _PERM_EXCLUDE: frozenset[str] = frozenset({Col.CI_LOWER, Col.CI_UPPER})
29
33
 
30
- def append_inference_columns(df: pl.DataFrame, state: object) -> pl.DataFrame:
34
+
35
+ def append_inference_columns(
36
+ df: pl.DataFrame,
37
+ state: object,
38
+ method: str | None = None,
39
+ ) -> pl.DataFrame:
31
40
  """Append standard inference columns to a DataFrame if available.
32
41
 
33
42
  Checks ``state.has_inference`` and, when True, adds each inference
34
- column (se, statistic, df, p_value, ci_lower, ci_upper) that is not
35
- None on *state*. Columns are added in canonical order. Attributes
36
- that do not exist on *state* are silently skipped.
43
+ column that is not None on *state*. Columns are added in canonical
44
+ order: se, ci_lower, ci_upper, statistic, df, p_value.
45
+
46
+ When *method* is ``"boot"``, the ``p_value`` column is excluded.
47
+ When *method* is ``"perm"``, the ``ci_lower`` and ``ci_upper``
48
+ columns are excluded.
37
49
 
38
50
  Args:
39
51
  df: Base DataFrame to augment (not mutated).
40
52
  state: Object with a ``has_inference`` bool and optional ``se``,
41
53
  ``statistic``, ``df``, ``p_value``, ``ci_lower``,
42
54
  ``ci_upper`` array attributes.
55
+ method: Inference method (``"asymp"``, ``"boot"``, ``"perm"``,
56
+ or ``None``). Controls which columns are included.
43
57
 
44
58
  Returns:
45
59
  A new DataFrame with inference columns appended (or the
@@ -48,7 +62,16 @@ def append_inference_columns(df: pl.DataFrame, state: object) -> pl.DataFrame:
48
62
  if not getattr(state, "has_inference", False):
49
63
  return df
50
64
 
65
+ if method == "boot":
66
+ exclude = _BOOT_EXCLUDE
67
+ elif method == "perm":
68
+ exclude = _PERM_EXCLUDE
69
+ else:
70
+ exclude = frozenset()
71
+
51
72
  for col_name in _INFERENCE_COLS:
73
+ if col_name in exclude:
74
+ continue
52
75
  values = getattr(state, col_name, None)
53
76
  if values is not None:
54
77
  df = df.with_columns(pl.Series(col_name, values))