Some checks failed
CI / skinny-install (aco) (push) Successful in 54s
CI / skinny-install (api) (push) Successful in 32s
CI / skinny-install (bcda) (push) Successful in 33s
CI / skinny-install (bib) (push) Successful in 30s
CI / skinny-install (bls) (push) Successful in 26s
CI / lint-test (push) Successful in 3m19s
CI / skinny-install (ccw) (push) Successful in 27s
CI / skinny-install (cms) (push) Successful in 32s
CI / skinny-install (cli) (push) Successful in 38s
CI / skinny-install (conf) (push) Successful in 33s
CI / skinny-install (opps) (push) Successful in 43s
Infra CI / notebooks (push) Successful in 7s
Infra CI / zotero (push) Successful in 7s
Infra CI / docs (push) Failing after 10s
Infra CI / api (push) Successful in 13s
Infra CI / mc (push) Successful in 7s
CI / skinny-install (perf) (push) Successful in 31s
CI / skinny-install (pfs) (push) Successful in 30s
CI / skinny-install (rex) (push) Successful in 31s
Deploy / build-scan-report (push) Failing after 1m47s
Rip and replace nature/loch with fhirworx — a Federal Register / data journalism aesthetic inspired by hti5.org. Typography: Playfair Display for display headings, Source Serif 4 for reading body, JetBrains Mono reserved for IDs, labels, metadata (docket codes, commit hashes, query editors, file paths, ports). Stripped carpet-bombed font-family: mono !important across inject.css and per-service sheets; kept mono only where load-bearing (th, pre/code, query editors, span IDs, badge/chip/tag, bucket names, query IDs). Palette: warm cream (#F7F5F0) background, near-black warm foreground, deep federal navy (#1C2B3A) primary/sidebar, indigo chart scale + teal (support) + amber (opposition) semantic accents. PALETTE extended to 8 colours (+ plum, gray, sepia) for categorical notebook charts. Rename (no backwards compat): - assets/nature.py → assets/fhirworx.py - assets/css/loch.css → assets/css/fhirworx.css - theme-loch.css → theme-fhirworx.css (Gitea) - Altair theme registered as "fhirworx" via new alt.theme.register decorator API, eliminating the altair 5.5 deprecation warning - Traefik inject-loch middleware → inject-fhirworx - Gitea DEFAULT_THEME=fhirworx - Delete empty theme-throwback.css stub Rewrote infra/nginx/index.html and infra/gitea/custom/templates/home.tmpl with editorial masthead (rule-line + Playfair headline + mono identifier + serif tagline + rule-line-thin), SERVICES eyebrow + Infrastructure h2, tiles with .tile-eyebrow / .tile-title / .tile-desc / .tile-port structure. Stripped letter-spacing: 2-4px tricks and text-transform: uppercase from non-metadata elements across all per-service sheets. Propagated import renames: src/conf/connect.py, src/aco/dag.py, notebooks/acodb_explorer.py, tests/conf/test_connect.py, tests/test_notebook_layout.py, docs/src/css/custom.css, README.md, README.md.j2, compose.yml, infra/traefik/dynamic/services.yml.
236 lines
8.5 KiB
Python
236 lines
8.5 KiB
Python
"""HTI-5 Federal Register design system — shared palette and theme.
|
|
|
|
Design: Federal Register Meets Data Journalism.
|
|
Inspired by ProPublica, The Marshall Project, and the Federal Register.
|
|
|
|
Provides:
|
|
|
|
- ``PALETTE`` — 8-colour chart sequence (indigo scale + teal + amber + plum + gray + sepia)
|
|
- ``SCHEMA_COLORS`` — pipeline schema → colour mapping for DAG viz
|
|
- ``altair_theme()`` — register-and-enable for Altair charts
|
|
- ``mpl_rc()`` — dict of matplotlib rcParams
|
|
- ``cytoscape_style()`` — Cytoscape.js stylesheet fragment
|
|
|
|
Design principles (HTI-5):
|
|
* Typography-first: Playfair Display for display, Source Serif 4 for body
|
|
* Off-white (#F7F5F0) background, near-black (#1A1A18) text
|
|
* Deep federal navy sidebar (#1C2B3A)
|
|
* Warm amber accent for opposition, teal for support
|
|
* Monospace font (JetBrains Mono) for IDs, labels, metadata
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
# ── Chart colour palette ──────────────────────────────────────────────
|
|
# Eight-colour categorical sequence for multi-series charts.
|
|
# First five match the hti5 --chart-* tokens (indigo scale + teal + amber);
|
|
# remaining three extend the editorial palette for categorical variety.
|
|
PALETTE = [
|
|
"#6B7FD7", # indigo medium (chart-1)
|
|
"#4A5CB8", # indigo dark (chart-2)
|
|
"#2E3D8F", # indigo deep (chart-3)
|
|
"#2E8B6E", # teal / support (chart-4)
|
|
"#C8702A", # amber / oppose (chart-5)
|
|
"#7448C0", # plum
|
|
"#6B6B68", # neutral gray
|
|
"#A85800", # sepia / dark amber
|
|
]
|
|
|
|
# Semantic aliases
|
|
INDIGO_MED, INDIGO_DARK, INDIGO_DEEP, TEAL, AMBER, PLUM, GRAY, SEPIA = PALETTE
|
|
|
|
# ── Core palette ──────────────────────────────────────────────────────
|
|
# Backgrounds and text following hti5 design tokens
|
|
BG_LIGHT = "#F7F5F0" # --background: off-white cream
|
|
BG_CARD = "#FAFAF7" # --card: slightly warmer white
|
|
BG_DARK = "#1C2B3A" # --primary / sidebar: deep federal navy
|
|
BG_CHART = "transparent" # chart area — let container bg show through
|
|
AXIS_COLOR = "#D4D0C8" # --border: warm gray
|
|
TEXT_COLOR = "#1A1A18" # --foreground: near-black
|
|
TITLE_COLOR = "#1A1A18" # --foreground for titles
|
|
MUTED_COLOR = "#6B6B68" # --muted-foreground
|
|
|
|
# ── Typography ────────────────────────────────────────────────────────
|
|
FONT_DISPLAY = "Playfair Display, Georgia, serif"
|
|
FONT_BODY = "Source Serif 4, Georgia, serif"
|
|
FONT_MONO = "JetBrains Mono, Fira Code, monospace"
|
|
FONT_FAMILY = FONT_BODY # default for charts
|
|
FONT_SIZE_BODY = 11 # pt — readable at screen DPI
|
|
FONT_SIZE_AXIS = 11 # pt
|
|
FONT_SIZE_TITLE = 13 # pt
|
|
FONT_SIZE_LABEL = 12 # pt
|
|
LINE_WIDTH = 0.75 # pt — axis/tick stroke
|
|
TICK_SIZE = 4 # pt
|
|
|
|
# ── Figure dimensions (single-column width: 89 mm) ───────────────────
|
|
FIG_WIDTH_MM = 89
|
|
FIG_HEIGHT_MM = 60
|
|
FIG_WIDTH_IN = FIG_WIDTH_MM / 25.4
|
|
FIG_HEIGHT_IN = FIG_HEIGHT_MM / 25.4
|
|
DPI = 150 # screen-appropriate DPI
|
|
|
|
|
|
# ── Pipeline schema colours (for DAG / lineage viz) ──────────────────
|
|
SCHEMA_COLORS: dict[str, str] = {
|
|
"core": INDIGO_DEEP,
|
|
"input_layer": TEAL,
|
|
"cclf": INDIGO_DARK,
|
|
"claims_preprocessing": AMBER,
|
|
"readmissions": TEAL,
|
|
"ahrq_measures": INDIGO_MED,
|
|
"pharmacy": "#7448C0", # purple
|
|
"quality_measures": "#C0392B", # destructive / red
|
|
"hcc_suspecting": "#A85800", # warm amber-brown
|
|
"provider_attribution": MUTED_COLOR,
|
|
"main": INDIGO_MED,
|
|
"data_quality": INDIGO_DARK,
|
|
}
|
|
EXTERNAL_COLOR = "#9B9B98"
|
|
|
|
|
|
def schema_color(schema: str) -> str:
|
|
"""Return the palette colour for a pipeline schema."""
|
|
return SCHEMA_COLORS.get(schema, EXTERNAL_COLOR)
|
|
|
|
|
|
# ── Altair theme ──────────────────────────────────────────────────────
|
|
|
|
|
|
def _altair_theme_config() -> dict:
|
|
"""Vega-Lite config dict conforming to HTI-5 editorial specs."""
|
|
return {
|
|
"config": {
|
|
"background": BG_LIGHT,
|
|
"font": FONT_BODY,
|
|
"title": {
|
|
"font": FONT_DISPLAY,
|
|
"fontSize": FONT_SIZE_TITLE,
|
|
"fontWeight": "bold",
|
|
"color": TITLE_COLOR,
|
|
"anchor": "start",
|
|
},
|
|
"axis": {
|
|
"labelFont": FONT_MONO,
|
|
"labelFontSize": FONT_SIZE_AXIS,
|
|
"labelColor": MUTED_COLOR,
|
|
"titleFont": FONT_BODY,
|
|
"titleFontSize": FONT_SIZE_AXIS,
|
|
"titleColor": TEXT_COLOR,
|
|
"gridColor": AXIS_COLOR,
|
|
"gridOpacity": 0.5,
|
|
"domainColor": AXIS_COLOR,
|
|
"domainWidth": LINE_WIDTH,
|
|
"tickColor": AXIS_COLOR,
|
|
"tickSize": TICK_SIZE,
|
|
"tickWidth": LINE_WIDTH,
|
|
},
|
|
"legend": {
|
|
"labelFont": FONT_MONO,
|
|
"labelFontSize": FONT_SIZE_BODY,
|
|
"labelColor": TEXT_COLOR,
|
|
"titleFont": FONT_BODY,
|
|
"titleFontSize": FONT_SIZE_BODY,
|
|
"titleColor": TEXT_COLOR,
|
|
"symbolSize": 60,
|
|
},
|
|
"view": {
|
|
"stroke": AXIS_COLOR,
|
|
"strokeWidth": LINE_WIDTH,
|
|
"fill": BG_CARD,
|
|
},
|
|
"range": {
|
|
"category": PALETTE,
|
|
},
|
|
"mark": {
|
|
"color": PALETTE[0],
|
|
},
|
|
"bar": {
|
|
"color": PALETTE[0],
|
|
},
|
|
"arc": {
|
|
"stroke": BG_LIGHT,
|
|
"strokeWidth": 1,
|
|
},
|
|
"line": {
|
|
"strokeWidth": 1.5,
|
|
},
|
|
"point": {
|
|
"size": 40,
|
|
},
|
|
"area": {
|
|
"opacity": 0.7,
|
|
},
|
|
}
|
|
}
|
|
|
|
|
|
def altair_theme() -> None:
|
|
"""Register and enable the fhirworx Altair chart theme.
|
|
|
|
Uses the Altair 5.5+ ``alt.theme.register`` decorator API.
|
|
"""
|
|
import altair as alt
|
|
|
|
@alt.theme.register("fhirworx", enable=True)
|
|
def _fhirworx_theme() -> dict:
|
|
return _altair_theme_config()
|
|
|
|
|
|
# ── Matplotlib rcParams ──────────────────────────────────────────────
|
|
|
|
|
|
def mpl_rc() -> dict:
|
|
"""Return an rcParams dict for ``matplotlib.rcParams.update()``."""
|
|
return {
|
|
"font.family": "serif",
|
|
"font.serif": ["Source Serif 4", "Georgia", "DejaVu Serif"],
|
|
"font.size": FONT_SIZE_BODY,
|
|
"axes.titlesize": FONT_SIZE_TITLE,
|
|
"axes.titleweight": "bold",
|
|
"axes.titlefontproperties": {"family": "serif"},
|
|
"axes.labelsize": FONT_SIZE_AXIS,
|
|
"axes.linewidth": LINE_WIDTH,
|
|
"axes.edgecolor": AXIS_COLOR,
|
|
"axes.labelcolor": TEXT_COLOR,
|
|
"axes.facecolor": BG_CARD,
|
|
"axes.grid": True,
|
|
"axes.grid.axis": "y",
|
|
"axes.prop_cycle": __import__("cycler").cycler(color=PALETTE),
|
|
"grid.color": AXIS_COLOR,
|
|
"grid.linewidth": 0.5,
|
|
"grid.alpha": 0.6,
|
|
"xtick.major.size": TICK_SIZE,
|
|
"xtick.major.width": LINE_WIDTH,
|
|
"xtick.color": AXIS_COLOR,
|
|
"xtick.labelsize": FONT_SIZE_BODY,
|
|
"ytick.major.size": TICK_SIZE,
|
|
"ytick.major.width": LINE_WIDTH,
|
|
"ytick.color": AXIS_COLOR,
|
|
"ytick.labelsize": FONT_SIZE_BODY,
|
|
"figure.figsize": (FIG_WIDTH_IN, FIG_HEIGHT_IN),
|
|
"figure.dpi": DPI,
|
|
"figure.facecolor": BG_LIGHT,
|
|
"savefig.dpi": DPI,
|
|
"savefig.facecolor": BG_LIGHT,
|
|
"legend.fontsize": FONT_SIZE_BODY,
|
|
"legend.frameon": False,
|
|
"text.color": TEXT_COLOR,
|
|
}
|
|
|
|
|
|
# ── Cytoscape.js style helpers ───────────────────────────────────────
|
|
|
|
|
|
def cytoscape_node_style() -> dict:
|
|
"""Base Cytoscape.js node style properties (HTI-5 editorial style)."""
|
|
return {
|
|
"font-family": FONT_MONO,
|
|
"font-size": "9px",
|
|
"text-valign": "center",
|
|
"text-halign": "center",
|
|
"shape": "round-rectangle",
|
|
"background-color": BG_CARD,
|
|
"border-color": AXIS_COLOR,
|
|
"color": TEXT_COLOR,
|
|
}
|