feat(channels)!: emission-band colorblind palette + source-file opt-in#58
Merged
Merged
Conversation
…file opt-in Replaces the fluorophore-name → true-color lookup with an emission-band scheme (cyan/green/yellow/magenta/white — the Nature Methods "Points of View" CMY palette) so overlays stay distinguishable under red-green colorblindness and no two red-family dyes collide the way ALEXA 546 and ALEXA 647 did under the old substring match. Colors are driven by what the eye sees (emission midpoint), falling back to excitation, then dye-name substring, then a round-robin palette; residual collisions reallocate through UNKNOWN_PALETTE and fire ChannelColorCollisionWarning naming the reassigned channel so users know to reach for the override mechanism. Adds channel_colors="source-file" as a third accepted value on convert(): trusts the source file's stored per-channel color (LIF LUTName, OME-XML ARGB int) where present, falling through to the emission-band scheme where not. config.channel_colors in the audit record preserves the literal value (dict, None, or "source-file") so downstream tools can distinguish user intent. NAME_COLORS / PALETTE / color_for_channel are removed rather than kept as deprecated shims — the failure at import time is loud on purpose and no pilot user depends on the exact old hex values. See ADR-0007 for the full rationale, band boundaries, source-file design, and the resolution of the "555 nm" ambiguity from the reporting session (excitation, not emission — the excitation-fallback table's [545, 620) magenta band covers the yellow-orange laser bucket). Closes #51 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 tasks
…n-band-channel-colors # Conflicts: # CHANGELOG.md # src/zarrmony/api.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
channel_colors.pywith an emission-band colorblind palette (cyan / green / yellow / magenta / white) per the ADR-0007 Nature Methods "Points of View" recommendation. Colors are driven by what the eye sees (emission midpoint → excitation → dye-name substring → round-robin palette).convert(..., channel_colors="source-file")— a third accepted value that trusts the source file's stored per-channel color (LIFLUTName, OME-XML ARGB int) with fall-through to the emission-band scheme.config.channel_colorsin the audit is preserved verbatim (dict / None /"source-file").UNKNOWN_PALETTEskipping already-taken slots and firing a newChannelColorCollisionWarningnaming the reassigned channels.NAME_COLORS/PALETTE/color_for_channelare removed (loud import-time failure over a silent shim); the acceptance criteria's DAPI/AF546/AF647 → cyan/magenta/white real-file case is pinned by test. See ADR-0007 for the resolution of the "555 nm" ambiguity (excitation, not emission).Closes #51
Test plan
uv run pytest -q— 366 passed, 2 skipped (missing-extras skips only), 0 failedtest_emission_boundary_*test_excitation_*ChannelColorCollisionWarningfires viatest_assign_colors_reallocates_collisions_and_warnsandtest_channels_to_omero_reallocates_collisionstest_dye_name_*andtest_non_lif_reader_default_channels_use_band_schemechannel_colors="source-file"end-to-end (with and without LUTName present) viatest_api_source_file_mode_*config.channel_colorsaudit round-trip preserves"source-file"viatest_convert_preserves_channel_colors_verbatim_in_audittest_api_dict_override_wins_over_band_schemetest_dapi_af546_af647_produces_cyan_magenta_white🤖 Generated with Claude Code