Skip to content

add tree-coloring appearance-tuning parameters#3

Merged
jbloom merged 1 commit intomainfrom
tree-appearance-tuning
May 6, 2026
Merged

add tree-coloring appearance-tuning parameters#3
jbloom merged 1 commit intomainfrom
tree-appearance-tuning

Conversation

@jbloom
Copy link
Copy Markdown
Member

@jbloom jbloom commented May 6, 2026

Three new parameters that work alongside color_tree_by (released in the prior PR) to give users control over the tree-coloring legend and the scale-bar label:

  • tree_color_scale (default None): override the default palette with an explicit {category: color} mapping. Keys must match the tree's categories one-to-one (mismatch raises a ValueError listing the actual categories so the user can copy them); legend order follows the dict's insertion order. "unknown" is auto-appended in gray and may not be specified by the user. CLI form is a comma-separated key=color list parsed by a custom click.ParamType.

  • tree_color_legend_format (default None): pass any subset of Vega-Lite's Legend properties as a dict (orient, direction, columns, padding, labelFontSize, titleFontSize, …) shallow- merged onto the package defaults. Smart default: when the final orient is "left" or "right" and the user has not set columns or direction, columns=1 is forced — this counteracts chart-level legend.columns defaults that would otherwise pack a side-anchored legend horizontally. CLI form is a JSON object string.

  • tree_color_legend_show (default True): explicit boolean to hide the legend while keeping the tree colored — replaces the older legend_loc="none" mechanism with a clearer surface.

  • scale_bar_font_size (default 10): replaces the previously- hardcoded fontSize=10 in _build_scale_bar_layer.

The legend wiring lives entirely in _build_tree_chart: a default dict of {"orient": "bottom", "title": <derived>} is merged with the user's legend_format, then the smart-default columns rule is applied, then the result is passed to alt.Legend(...). The legend_show boolean determines whether alt.Color receives the built legend or legend=None.

CLI auto-generation in cli.py gains a second dict-typed param branch: _is_str_dict is tightened to match dict[str, str] exactly, and a new _is_dict_any predicate plus
_JsonDictParamType route dict[str, Any] (and its | None variant) to a JSON-object parser. The bool flag auto-flows through the existing dual-form handler (--tree-color-legend-show / --no-tree-color-legend-show).

Documentation: a new "Customizing the colors and legend" subsection in docs/examples.md shows all four knobs with a worked H3N2 example (Okabe-Ito-inspired 6-color palette ordered K, J.2.4, J.2.3, J.2.2, J.2, G.1.3.1; legend on the left at 14pt; scale bar at 14pt). The scripts/generate_docs_assets.py build adds an h3n2_combined_custom_colors SVG + interactive HTML that the section embeds and links.

Tests: tests/test_appearance_tuning.py (new, 27 tests) covers scale validation (order preservation, missing/extra/unknown keys, genotype/haplotype category-string formats); plot() end-to-end (scale propagation, scale-without-color_tree_by raises); legend format defaults, font-size propagation, orient override, smart-default columns=1 for left/right, user-columns and user-direction beating the smart default, smart default skipped for top/bottom orients; legend_show hide; scale-bar font size; and CLI coverage for all four knobs (including JSON-error paths).

Three new parameters that work alongside `color_tree_by` (released in
the prior PR) to give users control over the tree-coloring legend and
the scale-bar label:

- `tree_color_scale` (default `None`): override the default palette
  with an explicit `{category: color}` mapping. Keys must match the
  tree's categories one-to-one (mismatch raises a `ValueError` listing
  the actual categories so the user can copy them); legend order
  follows the dict's insertion order. `"unknown"` is auto-appended in
  gray and may not be specified by the user. CLI form is a
  comma-separated `key=color` list parsed by a custom `click.ParamType`.

- `tree_color_legend_format` (default `None`): pass any subset of
  Vega-Lite's Legend properties as a dict (`orient`, `direction`,
  `columns`, `padding`, `labelFontSize`, `titleFontSize`, …) shallow-
  merged onto the package defaults. Smart default: when the final
  `orient` is `"left"` or `"right"` and the user has not set `columns`
  or `direction`, `columns=1` is forced — this counteracts chart-level
  `legend.columns` defaults that would otherwise pack a side-anchored
  legend horizontally. CLI form is a JSON object string.

- `tree_color_legend_show` (default `True`): explicit boolean to hide
  the legend while keeping the tree colored — replaces the older
  `legend_loc="none"` mechanism with a clearer surface.

- `scale_bar_font_size` (default `10`): replaces the previously-
  hardcoded `fontSize=10` in `_build_scale_bar_layer`.

The legend wiring lives entirely in `_build_tree_chart`: a default
dict of `{"orient": "bottom", "title": <derived>}` is merged with the
user's `legend_format`, then the smart-default columns rule is
applied, then the result is passed to `alt.Legend(...)`. The
`legend_show` boolean determines whether `alt.Color` receives the
built legend or `legend=None`.

CLI auto-generation in `cli.py` gains a second dict-typed param
branch: `_is_str_dict` is tightened to match `dict[str, str]`
exactly, and a new `_is_dict_any` predicate plus
`_JsonDictParamType` route `dict[str, Any]` (and its `| None`
variant) to a JSON-object parser. The `bool` flag auto-flows
through the existing dual-form handler (`--tree-color-legend-show /
--no-tree-color-legend-show`).

Documentation: a new "Customizing the colors and legend" subsection
in `docs/examples.md` shows all four knobs with a worked H3N2
example (Okabe-Ito-inspired 6-color palette ordered K, J.2.4, J.2.3,
J.2.2, J.2, G.1.3.1; legend on the left at 14pt; scale bar at
14pt). The `scripts/generate_docs_assets.py` build adds an
`h3n2_combined_custom_colors` SVG + interactive HTML that the
section embeds and links.

Tests: `tests/test_appearance_tuning.py` (new, 27 tests) covers
scale validation (order preservation, missing/extra/`unknown`
keys, genotype/haplotype category-string formats); plot()
end-to-end (scale propagation, scale-without-`color_tree_by`
raises); legend format defaults, font-size propagation, orient
override, smart-default `columns=1` for left/right, user-columns
and user-direction beating the smart default, smart default
skipped for top/bottom orients; `legend_show` hide; scale-bar font
size; and CLI coverage for all four knobs (including JSON-error
paths).
@jbloom jbloom merged commit 2471de4 into main May 6, 2026
3 checks passed
@jbloom jbloom deleted the tree-appearance-tuning branch May 6, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant