bs-python-utils 0.8.3__py3-none-any.whl → 0.9__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.
- bs_python_utils/bivariate_quantiles.py +120 -188
- bs_python_utils/bs_logging.py +1 -1
- {bs_python_utils-0.8.3.dist-info → bs_python_utils-0.9.dist-info}/METADATA +5 -1
- {bs_python_utils-0.8.3.dist-info → bs_python_utils-0.9.dist-info}/RECORD +7 -7
- {bs_python_utils-0.8.3.dist-info → bs_python_utils-0.9.dist-info}/WHEEL +1 -1
- {bs_python_utils-0.8.3.dist-info → bs_python_utils-0.9.dist-info}/licenses/LICENSE +0 -0
- {bs_python_utils-0.8.3.dist-info → bs_python_utils-0.9.dist-info}/top_level.txt +0 -0
|
@@ -10,11 +10,10 @@ Note:
|
|
|
10
10
|
|
|
11
11
|
The sequence of steps is as follows:
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* to obtain the $(u_1,u_2)$ quantiles for $(u_1, u_2)\\in [0,1]$, run
|
|
13
|
+
1. optimize the weights: `v = solve_for_v(y, n_nodes)` given `n_nodes` Chebyshev nodes for numerical integration
|
|
14
|
+
2. to obtain the $(u_1,u_2)$ quantiles for $(u_1, u_2)\\in [0,1]$, run
|
|
16
15
|
`qtiles_y = bivariate_quantiles_v(y, v, u1, u2)`
|
|
17
|
-
|
|
16
|
+
3. to compute the vector ranks for all points in the sample (the barycenters
|
|
18
17
|
of the cells in the power diagram):
|
|
19
18
|
`ranks_y = bivariate_ranks_v(y, v, n_nodes)`
|
|
20
19
|
|
|
@@ -33,200 +32,131 @@ from bs_python_utils.bsutils import bs_error_abort
|
|
|
33
32
|
from bs_python_utils.chebyshev import Interval, cheb_get_nodes_1d
|
|
34
33
|
|
|
35
34
|
|
|
36
|
-
def
|
|
37
|
-
"""Build the `A` and `
|
|
38
|
-
y1 =
|
|
35
|
+
def _compute_ad(y: np.ndarray) -> TwoArrays:
|
|
36
|
+
"""Build the `A` and `dy2` matrices used in the dual optimisation."""
|
|
37
|
+
y1 = y[:, 0]
|
|
39
38
|
dy1 = np.subtract.outer(y1, y1)
|
|
40
|
-
y2 =
|
|
39
|
+
y2 = y[:, 1]
|
|
41
40
|
dy2 = np.subtract.outer(y2, y2)
|
|
42
41
|
np.fill_diagonal(dy2, 1.0)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
b_mat = np.divide(dv.T, dy2, where=np.abs(dy2) > 1e-12)
|
|
47
|
-
a_mat = np.nan_to_num(a_mat, nan=0.0, posinf=0.0, neginf=0.0)
|
|
48
|
-
b_mat = np.nan_to_num(b_mat, nan=0.0, posinf=0.0, neginf=0.0)
|
|
49
|
-
return a_mat, b_mat
|
|
42
|
+
dy2 = dy2.T
|
|
43
|
+
a_mat = np.divide(dy1, dy2)
|
|
44
|
+
return a_mat, dy2
|
|
50
45
|
|
|
51
46
|
|
|
52
|
-
def
|
|
53
|
-
|
|
47
|
+
def _compute_m_M(
|
|
48
|
+
v: np.ndarray, a_mat: np.ndarray, dy2: np.ndarray, tau1_nodes: np.ndarray
|
|
54
49
|
) -> TwoArrays:
|
|
55
|
-
"""
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
else:
|
|
78
|
-
right_bound = np.ones(m)
|
|
79
|
-
elif k == n - 1:
|
|
80
|
-
a_left = a_mat[-1, :-1]
|
|
81
|
-
b_left = b_mat[-1, :-1]
|
|
82
|
-
if a_left.size:
|
|
83
|
-
left_bound = np.max(np.outer(u1, a_left) - b_left, 1)
|
|
84
|
-
else:
|
|
85
|
-
left_bound = np.zeros(m)
|
|
86
|
-
right_bound = np.ones(m)
|
|
87
|
-
else:
|
|
88
|
-
bs_error_abort(f"{k=} is not compatible with {n=}")
|
|
89
|
-
left_bound = np.clip(left_bound, 0.0, 1.0)
|
|
90
|
-
right_bound = np.clip(right_bound, 0.0, 1.0)
|
|
91
|
-
|
|
92
|
-
return left_bound, right_bound
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
def bivariate_quantiles_v(y: np.ndarray, u: np.ndarray, v: np.ndarray) -> np.ndarray:
|
|
50
|
+
"""Build the `m` and `M` matrices used in the dual optimisation."""
|
|
51
|
+
dv = np.subtract.outer(v, v)
|
|
52
|
+
b_mat = dv / dy2
|
|
53
|
+
np.fill_diagonal(dy2, 0.0)
|
|
54
|
+
EPS = 1e-12
|
|
55
|
+
maskp = dy2 < EPS
|
|
56
|
+
maskm = dy2 > -EPS
|
|
57
|
+
n, n_nodes = v.size, tau1_nodes.size
|
|
58
|
+
m_low = np.empty((n, n_nodes))
|
|
59
|
+
m_high = np.empty((n, n_nodes))
|
|
60
|
+
for i, tau1 in enumerate(tau1_nodes):
|
|
61
|
+
f_mat = tau1 * a_mat - b_mat
|
|
62
|
+
f_matp = f_mat.copy()
|
|
63
|
+
f_matm = f_mat.copy()
|
|
64
|
+
f_matp[maskp] = 1
|
|
65
|
+
f_matm[maskm] = 0
|
|
66
|
+
m_low[:, i] = np.max(f_matm, axis=1)
|
|
67
|
+
m_high[:, i] = np.min(f_matp, axis=1)
|
|
68
|
+
return np.clip(m_low, 0.0, 1.0), np.clip(m_high, 0.0, 1.0)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def bivariate_quantiles_v(y: np.ndarray, tau: np.ndarray, v: np.ndarray) -> np.ndarray:
|
|
96
72
|
"""Evaluate vector quantiles for a given set of dual weights.
|
|
97
73
|
|
|
98
74
|
Args:
|
|
99
75
|
y: Observations with shape ``(n, 2)``.
|
|
100
|
-
|
|
76
|
+
tau: Evaluation points in ``[0, 1]^2`` (shape ``(m, 2)``).
|
|
101
77
|
v: Dual weights solving the optimal transport problem (length ``n``).
|
|
102
78
|
|
|
103
79
|
Returns:
|
|
104
80
|
Array of quantile locations with shape ``(m, 2)``.
|
|
105
81
|
"""
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
m = u.shape[0]
|
|
110
|
-
q = np.empty((m, 2))
|
|
111
|
-
block = max(1, min(m, 5_000))
|
|
112
|
-
for start in range(0, m, block):
|
|
113
|
-
stop = min(start + block, m)
|
|
114
|
-
chunk = u[start:stop]
|
|
115
|
-
net_val = chunk @ y.T - v
|
|
116
|
-
k_max = np.argmax(net_val, axis=1)
|
|
117
|
-
q[start:stop] = y[k_max]
|
|
82
|
+
if tau.shape[1] != 2:
|
|
83
|
+
bs_error_abort("tau must have two columns")
|
|
84
|
+
q = y[np.argmax(tau @ y.T - v, axis=1), :]
|
|
118
85
|
return cast(np.ndarray, q)
|
|
119
86
|
|
|
120
87
|
|
|
121
|
-
def bivariate_ranks_v(
|
|
122
|
-
y: np.ndarray, v: np.ndarray, n_nodes: int = 32, presorted: bool = False
|
|
123
|
-
) -> np.ndarray:
|
|
124
|
-
"""Compute the barycentric ranks of each observation given optimal weights.
|
|
125
|
-
|
|
126
|
-
Args:
|
|
127
|
-
y: Observations with shape ``(n, 2)``.
|
|
128
|
-
v: Dual weights returned by ``solve_for_v_``.
|
|
129
|
-
n_nodes: Number of Chebyshev nodes used in the quadrature.
|
|
130
|
-
presorted: Set to ``True`` when ``y``/``v`` are pre-sorted by the
|
|
131
|
-
second coordinate.
|
|
132
|
-
|
|
133
|
-
Returns:
|
|
134
|
-
Array of average ranks (shape ``(n, 2)``) with ``nan`` for zero-mass cells.
|
|
135
|
-
"""
|
|
136
|
-
n, d = y.shape
|
|
137
|
-
|
|
138
|
-
if d != 2:
|
|
139
|
-
bs_error_abort(f"only works for 2-dimensional y, not for {d}")
|
|
140
|
-
|
|
141
|
-
interval01 = Interval(0.0, 1.0)
|
|
142
|
-
u1_nodes, u1_weights = cheb_get_nodes_1d(interval01, n_nodes)
|
|
143
|
-
|
|
144
|
-
if presorted:
|
|
145
|
-
sort_order = np.arange(n)
|
|
146
|
-
y_sorted = y
|
|
147
|
-
v_sorted = v
|
|
148
|
-
else:
|
|
149
|
-
sort_order = np.argsort(y[:, 1])
|
|
150
|
-
y_sorted = y[sort_order, :]
|
|
151
|
-
v_sorted = v[sort_order]
|
|
152
|
-
|
|
153
|
-
a_mat, b_mat = _compute_ab(y_sorted, v_sorted)
|
|
154
|
-
|
|
155
|
-
average_ranks = np.zeros((n, 2))
|
|
156
|
-
|
|
157
|
-
for k in range(n):
|
|
158
|
-
left_bounds, right_bounds = _compute_u2_bounds(k, u1_nodes, a_mat, b_mat)
|
|
159
|
-
pos_diffs = np.maximum(right_bounds - left_bounds, 0.0)
|
|
160
|
-
pos_diffs_sq = np.maximum(
|
|
161
|
-
right_bounds * right_bounds - left_bounds * left_bounds, 0.0
|
|
162
|
-
)
|
|
163
|
-
prob_k = pos_diffs @ u1_weights
|
|
164
|
-
if prob_k <= 1e-12:
|
|
165
|
-
average_ranks[sort_order[k], :] = np.array([np.nan, np.nan])
|
|
166
|
-
continue
|
|
167
|
-
average_ranks[sort_order[k], 0] = ((u1_nodes * pos_diffs) @ u1_weights) / prob_k
|
|
168
|
-
average_ranks[sort_order[k], 1] = ((pos_diffs_sq @ u1_weights) / 2.0) / prob_k
|
|
169
|
-
|
|
170
|
-
return average_ranks
|
|
171
|
-
|
|
172
|
-
|
|
173
88
|
def _objgrad(
|
|
174
|
-
|
|
175
|
-
) -> float | tuple[float, np.ndarray]:
|
|
176
|
-
"""computes the expectation of $\\psi(U, v)$ and perhaps its gradient wrt `v`
|
|
89
|
+
v: np.ndarray, args: list, gr: bool = False
|
|
90
|
+
) -> float | tuple[float, np.ndarray, np.ndarray]:
|
|
91
|
+
"""computes the expectation of $\\psi(U, v)$ and perhaps its gradient wrt `v` or the bivariate ranks
|
|
177
92
|
|
|
178
93
|
Args:
|
|
179
|
-
|
|
180
|
-
args: a list of other arguments `[
|
|
181
|
-
gr: if `
|
|
94
|
+
v: an `(n-1)`-vector
|
|
95
|
+
args: a list of other arguments `[y, a_mat, dy2, tau1_nodes, tau1_weights, verbose]`
|
|
96
|
+
gr: if `False`, we only return the value of the objective function
|
|
97
|
+
if `True`, we also return the gradient and the bivariate ranks
|
|
182
98
|
|
|
183
99
|
Returns:
|
|
184
|
-
the value of the expectation and perhaps its gradient
|
|
100
|
+
the value of the expectation and perhaps its gradient and the bivariate ranks
|
|
185
101
|
"""
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
102
|
+
y = args[0]
|
|
103
|
+
y1 = y[:, 0]
|
|
104
|
+
y2 = y[:, 1]
|
|
105
|
+
n = y.shape[0]
|
|
106
|
+
a_mat, dy2 = args[1], args[2]
|
|
107
|
+
tau1_nodes = args[3]
|
|
108
|
+
tau1_weights = args[4]
|
|
109
|
+
vs1 = np.append(v, -np.sum(v))
|
|
110
|
+
m, M = _compute_m_M(vs1, a_mat, dy2, tau1_nodes)
|
|
111
|
+
# print(f"m is {m}")
|
|
112
|
+
# print(f"M is {M}")
|
|
113
|
+
# import sys
|
|
114
|
+
|
|
115
|
+
# sys.exit(1)
|
|
116
|
+
|
|
117
|
+
EPS = 1e-12
|
|
193
118
|
obj_val = 0.0
|
|
194
119
|
probs = np.zeros(n)
|
|
120
|
+
bivrank = np.zeros((n, 2))
|
|
195
121
|
for k in range(n):
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
|
|
122
|
+
Mk = M[k, :]
|
|
123
|
+
mk = m[k, :]
|
|
124
|
+
pos_diffs = np.maximum(Mk - mk, 0.0)
|
|
125
|
+
# print(f"pos_diffs for k={k} are {pos_diffs}")
|
|
126
|
+
pos_diffs_sq = np.maximum(Mk * Mk - mk * mk, 0.0)
|
|
127
|
+
probs[k] = pos_diffs @ tau1_weights
|
|
128
|
+
# print(f"probs[{k}] = {probs[k]}")
|
|
129
|
+
factor1 = (tau1_nodes * pos_diffs) @ tau1_weights
|
|
130
|
+
factor2 = (pos_diffs_sq @ tau1_weights) / 2.0
|
|
131
|
+
obj_val += y1[k] * factor1 + y2[k] * factor2 - vs1[k] * probs[k]
|
|
132
|
+
if probs[k] > EPS:
|
|
133
|
+
bivrank[k, 0] = factor1 / probs[k]
|
|
134
|
+
bivrank[k, 1] = factor2 / probs[k]
|
|
135
|
+
|
|
136
|
+
# print(f"{np.min(probs)=}")
|
|
207
137
|
|
|
208
138
|
if gr:
|
|
209
139
|
grad_val = probs[-1] - probs[:-1]
|
|
210
|
-
return obj_val, grad_val
|
|
140
|
+
return obj_val, grad_val, bivrank
|
|
211
141
|
else:
|
|
212
|
-
return
|
|
142
|
+
return obj_val
|
|
213
143
|
|
|
214
144
|
|
|
215
|
-
def _obj(
|
|
216
|
-
return _objgrad(
|
|
145
|
+
def _obj(v: np.ndarray, args: list):
|
|
146
|
+
return _objgrad(v, args)
|
|
217
147
|
|
|
218
148
|
|
|
219
|
-
def _grad(
|
|
220
|
-
res_objg = cast(tuple[float, np.ndarray], _objgrad(
|
|
149
|
+
def _grad(v: np.ndarray, args: list):
|
|
150
|
+
res_objg = cast(tuple[float, np.ndarray], _objgrad(v, args, gr=True))
|
|
221
151
|
grad_val = res_objg[1]
|
|
222
|
-
verbose = args[
|
|
152
|
+
verbose = args[-1]
|
|
223
153
|
if verbose:
|
|
224
154
|
print(f"The error on the gradient is {npmaxabs(grad_val)}")
|
|
225
155
|
return grad_val
|
|
226
156
|
|
|
227
157
|
|
|
228
|
-
def
|
|
229
|
-
"""Solve the dual optimisation to obtain the optimal weights ``v
|
|
158
|
+
def _solve_for_v(y: np.ndarray, n_nodes: int = 32, verbose: bool = False) -> TwoArrays:
|
|
159
|
+
"""Solve the dual optimisation to obtain the optimal weights ``v`` and the bivariate ranks
|
|
230
160
|
|
|
231
161
|
Args:
|
|
232
162
|
y: Observations with shape ``(n, 2)``.
|
|
@@ -236,22 +166,21 @@ def solve_for_v_(y: np.ndarray, n_nodes: int = 32, verbose: bool = False) -> np.
|
|
|
236
166
|
Returns:
|
|
237
167
|
Array of length ``n`` containing the optimal weights (including the
|
|
238
168
|
residual term).
|
|
169
|
+
Array of shape ``(n, 2)`` containing the bivariate ranks (the barycenters of the cells in the power diagram).
|
|
239
170
|
"""
|
|
240
|
-
|
|
171
|
+
d = y.shape[1]
|
|
241
172
|
|
|
242
173
|
if d != 2:
|
|
243
174
|
bs_error_abort(f"only works for 2-dimensional y, not for {d}")
|
|
244
175
|
|
|
245
|
-
|
|
246
|
-
sort_order = np.argsort(y[:, 1])
|
|
247
|
-
y_sorted = y[sort_order, :]
|
|
248
|
-
|
|
249
|
-
v0 = np.mean(y_sorted[:-1, :], 1)
|
|
176
|
+
v0 = np.mean(y[:-1, :], 1)
|
|
250
177
|
|
|
251
178
|
interval01 = Interval(0.0, 1.0)
|
|
252
|
-
|
|
179
|
+
tau1_nodes, tau1_weights = cheb_get_nodes_1d(interval01, n_nodes)
|
|
253
180
|
|
|
254
|
-
|
|
181
|
+
a_mat, dy2 = _compute_ad(y)
|
|
182
|
+
|
|
183
|
+
argsog = [y, a_mat, dy2, tau1_nodes, tau1_weights, verbose]
|
|
255
184
|
|
|
256
185
|
res = minimize_free(_obj, _grad, v0, args=argsog)
|
|
257
186
|
if verbose:
|
|
@@ -262,45 +191,48 @@ def solve_for_v_(y: np.ndarray, n_nodes: int = 32, verbose: bool = False) -> np.
|
|
|
262
191
|
vstar = res.x
|
|
263
192
|
if verbose:
|
|
264
193
|
print(f"The final gradient over v is close to 0: error {npmaxabs(res.jac)}")
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
vstar1 = np.zeros_like(vstar1_sorted)
|
|
269
|
-
vstar1[sort_order] = vstar1_sorted
|
|
270
|
-
|
|
271
|
-
return vstar1
|
|
194
|
+
_, _, bivranks = cast(tuple, _objgrad(vstar, argsog, gr=True))
|
|
195
|
+
vstar = np.append(vstar, -np.sum(vstar))
|
|
196
|
+
return cast(np.ndarray, vstar), cast(np.ndarray, bivranks)
|
|
272
197
|
|
|
273
198
|
|
|
274
|
-
def
|
|
275
|
-
y: np.ndarray,
|
|
199
|
+
def bivariate_ranks(
|
|
200
|
+
y: np.ndarray,
|
|
201
|
+
n_nodes: int = 32,
|
|
202
|
+
verbose: bool = False,
|
|
276
203
|
) -> np.ndarray:
|
|
277
|
-
"""
|
|
204
|
+
"""Compute the barycentric ranks of each observation.
|
|
278
205
|
|
|
279
206
|
Args:
|
|
280
|
-
y: Observations
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
verbose: Print optimisation diagnostics when ``True``.
|
|
207
|
+
y: Observations with shape ``(n, 2)``.
|
|
208
|
+
n_nodes: Number of Chebyshev nodes used in the quadrature.
|
|
209
|
+
verbose: Print diagnostics when ``True``.
|
|
284
210
|
|
|
285
211
|
Returns:
|
|
286
|
-
|
|
212
|
+
Array of average ranks (shape ``(n, 2)``) with ``nan`` for zero-mass cells.
|
|
287
213
|
"""
|
|
288
|
-
|
|
289
|
-
|
|
214
|
+
d = y.shape[1]
|
|
215
|
+
|
|
216
|
+
if d != 2:
|
|
217
|
+
bs_error_abort(f"only works for 2-dimensional y, not for {d}")
|
|
290
218
|
|
|
219
|
+
_, bivranks = _solve_for_v(y, n_nodes, verbose)
|
|
220
|
+
return cast(np.ndarray, bivranks)
|
|
291
221
|
|
|
292
|
-
|
|
293
|
-
|
|
222
|
+
|
|
223
|
+
def bivariate_quantiles(
|
|
224
|
+
y: np.ndarray, tau: np.ndarray, n_nodes: int = 32, verbose: bool = False
|
|
294
225
|
) -> np.ndarray:
|
|
295
|
-
"""
|
|
226
|
+
"""Solve for the dual weights then evaluate bivariate quantiles.
|
|
296
227
|
|
|
297
228
|
Args:
|
|
298
229
|
y: Observations, shape ``(n, 2)``.
|
|
230
|
+
tau: Query points in ``[0, 1]^2`` (shape ``(m, 2)``).
|
|
299
231
|
n_nodes: Number of Chebyshev nodes for the quadrature.
|
|
300
232
|
verbose: Print optimisation diagnostics when ``True``.
|
|
301
233
|
|
|
302
234
|
Returns:
|
|
303
|
-
|
|
235
|
+
Bivariate quantiles at ``u``.
|
|
304
236
|
"""
|
|
305
|
-
v =
|
|
306
|
-
return
|
|
237
|
+
v, _ = _solve_for_v(y, n_nodes, verbose)
|
|
238
|
+
return bivariate_quantiles_v(y, tau, v)
|
bs_python_utils/bs_logging.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bs-python-utils
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.9
|
|
4
4
|
Summary: Utilities programs for my Python code
|
|
5
5
|
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -25,6 +25,7 @@ Requires-Dist: statsmodels>=0.14.5
|
|
|
25
25
|
Requires-Dist: streamlit>=1.49.1
|
|
26
26
|
Requires-Dist: vega-datasets>=0.9.0
|
|
27
27
|
Requires-Dist: colorama>=0.4.6
|
|
28
|
+
Requires-Dist: pyarrow>=21.0.0
|
|
28
29
|
Dynamic: license-file
|
|
29
30
|
|
|
30
31
|
## bs-python-utils
|
|
@@ -42,6 +43,9 @@ Dynamic: license-file
|
|
|
42
43
|
|
|
43
44
|
### Release notes
|
|
44
45
|
|
|
46
|
+
#### 0.8.5 (January 25, 2026)
|
|
47
|
+
Added colored logger.
|
|
48
|
+
|
|
45
49
|
#### 0.8.2 (October 26, 2025)
|
|
46
50
|
Included grids for sparse Gaussian integration.
|
|
47
51
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
bs_python_utils/Timer.py,sha256=Rwj0Gec6VUq9Y6Rmykc5wL3Xd9dIj7Un_QgbJc2cTxo,1966
|
|
2
2
|
bs_python_utils/__init__.py,sha256=XJ62LhKlvBaZH5ItthEpR7W6Sb9FEKi1d-6TZhP8DLc,1353
|
|
3
|
-
bs_python_utils/bivariate_quantiles.py,sha256=
|
|
3
|
+
bs_python_utils/bivariate_quantiles.py,sha256=NaoNvt0QHEssFvju9YTD6dcHycd8NyWRG3cJADuk_W0,7859
|
|
4
4
|
bs_python_utils/bs_altair.py,sha256=4-MyCBrpuem48BhZV0dBhPZBgrxyl9PivdY3gaSUdN8,35127
|
|
5
|
-
bs_python_utils/bs_logging.py,sha256=
|
|
5
|
+
bs_python_utils/bs_logging.py,sha256=CGi_pLeBSVd7FXsoafCI9xDu9eXLMnJebgY8Ku3-qP8,5050
|
|
6
6
|
bs_python_utils/bs_mathstr.py,sha256=zW2ECxDD-29H81s_PNE1UKbIXJZtuhReJwcYim_4YTg,3595
|
|
7
7
|
bs_python_utils/bs_mem.py,sha256=WaTikTlMBDBAakS6ZBh9EZuLYtNO_1XqcFXL33ws4vY,4668
|
|
8
8
|
bs_python_utils/bs_opt.py,sha256=iq1fzPFm20kylg21uWXVDcfQWY7c7OpE9OYNBBaxbYU,17797
|
|
@@ -42,8 +42,8 @@ bs_python_utils/examples/examples_opt.py,sha256=pcWuTzOtTDWVJtKJJSUmaRIaPwDnAY3G
|
|
|
42
42
|
bs_python_utils/examples/examples_seaborn.py,sha256=pwGx0pDVNGEtLMKgTqOEzoXkOsXgRND8-cJIxJQEY5o,783
|
|
43
43
|
bs_python_utils/examples/examples_sklearn.py,sha256=TAnPRdRIiokrWBUUqVKkji5KXGCXyy_AjTIAEcmhtIY,792
|
|
44
44
|
bs_python_utils/examples/examples_sparse_gaussian.py,sha256=xz3U2z97h-sxoxFmMDbtETRynVcGDUVahr9HCK42BtU,911
|
|
45
|
-
bs_python_utils-0.
|
|
46
|
-
bs_python_utils-0.
|
|
47
|
-
bs_python_utils-0.
|
|
48
|
-
bs_python_utils-0.
|
|
49
|
-
bs_python_utils-0.
|
|
45
|
+
bs_python_utils-0.9.dist-info/licenses/LICENSE,sha256=J03S1L_wQN4qquuluScbRUE09on78nCnNRpaUpOvHcw,1073
|
|
46
|
+
bs_python_utils-0.9.dist-info/METADATA,sha256=EuB4Uk_EJb6_RmwvLN6G7i9NRh3vHCROA9lbC-jsGCg,4015
|
|
47
|
+
bs_python_utils-0.9.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
48
|
+
bs_python_utils-0.9.dist-info/top_level.txt,sha256=4sbCpeuqAsdWmoAmZju1vf1ZFMJrSx310eS5SCyrAeQ,16
|
|
49
|
+
bs_python_utils-0.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|