PyMetaAnalysis 0.5.0__tar.gz → 0.7.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 (140) hide show
  1. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/.gitignore +1 -0
  2. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/CHANGELOG.md +63 -7
  3. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/CITATION.cff +2 -2
  4. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/PKG-INFO +13 -5
  5. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/README.md +12 -4
  6. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/benchmarks/README.md +5 -5
  7. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/benchmarks/benchmark_core.py +8 -0
  8. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/adr/0002-statistical-policy.md +8 -2
  9. pymetaanalysis-0.7.0/docs/adr/0005-mantel-haenszel-risk-difference.md +65 -0
  10. pymetaanalysis-0.7.0/docs/adr/0006-peto-odds-ratio.md +87 -0
  11. pymetaanalysis-0.7.0/docs/adr/0007-fisher-z-correlation.md +66 -0
  12. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/citation.md +1 -1
  13. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/development.md +2 -2
  14. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/getting-started.md +5 -3
  15. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/binary-outcomes.md +33 -5
  16. pymetaanalysis-0.7.0/docs/guides/correlation-outcomes.md +150 -0
  17. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/input-data.md +3 -2
  18. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/meta-regression.md +5 -4
  19. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/method-selection.md +20 -11
  20. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/plotting.md +3 -1
  21. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/provenance-reporting.md +12 -0
  22. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/r-interoperability.md +31 -6
  23. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/sensitivity-analysis.md +3 -3
  24. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/zero-events.md +45 -10
  25. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/index.md +9 -5
  26. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/installation.md +1 -1
  27. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/limitations.md +19 -5
  28. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/methods/statistical-methods.md +106 -9
  29. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/reference/api.md +69 -13
  30. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/reference/report-schema.md +10 -1
  31. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/reference/results.md +22 -6
  32. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/releasing.md +16 -17
  33. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/validation.md +13 -4
  34. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/mkdocs.yml +4 -0
  35. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/pyproject.toml +2 -1
  36. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/__init__.py +2 -0
  37. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/_version.py +1 -1
  38. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/binary_api.py +122 -28
  39. pymetaanalysis-0.7.0/src/meta_analyze/correlation_api.py +317 -0
  40. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/design_matrix.py +22 -5
  41. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/effect_sizes/__init__.py +8 -0
  42. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/effect_sizes/binary.py +93 -0
  43. pymetaanalysis-0.7.0/src/meta_analyze/effect_sizes/correlation.py +215 -0
  44. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/__init__.py +3 -0
  45. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/mantel_haenszel.py +52 -7
  46. pymetaanalysis-0.7.0/src/meta_analyze/estimators/peto.py +159 -0
  47. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/heterogeneity.py +8 -1
  48. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/_utils.py +3 -0
  49. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/reporting.py +29 -5
  50. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/results.py +2 -0
  51. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/sensitivity.py +26 -4
  52. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/subgroups.py +4 -1
  53. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/README.md +18 -1
  54. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/binary_metafor.json +60 -1
  55. pymetaanalysis-0.7.0/tests/reference/correlation_input.csv +9 -0
  56. pymetaanalysis-0.7.0/tests/reference/correlation_metafor.json +27 -0
  57. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_binary_metafor.R +80 -16
  58. pymetaanalysis-0.7.0/tests/reference/generate_correlation_metafor.R +59 -0
  59. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_generic_metafor.R +10 -0
  60. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_workflow_metafor.R +29 -0
  61. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generic_metafor.json +7 -0
  62. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/workflow_metafor.json +14 -0
  63. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_binary.py +324 -1
  64. pymetaanalysis-0.7.0/tests/test_correlation.py +288 -0
  65. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_estimators.py +62 -0
  66. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_funnel_plot.py +20 -0
  67. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_meta_regression.py +42 -13
  68. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_plotting.py +24 -0
  69. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_properties.py +210 -0
  70. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_r_references.py +134 -10
  71. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_release_readiness.py +1 -0
  72. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_reporting.py +42 -0
  73. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_sensitivity.py +48 -6
  74. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_subgroups.py +33 -5
  75. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/.github/workflows/ci.yml +0 -0
  76. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/.github/workflows/pages.yml +0 -0
  77. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/.github/workflows/release.yml +0 -0
  78. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/CONTRIBUTING.md +0 -0
  79. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/LICENSE +0 -0
  80. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/SECURITY.md +0 -0
  81. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/adr/0001-optional-matplotlib.md +0 -0
  82. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/adr/0003-meta-regression-prediction-intervals.md +0 -0
  83. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/adr/0004-hartung-knapp-prediction-intervals.md +0 -0
  84. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/continuous-outcomes.md +0 -0
  85. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/guides/generic-effects.md +0 -0
  86. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/docs/stylesheets/extra.css +0 -0
  87. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/examples/README.md +0 -0
  88. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/examples/meta_regression.ipynb +0 -0
  89. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/examples/quickstart.ipynb +0 -0
  90. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/api.py +0 -0
  91. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/config.py +0 -0
  92. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/continuous_api.py +0 -0
  93. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/data.py +0 -0
  94. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/effect_sizes/continuous.py +0 -0
  95. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/inverse_variance.py +0 -0
  96. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/meta_regression.py +0 -0
  97. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/estimators/tau2.py +0 -0
  98. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/exceptions.py +0 -0
  99. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/__init__.py +0 -0
  100. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/forest.py +0 -0
  101. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/funnel.py +0 -0
  102. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/regression.py +0 -0
  103. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/plotting/subgroup_forest.py +0 -0
  104. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/provenance.py +0 -0
  105. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/py.typed +0 -0
  106. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_api.py +0 -0
  107. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_collinearity.py +0 -0
  108. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_contrasts.py +0 -0
  109. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_results.py +0 -0
  110. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/src/meta_analyze/regression_sensitivity.py +0 -0
  111. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/binary_input.csv +0 -0
  112. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/binary_sparse_input.csv +0 -0
  113. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/continuous_input.csv +0 -0
  114. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/continuous_metafor.json +0 -0
  115. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_continuous_metafor.R +0 -0
  116. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_meta_regression_collinearity_metafor.R +0 -0
  117. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_meta_regression_contrasts_metafor.R +0 -0
  118. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_meta_regression_influence_metafor.R +0 -0
  119. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generate_meta_regression_metafor.R +0 -0
  120. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/generic_input.csv +0 -0
  121. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_boundary_input.csv +0 -0
  122. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_collinearity_metafor.json +0 -0
  123. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_contrasts_metafor.json +0 -0
  124. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_influence_metafor.json +0 -0
  125. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_input.csv +0 -0
  126. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/meta_regression_metafor.json +0 -0
  127. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/reference/workflow_input.csv +0 -0
  128. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_api.py +0 -0
  129. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_continuous.py +0 -0
  130. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_documentation.py +0 -0
  131. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_numerical_stability.py +0 -0
  132. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_reference_results.py +0 -0
  133. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_collinearity.py +0 -0
  134. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_contrasts.py +0 -0
  135. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_influence.py +0 -0
  136. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_plotting.py +0 -0
  137. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tests/test_regression_sensitivity.py +0 -0
  138. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tools/check_release.py +0 -0
  139. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.0}/tools/execute_notebooks.py +0 -0
  140. {pymetaanalysis-0.5.0 → pymetaanalysis-0.7.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,54 @@ Changes planned for the next release accumulate under `Unreleased`.
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 0.7.0 - 2026-09-02
10
+
11
+ ### Added
12
+
13
+ - `meta_correlation()` for independent study-level correlations using Fisher's
14
+ r-to-z transformation (`ZCOR`), `1 / (n - 3)` sampling variances, common- or
15
+ REML/PM/DL random-effects inverse-variance pooling, back-transformed result
16
+ displays, subgroup and sensitivity workflows, plotting, provenance, reports,
17
+ and independent R `metafor` references.
18
+
19
+ ### Changed
20
+
21
+ - integer-valued floating-point categorical moderators now match declared
22
+ integer levels while booleans remain distinct, supporting pandas columns
23
+ promoted to floating point by missing values;
24
+ - MH pooling corrections now use `None` as the context-sensitive scope default;
25
+ explicitly supplying either MH-only option to IV or Peto pooling raises an
26
+ error, and non-MH method metadata no longer records unused MH settings;
27
+ - estimator documentation now makes the pooled-mean-only Q-profile contract,
28
+ the prefiltered `fit_peto()` input contract, and sparse MH RD boundary policy
29
+ explicit;
30
+ - fixed-version `metafor` references now cover a two-study Hartung-Knapp
31
+ interval and Q-profile intervals reached through random-effects subgroups.
32
+
33
+ ### Fixed
34
+
35
+ - normal-inference subgroup tests reuse each fitted standard error directly,
36
+ avoiding an unnecessary recomputation and last-bit numerical drift.
37
+ - Peto observed-minus-expected arithmetic now uses a treatment/control-symmetric
38
+ formulation, preventing avoidable last-bit drift for highly imbalanced arms.
39
+
40
+ ## 0.6.0 - 2026-08-13
41
+
42
+ ### Added
43
+
44
+ - common-effect Peto one-step odds-ratio pooling, including Peto-specific
45
+ study estimates, O-minus-E heterogeneity, explicit approximation warnings,
46
+ provenance/report metadata, and independent R `metafor` references;
47
+ - common-effect Mantel-Haenszel risk-difference pooling with the
48
+ Sato-Greenland-Robins sampling variance, explicit method metadata,
49
+ sparse-table policy integration, and independent R `metafor` references.
50
+
51
+ ### Fixed
52
+
53
+ - isolated builds temporarily cap Hatchling below 1.32 so the release
54
+ workflow continues to produce Core Metadata 2.4 accepted by Twine 6.2;
55
+ the cap can be removed once Twine validates Metadata 2.5.
56
+
9
57
  ## 0.5.0 - 2026-07-25
10
58
 
11
59
  ### Added
@@ -26,6 +74,21 @@ Changes planned for the next release accumulate under `Unreleased`.
26
74
  Mantel-Haenszel pooling correction; iterative failure paths have direct
27
75
  regression tests.
28
76
 
77
+ ### Breaking changes
78
+
79
+ - explicitly supplying `tau2_method` to a common-effect model, including the
80
+ former default spelling `"REML"`, now raises an error instead of being
81
+ ignored; explicitly inapplicable SMD variance settings follow the same rule;
82
+ - cumulative analysis now rejects a string `order` selector when the name is
83
+ present in both source data and the calculated study table, instead of
84
+ silently preferring the source-data column;
85
+ - `LeaveOneOutResult.results` now preserves failed refits as `None`, and its
86
+ table adds `refit_success`, `error_type`, and `error_message` columns;
87
+ - pooled-result `prediction_interval_method` metadata now uses `null` when an
88
+ interval is unavailable and `"HK-PR"` for Hartung-Knapp intervals. Report
89
+ schema 1.2 remains unchanged because the field itself was already present;
90
+ consumers must handle the documented value set.
91
+
29
92
  ### Fixed
30
93
 
31
94
  - inverse-variance means, heterogeneity statistics, and pooling and
@@ -54,9 +117,6 @@ Changes planned for the next release accumulate under `Unreleased`.
54
117
  analysis;
55
118
  - tagged releases now rerun the full branch-coverage test suite before
56
119
  distributions can be built and published.
57
- - tau-squared methods and SMD variance conventions now use `None` as the
58
- context-sensitive default, so explicitly inapplicable settings raise domain
59
- errors instead of being silently ignored;
60
120
  - duplicate study labels now add a row-position warning while preserving
61
121
  `row_id` as the unique audit key;
62
122
  - report JSON now serializes `pd.NaT` study labels as `null` rather than the
@@ -64,8 +124,6 @@ Changes planned for the next release accumulate under `Unreleased`.
64
124
  - Meta-regression with `missing="drop"` now determines complete-row exclusions
65
125
  before validating moderator values, so invalid values in already excluded
66
126
  rows cannot abort the analysis;
67
- - cumulative analysis now rejects ambiguous string `order` selectors that
68
- exist in both source data and study results;
69
127
  - empty inputs now report that at least one study row is required, and binary
70
128
  zero-cell errors identify when `correction_scope="none"` disables an
71
129
  otherwise positive correction.
@@ -77,8 +135,6 @@ Changes planned for the next release accumulate under `Unreleased`.
77
135
  errors;
78
136
  - the Mantel-Haenszel estimator now rejects empty and zero-total strata before
79
137
  division, preventing NaN propagation and misleading variance diagnostics.
80
- - prediction-interval metadata is now `None` when too few studies prevent an
81
- interval from being calculated;
82
138
  - categorical moderator encoding no longer conflates booleans, integers, and
83
139
  floating-point values through Python's cross-type numeric equality;
84
140
  - CI now covers Python 3.14, Pages deployments are not cancelled mid-flight,
@@ -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.7.0
12
+ date-released: 2026-09-02
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.7.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,8 +133,9 @@ 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
+ | Correlations + sample sizes | Fisher's z (`ZCOR`) | Common/random inverse variance |
138
139
  | Effect + variance/SE + moderators | Generic | Common/mixed Meta-regression |
139
140
 
140
141
  Random-effects inverse-variance models support REML (default), Paule-Mandel,
@@ -153,6 +154,12 @@ Sparse binary behavior is explicit: study-level and Mantel-Haenszel continuity
153
154
  corrections are separate, relative-effect double-zero/double-all rows remain
154
155
  visible as exclusions, and RD exposes
155
156
  `rd_zero_variance="correct" | "exclude"`.
157
+ Peto OR uses raw tables for pooling and a separate one-step study estimator;
158
+ it always reports a caution that its approximation is intended for rare
159
+ outcomes, similar within-study arm sizes, and effects that are not large.
160
+ Common-effect MH risk differences use the Sato-Greenland-Robins sampling
161
+ variance; random-effects binary analyses continue to use inverse-variance
162
+ pooling.
156
163
 
157
164
  ## Inspect and report
158
165
 
@@ -176,7 +183,8 @@ markdown = report.to_markdown()
176
183
 
177
184
  OR and RR remain on the log model scale in auditable numeric attributes;
178
185
  `display_estimate`, `display_ci`, and `display_prediction_interval` provide
179
- exponentiated ratios.
186
+ exponentiated ratios. `ZCOR` results similarly retain Fisher's z internally
187
+ and expose back-transformed correlations through the display properties.
180
188
 
181
189
  Rows excluded by missing-value or sparse-data policies remain in
182
190
  `study_results` with a stable `row_id`, `included=False`, and an
@@ -229,7 +237,7 @@ The complete documentation is published at
229
237
  - [Installation](https://zhaoboding.github.io/PyMetaAnalysis/installation/)
230
238
  - [Getting started](https://zhaoboding.github.io/PyMetaAnalysis/getting-started/)
231
239
  - [Input data and row decisions](https://zhaoboding.github.io/PyMetaAnalysis/guides/input-data/)
232
- - [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/), and [continuous](https://zhaoboding.github.io/PyMetaAnalysis/guides/continuous-outcomes/) guides
240
+ - [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/), [continuous](https://zhaoboding.github.io/PyMetaAnalysis/guides/continuous-outcomes/), and [correlation](https://zhaoboding.github.io/PyMetaAnalysis/guides/correlation-outcomes/) guides
233
241
  - [Meta-regression](https://zhaoboding.github.io/PyMetaAnalysis/guides/meta-regression/)
234
242
  - [Choosing methods](https://zhaoboding.github.io/PyMetaAnalysis/guides/method-selection/) and [statistical formulas](https://zhaoboding.github.io/PyMetaAnalysis/methods/statistical-methods/)
235
243
  - [Sensitivity analysis](https://zhaoboding.github.io/PyMetaAnalysis/guides/sensitivity-analysis/) and [plotting](https://zhaoboding.github.io/PyMetaAnalysis/guides/plotting/)
@@ -252,7 +260,7 @@ python -m mkdocs serve
252
260
 
253
261
  The test suite combines hand calculations, statistical invariants, numerical
254
262
  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
263
+ 3.10–3.14, declared dependency lower bounds, strict typing/linting, docs, and
256
264
  distribution builds.
257
265
 
258
266
  This is independent cross-software validation, not a formal external
@@ -83,8 +83,9 @@ 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
+ | Correlations + sample sizes | Fisher's z (`ZCOR`) | Common/random inverse variance |
88
89
  | Effect + variance/SE + moderators | Generic | Common/mixed Meta-regression |
89
90
 
90
91
  Random-effects inverse-variance models support REML (default), Paule-Mandel,
@@ -103,6 +104,12 @@ Sparse binary behavior is explicit: study-level and Mantel-Haenszel continuity
103
104
  corrections are separate, relative-effect double-zero/double-all rows remain
104
105
  visible as exclusions, and RD exposes
105
106
  `rd_zero_variance="correct" | "exclude"`.
107
+ Peto OR uses raw tables for pooling and a separate one-step study estimator;
108
+ it always reports a caution that its approximation is intended for rare
109
+ outcomes, similar within-study arm sizes, and effects that are not large.
110
+ Common-effect MH risk differences use the Sato-Greenland-Robins sampling
111
+ variance; random-effects binary analyses continue to use inverse-variance
112
+ pooling.
106
113
 
107
114
  ## Inspect and report
108
115
 
@@ -126,7 +133,8 @@ markdown = report.to_markdown()
126
133
 
127
134
  OR and RR remain on the log model scale in auditable numeric attributes;
128
135
  `display_estimate`, `display_ci`, and `display_prediction_interval` provide
129
- exponentiated ratios.
136
+ exponentiated ratios. `ZCOR` results similarly retain Fisher's z internally
137
+ and expose back-transformed correlations through the display properties.
130
138
 
131
139
  Rows excluded by missing-value or sparse-data policies remain in
132
140
  `study_results` with a stable `row_id`, `included=False`, and an
@@ -179,7 +187,7 @@ The complete documentation is published at
179
187
  - [Installation](https://zhaoboding.github.io/PyMetaAnalysis/installation/)
180
188
  - [Getting started](https://zhaoboding.github.io/PyMetaAnalysis/getting-started/)
181
189
  - [Input data and row decisions](https://zhaoboding.github.io/PyMetaAnalysis/guides/input-data/)
182
- - [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/), and [continuous](https://zhaoboding.github.io/PyMetaAnalysis/guides/continuous-outcomes/) guides
190
+ - [Generic](https://zhaoboding.github.io/PyMetaAnalysis/guides/generic-effects/), [binary](https://zhaoboding.github.io/PyMetaAnalysis/guides/binary-outcomes/), [continuous](https://zhaoboding.github.io/PyMetaAnalysis/guides/continuous-outcomes/), and [correlation](https://zhaoboding.github.io/PyMetaAnalysis/guides/correlation-outcomes/) guides
183
191
  - [Meta-regression](https://zhaoboding.github.io/PyMetaAnalysis/guides/meta-regression/)
184
192
  - [Choosing methods](https://zhaoboding.github.io/PyMetaAnalysis/guides/method-selection/) and [statistical formulas](https://zhaoboding.github.io/PyMetaAnalysis/methods/statistical-methods/)
185
193
  - [Sensitivity analysis](https://zhaoboding.github.io/PyMetaAnalysis/guides/sensitivity-analysis/) and [plotting](https://zhaoboding.github.io/PyMetaAnalysis/guides/plotting/)
@@ -202,7 +210,7 @@ python -m mkdocs serve
202
210
 
203
211
  The test suite combines hand calculations, statistical invariants, numerical
204
212
  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
213
+ 3.10–3.14, declared dependency lower bounds, strict typing/linting, docs, and
206
214
  distribution builds.
207
215
 
208
216
  This is independent cross-software validation, not a formal external
@@ -1,10 +1,10 @@
1
1
  # Core performance baseline
2
2
 
3
- `benchmark_core.py` measures representative generic, binary, continuous, and
4
- multivariable Meta-regression random-effects fits using deterministic synthetic
5
- data. Correctness remains the primary performance requirement; this benchmark
6
- is intended to reveal large regressions, not to enforce a fragile wall-clock
7
- threshold.
3
+ `benchmark_core.py` measures representative generic, binary, continuous,
4
+ correlation, and multivariable Meta-regression random-effects fits using
5
+ deterministic synthetic data. Correctness remains the primary performance
6
+ requirement; this benchmark is intended to reveal large regressions, not to
7
+ enforce a fragile wall-clock threshold.
8
8
 
9
9
  Run the default benchmark with:
10
10
 
@@ -48,6 +48,8 @@ def _cases(studies: int) -> dict[str, Callable[[], object]]:
48
48
  mean_treat = mean_control + rng.normal(0.25, 0.18, size=studies)
49
49
  sd_treat = rng.uniform(0.7, 1.6, size=studies)
50
50
  sd_control = rng.uniform(0.7, 1.6, size=studies)
51
+ correlation = rng.uniform(-0.65, 0.65, size=studies)
52
+ correlation_n = rng.integers(20, 300, size=studies)
51
53
 
52
54
  return {
53
55
  "generic_random_reml": lambda: ma.meta_analysis(
@@ -77,6 +79,12 @@ def _cases(studies: int) -> dict[str, Callable[[], object]]:
77
79
  model="random",
78
80
  tau2_method="REML",
79
81
  ),
82
+ "correlation_random_reml": lambda: ma.meta_correlation(
83
+ correlation=correlation,
84
+ n=correlation_n,
85
+ model="random",
86
+ tau2_method="REML",
87
+ ),
80
88
  "meta_regression_multivariable_reml": lambda: ma.meta_regression(
81
89
  effect=generic_effect,
82
90
  variance=generic_variance,
@@ -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.
@@ -0,0 +1,66 @@
1
+ # ADR 0007: Fisher's z correlation pooling
2
+
3
+ - Status: Accepted
4
+ - Date: 2026-09-02
5
+
6
+ ## Context
7
+
8
+ Study-level correlations are common in behavioral, educational, and medical
9
+ research. Directly pooling raw correlations is possible but their sampling
10
+ distribution is bounded, asymmetric away from zero, and has a variance that
11
+ depends on the underlying correlation. Fisher's r-to-z transformation is the
12
+ standard first implementation in R `meta` and `metafor` and composes with the
13
+ library's existing inverse-variance machinery.
14
+
15
+ The API also needs an explicit position on perfect correlations, very small
16
+ samples, displayed values, and multiple correlations drawn from the same
17
+ participants.
18
+
19
+ ## Decision
20
+
21
+ `meta_correlation()` accepts raw `correlation` and sample size `n`, but its
22
+ first supported measure is only `ZCOR`:
23
+
24
+ ```text
25
+ y_i = atanh(r_i)
26
+ v_i = 1 / (n_i - 3)
27
+ ```
28
+
29
+ All fitting and heterogeneity calculations use Fisher's z. Result display
30
+ properties and plots use `tanh` to return the correlation scale. The result
31
+ records `effect_scale="fisher_z"`, `display_scale="tanh"`, the transformation,
32
+ variance equation, affected rows, and input sources.
33
+
34
+ Included correlations must be finite and strictly between -1 and 1. Sample
35
+ sizes must be whole numbers of at least 4. The implementation does not clip
36
+ perfect correlations or replace invalid sample sizes because either action
37
+ would introduce an undocumented effect or variance.
38
+
39
+ The default is the library's random-effects inverse-variance policy: REML
40
+ tau-squared and a normal confidence interval. Common effects, PM/DL, the two
41
+ documented Hartung-Knapp options, shared prediction intervals, Q-profile
42
+ heterogeneity intervals, subgroups, repeated-fit sensitivity, reports, and
43
+ plots reuse their existing contracts.
44
+
45
+ Rows are assumed independent. Duplicate labels remain allowed and warned, but
46
+ do not imply a dependence correction. Raw-correlation pooling (`COR`),
47
+ dependent correlations, partial/rank correlations, and reliability
48
+ corrections are deferred.
49
+
50
+ ## Validation
51
+
52
+ Committed fixtures generated by `metafor::escalc(measure="ZCOR")` and
53
+ `rma.uni()` validate study effects, variances, common-effect and REML fits,
54
+ weights, and back-transformation. Targeted and property-based tests cover
55
+ domain boundaries, missing rows, sign symmetry, row-order invariance,
56
+ subgroups, sensitivity refits, reports, and Matplotlib coordinates.
57
+
58
+ ## Consequences
59
+
60
+ - users can supply pandas columns without calculating z values or variances;
61
+ - model-scale and correlation-scale results remain distinguishable;
62
+ - behavior matches a documented R workflow without importing R at runtime;
63
+ - perfect correlations and samples smaller than four require an upstream,
64
+ scientifically justified decision rather than silent repair;
65
+ - users with dependent correlations must use a method outside the current
66
+ univariate scope.
@@ -19,7 +19,7 @@ print(ma.__version__)
19
19
  A provisional citation can use:
20
20
 
21
21
  ```text
22
- PyMetaAnalysis contributors. PyMetaAnalysis (version <version>):
22
+ Zhaobo Ding. PyMetaAnalysis (version <version>):
23
23
  a pandas-first meta-analysis library for Python.
24
24
  https://github.com/ZhaoboDing/PyMetaAnalysis
25
25
  ```
@@ -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
@@ -120,8 +120,9 @@ schema, strict JSON behavior, and subgroup reports.
120
120
  ## 6. Understand model and display scales
121
121
 
122
122
  Generic effects, MD, SMD, and RD use the identity scale. OR and RR are modeled
123
- on a log scale, so their audit-friendly numeric attributes remain logarithmic.
124
- Use display properties for ratios:
123
+ on a log scale, while `ZCOR` is modeled on Fisher's z scale. Their audit-
124
+ friendly numeric attributes remain on those model scales. Use display
125
+ properties for ratios and back-transformed correlations:
125
126
 
126
127
  ```python
127
128
  result.display_estimate
@@ -130,7 +131,8 @@ result.display_prediction_interval
130
131
  ```
131
132
 
132
133
  The [binary-outcome guide](guides/binary-outcomes.md) includes a complete ratio
133
- example.
134
+ example; the [correlation guide](guides/correlation-outcomes.md) explains the
135
+ Fisher transformation.
134
136
 
135
137
  ## 7. Check sensitivity
136
138
 
@@ -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.