Skip to content

Commit 2f4d959

Browse files
author
miranov25
committed
PHASE 13.36.DF — user style kwargs override auto-cycle in group_by path
Closes BUG-013: marker='s', color='red', markersize=10 silently ignored when group_by was active. The grouped rendering path (profile + hist) used the per-group color/marker cycle unconditionally, discarding user style kwargs. Priority rule (architect 2026-05-20): user kwarg > channel auto-cycle > style default None = 'user did not pass' (matches matplotlib default-color semantics). Profile fix (plots/profile.py): _draw_profile_grouped() signature: add _user_marker, _user_markersize, _user_color named params (default None). draw_profile() captures _ud_user_marker, _ud_user_markersize, _ud_user_color BEFORE the style fill-in at lines 311-321 (which replaces None with style defaults). Without pre-fill-in capture, the sentinel arrives as 'o' even when user passed nothing → cycle override (CODER NOTE §5.1). draw_profile() call to _draw_profile_grouped(): pass _user_marker= _ud_user_marker etc. (the pre-fill-in captures). REMOVED: marker=marker, markersize=markersize from the call. REMOVED: profile_kwargs.pop('marker'/'markersize') (nothing left to pop). Per-group loop: 'is None' check before palette/marker cycle. UserWarning fires ONCE per call (i==0) when color= makes all groups uniform. Hist fix (plots/histogram.py): _draw_hist_grouped() signature: add _user_color named param (default None). draw_hist() call to _draw_hist_grouped(): pass _user_color=color. draw_hist() body (early, before routing): pop 'marker' from kwargs + issue UserWarning. v1.2 spec said pop inside _draw_hist_grouped, but that path is only reached for grouped hist — non-grouped/vector path would crash ax.hist (AttributeError on marker). Single source of truth at draw_hist top (CODER NOTE §5.2). Per-group color: sentinel checked in BOTH stacked + overlaid branches. FORWARDED_NAMES (drawer.py): _PROFILE_FORWARDED_NAMES += marker, color, markersize (all 3 are explicit params of draw_profile()). _HIST_FORWARDED_NAMES += marker, color ONLY (NOT markersize — draw_hist() has no markersize explicit param; adding it would crash ax.hist via vector path. Sonet51 P1 from v1.2 review). DFDraw method signatures + bodies (drawer.py): DFDraw.profile() += color, marker, markersize params (R6 validator). DFDraw.hist() += color, marker params (R6 validator). Both bodies forward the params explicitly to draw_profile/draw_hist. same=True auto-color injection refactored: (a) assign to local color var not kwargs['color'] (collision); (b) skip auto-color when group_by is active — preserves pre-13.36 behavior (auto-color was silently dropped in grouped path) and prevents false-positive 'indistinguishable' UserWarning (CODER NOTE §5.3). linestyle: out of scope — already works (brainstorm + v0/v1 panel live tests, 2026-05-20). §9.LS.1 locks current behavior. Primary use case (TPC/ITS calibration overlay): adf.draw('y:row', group_by='drift', group_by_bins=5) adf.draw('y:row', group_by='drift', group_by_bins=5, same=True, marker='s') Spec history: v1.0 (Sonet50): 3 P1s including 'color not forwarded to grouped path'. v1.1 (Sonet50): attempted P1-A fix via profile_kwargs.pop, returns _UNSET unconditionally (color/marker/markersize consumed by explicit signature, not in **kwargs). Sonnet53_R2 [X], Claude48Coder [X]. v1.2 (Claude48Coder, architect-greenlit takeover): Sonnet53_R2 Option A — local variables, None sentinel. v1.2 review: Sonet50 [OK], Sonet51 [!] P1 (markersize crash in hist vector path — fixed at code time per architect 'no v1.3' directive), Claude40 [✅ APPROVED]. Implementation deviations from v1.2 spec (mandatory disclosure): - Edit 17 (NEW): pre-fill-in capture for _ud_user_* — caught at smoke test, not anticipated in spec. §5.1. - Edit 18: marker pop moved from _draw_hist_grouped to draw_hist top — caught by full regression (96 vector hist failures). §5.2. - Edit 15/16: same=True + group_by guard — caught at smoke test, false- positive UserWarning. §5.3. Tests: +10 §9 invariance (SO.1-5, SOH.1-2, LS.1, SC.1, VF.1) Linux Py3.12 (this env): 810 / 1 / 33 / 1 — 1 failed + 33 skipped are pre-existing per Phase 13.35.DF conversation summary. Expected on architect's Mac Py3.9.6: 843 / 0 / 1.
1 parent 3b910ae commit 2f4d959

4 files changed

Lines changed: 436 additions & 13 deletions

File tree

UTILS/dfextensions/dfdraw/drawer.py

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,10 @@ def _auto_label(self, y_expr, x_expr=None):
576576
'vector_compose', 'delta_facet',
577577
# Phase 13.33.DF: Normalized differential profiles (AD-80/81/82)
578578
'normalize', 'normalize_layout',
579+
# Phase 13.36.DF: user style override kwargs (BUG-013 fix).
580+
# draw_profile() has all 3 as explicit params at lines 162-164;
581+
# adding to FORWARDED_NAMES lets vector-dispatch path forward them.
582+
'marker', 'color', 'markersize',
579583
)
580584

581585
_HIST_FORWARDED_NAMES = (
@@ -601,6 +605,16 @@ def _auto_label(self, y_expr, x_expr=None):
601605
'group_by_bins', 'group_by_quantiles',
602606
'hist_norm',
603607
'min_entries',
608+
# Phase 13.36.DF: user style override kwargs (BUG-013 fix).
609+
# draw_hist() has 'color' as explicit param (consumed by signature);
610+
# 'marker' is NOT explicit — flows through **kwargs to _draw_hist_grouped()
611+
# where it gets popped + a UserWarning is issued (markers are meaningless
612+
# for histograms).
613+
# NOTE: 'markersize' deliberately NOT added — draw_hist() has no
614+
# markersize explicit param, so adding it would let it flow to ax.hist()
615+
# via vector dispatch and crash (matplotlib rejects markersize). Sonet51
616+
# P1 from v1.2 review.
617+
'marker', 'color',
604618
)
605619

606620
_SCATTER_FORWARDED_NAMES = (
@@ -3190,6 +3204,16 @@ def hist(
31903204
group_by_quantiles: Optional[int] = None,
31913205
hist_norm: Optional[str] = None,
31923206
min_entries: int = 0,
3207+
# Phase 13.36.DF: user style overrides for group_by path (BUG-013 fix).
3208+
# color applies uniformly to all groups. marker is consumed inside
3209+
# _draw_hist_grouped() with a UserWarning (matplotlib's ax.hist does
3210+
# not render markers — markers are meaningless for histograms).
3211+
# NOTE: 'markersize' deliberately absent — draw_hist() has no
3212+
# corresponding draw_hist() explicit param; adding it to
3213+
# _HIST_FORWARDED_NAMES would crash ax.hist via vector dispatch.
3214+
# See PHASE_13_36_DF_v1_2_Proposal §3.3 + Sonet51 P1.
3215+
color: Optional[str] = None,
3216+
marker: Optional[str] = None,
31933217
**kwargs
31943218
) -> DrawResult:
31953219
"""
@@ -3315,11 +3339,18 @@ def hist(
33153339

33163340
# Phase 13.13.DF: Inject color and label for same=True
33173341
# Phase 13.16.DF: _suppress_color_cycle flag (P1-2)
3342+
# Phase 13.36.DF: color is now explicit param. Two changes:
3343+
# (1) Assign to local `color`, not `kwargs['color']` (collision with
3344+
# explicit forwarding to draw_hist below).
3345+
# (2) Skip auto-color when group_by is active — same rationale as
3346+
# DFDraw.profile() (preserves effective pre-13.36 behavior where
3347+
# auto-color was silently dropped in the grouped path).
33183348
_suppress_color_cycle = kwargs.pop('_suppress_color_cycle', False)
33193349
save_auto_title = auto_title
33203350
if same:
3321-
if 'color' not in kwargs and not _suppress_color_cycle:
3322-
kwargs['color'] = self._get_next_color()
3351+
if (color is None and not _suppress_color_cycle
3352+
and group_by is None):
3353+
color = self._get_next_color()
33233354
if 'label' not in kwargs and group_by is None:
33243355
kwargs['label'] = self._auto_label(col_expr)
33253356
# Suppress title handling — we do it in _handle_same_post
@@ -3408,6 +3439,12 @@ def hist(
34083439
group_by_quantiles=group_by_quantiles,
34093440
hist_norm=hist_norm,
34103441
min_entries=min_entries,
3442+
# Phase 13.36.DF: user style overrides (color → draw_hist;
3443+
# marker flows via **kwargs after FORWARDED_NAMES, popped at
3444+
# _draw_hist_grouped first line). Without explicit forward,
3445+
# consumed by DFDraw.hist signature and lost.
3446+
color=color,
3447+
marker=marker,
34113448
**kwargs
34123449
)
34133450
axes = ax
@@ -3771,6 +3808,13 @@ def profile(
37713808
# PHASE_13_33_DF_v1_1_Proposal_NormalizedDifferentialProfiles.md.
37723809
normalize: Optional[Union[str, "callable"]] = None,
37733810
normalize_layout: str = "overlay+diff",
3811+
# Phase 13.36.DF: user style overrides for group_by path (BUG-013 fix).
3812+
# When passed, applies uniformly to ALL groups in the call (overrides
3813+
# the per-group auto-cycle). None = use auto-cycle (default).
3814+
# See PHASE_13_36_DF_v1_2_Proposal_UserStyleOverride.md.
3815+
color: Optional[str] = None,
3816+
marker: Optional[str] = None,
3817+
markersize: Optional[float] = None,
37743818
**kwargs
37753819
) -> DrawResult:
37763820
"""
@@ -4119,11 +4163,22 @@ def profile(
41194163

41204164
# Phase 13.13.DF: Inject color and label for same=True
41214165
# Phase 13.16.DF: _suppress_color_cycle flag (P1-2)
4166+
# Phase 13.36.DF: color is now explicit param of DFDraw.profile().
4167+
# Two changes vs pre-13.36:
4168+
# (1) Assign auto-color to local `color`, not `kwargs['color']`
4169+
# (would collide with explicit forwarding at line ~4262).
4170+
# (2) Skip auto-color injection when group_by is active. Pre-13.36
4171+
# dropped auto-color silently in the grouped path; post-13.36
4172+
# it would flow through and force all groups uniform, defeating
4173+
# the per-group color cycle. The cycle already distinguishes
4174+
# groups; same=True overlay distinguishes via marker (cycle or
4175+
# user-passed). This preserves the effective pre-13.36 behavior.
41224176
_suppress_color_cycle = kwargs.pop('_suppress_color_cycle', False)
41234177
save_auto_title = auto_title
41244178
if same:
4125-
if 'color' not in kwargs and not _suppress_color_cycle:
4126-
kwargs['color'] = self._get_next_color()
4179+
if (color is None and not _suppress_color_cycle
4180+
and group_by is None):
4181+
color = self._get_next_color()
41274182
if 'label' not in kwargs and group_by is None:
41284183
kwargs['label'] = self._auto_label(y_expr, x_expr)
41294184
# Suppress title — handled in _handle_same_post
@@ -4218,6 +4273,11 @@ def profile(
42184273
quantiles=quantiles, central=central, quantile_mode=quantile_mode,
42194274
# Phase 13.28.DF: NaN/inf filter policy
42204275
nan_policy=nan_policy,
4276+
# Phase 13.36.DF: user style overrides — all three forwarded
4277+
# from DFDraw.profile() explicit signature. draw_profile() has
4278+
# all three as explicit params at lines 162-164. Without these,
4279+
# consumed by DFDraw.profile() signature and lost.
4280+
color=color, marker=marker, markersize=markersize,
42214281
**kwargs
42224282
)
42234283
axes = ax

UTILS/dfextensions/dfdraw/plots/histogram.py

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,26 @@ def draw_hist(
288288
linewidth = get_style_value("hist.linewidth", 1.0)
289289
# Phase 13.12.DF v1.2: auto_title from style if not set per-call
290290
auto_title = resolve_auto_title(auto_title)
291-
291+
292+
# Phase 13.36.DF: pop 'marker' from kwargs BEFORE any rendering path.
293+
# 'marker' flows in here via _HIST_FORWARDED_NAMES (Phase 13.36 added it
294+
# to the tuple). matplotlib's ax.hist() does NOT accept marker — would
295+
# raise AttributeError on every hist render (vector path, non-grouped
296+
# path, grouped path). The pop must happen at draw_hist top, not deeper
297+
# inside _draw_hist_grouped (which is only reached for the grouped path).
298+
# markersize is NOT in _HIST_FORWARDED_NAMES (Sonet51 P1 from v1.2 review)
299+
# so it cannot arrive here via the vector path. No pop needed for it.
300+
_user_marker = kwargs.pop('marker', None)
301+
if _user_marker is not None:
302+
import warnings
303+
_ht_hint = histtype if histtype is not None else 'bar'
304+
warnings.warn(
305+
f"marker={_user_marker!r} has no effect on histograms "
306+
f"(histtype={_ht_hint!r} — ax.hist does not render markers). "
307+
f"Use color= to distinguish groups instead.",
308+
UserWarning, stacklevel=3
309+
)
310+
292311
# Create figure if needed
293312
if ax is None:
294313
figsize = get_style_value("figure.figsize", (8, 6))
@@ -469,6 +488,12 @@ def draw_hist(
469488
bin_edges=shared_edges,
470489
hist_norm=hist_norm,
471490
min_entries=min_entries,
491+
# Phase 13.36.DF: forward user color from draw_hist's local variable
492+
# (consumed by explicit signature at line ~157, NOT in **kwargs).
493+
# Without this, the user's color= silently no-ops in the grouped path
494+
# (v1.0 P1-A pattern). marker= still flows through **kwargs to
495+
# _draw_hist_grouped where it's popped + warned.
496+
_user_color=color,
472497
density=density, weights=_hist_weights,
473498
alpha=alpha, histtype=histtype, edgecolor=edgecolor,
474499
linewidth=linewidth,
@@ -530,15 +555,24 @@ def _draw_hist_grouped(
530555
bin_edges: Optional[np.ndarray] = None, # Phase 13.35.DF: shared edges from full dataset
531556
hist_norm: Optional[str] = None, # Phase 13.35.DF: None | "probability" | "density"
532557
min_entries: int = 0, # Phase 13.35.DF: skip groups below threshold
558+
# Phase 13.36.DF: user color override (None = use per-group palette cycle).
559+
# 'color' is consumed by draw_hist()'s explicit signature — must be passed
560+
# as a named param from there (not via **kwargs which doesn't contain it).
561+
_user_color: Optional[str] = None,
533562
**hist_kwargs
534563
) -> int:
535564
"""Draw grouped/overlaid histograms.
536565
537566
Phase 13.35.DF: extended for float group_by binning + per-group normalization.
567+
Phase 13.36.DF: extended for user color override + marker UserWarning.
538568
Returns the number of groups actually rendered (post min_entries filter).
539569
"""
540570
import matplotlib.pyplot as plt
541571

572+
# Phase 13.36.DF: 'marker' is popped earlier in draw_hist() body, so it
573+
# cannot arrive here in hist_kwargs. The UserWarning fires once at the
574+
# draw_hist level regardless of grouped/non-grouped routing.
575+
542576
# Phase 13.35.DF: pop 'weights' from hist_kwargs — the grouped path uses
543577
# per-group hist_norm weights (from _group_weights), not the routing
544578
# block's _hist_weights (which is None on this path anyway because
@@ -564,6 +598,17 @@ def _draw_hist_grouped(
564598
# Use shared edges if provided; fall back to matplotlib auto-bin (or kwarg)
565599
bins_arg = bin_edges if bin_edges is not None else hist_kwargs.pop('bins', 100)
566600

601+
# Phase 13.36.DF: warn ONCE per call when user color= makes all groups
602+
# indistinguishable. Fires before either render branch.
603+
if _user_color is not None and len(groups) > 1:
604+
import warnings
605+
warnings.warn(
606+
f"color={_user_color!r} applied uniformly to all {len(groups)} groups. "
607+
f"Groups will be indistinguishable by color. "
608+
f"Omit color= to use per-group colors (default behavior).",
609+
UserWarning, stacklevel=3
610+
)
611+
567612
if stacked:
568613
# One-pass loop: build data_list, labels, AND surviving_colors in lockstep
569614
# so all three stay aligned when min_entries filters drop groups.
@@ -573,6 +618,8 @@ def _draw_hist_grouped(
573618
# P3 (color-shift) also fixed here: pre-Phase 13.35.DF, colors[:M] gave
574619
# sequential tab10 colors, not the original-index color per surviving
575620
# group; surviving_colors[i] preserves the original colors[i] mapping.
621+
# Phase 13.36.DF: when _user_color is set, surviving_colors becomes
622+
# uniform (user wants all groups same color — already warned above).
576623
data_list, labels, surviving_colors = [], [], []
577624
for i, g in enumerate(groups):
578625
d = df[df[group_by] == g][x].dropna().values.astype(float)
@@ -582,7 +629,10 @@ def _draw_hist_grouped(
582629
# _format_interval_label is defined in profile.py and NOT
583630
# imported here. (v1.1 P1-A from review panel.)
584631
labels.append(str(g))
585-
surviving_colors.append(colors[i])
632+
# Phase 13.36.DF: user override > palette.
633+
surviving_colors.append(
634+
colors[i] if _user_color is None else _user_color
635+
)
586636
if not data_list:
587637
return 0
588638
ax.hist(data_list, bins=bins_arg, label=labels,
@@ -592,16 +642,19 @@ def _draw_hist_grouped(
592642
# Overlaid histograms — one ax.hist call per surviving group.
593643
# colors[i] preserves original-index color when groups are skipped
594644
# (overlaid branch was already correct in baseline; documented for parity).
645+
# Phase 13.36.DF: user override > palette per group.
595646
n_rendered = 0
596647
for i, group in enumerate(groups):
597648
# BUG_dfdraw_20260505: cast to float for boolean expressions
598649
group_data = df[df[group_by] == group][x].dropna().values.astype(float)
599650
if len(group_data) < min_entries:
600651
continue
601652
weights = _group_weights(group_data, bin_edges, hist_norm)
653+
# Phase 13.36.DF: user override > palette
654+
group_color = colors[i] if _user_color is None else _user_color
602655
# Label via str(group) — not _format_interval_label. (v1.1 P1-A)
603656
ax.hist(group_data, bins=bins_arg,
604-
label=str(group), color=colors[i],
657+
label=str(group), color=group_color,
605658
weights=weights, **hist_kwargs)
606659
n_rendered += 1 # count post-skip (v1.1 P1-C from review panel)
607660
if n_rendered > 0:

UTILS/dfextensions/dfdraw/plots/profile.py

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,16 @@ def draw_profile(
308308
context="profile",
309309
)
310310

311+
# Phase 13.36.DF: capture user-explicit marker/markersize BEFORE the style
312+
# fill-in below (which sets marker='o', markersize=6 when user passed None).
313+
# We need to distinguish "user explicitly passed marker='s'" from "user
314+
# passed nothing; style filled in default 'o'". The grouped path uses
315+
# these to decide between uniform-override vs per-group cycle.
316+
# color is NOT filled in by style (matplotlib handles None directly).
317+
_ud_user_marker = marker # None or user's value
318+
_ud_user_markersize = markersize # None or user's value
319+
_ud_user_color = color # None or user's value
320+
311321
# Get style defaults
312322
if bins is None:
313323
bins = get_style_value("hist.bins", 50)
@@ -485,8 +495,20 @@ def draw_profile(
485495
# discrete lines per group color; see _draw_profile_grouped docstring.
486496
profile_data_list, _per_group_stats = _draw_profile_grouped(
487497
df_filtered, x, y, ax, group_col, top_k,
498+
# Phase 13.36.DF: forward user style overrides as named params
499+
# (BUG-013 fix). The user's marker/markersize/color values live in
500+
# draw_profile()'s LOCAL VARIABLES — but the style fill-in above
501+
# at lines 314-317 replaces None with style defaults BEFORE this
502+
# call. Use the _ud_user_* captures (None when user passed nothing)
503+
# to correctly distinguish explicit-pass from style-fill.
504+
_user_marker=_ud_user_marker,
505+
_user_markersize=_ud_user_markersize,
506+
_user_color=_ud_user_color,
488507
bins=bins, x_range=_used_xrange, error=error,
489-
marker=marker, markersize=markersize, capsize=capsize,
508+
# Phase 13.36.DF: marker= and markersize= REMOVED from this call.
509+
# They are now forwarded via _user_marker / _user_markersize above.
510+
# The previous pops at lines 984-985 are also deleted (nothing to pop).
511+
capsize=capsize,
490512
linestyle=linestyle, linewidth=linewidth,
491513
min_entries=min_entries,
492514
sort_groups=sort_groups,
@@ -913,6 +935,13 @@ def _draw_profile_grouped(
913935
quantile_pair: Optional[tuple] = None,
914936
quantile_list: Optional[list] = None,
915937
quantile_style: Optional[str] = None,
938+
# Phase 13.36.DF: user style overrides (BUG-013 fix).
939+
# None = "user did not pass" (matches matplotlib default-color semantics).
940+
# Non-None = apply uniformly to all groups, override the auto-cycle.
941+
# See module-level docstring for design rationale.
942+
_user_marker: Optional[str] = None,
943+
_user_markersize: Optional[float] = None,
944+
_user_color: Optional[str] = None,
916945
**profile_kwargs
917946
) -> tuple:
918947
"""
@@ -980,9 +1009,13 @@ def _draw_profile_grouped(
9801009
x_range = profile_kwargs.pop('x_range', None)
9811010
error = profile_kwargs.pop('error', 'sem')
9821011
linewidth = profile_kwargs.get('linewidth', 1.5)
983-
# Remove marker/markersize from kwargs - we use fmt and dedicated markers
984-
profile_kwargs.pop('marker', None)
985-
profile_kwargs.pop('markersize', None)
1012+
# Phase 13.36.DF: pops for 'marker' and 'markersize' DELETED. These values
1013+
# are now forwarded as _user_marker / _user_markersize named params from
1014+
# draw_profile() (the local variables where the user's values live after
1015+
# consumption by draw_profile()'s explicit signature). The call site at
1016+
# line 489 no longer passes marker=marker / markersize=markersize.
1017+
# Both vector and non-vector paths route the values through _user_* params.
1018+
# → Nothing reaches profile_kwargs to pop.
9861019

9871020
# Phase 13.12.DF F1: Collect profile data
9881021
profile_data_list = [] if return_data else None
@@ -1028,7 +1061,22 @@ def _draw_profile_grouped(
10281061
# Phase 13.12.DF F2: Apply min_entries filter for plotting
10291062
plot_mask = bin_counts >= min_entries
10301063

1031-
group_color = palette(i % 10)
1064+
# Phase 13.36.DF: user color override > palette cycle.
1065+
# None = "user did not pass" (matches matplotlib default-color semantics).
1066+
group_color = (palette(i % 10)
1067+
if _user_color is None
1068+
else _user_color)
1069+
1070+
# Phase 13.36.DF: warn ONCE per call (i == 0) when color= makes all
1071+
# groups indistinguishable. Architect decision 2026-05-20.
1072+
if i == 0 and _user_color is not None and len(groups) > 1:
1073+
import warnings
1074+
warnings.warn(
1075+
f"color={_user_color!r} applied uniformly to all {len(groups)} groups. "
1076+
f"Groups will be indistinguishable by color. "
1077+
f"Omit color= to use per-group colors (default behavior).",
1078+
UserWarning, stacklevel=4
1079+
)
10321080

10331081
# Phase 13.32.DF Sub-fix 2: per-group quantile rendering BEFORE the
10341082
# central line so the central line stays visually on top.
@@ -1073,10 +1121,16 @@ def _draw_profile_grouped(
10731121
per_group_stats[group]['quantiles_per_bin'] = _q_all
10741122

10751123
# Central line (mean or median) — always rendered last so it sits on top
1124+
# Phase 13.36.DF: user marker/markersize override > cycle.
1125+
# None on either passes through to matplotlib defaults (correct).
1126+
group_marker = (markers[i % len(markers)]
1127+
if _user_marker is None
1128+
else _user_marker)
10761129
ax.errorbar(
10771130
bin_centers[plot_mask], bin_means[plot_mask], yerr=bin_errors[plot_mask],
1078-
fmt=markers[i % len(markers)],
1131+
fmt=group_marker,
10791132
color=group_color,
1133+
markersize=_user_markersize, # None → matplotlib default
10801134
# If quantiles already added a legend entry for this group, suppress
10811135
# the duplicate central-line legend entry by setting label=None.
10821136
label=(None if quantiles is not None and quantile_list is not None

0 commit comments

Comments
 (0)