yuclid 0.1.0__py3-none-any.whl

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.
yuclid/spread.py ADDED
@@ -0,0 +1,152 @@
1
+ from yuclid.log import report, LogLevel
2
+ from scipy.stats import norm
3
+ import seaborn as sns
4
+ import pandas as pd
5
+ import numpy as np
6
+ import re
7
+
8
+
9
+ available_parametrized = {"sd", "pi", "rsd"}
10
+ available_non_parametrized = {
11
+ "mad",
12
+ "range",
13
+ "iqr",
14
+ }
15
+ available = [f"{name},N" for name in available_parametrized]
16
+ available += [name for name in available_non_parametrized]
17
+
18
+
19
+ def mad(y):
20
+ if not isinstance(y, np.ndarray):
21
+ y = np.array(y)
22
+ return np.median(np.abs(y - np.median(y)))
23
+
24
+
25
+ def lower(spread_measure):
26
+ n = re.search(r"\d+(\.\d+)?", spread_measure)
27
+ if spread_measure.startswith("sd"):
28
+ coeff = float(n.group())
29
+ return lambda y: y.mean() - coeff * y.std()
30
+ elif spread_measure.startswith("pi"):
31
+ p = float(n.group()) / 100.0
32
+ return lambda y: np.quantile(y, (1 - p) / 2)
33
+ elif spread_measure.startswith("rsd"):
34
+ coeff = float(n.group())
35
+ return lambda y: y.mean() - coeff * (1 / norm.ppf(0.75)) * mad(y)
36
+ elif spread_measure == "mad":
37
+ return lambda y: np.median(y) - mad(y)
38
+ elif spread_measure == "range":
39
+ return lambda y: y.min()
40
+ elif spread_measure == "iqr":
41
+ return lambda y: np.quantile(y, 0.25)
42
+
43
+
44
+ def upper(spread_measure):
45
+ n = re.search(r"\d+(\.\d+)?", spread_measure)
46
+ if spread_measure.startswith("sd"):
47
+ coeff = float(n.group())
48
+ return lambda y: y.mean() + coeff * y.std()
49
+ elif spread_measure.startswith("pi"):
50
+ p = float(n.group()) / 100.0
51
+ return lambda y: np.quantile(y, (1 + p) / 2)
52
+ elif spread_measure.startswith("rsd"):
53
+ coeff = float(n.group())
54
+ return lambda y: y.mean() + coeff * (1 / norm.ppf(0.75)) * mad(y)
55
+ elif spread_measure == "mad":
56
+ return lambda y: np.median(y) + mad(y)
57
+ elif spread_measure == "range":
58
+ return lambda y: y.max()
59
+ elif spread_measure == "iqr":
60
+ return lambda y: np.quantile(y, 0.75)
61
+
62
+
63
+ def assert_validity(spread_measure):
64
+ if not isinstance(spread_measure, str):
65
+ report(LogLevel.ERROR, "spread_measure must be a string")
66
+ return False
67
+ parts = spread_measure.split(",")
68
+ if parts[0] not in available_non_parametrized.union(available_parametrized):
69
+ report(
70
+ LogLevel.ERROR,
71
+ f"spread_measure '{spread_measure}' is not available",
72
+ hint="use one of: " + " - ".join(available),
73
+ )
74
+ return False
75
+ if parts[0] in available_parametrized:
76
+ if len(parts) < 2:
77
+ report(
78
+ LogLevel.ERROR,
79
+ f"spread_measure '{spread_measure}' is missing a parameter",
80
+ hint=f"try '{spread_measure},N' where N is a number",
81
+ )
82
+ return False
83
+ n = float(parts[1])
84
+ if parts[0] == "pi" and n < 0 or n > 100:
85
+ report(
86
+ LogLevel.ERROR,
87
+ "parameter for spread_measure 'pi' must be in [0, 100]",
88
+ )
89
+ return False
90
+ if parts[0] in ["sd", "rsd"] and n <= 0:
91
+ report(
92
+ LogLevel.ERROR,
93
+ "parameter for spread_measure 'sd' and 'rsd' must be positive",
94
+ )
95
+ return False
96
+ if parts[0] in available_non_parametrized:
97
+ if len(parts) != 1:
98
+ report(
99
+ LogLevel.ERROR,
100
+ f"spread_measure '{spread_measure}' must not have any parameters",
101
+ )
102
+ return False
103
+ return True
104
+
105
+
106
+ def draw(
107
+ ax, spread_measures, df, x, y, z=None, colors=None, palette=None, style="area"
108
+ ):
109
+ alphas = {
110
+ "area": np.linspace(0.15, 0.05, len(spread_measures)),
111
+ "bar": np.linspace(0.30, 0.10, len(spread_measures)),
112
+ }[style]
113
+
114
+ x_dom = df[x].unique()
115
+ z_dom = df[z].unique()
116
+ groups = df.groupby([z, x])[y]
117
+
118
+ if isinstance(palette, str):
119
+ colors = sns.color_palette(palette)
120
+ palette = None
121
+
122
+ if colors is None and palette is None:
123
+ raise Exception("Missing color and palette")
124
+
125
+ for i, sm in enumerate(spread_measures):
126
+ ys_lower = groups.apply(lower(sm))
127
+ ys_upper = groups.apply(upper(sm))
128
+ for j, z_val in enumerate(z_dom):
129
+ if colors is not None:
130
+ color = colors[j % len(colors)]
131
+ else:
132
+ color = palette[z_val]
133
+ y_lower = ys_lower.xs(z_val)
134
+ y_upper = ys_upper.xs(z_val)
135
+ if style == "area":
136
+ ax.fill_between(
137
+ x_dom,
138
+ y_lower,
139
+ y_upper,
140
+ interpolate=True,
141
+ color=color,
142
+ alpha=alphas[i],
143
+ )
144
+ elif style == "bar":
145
+ ax.vlines(
146
+ x=x,
147
+ ymin=y_lower,
148
+ ymax=y_upper,
149
+ color=color,
150
+ alpha=alphas[i],
151
+ linewidth=4,
152
+ )
@@ -0,0 +1,15 @@
1
+ Metadata-Version: 2.4
2
+ Name: yuclid
3
+ Version: 0.1.0
4
+ Summary: A Python project.
5
+ Author-email: Your Name <your.email@example.com>
6
+ Project-URL: Homepage, https://github.com/fsossai/yuclid
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+
10
+ # Yuclid
11
+
12
+ *Combinatorially explode your experiments*
13
+
14
+ - **`yuclid run`**: Run experiments with with all combination of registered parameters.
15
+ - **`yuclid plot`**: Interactively visualizes the results produced by `yuclid run`.
@@ -0,0 +1,11 @@
1
+ yuclid/__init__.py,sha256=Pru0BlFBASFCFo7McHdohtKkUtgMPDwbGfyUZlE2_Vw,21
2
+ yuclid/cli.py,sha256=l5WUY6Q6nwg7WRrAAPf5uaspG9zrEPE9BA9v3eYI_vE,6410
3
+ yuclid/log.py,sha256=GR_FVfNroumuonKguAPd6H1rKjxJKRc8tAS2sVNTbzE,1655
4
+ yuclid/plot.py,sha256=RV_bgkFDpOGxw7ankW7QsnBsyrholBtYKKj9jUtBAyM,30836
5
+ yuclid/run.py,sha256=V3tcFHWyXH2fs6aFR6vJi2c5DhDb-zDXJMWp-xUi8DM,44048
6
+ yuclid/spread.py,sha256=4Ci3nsu8n_dhG-AK2IWHKRElQ8oaGdw14LrgNu79biM,4938
7
+ yuclid-0.1.0.dist-info/METADATA,sha256=umoUK82Bh__fTcoLiFS64thJ6d5brdDWHWmkozzA9p8,473
8
+ yuclid-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
9
+ yuclid-0.1.0.dist-info/entry_points.txt,sha256=2AvTtyt5iBnjr6HnjqH_3PeSoq9UzIbT92qivmEbOYA,43
10
+ yuclid-0.1.0.dist-info/top_level.txt,sha256=cL5mb4h_4etwTsqhPvSnoVBXImIzPFGd3rINV1nEjPo,7
11
+ yuclid-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ yuclid = yuclid.cli:main
@@ -0,0 +1 @@
1
+ yuclid