Hyperiso 1.0.3
Modular flavour-physics calculations, Wilson coefficients and statistical inference
Loading...
Searching...
No Matches
example_plot_copule.py
Go to the documentation of this file.
1from __future__ import annotations
2
3import os
4import math
5from typing import Any
6
7import numpy as np
8import matplotlib.pyplot as plt
9from statistics import NormalDist
10
11from pyhyperiso.core.Math.RealMatrix import Matrix
12
13
14from pyhyperiso.core.Statistic.Copula import CopulaKind
15
16from pyhyperiso.core.Statistic.Copula import CopulaFactoryWrapper as CF
17
18from pyhyperiso.core.Statistic.CopulaConfig import GaussianCopulaConfigPy as GaussianCfg
19
20from pyhyperiso.core.Statistic.CopulaConfig import StudentTCopulaConfigPy as StudentTCfg
21
22
23def ar1_corr(d: int, rho: float) -> Matrix:
24 """R_ij = rho^{|i-j|}. SPD si |rho|<1."""
25 if not (-0.999 < rho < 0.999):
26 raise ValueError("rho doit être dans (-1,1) pour une corrélation AR(1) SPD.")
27 R = [[(rho ** abs(i - j)) for j in range(d)] for i in range(d)]
28 return Matrix(R)
29
30
31def _rankdata(x: np.ndarray) -> np.ndarray:
32 """Ranks 1..n (mid-rank approx via argsort; suffisant pour tests visuels)."""
33 order = np.argsort(x)
34 ranks = np.empty_like(order, dtype=float)
35 ranks[order] = np.arange(1, len(x) + 1, dtype=float)
36 return ranks
37
38
39def spearman_corr(U: np.ndarray) -> np.ndarray:
40 """Corrélation de Spearman via corrcoef des rangs."""
41 R = np.vstack([_rankdata(U[:, i]) for i in range(U.shape[1])]).T
42 return np.corrcoef(R, rowvar=False)
43
44
45def gaussianize(U: np.ndarray) -> np.ndarray:
46 """Transforme U~(0,1) vers Z~N(0,1) via invCDF (sans scipy)."""
47 nd = NormalDist()
48 eps = 1e-12
49 Uc = np.clip(U, eps, 1 - eps)
50 inv = np.vectorize(nd.inv_cdf, otypes=[float])
51 Z = inv(Uc)
52 return Z
53
54
55def corrcoef_Z(U: np.ndarray) -> np.ndarray:
56 Z = gaussianize(U)
57 return np.corrcoef(Z, rowvar=False)
58
59
60def ensure_dir(path: str) -> None:
61 os.makedirs(path, exist_ok=True)
62
63
65 U: np.ndarray, title: str, outpath: str, use_hist2d: bool = False
66) -> None:
67 u1, u2 = U[:, 0], U[:, 1]
68 plt.figure(figsize=(6.8, 6.4))
69 if use_hist2d:
70 plt.hist2d(u1, u2, bins=70, density=True)
71 plt.colorbar(label="density")
72 else:
73 plt.plot(u1, u2, linestyle="none", marker=".", markersize=2, alpha=0.25)
74
75 plt.plot([0, 1], [0, 1], linestyle="--", linewidth=1.2) # diagonal
76 plt.title(title)
77 plt.xlabel("u1")
78 plt.ylabel("u2")
79 plt.xlim(0, 1)
80 plt.ylim(0, 1)
81 plt.grid(True, alpha=0.25)
82 plt.tight_layout()
83 plt.savefig(outpath, dpi=200)
84 plt.close()
85
86
87def plot_marginal_uniformity(U: np.ndarray, title_prefix: str, outdir: str) -> None:
88 d = U.shape[1]
89 for j in range(d):
90 plt.figure(figsize=(7.6, 4.6))
91 plt.hist(U[:, j], bins=50, density=True, alpha=0.45, label=f"u{j + 1}")
92
93 plt.plot([0, 1], [1, 1], linestyle="--", linewidth=1.6, label="Uniform(0,1) density")
94 plt.title(f"{title_prefix} — Marginal uniformity (dim {j + 1})")
95 plt.xlabel(f"u{j + 1}")
96 plt.ylabel("density")
97 plt.xlim(0, 1)
98 plt.ylim(bottom=0)
99 plt.grid(True, alpha=0.25)
100 plt.legend(frameon=True)
101 plt.tight_layout()
102 plt.savefig(os.path.join(outdir, f"{title_prefix}_marginal_u{j + 1}.png"), dpi=200)
103 plt.close()
104
105
106def plot_corr_heatmap(M: np.ndarray, title: str, outpath: str) -> None:
107 plt.figure(figsize=(6.8, 6.0))
108 im = plt.imshow(M, vmin=-1, vmax=1, interpolation="nearest")
109 plt.colorbar(im, label="correlation")
110 plt.title(title)
111 plt.xlabel("dim")
112 plt.ylabel("dim")
113
114 n = M.shape[0]
115 for i in range(n):
116 for j in range(n):
117 plt.text(j, i, f"{M[i, j]:.2f}", ha="center", va="center", fontsize=8)
118
119 plt.tight_layout()
120 plt.savefig(outpath, dpi=200)
121 plt.close()
122
123
124def plot_density_surface_2d(copula: Any, title: str, outpath: str, grid: int = 90) -> None:
125 """Visualise exp(log_density(u)) sur [0,1]^2. (Seulement 2D)."""
126 eps = 1e-4
127 xs = np.linspace(eps, 1 - eps, grid)
128 ys = np.linspace(eps, 1 - eps, grid)
129 D = np.empty((grid, grid), dtype=float)
130
131 for i, y in enumerate(ys):
132 row = []
133 for x in xs:
134 ld = float(copula.log_density([float(x), float(y)]))
135 row.append(math.exp(ld))
136 D[i, :] = row
137
138 approx_integral = float(D.mean())
139 plt.figure(figsize=(7.0, 6.0))
140 im = plt.imshow(D, origin="lower", extent=[0, 1, 0, 1], interpolation="nearest")
141 plt.colorbar(im, label="density c(u)")
142 plt.title(f"{title}\n(mean density ≈ {approx_integral:.3f} ; should be ~1 in 2D)")
143 plt.xlabel("u1")
144 plt.ylabel("u2")
145 plt.grid(False)
146 plt.tight_layout()
147 plt.savefig(outpath, dpi=200)
148 plt.close()
149
150
151def make_gaussian_copula(R: Matrix, seed: int):
152 cfg = GaussianCfg(R=R)
153 if hasattr(CF, "gaussian"):
154 return CF.gaussian(R, seed=seed)
155 if hasattr(CF, "create"):
156 return CF.create(CopulaKind.GAUSSIAN, cfg, seed=seed)
157 return CF.create_gaussian(cfg, seed)
158
159
160def make_student_t_copula(R: Matrix, nu: int, seed: int):
161 cfg = StudentTCfg(R=R, nu=int(nu))
162 if hasattr(CF, "student_t"):
163 return CF.student_t(R, nu=nu, seed=seed)
164 if hasattr(CF, "create"):
165 return CF.create(CopulaKind.STUDENT_T, cfg, seed=seed)
166 return CF.create_student_t(cfg, seed)
167
168
170 outdir: str = "copula_plots",
171 seed: int = 123,
172 n: int = 12000,
173 d: int = 3,
174 rho: float = 0.65,
175 nu: int = 6,
176) -> None:
177 ensure_dir(outdir)
178
179 R = ar1_corr(d, rho)
180
181 cop_gauss = make_gaussian_copula(R, seed=seed)
182 cop_t = make_student_t_copula(R, nu=nu, seed=seed)
183
184 specs = [
185 ("GaussianCopula", cop_gauss),
186 (f"StudentTCopula(nu={nu})", cop_t),
187 ]
188
189 for name, cop in specs:
190 U = np.array(cop.sample_u(int(n)), dtype=float) # shape (n, d)
191
192 if d >= 2:
194 U[:, :2],
195 title=f"{name} — samples in (0,1)^2 (projection)",
196 outpath=os.path.join(outdir, f"{name}_hist2d.png"),
197 use_hist2d=False,
198 )
199
200 if d == 2:
202 cop,
203 title=f"{name} — density surface in (0,1)^2",
204 outpath=os.path.join(outdir, f"{name}_density_surface.png"),
205 grid=90,
206 )
207
208 plot_marginal_uniformity(U, title_prefix=name, outdir=outdir)
209
210 S = spearman_corr(U)
211 C = corrcoef_Z(U)
212
214 S,
215 title=f"{name} — Spearman corr (ranks of U)",
216 outpath=os.path.join(outdir, f"{name}_spearman.png"),
217 )
219 C,
220 title=f"{name} — Corr of Z = Phi^-1(U) (compare to target R)",
221 outpath=os.path.join(outdir, f"{name}_corr_gaussianized.png"),
222 )
223
224 print(f"[OK] Plots saved in: {outdir}/")
225
226
227if __name__ == "__main__":
228 main(
229 outdir="copula_plots",
230 seed=123,
231 n=12000,
232 d=3,
233 rho=0.65,
234 nu=6,
235 )
None plot_density_surface_2d(Any copula, str title, str outpath, int grid=90)
np.ndarray gaussianize(np.ndarray U)
np.ndarray corrcoef_Z(np.ndarray U)
make_gaussian_copula(Matrix R, int seed)
Matrix ar1_corr(int d, float rho)
np.ndarray spearman_corr(np.ndarray U)
None plot_scatter_or_hist2d(np.ndarray U, str title, str outpath, bool use_hist2d=False)
None plot_marginal_uniformity(np.ndarray U, str title_prefix, str outdir)
make_student_t_copula(Matrix R, int nu, int seed)
np.ndarray _rankdata(np.ndarray x)
None plot_corr_heatmap(np.ndarray M, str title, str outpath)