PyMetaAnalysis 0.5.0__tar.gz → 0.6.0__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 (132) hide show
  1. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/.gitignore +1 -0
  2. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/CHANGELOG.md +17 -0
  3. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/CITATION.cff +2 -2
  4. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/PKG-INFO +9 -3
  5. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/README.md +8 -2
  6. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/adr/0002-statistical-policy.md +8 -2
  7. pymetaanalysis-0.6.0/docs/adr/0005-mantel-haenszel-risk-difference.md +65 -0
  8. pymetaanalysis-0.6.0/docs/adr/0006-peto-odds-ratio.md +87 -0
  9. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/development.md +2 -2
  10. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/binary-outcomes.md +33 -5
  11. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/method-selection.md +18 -11
  12. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/provenance-reporting.md +12 -0
  13. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/r-interoperability.md +20 -1
  14. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/sensitivity-analysis.md +1 -1
  15. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/zero-events.md +30 -4
  16. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/index.md +7 -5
  17. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/installation.md +1 -1
  18. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/limitations.md +7 -4
  19. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/methods/statistical-methods.md +78 -9
  20. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/reference/api.md +14 -6
  21. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/reference/results.md +11 -2
  22. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/releasing.md +16 -17
  23. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/validation.md +7 -2
  24. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/mkdocs.yml +2 -0
  25. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/pyproject.toml +2 -1
  26. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/_version.py +1 -1
  27. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/binary_api.py +97 -19
  28. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/effect_sizes/binary.py +94 -0
  29. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/estimators/__init__.py +3 -0
  30. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/estimators/mantel_haenszel.py +50 -7
  31. pymetaanalysis-0.6.0/src/meta_analyze/estimators/peto.py +154 -0
  32. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/reporting.py +22 -5
  33. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/README.md +6 -0
  34. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/binary_metafor.json +60 -1
  35. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generate_binary_metafor.R +80 -16
  36. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_binary.py +247 -1
  37. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_estimators.py +62 -0
  38. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_properties.py +148 -0
  39. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_r_references.py +79 -9
  40. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_reporting.py +42 -0
  41. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_sensitivity.py +24 -6
  42. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_subgroups.py +18 -5
  43. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/.github/workflows/ci.yml +0 -0
  44. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/.github/workflows/pages.yml +0 -0
  45. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/.github/workflows/release.yml +0 -0
  46. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/CONTRIBUTING.md +0 -0
  47. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/LICENSE +0 -0
  48. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/SECURITY.md +0 -0
  49. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/benchmarks/README.md +0 -0
  50. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/benchmarks/benchmark_core.py +0 -0
  51. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/adr/0001-optional-matplotlib.md +0 -0
  52. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/adr/0003-meta-regression-prediction-intervals.md +0 -0
  53. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/adr/0004-hartung-knapp-prediction-intervals.md +0 -0
  54. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/citation.md +0 -0
  55. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/getting-started.md +0 -0
  56. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/continuous-outcomes.md +0 -0
  57. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/generic-effects.md +0 -0
  58. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/input-data.md +0 -0
  59. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/meta-regression.md +0 -0
  60. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/guides/plotting.md +0 -0
  61. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/reference/report-schema.md +0 -0
  62. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/docs/stylesheets/extra.css +0 -0
  63. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/examples/README.md +0 -0
  64. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/examples/meta_regression.ipynb +0 -0
  65. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/examples/quickstart.ipynb +0 -0
  66. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/__init__.py +0 -0
  67. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/api.py +0 -0
  68. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/config.py +0 -0
  69. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/continuous_api.py +0 -0
  70. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/data.py +0 -0
  71. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/design_matrix.py +0 -0
  72. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/effect_sizes/__init__.py +0 -0
  73. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/effect_sizes/continuous.py +0 -0
  74. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/estimators/inverse_variance.py +0 -0
  75. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/estimators/meta_regression.py +0 -0
  76. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/estimators/tau2.py +0 -0
  77. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/exceptions.py +0 -0
  78. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/heterogeneity.py +0 -0
  79. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/plotting/__init__.py +0 -0
  80. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/plotting/_utils.py +0 -0
  81. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/plotting/forest.py +0 -0
  82. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/plotting/funnel.py +0 -0
  83. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/plotting/regression.py +0 -0
  84. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/plotting/subgroup_forest.py +0 -0
  85. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/provenance.py +0 -0
  86. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/py.typed +0 -0
  87. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/regression_api.py +0 -0
  88. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/regression_collinearity.py +0 -0
  89. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/regression_contrasts.py +0 -0
  90. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/regression_results.py +0 -0
  91. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/regression_sensitivity.py +0 -0
  92. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/results.py +0 -0
  93. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/sensitivity.py +0 -0
  94. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/src/meta_analyze/subgroups.py +0 -0
  95. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/binary_input.csv +0 -0
  96. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/binary_sparse_input.csv +0 -0
  97. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/continuous_input.csv +0 -0
  98. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/continuous_metafor.json +0 -0
  99. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generate_continuous_metafor.R +0 -0
  100. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generate_generic_metafor.R +0 -0
  101. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generate_meta_regression_collinearity_metafor.R +0 -0
  102. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generate_meta_regression_contrasts_metafor.R +0 -0
  103. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generate_meta_regression_influence_metafor.R +0 -0
  104. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generate_meta_regression_metafor.R +0 -0
  105. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generate_workflow_metafor.R +0 -0
  106. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generic_input.csv +0 -0
  107. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/generic_metafor.json +0 -0
  108. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/meta_regression_boundary_input.csv +0 -0
  109. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/meta_regression_collinearity_metafor.json +0 -0
  110. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/meta_regression_contrasts_metafor.json +0 -0
  111. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/meta_regression_influence_metafor.json +0 -0
  112. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/meta_regression_input.csv +0 -0
  113. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/meta_regression_metafor.json +0 -0
  114. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/workflow_input.csv +0 -0
  115. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/reference/workflow_metafor.json +0 -0
  116. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_api.py +0 -0
  117. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_continuous.py +0 -0
  118. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_documentation.py +0 -0
  119. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_funnel_plot.py +0 -0
  120. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_meta_regression.py +0 -0
  121. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_numerical_stability.py +0 -0
  122. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_plotting.py +0 -0
  123. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_reference_results.py +0 -0
  124. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_regression_collinearity.py +0 -0
  125. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_regression_contrasts.py +0 -0
  126. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_regression_influence.py +0 -0
  127. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_regression_plotting.py +0 -0
  128. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_regression_sensitivity.py +0 -0
  129. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tests/test_release_readiness.py +0 -0
  130. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tools/check_release.py +0 -0
  131. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tools/execute_notebooks.py +0 -0
  132. {pymetaanalysis-0.5.0 → pymetaanalysis-0.6.0}/tools/inspect_distribution.py +0 -0
@@ -1,5 +1,6 @@
1
1
  # Local design notes are intentionally not part of the published project.
2
2
  /DESIGN.md
3
+ /articles/
3
4
 
4
5
  # Python environments and generated files
5
6
  /.venv/
@@ -6,6 +6,23 @@ Changes planned for the next release accumulate under `Unreleased`.
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.6.0 - 2026-08-13
10
+
11
+ ### Added
12
+
13
+ - common-effect Peto one-step odds-ratio pooling, including Peto-specific
14
+ study estimates, O-minus-E heterogeneity, explicit approximation warnings,
15
+ provenance/report metadata, and independent R `metafor` references;
16
+ - common-effect Mantel-Haenszel risk-difference pooling with the
17
+ Sato-Greenland-Robins sampling variance, explicit method metadata,
18
+ sparse-table policy integration, and independent R `metafor` references.
19
+
20
+ ### Fixed
21
+
22
+ - isolated builds temporarily cap Hatchling below 1.32 so the release
23
+ workflow continues to produce Core Metadata 2.4 accepted by Twine 6.2;
24
+ the cap can be removed once Twine validates Metadata 2.5.
25
+
9
26
  ## 0.5.0 - 2026-07-25
10
27
 
11
28
  ### Added
@@ -8,8 +8,8 @@ authors:
8
8
  - family-names: Ding
9
9
  given-names: Zhaobo
10
10
  email: ding.zb@yahoo.com
11
- version: 0.5.0
12
- date-released: 2026-07-25
11
+ version: 0.6.0
12
+ date-released: 2026-08-13
13
13
  repository-code: https://github.com/ZhaoboDing/PyMetaAnalysis
14
14
  url: https://zhaoboding.github.io/PyMetaAnalysis/
15
15
  license: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyMetaAnalysis
3
- Version: 0.5.0
3
+ Version: 0.6.0
4
4
  Summary: A pandas-first, auditable meta-analysis library for Python
5
5
  Project-URL: Documentation, https://zhaoboding.github.io/PyMetaAnalysis/
6
6
  Project-URL: Source, https://github.com/ZhaoboDing/PyMetaAnalysis
@@ -133,7 +133,7 @@ not individual-level or causal effects.
133
133
  | Input | Effects | Pooling/models |
134
134
  | --- | --- | --- |
135
135
  | Effect + sampling variance or standard error | Generic | Common/random inverse variance |
136
- | Two-group events + totals | OR, RR, RD | Common MH OR/RR; common/random IV |
136
+ | Two-group events + totals | OR, RR, RD | Common MH; common Peto OR; common/random IV |
137
137
  | Two-group means + SDs + sizes | MD, Hedges' g | Common/random inverse variance |
138
138
  | Effect + variance/SE + moderators | Generic | Common/mixed Meta-regression |
139
139
 
@@ -153,6 +153,12 @@ Sparse binary behavior is explicit: study-level and Mantel-Haenszel continuity
153
153
  corrections are separate, relative-effect double-zero/double-all rows remain
154
154
  visible as exclusions, and RD exposes
155
155
  `rd_zero_variance="correct" | "exclude"`.
156
+ Peto OR uses raw tables for pooling and a separate one-step study estimator;
157
+ it always reports a caution that its approximation is intended for rare
158
+ outcomes, similar within-study arm sizes, and effects that are not large.
159
+ Common-effect MH risk differences use the Sato-Greenland-Robins sampling
160
+ variance; random-effects binary analyses continue to use inverse-variance
161
+ pooling.
156
162
 
157
163
  ## Inspect and report
158
164
 
@@ -252,7 +258,7 @@ python -m mkdocs serve
252
258
 
253
259
  The test suite combines hand calculations, statistical invariants, numerical
254
260
  edge cases, and committed R `metafor` reference fixtures. CI covers Python
255
- 3.10–3.13, declared dependency lower bounds, strict typing/linting, docs, and
261
+ 3.10–3.14, declared dependency lower bounds, strict typing/linting, docs, and
256
262
  distribution builds.
257
263
 
258
264
  This is independent cross-software validation, not a formal external
@@ -83,7 +83,7 @@ not individual-level or causal effects.
83
83
  | Input | Effects | Pooling/models |
84
84
  | --- | --- | --- |
85
85
  | Effect + sampling variance or standard error | Generic | Common/random inverse variance |
86
- | Two-group events + totals | OR, RR, RD | Common MH OR/RR; common/random IV |
86
+ | Two-group events + totals | OR, RR, RD | Common MH; common Peto OR; common/random IV |
87
87
  | Two-group means + SDs + sizes | MD, Hedges' g | Common/random inverse variance |
88
88
  | Effect + variance/SE + moderators | Generic | Common/mixed Meta-regression |
89
89
 
@@ -103,6 +103,12 @@ Sparse binary behavior is explicit: study-level and Mantel-Haenszel continuity
103
103
  corrections are separate, relative-effect double-zero/double-all rows remain
104
104
  visible as exclusions, and RD exposes
105
105
  `rd_zero_variance="correct" | "exclude"`.
106
+ Peto OR uses raw tables for pooling and a separate one-step study estimator;
107
+ it always reports a caution that its approximation is intended for rare
108
+ outcomes, similar within-study arm sizes, and effects that are not large.
109
+ Common-effect MH risk differences use the Sato-Greenland-Robins sampling
110
+ variance; random-effects binary analyses continue to use inverse-variance
111
+ pooling.
106
112
 
107
113
  ## Inspect and report
108
114
 
@@ -202,7 +208,7 @@ python -m mkdocs serve
202
208
 
203
209
  The test suite combines hand calculations, statistical invariants, numerical
204
210
  edge cases, and committed R `metafor` reference fixtures. CI covers Python
205
- 3.10–3.13, declared dependency lower bounds, strict typing/linting, docs, and
211
+ 3.10–3.14, declared dependency lower bounds, strict typing/linting, docs, and
206
212
  distribution builds.
207
213
 
208
214
  This is independent cross-software validation, not a formal external
@@ -4,6 +4,10 @@
4
4
  - Date: 2026-07-15
5
5
  - Amendment: the prediction-interval variance decision is superseded by
6
6
  [ADR 0004](0004-hartung-knapp-prediction-intervals.md).
7
+ - Amendment: the decision to defer Mantel-Haenszel risk differences is
8
+ superseded by [ADR 0005](0005-mantel-haenszel-risk-difference.md).
9
+ - Amendment: the decision to defer Peto pooling is superseded by
10
+ [ADR 0006](0006-peto-odds-ratio.md).
7
11
 
8
12
  ## Context
9
13
 
@@ -44,13 +48,15 @@ option, and a provenance transformation.
44
48
  Mantel-Haenszel pooling remains a common-effect estimator for OR and RR. It
45
49
  uses raw tables by default and has a correction setting separate from the one
46
50
  used for individual-study effects. Random-effects Mantel-Haenszel, RD
47
- Mantel-Haenszel, and Peto pooling are outside the current scope.
51
+ Mantel-Haenszel, and Peto pooling were outside the scope of this original
52
+ decision; ADRs 0005 and 0006 supersede the latter two deferrals.
48
53
 
49
54
  ### Heterogeneity
50
55
 
51
56
  Cochran's Q, degrees of freedom, and p-value always use common-effect inverse-
52
57
  variance weights. Common-effect and Mantel-Haenszel analyses use Q-based
53
- I-squared and H-squared.
58
+ I-squared and H-squared. ADR 0006 adds Peto's estimator-specific Q while
59
+ retaining those Q-based inconsistency transformations.
54
60
 
55
61
  Random-effects analyses use:
56
62
 
@@ -0,0 +1,65 @@
1
+ # ADR 0005: Mantel-Haenszel risk difference
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-08-13
5
+ - Supersedes: the RD exclusion from the Mantel-Haenszel scope in
6
+ [ADR 0002](0002-statistical-policy.md)
7
+
8
+ ## Context
9
+
10
+ ADR 0002 limited Mantel-Haenszel pooling to common-effect odds ratios and risk
11
+ ratios while the risk-difference estimator and its variance convention were
12
+ still undecided. This left inverse variance as the only pooling method for RD,
13
+ although conventional R implementations provide a common-effect MH RD.
14
+
15
+ The point estimator is straightforward, but several variance estimators have
16
+ appeared in the literature. The selected rule must work under both large-
17
+ stratum and sparse-data limiting models, preserve treatment/control symmetry,
18
+ and remain explicit in reports and cross-software validation.
19
+
20
+ ## Decision
21
+
22
+ PyMetaAnalysis supports `measure="RD", method="MH", model="common"`. With
23
+ treatment total `n1_i`, control total `n0_i`, total `N_i`, and
24
+ `w_i = n1_i n0_i / N_i`, the estimate is:
25
+
26
+ ```text
27
+ RD_i = a_i / n1_i - c_i / n0_i
28
+ RD_MH = sum(w_i RD_i) / sum(w_i)
29
+ ```
30
+
31
+ The normal confidence interval uses the Sato-Greenland-Robins sampling
32
+ variance. The resolved method options record
33
+ `mh_rd_variance="Sato-Greenland-Robins"`.
34
+
35
+ Raw tables are used for MH pooling by default. `mh_continuity_correction` and
36
+ `mh_correction_scope` remain the only settings that alter MH pooling tables;
37
+ the separate study-effect correction continues to control displayed study
38
+ uncertainty and the inverse-variance heterogeneity calculation. The existing
39
+ `rd_zero_variance` policy determines whether boundary studies enter all
40
+ synthesis calculations. A non-positive pooled Sato variance raises a domain
41
+ error instead of silently adding a correction.
42
+
43
+ Random-effects MH remains unsupported. Random-effects RD continues to use
44
+ inverse-variance pooling with an explicit tau-squared estimator.
45
+
46
+ ## Validation
47
+
48
+ - direct formula tests cover the estimate, Sato variance, weights, and normal
49
+ interval;
50
+ - treatment/control swaps negate the estimate and mirror its interval without
51
+ changing the standard error;
52
+ - row reordering and common count scaling preserve the expected invariants;
53
+ - extreme finite counts exercise the overflow-safe scaled implementation;
54
+ - boundary-policy, explicit-correction, subgroup, leave-one-out, and
55
+ cumulative paths are covered; and
56
+ - fixed-version `metafor::rma.mh(measure="RD")` fixtures cover ordinary,
57
+ sparse, and explicitly corrected tables.
58
+
59
+ ## Consequences
60
+
61
+ - common-effect OR, RR, and RD all support MH or inverse-variance pooling;
62
+ - study-table MH weights for RD are proportional to `n1_i n0_i / N_i`;
63
+ - the selected RD variance convention is recoverable from method metadata and
64
+ generated reports; and
65
+ - documentation must continue to distinguish MH RD from random-effects IV RD.
@@ -0,0 +1,87 @@
1
+ # ADR 0006: Peto one-step odds ratio
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-08-13
5
+ - Supersedes: the Peto deferral in
6
+ [ADR 0002](0002-statistical-policy.md)
7
+
8
+ ## Context
9
+
10
+ Peto's one-step method is a conventional common-effect estimator for binary
11
+ outcomes and is particularly associated with rare-event meta-analysis. It is
12
+ not interchangeable with an ordinary inverse-variance odds ratio: it derives
13
+ both the study contribution and pooled estimate from observed-minus-expected
14
+ events and hypergeometric information.
15
+
16
+ The approximation can be biased when treatment and control group sizes differ
17
+ substantially within studies, effects are large, or events are not rare. Its
18
+ zero-cell behavior also differs from ordinary log odds ratios, so pooling and
19
+ display corrections must not be conflated.
20
+
21
+ ## Decision
22
+
23
+ PyMetaAnalysis supports `measure="OR", method="Peto", model="common"` with
24
+ `ci_method="normal"`. `"peto_one_step"` is an accepted alias and the resolved
25
+ pooling method is `"peto"`.
26
+
27
+ For stratum `i`, let `O_i = a_i`, `m_i = a_i + c_i`, treatment and control
28
+ totals be `n1_i` and `n0_i`, and `N_i = n1_i + n0_i`. Define:
29
+
30
+ ```text
31
+ E_i = m_i n1_i / N_i
32
+ V_i = m_i (N_i - m_i) n1_i n0_i / (N_i^2 (N_i - 1))
33
+ ```
34
+
35
+ The individual and pooled model-scale estimates are:
36
+
37
+ ```text
38
+ y_i = (O_i - E_i) / V_i
39
+ Var(y_i) = 1 / V_i
40
+ y_Peto = sum(O_i - E_i) / sum(V_i)
41
+ Var(y_Peto) = 1 / sum(V_i)
42
+ ```
43
+
44
+ Pooling always uses raw 2-by-2 tables. The existing
45
+ `continuity_correction` and `correction_scope` settings affect only displayed
46
+ study estimates and variances; there is no Peto pooling correction parameter.
47
+ Double-zero and double-all rows are excluded before every synthesis
48
+ calculation because they contain no relative-effect information.
49
+
50
+ Peto heterogeneity uses the fitted pooled coefficient and the same
51
+ observed-minus-expected contributions:
52
+
53
+ ```text
54
+ Q = sum(((O_i - E_i) - y_Peto V_i)^2 / V_i)
55
+ ```
56
+
57
+ Q-based I-squared and H-squared follow the project's common-effect
58
+ conventions. Method options record `peto_pooling_tables="raw"` and
59
+ `peto_heterogeneity="O-minus-E"`. Every Peto result carries an approximation
60
+ warning naming the rare-outcome, balanced-arm, and modest-effect conditions.
61
+
62
+ Random-effects Peto and Peto RR/RD are unsupported. Users requesting those
63
+ estimands must select an implemented inverse-variance or Mantel-Haenszel
64
+ combination explicitly.
65
+
66
+ ## Validation
67
+
68
+ - direct formula tests cover study estimates, pooled estimate, variance,
69
+ weights, confidence interval, and Peto Q;
70
+ - treatment/control swapping reverses and exponentiates the log-OR limits as
71
+ expected, while row order leaves the fit unchanged;
72
+ - count scaling and extreme finite-count tests exercise overflow-safe
73
+ arithmetic;
74
+ - sparse tables verify that study-level correction does not alter raw Peto
75
+ pooling and that double-zero/double-all rows are excluded; and
76
+ - fixed-version `metafor::escalc(measure="PETO")` and `metafor::rma.peto()`
77
+ fixtures cover ordinary and sparse datasets.
78
+
79
+ ## Consequences
80
+
81
+ - common-effect binary OR now offers MH, Peto, and inverse-variance pooling;
82
+ - Peto results remain on the log-OR model scale and use exponentiated display
83
+ values like other OR results;
84
+ - sensitivity, subgroup, provenance, reporting, and plotting workflows reuse
85
+ the same public result contracts; and
86
+ - documentation and reports must preserve the Peto applicability warning
87
+ rather than presenting it as a general sparse-data default.
@@ -11,7 +11,7 @@ cd PyMetaAnalysis
11
11
  python -m pip install -e ".[test,dev,docs,plot]"
12
12
  ```
13
13
 
14
- Use a supported Python version (3.10–3.13). Keep changes focused and preserve
14
+ Use a supported Python version (3.10–3.14). Keep changes focused and preserve
15
15
  unrelated worktree modifications.
16
16
 
17
17
  ## Run checks
@@ -31,7 +31,7 @@ python -m build
31
31
  python tools/inspect_distribution.py dist
32
32
  ```
33
33
 
34
- The CI matrix also tests Python 3.10–3.13 and declared dependency lower bounds.
34
+ The CI matrix also tests Python 3.10–3.14 and declared dependency lower bounds.
35
35
  Install the `notebook` extra before running the notebook executor.
36
36
 
37
37
  ## Statistical changes
@@ -35,8 +35,33 @@ result = ma.meta_binary(
35
35
  print(result.summary())
36
36
  ```
37
37
 
38
- Mantel-Haenszel pooling currently supports OR and RR with `model="common"` and
39
- `ci_method="normal"`.
38
+ Mantel-Haenszel pooling supports OR, RR, and RD with `model="common"` and
39
+ `ci_method="normal"`. MH risk differences use the Sato-Greenland-Robins
40
+ sampling variance, recorded in `dict(result.method.options)`.
41
+
42
+ ## Peto common-effect odds ratio
43
+
44
+ Peto's one-step estimator is an explicit alternative for common-effect OR:
45
+
46
+ ```python
47
+ peto = ma.meta_binary(
48
+ studies,
49
+ event_treat="events_t",
50
+ n_treat="total_t",
51
+ event_control="events_c",
52
+ n_control="total_c",
53
+ measure="OR",
54
+ method="Peto",
55
+ model="common",
56
+ )
57
+ ```
58
+
59
+ Peto pooling uses the raw 2-by-2 tables and its own observed-minus-expected
60
+ heterogeneity statistic. The study table contains Peto one-step effects;
61
+ `continuity_correction` affects those displayed study effects but not the
62
+ pooled result. Peto is intended for rare outcomes when treatment/control arm
63
+ sizes are similar within studies and effects are not large. The result always
64
+ retains this caveat in `warnings` and Methods text.
40
65
 
41
66
  ## Random-effects analysis
42
67
 
@@ -71,7 +96,8 @@ them to the generic inverse-variance model.
71
96
  For OR and RR, `result.estimate` and `result.ci` stay on the log model scale.
72
97
  Use `display_estimate` and `display_ci` for exponentiated ratios.
73
98
 
74
- RD is available through inverse-variance pooling:
99
+ For a common-effect RD, choose either MH or inverse-variance pooling explicitly.
100
+ The MH form is:
75
101
 
76
102
  ```python
77
103
  result = ma.meta_binary(
@@ -81,7 +107,7 @@ result = ma.meta_binary(
81
107
  event_control="events_c",
82
108
  n_control="total_c",
83
109
  measure="RD",
84
- method="IV",
110
+ method="MH",
85
111
  model="common",
86
112
  rd_zero_variance="correct",
87
113
  )
@@ -91,6 +117,8 @@ result = ma.meta_binary(
91
117
  their raw RD and uses corrected counts only for sampling variance. Use
92
118
  `"exclude"` for a protocol that excludes these studies before all synthesis
93
119
  calculations. See [zero-event studies](zero-events.md) for details.
120
+ Use `method="IV"` for random-effects RD or when inverse-variance common-effect
121
+ pooling is the prespecified estimator.
94
122
 
95
123
  ## Input validation
96
124
 
@@ -104,5 +132,5 @@ Sparse tables require additional decisions. Read
104
132
  settings.
105
133
 
106
134
  See [statistical methods](../methods/statistical-methods.md#binary-study-effects)
107
- for the OR/RR/RD and Mantel-Haenszel equations, and
135
+ for the OR/RR/RD, Mantel-Haenszel, and Peto equations, and
108
136
  [validation](../validation.md) for cross-software coverage.
@@ -36,15 +36,21 @@ protocols.
36
36
  | Data and model | Available pooling method |
37
37
  | --- | --- |
38
38
  | Generic effects, common or random | Inverse variance |
39
- | Binary OR/RR, common effect | Mantel-Haenszel or inverse variance |
40
- | Binary OR/RR, random effects | Inverse variance |
41
- | Binary RD, common or random | Inverse variance |
39
+ | Binary OR, common effect | Mantel-Haenszel, Peto, or inverse variance |
40
+ | Binary RR/RD, common effect | Mantel-Haenszel or inverse variance |
41
+ | Binary OR/RR/RD, random effects | Inverse variance |
42
42
  | Continuous MD/SMD, common or random | Inverse variance |
43
43
 
44
44
  Mantel-Haenszel and inverse variance are different estimators, not aliases.
45
45
  PyMetaAnalysis does not extrapolate its common-effect Mantel-Haenszel weights
46
- into an undocumented random-effects procedure. Mantel-Haenszel OR/RR pooling
47
- uses raw tables by default and is not offered for RD.
46
+ into an undocumented random-effects procedure. Mantel-Haenszel OR/RR/RD
47
+ pooling uses raw tables by default. MH RD uses the Sato-Greenland-Robins
48
+ sampling variance; it is not a random-effects estimator.
49
+
50
+ Peto is a distinct common-effect OR estimator based on observed-minus-expected
51
+ events. Consider it only when outcomes are rare, treatment/control group sizes
52
+ are similar within each study, and effects are not large. It always uses raw
53
+ tables for pooling and is not an automatic sparse-data default.
48
54
 
49
55
  ## Estimating tau-squared
50
56
 
@@ -63,9 +69,9 @@ Failure to converge raises `ConvergenceError`; it does not silently fall back
63
69
  to DL.
64
70
 
65
71
  The public default is `tau2_method=None`: it resolves to REML for a random- or
66
- mixed-effects fit. Common-effect and Mantel-Haenszel fits reject an explicitly
67
- supplied tau-squared method so analysis code cannot appear to request an
68
- estimator that was not used.
72
+ mixed-effects fit. Common-effect, Mantel-Haenszel, and Peto fits reject an
73
+ explicitly supplied tau-squared method so analysis code cannot appear to
74
+ request an estimator that was not used.
69
75
 
70
76
  ## Confidence intervals
71
77
 
@@ -89,9 +95,10 @@ cautiously: choosing one does not remove the small-sample uncertainty.
89
95
 
90
96
  ## Heterogeneity definitions
91
97
 
92
- Cochran's Q, its degrees of freedom, and its p-value always use common-effect
93
- inverse-variance weights. Common-effect and Mantel-Haenszel analyses derive
94
- I-squared and H-squared from Q.
98
+ Cochran's Q for IV and Mantel-Haenszel fits uses common-effect
99
+ inverse-variance weights; MH residuals are centered on its pooled estimate.
100
+ Peto instead uses its documented observed-minus-expected Q. All common-effect
101
+ fits derive I-squared and H-squared from the applicable Q.
95
102
 
96
103
  For random-effects analyses, I-squared and H-squared instead use the estimated
97
104
  tau-squared and a typical within-study variance:
@@ -50,6 +50,16 @@ Binary analyses record:
50
50
  - non-informative relative-effect exclusions;
51
51
  - a separate Mantel-Haenszel correction record when MH pooling is used.
52
52
 
53
+ A Peto OR transformation additionally records
54
+ `study_estimator="peto_one_step"`. Its method options state that pooling used
55
+ raw tables and heterogeneity used O-minus-E contributions. The study-level
56
+ continuity-correction record remains separate because it does not alter Peto
57
+ pooling.
58
+
59
+ An MH risk-difference result additionally records
60
+ `mh_rd_variance="Sato-Greenland-Robins"` in its method options, and generated
61
+ Methods text names that variance convention.
62
+
53
63
  This separation matters because exact Mantel-Haenszel pooling can use raw
54
64
  tables even when a corrected individual effect is needed for display and
55
65
  heterogeneity calculations.
@@ -73,6 +83,8 @@ The text identifies the model, pooling estimator, tau-squared estimator,
73
83
  confidence interval, heterogeneity statistics, prediction interval,
74
84
  correction settings, missing-data policy, numerical controls, and package
75
85
  version as applicable.
86
+ For Peto it also names the O-minus-E heterogeneity calculation, raw-table
87
+ pooling, and the estimator's applicability caveat.
76
88
 
77
89
  It is a starting point for a manuscript Methods section. Review and adapt it to
78
90
  the analysis protocol, field conventions, and journal requirements.
@@ -16,6 +16,7 @@ fixtures used by this project.
16
16
  | Generic effects and variances | `meta_analysis()` | `rma.uni(yi, vi, ...)` | `metagen(TE, seTE, ...)` |
17
17
  | Binary 2x2 tables, inverse variance | `meta_binary(..., method="IV")` | `escalc()` then `rma.uni()` | `metabin(..., method="Inverse")` |
18
18
  | Binary 2x2 tables, Mantel-Haenszel | `meta_binary(..., method="MH")` | `rma.mh()` | `metabin(..., method="MH")` |
19
+ | Binary 2x2 tables, Peto OR | `meta_binary(..., measure="OR", method="Peto")` | `rma.peto()` | `metabin(..., sm="OR", method="Peto")` |
19
20
  | Continuous group summaries | `meta_continuous()` | `escalc()` then `rma.uni()` | `metacont()` |
20
21
  | Subgroups | `subgroup=` on a high-level call | separate fits or a moderator model | `subgroup=` |
21
22
  | Leave-one-out | `result.leave_one_out()` | `leave1out()` for supported fits | `metainf()` |
@@ -68,7 +69,8 @@ remain explicit attributes in Python.
68
69
  | `model="common"` | `rma.uni(..., method="EE")` | `common=TRUE, random=FALSE` | Inverse-variance common-effect fit |
69
70
  | `model="random"` | random-effects `rma.uni()` | `random=TRUE` | Requires a tau-squared policy |
70
71
  | `method="IV"` | inverse-variance weighting | `method="Inverse"` | Binary API only; generic and continuous fits are IV |
71
- | `method="MH"` | `rma.mh()` | `method="MH"` | Common-effect OR/RR only |
72
+ | `method="MH"` | `rma.mh()` | `method="MH"` | Common-effect OR/RR/RD |
73
+ | `method="Peto"` | `rma.peto()` | `method="Peto"` | Common-effect OR; raw pooling tables and O-minus-E heterogeneity |
72
74
  | `tau2_method=None` (resolved as `"REML"`) | `method="REML"` | `method.tau="REML"` | PyMetaAnalysis random-effects default |
73
75
  | `tau2_method="PM"` | `method="PM"` | `method.tau="PM"` | Paule-Mandel |
74
76
  | `tau2_method="DL"` | `method="DL"` | `method.tau="DL"` | DerSimonian-Laird |
@@ -78,6 +80,9 @@ handling, or heterogeneity definitions. In particular, PyMetaAnalysis records
78
80
  `i2_method`; random-effects inverse-variance results use the documented
79
81
  tau-squared/typical-variance definition, while common-effect and MH results use
80
82
  the Q-based definition.
83
+ Peto also reports Q-based inconsistency, but its Q is formed from the Peto
84
+ observed-minus-expected contributions rather than ordinary study-log-OR
85
+ inverse-variance residuals.
81
86
 
82
87
  `result.tau2_confidence_interval()` corresponds to
83
88
  `confint(fit, type="QP")` for an `rma.uni` random-effects fit. Both return
@@ -128,6 +133,19 @@ not implement. For OR/RR, double-zero and double-all studies are excluded from
128
133
  all model and heterogeneity calculations by default while remaining visible in
129
134
  the result table. RD uses its separate `rd_zero_variance` policy.
130
135
 
136
+ For `measure="RD"`, PyMetaAnalysis and `metafor::rma.mh(measure="RD")` use
137
+ the Sato-Greenland-Robins sampling variance. A separate explicit
138
+ `mh_continuity_correction` changes the MH tables; the study-effect
139
+ `continuity_correction` still affects only displayed study variances and
140
+ heterogeneity.
141
+
142
+ For Peto, PyMetaAnalysis's default study-level correction corresponds to
143
+ `escalc(measure="PETO", add=0.5, to="only0", drop00=TRUE)` for the displayed
144
+ study rows. Its pooled fit corresponds to `rma.peto()` with raw pooling tables;
145
+ the study correction never changes the pooled result. Compare Peto's
146
+ rare-outcome, within-study arm-balance, and modest-effect assumptions before
147
+ porting it solely because a table contains zeros.
148
+
131
149
  Read [zero-event studies](zero-events.md) before translating sparse analyses.
132
150
 
133
151
  ## Worked generic translation
@@ -194,6 +212,7 @@ as numerically equivalent.
194
212
  - [`metafor::rma.uni`](https://wviechtb.github.io/metafor/reference/rma.uni.html)
195
213
  - [`metafor::predict.rma`](https://wviechtb.github.io/metafor/reference/predict.rma.html)
196
214
  - [`metafor::rma.mh`](https://wviechtb.github.io/metafor/reference/rma.mh.html)
215
+ - [`metafor::rma.peto`](https://wviechtb.github.io/metafor/reference/rma.peto.html)
197
216
  - [`metafor::escalc`](https://wviechtb.github.io/metafor/reference/escalc.html)
198
217
  - [`meta::metagen`](https://search.r-project.org/CRAN/refmans/meta/html/metagen.html)
199
218
  - [`meta::metabin`](https://search.r-project.org/CRAN/refmans/meta/html/metabin.html)
@@ -160,7 +160,7 @@ model, and the boundary is recorded in `cumulative.warnings`.
160
160
  Every refit reuses the original result's:
161
161
 
162
162
  - common- or random-effects model;
163
- - inverse-variance or Mantel-Haenszel pooling method;
163
+ - inverse-variance, Mantel-Haenszel, or Peto pooling method;
164
164
  - tau-squared and confidence-interval methods;
165
165
  - confidence level, absolute tolerance, and iteration limit;
166
166
  - missing-data policy;
@@ -1,8 +1,8 @@
1
1
  # Zero-event studies
2
2
 
3
- Zero cells in 2-by-2 tables affect OR, RR, RD, and Mantel-Haenszel estimators in
4
- different ways. PyMetaAnalysis therefore separates study-level effect
5
- corrections from the pooled Mantel-Haenszel correction.
3
+ Zero cells in 2-by-2 tables affect OR, RR, RD, Mantel-Haenszel, and Peto
4
+ estimators in different ways. PyMetaAnalysis therefore separates study-level
5
+ effect corrections from table-based pooling rules.
6
6
 
7
7
  ## Default study-level correction
8
8
 
@@ -71,7 +71,8 @@ RD-specific; setting `exclude` for OR or RR is rejected.
71
71
 
72
72
  ## Mantel-Haenszel correction is separate
73
73
 
74
- Exact common-effect Mantel-Haenszel OR/RR pooling uses raw tables by default:
74
+ Uncorrected common-effect Mantel-Haenszel OR/RR/RD pooling uses raw tables by
75
+ default:
75
76
 
76
77
  ```python
77
78
  mh_continuity_correction = None
@@ -83,6 +84,29 @@ and heterogeneity. It does not silently alter the pooled Mantel-Haenszel
83
84
  estimator. If an exact pooled estimator is undefined, choose an explicit
84
85
  positive `mh_continuity_correction` and report that decision.
85
86
 
87
+ For MH RD, `rd_zero_variance="exclude"` removes zero-variance boundary rows
88
+ before every synthesis calculation. With the default `"correct"` policy, the
89
+ raw table still enters the MH point estimate unless an explicit
90
+ `mh_continuity_correction` is supplied. If the Sato-Greenland-Robins variance
91
+ is non-positive, the uncorrected fit raises instead of silently changing the
92
+ tables; a positive MH correction is an explicit protocol choice.
93
+
94
+ ## Peto pooling always uses raw tables
95
+
96
+ Peto's observed-minus-expected pooling contribution remains defined for many
97
+ single-zero tables, so `method="Peto"` does not apply a continuity correction
98
+ to pooling or Peto Q. The general `continuity_correction` and
99
+ `correction_scope` settings apply only to the one-step study effects and
100
+ variances shown in the study table. There is deliberately no separate Peto
101
+ pooling-correction option.
102
+
103
+ Double-zero and double-all studies have zero Peto information and are excluded
104
+ before pooling, Q, I-squared, H-squared, and weights. The result retains the
105
+ same structured exclusion reasons used for other relative-effect analyses.
106
+ Peto's lack of a single-zero pooling correction does not make it universally
107
+ preferable: its rare-outcome, balanced-arm, and modest-effect assumptions must
108
+ still be considered.
109
+
86
110
  ## Inspect what happened
87
111
 
88
112
  ```python
@@ -104,3 +128,5 @@ Resolved correction values and scopes also appear in
104
128
  zero-variance policy and affected row IDs in provenance. This makes it possible
105
129
  to distinguish a corrected analysis from an exact or exclusion-based one after
106
130
  fitting.
131
+ Peto analyses additionally record `peto_pooling_tables="raw"` and
132
+ `peto_heterogeneity="O-minus-E"`.
@@ -84,11 +84,13 @@ lists unsupported methods explicitly.
84
84
 
85
85
  ## Project status
86
86
 
87
- PyMetaAnalysis 0.4.0 extends Meta-regression with exact leave-one-out and
88
- influence diagnostics, VIF/GVIF and weighted condition diagnostics, explicit
89
- linear contrasts, and opt-in Riley prediction intervals. The project has not
90
- undergone a formal external statistical audit. Pin the package version for
91
- consequential work and independently check important analyses. See the
87
+ PyMetaAnalysis 0.6.0 adds common-effect Mantel-Haenszel risk-difference and
88
+ Peto one-step odds-ratio pooling, with explicit sparse-table policies,
89
+ statistical metadata, and independent R references. It also retains the
90
+ Q-profile heterogeneity intervals and Meta-regression diagnostics introduced
91
+ in earlier releases. The project has not undergone a formal external
92
+ statistical audit. Pin the package version for consequential work and
93
+ independently check important analyses. See the
92
94
  repository
93
95
  [changelog](https://github.com/ZhaoboDing/PyMetaAnalysis/blob/main/CHANGELOG.md)
94
96
  and [contribution guide](development.md). For manuscripts and archived
@@ -1,6 +1,6 @@
1
1
  # Installation
2
2
 
3
- PyMetaAnalysis supports Python 3.10 through 3.13. The numerical core depends
3
+ PyMetaAnalysis supports Python 3.10 through 3.14. The numerical core depends
4
4
  on NumPy, pandas, and SciPy; Matplotlib is optional.
5
5
 
6
6
  ## Install from PyPI