tombolo.plots

  1import re
  2
  3import jsonschema
  4import matplotlib.pyplot as plt
  5
  6from ._utils import _grid, _table, _forest, _barh, _reset_style
  7
  8
  9@_reset_style
 10def ranking_plot(data: dict) -> plt.Figure:
 11    """Horizontal bar chart of treatment rankings.
 12
 13    Parameters:
 14
 15    - `data`: Result dict from `tombolo.nma` or `tombolo.bnma`.
 16
 17    Returns treatments sorted by rank score (P-score for NMA, SUCRA for BNMA).
 18    """
 19    schema = {
 20        "type": "object",
 21        "required": ["ranking"],
 22        "properties": {
 23            "ranking": {
 24                "type": "object",
 25                "additionalProperties": {"type": "number", "minimum": 0, "maximum": 1},
 26            }
 27        },
 28    }
 29    jsonschema.validate(instance=data, schema=schema)
 30    return _barh(data["ranking"])
 31
 32
 33@_reset_style
 34def league_table(data: dict) -> plt.Figure:
 35    """Grid of pairwise treatment comparisons.
 36
 37    Parameters:
 38
 39    - `data`: Result dict from `tombolo.nma` or `tombolo.bnma`.
 40
 41    Each cell shows the mean difference and confidence (or credible) interval for the row
 42    treatment relative to the column treatment. The contrast is row minus column. Diagonal
 43    cells show the treatment name. P-values are included for NMA results.
 44    """
 45    matrix = {
 46        "type": "object",
 47        "additionalProperties": {
 48            "type": "object",
 49            "additionalProperties": {"type": ["number", "null"]},
 50        },
 51    }
 52
 53    schema = {
 54        "type": "object",
 55        "required": ["league"],
 56        "properties": {
 57            "league": {
 58                "type": "object",
 59                "required": ["md", "lower", "upper"],
 60                "properties": {
 61                    "md": matrix,
 62                    "lower": matrix,
 63                    "upper": matrix,
 64                    "pval": matrix,
 65                },
 66            }
 67        },
 68    }
 69
 70    jsonschema.validate(instance=data, schema=schema)
 71    return _grid(data["league"])
 72
 73
 74@_reset_style
 75def heterogeneity_table(data: dict) -> plt.Figure:
 76    """Summary table of heterogeneity statistics.
 77
 78    Parameters:
 79
 80    - `data`: Result dict from `tombolo.nma` or `tombolo.bnma`.
 81
 82    For NMA results: Q statistic, p-value, I², and τ.
 83    For BNMA results: posterior SD and 95% credible interval.
 84    """
 85    nma_heterogeneity = {
 86        "type": "object",
 87        "required": [
 88            "tau2",
 89            "tau",
 90            "i2",
 91            "i2_lower",
 92            "i2_upper",
 93            "q",
 94            "q_df",
 95            "q_pval",
 96        ],
 97        "properties": {
 98            "tau2": {"type": "number", "minimum": 0},
 99            "tau": {"type": "number", "minimum": 0},
100            "i2": {"type": "number", "minimum": 0, "maximum": 1},
101            "i2_lower": {"type": "number", "minimum": 0, "maximum": 1},
102            "i2_upper": {"type": "number", "minimum": 0, "maximum": 1},
103            "q": {"type": "number", "minimum": 0},
104            "q_df": {"type": "integer", "minimum": 0},
105            "q_pval": {"type": "number", "minimum": 0, "maximum": 1},
106        },
107    }
108
109    bnma_heterogeneity = {
110        "type": "object",
111        "required": ["sd", "sd_lower", "sd_upper"],
112        "properties": {
113            "sd": {"type": "number", "minimum": 0},
114            "sd_lower": {"type": "number", "minimum": 0},
115            "sd_upper": {"type": "number", "minimum": 0},
116        },
117    }
118
119    schema = {
120        "type": "object",
121        "required": ["heterogeneity"],
122        "properties": {
123            "heterogeneity": {"oneOf": [nma_heterogeneity, bnma_heterogeneity]}
124        },
125    }
126
127    jsonschema.validate(instance=data, schema=schema)
128    return _table(data["heterogeneity"])
129
130
131@_reset_style
132def forest_plot(data: dict, reference: str) -> plt.Figure:
133    """Forest plot of all treatments relative to a reference.
134
135    Parameters:
136
137    - `data`: Result dict from `tombolo.nma` or `tombolo.bnma`.
138    - `reference`: Name of the reference treatment. All other treatments are plotted
139      relative to it, sorted by effect size. Non-alphanumeric characters are normalized to underscores.
140
141    Returns mean differences and confidence (or credible) intervals for each treatment
142    versus the reference. P-values are included for NMA results.
143
144    Raises `RuntimeError` if `reference` is not found in the data.
145    """
146    matrix = {
147        "type": "object",
148        "additionalProperties": {
149            "type": "object",
150            "additionalProperties": {"type": ["number", "null"]},
151        },
152    }
153
154    schema = {
155        "type": "object",
156        "required": ["league"],
157        "properties": {
158            "league": {
159                "type": "object",
160                "required": ["md", "lower", "upper"],
161                "properties": {
162                    "md": matrix,
163                    "lower": matrix,
164                    "upper": matrix,
165                    "pval": matrix,
166                },
167            }
168        },
169    }
170
171    jsonschema.validate(instance=data, schema=schema)
172    ref = re.sub(r"[^A-Za-z0-9_]", "_", reference)
173    if ref not in data["league"]["md"]:
174        raise RuntimeError("Missing reference")
175
176    label = "[95% CI]" if "pval" in data["league"] else "[95% CrI]"
177    return _forest(data["league"], ref, interval_label=label)
178
179
180@_reset_style
181def prediction_table(data: dict) -> plt.Figure:
182    """Grid of prediction intervals. Only applicable to NMA results.
183
184    Parameters:
185
186    - `data`: Result dict from `tombolo.nma`.
187
188    Each cell shows the 95% prediction interval for the row treatment relative to the column treatment.
189    """
190    matrix = {
191        "type": "object",
192        "additionalProperties": {
193            "type": "object",
194            "additionalProperties": {"type": ["number", "null"]},
195        },
196    }
197
198    schema = {
199        "type": "object",
200        "required": ["prediction"],
201        "properties": {
202            "prediction": {
203                "type": "object",
204                "required": ["lower", "upper"],
205                "properties": {"lower": matrix, "upper": matrix},
206            }
207        },
208    }
209
210    jsonschema.validate(instance=data, schema=schema)
211    return _grid(data["prediction"])
212
213
214@_reset_style
215def convergence_table(data: dict) -> plt.Figure:
216    """Summary table of MCMC convergence diagnostics. Only applicable to BNMA results.
217
218    Parameters:
219
220    - `data`: Result dict from `tombolo.bnma`.
221
222    Returns R-hat (max), ESS bulk (min), and ESS tail (min) across all model parameters.
223    """
224    schema = {
225        "type": "object",
226        "required": ["convergence"],
227        "properties": {
228            "convergence": {
229                "type": "object",
230                "required": ["rhat_max", "ess_bulk_min", "ess_tail_min"],
231                "properties": {
232                    "rhat_max": {"type": "number"},
233                    "ess_bulk_min": {"type": "number"},
234                    "ess_tail_min": {"type": "number"},
235                },
236            }
237        },
238    }
239    jsonschema.validate(instance=data, schema=schema)
240    return _table(data["convergence"])
def ranking_plot(data: dict) -> matplotlib.figure.Figure:
10@_reset_style
11def ranking_plot(data: dict) -> plt.Figure:
12    """Horizontal bar chart of treatment rankings.
13
14    Parameters:
15
16    - `data`: Result dict from `tombolo.nma` or `tombolo.bnma`.
17
18    Returns treatments sorted by rank score (P-score for NMA, SUCRA for BNMA).
19    """
20    schema = {
21        "type": "object",
22        "required": ["ranking"],
23        "properties": {
24            "ranking": {
25                "type": "object",
26                "additionalProperties": {"type": "number", "minimum": 0, "maximum": 1},
27            }
28        },
29    }
30    jsonschema.validate(instance=data, schema=schema)
31    return _barh(data["ranking"])

Horizontal bar chart of treatment rankings.

Parameters:

Returns treatments sorted by rank score (P-score for NMA, SUCRA for BNMA).

def league_table(data: dict) -> matplotlib.figure.Figure:
34@_reset_style
35def league_table(data: dict) -> plt.Figure:
36    """Grid of pairwise treatment comparisons.
37
38    Parameters:
39
40    - `data`: Result dict from `tombolo.nma` or `tombolo.bnma`.
41
42    Each cell shows the mean difference and confidence (or credible) interval for the row
43    treatment relative to the column treatment. The contrast is row minus column. Diagonal
44    cells show the treatment name. P-values are included for NMA results.
45    """
46    matrix = {
47        "type": "object",
48        "additionalProperties": {
49            "type": "object",
50            "additionalProperties": {"type": ["number", "null"]},
51        },
52    }
53
54    schema = {
55        "type": "object",
56        "required": ["league"],
57        "properties": {
58            "league": {
59                "type": "object",
60                "required": ["md", "lower", "upper"],
61                "properties": {
62                    "md": matrix,
63                    "lower": matrix,
64                    "upper": matrix,
65                    "pval": matrix,
66                },
67            }
68        },
69    }
70
71    jsonschema.validate(instance=data, schema=schema)
72    return _grid(data["league"])

Grid of pairwise treatment comparisons.

Parameters:

Each cell shows the mean difference and confidence (or credible) interval for the row treatment relative to the column treatment. The contrast is row minus column. Diagonal cells show the treatment name. P-values are included for NMA results.

def heterogeneity_table(data: dict) -> matplotlib.figure.Figure:
 75@_reset_style
 76def heterogeneity_table(data: dict) -> plt.Figure:
 77    """Summary table of heterogeneity statistics.
 78
 79    Parameters:
 80
 81    - `data`: Result dict from `tombolo.nma` or `tombolo.bnma`.
 82
 83    For NMA results: Q statistic, p-value, I², and τ.
 84    For BNMA results: posterior SD and 95% credible interval.
 85    """
 86    nma_heterogeneity = {
 87        "type": "object",
 88        "required": [
 89            "tau2",
 90            "tau",
 91            "i2",
 92            "i2_lower",
 93            "i2_upper",
 94            "q",
 95            "q_df",
 96            "q_pval",
 97        ],
 98        "properties": {
 99            "tau2": {"type": "number", "minimum": 0},
100            "tau": {"type": "number", "minimum": 0},
101            "i2": {"type": "number", "minimum": 0, "maximum": 1},
102            "i2_lower": {"type": "number", "minimum": 0, "maximum": 1},
103            "i2_upper": {"type": "number", "minimum": 0, "maximum": 1},
104            "q": {"type": "number", "minimum": 0},
105            "q_df": {"type": "integer", "minimum": 0},
106            "q_pval": {"type": "number", "minimum": 0, "maximum": 1},
107        },
108    }
109
110    bnma_heterogeneity = {
111        "type": "object",
112        "required": ["sd", "sd_lower", "sd_upper"],
113        "properties": {
114            "sd": {"type": "number", "minimum": 0},
115            "sd_lower": {"type": "number", "minimum": 0},
116            "sd_upper": {"type": "number", "minimum": 0},
117        },
118    }
119
120    schema = {
121        "type": "object",
122        "required": ["heterogeneity"],
123        "properties": {
124            "heterogeneity": {"oneOf": [nma_heterogeneity, bnma_heterogeneity]}
125        },
126    }
127
128    jsonschema.validate(instance=data, schema=schema)
129    return _table(data["heterogeneity"])

Summary table of heterogeneity statistics.

Parameters:

For NMA results: Q statistic, p-value, I², and τ. For BNMA results: posterior SD and 95% credible interval.

def forest_plot(data: dict, reference: str) -> matplotlib.figure.Figure:
132@_reset_style
133def forest_plot(data: dict, reference: str) -> plt.Figure:
134    """Forest plot of all treatments relative to a reference.
135
136    Parameters:
137
138    - `data`: Result dict from `tombolo.nma` or `tombolo.bnma`.
139    - `reference`: Name of the reference treatment. All other treatments are plotted
140      relative to it, sorted by effect size. Non-alphanumeric characters are normalized to underscores.
141
142    Returns mean differences and confidence (or credible) intervals for each treatment
143    versus the reference. P-values are included for NMA results.
144
145    Raises `RuntimeError` if `reference` is not found in the data.
146    """
147    matrix = {
148        "type": "object",
149        "additionalProperties": {
150            "type": "object",
151            "additionalProperties": {"type": ["number", "null"]},
152        },
153    }
154
155    schema = {
156        "type": "object",
157        "required": ["league"],
158        "properties": {
159            "league": {
160                "type": "object",
161                "required": ["md", "lower", "upper"],
162                "properties": {
163                    "md": matrix,
164                    "lower": matrix,
165                    "upper": matrix,
166                    "pval": matrix,
167                },
168            }
169        },
170    }
171
172    jsonschema.validate(instance=data, schema=schema)
173    ref = re.sub(r"[^A-Za-z0-9_]", "_", reference)
174    if ref not in data["league"]["md"]:
175        raise RuntimeError("Missing reference")
176
177    label = "[95% CI]" if "pval" in data["league"] else "[95% CrI]"
178    return _forest(data["league"], ref, interval_label=label)

Forest plot of all treatments relative to a reference.

Parameters:

  • data: Result dict from tombolo.nma or tombolo.bnma.
  • reference: Name of the reference treatment. All other treatments are plotted relative to it, sorted by effect size. Non-alphanumeric characters are normalized to underscores.

Returns mean differences and confidence (or credible) intervals for each treatment versus the reference. P-values are included for NMA results.

Raises RuntimeError if reference is not found in the data.

def prediction_table(data: dict) -> matplotlib.figure.Figure:
181@_reset_style
182def prediction_table(data: dict) -> plt.Figure:
183    """Grid of prediction intervals. Only applicable to NMA results.
184
185    Parameters:
186
187    - `data`: Result dict from `tombolo.nma`.
188
189    Each cell shows the 95% prediction interval for the row treatment relative to the column treatment.
190    """
191    matrix = {
192        "type": "object",
193        "additionalProperties": {
194            "type": "object",
195            "additionalProperties": {"type": ["number", "null"]},
196        },
197    }
198
199    schema = {
200        "type": "object",
201        "required": ["prediction"],
202        "properties": {
203            "prediction": {
204                "type": "object",
205                "required": ["lower", "upper"],
206                "properties": {"lower": matrix, "upper": matrix},
207            }
208        },
209    }
210
211    jsonschema.validate(instance=data, schema=schema)
212    return _grid(data["prediction"])

Grid of prediction intervals. Only applicable to NMA results.

Parameters:

Each cell shows the 95% prediction interval for the row treatment relative to the column treatment.

def convergence_table(data: dict) -> matplotlib.figure.Figure:
215@_reset_style
216def convergence_table(data: dict) -> plt.Figure:
217    """Summary table of MCMC convergence diagnostics. Only applicable to BNMA results.
218
219    Parameters:
220
221    - `data`: Result dict from `tombolo.bnma`.
222
223    Returns R-hat (max), ESS bulk (min), and ESS tail (min) across all model parameters.
224    """
225    schema = {
226        "type": "object",
227        "required": ["convergence"],
228        "properties": {
229            "convergence": {
230                "type": "object",
231                "required": ["rhat_max", "ess_bulk_min", "ess_tail_min"],
232                "properties": {
233                    "rhat_max": {"type": "number"},
234                    "ess_bulk_min": {"type": "number"},
235                    "ess_tail_min": {"type": "number"},
236                },
237            }
238        },
239    }
240    jsonschema.validate(instance=data, schema=schema)
241    return _table(data["convergence"])

Summary table of MCMC convergence diagnostics. Only applicable to BNMA results.

Parameters:

Returns R-hat (max), ESS bulk (min), and ESS tail (min) across all model parameters.