Skip to content

Commit c64e6c4

Browse files
authored
Merge pull request #5 from Kitware/feature/category-filtering-and-ui-docs
feat: add category-based preset filtering and UI how-to docs
2 parents 5389b0c + 0d63154 commit c64e6c4

15 files changed

Lines changed: 382 additions & 50 deletions

README.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,118 @@ A production app using `trame-colormaps` for climate data visualization.
7777
Each data variable gets its own horizontal colorbar at the bottom of the view,
7878
with symlog tick marks that adapt to the data range.
7979

80+
## UI How-To
81+
82+
### Opening the Control Panel
83+
84+
Hover over any colorbar and the cursor changes to a **context-menu** icon:
85+
86+
<img src="docs/images/context-menu.png" alt="context-menu cursor" width="32">
87+
88+
Click the colorbar to open its control panel. Only one panel can be open at
89+
a time — opening one automatically closes any other.
90+
91+
### The Control Panel
92+
93+
<img src="docs/images/normal.png" alt="Control Panel" style="border: 1px solid black;">
94+
95+
The control panel has three sections, top to bottom:
96+
97+
- **Toolbar** — A row of icon buttons across the top that toggle modes and
98+
settings (category filter, colorblind safe, invert, scale, diverging,
99+
custom range, and discrete banding). The current preset name doubles as a
100+
search field on the right, with a close button to dismiss the panel.
101+
102+
- **Settings panels** — Context-sensitive inputs that appear below the toolbar
103+
depending on which modes are active. These include category filter
104+
checkboxes, discrete color count, diverging mode controls (|max| and
105+
ε tolerance), and custom range inputs (Min / Max).
106+
107+
- **Preset list** — A scrollable list of colormap swatches filtered by the
108+
active categories, colorblind setting, and search text. Click any swatch
109+
to apply it immediately.
110+
111+
### Toolbar
112+
113+
<img src="docs/images/panelbar.png" alt="Toolbar" style="border: 1px solid black;">
114+
115+
The toolbar has three areas, left to right:
116+
117+
- **Icon buttons** — Seven toggle buttons that control filtering and display
118+
modes. Each button lights up or changes icon when its mode is active.
119+
Details on each button are covered below.
120+
121+
- **Search / preset name** — Shows the name of the currently active preset.
122+
Click into it to type and filter the preset list by name. Use the clear
123+
button to reset the search.
124+
125+
- **Close button** (✕) — Dismisses the control panel.
126+
127+
#### Icon Buttons (left to right)
128+
129+
| # | Off | On | Toggle | Description |
130+
|---|-----|-----|--------|-------------|
131+
| 1 | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/palette-outline.svg" width="24"> | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/palette.svg" width="24"> | Category Filter | Shows/hides category checkboxes (Sequential, Multi-Sequential, Diverging, Cyclic) in the *Settings panel* to control which presets appear in the list. |
132+
| 2 | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/blinds.svg" width="24"> | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/blinds-open.svg" width="24"> | Colorblind Safe | Limits the *Preset list* to colorblind-safe presets only. Filters within the selected categories. |
133+
| 3 | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/invert-colors-off.svg" width="24"> | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/invert-colors.svg" width="24"> | Invert | Reverses the colormap direction (shown in the *Colorbar* and *Preset list*). |
134+
| 4a | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/stairs.svg" width="24"> | | Scale: Linear | Click to switch to Log scale. In diverging mode, switches to SymLog. |
135+
| 4b | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/math-log.svg" width="24"> | | Scale: Log | Click to switch to SymLog scale. **Note**: Not available in diverging mode. |
136+
| 4c | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/sine-wave.svg" width="24"> | | Scale: SymLog | Click to return to Linear scale. |
137+
| 5 | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/triangle-outline.svg" width="24"> | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/triangle.svg" width="24"> | Δ Difference | Enters diverging mode: forces diverging-only presets in *Preset list*, symmetric range around zero, and exposes \|max\| and ε controls in *Settings panel*. |
138+
| 6 | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/pencil.svg" width="24"> | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/arrow-expand-horizontal.svg" width="24"> | Custom Range | Toggles between data-driven range and manual Min/Max inputs exposed in the *Settings panel*. Locked (not shown in *Settings panel*)in diverging mode. |
139+
| 7 | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/gradient-horizontal.svg" width="24"> | <img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/view-sequential.svg" width="24"> | Discrete | Switches between continuous gradient and discrete color banding. Exposes "Colors per tick interval" (Linear) or "Colors per magnitude" (Log/SymLog) control in *Settings panel*. |
140+
141+
#### Scale Modes
142+
143+
<table>
144+
<tr>
145+
<td width="33%" align="center"><img src="docs/images/clicked-linear.png" width="100%" style="border: 1px solid black;"><br><em>Linear</em></td>
146+
<td width="33%" align="center"><img src="docs/images/clicked-log.png" width="100%" style="border: 1px solid black;"><br><em>Log</em></td>
147+
<td width="33%" align="center"><img src="docs/images/clicked-symlog.png" width="100%" style="border: 1px solid black;"><br><em>SymLog</em></td>
148+
</tr>
149+
</table>
150+
151+
In all three screenshots, every mode except Δ Difference is active:
152+
153+
- **Category Filter** — Only *Cyclic* is checked in the *Settings panel*;
154+
the *Preset list* shows only cyclic presets (vikO, brocO, corkO, …).
155+
- **Colorblind Safe** — Further limits the *Preset list* to colorblind-safe
156+
cyclic presets.
157+
- **Invert** — Preset swatches and the colorbar render reversed.
158+
- **Custom Range***Settings panel* shows editable **Min** and **Max** fields.
159+
- **Discrete***Settings panel* shows the band count control. Its label
160+
adapts to the active scale: "Colors per tick interval" (Linear) or
161+
"Colors per order of magnitude" (Log / SymLog).
162+
- **Search** — The text field contains "V", filtering the *Preset list* to
163+
matching names. A clear button (✕) appears to reset the search.
164+
165+
The only difference between the three images is the **Scale** button, which
166+
cycles through Linear (<img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/stairs.svg" width="16">), Log (<img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/math-log.svg" width="16">), and SymLog (<img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/sine-wave.svg" width="16">).
167+
The colorbar tick labels at the bottom switch between decimal notation
168+
(Linear) and scientific notation (Log / SymLog).
169+
170+
#### Δ Difference Mode
171+
172+
<table>
173+
<tr>
174+
<td width="50%" align="center"><img src="docs/images/clicked-delta-linear.png" width="100%" style="border: 1px solid black;"><br><em>Δ Linear</em></td>
175+
<td width="50%" align="center"><img src="docs/images/clicked-delta-symlog.png" width="100%" style="border: 1px solid black;"><br><em>Δ SymLog</em></td>
176+
</tr>
177+
</table>
178+
179+
When Δ Difference is active (<img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/triangle.svg" width="16"> filled):
180+
181+
- **Preset list** is forced to diverging-only presets regardless of category
182+
selection (vik shown here).
183+
- **Scale** only toggles between Linear (<img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/stairs.svg" width="16">) and SymLog (<img src="https://cdn.jsdelivr.net/npm/@mdi/svg/svg/sine-wave.svg" width="16">) — Log is
184+
not available.
185+
- **Settings panel** replaces Min/Max with **|max|** (symmetric range
186+
centered at zero) and **ε tolerance** (dead zone width around zero
187+
where the center color is held constant).
188+
- **Custom Range** button is locked — range is always driven by |max|.
189+
- **Category Filter** checkboxes are hidden since presets are forced to
190+
diverging.
191+
80192
## Public API
81193

82194
Import via the trame namespace:
@@ -119,6 +231,7 @@ All colormap presets are stored as JSON files under `src/trame_colormaps/presets
119231
| Category | Use When | Data Character |
120232
|----------|----------|----------------|
121233
| **Sequential** | Magnitude — more/less of something | Temperature, pressure, density |
234+
| **Multi-Sequential** | Structured subranges — regimes that differ | Terrain, threshold bands |
122235
| **Diverging** | Deviation — Δ from a reference value | Anomaly, residual, balance |
123236
| **Cyclic** | Periodic — values that wrap around | Phase, angle, time-of-day |
124237
| **Categorical** | Discrete labels — no inherent order | Material ID, region, class |
@@ -147,6 +260,29 @@ with no special reference value.
147260

148261
**Good defaults:** Viridis, Plasma, batlow — perceptually uniform ramps.
149262

263+
#### Using Multi-Sequential Colormaps
264+
265+
Multi-sequential colormaps encode **structured data** — data with meaningful
266+
subranges where different regimes should look visually distinct.
267+
268+
**Use when:**
269+
270+
- Data has meaningful subranges
271+
- Different regimes should look different
272+
273+
**Examples:**
274+
275+
1. **Terrain / elevation** — deep ocean → shallow → land → mountains → snow;
276+
each region has different semantics.
277+
2. **Threshold-based interpretation** — low → acceptable → warning → critical.
278+
3. **Nonlinear emphasis** (without changing scale) — more color variation in
279+
important ranges, less in unimportant ones.
280+
281+
**Properties:**
282+
283+
- Does not imply "above vs below" — just adds internal structure
284+
- Requires care to avoid false edges and visual discontinuities
285+
150286
#### Using Diverging Colormaps
151287

152288
Diverging colormaps encode **"above vs below reference"** — data with a meaningful
112 KB
Loading
115 KB
Loading

docs/images/clicked-linear.png

158 KB
Loading

docs/images/clicked-log.png

158 KB
Loading

docs/images/clicked-symlog.png

155 KB
Loading

docs/images/context-menu.png

11.7 KB
Loading

docs/images/normal.png

140 KB
Loading

docs/images/panelbar.png

20.1 KB
Loading

src/trame_colormaps/core/presets.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,12 @@ def load(filename):
5353
sequential = {
5454
n for n, p in registry.items() if p.get("Category", "").lower() == "sequential"
5555
}
56+
multi_sequential = {
57+
n for n, p in registry.items() if p.get("Category", "").lower() == "multi-sequential"
58+
}
5659
cyclic = {n for n, p in registry.items() if p.get("Category", "").lower() == "cyclic"}
5760
categorical = {
58-
n
59-
for n, p in registry.items()
60-
if p.get("Category", "").lower() in ("categorical", "multi-sequential")
61+
n for n, p in registry.items() if p.get("Category", "").lower() == "categorical"
6162
}
6263

6364
return (
@@ -67,6 +68,7 @@ def load(filename):
6768
defaults,
6869
diverging,
6970
sequential,
71+
multi_sequential,
7072
cyclic,
7173
categorical,
7274
)
@@ -79,6 +81,7 @@ def load(filename):
7981
DEFAULT_PRESETS,
8082
DIVERGING_PRESETS,
8183
SEQUENTIAL_PRESETS,
84+
MULTI_SEQUENTIAL_PRESETS,
8285
CYCLIC_PRESETS,
8386
CATEGORICAL_PRESETS,
8487
) = _init_registry()

0 commit comments

Comments
 (0)