Skip to content

Commit b84576a

Browse files
author
miranov25
committed
PHASE 13.41.DF FIX1 — 3 bug fixes carried forward from v1.6 panel
Items closed: §2.1: Sonnet54 P2 — auto_title=True silently dropped in 2D/3D facet. Now routes to fig.suptitle (cells reserved for facet labels). User-supplied title= takes precedence. Locked by §9.FBY.22. §2.2: StringDtype _process_color (Linux Py3.12 CI fail since Phase 13.38). Try/except astype with fallback to categorical mode. test_vector_draw_kwarg_surface_enumeration now passes. §2.3: DFDraw.* signature type hints (CRR §5 deferral from v1.6): facet_by → Optional[Union[str, List[str]]]; share_x/share_y/share_across_figures added as named params on draw/hist/profile/scatter/hist2d + forwarded at dispatch call sites + added to 5 _*_FORWARDED_NAMES tuples (R6 validator + IDE autocomplete unblocked). New §9 regression locks (3): FBY.20: share_y='row' symmetry to FBY.12 (Sonnet55 v1.6 END advisory) FBY.21: share_x='invalid' → ValueError (Sonet51 v1.4 advisory) FBY.22: auto_title=True suptitle lock (Sonnet54 P2) Tests: 942 → 945 (+3 §9 invariance).
1 parent 530954d commit b84576a

6 files changed

Lines changed: 247 additions & 26 deletions

File tree

UTILS/dfextensions/dfdraw/docs/CAPABILITY_MATRIX.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Capability Matrix — dfdraw
22

3-
**Generated:** 2026-05-23 07:18 UTC
3+
**Generated:** 2026-05-23 10:28 UTC
44
**Phase:** 13.15.DF
55
**Generator:** `scripts/generate_capability_matrix.py`
66
**Sources:** `tests/feature_taxonomy.py` + `tests/test_layer_classification.py`
@@ -14,8 +14,8 @@
1414
| 🧨 Broken | 0 | 0% |
1515
| 📋 Planned | 1 | 1% |
1616
| **Total features** | **107** | |
17-
| **Total proof tests** | **497** | |
18-
| **Invariance tests** | **268** | |
17+
| **Total proof tests** | **500** | |
18+
| **Invariance tests** | **271** | |
1919

2020
**Status key:**
2121
- ✅ Verified — has at least one invariance test (A ≡ B check)
@@ -170,7 +170,7 @@
170170
| | **HIST** | | |
171171
|| **HIST.cumulative** — hist() cumulative=True/-1/False — ROOT TH1::Draw('cumulative') equivalent. Three values: True (ascending CDF/ECDF), False (default, byte-identical backward compat), -1 (descending/survival, ROOT convention). matplotlib native cumulative= forwarded explicitly at 4 internal call sites (Phase 13.39 §2.2 lesson applied recursively: DFDraw.hist → draw_hist → _draw_hist_grouped → ax.hist; ALSO through _dispatch_faceted_render for facet_by composition). Composes with: norm='probability' (→ ECDF 0-1), group_by overlaid (per-group ECDFs), group_by stacked (CP2-1 regression lock for 3rd call site), facet_by (per-facet cumulative), histtype='step' (HEP-standard step ECDF). Correctness guard (M5): hist_errors+cumulative → NotImplementedError (Poisson per-bin errors are independent; cumulative counts are correlated). Vector dispatch [x,y] propagates cumulative correctly (Phase 13.16.DF FIX1 bug class lock) — Phase 13.40.DF | 10 | 0 |
172172
| | **FACET** | | |
173-
| ✅ | **FACET.list_grid** — facet_by accepts Union[str, List[str]] for 1D/2D/3D faceting. Convention LOCKED matching numpy/pandas (n_rows, n_cols, ...) shape: facet_by[0]=ROW (vertical within figure), facet_by[1]=COLUMN (horizontal within figure), facet_by[2]=FIGID (separate figures, one per value). facet_by[3+] raises NotImplementedError. 3D returns (List[Figure], List[axes_2d], List[stats_dict]) — DEVIATES from standard (fig, ax, stats) contract; documented prominently in inline help. New params: share_x/share_y ∈ {'all','row','col','none'} (within-figure axis sharing), share_across_figures: bool (3D global range lock). Per-plot-kind lock for share_across_figures (CP1-2): scatter locks x AND y; hist/profile locks x only (y auto-scales per figure to handle sparse-figID variance). New helpers: _normalize_facet_args, _to_mpl_share (symmetric {'all':True,'row':'row','col':'col','none':False} — v1.2 CP0-1 fix for Hard Constraint #3), _validate_share_axis_value, _resolve_facet_values (discrete or pd.cut/qcut Interval), _filter_facet_value (CP1-3 discrete vs binned), _compute_global_ranges. dfdraw is FIRST major plotting library with unified API where Nth faceting dimension generates separate figures (seaborn/ggplot2/plotly/altair all require manual loops). _validate_facet_by_binning guard for list input (v1.3 P1-A). Per-plot-kind dispatch: hist uses range= (matplotlib convention); profile uses range= which DFDraw.profile remaps to draw_profile's x_range= internally; scatter uses ax.set_xlim/set_ylim post-draw (no native range params); hist also locks ax.set_xlim post-draw (range= only locks bins, not axis xlim). Empty cell handling: '(no data)' diagnostic + stats={'n':0,'empty':True} — Phase 13.41.DF | 19 | 0 |
173+
| ✅ | **FACET.list_grid** — facet_by accepts Union[str, List[str]] for 1D/2D/3D faceting. Convention LOCKED matching numpy/pandas (n_rows, n_cols, ...) shape: facet_by[0]=ROW (vertical within figure), facet_by[1]=COLUMN (horizontal within figure), facet_by[2]=FIGID (separate figures, one per value). facet_by[3+] raises NotImplementedError. 3D returns (List[Figure], List[axes_2d], List[stats_dict]) — DEVIATES from standard (fig, ax, stats) contract; documented prominently in inline help. New params: share_x/share_y ∈ {'all','row','col','none'} (within-figure axis sharing), share_across_figures: bool (3D global range lock). Per-plot-kind lock for share_across_figures (CP1-2): scatter locks x AND y; hist/profile locks x only (y auto-scales per figure to handle sparse-figID variance). New helpers: _normalize_facet_args, _to_mpl_share (symmetric {'all':True,'row':'row','col':'col','none':False} — v1.2 CP0-1 fix for Hard Constraint #3), _validate_share_axis_value, _resolve_facet_values (discrete or pd.cut/qcut Interval), _filter_facet_value (CP1-3 discrete vs binned), _compute_global_ranges. dfdraw is FIRST major plotting library with unified API where Nth faceting dimension generates separate figures (seaborn/ggplot2/plotly/altair all require manual loops). _validate_facet_by_binning guard for list input (v1.3 P1-A). Per-plot-kind dispatch: hist uses range= (matplotlib convention); profile uses range= which DFDraw.profile remaps to draw_profile's x_range= internally; scatter uses ax.set_xlim/set_ylim post-draw (no native range params); hist also locks ax.set_xlim post-draw (range= only locks bins, not axis xlim). Empty cell handling: '(no data)' diagnostic + stats={'n':0,'empty':True} — Phase 13.41.DF | 22 | 0 |
174174

175175
---
176176

0 commit comments

Comments
 (0)