1111| ` facet.py ` | "Facet plot utilities for dfdraw. Creates subplot grids..." | [ OK] Present |
1212| ` style.py ` | "Style management for dfdraw. Supports: Predefined styles..." | [ OK] Present, comprehensive |
1313| ` stats.py ` | "Statistics computation for dfdraw. Phase 13.6.G.DF: Statistics Enhancements..." | [ OK] Present, comprehensive |
14+ | ` _auto_title.py ` | "Auto-title helpers for dfdraw plot functions. Phase 13.12.DF v1.2..." | [ OK] Present |
1415
1516** Assessment:** All files have module-level docstrings. [ OK]
1617
@@ -37,19 +38,94 @@ Values are approximately 6% smaller than previous versions.
3738| Method | Signature | Description |
3839| --------| -----------| -------------|
3940| ` __init__ ` | ` __init__(self, data) ` | Create drawer from DataFrame, AliasDataFrame, PyArrow Table, or dict |
40- | ` draw ` | ` draw(expr, type=None, selection=None, color=None, size=None, marker=None, group_by=None, facet=False, bins=None, stats=None, norm=None, title=None, ax=None, sample=None, save=None, **kwargs) ` | Universal draw method with auto type detection |
41- | ` hist ` | ` hist(expr, bins=None, range=None, norm=None, stats=None, title=None, xlabel=None, ylabel=None, color=None, alpha=None, histtype=None, edgecolor=None, linewidth=None, label=None, group_by=None, top_k=None, stacked =False, **kwargs) ` | Draw 1D histogram |
42- | ` scatter ` | ` scatter(expr, color=None, size=None, marker=None, stats=None, title=None, xlabel=None, ylabel=None, alpha=None, edgecolors=None, linewidths=None, cmap=None, colorbar=True, clabel=None, group_by=None, top_k=None, jitter=None , **kwargs) ` | Draw scatter plot |
43- | ` profile ` | ` profile(expr, bins=None, x_range=None, error="sem", stats =None, title =None, xlabel=None, ylabel =None, color=None, marker=None, markersize=None, capsize=None, linestyle=None, linewidth=None, label=None, group_by=None, top_k=None , **kwargs) ` | Draw profile plot (mean of y vs binned x) |
44- | ` hist2d ` | ` hist2d(expr, bins=None, range=None, norm=None, stats=None, title=None, xlabel=None, ylabel=None, cmap=None, colorbar=True, clabel=None, vmin=None, vmax=None , **kwargs) ` | Draw 2D histogram |
45- | ` hexbin ` | ` hexbin(expr, gridsize=50, extent=None, norm=None, stats=None, title=None, xlabel=None, ylabel=None, cmap=None, colorbar=True, clabel=None, mincnt=None, vmin=None, vmax=None , **kwargs) ` | Draw hexbin plot |
41+ | ` draw ` | ` draw(expr, type=None, selection=None, color=None, size=None, marker=None, group_by=None, facet=False, bins=None, stats=None, norm=None, title=None, ax=None, sample=None, save=None, figsize=None, same=False, **kwargs) ` | Universal draw method with auto type detection |
42+ | ` hist ` | ` hist(expr, ..., auto_title=False, same =False, **kwargs) ` | Draw 1D histogram |
43+ | ` scatter ` | ` scatter(expr, ..., same=False , **kwargs) ` | Draw scatter plot |
44+ | ` profile ` | ` profile(expr, ..., return_data=False, min_entries=3, group_by_bins =None, group_by_quantiles =None, sort_groups=True, weights =None, auto_title=False, same=False , **kwargs) ` | Draw profile plot (mean of y vs binned x) |
45+ | ` hist2d ` | ` hist2d(expr, ..., auto_title=False, same=False , **kwargs) ` | Draw 2D histogram |
46+ | ` hexbin ` | ` hexbin(expr, ..., auto_title=False, same=False , **kwargs) ` | Draw hexbin plot |
4647| ` stats ` | ` stats(expr, selection=None, group_by=None) ` | Compute statistics without plotting |
47- | ` draw_batch ` | ` draw_batch(specs, save_dir=None, defaults=None, on_error='skip', verbose=True, save_format='png', dpi=150, close_figures=True, **kwargs) ` | Batch plot generation from specification dict or YAML/JSON |
48+ | ` draw_batch ` | ` draw_batch(specs, save_dir=None, defaults=None, on_error='skip', verbose=True, save_format='png', dpi=150, close_figures=True, **kwargs) ` | Batch plot generation — dict format or list-of-groups format |
4849| ` add_statistics_box ` | ` add_statistics_box(ax, values, position='upper right', expected_mean=None, expected_std=None, precision=3, fontsize=8, alpha=0.5) ` | Add statistics annotation box to axis |
4950| ` add_reference_overlay ` | ` add_reference_overlay(ax, func='gaussian', mu=0, sigma=1, label=None, color='red', linestyle='--', linewidth=1.5, show_legend=True, n_points=100) ` | Add reference function overlay scaled to histogram |
5051| ` backend ` | ` @property ` | Return storage backend type ('pyarrow' or 'pandas') |
5152| ` memory_info ` | ` memory_info() ` | Return memory usage information |
5253
54+ ### New Parameters (Phase 13.12–13.14.DF)
55+
56+ #### same=True — Plot Superposition (Phase 13.13.DF, AD-15)
57+
58+ Available on all draw methods: ` draw() ` , ` hist() ` , ` scatter() ` , ` profile() ` , ` hist2d() ` , ` hexbin() ` .
59+
60+ ``` python
61+ same: bool = False
62+ ```
63+
64+ When ` True ` :
65+ - Reuses last axes (` self._last_ax ` ) or falls back to ` plt.gca() `
66+ - Auto-increments colors from palette (AD-16)
67+ - Auto-generates label from expression (AD-17)
68+ - Appends to title when ` auto_title=True ` (AD-18)
69+ - Shows legend automatically
70+
71+ Precedence: ` ax= ` wins over ` same=True ` . Explicit ` color= ` , ` label= ` , ` title= ` override auto-features.
72+
73+ #### auto_title — Automatic Title (Phase 13.12.DF v1.2)
74+
75+ Available on: ` hist() ` , ` profile() ` , ` hist2d() ` , ` hexbin() ` .
76+
77+ ``` python
78+ auto_title: Union[bool , str ] = False
79+ ```
80+
81+ Values:
82+ - ` False ` : no auto-title (default, or from style)
83+ - ` True ` / ` "all" ` : "y vs x group: group_by weights: w \nselection"
84+ - ` "expr" ` : "y vs x" only
85+ - ` "expr+group" ` : "y vs x group: group_by "
86+ - ` "expr+sel" ` : "y vs x\nselection"
87+
88+ Explicit ` title= ` always overrides ` auto_title ` .
89+
90+ #### Profile-Specific Parameters (Phase 13.12.DF)
91+
92+ ``` python
93+ return_data: bool = False # F1: Include profile DataFrame in stats_dict
94+ min_entries: int = 3 # F2: Min entries per bin to plot (AD-1)
95+ group_by_bins: int = None # F3: Equal-width bins for float group_by
96+ group_by_quantiles: int = None # F3: Equal-count bins for float group_by
97+ sort_groups: bool = True # F4: Sort groups in legend
98+ weights: str = None # v1.1: Column name for weighted statistics
99+ ```
100+
101+ #### draw_batch — List Format (Phase 13.14.DF)
102+
103+ ` specs ` parameter now accepts ` list ` (group format) in addition to ` dict ` (original format):
104+
105+ ``` python
106+ specs: Union[Dict[str , Dict[str , Any]], List[Dict[str , Any]], str ]
107+ ```
108+
109+ Group spec keys:
110+ - ` name ` (required), ` plots ` (required)
111+ - ` defaults ` , ` ncols ` , ` layout ` , ` figsize ` , ` suptitle ` , ` savefig ` , ` sharex ` , ` sharey `
112+
113+ Option hierarchy: ` kwargs < draw_batch defaults= < group['defaults'] < plot_spec `
114+
115+ #### verbose — Verbosity Levels (Phase 13.14.DF)
116+
117+ ``` python
118+ verbose: Union[bool , int ] = True
119+ ```
120+
121+ | Value | Behavior |
122+ | -------| ----------|
123+ | ` False ` / ` 0 ` | Silent |
124+ | ` True ` / ` 1 ` | Progress — group names, save paths, summary |
125+ | ` 2 ` | Debug — also prints merged parameters per plot |
126+
127+ ---
128+
53129### Annotation Methods (Phase 12.4b5)
54130
55131#### ` add_statistics_box() `
@@ -148,9 +224,9 @@ def add_reference_overlay(
148224
149225| Function | Signature | Description |
150226| ----------| -----------| -------------|
151- | ` draw_hist ` | ` draw_hist(df, x, ax=None, bins=None, range=None, norm=None, stats=None, title=None, xlabel=None, ylabel=None, color=None, alpha=None, histtype=None, edgecolor=None, linewidth=None, label=None, group_by=None, top_k=None, stacked=False, **kwargs) ` | Draw 1D histogram |
152- | ` draw_hist2d ` | ` draw_hist2d(df, x, y, ax=None, bins=None, range=None, norm=None, stats=None, title=None, xlabel=None, ylabel=None, cmap=None, colorbar=True, clabel=None, vmin=None, vmax=None, **kwargs) ` | Draw 2D histogram |
153- | ` draw_hexbin ` | ` draw_hexbin(df, x, y, ax=None, gridsize=50, extent=None, norm=None, stats=None, title=None, xlabel=None, ylabel=None, cmap=None, colorbar=True, clabel=None, mincnt=None, vmin=None, vmax=None, **kwargs) ` | Draw hexbin plot |
227+ | ` draw_hist ` | ` draw_hist(df, x, ax=None, bins=None, range=None, norm=None, stats=None, title=None, xlabel=None, ylabel=None, color=None, alpha=None, histtype=None, edgecolor=None, linewidth=None, label=None, group_by=None, top_k=None, stacked=False, auto_title=False, selection=None, **kwargs) ` | Draw 1D histogram |
228+ | ` draw_hist2d ` | ` draw_hist2d(df, x, y, ax=None, bins=None, range=None, norm=None, stats=None, title=None, xlabel=None, ylabel=None, cmap=None, colorbar=True, clabel=None, vmin=None, vmax=None, auto_title=False, selection=None, **kwargs) ` | Draw 2D histogram |
229+ | ` draw_hexbin ` | ` draw_hexbin(df, x, y, ax=None, gridsize=50, extent=None, norm=None, stats=None, title=None, xlabel=None, ylabel=None, cmap=None, colorbar=True, clabel=None, mincnt=None, vmin=None, vmax=None, auto_title=False, selection=None, **kwargs) ` | Draw hexbin plot |
154230
155231### scatter.py - Functions
156232
@@ -162,7 +238,19 @@ def add_reference_overlay(
162238
163239| Function | Signature | Description |
164240| ----------| -----------| -------------|
165- | ` draw_profile ` | ` draw_profile(df, x, y, ax=None, bins=None, x_range=None, error="sem", stats=None, title=None, xlabel=None, ylabel=None, color=None, marker=None, markersize=None, capsize=None, linestyle=None, linewidth=None, label=None, group_by=None, top_k=None, **kwargs) ` | Draw profile plot |
241+ | ` draw_profile ` | ` draw_profile(df, x, y, ax=None, bins=None, x_range=None, error="sem", stats=None, title=None, xlabel=None, ylabel=None, color=None, marker=None, markersize=None, capsize=None, linestyle=None, linewidth=None, label=None, group_by=None, top_k=None, return_data=False, min_entries=3, group_by_bins=None, group_by_quantiles=None, sort_groups=True, weights=None, auto_title=False, selection=None, **kwargs) ` | Draw profile plot |
242+ | ` _format_interval_label ` | ` _format_interval_label(interval) -> str ` | Format pandas Interval as 'low-high' string (AD-3) |
243+ | ` _interval_sort_key ` | ` _interval_sort_key(label) -> tuple ` | Sort key for interval labels including negative ranges |
244+
245+ ### _ auto_title.py - Functions (Phase 13.12.DF v1.2)
246+
247+ | Function | Signature | Description |
248+ | ----------| -----------| -------------|
249+ | ` parse_auto_title_parts ` | ` parse_auto_title_parts(auto_title) -> set ` | Parse auto_title parameter into set of parts |
250+ | ` build_auto_title ` | ` build_auto_title(x, y=None, group_by=None, selection=None, weights=None, parts=...) -> dict ` | Build auto-title dict with 'main' and 'sub' keys |
251+ | ` apply_auto_title ` | ` apply_auto_title(ax, title_dict, fontsize=None, sub_fontsize=None) ` | Apply auto-title to axes (first plot) |
252+ | ` append_auto_title ` | ` append_auto_title(ax, title_dict, fontsize=None, sub_fontsize=None) ` | Append to existing title for same=True overlay (Phase 13.13.DF) |
253+ | ` resolve_auto_title ` | ` resolve_auto_title(auto_title) -> bool\|str ` | Resolve auto_title: per-call value > style default |
166254
167255### facet.py - Functions
168256
@@ -335,6 +423,23 @@ stats_dict = {
335423
336424 # Group stats (additional)
337425 " grouped" : bool , # Was group_by used?
426+
427+ # Profile data export (when return_data=True, Phase 13.12.DF)
428+ " profile_data" : DataFrame, # x_center, x_low, x_high, y_mean, y_std, y_sem, count
429+ }
430+ ```
431+
432+ ** draw_batch return (list format, Phase 13.14.DF):**
433+ ``` python
434+ results = {
435+ ' group_name' : {
436+ ' fig' : Figure, # None if close_figures + save
437+ ' axes' : [ax1, ax2, ... ], # List of subplot axes
438+ ' stats' : [stats1, stats2, ... ], # Stats per plot
439+ ' path' : ' saved/path.png' , # Save path or None
440+ },
441+ ' _errors' : {' name' : ' error message' },
442+ ' _summary' : {' total' : int , ' success' : int , ' failed' : int },
338443}
339444```
340445
@@ -364,7 +469,7 @@ stats_dict = {
364469
365470---
366471
367- ## Style Keys (Phase 13.6.G .DF Updated)
472+ ## Style Keys (Phase 13.14 .DF Updated)
368473
369474| Key | Default | Description |
370475| -----| ---------| -------------|
@@ -374,7 +479,10 @@ stats_dict = {
374479| ` stats.fontsize ` | 10 | Stats box font size |
375480| ` stats.alpha ` | 0.8 | Stats box transparency |
376481| ` stats.boxstyle ` | "round" | Stats box style |
377- | ` stats.robust ` | False | ** NEW** Use robust defaults for 1D (median, MAD) |
482+ | ` stats.robust ` | False | Use robust defaults for 1D (median, MAD) |
483+ | ` auto_title ` | False | Enable auto-title globally (Phase 13.12.DF v1.2) |
484+ | ` auto_title.fontsize ` | 10 | Auto-title main font size |
485+ | ` auto_title.sel_fontsize ` | 8 | Auto-title selection subtitle font size |
378486
379487---
380488
@@ -423,6 +531,7 @@ stats_dict = {
423531| ` tree->Draw("y:x", "", "prof") ` | ` drawer.draw("y:x", type="profile") ` | Profile |
424532| ` tree->Draw("y:x", "", "colz") ` | ` drawer.draw("y:x", type="hist2d") ` | 2D histogram |
425533| ` tree->Draw("y:x>>h(100,0,1)") ` | ` drawer.draw("y:x", bins=100, range=(0,1)) ` | Custom binning |
534+ | ` hist2->Draw("same") ` | ` drawer.draw("y:x", same=True) ` | Superposition (Phase 13.13.DF) |
426535
427536** Phase 13.6.G.DF:** Stats now computed within range, matching ROOT behavior.
428537
@@ -444,9 +553,13 @@ stats_dict = {
444553| ` test_adf_integration.py ` | AliasDataFrame duck-typing, axis titles |
445554| ` test_validation_display.py ` | Statistics box, reference overlay |
446555| ` test_pyarrow_input.py ` | PyArrow Table input support |
447- | ` test_stats_enhancements.py ` | ** NEW** Statistics enhancements (Phase 13.6.G.DF) |
556+ | ` test_stats_enhancements.py ` | Statistics enhancements (Phase 13.6.G.DF) |
557+ | ` test_auto_title.py ` | Auto-title system (Phase 13.12.DF v1.2) |
558+ | ` test_profile_phase13_12.py ` | Profile enhancements: return_data, min_entries, group_by_bins, weights |
559+ | ` test_same.py ` | same=True superposition: axes reuse, colors, labels, titles (Phase 13.13.DF) |
560+ | ` test_batch_groups.py ` | Batch groups: defaults cascade, layouts, same=True, verbose levels (Phase 13.14.DF) |
448561
449- ** Total tests:** 310 passing
562+ ** Total tests:** 399 passing
450563
451564---
452565
@@ -471,3 +584,41 @@ stats_dict = {
471584
472585- ` compute_stats(..., range_x=None, range_y=None, robust=False) `
473586- ` format_stats_box(..., plot_type=None) `
587+
588+ ---
589+
590+ ## Phase 13.12–13.14.DF Summary
591+
592+ ### Phase 13.12.DF — Profile Enhancements
593+
594+ - ` return_data=True ` : export profile stats as DataFrame
595+ - ` min_entries=3 ` : suppress low-statistics bins
596+ - ` group_by_bins ` /` group_by_quantiles ` : auto-bin float columns
597+ - ` sort_groups=True ` : sorted legend order
598+ - ` weights='col' ` : weighted mean/std/sem
599+ - ` auto_title ` : automatic title system
600+
601+ ### Phase 13.13.DF — same=True Superposition
602+
603+ - ` same=True ` on all draw methods
604+ - Auto-increment colors, auto-labels, title append
605+ - ` self._last_ax ` tracking with ` plt.gca() ` fallback
606+ - ` append_auto_title() ` for title merging
607+
608+ ### Phase 13.14.DF — draw_batch Defaults Hierarchy
609+
610+ - List-of-groups format with option hierarchy
611+ - Subplot grid: ` ncols ` , ` layout=(r,c) ` , ` figsize ` , ` suptitle `
612+ - ` same=True ` within groups
613+ - ` verbose=2 ` debug mode (merged params per plot)
614+ - Interval sort fix for negative ranges
615+
616+ ---
617+
618+ ## Revision History
619+
620+ | Version | Date | Author | Changes |
621+ | ---------| ------| --------| ---------|
622+ | 1.0 | 2026-01-14 | Main Reviewer | Initial API_REFERENCE.md |
623+ | 1.1 | 2026-01-29 | Claude-Main | Added Phase 13.6.G.DF stats API |
624+ | 1.2 | 2026-03-28 | Claude41 | Added Phase 13.12-13.14 APIs: same=, auto_title=, profile params, list format, verbose=int, _ auto_title.py functions, _ interval_sort_key, updated test coverage to 399 |
0 commit comments