Commit 998ec20
feat(silo-import, helm, website): Revive hierarchical filter functionality (#6575)
This PR reintroduces hierarchical filtering functionality that was added
in #6302 and
#6404 but reverted so
that we could roll out the required breaking change from `hostTaxonId:
int` to `hostTaxonId: string` on its own first.
Below is an updated description taken from the original PR:
## Summary
Introduces a new "hierarchical filter" concept for metadata fields whose
values form a hierarchy resolved dynamically at SILO import time (rather
than statically pinned per pipeline version, the way lineageSystem
works). The first use case is hostTaxonId: at import time the SILO
importer collects the set of host taxon IDs observed in the released
data, asks the taxonomy service to render a SILO-format lineage YAML for
those taxa, and writes it into SILO's input directory. SILO then indexes
the column as a lineage, which gives the website a hierarchical search
UI ("Culicidae" matches records of all mosquito species, etc.).
This PR introduces changes to the helm chart, the SILO importer, and the
website.
## Helm / config
- New metadata-field property hierarchicalFilter: <URL>. Mutually
exclusive with lineageSystem (enforced in values.schema.json). When set,
the field is treated like a lineage system for SILO indexing
(generateLineageIndex) and surfaces a new hierarchicalSearch: true flag
in the website config.
- _hierarchical-filters-for-organism.tpl mirrors the existing
lineageSystemForOrganism helper. The SILO database config combines both
lists into lineageDefinitionFilenames.
- silo-deployment.yaml builds and injects the HIERARCHICAL_FILTERS env
var (JSON map) consumed by the importer.
- West-nile given hierarchicalFilter: *taxonomy_service_url to observe
the new feature on previews.
- New section in helm-chart-config.mdx documenting the feature.
## SILO import
- HIERARCHICAL_FILTERS env var parsed at startup.
- update_hierarchical_filters checks whether the most recent import
cycle returned new values for the hierarchical filter field, and fetches
an updated lineage if so. The response is written to
<input_dir>/<field>.yaml. If the service responds 413 (file exceeds
SILO's Jackson YAML size limit), the importer retries with prune=true.
- New tests in tests/test_runner.py cover both the happy path and the
skip-when-unchanged path; new tests in tests/test_config.py cover
env-var parsing.
## Frontend
- New config options (types/config.ts). Two optional fields added to the
metadata schema: hierarchicalSearch: boolean — opt a field into the
hierarchical filter UI. hierarchicalSearchLabel: string — custom label
for the "include sublineages/subcategories" checkbox
- LineageField.tsx is renamed and extended to HierarchicalField.tsx. The
component was now has a mode prop ('lineage' | 'default') with a
MODE_CONFIGS table:
| | `lineage` mode | `default` (hierarchical) mode |
|---|---|---|
| default "include sublineages" | off | **on** |
| `showAlias` | false | **true** |
| checkbox label | "include sublineages" | "include subcategories" |
| `includeZeroCounts` | true | true |
- SearchForm.tsx renders the HierarchicalField when either
field.lineageSearch or field.hierarchicalSearch is set, passing
mode='lineage' for the former and 'default' for the latter.
- The lineage options hook in AutoCompleteOptions.ts gains two
parameters: 1) showAlias — when a lineage/node has aliases, display the
first alias as the user-facing label (the value stays the canonical
name). This is the hierarchical filter's user-facing label. 2)
includeZeroCounts — when false, options with a count of 0 are filtered
out.
- Added a valueToLabel map to SingleChoiceAutoCompleteField.tsx so the
input's displayValue shows the human-readable label (e.g., the alias)
instead of the raw stored value.
## Screenshots & manual testing
I configured a hierarchical filter for hostTaxonId and set up a preview.
On the preview, I tested filtering west-nile sequences using the new
hierarchical filter autocomplete. It seems to work as intended, and also
the interplay with the existing host name - common / scientific looks
reasonable: if I set a filter for the species 'Culex' using host
name-scientific, all the options with zero count (birds etc.) no longes
show up in the hierarchical filter autocomplete.
This is how the autocomplete looks:
<img width="274" height="122" alt="grafik"
src="https://github.com/user-attachments/assets/8224989c-a64e-4154-b45a-72f4551faa0b"
/>
<img width="274" height="343" alt="grafik"
src="https://github.com/user-attachments/assets/89b0eb28-4f9e-4dd8-9273-a01dd0702d65"
/>
### PR Checklist
- [ ] All necessary documentation has been adapted.
- [ ] The implemented feature is covered by appropriate, automated
tests.
- [ ] Any manual testing that has been done is documented (i.e. what
exactly was tested?)
🚀 Preview: https://revive-hierarchical-filte.loculus.org
---------
Co-authored-by: Anna (Anya) Parker <50943381+anna-parker@users.noreply.github.com>1 parent 987fe18 commit 998ec20
25 files changed
Lines changed: 623 additions & 56 deletions
File tree
- docs/src/content/docs/reference
- kubernetes/loculus
- templates
- loculus-silo
- src/silo_import
- tests
- taxonomy/taxonomy_service
- src/taxonomy_service
- test
- website/src
- components/SearchPage
- fields
- types
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
84 | 93 | | |
85 | 94 | | |
86 | 95 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
372 | 372 | | |
373 | 373 | | |
374 | 374 | | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
375 | 381 | | |
376 | 382 | | |
377 | 383 | | |
| |||
Lines changed: 11 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | | - | |
| 5 | + | |
5 | 6 | | |
6 | 7 | | |
7 | | - | |
| 8 | + | |
8 | 9 | | |
9 | | - | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
| |||
Lines changed: 8 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
8 | 13 | | |
9 | 14 | | |
10 | 15 | | |
| |||
24 | 29 | | |
25 | 30 | | |
26 | 31 | | |
27 | | - | |
| 32 | + | |
28 | 33 | | |
29 | | - | |
30 | | - | |
| 34 | + | |
| 35 | + | |
31 | 36 | | |
32 | 37 | | |
33 | 38 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
10 | 11 | | |
| |||
94 | 95 | | |
95 | 96 | | |
96 | 97 | | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
97 | 102 | | |
98 | 103 | | |
99 | 104 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
232 | 232 | | |
233 | 233 | | |
234 | 234 | | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
235 | 245 | | |
236 | 246 | | |
237 | 247 | | |
| |||
290 | 300 | | |
291 | 301 | | |
292 | 302 | | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
293 | 321 | | |
294 | 322 | | |
295 | 323 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1256 | 1256 | | |
1257 | 1257 | | |
1258 | 1258 | | |
1259 | | - | |
| 1259 | + | |
1260 | 1260 | | |
1261 | 1261 | | |
1262 | 1262 | | |
| |||
1276 | 1276 | | |
1277 | 1277 | | |
1278 | 1278 | | |
1279 | | - | |
| 1279 | + | |
1280 | 1280 | | |
1281 | 1281 | | |
1282 | 1282 | | |
| |||
1295 | 1295 | | |
1296 | 1296 | | |
1297 | 1297 | | |
1298 | | - | |
| 1298 | + | |
1299 | 1299 | | |
1300 | 1300 | | |
1301 | 1301 | | |
| |||
1535 | 1535 | | |
1536 | 1536 | | |
1537 | 1537 | | |
1538 | | - | |
| 1538 | + | |
1539 | 1539 | | |
1540 | 1540 | | |
1541 | 1541 | | |
| |||
1657 | 1657 | | |
1658 | 1658 | | |
1659 | 1659 | | |
| 1660 | + | |
| 1661 | + | |
| 1662 | + | |
1660 | 1663 | | |
1661 | 1664 | | |
1662 | 1665 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4 | 4 | | |
5 | 5 | | |
6 | 6 | | |
| 7 | + | |
7 | 8 | | |
8 | 9 | | |
9 | | - | |
| 10 | + | |
10 | 11 | | |
11 | 12 | | |
12 | 13 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
8 | 11 | | |
9 | 12 | | |
10 | 13 | | |
| |||
16 | 19 | | |
17 | 20 | | |
18 | 21 | | |
| 22 | + | |
19 | 23 | | |
20 | 24 | | |
21 | 25 | | |
| |||
47 | 51 | | |
48 | 52 | | |
49 | 53 | | |
| 54 | + | |
| 55 | + | |
50 | 56 | | |
51 | 57 | | |
52 | 58 | | |
| |||
66 | 72 | | |
67 | 73 | | |
68 | 74 | | |
| 75 | + | |
69 | 76 | | |
70 | 77 | | |
71 | 78 | | |
72 | 79 | | |
73 | 80 | | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
0 commit comments