550a0e2666bcce27181a0cb0eab32ed261e444f6
mspeir
  Thu Aug 27 14:56:42 2026 -0700
singleCellSignalsPeaks: color the Cell class facet checkboxes, refs #37820, refs #37914

The faceted UI already draws a color swatch beside each checkbox of any facet
named in a colorSettingsUrl JSON, and the track already colors its subtracks by
broad cell class from celltype-palette.tsv. Publish that palette so the selector
shows the same colors: copySingleCellSignalsPeaksFiles.py now writes
<bed>/singleCellSignalsPeaks_colors.json alongside the facet metadata, and the
composite header names it. Rendered from the one shared palette, so a class is
the same color in the checkbox list, in the drawn tracks, and on both assemblies.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

diff --git src/hg/makeDb/doc/mm10/singleCellSignalsPeaks.txt src/hg/makeDb/doc/mm10/singleCellSignalsPeaks.txt
index 69a7ad01e47..3594e984eb9 100644
--- src/hg/makeDb/doc/mm10/singleCellSignalsPeaks.txt
+++ src/hg/makeDb/doc/mm10/singleCellSignalsPeaks.txt
@@ -34,30 +34,40 @@
 # git-controlled). Default: /hive/data/inside/cells/all-tracks-hub-build
 #
 # The per-track source files (abs_path column of manifest.tsv) are the files the
 # Cell Browser datasets already serve; nothing is regenerated here, only copied.
 
 ##############################################################################
 # 2. Copy the data files into place  (bed dir, served via a /gbdb symlink)
 ##############################################################################
 # copySingleCellSignalsPeaksFiles.py copies every cellBrowserMm10 subtrack file
 # into /hive/data/genomes/mm10/bed/singleCellSignalsPeaks/<served-relpath>,
 # keeping each file's served relative path, and copies the composite's facet
 # metadata to <bed>/singleCellSignalsPeaks_metadata.tsv. The served subpath is
 # preserved on purpose: some coverage/peak basenames (e.g. MOL.bw, OPC.bw) repeat
 # across datasets, so a flat directory would clobber them.  89.6 GB, 647 files.
 #
+# The same script also writes <bed>/singleCellSignalsPeaks_colors.json, the track's
+# colorSettingsUrl target: {"Cell_class": {<class>: "#RRGGBB"}}, rendered straight from
+# celltype-palette.tsv. The faceted UI draws a color swatch beside each checkbox of any
+# facet named in that file, so the Cell class checkboxes carry the same colors the
+# subtracks are drawn in. Keys must match the metadata column value verbatim -- the
+# lookup in facetedComposite.js is an exact string match, and an unmatched key just
+# leaves that swatch blank. The whole palette is written for both assemblies, so classes
+# an assembly does not use (mm10 uses all 23; hg38 has no Ependymal or Choroid plexus)
+# are simply unused keys.
+#
 #   scriptDir=$HOME/kent/src/hg/makeDb/scripts/singleCellSignalsPeaks
 #   python3 $scriptDir/copySingleCellSignalsPeaksFiles.py --assembly mm10 --dry-run
 #   python3 $scriptDir/copySingleCellSignalsPeaksFiles.py --assembly mm10
 
 ##############################################################################
 # 3. Generate the trackDb .ra
 ##############################################################################
 # makeSingleCellSignalsPeaksRa.py reads the hub's mm10 stanzas, keeps the
 # cellBrowserMm10 subtracks, renames the composite to singleCellSignalsPeaks,
 # repoints every bigDataUrl at the local /gbdb copy, and writes the .ra with
 # group=regulation (ATAC signal/peaks sit with the ENCODE regulatory tracks).
 # The generator also: drops any subtrack whose source path is under a deprecated
 # "*.old/" dir, sets every subtrack "off" by default (users pick tracks from the
 # faceted selector), and assigns "priority" by cell class so same-class tracks
 # group together in the display. Labels/colors/facets are already resolved by
@@ -75,31 +85,32 @@
 # doc/hg38/singleCellSignalsPeaks.txt).
 #
 # Cell type: the source cluster label is cleaned and, for datasets with coded
 #   cluster names, mapped to a canonical name via a paper-curated crosswalk
 #   (celltype-crosswalks/<collection>.tsv; codes decoded from Li 2021 PMID 34616068,
 #   Zhang 2022 PMID 36207411, Zhu 2021 PMID 33589836, and the Allen whole-brain
 #   taxonomy). Redundant synonyms are merged, QC clusters (doublet / low-quality /
 #   batch) are dropped, and commas become ';' (the faceted UI tokenizes cell
 #   values on commas). The full cell type is a searchable table column (_Cell_type),
 #   not a facet -- there are too many values.
 #
 # Cell class: each cell type is assigned one of 23 broad classes
 #   (celltype-crosswalks/celltype-class.tsv, built by build_celltype_crosswalks.py).
 #   The class drives BOTH the track color (one colorblind-conscious palette,
 #   celltype-palette.tsv, shared by hg38 and mm10 so a class is the same color on
-#   both assemblies) and the subtrack priority. Cell class is the primary cell facet.
+#   both assemblies) and the subtrack priority. Cell class is the primary cell facet,
+#   and the same palette is published as the facet swatch colors (section 2).
 #
 #   "Other glia" (88,160,88) was added because "Other" was doing four unrelated
 #   jobs. Of 40 tracks corpus-wide sitting in it: 14 real glia with nowhere else to
 #   go, 14 peripheral glia deliberately placed there (Schwann / enteric -- left
 #   alone), 5 that are not cell types at all (All cell types / All cells /
 #   Neuronal and glial -- aggregate peak calls, a separate defect NOT addressed),
 #   and 6 genuinely other. The new class takes the glial aggregate labels (Glia,
 #   Glial), olfactory ensheathing cells, and the five fly glia subtypes; Schwann and
 #   enteric glia stay under "Other". Named for symmetry with the existing
 #   "Other neuron". The color came from a grid search maximizing minimum dE against
 #   the 22 existing entries under normal, deuteranope and protanope simulation,
 #   restricted to the widest free hue band; nearest neighbours are Epithelial
 #   (dE 17) and Astrocyte (dE 20), both above the palette's own closest pair
 #   (Other vs Unknown, 12.7). Before this, Glia and Non-Neuronal were both grey.
 #