lessPython 0.2.0__py3-none-any.whl → 0.3.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.
Files changed (48) hide show
  1. lessPy/ANOVA.py +5 -5
  2. lessPy/Chart.py +386 -88
  3. lessPy/Correlation.py +2 -2
  4. lessPy/Logit.py +2 -2
  5. lessPy/Regression.py +6 -4
  6. lessPy/X.py +279 -42
  7. lessPy/XY.py +814 -158
  8. lessPy/__init__.py +12 -2
  9. lessPy/_themes.py +5007 -0
  10. lessPy/bc_items_plotly.py +31 -18
  11. lessPy/bc_plotly.py +23 -7
  12. lessPy/bubble_plotly.py +17 -2
  13. lessPy/corCFA.py +3 -3
  14. lessPy/corProp.py +2 -2
  15. lessPy/corReflect.py +2 -2
  16. lessPy/corReorder.py +2 -2
  17. lessPy/corScree.py +3 -3
  18. lessPy/data/StockPrice.csv +1401 -1386
  19. lessPy/details.py +17 -4
  20. lessPy/dn_plotly.py +65 -45
  21. lessPy/freq_poly_plotly.py +12 -5
  22. lessPy/getColors.py +247 -20
  23. lessPy/hier_plotly.py +36 -9
  24. lessPy/hs_plotly.py +16 -4
  25. lessPy/plotly_utils.py +78 -9
  26. lessPy/plt_mat_plotly.py +74 -2
  27. lessPy/plt_time.py +10 -3
  28. lessPy/prob_norm.py +3 -3
  29. lessPy/prob_tcut.py +3 -3
  30. lessPy/prob_znorm.py +3 -1
  31. lessPy/rcolors.py +461 -0
  32. lessPy/simCImean.py +3 -3
  33. lessPy/simCLT.py +3 -3
  34. lessPy/simFlips.py +3 -3
  35. lessPy/simMeans.py +3 -3
  36. lessPy/stats_out.py +257 -11
  37. lessPy/style.py +160 -0
  38. lessPy/sunflower_plotly.py +140 -0
  39. lessPy/ttest.py +5 -5
  40. lessPy/utils.py +43 -6
  41. lessPy/vbs_plotly.py +16 -5
  42. lessPy/x_console.py +763 -0
  43. {lesspython-0.2.0.dist-info → lesspython-0.3.0.dist-info}/METADATA +6 -2
  44. lesspython-0.3.0.dist-info/RECORD +89 -0
  45. lesspython-0.2.0.dist-info/RECORD +0 -84
  46. {lesspython-0.2.0.dist-info → lesspython-0.3.0.dist-info}/WHEEL +0 -0
  47. {lesspython-0.2.0.dist-info → lesspython-0.3.0.dist-info}/licenses/LICENSE +0 -0
  48. {lesspython-0.2.0.dist-info → lesspython-0.3.0.dist-info}/top_level.txt +0 -0
lessPy/hier_plotly.py CHANGED
@@ -19,15 +19,18 @@
19
19
  # ported; fills default to BASE_COLORS keyed by top-level
20
20
  # category (lessR's default "colors" theme). A sequential
21
21
  # palette NAMED in fill= is ported (read by magnitude off the
22
- # palette's ramp, R's pal_explicit branch). For the same
23
- # reason the per-facet luminance remap (fill_vec_byfac) has
24
- # no counterpart: every facet panel uses the global fills.
22
+ # palette's ramp, R's pal_explicit branch), and with facet=
23
+ # each panel reads its own shades off that ramp
24
+ # (fill_vec_byfac); other fills are the same in every panel.
25
25
 
26
26
  import numpy as np
27
27
  import pandas as pd
28
28
  import plotly.graph_objects as go
29
29
 
30
30
  from .getColors import _SEQ_NAMES
31
+
32
+ # the palettes read by magnitude, R's seq.pals of .hier_color_resolve()
33
+ _HIER_SEQ = set(_SEQ_NAMES) | {"terrain"}
31
34
  from .utils import STAT_FUN, get_option
32
35
  from .plotly_utils import (
33
36
  BASE_COLORS, facet_layout, plotly_style, to_hex,
@@ -160,6 +163,28 @@ def _seq_palette_fill(top_levels, pal, x, y, stat):
160
163
  return {lv: ramp[i] for lv, i in zip(top_levels, idx)}
161
164
 
162
165
 
166
+ def hier_color_resolve_byfac(top_levels, fill, x, y, stat, facet,
167
+ facet_order):
168
+ """Per-panel fills for a faceted chart: with a named sequential
169
+ palette, each panel's categories take their shades from that
170
+ panel's own counts (or stat of y), so each panel spans the
171
+ palette; None for any other fill, which every panel shares.
172
+ R analog: the fill_vec_byfac branch of .hier_color_resolve()"""
173
+ if not (isinstance(fill, str) and fill.lower() in _HIER_SEQ):
174
+ return None
175
+ fac = facet.astype(str)
176
+ out = {}
177
+ for lv in facet_order:
178
+ m = (fac == str(lv)).to_numpy()
179
+ present = set(x[m].astype(str))
180
+ tops = [t for t in top_levels if str(t) in present]
181
+ if tops:
182
+ out[str(lv)] = _seq_palette_fill(
183
+ tops, fill.lower(), x[m].astype(str),
184
+ None if y is None else y[m], stat)
185
+ return out
186
+
187
+
163
188
  def hier_color_resolve(top_levels, fill=None, x=None, y=None,
164
189
  stat=None):
165
190
  """Hex color per top-level category, inherited down the tree.
@@ -169,7 +194,7 @@ def hier_color_resolve(top_levels, fill=None, x=None, y=None,
169
194
  ported."""
170
195
  if fill is None:
171
196
  fill = BASE_COLORS
172
- if (isinstance(fill, str) and fill.lower() in _SEQ_NAMES
197
+ if (isinstance(fill, str) and fill.lower() in _HIER_SEQ
173
198
  and x is not None):
174
199
  return _seq_palette_fill(top_levels, fill.lower(), x, y,
175
200
  stat)
@@ -183,7 +208,7 @@ def hier_color_resolve(top_levels, fill=None, x=None, y=None,
183
208
  for i, lv in enumerate(top_levels)}
184
209
 
185
210
 
186
- def hier_plotly(agg, fill_vec, type="sunburst",
211
+ def hier_plotly(agg, fill_vec, type="sunburst", fill_vec_byfac=None,
187
212
  x_name="X", by_name=None, facet_name=None,
188
213
  main=None, border=None, digits_d=None,
189
214
  labels=None, labels_color="white",
@@ -254,8 +279,9 @@ def hier_plotly(agg, fill_vec, type="sunburst",
254
279
  if texttemplate is not None:
255
280
  kw["texttemplate"] = texttemplate
256
281
 
257
- def make_trace(nd_i, dom_x, dom_y):
258
- node_cols = [fill_vec.get(r, list(fill_vec.values())[0])
282
+ def make_trace(nd_i, dom_x, dom_y, cols=None):
283
+ cols = fill_vec if not cols else cols
284
+ node_cols = [cols.get(r, list(cols.values())[0])
259
285
  for r in nd_i["root"]]
260
286
  return trace_cls(
261
287
  ids=nd_i["ids"],
@@ -334,8 +360,9 @@ def hier_plotly(agg, fill_vec, type="sunburst",
334
360
  for i, lv in enumerate(fac_levels):
335
361
  nd_i = nd_byfac[lv]
336
362
  if nd_i["ids"]:
337
- fig.add_trace(make_trace(nd_i, domains[i]["x"],
338
- domains[i]["y"]))
363
+ fig.add_trace(make_trace(
364
+ nd_i, domains[i]["x"], domains[i]["y"],
365
+ cols=(fill_vec_byfac or {}).get(str(lv))))
339
366
 
340
367
  t_margin = round(title_size * 2.8)
341
368
  fig.update_layout(
lessPy/hs_plotly.py CHANGED
@@ -93,8 +93,8 @@ def hs_plotly(x, by=None, x_name=None, by_name=None,
93
93
 
94
94
  # groups need distinguishable hues: default to the palette
95
95
  if fill_miss and G > 1:
96
- from .plotly_utils import BASE_COLORS
97
- fill = BASE_COLORS
96
+ from .plotly_utils import by_colors
97
+ fill = by_colors(G)
98
98
 
99
99
  # --- counts per bin (right-closed bins, as in R's hist) ---
100
100
  def bin_counts(xg):
@@ -107,6 +107,18 @@ def hs_plotly(x, by=None, x_name=None, by_name=None,
107
107
  xg = xg[np.isfinite(xg)]
108
108
  y_mat[:, g] = bin_counts(pd.Series(xg))
109
109
 
110
+ # the bins as R's X() returns them
111
+ from .stats_out import record_stats
112
+ cnt = y_mat[:, 0] if G == 1 else pd.DataFrame(y_mat, columns=groups)
113
+ tot = cnt.sum() if G == 1 else cnt.sum(axis=0)
114
+ record_stats(bin_width=float(widths[0]), n_bins=n_bins,
115
+ breaks=list(breaks), mids=mids.tolist(),
116
+ counts=(cnt.astype(int).tolist() if G == 1
117
+ else cnt.astype(int)),
118
+ prop=(cnt / tot).tolist() if G == 1 else cnt / tot,
119
+ cprop=(np.cumsum(cnt) / tot).tolist() if G == 1
120
+ else cnt.cumsum() / tot)
121
+
110
122
  # density: normalize each group to unit area; proportion: to 1
111
123
  if not freq:
112
124
  for g in range(G):
@@ -287,8 +299,8 @@ def _hs_facet(x, facet, facet_order, x_name, facet_name, breaks,
287
299
 
288
300
  if fill is None:
289
301
  if G > 1:
290
- from .plotly_utils import BASE_COLORS
291
- fill = BASE_COLORS
302
+ from .plotly_utils import by_colors
303
+ fill = by_colors(G)
292
304
  else:
293
305
  fill = get_option("bar_fill_cont", "#96AAC3")
294
306
  if border is None:
lessPy/plotly_utils.py CHANGED
@@ -17,6 +17,43 @@ BASE_COLORS = [
17
17
  "#00A3BA", "#D26FAF", "#00A76F", "#BD76CB",
18
18
  ]
19
19
 
20
+
21
+ def theme_palette(theme=None):
22
+ """The palette a color theme gives to groups. R analog: .get_fill()
23
+ (not divergent): the qualitative hues for the default theme, else a
24
+ sequential palette in the theme's hue."""
25
+ from .utils import get_option
26
+ if theme is None:
27
+ theme = get_option("theme", "colors")
28
+ if theme == "colors":
29
+ return "hues"
30
+ for pal, members in (
31
+ ("grays", ("gray", "white")),
32
+ ("blues", ("lightbronze", "dodgerblue", "blue")),
33
+ ("browns", ("gold", "brown", "sienna")),
34
+ ("rusts", ("orange",)),
35
+ ("reds", ("darkred", "red", "rose", "slatered")),
36
+ ("greens", ("darkgreen", "green")),
37
+ ("violets", ("purple",))):
38
+ if theme in members:
39
+ return pal
40
+ return "blues"
41
+
42
+
43
+ def by_colors(n, theme=None):
44
+ """One color per group of a by variable under the current theme,
45
+ as X() and XY() draw them. R analog: .color_range(.get_fill(theme),
46
+ n), two grays set apart as gray60 and gray30."""
47
+ pal = theme_palette(theme)
48
+ if pal == "hues":
49
+ return [BASE_COLORS[i % len(BASE_COLORS)] for i in range(n)]
50
+ if pal == "grays" and n == 2:
51
+ return ["#999999", "#4D4D4D"]
52
+ from .getColors import getColors
53
+ cols = getColors(pal, n=max(1, n), quiet=True)
54
+ return [c[:7] if len(c) == 9 else c for c in cols]
55
+
56
+
20
57
  # minimal named-color table; R's col2rgb() knows all R names, but
21
58
  # plotly accepts CSS names directly so unknowns pass through as-is
22
59
  _NAMED = {
@@ -80,6 +117,10 @@ def to_hex(col):
80
117
  gray = _gray_level(lower)
81
118
  if gray is not None:
82
119
  return gray
120
+ # any of R's named colors, as col2rgb() resolves them
121
+ from .rcolors import R_COLORS
122
+ if lower in R_COLORS:
123
+ return R_COLORS[lower]
83
124
  return c1 # CSS name unknown to us; plotly handles it
84
125
 
85
126
 
@@ -222,9 +263,13 @@ def legend_style(by_name, style_opts, title=None, position=None,
222
263
  leg = dict(
223
264
  title=dict(text=abbrev(text, abbrev_n) or "",
224
265
  font=dict(size=round(
225
- 15 * get_option("lab_size", 1) * mult))),
266
+ 15 * get_option("lab_size", 1) * mult),
267
+ color=to_hex(style_opts["lab_color"]))),
268
+ # the legend reads in the theme's label color, light on the
269
+ # black sub_theme as the axis labels are
226
270
  font=dict(size=round(
227
- 16 * get_option("axis_size", 0.9) * mult)),
271
+ 16 * get_option("axis_size", 0.9) * mult),
272
+ color=to_hex(style_opts["lab_color"])),
228
273
  bgcolor=to_hex(style_opts["window_fill"]),
229
274
  bordercolor=to_hex(style_opts["legend_border"]),
230
275
  borderwidth=1,
@@ -316,9 +361,13 @@ def axis_format(vals, digits_d=2, axis_fmt="K", prefix=""):
316
361
 
317
362
 
318
363
  def grid_style():
319
- """R analog: .grid_style()"""
364
+ """R analog: .grid_style(). A sub_theme sets the grid through
365
+ grid_x_color / grid_y_color (white on the gray panel of "default"),
366
+ which take precedence over the grid color itself"""
367
+ clr = (get_option("grid_y_color") or get_option("grid_x_color")
368
+ or get_option("grid_col", "gray85"))
320
369
  return {
321
- "color": to_hex(get_option("grid_col", "gray85")),
370
+ "color": to_hex(clr),
322
371
  "width": get_option("grid_lwd", 0.5),
323
372
  "dash": get_option("grid_lty", None),
324
373
  }
@@ -355,17 +404,26 @@ def y_grid(y_vals):
355
404
 
356
405
 
357
406
  def axis_base():
358
- """R analog: axis_base()"""
407
+ """R analog: axis_base(). A sub_theme sets the axes through their
408
+ own settings, so on sub_theme="black" the axis line and its labels
409
+ are light where axis_color stays dark; the labels are text, so they
410
+ take axis_text_color, as lessR's base R axes do"""
411
+ ax_line = (get_option("axis_x_color")
412
+ or get_option("axis_color", "black"))
413
+ ax_text = (get_option("axis_x_text_color")
414
+ or get_option("axis_text_color")
415
+ or get_option("axis_color", "black"))
359
416
  return {
360
417
  "zeroline": False,
361
418
  "showline": True,
362
- "linecolor": to_hex(get_option("axis_color", "black")),
419
+ "linecolor": to_hex(ax_line),
363
420
  "linewidth": get_option("axis_lwd", 1),
364
421
  "ticks": "outside",
365
422
  "ticklen": 4,
423
+ "tickcolor": to_hex(ax_line),
366
424
  "automargin": True,
367
425
  "tickfont": {
368
- "color": to_hex(get_option("axis_color", "black")),
426
+ "color": to_hex(ax_text),
369
427
  "size": 16 * get_option("axis_size", 0.9),
370
428
  },
371
429
  "title": {
@@ -486,6 +544,10 @@ def font_scaled(func):
486
544
  fig = func(*args, **kwargs)
487
545
  if sub and hasattr(fig, "layout"):
488
546
  add_subtitle(fig, sub)
547
+ # style(font_family=) sets the family of all plotted text
548
+ family = get_option("font_family")
549
+ if family and hasattr(fig, "layout"):
550
+ fig.update_layout(font=dict(family=family))
489
551
  try:
490
552
  if font_size and font_size != 1 and hasattr(fig, "layout"):
491
553
  apply_font_size(fig, font_size)
@@ -603,7 +665,7 @@ def facet_panels(facet, facet_order, facet2=None,
603
665
 
604
666
  def finish_facet(fig, levels, ax, x_lab, y_lab, gridT1,
605
667
  style_opts=None, y_cat=None, n_col=1, pos=None,
606
- height=None, width=None):
668
+ height=None, width=None, x_cat=None):
607
669
  """Facet styling shared by the faceted renderers: per-panel y
608
670
  axes on a common scale (y label on the middle panel of the
609
671
  first column), x ticks on the bottom row only, vertical grid
@@ -670,7 +732,14 @@ def finish_facet(fig, levels, ax, x_lab, y_lab, gridT1,
670
732
  showticklabels=c == 1)
671
733
  fig.update_yaxes(row=r, col=c, **ay)
672
734
  lowest = r == n_row or (r + 1, c) not in occupied
673
- if lowest:
735
+ if lowest and x_cat is not None:
736
+ # categories along x, the vertical bars of a panel
737
+ ax_x = axis_cat(x_lab if c == mid_c else "")
738
+ ax_x.update(categoryorder="array",
739
+ categoryarray=list(x_cat), tickmode="array",
740
+ tickvals=list(x_cat), ticktext=list(x_cat))
741
+ fig.update_xaxes(row=r, col=c, showticklabels=True, **ax_x)
742
+ elif lowest:
674
743
  # a shared x axis hides the labels above the bottom row,
675
744
  # so a ragged grid's lowest panel turns its own back on
676
745
  fig.update_xaxes(
lessPy/plt_mat_plotly.py CHANGED
@@ -29,14 +29,28 @@ def _axis_ref(k, kind):
29
29
 
30
30
 
31
31
  def scatter_matrix(df, fit="lm", digits_d=2, cor_coef=True,
32
- main=None, band=True):
32
+ main=None, band=True, form="scatter",
33
+ contour_n=None, contour_nbins=50,
34
+ contour_points=False, smooth_bins=128,
35
+ smooth_power=0.25):
33
36
  """Scatterplot matrix of the columns of df, in column order.
34
37
  fit: "off" (no line, XY default), "lm" (Regression) or
35
38
  "loess". cor_coef=True puts the correlation in the upper
36
39
  triangle and the scatter below (~ .plt.mat, Regression);
37
40
  cor_coef=False draws the scatter in every off-diagonal cell,
38
41
  the symmetric matrix R's Logit uses (logit.4Pred). band adds
39
- the fit's 95% confidence band. Returns a plotly Figure."""
42
+ the fit's 95% confidence band. form="contour" or "smooth"
43
+ draws each cell as its own kernel density over the cell's
44
+ range, 8 contour bands unless contour_n is given (a cell cannot
45
+ resolve the 20 of a single plot), any fit drawn without its
46
+ band. R analog: .plt.mat() panel.dens. Returns a plotly
47
+ Figure."""
48
+ if form not in ("scatter", "contour", "smooth"):
49
+ raise ValueError(
50
+ 'A matrix renders its cells as form="scatter", "contour", '
51
+ f'or "smooth", so form="{form}" is not\navailable for a '
52
+ "matrix.")
53
+ contour_n = 8 if contour_n is None else int(contour_n)
40
54
  cols = list(df.columns)
41
55
  n = len(cols)
42
56
  if n < 2:
@@ -78,6 +92,17 @@ def scatter_matrix(df, fit="lm", digits_d=2, cor_coef=True,
78
92
 
79
93
  # scatter in the lower triangle, and also in the
80
94
  # upper triangle when no correlations are requested
95
+ if r != c and (r > c or not cor_coef) \
96
+ and form != "scatter":
97
+ _cell_bg(fig, xr, yr, bg, border)
98
+ _density_cell(fig, r, c, vals[cols[c - 1]],
99
+ vals[cols[r - 1]], rng[cols[c - 1]],
100
+ rng[cols[r - 1]], form, contour_n,
101
+ contour_nbins, contour_points,
102
+ smooth_bins, smooth_power,
103
+ fit if do_fit else "off", fit_color,
104
+ fit_lwd)
105
+ continue
81
106
  if r != c and (r > c or not cor_coef):
82
107
  _cell_bg(fig, xr, yr, bg, border)
83
108
  _scatter_cell(fig, r, c, vals[cols[c - 1]],
@@ -199,3 +224,50 @@ def _scatter_cell(fig, r, c, xv, yv, fit, do_fit, px,
199
224
  x=xs, y=f, mode="lines",
200
225
  line=dict(color=fit_color, width=fit_lwd),
201
226
  hoverinfo="skip", showlegend=False), row=r, col=c)
227
+
228
+
229
+ def _density_cell(fig, r, c, xv, yv, xr, yr, form, contour_n,
230
+ contour_nbins, contour_points, smooth_bins,
231
+ smooth_power, fit, fit_color, fit_lwd):
232
+ """One cell as a kernel density over the cell's range: filled
233
+ contour bands or the smooth shading, then the fit, unbanded.
234
+ R analog: panel.dens of .plt.mat()"""
235
+ from .plt_contour import _COLORSCALE, _bw_nrd, _kde2d
236
+ from .plt_smooth import _RAMP
237
+ from .XY import _loess, _plt_fit
238
+
239
+ ok = np.isfinite(xv) & np.isfinite(yv)
240
+ xo, yo = xv[ok], yv[ok]
241
+ if len(xo) < 3 or _bw_nrd(xo) <= 0 or _bw_nrd(yo) <= 0:
242
+ return
243
+ lims = (float(xr[0]), float(xr[-1]), float(yr[0]), float(yr[-1]))
244
+ n_grid = smooth_bins if form == "smooth" else contour_nbins
245
+ gx, gy, z = _kde2d(xo, yo, n_grid, lims)
246
+ if form == "smooth":
247
+ fig.add_trace(go.Heatmap(
248
+ x=gx, y=gy, z=(z ** smooth_power).T, colorscale=_RAMP,
249
+ zsmooth="best", showscale=False, hoverinfo="skip"),
250
+ row=r, col=c)
251
+ else:
252
+ lv0, lv1 = float(z.min()), float(z.max())
253
+ step = (lv1 - lv0) / contour_n
254
+ fig.add_trace(go.Contour(
255
+ x=gx, y=gy, z=z.T, colorscale=_COLORSCALE,
256
+ contours=dict(start=lv0 + step, end=lv1, size=step),
257
+ line=dict(width=0), showscale=False, hoverinfo="skip"),
258
+ row=r, col=c)
259
+ if contour_points:
260
+ fig.add_trace(go.Scatter(
261
+ x=xo, y=yo, mode="markers",
262
+ marker=dict(size=3, color="rgba(0,0,0,0.27)",
263
+ line=dict(color="white", width=0.2)),
264
+ hoverinfo="skip", showlegend=False), row=r, col=c)
265
+ if fit in ("lm", "loess"):
266
+ if fit == "loess":
267
+ xs, _, f, _ = _loess(xo, yo, 2 / 3)
268
+ else:
269
+ xs, _, f = _plt_fit(xo, yo, "lm", 1)
270
+ fig.add_trace(go.Scatter(
271
+ x=xs, y=f, mode="lines",
272
+ line=dict(color=fit_color, width=fit_lwd),
273
+ hoverinfo="skip", showlegend=False), row=r, col=c)
lessPy/plt_time.py CHANGED
@@ -56,11 +56,18 @@ def _agg_one(dser, yser, ts_unit, aggfun):
56
56
  per = dser
57
57
  else:
58
58
  per = dser.dt.to_period(_PERIOD_FREQ[ts_unit])
59
- # trailing partial period: last date short of period end
59
+ # trailing partial period: its last date short of the period
60
+ # end AND fewer observations than the median of the earlier
61
+ # periods, so data dated at period starts keeps its complete
62
+ # final period. R analog: ts_truncate() (plt.time.R)
60
63
  last_per = per.iloc[int(np.argmax(dser.to_numpy()))]
61
64
  if dser.max() < last_per.end_time.normalize():
62
- keep = (per != last_per).to_numpy()
63
- dser, yser, per = dser[keep], yser[keep], per[keep]
65
+ n_per = per.value_counts()
66
+ others = n_per.drop(last_per)
67
+ n_full = float(np.median(others)) if len(others) else 0
68
+ if n_per[last_per] < n_full:
69
+ keep = (per != last_per).to_numpy()
70
+ dser, yser, per = dser[keep], yser[keep], per[keep]
64
71
  if len(dser) == 0:
65
72
  return (np.array([], dtype="datetime64[ns]"),
66
73
  np.array([]))
lessPy/prob_norm.py CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  import numpy as np
10
10
 
11
- from .utils import fmt
11
+ from .utils import fmt, show_plots
12
12
 
13
13
  _FILL_NRM = "#E8E8E8" # grey91
14
14
  _FILL_INT = "#9FB6CD" # slategray3
@@ -57,8 +57,8 @@ def prob_norm(lo=None, hi=None, mu=0, sigma=1, nrm_color="black",
57
57
 
58
58
  print(f"Probability: {prob}")
59
59
 
60
- return ProbNormResults(prob=prob, lo=lo_v, hi=hi_v, mu=mu,
61
- sigma=sigma, plots={"norm": fig})
60
+ return show_plots(ProbNormResults(prob=prob, lo=lo_v, hi=hi_v, mu=mu,
61
+ sigma=sigma, plots={"norm": fig}))
62
62
 
63
63
 
64
64
  def _plot(lo, hi, lo_lbl, hi_lbl, mu, sigma, prob, nrm_color,
lessPy/prob_tcut.py CHANGED
@@ -9,7 +9,7 @@
9
9
 
10
10
  import numpy as np
11
11
 
12
- from .utils import fmt
12
+ from .utils import fmt, show_plots
13
13
 
14
14
  _BG = "#F9F9FC" # rgb(249,249,252)
15
15
  _TAIL = "#8B475D" # palevioletred4
@@ -51,8 +51,8 @@ def prob_tcut(df, alpha=0.05, digits_d=3, y_axis=False,
51
51
  fill, color_tail, nrm_color, color_t)
52
52
 
53
53
  print(f"Probability: {cutoff}")
54
- return ProbTcutResults(cutoff=cutoff, df=df, alpha=alpha,
55
- plots={"tcut": fig})
54
+ return show_plots(ProbTcutResults(cutoff=cutoff, df=df, alpha=alpha,
55
+ plots={"tcut": fig}))
56
56
 
57
57
 
58
58
  def _cut_line(fig, x, top, color):
lessPy/prob_znorm.py CHANGED
@@ -11,6 +11,8 @@
11
11
 
12
12
  import numpy as np
13
13
 
14
+ from .utils import show_plots
15
+
14
16
 
15
17
  class ProbZnormResults:
16
18
  """Result of prob_znorm(): mu/sigma and the plotly figure in
@@ -46,7 +48,7 @@ def prob_znorm(mu=0, sigma=1, color_border="gray10", r=0.10,
46
48
  f"{round(b * 255)},{a})"
47
49
 
48
50
  fig = _plot(mu, sigma, border, fill, main, y_axis, z)
49
- return ProbZnormResults(mu=mu, sigma=sigma, plots={"znorm": fig})
51
+ return show_plots(ProbZnormResults(mu=mu, sigma=sigma, plots={"znorm": fig}))
50
52
 
51
53
 
52
54
  def _gray_to_hex(color):