diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..d079320fc0089792fda7151a5caa51a08cb62721 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text +trackio/assets/badge.png filter=lfs diff=lfs merge=lfs -text +trackio/assets/trackio_logo_old.png filter=lfs diff=lfs merge=lfs -text diff --git a/trackio/.DS_Store b/trackio/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4c7acc58dab4e35c5d2974a040a6041b65b12296 Binary files /dev/null and b/trackio/.DS_Store differ diff --git a/trackio/CHANGELOG.md b/trackio/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..368bb81aaebe3bfb96a3ae9cb42ae02221f16720 --- /dev/null +++ b/trackio/CHANGELOG.md @@ -0,0 +1,232 @@ +# trackio + +## 0.22.0 + +### Features + +- [#484](https://github.com/gradio-app/trackio/pull/484) [`cc05ada`](https://github.com/gradio-app/trackio/commit/cc05ada8e89773f3a894af99b801ef680f64418f) - Fix duplicate columns in parquet export. Thanks @abidlabs! +- [#487](https://github.com/gradio-app/trackio/pull/487) [`853f764`](https://github.com/gradio-app/trackio/commit/853f7646a70d12633afaa4f69db86425aa665413) - Relax `PIL` dependency and remove `plotly` as it's no longer used. Thanks @abidlabs! + +## 0.21.2 + +### Features + +- [#482](https://github.com/gradio-app/trackio/pull/482) [`f62180a`](https://github.com/gradio-app/trackio/commit/f62180a0218bc99a259d5ca110a0384a6cae11c8) - Use server-side bucket copy when freezing Spaces. Thanks @abidlabs! + +## 0.21.1 + +### Features + +- [#475](https://github.com/gradio-app/trackio/pull/475) [`fcb476c`](https://github.com/gradio-app/trackio/commit/fcb476cd37a40923e9679aaf966f41d582a878a8) - Tweaks. Thanks @abidlabs! +- [#477](https://github.com/gradio-app/trackio/pull/477) [`7d52dfd`](https://github.com/gradio-app/trackio/commit/7d52dfdce5b6eff6a34501a6d5a620220663cf09) - Fix `.sync()` and add `.freeze()` as a separate methods. Thanks @abidlabs! + +## 0.21.0 + +### Features + +- [#467](https://github.com/gradio-app/trackio/pull/467) [`f357deb`](https://github.com/gradio-app/trackio/commit/f357debf78957e4c1f2b901bee4f77cf397298b4) - Allow logged metrics as x-axis choices. Thanks @abidlabs! +- [#474](https://github.com/gradio-app/trackio/pull/474) [`655673d`](https://github.com/gradio-app/trackio/commit/655673d4c6b7c8b7ee8f87f2589f2dbbc3d2ef91) - Fix file descriptor leak from `sqlite3.connect`. Thanks @abidlabs! +- [#470](https://github.com/gradio-app/trackio/pull/470) [`bea8c9d`](https://github.com/gradio-app/trackio/commit/bea8c9dcae0b59d071b6c779c97ee525c9bbf6e7) - Restores tooltips to line plots and fixes the call to uses TTL instead of OAuth. Thanks @abidlabs! +- [#471](https://github.com/gradio-app/trackio/pull/471) [`246fce0`](https://github.com/gradio-app/trackio/commit/246fce0a01619e1c2c538c67b3e460883334d500) - Deprecate dataset backend in favor of buckets. Thanks @abidlabs! +- [#465](https://github.com/gradio-app/trackio/pull/465) [`3e11174`](https://github.com/gradio-app/trackio/commit/3e1117438bb8168b802245a33059affa558ae519) - Use HF buckets as backend. Thanks @abidlabs! +- [#469](https://github.com/gradio-app/trackio/pull/469) [`915d170`](https://github.com/gradio-app/trackio/commit/915d17045133172b59195acfdcc70709229668aa) - Make static Spaces work with Buckets and also allow conversion from Gradio SDK to Static Spaces. Thanks @abidlabs! + +## 0.20.2 + +### Features + +- [#464](https://github.com/gradio-app/trackio/pull/464) [`c89ebb3`](https://github.com/gradio-app/trackio/commit/c89ebb3b50f695bc7f16cbc6f46dce86f79a01e9) - Improve rendering of curves. Thanks @abidlabs! +- [#462](https://github.com/gradio-app/trackio/pull/462) [`9160b78`](https://github.com/gradio-app/trackio/commit/9160b78ff6f258f0b87a4f34a24e7d0b5dfbf2fb) - Refactor plot title to display only the metric name without the path. Thanks @qgallouedec! + +## 0.20.1 + +### Features + +- [#454](https://github.com/gradio-app/trackio/pull/454) [`22881db`](https://github.com/gradio-app/trackio/commit/22881dbbbb6b81197a00a19853771007093d61e4) - Bar chart single point. Thanks @abidlabs! +- [#455](https://github.com/gradio-app/trackio/pull/455) [`f8db51a`](https://github.com/gradio-app/trackio/commit/f8db51a20ca61ef703f3f2c2ee1ebd9c4f239cf2) - Adds a static Trackio mode via `trackio.sync(sdk="static")` and support for the `TRACKIO_SPACE_ID` environment variable. Thanks @abidlabs! + +## 0.20.0 + +### Features + +- [#450](https://github.com/gradio-app/trackio/pull/450) [`b0571ef`](https://github.com/gradio-app/trackio/commit/b0571ef6207a1ce346696f858ad2b7b584dd194f) - Use Svelte source for Gradio components directly in Trackio dashboard. Thanks @abidlabs! + +## 0.19.0 + +### Features + +- [#445](https://github.com/gradio-app/trackio/pull/445) [`cef4a58`](https://github.com/gradio-app/trackio/commit/cef4a583cb76f4091fc6c0e5783124ee84f8e243) - Add remote HF Space support to CLI. Thanks @abidlabs! +- [#444](https://github.com/gradio-app/trackio/pull/444) [`358f2a9`](https://github.com/gradio-app/trackio/commit/358f2a9ca238ee8b90b5a8c96220da287e0698fb) - Fix alerts placeholder flashing on reports page. Thanks @abidlabs! + +## 0.18.0 + +### Features + +- [#435](https://github.com/gradio-app/trackio/pull/435) [`4a47112`](https://github.com/gradio-app/trackio/commit/4a471128e18a39e45fad48a67fd711c5ae9e4aed) - feat: allow hiding section header accordions. Thanks @Saba9! +- [#439](https://github.com/gradio-app/trackio/pull/439) [`18e9650`](https://github.com/gradio-app/trackio/commit/18e96503d5a3a7cf926e92782d457e23c19942bd) - Add alerts with webhooks, CLI, and documentation. Thanks @abidlabs! +- [#438](https://github.com/gradio-app/trackio/pull/438) [`0875ccd`](https://github.com/gradio-app/trackio/commit/0875ccd3d8a41b1376f64030f21cfe8cdcc73b05) - Add "share this view" functionality. Thanks @qgallouedec! +- [#409](https://github.com/gradio-app/trackio/pull/409) [`9282403`](https://github.com/gradio-app/trackio/commit/9282403d8896d48679b0f888208a7ba5bdd4271a) - Add Apple Silicon GPU and system monitoring support. Thanks @znation! +- [#434](https://github.com/gradio-app/trackio/pull/434) [`4193223`](https://github.com/gradio-app/trackio/commit/41932230a3a2e1c16405dba08ecba5a42f11d1a8) - fix: table slider crash. Thanks @Saba9! + +### Fixes + +- [#441](https://github.com/gradio-app/trackio/pull/441) [`3a2d11d`](https://github.com/gradio-app/trackio/commit/3a2d11dab0b4b37c925abc30ef84b0e2910321ee) - preserve x-axis step when toggling run checkboxes. Thanks @Saba9! + +## 0.17.0 + +### Features + +- [#428](https://github.com/gradio-app/trackio/pull/428) [`f7dd1ce`](https://github.com/gradio-app/trackio/commit/f7dd1ce2dc8a1936f9983467fcbcf93bfef01e09) - feat: add ability to rename runs. Thanks @Saba9! +- [#437](https://github.com/gradio-app/trackio/pull/437) [`2727c0b`](https://github.com/gradio-app/trackio/commit/2727c0b0755f48f7f186162ea45185c98f6b5516) - Add markdown reports across Trackio. Thanks @abidlabs! +- [#427](https://github.com/gradio-app/trackio/pull/427) [`5aeb9ed`](https://github.com/gradio-app/trackio/commit/5aeb9edcfd2068d309d9d64f172dcbcc327be1ab) - Make Trackio logging much more robust. Thanks @abidlabs! + +## 0.16.1 + +### Features + +- [#431](https://github.com/gradio-app/trackio/pull/431) [`c7ce55b`](https://github.com/gradio-app/trackio/commit/c7ce55b14dd5eb0c2165fb15df17dd60721c9325) - Lazy load the UI when trackio is imported. Thanks @abidlabs! + +## 0.16.0 + +### Features + +- [#426](https://github.com/gradio-app/trackio/pull/426) [`ead4dc8`](https://github.com/gradio-app/trackio/commit/ead4dc8e74ee2d8e47d61bca0a7668456acf49be) - Fix redundant double rendering of group checkboxes. Thanks @abidlabs! +- [#413](https://github.com/gradio-app/trackio/pull/413) [`39c4750`](https://github.com/gradio-app/trackio/commit/39c4750951d554ba6eb4d58847c6bb444b2891a8) - Check `dist-packages` when checking for source installation. Thanks @sergiopaniego! +- [#423](https://github.com/gradio-app/trackio/pull/423) [`2e52ab3`](https://github.com/gradio-app/trackio/commit/2e52ab303e3041718a6a56fbf84d0848aca9ad67) - Fix legend outline visibility issue. Thanks @Raghunath-Balaji! +- [#407](https://github.com/gradio-app/trackio/pull/407) [`c8a384d`](https://github.com/gradio-app/trackio/commit/c8a384ddfe5a295cecf862a26178d40e48acb424) - Fix pytests that were failling locally on MacOS. Thanks @abidlabs! +- [#405](https://github.com/gradio-app/trackio/pull/405) [`35aae4e`](https://github.com/gradio-app/trackio/commit/35aae4e3aa3e2b2888887528478b9dc6a9808bda) - Add conditional padding for HF Space dashboard when not in iframe. Thanks @znation! + +## 0.15.0 + +### Features + +- [#397](https://github.com/gradio-app/trackio/pull/397) [`6b38ad0`](https://github.com/gradio-app/trackio/commit/6b38ad02e5d73a0df49c4eede7e91331282ece04) - Adds `--host` cli option support. Thanks @abidlabs! +- [#396](https://github.com/gradio-app/trackio/pull/396) [`4a4d1ab`](https://github.com/gradio-app/trackio/commit/4a4d1ab85e63d923132a3fa7afa5d90e16431bec) - Fix run selection issue. Thanks @abidlabs! +- [#394](https://github.com/gradio-app/trackio/pull/394) [`c47a3a3`](https://github.com/gradio-app/trackio/commit/c47a3a31f8c4b83bce1aa7fc22eeba3d9021ad3d) - Add wandb-compatible API for trackio. Thanks @abidlabs! +- [#378](https://github.com/gradio-app/trackio/pull/378) [`b02046a`](https://github.com/gradio-app/trackio/commit/b02046a5b0dad7c9854e099a87f884afba4aecb2) - Add JSON export button for line plots and upgrade gradio dependency. Thanks @JamshedAli18! + +## 0.14.2 + +### Features + +- [#386](https://github.com/gradio-app/trackio/pull/386) [`f9452cd`](https://github.com/gradio-app/trackio/commit/f9452cdb8f0819368f3610f7ac0ed08957305275) - Fixing some issues related to deployed Trackio Spaces. Thanks @abidlabs! + +## 0.14.1 + +### Features + +- [#382](https://github.com/gradio-app/trackio/pull/382) [`44fe9bb`](https://github.com/gradio-app/trackio/commit/44fe9bb264fb2aafb0ec302ff15227c045819a2c) - Fix app file path when Trackio is not installed from source. Thanks @abidlabs! +- [#380](https://github.com/gradio-app/trackio/pull/380) [`c3f4cff`](https://github.com/gradio-app/trackio/commit/c3f4cff74bc5676e812773d8571454894fcdc7cc) - Add CLI commands for querying projects, runs, and metrics. Thanks @abidlabs! + +## 0.14.0 + +### Features + +- [#377](https://github.com/gradio-app/trackio/pull/377) [`5c5015b`](https://github.com/gradio-app/trackio/commit/5c5015b68c85c5de51111dad983f735c27b9a05f) - fixed wrapping issue in Runs table. Thanks @gaganchapa! +- [#374](https://github.com/gradio-app/trackio/pull/374) [`388e26b`](https://github.com/gradio-app/trackio/commit/388e26b9e9f24cd7ad203affe9b709be885b3d24) - Save Optimized Parquet files. Thanks @lhoestq! +- [#371](https://github.com/gradio-app/trackio/pull/371) [`fbace9c`](https://github.com/gradio-app/trackio/commit/fbace9cd7732c166f34d268f54b05bb06846cc5d) - Add GPU metrics logging. Thanks @kashif! +- [#367](https://github.com/gradio-app/trackio/pull/367) [`862840c`](https://github.com/gradio-app/trackio/commit/862840c13e30fc960cbee5b9eac4d3c25beba9de) - Add option to only show latest run, and fix the double logo issue. Thanks @abidlabs! + +## 0.13.1 + +### Features + +- [#369](https://github.com/gradio-app/trackio/pull/369) [`767e9fe`](https://github.com/gradio-app/trackio/commit/767e9fe095d7c6ed102016caf927c1517fb8618c) - tiny pr removing unnecessary code. Thanks @abidlabs! + +## 0.13.0 + +### Features + +- [#358](https://github.com/gradio-app/trackio/pull/358) [`073715d`](https://github.com/gradio-app/trackio/commit/073715d1caf8282f68890117f09c3ac301205312) - Improvements to `trackio.sync()`. Thanks @abidlabs! + +## 0.12.0 + +### Features + +- [#357](https://github.com/gradio-app/trackio/pull/357) [`02ba815`](https://github.com/gradio-app/trackio/commit/02ba815358060f1966052de051a5bdb09702920e) - Redesign media and tables to show up on separate page. Thanks @abidlabs! +- [#359](https://github.com/gradio-app/trackio/pull/359) [`08fe9c9`](https://github.com/gradio-app/trackio/commit/08fe9c9ddd7fe99ee811555fdfb62df9ab88e939) - docs: Improve docstrings. Thanks @qgallouedec! + +## 0.11.0 + +### Features + +- [#355](https://github.com/gradio-app/trackio/pull/355) [`ea51f49`](https://github.com/gradio-app/trackio/commit/ea51f4954922f21be76ef828700420fe9a912c4b) - Color code run checkboxes and match with plot lines. Thanks @abidlabs! +- [#353](https://github.com/gradio-app/trackio/pull/353) [`8abe691`](https://github.com/gradio-app/trackio/commit/8abe6919aeefe21fc7a23af814883efbb037c21f) - Remove show_api from demo.launch. Thanks @sergiopaniego! +- [#351](https://github.com/gradio-app/trackio/pull/351) [`8a8957e`](https://github.com/gradio-app/trackio/commit/8a8957e530dd7908d1fef7f2df030303f808101f) - Add `trackio.save()`. Thanks @abidlabs! + +## 0.10.0 + +### Features + +- [#305](https://github.com/gradio-app/trackio/pull/305) [`e64883a`](https://github.com/gradio-app/trackio/commit/e64883a51f7b8b93f7d48b8afe55acdb62238b71) - bump to gradio 6.0, make `trackio` compatible, and fix related issues. Thanks @abidlabs! + +## 0.9.1 + +### Features + +- [#344](https://github.com/gradio-app/trackio/pull/344) [`7e01024`](https://github.com/gradio-app/trackio/commit/7e010241d9a34794e0ce0dc19c1a6f0cf94ba856) - Avoid redundant calls to /whoami-v2. Thanks @Wauplin! + +## 0.9.0 + +### Features + +- [#343](https://github.com/gradio-app/trackio/pull/343) [`51bea30`](https://github.com/gradio-app/trackio/commit/51bea30f2877adff8e6497466d3a799400a0a049) - Sync offline projects to Hugging Face spaces. Thanks @candemircan! +- [#341](https://github.com/gradio-app/trackio/pull/341) [`4fd841f`](https://github.com/gradio-app/trackio/commit/4fd841fa190e15071b02f6fba7683ef4f393a654) - Adds a basic UI test to `trackio`. Thanks @abidlabs! +- [#339](https://github.com/gradio-app/trackio/pull/339) [`011d91b`](https://github.com/gradio-app/trackio/commit/011d91bb6ae266516fd250a349285670a8049d05) - Allow customzing the trackio color palette. Thanks @abidlabs! + +## 0.8.1 + +### Features + +- [#336](https://github.com/gradio-app/trackio/pull/336) [`5f9f51d`](https://github.com/gradio-app/trackio/commit/5f9f51dac8677f240d7c42c3e3b2660a22aee138) - Support a list of `Trackio.Image` in a `trackio.Table` cell. Thanks @abidlabs! + +## 0.8.0 + +### Features + +- [#331](https://github.com/gradio-app/trackio/pull/331) [`2c02d0f`](https://github.com/gradio-app/trackio/commit/2c02d0fd0a5824160528782402bb0dd4083396d5) - Truncate table string values that are greater than 250 characters (configuirable via env variable). Thanks @abidlabs! +- [#324](https://github.com/gradio-app/trackio/pull/324) [`50b2122`](https://github.com/gradio-app/trackio/commit/50b2122e7965ac82a72e6cb3b7d048bc10a2a6b1) - Add log y-axis functionality to UI. Thanks @abidlabs! +- [#326](https://github.com/gradio-app/trackio/pull/326) [`61dc1f4`](https://github.com/gradio-app/trackio/commit/61dc1f40af2f545f8e70395ddf0dbb8aee6b60d5) - Fix: improve table rendering for metrics in Trackio Dashboard. Thanks @vigneshwaran! +- [#328](https://github.com/gradio-app/trackio/pull/328) [`6857cbb`](https://github.com/gradio-app/trackio/commit/6857cbbe557a59a4642f210ec42566d108294e63) - Support trackio.Table with trackio.Image columns. Thanks @abidlabs! +- [#323](https://github.com/gradio-app/trackio/pull/323) [`6857cbb`](https://github.com/gradio-app/trackio/commit/6857cbbe557a59a4642f210ec42566d108294e63) - add Trackio client implementations in Go, Rust, and JS. Thanks @vaibhav-research! + +## 0.7.0 + +### Features + +- [#277](https://github.com/gradio-app/trackio/pull/277) [`db35601`](https://github.com/gradio-app/trackio/commit/db35601b9c023423c4654c9909b8ab73e58737de) - fix: make grouped runs view reflect live updates. Thanks @Saba9! +- [#320](https://github.com/gradio-app/trackio/pull/320) [`24ae739`](https://github.com/gradio-app/trackio/commit/24ae73969b09fb3126acd2f91647cdfbf8cf72a1) - Add additional query parms for xmin, xmax, and smoothing. Thanks @abidlabs! +- [#270](https://github.com/gradio-app/trackio/pull/270) [`cd1dfc3`](https://github.com/gradio-app/trackio/commit/cd1dfc3dc641b4499ac6d4a1b066fa8e2b52c57b) - feature: add support for logging audio. Thanks @Saba9! + +## 0.6.0 + +### Features + +- [#309](https://github.com/gradio-app/trackio/pull/309) [`1df2353`](https://github.com/gradio-app/trackio/commit/1df23534d6c01938c8db9c0f584ffa23e8d6021d) - Add histogram support with wandb-compatible API. Thanks @abidlabs! +- [#315](https://github.com/gradio-app/trackio/pull/315) [`76ba060`](https://github.com/gradio-app/trackio/commit/76ba06055dc43ca8f03b79f3e72d761949bd19a8) - Add guards to avoid silent fails. Thanks @Xmaster6y! +- [#313](https://github.com/gradio-app/trackio/pull/313) [`a606b3e`](https://github.com/gradio-app/trackio/commit/a606b3e1c5edf3d4cf9f31bd50605226a5a1c5d0) - No longer prevent certain keys from being used. Instead, dunderify them to prevent collisions with internal usage. Thanks @abidlabs! +- [#317](https://github.com/gradio-app/trackio/pull/317) [`27370a5`](https://github.com/gradio-app/trackio/commit/27370a595d0dbdf7eebbe7159d2ba778f039da44) - quick fixes for trackio.histogram. Thanks @abidlabs! +- [#312](https://github.com/gradio-app/trackio/pull/312) [`aa0f3bf`](https://github.com/gradio-app/trackio/commit/aa0f3bf372e7a0dd592a38af699c998363830eeb) - Fix video logging by adding TRACKIO_DIR to allowed_paths. Thanks @abidlabs! + +## 0.5.3 + +### Features + +- [#300](https://github.com/gradio-app/trackio/pull/300) [`5e4cacf`](https://github.com/gradio-app/trackio/commit/5e4cacf2e7ce527b4ce60de3a5bc05d2c02c77fb) - Adds more environment variables to allow customization of Trackio dashboard. Thanks @abidlabs! + +## 0.5.2 + +### Features + +- [#293](https://github.com/gradio-app/trackio/pull/293) [`64afc28`](https://github.com/gradio-app/trackio/commit/64afc28d3ea1dfd821472dc6bf0b8ed35a9b74be) - Ensures that the TRACKIO_DIR environment variable is respected. Thanks @abidlabs! +- [#287](https://github.com/gradio-app/trackio/pull/287) [`cd3e929`](https://github.com/gradio-app/trackio/commit/cd3e9294320949e6b8b829239069a43d5d7ff4c1) - fix(sqlite): unify .sqlite extension, allow export when DBs exist, clean WAL sidecars on import. Thanks @vaibhav-research! + +### Fixes + +- [#291](https://github.com/gradio-app/trackio/pull/291) [`3b5adc3`](https://github.com/gradio-app/trackio/commit/3b5adc3d1f452dbab7a714d235f4974782f93730) - Fix the wheel build. Thanks @pngwn! + +## 0.5.1 + +### Fixes + +- [#278](https://github.com/gradio-app/trackio/pull/278) [`314c054`](https://github.com/gradio-app/trackio/commit/314c05438007ddfea3383e06fd19143e27468e2d) - Fix row orientation of metrics plots. Thanks @abidlabs! \ No newline at end of file diff --git a/trackio/__init__.py b/trackio/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8e540d4e7070ed63beb37cea004b773bd5066a55 --- /dev/null +++ b/trackio/__init__.py @@ -0,0 +1,750 @@ +import atexit +import glob +import json +import logging +import os +import shutil +import warnings +import webbrowser +from pathlib import Path +from typing import Any + +import huggingface_hub +from gradio_client import Client, handle_file +from huggingface_hub import SpaceStorage +from huggingface_hub.errors import LocalTokenNotFoundError + +from trackio import context_vars, deploy, utils +from trackio.alerts import AlertLevel +from trackio.api import Api +from trackio.apple_gpu import apple_gpu_available +from trackio.apple_gpu import log_apple_gpu as _log_apple_gpu +from trackio.deploy import freeze, sync +from trackio.gpu import gpu_available +from trackio.gpu import log_gpu as _log_nvidia_gpu +from trackio.histogram import Histogram +from trackio.imports import import_csv, import_tf_events +from trackio.launch import launch_trackio_dashboard +from trackio.markdown import Markdown +from trackio.media import ( + TrackioAudio, + TrackioImage, + TrackioVideo, + get_project_media_path, +) +from trackio.run import Run +from trackio.server import TrackioDashboardApp, build_starlette_app_only +from trackio.sqlite_storage import SQLiteStorage +from trackio.table import Table +from trackio.typehints import UploadEntry +from trackio.utils import TRACKIO_DIR + +logging.getLogger("httpx").setLevel(logging.WARNING) + +__version__ = json.loads(Path(__file__).parent.joinpath("package.json").read_text())[ + "version" +] + + +class _TupleNoPrint(tuple): + def __repr__(self) -> str: + return "" + + +__all__ = [ + "init", + "log", + "log_system", + "log_gpu", + "finish", + "alert", + "AlertLevel", + "show", + "sync", + "freeze", + "delete_project", + "import_csv", + "import_tf_events", + "save", + "Image", + "Video", + "Audio", + "Table", + "Histogram", + "Markdown", + "Api", +] + +Audio = TrackioAudio +Image = TrackioImage +Video = TrackioVideo + + +config = {} + +_atexit_registered = False +_projects_notified_auto_log_hw: set[str] = set() + + +def _cleanup_current_run(): + run = context_vars.current_run.get() + if run is not None: + try: + run.finish() + except Exception: + pass + + +def init( + project: str, + name: str | None = None, + group: str | None = None, + space_id: str | None = None, + space_storage: SpaceStorage | None = None, + dataset_id: str | None = None, + bucket_id: str | None = None, + config: dict | None = None, + resume: str = "never", + settings: Any = None, + private: bool | None = None, + embed: bool = True, + auto_log_gpu: bool | None = None, + gpu_log_interval: float = 10.0, + webhook_url: str | None = None, + webhook_min_level: AlertLevel | str | None = None, +) -> Run: + """ + Creates a new Trackio project and returns a [`Run`] object. + + Args: + project (`str`): + The name of the project (can be an existing project to continue tracking or + a new project to start tracking from scratch). + name (`str`, *optional*): + The name of the run (if not provided, a default name will be generated). + group (`str`, *optional*): + The name of the group which this run belongs to in order to help organize + related runs together. You can toggle the entire group's visibilitiy in the + dashboard. + space_id (`str`, *optional*): + If provided, the project will be logged to a Hugging Face Space instead of + a local directory. Should be a complete Space name like + `"username/reponame"` or `"orgname/reponame"`, or just `"reponame"` in which + case the Space will be created in the currently-logged-in Hugging Face + user's namespace. If the Space does not exist, it will be created. If the + Space already exists, the project will be logged to it. Can also be set + via the `TRACKIO_SPACE_ID` environment variable. You cannot log to a + Space that has been **frozen** (converted to the static SDK); use + ``trackio.sync(..., sdk="static")`` only after you are done logging. + space_storage ([`~huggingface_hub.SpaceStorage`], *optional*): + Choice of persistent storage tier. + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + bucket_id (`str`, *optional*): + The ID of the Hugging Face Bucket to use for metric persistence. By default, + when a `space_id` is provided and `bucket_id` is not explicitly set, a + bucket is auto-generated from the space_id. Buckets provide + S3-like storage without git overhead - the SQLite database is stored directly + via `hf-mount` in the Space. Specify a Bucket with name like + `"username/bucketname"` or just `"bucketname"`. + config (`dict`, *optional*): + A dictionary of configuration options. Provided for compatibility with + `wandb.init()`. + resume (`str`, *optional*, defaults to `"never"`): + Controls how to handle resuming a run. Can be one of: + + - `"must"`: Must resume the run with the given name, raises error if run + doesn't exist + - `"allow"`: Resume the run if it exists, otherwise create a new run + - `"never"`: Never resume a run, always create a new one + private (`bool`, *optional*): + Whether to make the Space private. If None (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. + settings (`Any`, *optional*): + Not used. Provided for compatibility with `wandb.init()`. + embed (`bool`, *optional*, defaults to `True`): + If running inside a Jupyter/Colab notebook, whether the dashboard should + automatically be embedded in the cell when trackio.init() is called. For + local runs, this launches a local Gradio app and embeds it. For Space runs, + this embeds the Space URL. In Colab, the local dashboard will be accessible + via a public share URL (default Gradio behavior). + auto_log_gpu (`bool` or `None`, *optional*, defaults to `None`): + Controls automatic GPU metrics logging. If `None` (default), GPU logging + is automatically enabled when `nvidia-ml-py` is installed and an NVIDIA + GPU or Apple M series is detected. Set to `True` to force enable or + `False` to disable. + gpu_log_interval (`float`, *optional*, defaults to `10.0`): + The interval in seconds between automatic GPU metric logs. + Only used when `auto_log_gpu=True`. + webhook_url (`str`, *optional*): + A webhook URL to POST alert payloads to when `trackio.alert()` is + called. Supports Slack and Discord webhook URLs natively (payloads + are formatted automatically). Can also be set via the + `TRACKIO_WEBHOOK_URL` environment variable. Individual alerts can + override this URL by passing `webhook_url` to `trackio.alert()`. + webhook_min_level (`AlertLevel` or `str`, *optional*): + Minimum alert level that should trigger webhook delivery. + For example, `AlertLevel.WARN` sends only `WARN` and `ERROR` + alerts to the webhook destination. Can also be set via + `TRACKIO_WEBHOOK_MIN_LEVEL`. + Returns: + `Run`: A [`Run`] object that can be used to log metrics and finish the run. + """ + if settings is not None: + warnings.warn( + "* Warning: settings is not used. Provided for compatibility with wandb.init(). Please create an issue at: https://github.com/gradio-app/trackio/issues if you need a specific feature implemented." + ) + + space_id = space_id or os.environ.get("TRACKIO_SPACE_ID") + bucket_id = bucket_id or os.environ.get("TRACKIO_BUCKET_ID") + if space_id is None and dataset_id is not None: + raise ValueError("Must provide a `space_id` when `dataset_id` is provided.") + if dataset_id is not None and bucket_id is not None: + raise ValueError("Cannot provide both `dataset_id` and `bucket_id`.") + try: + space_id, dataset_id, bucket_id = utils.preprocess_space_and_dataset_ids( + space_id, dataset_id, bucket_id + ) + except LocalTokenNotFoundError as e: + raise LocalTokenNotFoundError( + f"You must be logged in to Hugging Face locally when `space_id` is provided to deploy to a Space. {e}" + ) from e + + if space_id is None and bucket_id is not None: + warnings.warn( + "trackio.init() has `bucket_id` set but `space_id` is None: metrics will be logged " + "locally only. Pass `space_id` to create or use a Hugging Face Space, which will be " + "attached to the Hugging Face Bucket.", + UserWarning, + stacklevel=2, + ) + + if space_id is not None: + deploy.raise_if_space_is_frozen_for_logging(space_id) + + url = context_vars.current_server.get() + + if space_id is not None: + if url is None: + url = space_id + context_vars.current_server.set(url) + context_vars.current_space_id.set(space_id) + + _should_embed_local = False + + if ( + context_vars.current_project.get() is None + or context_vars.current_project.get() != project + ): + print(f"* Trackio project initialized: {project}") + + if bucket_id is not None: + os.environ["TRACKIO_BUCKET_ID"] = bucket_id + bucket_url = f"https://huggingface.co/buckets/{bucket_id}" + print( + f"* Trackio metrics will be synced to Hugging Face Bucket: {bucket_url}" + ) + elif dataset_id is not None: + os.environ["TRACKIO_DATASET_ID"] = dataset_id + print( + f"* Trackio metrics will be synced to Hugging Face Dataset: {dataset_id}" + ) + if space_id is None: + print(f"* Trackio metrics logged to: {TRACKIO_DIR}") + _should_embed_local = embed and utils.is_in_notebook() + if not _should_embed_local: + utils.print_dashboard_instructions(project) + else: + deploy.create_space_if_not_exists( + space_id, + space_storage, + dataset_id, + bucket_id, + private, + ) + user_name, space_name = space_id.split("/") + space_url = deploy.SPACE_HOST_URL.format( + user_name=user_name, space_name=space_name + ) + if utils.is_in_notebook() and embed: + utils.embed_url_in_notebook(space_url) + context_vars.current_project.set(project) + + if resume == "must": + if name is None: + raise ValueError("Must provide a run name when resume='must'") + if name not in SQLiteStorage.get_runs(project): + raise ValueError(f"Run '{name}' does not exist in project '{project}'") + resumed = True + elif resume == "allow": + resumed = name is not None and name in SQLiteStorage.get_runs(project) + elif resume == "never": + if name is not None and name in SQLiteStorage.get_runs(project): + warnings.warn( + f"* Warning: resume='never' but a run '{name}' already exists in " + f"project '{project}'. Generating a new name and instead. If you want " + "to resume this run, call init() with resume='must' or resume='allow'." + ) + name = None + resumed = False + else: + raise ValueError("resume must be one of: 'must', 'allow', or 'never'") + + if auto_log_gpu is None: + nvidia_available = gpu_available() + apple_available = apple_gpu_available() + auto_log_gpu = nvidia_available or apple_available + if project not in _projects_notified_auto_log_hw: + if nvidia_available: + print("* NVIDIA GPU detected, enabling automatic GPU metrics logging") + elif apple_available: + print( + "* Apple Silicon detected, enabling automatic system metrics logging" + ) + if nvidia_available or apple_available: + _projects_notified_auto_log_hw.add(project) + + run = Run( + url=url, + project=project, + client=None, + name=name, + group=group, + config=config, + space_id=space_id, + auto_log_gpu=auto_log_gpu, + gpu_log_interval=gpu_log_interval, + webhook_url=webhook_url, + webhook_min_level=webhook_min_level, + ) + + if space_id is not None: + SQLiteStorage.set_project_metadata(project, "space_id", space_id) + if SQLiteStorage.has_pending_data(project): + run._has_local_buffer = True + + global _atexit_registered + if not _atexit_registered: + atexit.register(_cleanup_current_run) + _atexit_registered = True + + if resumed: + print(f"* Resumed existing run: {run.name}") + else: + print(f"* Created new run: {run.name}") + + context_vars.current_run.set(run) + globals()["config"] = run.config + + if _should_embed_local: + show(project=project, open_browser=False, block_thread=False) + + return run + + +def log(metrics: dict, step: int | None = None) -> None: + """ + Logs metrics to the current run. + + Args: + metrics (`dict`): + A dictionary of metrics to log. + step (`int`, *optional*): + The step number. If not provided, the step will be incremented + automatically. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log().") + run.log( + metrics=metrics, + step=step, + ) + + +def log_system(metrics: dict) -> None: + """ + Logs system metrics (GPU, etc.) to the current run using timestamps instead of steps. + + Args: + metrics (`dict`): + A dictionary of system metrics to log. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_system().") + run.log_system(metrics=metrics) + + +def log_gpu(run: Run | None = None, device: int | None = None) -> dict: + """ + Log GPU metrics to the current or specified run as system metrics. + Automatically detects whether an NVIDIA or Apple GPU is available and calls + the appropriate logging method. + + Args: + run: Optional Run instance. If None, uses current run from context. + device: CUDA device index to collect metrics from (NVIDIA GPUs only). + If None, collects from all GPUs visible to this process. + This parameter is ignored for Apple GPUs. + + Returns: + dict: The GPU metrics that were logged. + + Example: + ```python + import trackio + + run = trackio.init(project="my-project") + trackio.log({"loss": 0.5}) + trackio.log_gpu() + trackio.log_gpu(device=0) + ``` + """ + if run is None: + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_gpu().") + + if gpu_available(): + return _log_nvidia_gpu(run=run, device=device) + elif apple_gpu_available(): + return _log_apple_gpu(run=run) + else: + warnings.warn( + "No GPU detected. Install nvidia-ml-py for NVIDIA GPU support " + "or psutil for Apple Silicon support." + ) + return {} + + +def finish(): + """ + Finishes the current run. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.finish().") + run.finish() + + +def alert( + title: str, + text: str | None = None, + level: AlertLevel = AlertLevel.WARN, + webhook_url: str | None = None, +) -> None: + """ + Fires an alert immediately on the current run. The alert is printed to the + terminal, stored in the database, and displayed in the dashboard. If a + webhook URL is configured (via `trackio.init()`, the `TRACKIO_WEBHOOK_URL` + environment variable, or the `webhook_url` parameter here), the alert is + also POSTed to that URL. + + Args: + title (`str`): + A short title for the alert. + text (`str`, *optional*): + A longer description with details about the alert. + level (`AlertLevel`, *optional*, defaults to `AlertLevel.WARN`): + The severity level. One of `AlertLevel.INFO`, `AlertLevel.WARN`, + or `AlertLevel.ERROR`. + webhook_url (`str`, *optional*): + A webhook URL to send this specific alert to. Overrides any + URL set in `trackio.init()` or the `TRACKIO_WEBHOOK_URL` + environment variable. Supports Slack and Discord webhook + URLs natively. + """ + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.alert().") + run.alert(title=title, text=text, level=level, webhook_url=webhook_url) + + +def delete_project(project: str, force: bool = False) -> bool: + """ + Deletes a project by removing its local SQLite database. + + Args: + project (`str`): + The name of the project to delete. + force (`bool`, *optional*, defaults to `False`): + If `True`, deletes the project without prompting for confirmation. + If `False`, prompts the user to confirm before deleting. + + Returns: + `bool`: `True` if the project was deleted, `False` otherwise. + """ + db_path = SQLiteStorage.get_project_db_path(project) + + if not db_path.exists(): + print(f"* Project '{project}' does not exist.") + return False + + if not force: + response = input( + f"Are you sure you want to delete project '{project}'? " + f"This will permanently delete all runs and metrics. (y/N): " + ) + if response.lower() not in ["y", "yes"]: + print("* Deletion cancelled.") + return False + + try: + db_path.unlink() + + for suffix in ("-wal", "-shm"): + sidecar = Path(str(db_path) + suffix) + if sidecar.exists(): + sidecar.unlink() + + print(f"* Project '{project}' has been deleted.") + return True + except Exception as e: + print(f"* Error deleting project '{project}': {e}") + return False + + +def save( + glob_str: str | Path, + project: str | None = None, +) -> str: + """ + Saves files to a project (not linked to a specific run). If Trackio is running + locally, the file(s) will be copied to the project's files directory. If Trackio is + running in a Space, the file(s) will be uploaded to the Space's files directory. + + Args: + glob_str (`str` or `Path`): + The file path or glob pattern to save. Can be a single file or a pattern + matching multiple files (e.g., `"*.py"`, `"models/**/*.pth"`). + project (`str`, *optional*): + The name of the project to save files to. If not provided, uses the current + project from `trackio.init()`. If no project is initialized, raises an + error. + + Returns: + `str`: The path where the file(s) were saved (project's files directory). + + Example: + ```python + import trackio + + trackio.init(project="my-project") + trackio.save("config.yaml") + trackio.save("models/*.pth") + ``` + """ + if project is None: + project = context_vars.current_project.get() + if project is None: + raise RuntimeError( + "No project specified. Either call trackio.init() first or provide a " + "project parameter to trackio.save()." + ) + + glob_str = Path(glob_str) + base_path = Path.cwd().resolve() + + matched_files = [] + if glob_str.is_file(): + matched_files = [glob_str.resolve()] + else: + pattern = str(glob_str) + if not glob_str.is_absolute(): + pattern = str((Path.cwd() / glob_str).resolve()) + matched_files = [ + Path(f).resolve() + for f in glob.glob(pattern, recursive=True) + if Path(f).is_file() + ] + + if not matched_files: + raise ValueError(f"No files found matching pattern: {glob_str}") + + current_run = context_vars.current_run.get() + is_local = ( + current_run._is_local + if current_run is not None + else (context_vars.current_space_id.get() is None) + ) + + if is_local: + for file_path in matched_files: + try: + relative_to_base = file_path.relative_to(base_path) + except ValueError: + relative_to_base = Path(file_path.name) + + if current_run is not None: + current_run._queue_upload( + file_path, + step=None, + relative_path=str(relative_to_base.parent), + use_run_name=False, + ) + else: + media_path = get_project_media_path( + project=project, + run=None, + step=None, + relative_path=str(relative_to_base), + ) + shutil.copy(str(file_path), str(media_path)) + else: + url = context_vars.current_server.get() + + upload_entries = [] + for file_path in matched_files: + try: + relative_to_base = file_path.relative_to(base_path) + except ValueError: + relative_to_base = Path(file_path.name) + + if current_run is not None: + current_run._queue_upload( + file_path, + step=None, + relative_path=str(relative_to_base.parent), + use_run_name=False, + ) + else: + upload_entry: UploadEntry = { + "project": project, + "run": None, + "step": None, + "relative_path": str(relative_to_base), + "uploaded_file": handle_file(file_path), + } + upload_entries.append(upload_entry) + + if upload_entries: + if url is None: + raise RuntimeError( + "No server available. Call trackio.init() before trackio.save() to start the server." + ) + + try: + client = Client(url, verbose=False, httpx_kwargs={"timeout": 90}) + client.predict( + api_name="/bulk_upload_media", + uploads=upload_entries, + hf_token=huggingface_hub.utils.get_token(), + ) + except Exception as e: + warnings.warn( + f"Failed to upload files: {e}. " + "Files may not be available in the dashboard." + ) + + return str(utils.MEDIA_DIR / project / "files") + + +def show( + project: str | None = None, + *, + theme: Any = None, + mcp_server: bool | None = None, + footer: bool = True, + color_palette: list[str] | None = None, + open_browser: bool = True, + block_thread: bool | None = None, + host: str | None = None, + share: bool | None = None, + server_port: int | None = None, +): + """ + Launches the Trackio dashboard. + + Args: + project (`str`, *optional*): + The name of the project whose runs to show. If not provided, all projects + will be shown and the user can select one. + theme (`Any`, *optional*): + Ignored. Kept for backward compatibility; Trackio no longer uses Gradio themes. + mcp_server (`bool`, *optional*): + If `True`, the dashboard enables MCP lifespan hooks when available. If `None` + (default), the `GRADIO_MCP_SERVER` environment variable is used (e.g. on Spaces). + footer (`bool`, *optional*, defaults to `True`): + Whether to include `footer=false` in the write-token URL when `False`. + This can also be controlled via the `footer` query parameter in the URL. + color_palette (`list[str]`, *optional*): + A list of hex color codes to use for plot lines. If not provided, the + `TRACKIO_COLOR_PALETTE` environment variable will be used (comma-separated + hex codes), or if that is not set, the default color palette will be used. + Example: `['#FF0000', '#00FF00', '#0000FF']` + open_browser (`bool`, *optional*, defaults to `True`): + If `True` and not in a notebook, a new browser tab will be opened with the + dashboard. If `False`, the browser will not be opened. + block_thread (`bool`, *optional*): + If `True`, the main thread will be blocked until the dashboard is closed. + If `None` (default behavior), then the main thread will not be blocked if the + dashboard is launched in a notebook, otherwise the main thread will be blocked. + host (`str`, *optional*): + The host to bind the server to. If not provided, defaults to `'127.0.0.1'` + (localhost only). Set to `'0.0.0.0'` to allow remote access. + share (`bool`, *optional*): + If `True`, creates a temporary public URL (Gradio-compatible tunnel). On Colab + or hosted notebooks, defaults to `True` unless overridden. + server_port (`int`, *optional*): + Port to bind. If not set, scans from `GRADIO_SERVER_PORT` (default 7860). + + Returns: + `app`: The dashboard handle (`.close()` stops the server). + `url`: The local URL of the dashboard. + `share_url`: The public share URL, if any. + `full_url`: The full URL including the write token (share URL when sharing, else local). + """ + if theme is not None: + warnings.warn( + "The theme argument is ignored; Trackio no longer depends on Gradio themes.", + UserWarning, + stacklevel=2, + ) + + if color_palette is not None: + os.environ["TRACKIO_COLOR_PALETTE"] = ",".join(color_palette) + + _mcp_server = ( + mcp_server + if mcp_server is not None + else os.environ.get("GRADIO_MCP_SERVER", "False") == "True" + ) + + starlette_app, wt = build_starlette_app_only(mcp_server=_mcp_server) + local_url, share_url, _local_api_url, uv_server = launch_trackio_dashboard( + starlette_app, + server_name=host, + server_port=server_port, + share=share, + mcp_server=_mcp_server, + quiet=True, + ) + server = TrackioDashboardApp(starlette_app, uv_server, wt) + + base_root = (share_url or local_url).rstrip("/") + base_url = base_root + "/" + dashboard_url = base_url + if project: + dashboard_url += f"?project={project}" + full_url = utils.get_full_url( + base_root, + project=project, + write_token=wt, + footer=footer, + ) + + if not utils.is_in_notebook(): + print(f"* Trackio UI launched at: {dashboard_url}") + print(f"* API (gradio_client-compatible) at: {base_url}gradio_api/") + if open_browser: + webbrowser.open(dashboard_url) + block_thread = block_thread if block_thread is not None else True + else: + utils.embed_url_in_notebook(dashboard_url) + block_thread = block_thread if block_thread is not None else False + + if block_thread: + utils.block_main_thread_until_keyboard_interrupt() + return _TupleNoPrint((server, local_url, share_url, full_url)) diff --git a/trackio/_vendor/__init__.py b/trackio/_vendor/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/trackio/_vendor/gradio_exceptions.py b/trackio/_vendor/gradio_exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..34696b9e534896b66557bab78a2d78709c07e351 --- /dev/null +++ b/trackio/_vendor/gradio_exceptions.py @@ -0,0 +1,6 @@ +class ChecksumMismatchError(Exception): + pass + + +class ShareCertificateWriteError(Exception): + pass diff --git a/trackio/_vendor/networking.py b/trackio/_vendor/networking.py new file mode 100644 index 0000000000000000000000000000000000000000..04ef35763f89eb813059ea6fc91a7316ecd2f2de --- /dev/null +++ b/trackio/_vendor/networking.py @@ -0,0 +1,81 @@ +from __future__ import annotations + +import os +import time +import warnings +from pathlib import Path +from urllib.parse import urlparse, urlunparse + +import httpx + +from trackio._vendor.gradio_exceptions import ShareCertificateWriteError +from trackio._vendor.tunneling import CERTIFICATE_PATH, Tunnel + +GRADIO_API_SERVER = "https://api.gradio.app/v3/tunnel-request" +GRADIO_SHARE_SERVER_ADDRESS = os.getenv("GRADIO_SHARE_SERVER_ADDRESS") + + +def setup_tunnel( + local_host: str, + local_port: int, + share_token: str, + share_server_address: str | None, + share_server_tls_certificate: str | None, +) -> str: + share_server_address = ( + GRADIO_SHARE_SERVER_ADDRESS + if share_server_address is None + else share_server_address + ) + if share_server_address is None: + try: + response = httpx.get(GRADIO_API_SERVER, timeout=30) + payload = response.json()[0] + remote_host, remote_port = payload["host"], int(payload["port"]) + certificate = payload["root_ca"] + except Exception as e: + raise RuntimeError( + "Could not get share link from Gradio API Server." + ) from e + try: + Path(CERTIFICATE_PATH).parent.mkdir(parents=True, exist_ok=True) + with open(CERTIFICATE_PATH, "w") as f: + f.write(certificate) + except Exception as e: + raise ShareCertificateWriteError( + f"{e}. This can happen if the current working directory is read-only." + ) from e + share_server_tls_certificate = CERTIFICATE_PATH + + else: + remote_host, remote_port = share_server_address.split(":") + remote_port = int(remote_port) + tunnel = Tunnel( + remote_host, + remote_port, + local_host, + local_port, + share_token, + share_server_tls_certificate, + ) + address = tunnel.start_tunnel() + return address + + +def url_ok(url: str) -> bool: + try: + for _ in range(5): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore") + r = httpx.head(url, timeout=3, verify=False) + if r.status_code in (200, 401, 302, 303, 307): + return True + time.sleep(0.500) + except (ConnectionError, httpx.ConnectError, httpx.TimeoutException): + return False + return False + + +def normalize_share_url(share_url: str, share_server_protocol: str) -> str: + parsed_url = urlparse(share_url) + return urlunparse((share_server_protocol,) + parsed_url[1:]) diff --git a/trackio/_vendor/tunneling.py b/trackio/_vendor/tunneling.py new file mode 100644 index 0000000000000000000000000000000000000000..6bd6258ed043ba70b07bb1e928bf009864206000 --- /dev/null +++ b/trackio/_vendor/tunneling.py @@ -0,0 +1,191 @@ +import atexit +import hashlib +import os +import platform +import re +import stat +import subprocess +import sys +import time +from pathlib import Path + +import httpx +from huggingface_hub.constants import HF_HOME + +from trackio._vendor.gradio_exceptions import ChecksumMismatchError + +VERSION = "0.3" +CURRENT_TUNNELS: list["Tunnel"] = [] + +machine = platform.machine() +if machine == "x86_64": + machine = "amd64" +elif machine == "aarch64": + machine = "arm64" + +BINARY_REMOTE_NAME = f"frpc_{platform.system().lower()}_{machine.lower()}" +EXTENSION = ".exe" if os.name == "nt" else "" +BINARY_URL = f"https://cdn-media.huggingface.co/frpc-gradio-{VERSION}/{BINARY_REMOTE_NAME}{EXTENSION}" + +CHECKSUMS = { + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_windows_amd64.exe": "14bc0ea470be5d67d79a07412bd21de8a0a179c6ac1116d7764f68e942dc9ceb", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_amd64": "c791d1f047b41ff5885772fc4bf20b797c6059bbd82abb9e31de15e55d6a57c4", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_arm64": "823ced25104de6dc3c9f4798dbb43f20e681207279e6ab89c40e2176ccbf70cd", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_darwin_amd64": "930f8face3365810ce16689da81b7d1941fda4466225a7bbcbced9a2916a6e15", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_darwin_arm64": "dfac50c690aca459ed5158fad8bfbe99f9282baf4166cf7c410a6673fbc1f327", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_arm": "4b563beb2e36c448cc688174e20b53af38dc1ff2b5e362d4ddd1401f2affbfb7", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_freebsd_386": "cb0a56c764ecf96dd54ed601d240c564f060ee4e58202d65ffca17c1a51ce19c", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_freebsd_amd64": "516d9e6903513869a011ddcd1ec206167ad1eb5dd6640d21057acc258edecbbb", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_386": "4c2f2a48cd71571498c0ac8a4d42a055f22cb7f14b4b5a2b0d584220fd60a283", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_mips": "b309ecd594d4f0f7f33e556a80d4b67aef9319c00a8334648a618e56b23cb9e0", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_mips64": "0372ef5505baa6f3b64c6295a86541b24b7b0dbe4ef28b344992e21f47624b7b", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_riscv64": "1658eed7e8c14ea76e1d95749d58441ce24147c3d559381832c725c29cfc3df3", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_mipsle": "a2aaba16961d3372b79bd7a28976fcd0f0bbaebc2b50d5a7a71af2240747960f", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_windows_386.exe": "721b90550195a83e15f2176d8f85a48d5a25822757cb872e9723d4bccc4e5bb6", + "https://cdn-media.huggingface.co/frpc-gradio-0.3/frpc_linux_mips64le": "796481edd609f31962b45cc0ab4c9798d040205ae3bf354ed1b72fb432d796b8", +} + +CHUNK_SIZE = 128 + +BINARY_FILENAME = f"{BINARY_REMOTE_NAME}_v{VERSION}" +BINARY_FOLDER = Path(HF_HOME) / "trackio" / "frpc" +BINARY_PATH = str(BINARY_FOLDER / BINARY_FILENAME) + +TUNNEL_TIMEOUT_SECONDS = 30 +TUNNEL_ERROR_MESSAGE = ( + "Could not create share URL. " + "Please check the appended log from frpc for more information:" +) + +CERTIFICATE_PATH = ".trackio/certificate.pem" + + +class Tunnel: + def __init__( + self, + remote_host: str, + remote_port: int, + local_host: str, + local_port: int, + share_token: str, + share_server_tls_certificate: str | None, + ): + self.proc = None + self.url = None + self.remote_host = remote_host + self.remote_port = remote_port + self.local_host = local_host + self.local_port = local_port + self.share_token = share_token + self.share_server_tls_certificate = share_server_tls_certificate + + @staticmethod + def download_binary(): + if not Path(BINARY_PATH).exists(): + Path(BINARY_FOLDER).mkdir(parents=True, exist_ok=True) + resp = httpx.get(BINARY_URL, timeout=30) + + if resp.status_code == 403: + raise OSError( + f"Cannot set up a share link as this platform is incompatible. Please " + f"create a GitHub issue with information about your platform: {platform.uname()}" + ) + + resp.raise_for_status() + + with open(BINARY_PATH, "wb") as file: + file.write(resp.content) + st = os.stat(BINARY_PATH) + os.chmod(BINARY_PATH, st.st_mode | stat.S_IEXEC) + + if BINARY_URL in CHECKSUMS: + sha = hashlib.sha256() + with open(BINARY_PATH, "rb") as f: + for chunk in iter(lambda: f.read(CHUNK_SIZE * sha.block_size), b""): + sha.update(chunk) + calculated_hash = sha.hexdigest() + + if calculated_hash != CHECKSUMS[BINARY_URL]: + raise ChecksumMismatchError() + + def start_tunnel(self) -> str: + self.download_binary() + self.url = self._start_tunnel(BINARY_PATH) + return self.url + + def kill(self): + if self.proc is not None: + print(f"Killing tunnel {self.local_host}:{self.local_port} <> {self.url}") + self.proc.terminate() + self.proc = None + + def _start_tunnel(self, binary: str) -> str: + CURRENT_TUNNELS.append(self) + command = [ + binary, + "http", + "-n", + self.share_token, + "-l", + str(self.local_port), + "-i", + self.local_host, + "--uc", + "--sd", + "random", + "--ue", + "--server_addr", + f"{self.remote_host}:{self.remote_port}", + "--disable_log_color", + ] + if self.share_server_tls_certificate is not None: + command.extend( + [ + "--tls_enable", + "--tls_trusted_ca_file", + self.share_server_tls_certificate, + ] + ) + self.proc = subprocess.Popen( + command, stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + atexit.register(self.kill) + return self._read_url_from_tunnel_stream() + + def _read_url_from_tunnel_stream(self) -> str: + start_timestamp = time.time() + + log = [] + url = "" + + def _raise_tunnel_error(): + log_text = "\n".join(log) + print(log_text, file=sys.stderr) + raise ValueError(f"{TUNNEL_ERROR_MESSAGE}\n{log_text}") + + while url == "": + if time.time() - start_timestamp >= TUNNEL_TIMEOUT_SECONDS: + _raise_tunnel_error() + + assert self.proc is not None # noqa: S101 + if self.proc.stdout is None: + continue + + line = self.proc.stdout.readline() + line = line.decode("utf-8") + + if line == "": + continue + + log.append(line.strip()) + + if "start proxy success" in line: + result = re.search("start proxy success: (.+)\n", line) + if result is None: + _raise_tunnel_error() + else: + url = result.group(1) + elif "login to server failed" in line: + _raise_tunnel_error() + + return url diff --git a/trackio/alerts.py b/trackio/alerts.py new file mode 100644 index 0000000000000000000000000000000000000000..646b9786eacb91fca5270189a78280293e045fc0 --- /dev/null +++ b/trackio/alerts.py @@ -0,0 +1,184 @@ +import json +import logging +import ssl +import urllib.request +from enum import Enum + +try: + import certifi + + _SSL_CONTEXT = ssl.create_default_context(cafile=certifi.where()) +except ImportError: + _SSL_CONTEXT = None + +logger = logging.getLogger(__name__) + + +class AlertLevel(str, Enum): + INFO = "info" + WARN = "warn" + ERROR = "error" + + +ALERT_LEVEL_ORDER = { + AlertLevel.INFO: 0, + AlertLevel.WARN: 1, + AlertLevel.ERROR: 2, +} + +ALERT_COLORS = { + AlertLevel.INFO: "\033[94m", + AlertLevel.WARN: "\033[93m", + AlertLevel.ERROR: "\033[91m", +} +RESET_COLOR = "\033[0m" + +LEVEL_EMOJI = { + AlertLevel.INFO: "ℹ️", + AlertLevel.WARN: "⚠️", + AlertLevel.ERROR: "🚨", +} + + +def format_alert_terminal( + level: AlertLevel, title: str, text: str | None, step: int | None +) -> str: + color = ALERT_COLORS.get(level, "") + step_str = f" (step {step})" if step is not None else "" + if text: + return f"{color}[TRACKIO {level.value.upper()}]{RESET_COLOR} {title}: {text}{step_str}" + return f"{color}[TRACKIO {level.value.upper()}]{RESET_COLOR} {title}{step_str}" + + +def _is_slack_url(url: str) -> bool: + return "hooks.slack.com" in url + + +def _is_discord_url(url: str) -> bool: + return "discord.com/api/webhooks" in url or "discordapp.com/api/webhooks" in url + + +def _build_slack_payload( + level: AlertLevel, + title: str, + text: str | None, + project: str, + run: str, + step: int | None, +) -> dict: + emoji = LEVEL_EMOJI.get(level, "") + step_str = f" • Step {step}" if step is not None else "" + header = f"{emoji} *[{level.value.upper()}] {title}*" + context = f"Project: {project} • Run: {run}{step_str}" + blocks = [ + {"type": "section", "text": {"type": "mrkdwn", "text": header}}, + ] + if text: + blocks.append({"type": "section", "text": {"type": "mrkdwn", "text": text}}) + blocks.append( + {"type": "context", "elements": [{"type": "mrkdwn", "text": context}]} + ) + return {"blocks": blocks} + + +def _build_discord_payload( + level: AlertLevel, + title: str, + text: str | None, + project: str, + run: str, + step: int | None, +) -> dict: + color_map = { + AlertLevel.INFO: 3447003, + AlertLevel.WARN: 16776960, + AlertLevel.ERROR: 15158332, + } + emoji = LEVEL_EMOJI.get(level, "") + step_str = f" • Step {step}" if step is not None else "" + embed = { + "title": f"{emoji} [{level.value.upper()}] {title}", + "color": color_map.get(level, 0), + "footer": {"text": f"Project: {project} • Run: {run}{step_str}"}, + } + if text: + embed["description"] = text + return {"embeds": [embed]} + + +def _build_generic_payload( + level: AlertLevel, + title: str, + text: str | None, + project: str, + run: str, + step: int | None, + timestamp: str | None, +) -> dict: + return { + "level": level.value, + "title": title, + "text": text, + "project": project, + "run": run, + "step": step, + "timestamp": timestamp, + } + + +def parse_alert_level(level: AlertLevel | str) -> AlertLevel: + if isinstance(level, AlertLevel): + return level + normalized = level.lower().strip() + try: + return AlertLevel(normalized) + except ValueError as e: + allowed = ", ".join(lvl.value for lvl in AlertLevel) + raise ValueError( + f"Invalid alert level '{level}'. Expected one of: {allowed}." + ) from e + + +def resolve_webhook_min_level( + webhook_min_level: AlertLevel | str | None, +) -> AlertLevel | None: + if webhook_min_level is None: + return None + return parse_alert_level(webhook_min_level) + + +def should_send_webhook( + level: AlertLevel, webhook_min_level: AlertLevel | None +) -> bool: + if webhook_min_level is None: + return True + return ALERT_LEVEL_ORDER[level] >= ALERT_LEVEL_ORDER[webhook_min_level] + + +def send_webhook( + url: str, + level: AlertLevel, + title: str, + text: str | None, + project: str, + run: str, + step: int | None, + timestamp: str | None = None, +) -> None: + if _is_slack_url(url): + payload = _build_slack_payload(level, title, text, project, run, step) + elif _is_discord_url(url): + payload = _build_discord_payload(level, title, text, project, run, step) + else: + payload = _build_generic_payload( + level, title, text, project, run, step, timestamp + ) + + data = json.dumps(payload).encode("utf-8") + req = urllib.request.Request( + url, data=data, headers={"Content-Type": "application/json"} + ) + try: + urllib.request.urlopen(req, timeout=10, context=_SSL_CONTEXT) + except Exception as e: + logger.warning(f"Failed to send webhook to {url}: {e}") diff --git a/trackio/api.py b/trackio/api.py new file mode 100644 index 0000000000000000000000000000000000000000..801396543efdf24ba589a21b2cb3c6458f550899 --- /dev/null +++ b/trackio/api.py @@ -0,0 +1,87 @@ +from typing import Iterator + +from trackio.sqlite_storage import SQLiteStorage + + +class Run: + def __init__(self, project: str, name: str): + self.project = project + self.name = name + self._config = None + + @property + def id(self) -> str: + return self.name + + @property + def config(self) -> dict | None: + if self._config is None: + self._config = SQLiteStorage.get_run_config(self.project, self.name) + return self._config + + def alerts(self, level: str | None = None, since: str | None = None) -> list[dict]: + return SQLiteStorage.get_alerts( + self.project, run_name=self.name, level=level, since=since + ) + + def delete(self) -> bool: + return SQLiteStorage.delete_run(self.project, self.name) + + def move(self, new_project: str) -> bool: + success = SQLiteStorage.move_run(self.project, self.name, new_project) + if success: + self.project = new_project + return success + + def rename(self, new_name: str) -> "Run": + SQLiteStorage.rename_run(self.project, self.name, new_name) + self.name = new_name + return self + + def __repr__(self) -> str: + return f"" + + +class Runs: + def __init__(self, project: str): + self.project = project + self._runs = None + + def _load_runs(self): + if self._runs is None: + run_names = SQLiteStorage.get_runs(self.project) + self._runs = [Run(self.project, name) for name in run_names] + + def __iter__(self) -> Iterator[Run]: + self._load_runs() + return iter(self._runs) + + def __getitem__(self, index: int) -> Run: + self._load_runs() + return self._runs[index] + + def __len__(self) -> int: + self._load_runs() + return len(self._runs) + + def __repr__(self) -> str: + self._load_runs() + return f"" + + +class Api: + def runs(self, project: str) -> Runs: + if not SQLiteStorage.get_project_db_path(project).exists(): + raise ValueError(f"Project '{project}' does not exist") + return Runs(project) + + def alerts( + self, + project: str, + run: str | None = None, + level: str | None = None, + since: str | None = None, + ) -> list[dict]: + if not SQLiteStorage.get_project_db_path(project).exists(): + raise ValueError(f"Project '{project}' does not exist") + return SQLiteStorage.get_alerts(project, run_name=run, level=level, since=since) diff --git a/trackio/apple_gpu.py b/trackio/apple_gpu.py new file mode 100644 index 0000000000000000000000000000000000000000..6192319db2aa56b6a7c752e97ceabdb0678ca367 --- /dev/null +++ b/trackio/apple_gpu.py @@ -0,0 +1,253 @@ +import platform +import subprocess +import sys +import threading +import warnings +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from trackio.run import Run + +psutil: Any = None +PSUTIL_AVAILABLE = False +_monitor_lock = threading.Lock() + + +def _ensure_psutil(): + global PSUTIL_AVAILABLE, psutil + if PSUTIL_AVAILABLE: + return psutil + try: + import psutil as _psutil + + psutil = _psutil + PSUTIL_AVAILABLE = True + return psutil + except ImportError: + raise ImportError( + "psutil is required for Apple Silicon monitoring. " + "Install it with: pip install psutil" + ) + + +def is_apple_silicon() -> bool: + """Check if running on Apple Silicon (M1/M2/M3/M4).""" + if platform.system() != "Darwin": + return False + + try: + result = subprocess.run( + ["sysctl", "-n", "machdep.cpu.brand_string"], + capture_output=True, + text=True, + timeout=1, + ) + cpu_brand = result.stdout.strip() + return "Apple" in cpu_brand + except Exception: + return False + + +def get_gpu_info() -> dict[str, Any]: + """Get Apple GPU information using ioreg.""" + try: + result = subprocess.run( + ["ioreg", "-r", "-d", "1", "-w", "0", "-c", "IOAccelerator"], + capture_output=True, + text=True, + timeout=2, + ) + + if result.returncode == 0 and result.stdout: + lines = result.stdout.strip().split("\n") + for line in lines: + if "IOAccelerator" in line and "class" in line: + return {"detected": True, "type": "Apple GPU"} + else: + print("Error collecting Apple GPU info. ioreg stdout was:", file=sys.stderr) + print(result.stdout, file=sys.stderr) + print("ioreg stderr was:", file=sys.stderr) + print(result.stderr, file=sys.stderr) + + result = subprocess.run( + ["system_profiler", "SPDisplaysDataType"], + capture_output=True, + text=True, + timeout=3, + ) + + if result.returncode == 0 and "Apple" in result.stdout: + for line in result.stdout.split("\n"): + if "Chipset Model:" in line: + model = line.split(":")[-1].strip() + return {"detected": True, "type": model} + + except Exception: + pass + + return {"detected": False} + + +def apple_gpu_available() -> bool: + """ + Check if Apple GPU monitoring is available. + + Returns True if running on Apple Silicon (M-series chips) and psutil is installed. + """ + try: + _ensure_psutil() + return is_apple_silicon() + except ImportError: + return False + except Exception: + return False + + +def collect_apple_metrics() -> dict: + """ + Collect system metrics for Apple Silicon. + + Returns: + Dictionary of system metrics including CPU, memory, and GPU info. + """ + if not PSUTIL_AVAILABLE: + try: + _ensure_psutil() + except ImportError: + return {} + + metrics = {} + + try: + cpu_percent = psutil.cpu_percent(interval=0.1, percpu=False) + metrics["cpu/utilization"] = cpu_percent + except Exception: + pass + + try: + cpu_percents = psutil.cpu_percent(interval=0.1, percpu=True) + for i, percent in enumerate(cpu_percents): + metrics[f"cpu/{i}/utilization"] = percent + except Exception: + pass + + try: + cpu_freq = psutil.cpu_freq() + if cpu_freq: + metrics["cpu/frequency"] = cpu_freq.current + if cpu_freq.max > 0: + metrics["cpu/frequency_max"] = cpu_freq.max + except Exception: + pass + + try: + mem = psutil.virtual_memory() + metrics["memory/used"] = mem.used / (1024**3) + metrics["memory/total"] = mem.total / (1024**3) + metrics["memory/available"] = mem.available / (1024**3) + metrics["memory/percent"] = mem.percent + except Exception: + pass + + try: + swap = psutil.swap_memory() + metrics["swap/used"] = swap.used / (1024**3) + metrics["swap/total"] = swap.total / (1024**3) + metrics["swap/percent"] = swap.percent + except Exception: + pass + + try: + sensors_temps = psutil.sensors_temperatures() + if sensors_temps: + for name, entries in sensors_temps.items(): + for i, entry in enumerate(entries): + label = entry.label or f"{name}_{i}" + metrics[f"temp/{label}"] = entry.current + except Exception: + pass + + gpu_info = get_gpu_info() + if gpu_info.get("detected"): + metrics["gpu/detected"] = 1 + if "type" in gpu_info: + pass + + return metrics + + +class AppleGpuMonitor: + def __init__(self, run: "Run", interval: float = 10.0): + self._run = run + self._interval = interval + self._stop_flag = threading.Event() + self._thread: "threading.Thread | None" = None + + def start(self): + if not is_apple_silicon(): + warnings.warn( + "auto_log_gpu=True but not running on Apple Silicon. " + "Apple GPU logging disabled." + ) + return + + if not PSUTIL_AVAILABLE: + try: + _ensure_psutil() + except ImportError: + warnings.warn( + "auto_log_gpu=True but psutil not installed. " + "Install with: pip install psutil" + ) + return + + self._thread = threading.Thread(target=self._monitor_loop, daemon=True) + self._thread.start() + + def stop(self): + self._stop_flag.set() + if self._thread is not None: + self._thread.join(timeout=2.0) + + def _monitor_loop(self): + while not self._stop_flag.is_set(): + try: + metrics = collect_apple_metrics() + if metrics: + self._run.log_system(metrics) + except Exception: + pass + + self._stop_flag.wait(timeout=self._interval) + + +def log_apple_gpu(run: "Run | None" = None) -> dict: + """ + Log Apple Silicon system metrics to the current or specified run. + + Args: + run: Optional Run instance. If None, uses current run from context. + + Returns: + dict: The system metrics that were logged. + + Example: + ```python + import trackio + + run = trackio.init(project="my-project") + trackio.log({"loss": 0.5}) + trackio.log_apple_gpu() + ``` + """ + from trackio import context_vars + + if run is None: + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_apple_gpu().") + + metrics = collect_apple_metrics() + if metrics: + run.log_system(metrics) + return metrics diff --git a/trackio/asgi_app.py b/trackio/asgi_app.py new file mode 100644 index 0000000000000000000000000000000000000000..9f9a60961ed022965847444b75e405cd9ff94db1 --- /dev/null +++ b/trackio/asgi_app.py @@ -0,0 +1,175 @@ +from __future__ import annotations + +import asyncio +import inspect +import json +import secrets +import traceback +from collections.abc import Callable +from typing import Any + +from starlette.applications import Starlette +from starlette.requests import Request +from starlette.responses import FileResponse, JSONResponse, Response, StreamingResponse +from starlette.routing import Route + +from trackio.exceptions import TrackioAPIError + +API_PREFIX = "/gradio_api" + + +def _serialize_result(data: Any) -> str: + def default(o: Any): + if isinstance(o, (dict, list, str, int, float, bool)) or o is None: + return o + if hasattr(o, "item"): + try: + return o.item() + except Exception: + pass + return str(o) + + return json.dumps(data, default=default) + + +def _invoke_handler( + fn: Callable, + request: Request, + data: list[Any], +) -> Any: + sig = inspect.signature(fn) + params = list(sig.parameters.values()) + pos_args: list[Any] = [] + di = 0 + for p in params: + if p.name == "request": + pos_args.append(request) + else: + if di < len(data): + pos_args.append(data[di]) + else: + pos_args.append(None) + di += 1 + return fn(*pos_args) + + +class _EventStore: + def __init__(self) -> None: + self._results: dict[str, tuple[Any, bool, str | None]] = {} + + def store_result( + self, event_id: str, result: Any, is_error: bool, err_msg: str | None + ) -> None: + self._results[event_id] = (result, is_error, err_msg) + + def pop(self, event_id: str) -> tuple[Any, bool, str | None] | None: + return self._results.pop(event_id, None) + + +_event_store = _EventStore() + + +def build_gradio_compat_handlers( + api_registry: dict[str, Callable[..., Any]], +) -> tuple[Callable, Callable]: + async def call_post(request: Request) -> Response: + api_name = request.path_params["api_name"].lstrip("/") + fn = api_registry.get(api_name) + if fn is None: + return JSONResponse({"detail": f"Unknown API: {api_name}"}, status_code=404) + try: + body = await request.json() + except Exception: + body = {} + data = body.get("data") or [] + if not isinstance(data, list): + data = [data] + event_id = secrets.token_urlsafe(16) + try: + out = await asyncio.to_thread(_invoke_handler, fn, request, data) + _event_store.store_result(event_id, out, False, None) + except TrackioAPIError as e: + _event_store.store_result(event_id, None, True, str(e)) + except Exception: + tb = traceback.format_exc() + print(tb) + _event_store.store_result(event_id, None, True, tb) + return JSONResponse({"event_id": event_id}) + + async def call_get(request: Request) -> Response: + event_id = request.path_params["event_id"] + + async def sse_gen(): + for _ in range(500): + await asyncio.sleep(0.005) + got = _event_store.pop(event_id) + if got is not None: + result, is_err, err_msg = got + if is_err: + payload = json.dumps(err_msg) + yield f"event: error\ndata: {payload}\n\n" + else: + wrapped = [result] if not isinstance(result, list) else result + payload = _serialize_result(wrapped) + yield f"event: complete\ndata: {payload}\n\n" + return + err = json.dumps("timeout waiting for result") + yield f"event: error\ndata: {err}\n\n" + + return StreamingResponse(sse_gen(), media_type="text/event-stream") + + return call_post, call_get + + +async def gradio_file_handler(request: Request) -> Response: + from pathlib import Path + from urllib.parse import unquote + + rest = request.path_params.get("rest", "") + if not rest.startswith("file="): + return Response("Not found", status_code=404) + fs_path = unquote(rest[5:]) + fp = Path(fs_path) + if fp.is_file(): + return FileResponse(str(fp)) + return Response("Not found", status_code=404) + + +async def startup_events_handler(request: Request) -> Response: + return JSONResponse({"status": "ok"}) + + +def create_trackio_starlette_app( + oauth_routes: list[Route], + api_registry: dict[str, Callable[..., Any]], + mcp_lifespan: Any = None, +) -> Starlette: + call_post, call_get = build_gradio_compat_handlers(api_registry) + routes: list[Any] = list(oauth_routes) + routes.append( + Route( + API_PREFIX + "/call/{api_name:path}", + endpoint=call_post, + methods=["POST"], + ) + ) + routes.append( + Route( + API_PREFIX + "/call/{api_name:path}/{event_id}", + endpoint=call_get, + methods=["GET"], + ) + ) + routes.append( + Route( + API_PREFIX + "/startup-events", + endpoint=startup_events_handler, + methods=["GET"], + ) + ) + routes.append( + Route( + API_PREFIX + "/{rest:path}", endpoint=gradio_file_handler, methods=["GET"] + ) + ) + return Starlette(routes=routes, lifespan=mcp_lifespan) diff --git a/trackio/assets/badge.png b/trackio/assets/badge.png new file mode 100644 index 0000000000000000000000000000000000000000..03e0340873223b3ecb45f3ebf09512f6d6746ec2 --- /dev/null +++ b/trackio/assets/badge.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:206b7847247e83279f498510a2760338a03116bb5141a658d71ec14429f9ea9e +size 169669 diff --git a/trackio/assets/trackio_logo_dark.png b/trackio/assets/trackio_logo_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..e6ff7e0a3580bca040d9ec3ea8c91e8cca469e61 Binary files /dev/null and b/trackio/assets/trackio_logo_dark.png differ diff --git a/trackio/assets/trackio_logo_light.png b/trackio/assets/trackio_logo_light.png new file mode 100644 index 0000000000000000000000000000000000000000..b3438262c61989e6c6d16df4801a8935136115b3 Binary files /dev/null and b/trackio/assets/trackio_logo_light.png differ diff --git a/trackio/assets/trackio_logo_old.png b/trackio/assets/trackio_logo_old.png new file mode 100644 index 0000000000000000000000000000000000000000..48a07d40b83e23c9cc9dc0cb6544a3c6ad62b57f --- /dev/null +++ b/trackio/assets/trackio_logo_old.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3922c4d1e465270ad4d8abb12023f3beed5d9f7f338528a4c0ac21dcf358a1c8 +size 487101 diff --git a/trackio/assets/trackio_logo_type_dark.png b/trackio/assets/trackio_logo_type_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..6f80a3191e514a8a0beaa6ab2011e5baf8df5eda Binary files /dev/null and b/trackio/assets/trackio_logo_type_dark.png differ diff --git a/trackio/assets/trackio_logo_type_dark_transparent.png b/trackio/assets/trackio_logo_type_dark_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..2495f610c975917290b57706133b38621a58cb8b Binary files /dev/null and b/trackio/assets/trackio_logo_type_dark_transparent.png differ diff --git a/trackio/assets/trackio_logo_type_light.png b/trackio/assets/trackio_logo_type_light.png new file mode 100644 index 0000000000000000000000000000000000000000..f07866d245ea897b9aba417b29403f7f91cc8bbd Binary files /dev/null and b/trackio/assets/trackio_logo_type_light.png differ diff --git a/trackio/assets/trackio_logo_type_light_transparent.png b/trackio/assets/trackio_logo_type_light_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..a20b4d5e64c61c91546577645310593fe3493508 Binary files /dev/null and b/trackio/assets/trackio_logo_type_light_transparent.png differ diff --git a/trackio/bucket_storage.py b/trackio/bucket_storage.py new file mode 100644 index 0000000000000000000000000000000000000000..9ba9b6b381a2b17021a113e868bcb99f87bd0792 --- /dev/null +++ b/trackio/bucket_storage.py @@ -0,0 +1,151 @@ +import shutil +import tempfile +from pathlib import Path + +import huggingface_hub +from huggingface_hub import copy_files, sync_bucket + +from trackio.sqlite_storage import SQLiteStorage +from trackio.utils import MEDIA_DIR, TRACKIO_DIR + + +def create_bucket_if_not_exists(bucket_id: str, private: bool | None = None) -> None: + huggingface_hub.create_bucket(bucket_id, private=private, exist_ok=True) + + +def _list_bucket_file_paths(bucket_id: str, prefix: str | None = None) -> list[str]: + items = huggingface_hub.list_bucket_tree(bucket_id, prefix=prefix, recursive=True) + return [ + item.path + for item in items + if getattr(item, "type", None) == "file" and getattr(item, "path", None) + ] + + +def download_bucket_to_trackio_dir(bucket_id: str) -> None: + TRACKIO_DIR.mkdir(parents=True, exist_ok=True) + sync_bucket( + source=f"hf://buckets/{bucket_id}", + dest=str(TRACKIO_DIR.parent), + quiet=True, + ) + + +def upload_project_to_bucket(project: str, bucket_id: str) -> None: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + raise FileNotFoundError(f"No database found for project '{project}'") + + with SQLiteStorage._get_connection( + db_path, configure_pragmas=False, row_factory=None + ) as conn: + conn.execute("PRAGMA wal_checkpoint(TRUNCATE)") + + files_to_add = [(str(db_path), f"trackio/{db_path.name}")] + + media_dir = MEDIA_DIR / project + if media_dir.exists(): + for media_file in media_dir.rglob("*"): + if media_file.is_file(): + rel = media_file.relative_to(TRACKIO_DIR) + files_to_add.append((str(media_file), f"trackio/{rel}")) + + huggingface_hub.batch_bucket_files(bucket_id, add=files_to_add) + + +def _download_db_from_bucket( + project: str, bucket_id: str, dest_path: Path | None = None +) -> bool: + db_filename = SQLiteStorage.get_project_db_filename(project) + remote_path = f"trackio/{db_filename}" + local_path = dest_path or SQLiteStorage.get_project_db_path(project) + local_path.parent.mkdir(parents=True, exist_ok=True) + try: + huggingface_hub.download_bucket_files( + bucket_id, + files=[(remote_path, str(local_path))], + ) + return local_path.exists() + except Exception: + return False + + +def _local_db_has_data(project: str) -> bool: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists() or db_path.stat().st_size == 0: + return False + try: + with SQLiteStorage._get_connection( + db_path, configure_pragmas=False, row_factory=None + ) as conn: + count = conn.execute("SELECT COUNT(*) FROM metrics").fetchone()[0] + return count > 0 + except Exception: + return False + + +def _export_and_upload_static( + project: str, + dest_bucket_id: str, + db_path: Path, + media_dir: Path | None = None, +) -> None: + with tempfile.TemporaryDirectory() as tmp_dir: + output_dir = Path(tmp_dir) + SQLiteStorage.export_for_static_space( + project, output_dir, db_path_override=db_path + ) + + if media_dir and media_dir.exists(): + shutil.copytree(media_dir, output_dir / "media") + + files_to_add = [] + for f in output_dir.rglob("*"): + if f.is_file(): + rel = f.relative_to(output_dir) + files_to_add.append((str(f), str(rel))) + + huggingface_hub.batch_bucket_files(dest_bucket_id, add=files_to_add) + + +def _copy_project_media_between_buckets( + source_bucket_id: str, dest_bucket_id: str, project: str +) -> None: + source_media_prefix = f"trackio/media/{project}/" + media_to_copy = _list_bucket_file_paths( + source_bucket_id, prefix=source_media_prefix + ) + if not media_to_copy: + return + + copy_files( + f"hf://buckets/{source_bucket_id}/{source_media_prefix}", + f"hf://buckets/{dest_bucket_id}/media/", + ) + + +def upload_project_to_bucket_for_static(project: str, bucket_id: str) -> None: + if not _local_db_has_data(project): + _download_db_from_bucket(project, bucket_id) + + db_path = SQLiteStorage.get_project_db_path(project) + _export_and_upload_static(project, bucket_id, db_path, MEDIA_DIR / project) + + +def export_from_bucket_for_static( + source_bucket_id: str, + dest_bucket_id: str, + project: str, +) -> None: + with tempfile.TemporaryDirectory() as work_dir: + work_path = Path(work_dir) + db_path = work_path / SQLiteStorage.get_project_db_filename(project) + + if not _download_db_from_bucket(project, source_bucket_id, dest_path=db_path): + raise FileNotFoundError( + f"Could not download database for project '{project}' " + f"from bucket '{source_bucket_id}'." + ) + + _export_and_upload_static(project, dest_bucket_id, db_path) + _copy_project_media_between_buckets(source_bucket_id, dest_bucket_id, project) diff --git a/trackio/cli.py b/trackio/cli.py new file mode 100644 index 0000000000000000000000000000000000000000..6f7252b61b03691d9ce2f2a5a9449bb3ed3062dd --- /dev/null +++ b/trackio/cli.py @@ -0,0 +1,1272 @@ +import argparse +import os + +from trackio import freeze, show, sync +from trackio.cli_helpers import ( + error_exit, + format_alerts, + format_json, + format_list, + format_metric_values, + format_project_summary, + format_run_summary, + format_snapshot, + format_system_metric_names, + format_system_metrics, +) +from trackio.markdown import Markdown +from trackio.server import get_project_summary, get_run_summary +from trackio.sqlite_storage import SQLiteStorage + + +def _get_space(args): + return getattr(args, "space", None) + + +def _get_remote(args): + from trackio.remote_client import RemoteClient + + space = _get_space(args) + if not space: + return None + hf_token = getattr(args, "hf_token", None) + return RemoteClient(space, hf_token=hf_token) + + +def _handle_status(): + print("Reading local Trackio projects...\n") + projects = SQLiteStorage.get_projects() + if not projects: + print("No Trackio projects found.") + return + + local_projects = [] + synced_projects = [] + unsynced_projects = [] + + for project in projects: + space_id = SQLiteStorage.get_space_id(project) + if space_id is None: + local_projects.append(project) + elif SQLiteStorage.has_pending_data(project): + unsynced_projects.append(project) + else: + synced_projects.append(project) + + print("Finished reading Trackio projects") + if local_projects: + print(f" * {len(local_projects)} local trackio project(s) [OK]") + if synced_projects: + print(f" * {len(synced_projects)} trackio project(s) synced to Spaces [OK]") + if unsynced_projects: + print( + f" * {len(unsynced_projects)} trackio project(s) with unsynced changes [WARNING]:" + ) + for p in unsynced_projects: + print(f" - {p}") + + if unsynced_projects: + print( + f"\nRun `trackio sync --project {unsynced_projects[0]}` to sync. " + "Or run `trackio sync --all` to sync all unsynced changes." + ) + + +def _handle_sync(args): + from trackio.deploy import sync_incremental + + if args.sync_all and args.project: + error_exit("Cannot use --all and --project together.") + if not args.sync_all and not args.project: + error_exit("Must provide either --project or --all.") + + if args.sync_all: + projects = SQLiteStorage.get_projects() + synced_any = False + for project in projects: + space_id = SQLiteStorage.get_space_id(project) + if space_id and SQLiteStorage.has_pending_data(project): + sync_incremental( + project, space_id, private=args.private, pending_only=True + ) + synced_any = True + if not synced_any: + print("No projects with unsynced data found.") + else: + space_id = args.space_id + if space_id is None: + space_id = SQLiteStorage.get_space_id(args.project) + sync( + project=args.project, + space_id=space_id, + private=args.private, + force=args.force, + sdk=args.sdk, + ) + + +def _extract_reports( + run: str, logs: list[dict], report_name: str | None = None +) -> list[dict]: + reports = [] + for log in logs: + timestamp = log.get("timestamp") + step = log.get("step") + for key, value in log.items(): + if report_name is not None and key != report_name: + continue + if isinstance(value, dict) and value.get("_type") == Markdown.TYPE: + content = value.get("_value") + if isinstance(content, str): + reports.append( + { + "run": run, + "report": key, + "step": step, + "timestamp": timestamp, + "content": content, + } + ) + return reports + + +def main(): + parser = argparse.ArgumentParser(description="Trackio CLI") + parser.add_argument( + "--space", + required=False, + help="HF Space ID (e.g. 'user/space') or Space URL to query remotely.", + ) + parser.add_argument( + "--hf-token", + required=False, + help="HF token for accessing private Spaces.", + ) + subparsers = parser.add_subparsers(dest="command") + + ui_parser = subparsers.add_parser( + "show", help="Show the Trackio dashboard UI for a project" + ) + ui_parser.add_argument( + "--project", required=False, help="Project name to show in the dashboard" + ) + ui_parser.add_argument( + "--theme", + required=False, + default="default", + help="A Gradio Theme to use for the dashboard instead of the default, can be a built-in theme (e.g. 'soft', 'citrus'), or a theme from the Hub (e.g. 'gstaff/xkcd').", + ) + ui_parser.add_argument( + "--mcp-server", + action="store_true", + help="Enable MCP server functionality. The Trackio dashboard will be set up as an MCP server and certain functions will be exposed as MCP tools.", + ) + ui_parser.add_argument( + "--footer", + action="store_true", + default=True, + help="Show the Gradio footer. Use --no-footer to hide it.", + ) + ui_parser.add_argument( + "--no-footer", + dest="footer", + action="store_false", + help="Hide the Gradio footer.", + ) + ui_parser.add_argument( + "--color-palette", + required=False, + help="Comma-separated list of hex color codes for plot lines (e.g. '#FF0000,#00FF00,#0000FF'). If not provided, the TRACKIO_COLOR_PALETTE environment variable will be used, or the default palette if not set.", + ) + ui_parser.add_argument( + "--host", + required=False, + help="Host to bind the server to (e.g. '0.0.0.0' for remote access). If not provided, defaults to '127.0.0.1' (localhost only).", + ) + + subparsers.add_parser( + "status", + help="Show the status of all local Trackio projects, including sync status.", + ) + + sync_parser = subparsers.add_parser( + "sync", + help="Sync a local project's database to a Hugging Face Space. If the Space does not exist, it will be created.", + ) + sync_parser.add_argument( + "--project", + required=False, + help="The name of the local project.", + ) + sync_parser.add_argument( + "--space-id", + required=False, + help="The Hugging Face Space ID where the project will be synced (e.g. username/space_id). If not provided, uses the previously-configured Space.", + ) + sync_parser.add_argument( + "--all", + action="store_true", + dest="sync_all", + help="Sync all projects that have unsynced data to their configured Spaces.", + ) + sync_parser.add_argument( + "--private", + action="store_true", + help="Make the Hugging Face Space private if creating a new Space. By default, the repo will be public unless the organization's default is private. This value is ignored if the repo already exists.", + ) + sync_parser.add_argument( + "--force", + action="store_true", + help="Overwrite the existing database without prompting for confirmation.", + ) + sync_parser.add_argument( + "--sdk", + choices=["gradio", "static"], + default="gradio", + help="The type of Space to deploy. 'gradio' (default) deploys a live Gradio server. 'static' deploys a static Space that reads from an HF Bucket.", + ) + + freeze_parser = subparsers.add_parser( + "freeze", + help="Create a one-time static Space snapshot from a project's data.", + ) + freeze_parser.add_argument( + "--space-id", + required=True, + help="The source Gradio Space ID (e.g. username/space_id).", + ) + freeze_parser.add_argument( + "--project", + required=True, + help="The name of the project to freeze into a static snapshot.", + ) + freeze_parser.add_argument( + "--new-space-id", + required=False, + help="The Space ID for the new static Space. Defaults to {space_id}_static.", + ) + freeze_parser.add_argument( + "--private", + action="store_true", + help="Make the new static Space private.", + ) + + list_parser = subparsers.add_parser( + "list", + help="List projects, runs, or metrics", + ) + list_subparsers = list_parser.add_subparsers(dest="list_type", required=True) + + list_projects_parser = list_subparsers.add_parser( + "projects", + help="List all projects", + ) + list_projects_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_runs_parser = list_subparsers.add_parser( + "runs", + help="List runs for a project", + ) + list_runs_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_runs_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_metrics_parser = list_subparsers.add_parser( + "metrics", + help="List metrics for a run", + ) + list_metrics_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_metrics_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + list_metrics_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_system_metrics_parser = list_subparsers.add_parser( + "system-metrics", + help="List system metrics for a run", + ) + list_system_metrics_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_system_metrics_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + list_system_metrics_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + list_alerts_parser = list_subparsers.add_parser( + "alerts", + help="List alerts for a project or run", + ) + list_alerts_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_alerts_parser.add_argument( + "--run", + required=False, + help="Run name (optional)", + ) + list_alerts_parser.add_argument( + "--level", + required=False, + help="Filter by alert level (info, warn, error)", + ) + list_alerts_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + list_alerts_parser.add_argument( + "--since", + required=False, + help="Only show alerts after this ISO 8601 timestamp", + ) + + list_reports_parser = list_subparsers.add_parser( + "reports", + help="List markdown reports for a project or run", + ) + list_reports_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + list_reports_parser.add_argument( + "--run", + required=False, + help="Run name (optional)", + ) + list_reports_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_parser = subparsers.add_parser( + "get", + help="Get project, run, or metric information", + ) + get_subparsers = get_parser.add_subparsers(dest="get_type", required=True) + + get_project_parser = get_subparsers.add_parser( + "project", + help="Get project summary", + ) + get_project_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_project_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_run_parser = get_subparsers.add_parser( + "run", + help="Get run summary", + ) + get_run_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_run_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_run_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_metric_parser = get_subparsers.add_parser( + "metric", + help="Get metric values for a run", + ) + get_metric_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_metric_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_metric_parser.add_argument( + "--metric", + required=True, + help="Metric name", + ) + get_metric_parser.add_argument( + "--step", + type=int, + required=False, + help="Get metric at exactly this step", + ) + get_metric_parser.add_argument( + "--around", + type=int, + required=False, + help="Get metrics around this step (use with --window)", + ) + get_metric_parser.add_argument( + "--at-time", + required=False, + help="Get metrics around this ISO 8601 timestamp (use with --window)", + ) + get_metric_parser.add_argument( + "--window", + type=int, + required=False, + default=10, + help="Window size: ±steps for --around, ±seconds for --at-time (default: 10)", + ) + get_metric_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_snapshot_parser = get_subparsers.add_parser( + "snapshot", + help="Get all metrics at/around a step or timestamp", + ) + get_snapshot_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_snapshot_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_snapshot_parser.add_argument( + "--step", + type=int, + required=False, + help="Get all metrics at exactly this step", + ) + get_snapshot_parser.add_argument( + "--around", + type=int, + required=False, + help="Get all metrics around this step (use with --window)", + ) + get_snapshot_parser.add_argument( + "--at-time", + required=False, + help="Get all metrics around this ISO 8601 timestamp (use with --window)", + ) + get_snapshot_parser.add_argument( + "--window", + type=int, + required=False, + default=10, + help="Window size: ±steps for --around, ±seconds for --at-time (default: 10)", + ) + get_snapshot_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_system_metric_parser = get_subparsers.add_parser( + "system-metric", + help="Get system metric values for a run", + ) + get_system_metric_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_system_metric_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_system_metric_parser.add_argument( + "--metric", + required=False, + help="System metric name (optional, if not provided returns all system metrics)", + ) + get_system_metric_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + get_alerts_parser = get_subparsers.add_parser( + "alerts", + help="Get alerts for a project or run", + ) + get_alerts_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_alerts_parser.add_argument( + "--run", + required=False, + help="Run name (optional)", + ) + get_alerts_parser.add_argument( + "--level", + required=False, + help="Filter by alert level (info, warn, error)", + ) + get_alerts_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + get_alerts_parser.add_argument( + "--since", + required=False, + help="Only show alerts after this ISO 8601 timestamp", + ) + + get_report_parser = get_subparsers.add_parser( + "report", + help="Get markdown report entries for a run", + ) + get_report_parser.add_argument( + "--project", + required=True, + help="Project name", + ) + get_report_parser.add_argument( + "--run", + required=True, + help="Run name", + ) + get_report_parser.add_argument( + "--report", + required=True, + help="Report metric name", + ) + get_report_parser.add_argument( + "--json", + action="store_true", + help="Output in JSON format", + ) + + skills_parser = subparsers.add_parser( + "skills", + help="Manage Trackio skills for AI coding assistants", + ) + skills_subparsers = skills_parser.add_subparsers( + dest="skills_action", required=True + ) + skills_add_parser = skills_subparsers.add_parser( + "add", + help="Download and install the Trackio skill for an AI assistant", + ) + skills_add_parser.add_argument( + "--cursor", + action="store_true", + help="Install for Cursor", + ) + skills_add_parser.add_argument( + "--claude", + action="store_true", + help="Install for Claude Code", + ) + skills_add_parser.add_argument( + "--codex", + action="store_true", + help="Install for Codex", + ) + skills_add_parser.add_argument( + "--opencode", + action="store_true", + help="Install for OpenCode", + ) + skills_add_parser.add_argument( + "--global", + dest="global_", + action="store_true", + help="Install globally (user-level) instead of in the current project directory", + ) + skills_add_parser.add_argument( + "--dest", + type=str, + required=False, + help="Install into a custom destination (path to skills directory)", + ) + skills_add_parser.add_argument( + "--force", + action="store_true", + help="Overwrite existing skill if it already exists", + ) + + args, unknown_args = parser.parse_known_args() + if unknown_args: + trailing_global_parser = argparse.ArgumentParser(add_help=False) + trailing_global_parser.add_argument("--space", required=False) + trailing_global_parser.add_argument("--hf-token", required=False) + trailing_globals, remaining_unknown = trailing_global_parser.parse_known_args( + unknown_args + ) + if remaining_unknown: + parser.error(f"unrecognized arguments: {' '.join(remaining_unknown)}") + if trailing_globals.space is not None: + args.space = trailing_globals.space + if trailing_globals.hf_token is not None: + args.hf_token = trailing_globals.hf_token + + if args.command in ("show", "status", "sync", "freeze", "skills") and _get_space( + args + ): + error_exit( + f"The '{args.command}' command does not support --space (remote mode)." + ) + + if args.command == "show": + color_palette = None + if args.color_palette: + color_palette = [color.strip() for color in args.color_palette.split(",")] + show( + project=args.project, + theme=args.theme, + mcp_server=args.mcp_server, + footer=args.footer, + color_palette=color_palette, + host=args.host, + ) + elif args.command == "status": + _handle_status() + elif args.command == "sync": + _handle_sync(args) + elif args.command == "freeze": + freeze( + space_id=args.space_id, + project=args.project, + new_space_id=args.new_space_id, + private=args.private, + ) + elif args.command == "list": + remote = _get_remote(args) + if args.list_type == "projects": + if remote: + projects = remote.predict(api_name="/get_all_projects") + else: + projects = SQLiteStorage.get_projects() + if args.json: + print(format_json({"projects": projects})) + else: + print(format_list(projects, "Projects")) + elif args.list_type == "runs": + if remote: + runs = remote.predict(args.project, api_name="/get_runs_for_project") + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.json: + print(format_json({"project": args.project, "runs": runs})) + else: + print(format_list(runs, f"Runs in '{args.project}'")) + elif args.list_type == "metrics": + if remote: + metrics = remote.predict( + args.project, args.run, api_name="/get_metrics_for_run" + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + metrics = SQLiteStorage.get_all_metrics_for_run(args.project, args.run) + if args.json: + print( + format_json( + {"project": args.project, "run": args.run, "metrics": metrics} + ) + ) + else: + print( + format_list( + metrics, f"Metrics for '{args.run}' in '{args.project}'" + ) + ) + elif args.list_type == "system-metrics": + if remote: + system_metrics = remote.predict( + args.project, args.run, api_name="/get_system_metrics_for_run" + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + system_metrics = SQLiteStorage.get_all_system_metrics_for_run( + args.project, args.run + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "system_metrics": system_metrics, + } + ) + ) + else: + print(format_system_metric_names(system_metrics)) + elif args.list_type == "alerts": + if remote: + alerts = remote.predict( + args.project, + args.run, + args.level, + args.since, + api_name="/get_alerts", + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + alerts = SQLiteStorage.get_alerts( + args.project, + run_name=args.run, + level=args.level, + since=args.since, + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "level": args.level, + "since": args.since, + "alerts": alerts, + } + ) + ) + else: + print(format_alerts(alerts)) + elif args.list_type == "reports": + if remote: + runs = remote.predict(args.project, api_name="/get_runs_for_project") + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run and args.run not in runs: + error_exit(f"Run '{args.run}' not found in project '{args.project}'.") + + target_runs = [args.run] if args.run else runs + all_reports = [] + for run_name in target_runs: + if remote: + logs = remote.predict(args.project, run_name, api_name="/get_logs") + else: + logs = SQLiteStorage.get_logs(args.project, run_name) + all_reports.extend(_extract_reports(run_name, logs)) + + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "reports": all_reports, + } + ) + ) + else: + report_lines = [ + f"{entry['run']} | {entry['report']} | step={entry['step']} | {entry['timestamp']}" + for entry in all_reports + ] + if args.run: + print( + format_list( + report_lines, + f"Reports for '{args.run}' in '{args.project}'", + ) + ) + else: + print(format_list(report_lines, f"Reports in '{args.project}'")) + elif args.command == "get": + remote = _get_remote(args) + if args.get_type == "project": + if remote: + summary = remote.predict(args.project, api_name="/get_project_summary") + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + summary = get_project_summary(args.project) + if args.json: + print(format_json(summary)) + else: + print(format_project_summary(summary)) + elif args.get_type == "run": + if remote: + summary = remote.predict( + args.project, args.run, api_name="/get_run_summary" + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + summary = get_run_summary(args.project, args.run) + if args.json: + print(format_json(summary)) + else: + print(format_run_summary(summary)) + elif args.get_type == "metric": + at_time = getattr(args, "at_time", None) + if remote: + values = remote.predict( + args.project, + args.run, + args.metric, + args.step, + args.around, + at_time, + args.window, + api_name="/get_metric_values", + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + metrics = SQLiteStorage.get_all_metrics_for_run(args.project, args.run) + if args.metric not in metrics: + error_exit( + f"Metric '{args.metric}' not found in run '{args.run}' of project '{args.project}'." + ) + values = SQLiteStorage.get_metric_values( + args.project, + args.run, + args.metric, + step=args.step, + around_step=args.around, + at_time=at_time, + window=args.window, + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "metric": args.metric, + "values": values, + } + ) + ) + else: + print(format_metric_values(values)) + elif args.get_type == "snapshot": + if not args.step and not args.around and not getattr(args, "at_time", None): + error_exit( + "Provide --step, --around (with --window), or --at-time (with --window)." + ) + at_time = getattr(args, "at_time", None) + if remote: + snapshot = remote.predict( + args.project, + args.run, + args.step, + args.around, + at_time, + args.window, + api_name="/get_snapshot", + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + snapshot = SQLiteStorage.get_snapshot( + args.project, + args.run, + step=args.step, + around_step=args.around, + at_time=at_time, + window=args.window, + ) + if args.json: + result = { + "project": args.project, + "run": args.run, + "metrics": snapshot, + } + if args.step is not None: + result["step"] = args.step + if args.around is not None: + result["around"] = args.around + result["window"] = args.window + if at_time is not None: + result["at_time"] = at_time + result["window"] = args.window + print(format_json(result)) + else: + print(format_snapshot(snapshot)) + elif args.get_type == "system-metric": + if remote: + system_metrics = remote.predict( + args.project, args.run, api_name="/get_system_logs" + ) + if args.metric: + all_system_metric_names = remote.predict( + args.project, + args.run, + api_name="/get_system_metrics_for_run", + ) + if args.metric not in all_system_metric_names: + error_exit( + f"System metric '{args.metric}' not found in run '{args.run}' of project '{args.project}'." + ) + filtered_metrics = [ + { + k: v + for k, v in entry.items() + if k == "timestamp" or k == args.metric + } + for entry in system_metrics + if args.metric in entry + ] + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "metric": args.metric, + "values": filtered_metrics, + } + ) + ) + else: + print(format_system_metrics(filtered_metrics)) + else: + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "system_metrics": system_metrics, + } + ) + ) + else: + print(format_system_metrics(system_metrics)) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + if args.metric: + system_metrics = SQLiteStorage.get_system_logs( + args.project, args.run + ) + all_system_metric_names = ( + SQLiteStorage.get_all_system_metrics_for_run( + args.project, args.run + ) + ) + if args.metric not in all_system_metric_names: + error_exit( + f"System metric '{args.metric}' not found in run '{args.run}' of project '{args.project}'." + ) + filtered_metrics = [ + { + k: v + for k, v in entry.items() + if k == "timestamp" or k == args.metric + } + for entry in system_metrics + if args.metric in entry + ] + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "metric": args.metric, + "values": filtered_metrics, + } + ) + ) + else: + print(format_system_metrics(filtered_metrics)) + else: + system_metrics = SQLiteStorage.get_system_logs( + args.project, args.run + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "system_metrics": system_metrics, + } + ) + ) + else: + print(format_system_metrics(system_metrics)) + elif args.get_type == "alerts": + if remote: + alerts = remote.predict( + args.project, + args.run, + args.level, + args.since, + api_name="/get_alerts", + ) + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + alerts = SQLiteStorage.get_alerts( + args.project, + run_name=args.run, + level=args.level, + since=args.since, + ) + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "level": args.level, + "since": args.since, + "alerts": alerts, + } + ) + ) + else: + print(format_alerts(alerts)) + elif args.get_type == "report": + if remote: + logs = remote.predict(args.project, args.run, api_name="/get_logs") + else: + db_path = SQLiteStorage.get_project_db_path(args.project) + if not db_path.exists(): + error_exit(f"Project '{args.project}' not found.") + runs = SQLiteStorage.get_runs(args.project) + if args.run not in runs: + error_exit( + f"Run '{args.run}' not found in project '{args.project}'." + ) + logs = SQLiteStorage.get_logs(args.project, args.run) + + reports = _extract_reports(args.run, logs, report_name=args.report) + if not reports: + error_exit( + f"Report '{args.report}' not found in run '{args.run}' of project '{args.project}'." + ) + + if args.json: + print( + format_json( + { + "project": args.project, + "run": args.run, + "report": args.report, + "values": reports, + } + ) + ) + else: + output = [] + for idx, entry in enumerate(reports, start=1): + output.append( + f"Entry {idx} | step={entry['step']} | timestamp={entry['timestamp']}" + ) + output.append(entry["content"]) + if idx < len(reports): + output.append("-" * 80) + print("\n".join(output)) + elif args.command == "skills": + if args.skills_action == "add": + _handle_skills_add(args) + else: + parser.print_help() + + +def _handle_skills_add(args): + import shutil + from pathlib import Path + + try: + from huggingface_hub.cli.skills import ( + CENTRAL_GLOBAL, + CENTRAL_LOCAL, + GLOBAL_TARGETS, + LOCAL_TARGETS, + ) + except (ImportError, ModuleNotFoundError): + error_exit( + "The 'trackio skills' command requires huggingface_hub >= 1.4.0.\n" + "Please upgrade: pip install --upgrade huggingface_hub" + ) + + SKILL_ID = "trackio" + GITHUB_RAW = "https://raw.githubusercontent.com/gradio-app/trackio/main" + SKILL_PREFIX = ".agents/skills/trackio" + SKILL_FILES = [ + "SKILL.md", + "alerts.md", + "logging_metrics.md", + "retrieving_metrics.md", + ] + + if not (args.cursor or args.claude or args.codex or args.opencode or args.dest): + error_exit( + "Pick a destination via --cursor, --claude, --codex, --opencode, or --dest." + ) + + def download(url: str) -> str: + from huggingface_hub.utils import get_session + + try: + response = get_session().get(url) + response.raise_for_status() + except Exception as e: + error_exit( + f"Failed to download {url}\n{e}\n\n" + "Make sure you have internet access. The skill files are fetched from " + "the Trackio GitHub repository." + ) + return response.text + + def remove_existing(path: Path, force: bool): + if not (path.exists() or path.is_symlink()): + return + if not force: + error_exit( + f"Skill already exists at {path}.\nRe-run with --force to overwrite." + ) + if path.is_dir() and not path.is_symlink(): + shutil.rmtree(path) + else: + path.unlink() + + def install_to(skills_dir: Path, force: bool) -> Path: + skills_dir = skills_dir.expanduser().resolve() + skills_dir.mkdir(parents=True, exist_ok=True) + dest = skills_dir / SKILL_ID + remove_existing(dest, force) + dest.mkdir() + for fname in SKILL_FILES: + content = download(f"{GITHUB_RAW}/{SKILL_PREFIX}/{fname}") + (dest / fname).write_text(content, encoding="utf-8") + return dest + + def create_symlink( + agent_skills_dir: Path, central_skill_path: Path, force: bool + ) -> Path: + agent_skills_dir = agent_skills_dir.expanduser().resolve() + agent_skills_dir.mkdir(parents=True, exist_ok=True) + link_path = agent_skills_dir / SKILL_ID + remove_existing(link_path, force) + link_path.symlink_to(os.path.relpath(central_skill_path, agent_skills_dir)) + return link_path + + global_targets = {**GLOBAL_TARGETS, "cursor": Path("~/.cursor/skills")} + local_targets = {**LOCAL_TARGETS, "cursor": Path(".cursor/skills")} + targets_dict = global_targets if args.global_ else local_targets + + if args.dest: + if args.cursor or args.claude or args.codex or args.opencode or args.global_: + error_exit("--dest cannot be combined with agent flags or --global.") + skill_dest = install_to(Path(args.dest), args.force) + print(f"Installed '{SKILL_ID}' to {skill_dest}") + return + + agent_targets = [] + if args.cursor: + agent_targets.append(targets_dict["cursor"]) + if args.claude: + agent_targets.append(targets_dict["claude"]) + if args.codex: + agent_targets.append(targets_dict["codex"]) + if args.opencode: + agent_targets.append(targets_dict["opencode"]) + + central_path = CENTRAL_GLOBAL if args.global_ else CENTRAL_LOCAL + central_skill_path = install_to(central_path, args.force) + print(f"Installed '{SKILL_ID}' to central location: {central_skill_path}") + + for agent_target in agent_targets: + link_path = create_symlink(agent_target, central_skill_path, args.force) + print(f"Created symlink: {link_path}") + + +if __name__ == "__main__": + main() diff --git a/trackio/cli_helpers.py b/trackio/cli_helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..55967a365096a0463e8c2d6b4fc21ba6679c5932 --- /dev/null +++ b/trackio/cli_helpers.py @@ -0,0 +1,158 @@ +import json +import sys +from typing import Any + + +def format_json(data: Any) -> str: + """Format data as JSON.""" + return json.dumps(data, indent=2) + + +def format_list(items: list[str], title: str | None = None) -> str: + """Format a list of items in human-readable format.""" + if not items: + return f"No {title.lower() if title else 'items'} found." + + output = [] + if title: + output.append(f"{title}:") + + for item in items: + output.append(f" - {item}") + + return "\n".join(output) + + +def format_project_summary(summary: dict) -> str: + """Format project summary in human-readable format.""" + output = [f"Project: {summary['project']}"] + output.append(f"Number of runs: {summary['num_runs']}") + + if summary["runs"]: + output.append("\nRuns:") + for run in summary["runs"]: + output.append(f" - {run}") + else: + output.append("\nNo runs found.") + + if summary.get("last_activity"): + output.append(f"\nLast activity (max step): {summary['last_activity']}") + + return "\n".join(output) + + +def format_run_summary(summary: dict) -> str: + """Format run summary in human-readable format.""" + output = [f"Project: {summary['project']}"] + output.append(f"Run: {summary['run']}") + output.append(f"Number of logs: {summary['num_logs']}") + + if summary.get("last_step") is not None: + output.append(f"Last step: {summary['last_step']}") + + if summary.get("metrics"): + output.append("\nMetrics:") + for metric in summary["metrics"]: + output.append(f" - {metric}") + else: + output.append("\nNo metrics found.") + + config = summary.get("config") + if config: + output.append("\nConfig:") + config_display = {k: v for k, v in config.items() if not k.startswith("_")} + if config_display: + for key, value in config_display.items(): + output.append(f" {key}: {value}") + else: + output.append(" (no config)") + else: + output.append("\nConfig: (no config)") + + return "\n".join(output) + + +def format_metric_values(values: list[dict]) -> str: + """Format metric values in human-readable format.""" + if not values: + return "No metric values found." + + output = [f"Found {len(values)} value(s):\n"] + output.append("Step | Timestamp | Value") + output.append("-" * 50) + + for value in values: + step = value.get("step", "N/A") + timestamp = value.get("timestamp", "N/A") + val = value.get("value", "N/A") + output.append(f"{step} | {timestamp} | {val}") + + return "\n".join(output) + + +def format_system_metrics(metrics: list[dict]) -> str: + """Format system metrics in human-readable format.""" + if not metrics: + return "No system metrics found." + + output = [f"Found {len(metrics)} system metric entry/entries:\n"] + + for i, entry in enumerate(metrics): + timestamp = entry.get("timestamp", "N/A") + output.append(f"\nEntry {i + 1} (Timestamp: {timestamp}):") + for key, value in entry.items(): + if key != "timestamp": + output.append(f" {key}: {value}") + + return "\n".join(output) + + +def format_system_metric_names(names: list[str]) -> str: + """Format system metric names in human-readable format.""" + return format_list(names, "System Metrics") + + +def format_snapshot(snapshot: dict[str, list[dict]]) -> str: + """Format a metrics snapshot in human-readable format.""" + if not snapshot: + return "No metrics found in the specified range." + + output = [] + for metric_name, values in sorted(snapshot.items()): + output.append(f"\n{metric_name}:") + output.append(" Step | Timestamp | Value") + output.append(" " + "-" * 48) + for v in values: + step = v.get("step", "N/A") + ts = v.get("timestamp", "N/A") + val = v.get("value", "N/A") + output.append(f" {step} | {ts} | {val}") + + return "\n".join(output) + + +def format_alerts(alerts: list[dict]) -> str: + """Format alerts in human-readable format.""" + if not alerts: + return "No alerts found." + + output = [f"Found {len(alerts)} alert(s):\n"] + output.append("Timestamp | Run | Level | Title | Text | Step") + output.append("-" * 80) + + for a in alerts: + ts = a.get("timestamp", "N/A") + run = a.get("run", "N/A") + level = a.get("level", "N/A").upper() + title = a.get("title", "") + text = a.get("text", "") or "" + step = a.get("step", "N/A") + output.append(f"{ts} | {run} | {level} | {title} | {text} | {step}") + + return "\n".join(output) + + +def error_exit(message: str, code: int = 1) -> None: + """Print error message and exit.""" + print(f"Error: {message}", file=sys.stderr) + sys.exit(code) diff --git a/trackio/commit_scheduler.py b/trackio/commit_scheduler.py new file mode 100644 index 0000000000000000000000000000000000000000..2e1cbabc2f9e576def2332cd4fbdc5788828ace6 --- /dev/null +++ b/trackio/commit_scheduler.py @@ -0,0 +1,310 @@ +# Originally copied from https://github.com/huggingface/huggingface_hub/blob/d0a948fc2a32ed6e557042a95ef3e4af97ec4a7c/src/huggingface_hub/_commit_scheduler.py + +import atexit +import logging +import time +from concurrent.futures import Future +from dataclasses import dataclass +from pathlib import Path +from threading import Lock, Thread +from typing import Callable, Dict, List, Union + +from huggingface_hub.hf_api import ( + DEFAULT_IGNORE_PATTERNS, + CommitInfo, + CommitOperationAdd, + HfApi, +) +from huggingface_hub.utils import filter_repo_objects + +logger = logging.getLogger(__name__) + + +@dataclass(frozen=True) +class _FileToUpload: + """Temporary dataclass to store info about files to upload. Not meant to be used directly.""" + + local_path: Path + path_in_repo: str + size_limit: int + last_modified: float + + +class CommitScheduler: + """ + Scheduler to upload a local folder to the Hub at regular intervals (e.g. push to hub every 5 minutes). + + The recommended way to use the scheduler is to use it as a context manager. This ensures that the scheduler is + properly stopped and the last commit is triggered when the script ends. The scheduler can also be stopped manually + with the `stop` method. Checkout the [upload guide](https://huggingface.co/docs/huggingface_hub/guides/upload#scheduled-uploads) + to learn more about how to use it. + + Args: + repo_id (`str`): + The id of the repo to commit to. + folder_path (`str` or `Path`): + Path to the local folder to upload regularly. + every (`int` or `float`, *optional*): + The number of minutes between each commit. Defaults to 5 minutes. + path_in_repo (`str`, *optional*): + Relative path of the directory in the repo, for example: `"checkpoints/"`. Defaults to the root folder + of the repository. + repo_type (`str`, *optional*): + The type of the repo to commit to. Defaults to `model`. + revision (`str`, *optional*): + The revision of the repo to commit to. Defaults to `main`. + private (`bool`, *optional*): + Whether to make the repo private. If `None` (default), the repo will be public unless the organization's default is private. This value is ignored if the repo already exists. + token (`str`, *optional*): + The token to use to commit to the repo. Defaults to the token saved on the machine. + allow_patterns (`List[str]` or `str`, *optional*): + If provided, only files matching at least one pattern are uploaded. + ignore_patterns (`List[str]` or `str`, *optional*): + If provided, files matching any of the patterns are not uploaded. + squash_history (`bool`, *optional*): + Whether to squash the history of the repo after each commit. Defaults to `False`. Squashing commits is + useful to avoid degraded performances on the repo when it grows too large. + hf_api (`HfApi`, *optional*): + The [`HfApi`] client to use to commit to the Hub. Can be set with custom settings (user agent, token,...). + on_before_commit (`Callable[[], None]`, *optional*): + If specified, a function that will be called before the CommitScheduler lists files to create a commit. + + Example: + ```py + >>> from pathlib import Path + >>> from huggingface_hub import CommitScheduler + + # Scheduler uploads every 10 minutes + >>> csv_path = Path("watched_folder/data.csv") + >>> CommitScheduler(repo_id="test_scheduler", repo_type="dataset", folder_path=csv_path.parent, every=10) + + >>> with csv_path.open("a") as f: + ... f.write("first line") + + # Some time later (...) + >>> with csv_path.open("a") as f: + ... f.write("second line") + ``` + + Example using a context manager: + ```py + >>> from pathlib import Path + >>> from huggingface_hub import CommitScheduler + + >>> with CommitScheduler(repo_id="test_scheduler", repo_type="dataset", folder_path="watched_folder", every=10) as scheduler: + ... csv_path = Path("watched_folder/data.csv") + ... with csv_path.open("a") as f: + ... f.write("first line") + ... (...) + ... with csv_path.open("a") as f: + ... f.write("second line") + + # Scheduler is now stopped and last commit have been triggered + ``` + """ + + def __init__( + self, + *, + repo_id: str, + folder_path: Union[str, Path], + every: Union[int, float] = 5, + path_in_repo: str | None = None, + repo_type: str | None = None, + revision: str | None = None, + private: bool | None = None, + token: str | None = None, + allow_patterns: list[str] | str | None = None, + ignore_patterns: list[str] | str | None = None, + squash_history: bool = False, + hf_api: HfApi | None = None, + on_before_commit: Callable[[], None] | None = None, + ) -> None: + self.api = hf_api or HfApi(token=token) + self.on_before_commit = on_before_commit + + # Folder + self.folder_path = Path(folder_path).expanduser().resolve() + self.path_in_repo = path_in_repo or "" + self.allow_patterns = allow_patterns + + if ignore_patterns is None: + ignore_patterns = [] + elif isinstance(ignore_patterns, str): + ignore_patterns = [ignore_patterns] + self.ignore_patterns = ignore_patterns + DEFAULT_IGNORE_PATTERNS + + if self.folder_path.is_file(): + raise ValueError( + f"'folder_path' must be a directory, not a file: '{self.folder_path}'." + ) + self.folder_path.mkdir(parents=True, exist_ok=True) + + # Repository + repo_url = self.api.create_repo( + repo_id=repo_id, private=private, repo_type=repo_type, exist_ok=True + ) + self.repo_id = repo_url.repo_id + self.repo_type = repo_type + self.revision = revision + self.token = token + + self.last_uploaded: Dict[Path, float] = {} + self.last_push_time: float | None = None + + if not every > 0: + raise ValueError(f"'every' must be a positive integer, not '{every}'.") + self.lock = Lock() + self.every = every + self.squash_history = squash_history + + logger.info( + f"Scheduled job to push '{self.folder_path}' to '{self.repo_id}' every {self.every} minutes." + ) + self._scheduler_thread = Thread(target=self._run_scheduler, daemon=True) + self._scheduler_thread.start() + atexit.register(self._push_to_hub) + + self.__stopped = False + + def stop(self) -> None: + """Stop the scheduler. + + A stopped scheduler cannot be restarted. Mostly for tests purposes. + """ + self.__stopped = True + + def __enter__(self) -> "CommitScheduler": + return self + + def __exit__(self, exc_type, exc_value, traceback) -> None: + # Upload last changes before exiting + self.trigger().result() + self.stop() + return + + def _run_scheduler(self) -> None: + """Dumb thread waiting between each scheduled push to Hub.""" + while True: + self.last_future = self.trigger() + time.sleep(self.every * 60) + if self.__stopped: + break + + def trigger(self) -> Future: + """Trigger a `push_to_hub` and return a future. + + This method is automatically called every `every` minutes. You can also call it manually to trigger a commit + immediately, without waiting for the next scheduled commit. + """ + return self.api.run_as_future(self._push_to_hub) + + def _push_to_hub(self) -> CommitInfo | None: + if self.__stopped: # If stopped, already scheduled commits are ignored + return None + + logger.info("(Background) scheduled commit triggered.") + try: + value = self.push_to_hub() + if self.squash_history: + logger.info("(Background) squashing repo history.") + self.api.super_squash_history( + repo_id=self.repo_id, repo_type=self.repo_type, branch=self.revision + ) + return value + except Exception as e: + logger.error( + f"Error while pushing to Hub: {e}" + ) # Depending on the setup, error might be silenced + raise + + def push_to_hub(self) -> CommitInfo | None: + """ + Push folder to the Hub and return the commit info. + + + + This method is not meant to be called directly. It is run in the background by the scheduler, respecting a + queue mechanism to avoid concurrent commits. Making a direct call to the method might lead to concurrency + issues. + + + + The default behavior of `push_to_hub` is to assume an append-only folder. It lists all files in the folder and + uploads only changed files. If no changes are found, the method returns without committing anything. If you want + to change this behavior, you can inherit from [`CommitScheduler`] and override this method. This can be useful + for example to compress data together in a single file before committing. For more details and examples, check + out our [integration guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/upload#scheduled-uploads). + """ + # Check files to upload (with lock) + with self.lock: + if self.on_before_commit is not None: + self.on_before_commit() + + logger.debug("Listing files to upload for scheduled commit.") + + # List files from folder (taken from `_prepare_upload_folder_additions`) + relpath_to_abspath = { + path.relative_to(self.folder_path).as_posix(): path + for path in sorted( + self.folder_path.glob("**/*") + ) # sorted to be deterministic + if path.is_file() + } + prefix = f"{self.path_in_repo.strip('/')}/" if self.path_in_repo else "" + + # Filter with pattern + filter out unchanged files + retrieve current file size + files_to_upload: List[_FileToUpload] = [] + for relpath in filter_repo_objects( + relpath_to_abspath.keys(), + allow_patterns=self.allow_patterns, + ignore_patterns=self.ignore_patterns, + ): + local_path = relpath_to_abspath[relpath] + stat = local_path.stat() + if ( + self.last_uploaded.get(local_path) is None + or self.last_uploaded[local_path] != stat.st_mtime + ): + files_to_upload.append( + _FileToUpload( + local_path=local_path, + path_in_repo=prefix + relpath, + size_limit=stat.st_size, + last_modified=stat.st_mtime, + ) + ) + + # Return if nothing to upload + if len(files_to_upload) == 0: + logger.debug("Dropping schedule commit: no changed file to upload.") + return None + + # Convert `_FileToUpload` as `CommitOperationAdd` (=> compute file shas + limit to file size) + logger.debug("Removing unchanged files since previous scheduled commit.") + add_operations = [ + CommitOperationAdd( + # TODO: Cap the file to its current size, even if the user append data to it while a scheduled commit is happening + # (requires an upstream fix for XET-535: `hf_xet` should support `BinaryIO` for upload) + path_or_fileobj=file_to_upload.local_path, + path_in_repo=file_to_upload.path_in_repo, + ) + for file_to_upload in files_to_upload + ] + + # Upload files (append mode expected - no need for lock) + logger.debug("Uploading files for scheduled commit.") + commit_info = self.api.create_commit( + repo_id=self.repo_id, + repo_type=self.repo_type, + operations=add_operations, + commit_message="Scheduled Commit", + revision=self.revision, + ) + + for file in files_to_upload: + self.last_uploaded[file.local_path] = file.last_modified + + self.last_push_time = time.time() + + return commit_info diff --git a/trackio/context_vars.py b/trackio/context_vars.py new file mode 100644 index 0000000000000000000000000000000000000000..5390161add6e88d83071880d181a76c3ba9d52c0 --- /dev/null +++ b/trackio/context_vars.py @@ -0,0 +1,18 @@ +import contextvars +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from trackio.run import Run + +current_run: contextvars.ContextVar["Run | None"] = contextvars.ContextVar( + "current_run", default=None +) +current_project: contextvars.ContextVar[str | None] = contextvars.ContextVar( + "current_project", default=None +) +current_server: contextvars.ContextVar[str | None] = contextvars.ContextVar( + "current_server", default=None +) +current_space_id: contextvars.ContextVar[str | None] = contextvars.ContextVar( + "current_space_id", default=None +) diff --git a/trackio/deploy.py b/trackio/deploy.py new file mode 100644 index 0000000000000000000000000000000000000000..6afd797583297da1055e06272d218757dd042ce0 --- /dev/null +++ b/trackio/deploy.py @@ -0,0 +1,938 @@ +import importlib.metadata +import io +import json as json_mod +import os +import shutil +import sys +import tempfile +import threading +import time +from importlib.resources import files +from pathlib import Path + +if sys.version_info >= (3, 11): + import tomllib +else: + import tomli as tomllib + +import httpx +import huggingface_hub +from gradio_client import Client, handle_file +from httpx import ReadTimeout +from huggingface_hub import Volume +from huggingface_hub.errors import HfHubHTTPError, RepositoryNotFoundError + +import trackio +from trackio.bucket_storage import ( + create_bucket_if_not_exists, + export_from_bucket_for_static, + upload_project_to_bucket, + upload_project_to_bucket_for_static, +) +from trackio.sqlite_storage import SQLiteStorage +from trackio.utils import ( + MEDIA_DIR, + get_or_create_project_hash, + preprocess_space_and_dataset_ids, +) + +SPACE_HOST_URL = "https://{user_name}-{space_name}.hf.space/" +SPACE_URL = "https://huggingface.co/spaces/{space_id}" +_BOLD_ORANGE = "\033[1m\033[38;5;208m" +_RESET = "\033[0m" + + +def raise_if_space_is_frozen_for_logging(space_id: str) -> None: + try: + info = huggingface_hub.HfApi().space_info(space_id) + except RepositoryNotFoundError: + return + if getattr(info, "sdk", None) == "static": + raise RuntimeError( + f"Cannot log to Hugging Face Space '{space_id}' because it has been frozen " + f"(it uses the static SDK: a read-only dashboard with no live Trackio server).\n\n" + f"Use a different space_id for training, or create a new Gradio Trackio Space. " + f"Freezing converts a live Gradio Space to static after a run; a frozen Space " + f'cannot accept new logs. See trackio.sync(..., sdk="static") in the Trackio docs.' + ) + + +def _readme_linked_hub_yaml(dataset_id: str | None) -> str: + if dataset_id is not None: + return f"datasets:\n - {dataset_id}\n" + return "" + + +_SPACE_APP_PY = "import trackio\ntrackio.show()\n" + + +def _retry_hf_write(op_name: str, fn, retries: int = 4, initial_delay: float = 1.5): + delay = initial_delay + for attempt in range(1, retries + 1): + try: + return fn() + except ReadTimeout: + if attempt == retries: + raise + print( + f"* {op_name} timed out (attempt {attempt}/{retries}). Retrying in {delay:.1f}s..." + ) + time.sleep(delay) + delay = min(delay * 2, 12) + except HfHubHTTPError as e: + status = e.response.status_code if e.response is not None else None + if status is None or status < 500 or attempt == retries: + raise + print( + f"* {op_name} failed with HTTP {status} (attempt {attempt}/{retries}). Retrying in {delay:.1f}s..." + ) + time.sleep(delay) + delay = min(delay * 2, 12) + + +def _get_space_volumes(space_id: str) -> list[Volume]: + """ + Return mounted volumes for a Space. + + `HfApi.get_space_runtime()` does not always populate `volumes`, even when the + mount exists. Fall back to `space_info().runtime.volumes`, which currently + carries the volume metadata for running Spaces. + """ + hf_api = huggingface_hub.HfApi() + runtime = hf_api.get_space_runtime(space_id) + if runtime.volumes: + return list(runtime.volumes) + + info = hf_api.space_info(space_id) + if info.runtime and info.runtime.volumes: + return list(info.runtime.volumes) + + return [] + + +def _get_source_install_dependencies() -> str: + """Get trackio dependencies from pyproject.toml for source installs.""" + trackio_path = files("trackio") + pyproject_path = Path(trackio_path).parent / "pyproject.toml" + with open(pyproject_path, "rb") as f: + pyproject = tomllib.load(f) + deps = pyproject["project"]["dependencies"] + spaces_deps = ( + pyproject["project"].get("optional-dependencies", {}).get("spaces", []) + ) + return "\n".join(deps + spaces_deps) + + +def _is_trackio_installed_from_source() -> bool: + """Check if trackio is installed from source/editable install vs PyPI.""" + try: + trackio_file = trackio.__file__ + if "site-packages" not in trackio_file and "dist-packages" not in trackio_file: + return True + + dist = importlib.metadata.distribution("trackio") + if dist.files: + files = list(dist.files) + has_pth = any(".pth" in str(f) for f in files) + if has_pth: + return True + + return False + except ( + AttributeError, + importlib.metadata.PackageNotFoundError, + importlib.metadata.MetadataError, + ValueError, + TypeError, + ): + return True + + +def deploy_as_space( + space_id: str, + space_storage: huggingface_hub.SpaceStorage | None = None, + dataset_id: str | None = None, + bucket_id: str | None = None, + private: bool | None = None, +): + if ( + os.getenv("SYSTEM") == "spaces" + ): # in case a repo with this function is uploaded to spaces + return + + if dataset_id is not None and bucket_id is not None: + raise ValueError( + "Cannot use bucket volume options together with dataset_id; use one persistence mode." + ) + + trackio_path = files("trackio") + + hf_api = huggingface_hub.HfApi() + + try: + huggingface_hub.create_repo( + space_id, + private=private, + space_sdk="gradio", + space_storage=space_storage, + repo_type="space", + exist_ok=True, + ) + except HfHubHTTPError as e: + if e.response.status_code in [401, 403]: # unauthorized or forbidden + print("Need 'write' access token to create a Spaces repo.") + huggingface_hub.login(add_to_git_credential=False) + huggingface_hub.create_repo( + space_id, + private=private, + space_sdk="gradio", + space_storage=space_storage, + repo_type="space", + exist_ok=True, + ) + else: + raise ValueError(f"Failed to create Space: {e}") + + # We can assume pandas and huggingface-hub are available; requirements.txt pins trackio. + # Make sure necessary dependencies are installed by creating a requirements.txt. + is_source_install = _is_trackio_installed_from_source() + + if bucket_id is not None: + create_bucket_if_not_exists(bucket_id, private=private) + + with open(Path(trackio_path, "README.md"), "r") as f: + readme_content = f.read() + readme_content = readme_content.replace("{GRADIO_VERSION}", trackio.__version__) + readme_content = readme_content.replace("{APP_FILE}", "app.py") + readme_content = readme_content.replace( + "{LINKED_HUB_METADATA}", _readme_linked_hub_yaml(dataset_id) + ) + readme_buffer = io.BytesIO(readme_content.encode("utf-8")) + hf_api.upload_file( + path_or_fileobj=readme_buffer, + path_in_repo="README.md", + repo_id=space_id, + repo_type="space", + ) + + if is_source_install: + requirements_content = _get_source_install_dependencies() + else: + requirements_content = f"trackio[spaces]=={trackio.__version__}" + + requirements_buffer = io.BytesIO(requirements_content.encode("utf-8")) + hf_api.upload_file( + path_or_fileobj=requirements_buffer, + path_in_repo="requirements.txt", + repo_id=space_id, + repo_type="space", + ) + + huggingface_hub.utils.disable_progress_bars() + + if is_source_install: + dist_index = ( + Path(trackio.__file__).resolve().parent / "frontend" / "dist" / "index.html" + ) + if not dist_index.is_file(): + raise ValueError( + "The Trackio frontend build is missing. From the repository root run " + "`cd trackio/frontend && npm ci && npm run build`, then deploy again." + ) + hf_api.upload_folder( + repo_id=space_id, + repo_type="space", + folder_path=trackio_path, + path_in_repo="trackio", + ignore_patterns=[ + "README.md", + "frontend/node_modules/**", + "frontend/src/**", + "frontend/.gitignore", + "frontend/package.json", + "frontend/package-lock.json", + "frontend/vite.config.js", + "frontend/svelte.config.js", + "**/__pycache__/**", + "*.pyc", + ], + ) + + app_file_content = _SPACE_APP_PY + app_file_buffer = io.BytesIO(app_file_content.encode("utf-8")) + hf_api.upload_file( + path_or_fileobj=app_file_buffer, + path_in_repo="app.py", + repo_id=space_id, + repo_type="space", + ) + + if hf_token := huggingface_hub.utils.get_token(): + huggingface_hub.add_space_secret(space_id, "HF_TOKEN", hf_token) + if bucket_id is not None: + existing = _get_space_volumes(space_id) + already_mounted = any( + v.type == "bucket" and v.source == bucket_id and v.mount_path == "/data" + for v in existing + ) + if not already_mounted: + non_bucket = [ + v + for v in existing + if not (v.type == "bucket" and v.source == bucket_id) + ] + hf_api.set_space_volumes( + space_id, + non_bucket + + [Volume(type="bucket", source=bucket_id, mount_path="/data")], + ) + print(f"* Attached bucket {bucket_id} at '/data'") + huggingface_hub.add_space_variable(space_id, "TRACKIO_DIR", "/data/trackio") + elif dataset_id is not None: + huggingface_hub.add_space_variable(space_id, "TRACKIO_DATASET_ID", dataset_id) + if logo_light_url := os.environ.get("TRACKIO_LOGO_LIGHT_URL"): + huggingface_hub.add_space_variable( + space_id, "TRACKIO_LOGO_LIGHT_URL", logo_light_url + ) + if logo_dark_url := os.environ.get("TRACKIO_LOGO_DARK_URL"): + huggingface_hub.add_space_variable( + space_id, "TRACKIO_LOGO_DARK_URL", logo_dark_url + ) + if plot_order := os.environ.get("TRACKIO_PLOT_ORDER"): + huggingface_hub.add_space_variable(space_id, "TRACKIO_PLOT_ORDER", plot_order) + if theme := os.environ.get("TRACKIO_THEME"): + huggingface_hub.add_space_variable(space_id, "TRACKIO_THEME", theme) + huggingface_hub.add_space_variable(space_id, "GRADIO_MCP_SERVER", "True") + + +def create_space_if_not_exists( + space_id: str, + space_storage: huggingface_hub.SpaceStorage | None = None, + dataset_id: str | None = None, + bucket_id: str | None = None, + private: bool | None = None, +) -> None: + """ + Creates a new Hugging Face Space if it does not exist. + + Args: + space_id (`str`): + The ID of the Space to create. + space_storage ([`~huggingface_hub.SpaceStorage`], *optional*): + Choice of persistent storage tier for the Space. + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + bucket_id (`str`, *optional*): + Full Hub bucket id (`namespace/name`) to attach via the Hub volumes API (platform mount). + Sets `TRACKIO_DIR` to the mount path. + private (`bool`, *optional*): + Whether to make the Space private. If `None` (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. + """ + if "/" not in space_id: + raise ValueError( + f"Invalid space ID: {space_id}. Must be in the format: username/reponame or orgname/reponame." + ) + if dataset_id is not None and "/" not in dataset_id: + raise ValueError( + f"Invalid dataset ID: {dataset_id}. Must be in the format: username/datasetname or orgname/datasetname." + ) + if bucket_id is not None and "/" not in bucket_id: + raise ValueError( + f"Invalid bucket ID: {bucket_id}. Must be in the format: username/bucketname or orgname/bucketname." + ) + try: + huggingface_hub.repo_info(space_id, repo_type="space") + print( + f"* Found existing space: {_BOLD_ORANGE}{SPACE_URL.format(space_id=space_id)}{_RESET}" + ) + return + except RepositoryNotFoundError: + pass + except HfHubHTTPError as e: + if e.response.status_code in [401, 403]: # unauthorized or forbidden + print("Need 'write' access token to create a Spaces repo.") + huggingface_hub.login(add_to_git_credential=False) + else: + raise ValueError(f"Failed to create Space: {e}") + + print( + f"* Creating new space: {_BOLD_ORANGE}{SPACE_URL.format(space_id=space_id)}{_RESET}" + ) + deploy_as_space( + space_id, + space_storage, + dataset_id, + bucket_id, + private, + ) + print("* Waiting for Space to be ready...") + _wait_until_space_running(space_id) + + +def _wait_until_space_running(space_id: str, timeout: int = 300) -> None: + hf_api = huggingface_hub.HfApi() + start = time.time() + delay = 2 + request_timeout = 45.0 + failure_stages = frozenset( + ("NO_APP_FILE", "CONFIG_ERROR", "BUILD_ERROR", "RUNTIME_ERROR") + ) + while time.time() - start < timeout: + try: + info = hf_api.space_info(space_id, timeout=request_timeout) + if info.runtime: + stage = str(info.runtime.stage) + if stage in failure_stages: + raise RuntimeError( + f"Space {space_id} entered terminal stage {stage}. " + "Fix README.md or app files; see build logs on the Hub." + ) + if stage == "RUNNING": + return + except RuntimeError: + raise + except (huggingface_hub.utils.HfHubHTTPError, httpx.RequestError): + pass + time.sleep(delay) + delay = min(delay * 1.5, 15) + raise TimeoutError( + f"Space {space_id} did not reach RUNNING within {timeout}s. " + "Check status and build logs on the Hub." + ) + + +def wait_until_space_exists( + space_id: str, +) -> None: + """ + Blocks the current thread until the Space exists. + + Args: + space_id (`str`): + The ID of the Space to wait for. + + Raises: + `TimeoutError`: If waiting for the Space takes longer than expected. + """ + hf_api = huggingface_hub.HfApi() + delay = 1 + for _ in range(30): + try: + hf_api.space_info(space_id) + return + except (huggingface_hub.utils.HfHubHTTPError, httpx.RequestError): + time.sleep(delay) + delay = min(delay * 2, 60) + raise TimeoutError("Waiting for space to exist took longer than expected") + + +def upload_db_to_space(project: str, space_id: str, force: bool = False) -> None: + """ + Uploads the database of a local Trackio project to a Hugging Face Space. + + This uses the Gradio Client to upload since we do not want to trigger a new build of + the Space, which would happen if we used `huggingface_hub.upload_file`. + + Args: + project (`str`): + The name of the project to upload. + space_id (`str`): + The ID of the Space to upload to. + force (`bool`, *optional*, defaults to `False`): + If `True`, overwrites the existing database without prompting. If `False`, + prompts for confirmation. + """ + db_path = SQLiteStorage.get_project_db_path(project) + client = Client(space_id, verbose=False, httpx_kwargs={"timeout": 90}) + + if not force: + try: + existing_projects = client.predict(api_name="/get_all_projects") + if project in existing_projects: + response = input( + f"Database for project '{project}' already exists on Space '{space_id}'. " + f"Overwrite it? (y/N): " + ) + if response.lower() not in ["y", "yes"]: + print("* Upload cancelled.") + return + except Exception as e: + print(f"* Warning: Could not check if project exists on Space: {e}") + print("* Proceeding with upload...") + + client.predict( + api_name="/upload_db_to_space", + project=project, + uploaded_db=handle_file(db_path), + hf_token=huggingface_hub.utils.get_token(), + ) + + +SYNC_BATCH_SIZE = 500 + + +def sync_incremental( + project: str, + space_id: str, + private: bool | None = None, + pending_only: bool = False, +) -> None: + """ + Syncs a local Trackio project to a Space via the bulk_log API endpoints + instead of uploading the entire DB file. Supports incremental sync. + + Args: + project: The name of the project to sync. + space_id: The HF Space ID to sync to. + private: Whether to make the Space private if creating. + pending_only: If True, only sync rows tagged with space_id (pending data). + """ + print( + f"* Syncing project '{project}' to: {SPACE_URL.format(space_id=space_id)} (please wait...)" + ) + create_space_if_not_exists(space_id, private=private) + wait_until_space_exists(space_id) + + client = Client(space_id, verbose=False, httpx_kwargs={"timeout": 90}) + hf_token = huggingface_hub.utils.get_token() + + if pending_only: + pending_logs = SQLiteStorage.get_pending_logs(project) + if pending_logs: + logs = pending_logs["logs"] + for i in range(0, len(logs), SYNC_BATCH_SIZE): + batch = logs[i : i + SYNC_BATCH_SIZE] + print( + f" Syncing metrics: {min(i + SYNC_BATCH_SIZE, len(logs))}/{len(logs)}..." + ) + client.predict(api_name="/bulk_log", logs=batch, hf_token=hf_token) + SQLiteStorage.clear_pending_logs(project, pending_logs["ids"]) + + pending_sys = SQLiteStorage.get_pending_system_logs(project) + if pending_sys: + logs = pending_sys["logs"] + for i in range(0, len(logs), SYNC_BATCH_SIZE): + batch = logs[i : i + SYNC_BATCH_SIZE] + print( + f" Syncing system metrics: {min(i + SYNC_BATCH_SIZE, len(logs))}/{len(logs)}..." + ) + client.predict( + api_name="/bulk_log_system", logs=batch, hf_token=hf_token + ) + SQLiteStorage.clear_pending_system_logs(project, pending_sys["ids"]) + + pending_uploads = SQLiteStorage.get_pending_uploads(project) + if pending_uploads: + upload_entries = [] + for u in pending_uploads["uploads"]: + fp = u["file_path"] + if os.path.exists(fp): + upload_entries.append( + { + "project": u["project"], + "run": u["run"], + "step": u["step"], + "relative_path": u["relative_path"], + "uploaded_file": handle_file(fp), + } + ) + if upload_entries: + print(f" Syncing {len(upload_entries)} media files...") + client.predict( + api_name="/bulk_upload_media", + uploads=upload_entries, + hf_token=hf_token, + ) + SQLiteStorage.clear_pending_uploads(project, pending_uploads["ids"]) + else: + all_logs = SQLiteStorage.get_all_logs_for_sync(project) + if all_logs: + for i in range(0, len(all_logs), SYNC_BATCH_SIZE): + batch = all_logs[i : i + SYNC_BATCH_SIZE] + print( + f" Syncing metrics: {min(i + SYNC_BATCH_SIZE, len(all_logs))}/{len(all_logs)}..." + ) + client.predict(api_name="/bulk_log", logs=batch, hf_token=hf_token) + + all_sys_logs = SQLiteStorage.get_all_system_logs_for_sync(project) + if all_sys_logs: + for i in range(0, len(all_sys_logs), SYNC_BATCH_SIZE): + batch = all_sys_logs[i : i + SYNC_BATCH_SIZE] + print( + f" Syncing system metrics: {min(i + SYNC_BATCH_SIZE, len(all_sys_logs))}/{len(all_sys_logs)}..." + ) + client.predict( + api_name="/bulk_log_system", logs=batch, hf_token=hf_token + ) + + SQLiteStorage.set_project_metadata(project, "space_id", space_id) + print( + f"* Synced successfully to space: {_BOLD_ORANGE}{SPACE_URL.format(space_id=space_id)}{_RESET}" + ) + + +def upload_dataset_for_static( + project: str, + dataset_id: str, + private: bool | None = None, +) -> None: + hf_api = huggingface_hub.HfApi() + + try: + huggingface_hub.create_repo( + dataset_id, + private=private, + repo_type="dataset", + exist_ok=True, + ) + except HfHubHTTPError as e: + if e.response.status_code in [401, 403]: + print("Need 'write' access token to create a Dataset repo.") + huggingface_hub.login(add_to_git_credential=False) + huggingface_hub.create_repo( + dataset_id, + private=private, + repo_type="dataset", + exist_ok=True, + ) + else: + raise ValueError(f"Failed to create Dataset: {e}") + + with tempfile.TemporaryDirectory() as tmp_dir: + output_dir = Path(tmp_dir) + SQLiteStorage.export_for_static_space(project, output_dir) + + media_dir = MEDIA_DIR / project + if media_dir.exists(): + dest = output_dir / "media" + shutil.copytree(media_dir, dest) + + _retry_hf_write( + "Dataset upload", + lambda: hf_api.upload_folder( + repo_id=dataset_id, + repo_type="dataset", + folder_path=str(output_dir), + ), + ) + + print(f"* Dataset uploaded: https://huggingface.co/datasets/{dataset_id}") + + +def deploy_as_static_space( + space_id: str, + dataset_id: str | None, + project: str, + bucket_id: str | None = None, + private: bool | None = None, + hf_token: str | None = None, +) -> None: + if os.getenv("SYSTEM") == "spaces": + return + + hf_api = huggingface_hub.HfApi() + + try: + huggingface_hub.create_repo( + space_id, + private=private, + space_sdk="static", + repo_type="space", + exist_ok=True, + ) + except HfHubHTTPError as e: + if e.response.status_code in [401, 403]: + print("Need 'write' access token to create a Spaces repo.") + huggingface_hub.login(add_to_git_credential=False) + huggingface_hub.create_repo( + space_id, + private=private, + space_sdk="static", + repo_type="space", + exist_ok=True, + ) + else: + raise ValueError(f"Failed to create Space: {e}") + + linked = _readme_linked_hub_yaml(dataset_id) + readme_content = ( + f"---\nsdk: static\npinned: false\ntags:\n - trackio\n{linked}---\n" + ) + _retry_hf_write( + "Static Space README upload", + lambda: hf_api.upload_file( + path_or_fileobj=io.BytesIO(readme_content.encode("utf-8")), + path_in_repo="README.md", + repo_id=space_id, + repo_type="space", + ), + ) + + trackio_path = files("trackio") + dist_dir = Path(trackio_path).parent / "trackio" / "frontend" / "dist" + if not dist_dir.is_dir(): + dist_dir = Path(trackio.__file__).resolve().parent / "frontend" / "dist" + if not dist_dir.is_dir(): + raise ValueError( + "The Trackio frontend build is missing. From the repository root run " + "`cd trackio/frontend && npm ci && npm run build`, then deploy again." + ) + + _retry_hf_write( + "Static Space frontend upload", + lambda: hf_api.upload_folder( + repo_id=space_id, + repo_type="space", + folder_path=str(dist_dir), + ), + ) + + config = { + "mode": "static", + "project": project, + "private": bool(private), + } + if bucket_id is not None: + config["bucket_id"] = bucket_id + if dataset_id is not None: + config["dataset_id"] = dataset_id + if hf_token and private: + config["hf_token"] = hf_token + + _retry_hf_write( + "Static Space config upload", + lambda: hf_api.upload_file( + path_or_fileobj=io.BytesIO(json_mod.dumps(config).encode("utf-8")), + path_in_repo="config.json", + repo_id=space_id, + repo_type="space", + ), + ) + + assets_dir = Path(trackio.__file__).resolve().parent / "assets" + if assets_dir.is_dir(): + _retry_hf_write( + "Static Space assets upload", + lambda: hf_api.upload_folder( + repo_id=space_id, + repo_type="space", + folder_path=str(assets_dir), + path_in_repo="assets", + ), + ) + + print( + f"* Static Space deployed: {_BOLD_ORANGE}{SPACE_URL.format(space_id=space_id)}{_RESET}" + ) + + +def sync( + project: str, + space_id: str | None = None, + private: bool | None = None, + force: bool = False, + run_in_background: bool = False, + sdk: str = "gradio", + dataset_id: str | None = None, + bucket_id: str | None = None, +) -> str: + """ + Syncs a local Trackio project's database to a Hugging Face Space. + If the Space does not exist, it will be created. Local data is never deleted. + + **Freezing:** Passing ``sdk="static"`` deploys a static Space backed by an HF Bucket + (read-only dashboard, no Gradio server). You can sync the same project again later to + refresh that static Space. If you want a one-time snapshot of an existing Gradio Space, + use ``freeze()`` instead. + + Args: + project (`str`): The name of the project to upload. + space_id (`str`, *optional*): The ID of the Space to upload to (e.g., `"username/space_id"`). + If not provided, checks project metadata first, then generates a random space_id. + private (`bool`, *optional*): + Whether to make the Space private. If None (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. + force (`bool`, *optional*, defaults to `False`): + If `True`, overwrite the existing database without prompting for confirmation. + If `False`, prompt the user before overwriting an existing database. + run_in_background (`bool`, *optional*, defaults to `False`): + If `True`, the Space creation and database upload will be run in a background thread. + If `False`, all the steps will be run synchronously. + sdk (`str`, *optional*, defaults to `"gradio"`): + The type of Space to deploy. `"gradio"` deploys a Gradio Space with a live + server. `"static"` freezes the Space: deploys a static Space that reads from an HF Bucket + (no server needed). + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + bucket_id (`str`, *optional*): + The ID of the HF Bucket to sync to. By default, a bucket is auto-generated + from the space_id. + Returns: + `str`: The Space ID of the synced project. + """ + if sdk not in ("gradio", "static"): + raise ValueError(f"sdk must be 'gradio' or 'static', got '{sdk}'") + if space_id is None: + space_id = SQLiteStorage.get_space_id(project) + if space_id is None: + space_id = f"{project}-{get_or_create_project_hash(project)}" + space_id, dataset_id, bucket_id = preprocess_space_and_dataset_ids( + space_id, dataset_id, bucket_id + ) + + def _do_sync(): + try: + info = huggingface_hub.HfApi().space_info(space_id) + existing_sdk = info.sdk + if existing_sdk and existing_sdk != sdk: + raise ValueError( + f"Space '{space_id}' is a '{existing_sdk}' Space but sdk='{sdk}' was requested. " + f"The sdk must match the existing Space type." + ) + except RepositoryNotFoundError: + pass + + if sdk == "static": + if dataset_id is not None: + upload_dataset_for_static(project, dataset_id, private=private) + hf_token = huggingface_hub.utils.get_token() if private else None + deploy_as_static_space( + space_id, + dataset_id, + project, + private=private, + hf_token=hf_token, + ) + elif bucket_id is not None: + create_bucket_if_not_exists(bucket_id, private=private) + upload_project_to_bucket_for_static(project, bucket_id) + print( + f"* Project data uploaded to bucket: https://huggingface.co/buckets/{bucket_id}" + ) + deploy_as_static_space( + space_id, + None, + project, + bucket_id=bucket_id, + private=private, + hf_token=huggingface_hub.utils.get_token() if private else None, + ) + else: + if bucket_id is not None: + create_bucket_if_not_exists(bucket_id, private=private) + upload_project_to_bucket(project, bucket_id) + print( + f"* Project data uploaded to bucket: https://huggingface.co/buckets/{bucket_id}" + ) + create_space_if_not_exists( + space_id, bucket_id=bucket_id, private=private + ) + else: + sync_incremental(project, space_id, private=private, pending_only=False) + SQLiteStorage.set_project_metadata(project, "space_id", space_id) + + if run_in_background: + threading.Thread(target=_do_sync).start() + else: + _do_sync() + return space_id + + +def _get_source_bucket(space_id: str) -> str: + volumes = _get_space_volumes(space_id) + for v in volumes: + if v.type == "bucket" and v.mount_path == "/data": + return v.source + raise ValueError( + f"Space '{space_id}' has no bucket mounted at '/data'. " + f"freeze() requires the source Space to use bucket storage." + ) + + +def freeze( + space_id: str, + project: str, + new_space_id: str | None = None, + private: bool | None = None, + bucket_id: str | None = None, +) -> str: + """ + Creates a new static Hugging Face Space containing a read-only snapshot of + the data for the specified project from the source Gradio Space. The data is + read from the bucket attached to the source Space at freeze time. The original + Space is not modified, and the new static Space does not automatically reflect + metrics uploaded to the original Gradio Space after the freeze completes. + + Args: + space_id (`str`): + The ID of the source Gradio Space (e.g., `"username/my-space"` or a + short repo name with the logged-in namespace inferred, like `init()`). + Must be a Gradio Space with a bucket mounted at `/data`. + project (`str`): + The name of the project whose data to include in the frozen Space. + new_space_id (`str`, *optional*): + The ID for the new static Space. If not provided, defaults to + `"{space_id}_static"`. + private (`bool`, *optional*): + Whether to make the new Space private. If None (default), the repo + will be public unless the organization's default is private. + bucket_id (`str`, *optional*): + The ID of the HF Bucket for the new static Space's data storage. + If not provided, one is auto-generated from the new Space ID. + + Returns: + `str`: The Space ID of the newly created static Space. + """ + space_id, _, _ = preprocess_space_and_dataset_ids(space_id, None, None) + + try: + info = huggingface_hub.HfApi().space_info(space_id) + if info.sdk != "gradio": + raise ValueError( + f"Space '{space_id}' is not a Gradio Space (sdk='{info.sdk}'). " + f"freeze() requires a Gradio Space as the source." + ) + except RepositoryNotFoundError: + raise ValueError( + f"Space '{space_id}' not found. Provide an existing Gradio Space ID." + ) + + source_bucket_id = _get_source_bucket(space_id) + print(f"* Reading project data from bucket: {source_bucket_id}") + + if new_space_id is None: + new_space_id = f"{space_id}_static" + new_space_id, _dataset_id, bucket_id = preprocess_space_and_dataset_ids( + new_space_id, None, bucket_id + ) + + hf_api = huggingface_hub.HfApi() + try: + dest_info = hf_api.space_info(new_space_id) + tags = dest_info.tags or [] + if dest_info.sdk != "static" or "trackio" not in tags: + raise ValueError( + f"Space '{new_space_id}' already exists and is not a Trackio static Space " + f"(sdk='{dest_info.sdk}', tags={tags}). Choose a different new_space_id " + f"or delete the existing Space first." + ) + except RepositoryNotFoundError: + pass + + create_bucket_if_not_exists(bucket_id, private=private) + export_from_bucket_for_static(source_bucket_id, bucket_id, project) + print( + f"* Project data uploaded to bucket: https://huggingface.co/buckets/{bucket_id}" + ) + deploy_as_static_space( + new_space_id, + None, + project, + bucket_id=bucket_id, + private=private, + hf_token=huggingface_hub.utils.get_token() if private else None, + ) + return new_space_id diff --git a/trackio/dummy_commit_scheduler.py b/trackio/dummy_commit_scheduler.py new file mode 100644 index 0000000000000000000000000000000000000000..6068fe8a36b8647ade92dd300af0855f4338826f --- /dev/null +++ b/trackio/dummy_commit_scheduler.py @@ -0,0 +1,19 @@ +from concurrent.futures import Future + + +class DummyCommitSchedulerLock: + def __enter__(self): + return None + + def __exit__(self, exception_type, exception_value, exception_traceback): + pass + + +class DummyCommitScheduler: + def __init__(self): + self.lock = DummyCommitSchedulerLock() + + def trigger(self) -> Future: + fut: Future = Future() + fut.set_result(None) + return fut diff --git a/trackio/exceptions.py b/trackio/exceptions.py new file mode 100644 index 0000000000000000000000000000000000000000..189f56d718245b65790ff43e14005b846aad2402 --- /dev/null +++ b/trackio/exceptions.py @@ -0,0 +1,2 @@ +class TrackioAPIError(Exception): + pass diff --git a/trackio/frontend/dist/assets/index-Cs1UkfOV.css b/trackio/frontend/dist/assets/index-Cs1UkfOV.css new file mode 100644 index 0000000000000000000000000000000000000000..619e21e53d8ef44e4324557d126e4e3af9e5023d --- /dev/null +++ b/trackio/frontend/dist/assets/index-Cs1UkfOV.css @@ -0,0 +1 @@ +:root{--primary-50: #fff7ed;--primary-100: #ffedd5;--primary-200: #fed7aa;--primary-300: #fdba74;--primary-400: #fb923c;--primary-500: #f97316;--primary-600: #ea580c;--primary-700: #c2410c;--primary-800: #9a3412;--primary-900: #7c2d12;--primary-950: #6c2e12;--secondary-50: #eff6ff;--secondary-100: #dbeafe;--secondary-200: #bfdbfe;--secondary-300: #93c5fd;--secondary-400: #60a5fa;--secondary-500: #3b82f6;--secondary-600: #2563eb;--secondary-700: #1d4ed8;--secondary-800: #1e40af;--secondary-900: #1e3a8a;--secondary-950: #1d3660;--neutral-50: #f9fafb;--neutral-100: #f3f4f6;--neutral-200: #e5e7eb;--neutral-300: #d1d5db;--neutral-400: #9ca3af;--neutral-500: #6b7280;--neutral-600: #4b5563;--neutral-700: #374151;--neutral-800: #1f2937;--neutral-900: #111827;--neutral-950: #0b0f19;--size-0-5: 2px;--size-1: 4px;--size-2: 8px;--size-3: 12px;--size-4: 16px;--size-5: 20px;--size-6: 24px;--size-8: 32px;--size-14: 56px;--size-16: 64px;--size-28: 112px;--size-full: 100%;--spacing-xxs: 1px;--spacing-xs: 2px;--spacing-sm: 4px;--spacing-md: 6px;--spacing-lg: 8px;--spacing-xl: 10px;--spacing-xxl: 16px;--radius-xxs: 1px;--radius-xs: 2px;--radius-sm: 3px;--radius-md: 4px;--radius-lg: 5px;--radius-xl: 8px;--radius-xxl: 12px;--text-xxs: 9px;--text-xs: 10px;--text-sm: 12px;--text-md: 14px;--text-lg: 16px;--text-xl: 22px;--text-xxl: 26px;--line-sm: 1.4;--background-fill-primary: white;--background-fill-secondary: var(--neutral-50);--body-text-color: var(--neutral-900);--body-text-color-subdued: var(--neutral-600);--border-color-primary: var(--neutral-200);--color-accent: var(--primary-500);--color-accent-soft: var(--primary-50);--shadow-drop: rgba(0, 0, 0, .05) 0px 1px 2px 0px;--shadow-drop-lg: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--shadow-inset: rgba(0, 0, 0, .05) 0px 2px 4px 0px inset;--shadow-spread: 3px;--block-title-text-color: var(--neutral-500);--block-title-text-size: var(--text-md);--block-title-text-weight: 400;--block-info-text-color: var(--body-text-color-subdued);--block-info-text-size: var(--text-sm);--input-background-fill: white;--input-background-fill-focus: var(--primary-500);--input-border-color: var(--border-color-primary);--input-border-color-focus: var(--primary-300);--input-border-width: 1px;--input-padding: var(--spacing-xl);--input-placeholder-color: var(--neutral-400);--input-radius: var(--radius-lg);--input-shadow: 0 0 0 var(--shadow-spread) transparent, var(--shadow-inset);--input-shadow-focus: 0 0 0 var(--shadow-spread) var(--primary-50), var(--shadow-inset);--input-text-size: var(--text-md);--checkbox-background-color: var(--background-fill-primary);--checkbox-background-color-focus: var(--checkbox-background-color);--checkbox-background-color-hover: var(--checkbox-background-color);--checkbox-background-color-selected: var(--primary-600);--checkbox-border-color: var(--neutral-300);--checkbox-border-color-focus: var(--primary-500);--checkbox-border-color-hover: var(--neutral-300);--checkbox-border-color-selected: var(--primary-600);--checkbox-border-radius: var(--radius-sm);--checkbox-border-width: var(--input-border-width);--checkbox-label-gap: var(--spacing-lg);--checkbox-label-padding: var(--spacing-md) calc(2 * var(--spacing-md));--checkbox-label-text-size: var(--text-md);--checkbox-shadow: var(--input-shadow);--checkbox-check: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");--slider-color: var(--primary-500);--container-radius: var(--radius-lg);--layer-top: 9999}.navbar.svelte-d8j1hi{display:flex;align-items:stretch;border-bottom:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, white);padding:0;flex-shrink:0;min-height:44px}.nav-spacer.svelte-d8j1hi{flex:1}.nav-tabs.svelte-d8j1hi{display:flex;gap:0;padding-right:16px}.nav-link.svelte-d8j1hi{padding:10px 16px;border:none;background:none;color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-md, 14px);cursor:pointer;white-space:nowrap;border-bottom:2px solid transparent;transition:color .15s;font-weight:400}.nav-link.svelte-d8j1hi:hover{color:var(--body-text-color, #1f2937)}.nav-link.active.svelte-d8j1hi{color:var(--body-text-color, #1f2937);border-bottom-color:var(--body-text-color, #1f2937);font-weight:500}.checkbox-group.svelte-17gmtkf{display:flex;flex-direction:column}.checkbox-item.svelte-17gmtkf{display:flex;align-items:center;gap:8px;padding:3px 0;cursor:pointer;font-size:13px}.checkbox-item.svelte-17gmtkf input[type=checkbox]:where(.svelte-17gmtkf){-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;margin:0;border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);box-shadow:var(--checkbox-shadow);cursor:pointer;flex-shrink:0;transition:background-color .15s,border-color .15s}.checkbox-item.svelte-17gmtkf input[type=checkbox]:where(.svelte-17gmtkf):checked{background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected, #f97316);border-color:var(--checkbox-border-color-selected, #f97316)}.checkbox-item.svelte-17gmtkf input[type=checkbox]:where(.svelte-17gmtkf):hover{border-color:var(--checkbox-border-color-hover, #d1d5db)}.color-dot.svelte-17gmtkf{width:10px;height:10px;border-radius:50%;flex-shrink:0}.run-name.svelte-17gmtkf{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--body-text-color, #1f2937)}.dropdown-container.svelte-kgylqb{width:100%}.label.svelte-kgylqb{display:block;font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280);margin-bottom:6px}.info.svelte-kgylqb{display:block;font-size:12px;color:var(--body-text-color-subdued, #9ca3af);margin-bottom:4px}.wrap.svelte-kgylqb{position:relative;border-radius:var(--input-radius, 8px);background:var(--input-background-fill, white);border:1px solid var(--border-color-primary, #e5e7eb);transition:border-color .15s,box-shadow .15s}.wrap.focused.svelte-kgylqb{border-color:var(--input-border-color-focus, #fdba74);box-shadow:0 0 0 2px var(--primary-50, #fff7ed)}.wrap-inner.svelte-kgylqb{display:flex;position:relative;align-items:center;padding:0 10px}.secondary-wrap.svelte-kgylqb{display:flex;flex:1;align-items:center}input.svelte-kgylqb{margin:0;outline:none;border:none;background:inherit;width:100%;color:var(--body-text-color, #1f2937);font-size:13px;font-family:inherit;padding:7px 0}input.svelte-kgylqb::placeholder{color:var(--input-placeholder-color, #9ca3af)}input[readonly].svelte-kgylqb{cursor:pointer}.icon-wrap.svelte-kgylqb{color:var(--body-text-color-subdued, #9ca3af);width:16px;flex-shrink:0;pointer-events:none}.options.svelte-kgylqb{position:fixed;z-index:var(--layer-top, 9999);margin:0;padding:4px 0;box-shadow:0 4px 12px #0000001f;border-radius:var(--input-radius, 8px);border:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, white);min-width:fit-content;overflow:auto;color:var(--body-text-color, #1f2937);list-style:none}.item.svelte-kgylqb{display:flex;cursor:pointer;padding:6px 10px;font-size:13px;word-break:break-word}.item.svelte-kgylqb:hover,.item.active.svelte-kgylqb{background:var(--background-fill-secondary, #f9fafb)}.item.selected.svelte-kgylqb{font-weight:500}.check-mark.svelte-kgylqb{padding-right:6px;min-width:16px;font-size:12px}.check-mark.hide.svelte-kgylqb{visibility:hidden}.checkbox-container.svelte-oj84db{display:flex;align-items:center;gap:8px;cursor:pointer;margin:8px 0}.label-text.svelte-oj84db{color:var(--body-text-color, #1f2937);font-size:13px;line-height:1.4}input[type=checkbox].svelte-oj84db{--ring-color: transparent;position:relative;-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;box-shadow:var(--checkbox-shadow);border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);flex-shrink:0;cursor:pointer;transition:background-color .15s,border-color .15s}input[type=checkbox].svelte-oj84db:checked,input[type=checkbox].svelte-oj84db:checked:hover,input[type=checkbox].svelte-oj84db:checked:focus{background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected, #f97316);border-color:var(--checkbox-border-color-selected, #f97316)}input[type=checkbox].svelte-oj84db:hover{border-color:var(--checkbox-border-color-hover, #d1d5db);background-color:var(--checkbox-background-color-hover, white)}input[type=checkbox].svelte-oj84db:focus{border-color:var(--checkbox-border-color-focus, #f97316);background-color:var(--checkbox-background-color-focus, white);outline:none}.slider-wrap.svelte-wei6ev{display:flex;flex-direction:column;width:100%}.head.svelte-wei6ev{margin-bottom:4px;display:flex;justify-content:space-between;align-items:center;width:100%}.label.svelte-wei6ev{flex:1;font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280)}.info.svelte-wei6ev{display:block;font-size:12px;color:var(--body-text-color-subdued, #9ca3af);margin-bottom:4px}.slider-input-container.svelte-wei6ev{display:flex;align-items:center;gap:6px}input[type=range].svelte-wei6ev{-webkit-appearance:none;-moz-appearance:none;appearance:none;width:100%;cursor:pointer;outline:none;border-radius:var(--radius-xl, 12px);min-width:var(--size-28, 112px);background:transparent}input[type=range].svelte-wei6ev::-webkit-slider-runnable-track{height:6px;border-radius:var(--radius-xl, 12px);background:linear-gradient(to right,var(--slider-color, #f97316) var(--range_progress, 50%),var(--neutral-200, #e5e7eb) var(--range_progress, 50%))}input[type=range].svelte-wei6ev::-webkit-slider-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;height:16px;width:16px;background-color:var(--slider-color, #f97316);border:2px solid var(--background-fill-primary, white);border-radius:50%;margin-top:-5px;box-shadow:0 0 0 1px var(--border-color-primary, rgba(0, 0, 0, .08)),0 1px 3px #0003}input[type=range].svelte-wei6ev::-moz-range-track{height:6px;background:var(--neutral-200, #e5e7eb);border-radius:var(--radius-xl, 12px)}input[type=range].svelte-wei6ev::-moz-range-thumb{-webkit-appearance:none;-moz-appearance:none;appearance:none;height:16px;width:16px;background-color:var(--slider-color, #f97316);border:2px solid var(--background-fill-primary, white);border-radius:50%;box-shadow:0 0 0 1px var(--border-color-primary, rgba(0, 0, 0, .08)),0 1px 3px #0003}input[type=range].svelte-wei6ev::-moz-range-progress{height:6px;background-color:var(--slider-color, #f97316);border-radius:var(--radius-xl, 12px)}.bound.svelte-wei6ev{font-size:11px;color:var(--body-text-color-subdued, #9ca3af);min-width:12px;text-align:center}.textbox-container.svelte-6yncpg{width:100%}.label.svelte-6yncpg{display:block;font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280);margin-bottom:6px}.info.svelte-6yncpg{display:block;font-size:12px;color:var(--body-text-color-subdued, #9ca3af);margin-bottom:4px}.input-wrap.svelte-6yncpg{border-radius:var(--input-radius, 8px);background:var(--input-background-fill, white);border:1px solid var(--border-color-primary, #e5e7eb);transition:border-color .15s,box-shadow .15s}.input-wrap.svelte-6yncpg:focus-within{border-color:var(--input-border-color-focus, #fdba74);box-shadow:0 0 0 2px var(--primary-50, #fff7ed)}input.svelte-6yncpg{width:100%;padding:7px 10px;outline:none;border:none;background:transparent;color:var(--body-text-color, #1f2937);font-size:13px;font-family:inherit;border-radius:var(--input-radius, 8px)}input.svelte-6yncpg::placeholder{color:var(--input-placeholder-color, #9ca3af)}.sidebar.svelte-181dlmc{width:290px;min-width:290px;background:var(--background-fill-primary, white);border-right:1px solid var(--border-color-primary, #e5e7eb);display:flex;flex-direction:column;position:relative;overflow:hidden;transition:width .2s,min-width .2s}.sidebar.collapsed.svelte-181dlmc{width:40px;min-width:40px}.toggle-btn.svelte-181dlmc{position:absolute;top:12px;right:8px;z-index:10;border:none;background:none;color:var(--body-text-color-subdued, #9ca3af);cursor:pointer;padding:4px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm, 4px);transition:color .15s,background-color .15s}.toggle-btn.svelte-181dlmc:hover{color:var(--body-text-color, #1f2937);background-color:var(--background-fill-secondary, #f9fafb)}.sidebar-content.svelte-181dlmc{padding:16px;flex:1;min-height:0;display:flex;flex-direction:column}.sidebar-scroll.svelte-181dlmc{overflow-y:auto;flex:1;min-height:0}.oauth-footer.svelte-181dlmc{flex-shrink:0;margin-top:12px;padding-top:12px;border-top:1px solid var(--border-color-primary, #e5e7eb)}.readonly-footer.svelte-181dlmc{flex-shrink:0;margin-top:12px;padding-top:12px;border-top:1px solid var(--border-color-primary, #e5e7eb);display:flex;align-items:center;gap:8px;flex-wrap:wrap}.readonly-badge.svelte-181dlmc{display:inline-flex;align-items:center;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:999px;padding:2px 8px;font-size:10px;letter-spacing:.06em;font-weight:600;color:var(--body-text-color-subdued, #6b7280);background:var(--background-fill-secondary, #f9fafb)}.readonly-link.svelte-181dlmc{font-size:12px;color:var(--body-text-color-subdued, #6b7280);text-decoration:none;max-width:100%;overflow-wrap:anywhere}.readonly-link.svelte-181dlmc:hover{color:var(--body-text-color, #1f2937);text-decoration:underline}.oauth-line.svelte-181dlmc{margin:0;font-size:12px;line-height:1.4;color:var(--body-text-color-subdued, #6b7280)}.oauth-warn.svelte-181dlmc{color:var(--body-text-color, #92400e)}.hf-login-btn.svelte-181dlmc{display:inline-flex;align-items:center;justify-content:center;gap:8px;width:100%;padding:8px 12px;font-size:13px;font-weight:600;color:#fff;background:#141c2e;border-radius:var(--radius-lg, 8px);text-decoration:none;border:none;cursor:pointer;box-sizing:border-box}.hf-login-btn.svelte-181dlmc:hover{background:#283042}.hf-logo.svelte-181dlmc{width:20px;height:20px;flex-shrink:0}.oauth-hint.svelte-181dlmc{margin:8px 0 0;font-size:11px;line-height:1.35;color:var(--body-text-color-subdued, #9ca3af)}.oauth-signed-in.svelte-181dlmc{margin:0;font-size:12px;color:var(--body-text-color-subdued, #6b7280)}.oauth-logout.svelte-181dlmc{font-size:12px;color:var(--body-text-color-subdued, #9ca3af);text-decoration:none;cursor:pointer}.oauth-logout.svelte-181dlmc:hover{text-decoration:underline;color:var(--body-text-color, #1f2937)}.logo-section.svelte-181dlmc{margin-bottom:20px}.logo.svelte-181dlmc{width:80%;max-width:200px}.section.svelte-181dlmc{margin-bottom:18px}.section-label.svelte-181dlmc{font-size:13px;font-weight:500;color:var(--body-text-color-subdued, #6b7280)}.locked-project.svelte-181dlmc{margin-top:4px;font-size:13px;font-weight:500;color:var(--body-text-color, #1f2937);padding:8px 10px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-md, 6px);background:var(--background-fill-secondary, #f9fafb)}.runs-header.svelte-181dlmc{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px}.select-all-label.svelte-181dlmc{display:flex;align-items:center;gap:6px;cursor:pointer}.select-all-cb.svelte-181dlmc{-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);cursor:pointer;flex-shrink:0;position:relative;transition:background-color .15s,border-color .15s}.select-all-cb.svelte-181dlmc:checked{background-color:var(--checkbox-background-color-selected, var(--color-accent, #f97316));border-color:var(--checkbox-background-color-selected, var(--color-accent, #f97316));background-image:var(--checkbox-check)}.select-all-cb.svelte-181dlmc:indeterminate{background-color:var(--checkbox-background-color-selected, var(--color-accent, #f97316));border-color:var(--checkbox-background-color-selected, var(--color-accent, #f97316));background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='3' y='7' width='10' height='2' rx='1'/%3E%3C/svg%3E");background-size:12px;background-position:center;background-repeat:no-repeat}.latest-toggle.svelte-181dlmc{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--body-text-color-subdued, #6b7280);cursor:pointer}.latest-toggle.svelte-181dlmc input[type=checkbox]:where(.svelte-181dlmc){-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;margin:0;border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);box-shadow:var(--checkbox-shadow);cursor:pointer;flex-shrink:0;transition:background-color .15s,border-color .15s}.latest-toggle.svelte-181dlmc input[type=checkbox]:where(.svelte-181dlmc):checked{background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected, #f97316);border-color:var(--checkbox-border-color-selected, #f97316)}.checkbox-list.svelte-181dlmc{max-height:300px;overflow-y:auto;margin-top:8px}.alert-panel.svelte-x5aqew{position:fixed;bottom:16px;right:16px;width:380px;max-height:400px;background:var(--background-fill-primary, white);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);box-shadow:var(--shadow-drop-lg);z-index:1000;overflow:hidden;display:flex;flex-direction:column}.alert-panel.collapsed.svelte-x5aqew{max-height:none}.alert-header.svelte-x5aqew{padding:10px 12px;border:none;border-bottom:1px solid var(--border-color-primary, #e5e7eb);background:none;width:100%;display:flex;align-items:center;justify-content:space-between;cursor:pointer;gap:8px}.alert-panel.collapsed.svelte-x5aqew .alert-header:where(.svelte-x5aqew){border-bottom:none}.collapse-icon.svelte-x5aqew{color:var(--body-text-color-subdued, #9ca3af);flex-shrink:0;transition:transform .15s}.collapse-icon.rotated.svelte-x5aqew{transform:rotate(-90deg)}.alert-title.svelte-x5aqew{font-size:13px;font-weight:600;color:var(--body-text-color, #1f2937)}.filter-pills.svelte-x5aqew{display:flex;gap:4px}.pill.svelte-x5aqew{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-xxl, 22px);padding:2px 8px;font-size:11px;background:var(--background-fill-secondary, #f9fafb);color:var(--body-text-color-subdued, #6b7280);cursor:pointer}.pill.active.svelte-x5aqew{background:var(--color-accent, #f97316);color:#fff;border-color:var(--color-accent, #f97316)}.alert-list.svelte-x5aqew{overflow-y:auto;flex:1}.alert-item.svelte-x5aqew{border-bottom:1px solid var(--neutral-100, #f3f4f6)}.alert-row.svelte-x5aqew{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;font-size:var(--text-sm, 12px)}.alert-row.svelte-x5aqew:hover{background:var(--background-fill-secondary, #f9fafb)}.alert-text.svelte-x5aqew{flex:1;color:var(--body-text-color, #1f2937)}.alert-meta.svelte-x5aqew{font-size:var(--text-xs, 10px);color:var(--body-text-color-subdued, #9ca3af);white-space:nowrap}.alert-detail.svelte-x5aqew{padding:4px 12px 8px 32px;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280)}.plot-container.svelte-9thu1j{min-width:350px;flex:1;background:var(--background-fill-primary, white);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);padding:12px;overflow:hidden;position:relative}.plot-container[draggable=true].svelte-9thu1j{cursor:grab}.plot-container[draggable=true].svelte-9thu1j:active{cursor:grabbing}.hidden-plot.svelte-9thu1j{visibility:hidden;height:0;padding:0;margin:0;border:none;overflow:hidden;pointer-events:none}.drag-handle.svelte-9thu1j{position:absolute;top:8px;left:8px;color:var(--body-text-color-subdued, #9ca3af);opacity:0;transition:opacity .15s;z-index:5}.plot-container.svelte-9thu1j:hover .drag-handle:where(.svelte-9thu1j){opacity:.5}.drag-handle.svelte-9thu1j:hover{opacity:1!important}.plot-toolbar.svelte-9thu1j{position:absolute;top:8px;right:8px;display:flex;gap:4px;z-index:5;opacity:0;transition:opacity .15s}.plot-container.svelte-9thu1j:hover .plot-toolbar:where(.svelte-9thu1j){opacity:1}.toolbar-btn.svelte-9thu1j{border:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, white);color:var(--body-text-color-subdued, #6b7280);cursor:pointer;padding:4px 6px;border-radius:var(--radius-sm, 4px);display:flex;align-items:center;justify-content:center}.toolbar-btn.svelte-9thu1j:hover{background:var(--neutral-100, #f3f4f6);color:var(--body-text-color, #1f2937)}.plot-chart-wrap.svelte-9thu1j{position:relative;width:100%}.plot-chart-wrap--fs.svelte-9thu1j{flex:1;min-height:0;display:flex;flex-direction:column}.reset-zoom-btn.svelte-9thu1j{position:absolute;bottom:1px;right:1px;z-index:6;display:inline-flex;align-items:center;justify-content:center;margin:0;min-width:52px;padding:5px 12px 5px 10px;border:none;border-radius:4px;background:transparent;color:var(--body-text-color-subdued, #334155);cursor:pointer;opacity:.92;transform:translateY(6px);transition:opacity .15s ease,color .15s ease,background .15s ease;box-shadow:none}.reset-zoom-btn.svelte-9thu1j:hover{opacity:1;color:var(--body-text-color, #0f172a);background:var(--background-fill-secondary, rgba(226, 232, 240, .85));transform:translateY(6px)}.reset-zoom-btn.svelte-9thu1j svg:where(.svelte-9thu1j){display:block;flex-shrink:0;filter:drop-shadow(0 0 .5px rgba(255,255,255,.95))}.plot.svelte-9thu1j{width:100%}.plot.svelte-9thu1j .vega-embed{width:100%!important}.plot.svelte-9thu1j .vega-embed summary{display:none}.fullscreen-host.svelte-9thu1j{position:fixed;top:0;right:0;bottom:0;left:0;z-index:10000;box-sizing:border-box;display:flex;flex-direction:column;background:var(--background-fill-primary, white);padding:12px;gap:8px;pointer-events:auto}.fullscreen-host.svelte-9thu1j:fullscreen{width:100%;height:100%}.fullscreen-host.svelte-9thu1j:-webkit-full-screen{width:100%;height:100%}.fullscreen-toolbar.svelte-9thu1j{flex-shrink:0;display:flex;justify-content:flex-end;gap:4px;z-index:5}.fullscreen-chart-wrap.svelte-9thu1j{flex:1;min-height:0;display:flex;flex-direction:column}.fullscreen-legend.svelte-9thu1j{flex-shrink:0}.fullscreen-plot.svelte-9thu1j{flex:1;min-height:0;width:100%;overflow:hidden}.fullscreen-plot.svelte-9thu1j .vega-embed{width:100%!important;height:100%!important;min-height:0;display:flex;flex-direction:column}.fullscreen-plot.svelte-9thu1j .vega-embed .vega-view{flex:1;min-height:0}.fullscreen-plot.svelte-9thu1j .vega-embed summary{display:none}.custom-legend.svelte-9thu1j{display:flex;align-items:center;justify-content:center;gap:12px;padding:6px 0 0;flex-wrap:wrap}.legend-title.svelte-9thu1j{font-size:11px;color:var(--body-text-color-subdued, #6b7280);font-weight:600}.legend-item.svelte-9thu1j{display:flex;align-items:center;gap:4px}.legend-dot.svelte-9thu1j{width:10px;height:10px;border-radius:50%;flex-shrink:0}.legend-label.svelte-9thu1j{font-size:11px;color:var(--body-text-color-subdued, #6b7280)}.plot-container.svelte-1swghqy{min-width:350px;flex:1;background:var(--background-fill-primary, white);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);padding:12px;overflow:hidden;position:relative}.plot-container[draggable=true].svelte-1swghqy{cursor:grab}.plot-container[draggable=true].svelte-1swghqy:active{cursor:grabbing}.hidden-plot.svelte-1swghqy{visibility:hidden;height:0;padding:0;margin:0;border:none;overflow:hidden;pointer-events:none}.drag-handle.svelte-1swghqy{position:absolute;top:8px;left:8px;color:var(--body-text-color-subdued, #9ca3af);opacity:0;transition:opacity .15s;z-index:5}.plot-container.svelte-1swghqy:hover .drag-handle:where(.svelte-1swghqy){opacity:.5}.drag-handle.svelte-1swghqy:hover{opacity:1!important}.plot-toolbar.svelte-1swghqy{position:absolute;top:8px;right:8px;display:flex;gap:4px;z-index:5;opacity:0;transition:opacity .15s}.plot-container.svelte-1swghqy:hover .plot-toolbar:where(.svelte-1swghqy){opacity:1}.toolbar-btn.svelte-1swghqy{border:1px solid var(--border-color-primary, #e5e7eb);background:var(--background-fill-primary, white);color:var(--body-text-color-subdued, #6b7280);cursor:pointer;padding:4px 6px;border-radius:var(--radius-sm, 4px);display:flex;align-items:center;justify-content:center}.toolbar-btn.svelte-1swghqy:hover{background:var(--neutral-100, #f3f4f6);color:var(--body-text-color, #1f2937)}.plot-chart-wrap.svelte-1swghqy{position:relative;width:100%}.plot-chart-wrap--fs.svelte-1swghqy{flex:1;min-height:0;display:flex;flex-direction:column}.plot.svelte-1swghqy{width:100%}.plot.svelte-1swghqy .vega-embed{width:100%!important}.plot.svelte-1swghqy .vega-embed summary{display:none}.fullscreen-host.svelte-1swghqy{position:fixed;top:0;right:0;bottom:0;left:0;z-index:10000;box-sizing:border-box;display:flex;flex-direction:column;background:var(--background-fill-primary, white);padding:12px;gap:8px;pointer-events:auto}.fullscreen-host.svelte-1swghqy:fullscreen{width:100%;height:100%}.fullscreen-host.svelte-1swghqy:-webkit-full-screen{width:100%;height:100%}.fullscreen-toolbar.svelte-1swghqy{flex-shrink:0;display:flex;justify-content:flex-end;gap:4px;z-index:5}.fullscreen-chart-wrap.svelte-1swghqy{flex:1;min-height:0;display:flex;flex-direction:column}.fullscreen-legend.svelte-1swghqy{flex-shrink:0}.fullscreen-plot.svelte-1swghqy{flex:1;min-height:0;width:100%;overflow:hidden}.fullscreen-plot.svelte-1swghqy .vega-embed{width:100%!important;height:100%!important;min-height:0;display:flex;flex-direction:column}.fullscreen-plot.svelte-1swghqy .vega-embed .vega-view{flex:1;min-height:0}.fullscreen-plot.svelte-1swghqy .vega-embed summary{display:none}.custom-legend.svelte-1swghqy{display:flex;align-items:center;justify-content:center;gap:12px;padding:6px 0 0;flex-wrap:wrap}.legend-title.svelte-1swghqy{font-size:11px;color:var(--body-text-color-subdued, #6b7280);font-weight:600}.legend-item.svelte-1swghqy{display:flex;align-items:center;gap:4px}.legend-dot.svelte-1swghqy{width:10px;height:10px;border-radius:50%;flex-shrink:0}.legend-label.svelte-1swghqy{font-size:11px;color:var(--body-text-color-subdued, #6b7280)}.accordion.svelte-1jep0a{margin-bottom:12px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);background:var(--background-fill-primary, white);overflow:hidden}.accordion-hidden.svelte-1jep0a{margin-bottom:8px}.accordion-header.svelte-1jep0a{display:flex;align-items:center;gap:8px;width:100%;padding:10px 14px;border:none;background:var(--background-fill-primary, white);color:var(--body-text-color, #1f2937);font-size:var(--text-md, 14px);font-weight:600;cursor:pointer;text-align:left}.accordion-header.svelte-1jep0a:hover{background:var(--background-fill-secondary, #f9fafb)}.arrow.svelte-1jep0a{font-size:14px;transition:transform .15s;color:var(--body-text-color, #1f2937);display:inline-block}.arrow.svelte-1jep0a:not(.rotated){transform:rotate(-90deg)}.accordion-body.svelte-1jep0a{padding:0 14px 14px}.trackio-loading.svelte-1kc6b2l{display:flex;align-items:center;justify-content:center;width:100%;min-height:min(70vh,640px);padding:32px 24px;box-sizing:border-box;background:transparent}.logo-stack.svelte-1kc6b2l{position:relative;width:min(100%,200px);max-width:min(92vw,200px);line-height:0;background:transparent;isolation:isolate}.logo-base.svelte-1kc6b2l{display:block;background:transparent}.logo-img.svelte-1kc6b2l{width:100%;height:auto;display:block;background:transparent}.logo-overlay.svelte-1kc6b2l{position:absolute;left:0;top:0;width:100%;animation:svelte-1kc6b2l-trackio-logo-sweep 4s linear infinite;pointer-events:none;background:transparent}.logo-overlay.svelte-1kc6b2l .logo-img:where(.svelte-1kc6b2l){width:100%;height:auto;object-position:left center}.logo-img--gray.svelte-1kc6b2l{filter:grayscale(1)}@keyframes svelte-1kc6b2l-trackio-logo-sweep{0%{clip-path:inset(0 0 0 0)}50%{clip-path:inset(0 0 0 100%)}to{clip-path:inset(0 0 0 0)}}@media(prefers-reduced-motion:reduce){.logo-overlay.svelte-1kc6b2l{display:none}}.sr-only.svelte-1kc6b2l{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.metrics-page.svelte-2bul55{padding:20px 24px;overflow-y:auto;flex:1;min-height:0}.plot-grid.svelte-2bul55{display:flex;flex-wrap:wrap;gap:16px}.subgroup-list.svelte-2bul55{margin-top:16px}.empty-state.svelte-2bul55{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-2bul55 h2:where(.svelte-2bul55){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-2bul55 p:where(.svelte-2bul55){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-2bul55 pre:where(.svelte-2bul55){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-2bul55 code:where(.svelte-2bul55){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-2bul55 pre:where(.svelte-2bul55) code:where(.svelte-2bul55){background:none;padding:0}.system-page.svelte-nv5os4{padding:20px 24px;overflow-y:auto;flex:1;min-height:0}.plot-grid.svelte-nv5os4{display:flex;flex-wrap:wrap;gap:12px}.empty-state.svelte-nv5os4{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-nv5os4 h2:where(.svelte-nv5os4){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-nv5os4 p:where(.svelte-nv5os4){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-nv5os4 pre:where(.svelte-nv5os4){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-nv5os4 ul:where(.svelte-nv5os4){list-style:disc;padding-left:20px;margin:4px 0 0}.empty-state.svelte-nv5os4 li:where(.svelte-nv5os4){margin:4px 0;color:var(--body-text-color, #1f2937)}.empty-state.svelte-nv5os4 code:where(.svelte-nv5os4){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-nv5os4 pre:where(.svelte-nv5os4) code:where(.svelte-nv5os4){background:none;padding:0}.table-container.svelte-1cp60rw{display:flex;flex-direction:column;gap:var(--size-2, 8px);position:relative}.header-row.svelte-1cp60rw{display:flex;justify-content:flex-end;align-items:center;min-height:var(--size-6, 24px);width:100%}.header-row.svelte-1cp60rw .label:where(.svelte-1cp60rw){flex:1;margin:0;color:var(--block-label-text-color, var(--neutral-500, #6b7280));font-size:var(--block-label-text-size, 12px);line-height:var(--line-sm, 1.4)}.table-wrap.svelte-1cp60rw{position:relative;overflow:auto;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--table-radius, var(--radius-lg, 8px))}table.svelte-1cp60rw{width:100%;table-layout:auto;color:var(--body-text-color, #1f2937);font-size:var(--input-text-size, 14px);line-height:var(--line-sm, 1.4);border-spacing:0;border-collapse:separate}thead.svelte-1cp60rw{position:sticky;top:0;z-index:5;box-shadow:var(--shadow-drop, rgba(0,0,0,.05) 0px 1px 2px 0px)}th.svelte-1cp60rw{padding:0;background:var(--table-even-background-fill, white);border-right-width:0px;border-left-width:1px;border-bottom-width:1px;border-style:solid;border-color:var(--border-color-primary, #e5e7eb);text-align:left;cursor:pointer;-webkit-user-select:none;user-select:none}th.first.svelte-1cp60rw{border-left-width:0;border-top-left-radius:var(--table-radius, var(--radius-lg, 8px))}th.last.svelte-1cp60rw{border-top-right-radius:var(--table-radius, var(--radius-lg, 8px))}.th-inner.svelte-1cp60rw{padding:var(--size-2, 8px);display:flex;align-items:center;gap:4px;font-weight:600;font-size:var(--text-sm, 12px);white-space:nowrap}.sort-arrow.svelte-1cp60rw{font-size:10px;color:var(--body-text-color-subdued, #9ca3af);visibility:hidden}.sort-arrow.visible.svelte-1cp60rw{visibility:visible}td.svelte-1cp60rw{padding:var(--size-2, 8px);border-right-width:0px;border-left-width:1px;border-bottom-width:1px;border-style:solid;border-color:var(--border-color-primary, #e5e7eb);font-size:var(--text-sm, 12px)}td.first.svelte-1cp60rw{border-left-width:0}tr.svelte-1cp60rw{background:var(--table-even-background-fill, white);border-bottom:1px solid var(--border-color-primary, #e5e7eb);text-align:left}tr.row-odd.svelte-1cp60rw{background:var(--table-odd-background-fill, var(--neutral-50, #f9fafb))}tr.selected.svelte-1cp60rw{background:var(--color-accent-soft, var(--primary-50, #fff7ed))}tr.svelte-1cp60rw:last-child td.first:where(.svelte-1cp60rw){border-bottom-left-radius:var(--table-radius, var(--radius-lg, 8px))}tr.svelte-1cp60rw:last-child td.last:where(.svelte-1cp60rw){border-bottom-right-radius:var(--table-radius, var(--radius-lg, 8px))}.check-col.svelte-1cp60rw{width:40px;text-align:center;padding:var(--size-2, 8px);border-left-width:0}.check-col.svelte-1cp60rw input[type=checkbox]:where(.svelte-1cp60rw){-moz-appearance:none;appearance:none;-webkit-appearance:none;width:16px;height:16px;border:1px solid var(--checkbox-border-color, #d1d5db);border-radius:var(--checkbox-border-radius, 4px);background-color:var(--checkbox-background-color, white);cursor:pointer;flex-shrink:0;transition:background-color .15s,border-color .15s}.check-col.svelte-1cp60rw input[type=checkbox]:where(.svelte-1cp60rw):checked{background-image:var(--checkbox-check);background-color:var(--checkbox-background-color-selected, #2563eb);border-color:var(--checkbox-border-color-selected, #2563eb)}.media-page.svelte-outb32{padding:20px 24px;overflow-y:auto;flex:1}.section-title.svelte-outb32{font-size:var(--text-lg, 16px);font-weight:600;color:var(--body-text-color, #1f2937);margin:16px 0 8px}.gallery.svelte-outb32{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}.gallery-item.svelte-outb32{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);overflow:hidden;background:var(--background-fill-secondary, #f9fafb)}.gallery-item.svelte-outb32 img:where(.svelte-outb32),.gallery-item.svelte-outb32 video:where(.svelte-outb32){width:100%;display:block}.caption.svelte-outb32{padding:4px 8px;font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #9ca3af)}.step-label.svelte-outb32{padding:4px 8px;font-size:var(--text-xs, 10px);color:var(--body-text-color-subdued, #9ca3af)}.audio-list.svelte-outb32{display:flex;flex-direction:column;gap:8px}.audio-item.svelte-outb32{display:flex;align-items:center;gap:12px;padding:8px;border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px)}.audio-label.svelte-outb32{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #9ca3af);min-width:120px}.table-section.svelte-outb32{margin-bottom:16px}.empty-state.svelte-outb32{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-outb32 h2:where(.svelte-outb32){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-outb32 p:where(.svelte-outb32){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-outb32 pre:where(.svelte-outb32){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-outb32 code:where(.svelte-outb32){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-outb32 pre:where(.svelte-outb32) code:where(.svelte-outb32){background:none;padding:0}.reports-page.svelte-iufsej{padding:20px 24px;overflow-y:auto;flex:1}.controls.svelte-iufsej{display:flex;gap:16px;margin-bottom:16px;flex-wrap:wrap;align-items:flex-end}.control.svelte-iufsej{min-width:200px}.filter-pills.svelte-iufsej{display:flex;gap:4px}.pill.svelte-iufsej{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-xxl, 22px);padding:4px 12px;font-size:var(--text-sm, 12px);background:var(--background-fill-secondary, #f9fafb);color:var(--body-text-color-subdued, #6b7280);cursor:pointer;transition:background-color .15s,color .15s}.pill.svelte-iufsej:hover{background:var(--neutral-100, #f3f4f6)}.pill.active.svelte-iufsej{background:var(--color-accent, #f97316);color:#fff;border-color:var(--color-accent, #f97316)}.empty-state.svelte-iufsej{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-iufsej h2:where(.svelte-iufsej){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-iufsej p:where(.svelte-iufsej){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-iufsej pre:where(.svelte-iufsej){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-iufsej code:where(.svelte-iufsej){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-iufsej pre:where(.svelte-iufsej) code:where(.svelte-iufsej){background:none;padding:0}.alerts-table.svelte-iufsej{width:100%;border-collapse:collapse;font-size:var(--text-md, 14px)}.alerts-table.svelte-iufsej th:where(.svelte-iufsej){text-align:left;padding:8px 12px;border-bottom:2px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color-subdued, #6b7280);font-weight:600;font-size:var(--text-sm, 12px);text-transform:uppercase;letter-spacing:.05em}.alerts-table.svelte-iufsej td:where(.svelte-iufsej){padding:8px 12px;border-bottom:1px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color, #1f2937)}.alerts-table.svelte-iufsej tbody:where(.svelte-iufsej) tr:where(.svelte-iufsej):nth-child(odd){background:var(--table-odd-background-fill, var(--background-fill-primary, white))}.alerts-table.svelte-iufsej tbody:where(.svelte-iufsej) tr:where(.svelte-iufsej):nth-child(2n){background:var(--table-even-background-fill, var(--background-fill-secondary, #f9fafb))}.alerts-table.svelte-iufsej tr:where(.svelte-iufsej):hover{background:var(--background-fill-secondary, #f3f4f6)}.section-title.svelte-iufsej{font-size:16px;font-weight:700;margin:0 0 12px;color:var(--body-text-color, #1f2937)}.reports-section.svelte-iufsej,.alerts-section.svelte-iufsej{margin-bottom:32px}.report-card.svelte-iufsej{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);padding:16px 20px;margin-bottom:12px;background:var(--background-fill-primary, white)}.report-meta.svelte-iufsej{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280);margin-bottom:8px}.report-content.svelte-iufsej{font-size:var(--text-md, 14px);color:var(--body-text-color, #1f2937);line-height:1.6}.report-content.svelte-iufsej h2{font-size:18px;font-weight:700;margin:0 0 8px}.report-content.svelte-iufsej h3{font-size:16px;font-weight:600;margin:12px 0 6px}.report-content.svelte-iufsej h4{font-size:14px;font-weight:600;margin:10px 0 4px}.report-content.svelte-iufsej code{background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.report-content.svelte-iufsej ul{margin:4px 0;padding-left:20px}.report-content.svelte-iufsej li{margin:2px 0}.report-content.svelte-iufsej p{margin:6px 0}.filter-empty.svelte-iufsej{color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-md, 14px)}.runs-page.svelte-1yb6d54{padding:20px 24px;overflow-y:auto;flex:1}.empty-state.svelte-1yb6d54{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-1yb6d54 h2:where(.svelte-1yb6d54){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-1yb6d54 p:where(.svelte-1yb6d54){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-1yb6d54 pre:where(.svelte-1yb6d54){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-1yb6d54 code:where(.svelte-1yb6d54){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-1yb6d54 pre:where(.svelte-1yb6d54) code:where(.svelte-1yb6d54){background:none;padding:0}.runs-table.svelte-1yb6d54{width:100%;border-collapse:collapse;font-size:var(--text-md, 14px)}.runs-table.svelte-1yb6d54 th:where(.svelte-1yb6d54){text-align:left;padding:8px 12px;border-bottom:2px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color-subdued, #6b7280);font-weight:600;font-size:var(--text-sm, 12px);text-transform:uppercase;letter-spacing:.05em}.runs-table.svelte-1yb6d54 td:where(.svelte-1yb6d54){padding:8px 12px;border-bottom:1px solid var(--border-color-primary, #e5e7eb);color:var(--body-text-color, #1f2937)}.runs-table.svelte-1yb6d54 tbody:where(.svelte-1yb6d54) tr:where(.svelte-1yb6d54):nth-child(odd){background:var(--table-odd-background-fill, var(--background-fill-primary, white))}.runs-table.svelte-1yb6d54 tbody:where(.svelte-1yb6d54) tr:where(.svelte-1yb6d54):nth-child(2n){background:var(--table-even-background-fill, var(--background-fill-secondary, #f9fafb))}.runs-table.svelte-1yb6d54 tr:where(.svelte-1yb6d54):hover{background:var(--background-fill-secondary, #f3f4f6)}.run-name-cell.svelte-1yb6d54{font-weight:500}.run-name-with-dot.svelte-1yb6d54{display:inline-flex;align-items:center;gap:8px;max-width:100%}.run-dot.svelte-1yb6d54{width:10px;height:10px;border-radius:50%;flex-shrink:0}.link-btn.svelte-1yb6d54{background:none;border:none;color:var(--color-accent, #f97316);cursor:pointer;font:inherit;font-weight:500;padding:0;text-align:left}.link-btn.svelte-1yb6d54:hover{text-decoration:underline}.rename-input.svelte-1yb6d54{font:inherit;padding:2px 6px;border:1px solid var(--color-accent, #f97316);border-radius:var(--radius-sm, 4px);outline:none;width:100%}.actions-cell.svelte-1yb6d54{display:flex;gap:4px}.action-btn.svelte-1yb6d54{background:none;border:1px solid transparent;color:var(--body-text-color-subdued, #6b7280);cursor:pointer;padding:4px;border-radius:var(--radius-sm, 4px);display:flex;align-items:center}.action-btn.svelte-1yb6d54:hover{background:var(--background-fill-secondary, #f9fafb);border-color:var(--border-color-primary, #e5e7eb);color:var(--body-text-color, #1f2937)}.delete-btn.svelte-1yb6d54:hover{color:#dc2626;border-color:#fecaca;background:#fef2f2}.action-btn.svelte-1yb6d54:disabled{opacity:.45;cursor:not-allowed;pointer-events:none}.run-detail-page.svelte-1bpgsx2{padding:20px 24px;overflow-y:auto;flex:1}.detail-card.svelte-1bpgsx2{background:var(--background-fill-primary, white);border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);padding:24px;max-width:800px}.detail-card.svelte-1bpgsx2 h2:where(.svelte-1bpgsx2){color:var(--body-text-color, #1f2937);margin:0 0 16px;font-size:var(--text-xl, 22px)}.detail-card.svelte-1bpgsx2 h3:where(.svelte-1bpgsx2){color:var(--body-text-color, #1f2937);margin:20px 0 8px;font-size:var(--text-lg, 16px)}.detail-grid.svelte-1bpgsx2{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px}.detail-item.svelte-1bpgsx2{display:flex;flex-direction:column;gap:2px}.detail-label.svelte-1bpgsx2{font-size:var(--text-xs, 10px);font-weight:600;color:var(--body-text-color-subdued, #9ca3af);text-transform:uppercase}.detail-value.svelte-1bpgsx2{font-size:var(--text-md, 14px);color:var(--body-text-color, #1f2937)}.config-block.svelte-1bpgsx2{background:var(--background-fill-secondary, #f9fafb);padding:12px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:var(--text-sm, 12px);color:var(--body-text-color, #1f2937);overflow-x:auto}.empty-state.svelte-1bpgsx2{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-1bpgsx2 h2:where(.svelte-1bpgsx2){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-1bpgsx2 p:where(.svelte-1bpgsx2){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-1bpgsx2 pre:where(.svelte-1bpgsx2){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-1bpgsx2 code:where(.svelte-1bpgsx2){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-1bpgsx2 pre:where(.svelte-1bpgsx2) code:where(.svelte-1bpgsx2){background:none;padding:0}.files-page.svelte-1xvfk9n{padding:20px 24px;overflow-y:auto;flex:1}.page-title.svelte-1xvfk9n{color:var(--body-text-color, #1f2937);font-size:16px;font-weight:700;margin:0 0 4px}.page-subtitle.svelte-1xvfk9n{color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-sm, 12px);margin:0 0 16px}.file-list.svelte-1xvfk9n{display:flex;flex-direction:column;gap:4px}.file-item.svelte-1xvfk9n{border:1px solid var(--border-color-primary, #e5e7eb);border-radius:var(--radius-lg, 8px);background:var(--background-fill-primary, white);overflow:hidden}.file-item.expanded.svelte-1xvfk9n{border-color:var(--color-accent, #f97316)}.file-row.svelte-1xvfk9n{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;gap:12px}.file-name.svelte-1xvfk9n{display:flex;align-items:center;gap:8px;background:none;border:none;padding:0;font-size:var(--text-md, 14px);color:var(--body-text-color, #1f2937);cursor:pointer;text-align:left}.file-name.svelte-1xvfk9n:hover{color:var(--color-accent, #f97316)}.file-icon.svelte-1xvfk9n{font-size:14px;flex-shrink:0}.file-actions.svelte-1xvfk9n{display:flex;align-items:center;gap:12px;flex-shrink:0}.file-size.svelte-1xvfk9n{font-size:var(--text-sm, 12px);color:var(--body-text-color-subdued, #6b7280);white-space:nowrap}.download-btn.svelte-1xvfk9n{display:flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:var(--radius-md, 6px);color:var(--body-text-color-subdued, #6b7280);transition:background-color .15s,color .15s}.download-btn.svelte-1xvfk9n:hover{background:var(--background-fill-secondary, #f3f4f6);color:var(--body-text-color, #1f2937)}.file-preview.svelte-1xvfk9n{border-top:1px solid var(--border-color-primary, #e5e7eb);padding:12px 14px;background:var(--background-fill-secondary, #f9fafb)}.preview-code.svelte-1xvfk9n{margin:0;font-size:12px;line-height:1.5;max-height:400px;overflow:auto;white-space:pre-wrap;word-break:break-all;color:var(--body-text-color, #1f2937)}.preview-loading.svelte-1xvfk9n,.preview-unavailable.svelte-1xvfk9n{color:var(--body-text-color-subdued, #6b7280);font-size:var(--text-sm, 12px);padding:8px 0}.preview-unavailable.svelte-1xvfk9n a:where(.svelte-1xvfk9n){color:var(--color-accent, #f97316);text-decoration:none}.preview-unavailable.svelte-1xvfk9n a:where(.svelte-1xvfk9n):hover{text-decoration:underline}.empty-state.svelte-1xvfk9n{max-width:640px;padding:40px 24px;color:var(--body-text-color, #1f2937)}.empty-state.svelte-1xvfk9n h2:where(.svelte-1xvfk9n){margin:0 0 8px;font-size:20px;font-weight:700}.empty-state.svelte-1xvfk9n p:where(.svelte-1xvfk9n){margin:12px 0 8px;color:var(--body-text-color-subdued, #6b7280)}.empty-state.svelte-1xvfk9n pre:where(.svelte-1xvfk9n){background:var(--background-fill-secondary, #f9fafb);padding:16px;border-radius:var(--radius-lg, 8px);border:1px solid var(--border-color-primary, #e5e7eb);font-size:13px;overflow-x:auto}.empty-state.svelte-1xvfk9n code:where(.svelte-1xvfk9n){background:var(--background-fill-secondary, #f0f0f0);padding:1px 5px;border-radius:var(--radius-sm, 4px);font-size:13px}.empty-state.svelte-1xvfk9n pre:where(.svelte-1xvfk9n) code:where(.svelte-1xvfk9n){background:none;padding:0}*{margin:0;padding:0;box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;background:var(--background-fill-primary, #fff);color:var(--body-text-color, #1f2937);font-size:var(--text-md, 14px);-webkit-font-smoothing:antialiased}.app.svelte-1n46o8q{display:flex;height:100vh;overflow:hidden}.main.svelte-1n46o8q{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0}.page-content.svelte-1n46o8q{flex:1;overflow:hidden;display:flex;background:var(--bg-primary)} diff --git a/trackio/frontend/dist/assets/index-UYQ1xITV.js b/trackio/frontend/dist/assets/index-UYQ1xITV.js new file mode 100644 index 0000000000000000000000000000000000000000..d8f5449672d319eedf3029dd730d8dcf75e51cb0 --- /dev/null +++ b/trackio/frontend/dist/assets/index-UYQ1xITV.js @@ -0,0 +1,250 @@ +var DU=Object.defineProperty;var E$=e=>{throw TypeError(e)};var MU=(e,t,n)=>t in e?DU(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Qi=(e,t,n)=>MU(e,typeof t!="symbol"?t+"":t,n),Pb=(e,t,n)=>t.has(e)||E$("Cannot "+n);var Y=(e,t,n)=>(Pb(e,t,"read from private field"),n?n.call(e):t.get(e)),tt=(e,t,n)=>t.has(e)?E$("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),Ve=(e,t,n,r)=>(Pb(e,t,"write to private field"),r?r.call(e,n):t.set(e,n),n),fn=(e,t,n)=>(Pb(e,t,"access private method"),n);(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();const RU="5";var X6;typeof window<"u"&&((X6=window.__svelte??(window.__svelte={})).v??(X6.v=new Set)).add(RU);const TU=1,NU=2,J6=4,OU=8,LU=16,IU=1,PU=2,BU=4,zU=8,jU=16,UU=1,qU=2,In=Symbol(),Q6="http://www.w3.org/1999/xhtml",WU="http://www.w3.org/2000/svg",HU="http://www.w3.org/1998/Math/MathML",GU=!1;var e8=Array.isArray,YU=Array.prototype.indexOf,Ff=Array.prototype.includes,my=Array.from,VU=Object.defineProperty,uf=Object.getOwnPropertyDescriptor,t8=Object.getOwnPropertyDescriptors,XU=Object.prototype,KU=Array.prototype,NE=Object.getPrototypeOf,A$=Object.isExtensible;const ZU=()=>{};function JU(e){return e()}function Ux(e){for(var t=0;t{e=r,t=i});return{promise:n,resolve:e,reject:t}}function QU(e,t){if(Array.isArray(e))return e;if(!(Symbol.iterator in e))return Array.from(e);const n=[];for(const r of e)if(n.push(r),n.length===t)break;return n}const Rn=2,Df=4,Zp=8,r8=1<<24,$u=16,ws=32,Pl=64,qx=128,Li=512,An=1024,Vn=2048,Es=4096,hi=8192,Ii=16384,pc=32768,Wx=1<<25,Bl=65536,S$=1<<17,eq=1<<18,md=1<<19,i8=1<<20,io=1<<25,zl=65536,Hx=1<<21,OE=1<<22,eu=1<<23,El=Symbol("$state"),tq=Symbol("legacy props"),nq=Symbol(""),Go=new class extends Error{constructor(){super(...arguments);Qi(this,"name","StaleReactionError");Qi(this,"message","The reaction that called `getAbortSignal()` was re-run or destroyed")}};function rq(e){throw new Error("https://svelte.dev/e/lifecycle_outside_component")}function iq(){throw new Error("https://svelte.dev/e/async_derived_orphan")}function sq(e,t,n){throw new Error("https://svelte.dev/e/each_key_duplicate")}function oq(e){throw new Error("https://svelte.dev/e/effect_in_teardown")}function aq(){throw new Error("https://svelte.dev/e/effect_in_unowned_derived")}function uq(e){throw new Error("https://svelte.dev/e/effect_orphan")}function lq(){throw new Error("https://svelte.dev/e/effect_update_depth_exceeded")}function cq(e){throw new Error("https://svelte.dev/e/props_invalid_value")}function fq(){throw new Error("https://svelte.dev/e/state_descriptors_fixed")}function dq(){throw new Error("https://svelte.dev/e/state_prototype_fixed")}function hq(){throw new Error("https://svelte.dev/e/state_unsafe_mutation")}function pq(){throw new Error("https://svelte.dev/e/svelte_boundary_reset_onerror")}function gq(){console.warn("https://svelte.dev/e/svelte_boundary_reset_noop")}function s8(e){return e===this.v}function o8(e,t){return e!=e?t==t:e!==t||e!==null&&typeof e=="object"||typeof e=="function"}function a8(e){return!o8(e,this.v)}let yd=!1,mq=!1;function yq(){yd=!0}let Qt=null;function Mf(e){Qt=e}function nn(e,t=!1,n){Qt={p:Qt,i:!1,c:null,e:null,s:e,x:null,r:nt,l:yd&&!t?{s:null,u:null,$:[]}:null}}function rn(e){var t=Qt,n=t.e;if(n!==null){t.e=null;for(var r of n)D8(r)}return t.i=!0,Qt=t.p,{}}function Jp(){return!yd||Qt!==null&&Qt.l===null}let hl=[];function u8(){var e=hl;hl=[],Ux(e)}function tu(e){if(hl.length===0&&!Yh){var t=hl;queueMicrotask(()=>{t===hl&&u8()})}hl.push(e)}function vq(){for(;hl.length>0;)u8()}function l8(e){var t=nt;if(t===null)return Ze.f|=eu,e;if((t.f&pc)===0&&(t.f&Df)===0)throw e;Wa(e,t)}function Wa(e,t){for(;t!==null;){if((t.f&qx)!==0){if((t.f&pc)===0)throw e;try{t.b.error(e);return}catch(n){e=n}}t=t.parent}throw e}const bq=-7169;function an(e,t){e.f=e.f&bq|t}function LE(e){(e.f&Li)!==0||e.deps===null?an(e,An):an(e,Es)}function c8(e){if(e!==null)for(const t of e)(t.f&Rn)===0||(t.f&zl)===0||(t.f^=zl,c8(t.deps))}function f8(e,t,n){(e.f&Vn)!==0?t.add(e):(e.f&Es)!==0&&n.add(e),c8(e.deps),an(e,An)}let Jg=!1;function xq(e){var t=Jg;try{return Jg=!1,[e(),Jg]}finally{Jg=t}}const Gd=new Set;let Ye=null,Bn=null,Gx=null,Yh=!1,Bb=!1,Qc=null,V0=null;var k$=0;let _q=1;var xf,_f,wf,Ef,Vp,ki,Af,Ua,Ks,Sf,gr,Yx,Vx,Xx,Kx,d8;const hy=class hy{constructor(){tt(this,gr);Qi(this,"id",_q++);Qi(this,"current",new Map);Qi(this,"previous",new Map);tt(this,xf,new Set);tt(this,_f,new Set);tt(this,wf,0);tt(this,Ef,0);tt(this,Vp,null);tt(this,ki,[]);tt(this,Af,new Set);tt(this,Ua,new Set);tt(this,Ks,new Map);Qi(this,"is_fork",!1);tt(this,Sf,!1)}skip_effect(t){Y(this,Ks).has(t)||Y(this,Ks).set(t,{d:[],m:[]})}unskip_effect(t){var n=Y(this,Ks).get(t);if(n){Y(this,Ks).delete(t);for(var r of n.d)an(r,Vn),this.schedule(r);for(r of n.m)an(r,Es),this.schedule(r)}}capture(t,n){n!==In&&!this.previous.has(t)&&this.previous.set(t,n),(t.f&eu)===0&&(this.current.set(t,t.v),Bn==null||Bn.set(t,t.v))}activate(){Ye=this}deactivate(){Ye=null,Bn=null}flush(){try{if(Bb=!0,Ye=this,!fn(this,gr,Yx).call(this)){for(const t of Y(this,Af))Y(this,Ua).delete(t),an(t,Vn),this.schedule(t);for(const t of Y(this,Ua))an(t,Es),this.schedule(t)}fn(this,gr,Vx).call(this)}finally{k$=0,Gx=null,Qc=null,V0=null,Bb=!1,Ye=null,Bn=null,nu.clear()}}discard(){for(const t of Y(this,_f))t(this);Y(this,_f).clear()}increment(t){Ve(this,wf,Y(this,wf)+1),t&&Ve(this,Ef,Y(this,Ef)+1)}decrement(t,n){Ve(this,wf,Y(this,wf)-1),t&&Ve(this,Ef,Y(this,Ef)-1),!(Y(this,Sf)||n)&&(Ve(this,Sf,!0),tu(()=>{Ve(this,Sf,!1),this.flush()}))}oncommit(t){Y(this,xf).add(t)}ondiscard(t){Y(this,_f).add(t)}settled(){return(Y(this,Vp)??Ve(this,Vp,n8())).promise}static ensure(){if(Ye===null){const t=Ye=new hy;Bb||(Gd.add(Ye),Yh||tu(()=>{Ye===t&&t.flush()}))}return Ye}apply(){}schedule(t){var i;if(Gx=t,(i=t.b)!=null&&i.is_pending&&(t.f&(Df|Zp|r8))!==0&&(t.f&pc)===0){t.b.defer_effect(t);return}for(var n=t;n.parent!==null;){n=n.parent;var r=n.f;if(Qc!==null&&n===nt&&(Ze===null||(Ze.f&Rn)===0))return;if((r&(Pl|ws))!==0){if((r&An)===0)return;n.f^=An}}Y(this,ki).push(n)}};xf=new WeakMap,_f=new WeakMap,wf=new WeakMap,Ef=new WeakMap,Vp=new WeakMap,ki=new WeakMap,Af=new WeakMap,Ua=new WeakMap,Ks=new WeakMap,Sf=new WeakMap,gr=new WeakSet,Yx=function(){return this.is_fork||Y(this,Ef)>0},Vx=function(){var a,u;k$++>1e3&&Eq();const t=Y(this,ki);Ve(this,ki,[]),this.apply();var n=Qc=[],r=[],i=V0=[];for(const l of t)fn(this,gr,Xx).call(this,l,n,r);if(Ye=null,i.length>0){var s=hy.ensure();for(const l of i)s.schedule(l)}if(Qc=null,V0=null,fn(this,gr,Yx).call(this)){fn(this,gr,Kx).call(this,r),fn(this,gr,Kx).call(this,n);for(const[l,c]of Y(this,Ks))g8(l,c)}else{Y(this,Af).clear(),Y(this,Ua).clear();for(const l of Y(this,xf))l(this);Y(this,xf).clear(),C$(r),C$(n),Y(this,wf)===0&&fn(this,gr,d8).call(this),(a=Y(this,Vp))==null||a.resolve()}var o=Ye;if(Y(this,ki).length>0){const l=o??(o=this);Y(l,ki).push(...Y(this,ki).filter(c=>!Y(l,ki).includes(c)))}o!==null&&(Gd.add(o),fn(u=o,gr,Vx).call(u))},Xx=function(t,n,r){t.f^=An;for(var i=t.first;i!==null;){var s=i.f,o=(s&(ws|Pl))!==0,a=o&&(s&An)!==0,u=a||(s&hi)!==0||Y(this,Ks).has(i);if(!u&&i.fn!==null){o?i.f^=An:(s&Df)!==0?n.push(i):ng(i)&&((s&$u)!==0&&Y(this,Ua).add(i),Tf(i));var l=i.first;if(l!==null){i=l;continue}}for(;i!==null;){var c=i.next;if(c!==null){i=c;break}i=i.parent}}},Kx=function(t){for(var n=0;n1){this.previous.clear();var t=Ye,n=Bn,r=!0;for(const s of Gd){if(s===this){r=!1;continue}const o=[];for(const[u,l]of this.current){if(s.current.has(u))if(r&&l!==s.current.get(u))s.current.set(u,l);else continue;o.push(u)}if(o.length===0)continue;const a=[...s.current.keys()].filter(u=>!this.current.has(u));if(a.length>0){s.activate();const u=new Set,l=new Map;for(const c of o)h8(c,a,u,l);if(Y(s,ki).length>0){s.apply();for(const c of Y(s,ki))fn(i=s,gr,Xx).call(i,c,[],[])}s.deactivate()}}Ye=t,Bn=n}Y(this,Ks).clear(),Gd.delete(this)};let jl=hy;function wq(e){var t=Yh;Yh=!0;try{for(var n;;){if(vq(),Ye===null)return n;Ye.flush()}}finally{Yh=t}}function Eq(){try{lq()}catch(e){Wa(e,Gx)}}let rs=null;function C$(e){var t=e.length;if(t!==0){for(var n=0;n0)){nu.clear();for(const i of rs){if((i.f&(Ii|hi))!==0)continue;const s=[i];let o=i.parent;for(;o!==null;)rs.has(o)&&(rs.delete(o),s.push(o)),o=o.parent;for(let a=s.length-1;a>=0;a--){const u=s[a];(u.f&(Ii|hi))===0&&Tf(u)}}rs.clear()}}rs=null}}function h8(e,t,n,r){if(!n.has(e)&&(n.add(e),e.reactions!==null))for(const i of e.reactions){const s=i.f;(s&Rn)!==0?h8(i,t,n,r):(s&(OE|$u))!==0&&(s&Vn)===0&&p8(i,t,r)&&(an(i,Vn),IE(i))}}function p8(e,t,n){const r=n.get(e);if(r!==void 0)return r;if(e.deps!==null)for(const i of e.deps){if(Ff.call(t,i))return!0;if((i.f&Rn)!==0&&p8(i,t,n))return n.set(i,!0),!0}return n.set(e,!1),!1}function IE(e){Ye.schedule(e)}function g8(e,t){if(!((e.f&ws)!==0&&(e.f&An)!==0)){(e.f&Vn)!==0?t.d.push(e):(e.f&Es)!==0&&t.m.push(e),an(e,An);for(var n=e.first;n!==null;)g8(n,t),n=n.next}}function Aq(e){let t=0,n=Ul(0),r;return()=>{zE()&&(w(n),tg(()=>(t===0&&(r=Fu(()=>e(()=>Vh(n)))),t+=1,()=>{tu(()=>{t-=1,t===0&&(r==null||r(),r=void 0,Vh(n))})})))}}var Sq=Bl|md;function kq(e,t,n,r){new Cq(e,t,n,r)}var Ci,TE,Zs,xl,Lr,Js,si,is,Ko,_l,qa,kf,Cf,$f,Zo,py,bn,$q,Fq,Dq,Zx,X0,K0,Jx;class Cq{constructor(t,n,r,i){tt(this,bn);Qi(this,"parent");Qi(this,"is_pending",!1);Qi(this,"transform_error");tt(this,Ci);tt(this,TE,null);tt(this,Zs);tt(this,xl);tt(this,Lr);tt(this,Js,null);tt(this,si,null);tt(this,is,null);tt(this,Ko,null);tt(this,_l,0);tt(this,qa,0);tt(this,kf,!1);tt(this,Cf,new Set);tt(this,$f,new Set);tt(this,Zo,null);tt(this,py,Aq(()=>(Ve(this,Zo,Ul(Y(this,_l))),()=>{Ve(this,Zo,null)})));var s;Ve(this,Ci,t),Ve(this,Zs,n),Ve(this,xl,o=>{var a=nt;a.b=this,a.f|=qx,r(o)}),this.parent=nt.b,this.transform_error=i??((s=this.parent)==null?void 0:s.transform_error)??(o=>o),Ve(this,Lr,vy(()=>{fn(this,bn,Zx).call(this)},Sq))}defer_effect(t){f8(t,Y(this,Cf),Y(this,$f))}is_rendered(){return!this.is_pending&&(!this.parent||this.parent.is_rendered())}has_pending_snippet(){return!!Y(this,Zs).pending}update_pending_count(t,n){fn(this,bn,Jx).call(this,t,n),Ve(this,_l,Y(this,_l)+t),!(!Y(this,Zo)||Y(this,kf))&&(Ve(this,kf,!0),tu(()=>{Ve(this,kf,!1),Y(this,Zo)&&Rf(Y(this,Zo),Y(this,_l))}))}get_effect_pending(){return Y(this,py).call(this),w(Y(this,Zo))}error(t){var n=Y(this,Zs).onerror;let r=Y(this,Zs).failed;if(!n&&!r)throw t;Y(this,Js)&&(Wr(Y(this,Js)),Ve(this,Js,null)),Y(this,si)&&(Wr(Y(this,si)),Ve(this,si,null)),Y(this,is)&&(Wr(Y(this,is)),Ve(this,is,null));var i=!1,s=!1;const o=()=>{if(i){gq();return}i=!0,s&&pq(),Y(this,is)!==null&&Al(Y(this,is),()=>{Ve(this,is,null)}),fn(this,bn,K0).call(this,()=>{fn(this,bn,Zx).call(this)})},a=u=>{try{s=!0,n==null||n(u,o),s=!1}catch(l){Wa(l,Y(this,Lr)&&Y(this,Lr).parent)}r&&Ve(this,is,fn(this,bn,K0).call(this,()=>{try{return $i(()=>{var l=nt;l.b=this,l.f|=qx,r(Y(this,Ci),()=>u,()=>o)})}catch(l){return Wa(l,Y(this,Lr).parent),null}}))};tu(()=>{var u;try{u=this.transform_error(t)}catch(l){Wa(l,Y(this,Lr)&&Y(this,Lr).parent);return}u!==null&&typeof u=="object"&&typeof u.then=="function"?u.then(a,l=>Wa(l,Y(this,Lr)&&Y(this,Lr).parent)):a(u)})}}Ci=new WeakMap,TE=new WeakMap,Zs=new WeakMap,xl=new WeakMap,Lr=new WeakMap,Js=new WeakMap,si=new WeakMap,is=new WeakMap,Ko=new WeakMap,_l=new WeakMap,qa=new WeakMap,kf=new WeakMap,Cf=new WeakMap,$f=new WeakMap,Zo=new WeakMap,py=new WeakMap,bn=new WeakSet,$q=function(){try{Ve(this,Js,$i(()=>Y(this,xl).call(this,Y(this,Ci))))}catch(t){this.error(t)}},Fq=function(t){const n=Y(this,Zs).failed;n&&Ve(this,is,$i(()=>{n(Y(this,Ci),()=>t,()=>()=>{})}))},Dq=function(){const t=Y(this,Zs).pending;if(t){this.is_pending=!0,Ve(this,si,$i(()=>t(Y(this,Ci))));var n=Ye;tu(()=>{var r=Ve(this,Ko,document.createDocumentFragment()),i=ru();r.append(i),Ve(this,Js,fn(this,bn,K0).call(this,()=>$i(()=>Y(this,xl).call(this,i)))),Y(this,qa)===0&&(Y(this,Ci).before(r),Ve(this,Ko,null),Al(Y(this,si),()=>{Ve(this,si,null)}),fn(this,bn,X0).call(this,n))})}},Zx=function(){var t=Ye;try{if(this.is_pending=this.has_pending_snippet(),Ve(this,qa,0),Ve(this,_l,0),Ve(this,Js,$i(()=>{Y(this,xl).call(this,Y(this,Ci))})),Y(this,qa)>0){var n=Ve(this,Ko,document.createDocumentFragment());qE(Y(this,Js),n);const r=Y(this,Zs).pending;Ve(this,si,$i(()=>r(Y(this,Ci))))}else fn(this,bn,X0).call(this,t)}catch(r){this.error(r)}},X0=function(t){this.is_pending=!1;for(const n of Y(this,Cf))an(n,Vn),t.schedule(n);for(const n of Y(this,$f))an(n,Es),t.schedule(n);Y(this,Cf).clear(),Y(this,$f).clear()},K0=function(t){var n=nt,r=Ze,i=Qt;go(Y(this,Lr)),ji(Y(this,Lr)),Mf(Y(this,Lr).ctx);try{return jl.ensure(),t()}catch(s){return l8(s),null}finally{go(n),ji(r),Mf(i)}},Jx=function(t,n){var r;if(!this.has_pending_snippet()){this.parent&&fn(r=this.parent,bn,Jx).call(r,t,n);return}Ve(this,qa,Y(this,qa)+t),Y(this,qa)===0&&(fn(this,bn,X0).call(this,n),Y(this,si)&&Al(Y(this,si),()=>{Ve(this,si,null)}),Y(this,Ko)&&(Y(this,Ci).before(Y(this,Ko)),Ve(this,Ko,null)))};function Mq(e,t,n,r){const i=Jp()?Qp:PE;var s=e.filter(d=>!d.settled);if(n.length===0&&s.length===0){r(t.map(i));return}var o=nt,a=Rq(),u=s.length===1?s[0].promise:s.length>1?Promise.all(s.map(d=>d.promise)):null;function l(d){a();try{r(d)}catch(h){(o.f&Ii)===0&&Wa(h,o)}$m()}if(n.length===0){u.then(()=>l(t.map(i)));return}var c=m8();function f(){Promise.all(n.map(d=>Tq(d))).then(d=>l([...t.map(i),...d])).catch(d=>Wa(d,o)).finally(()=>c())}u?u.then(()=>{a(),f(),$m()}):f()}function Rq(){var e=nt,t=Ze,n=Qt,r=Ye;return function(s=!0){go(e),ji(t),Mf(n),s&&(e.f&Ii)===0&&(r==null||r.activate(),r==null||r.apply())}}function $m(e=!0){go(null),ji(null),Mf(null),e&&(Ye==null||Ye.deactivate())}function m8(){var e=nt.b,t=Ye,n=e.is_rendered();return e.update_pending_count(1,t),t.increment(n),(r=!1)=>{e.update_pending_count(-1,t),t.decrement(n,r)}}function Qp(e){var t=Rn|Vn,n=Ze!==null&&(Ze.f&Rn)!==0?Ze:null;return nt!==null&&(nt.f|=md),{ctx:Qt,deps:null,effects:null,equals:s8,f:t,fn:e,reactions:null,rv:0,v:In,wv:0,parent:n??nt,ac:null}}function Tq(e,t,n){let r=nt;r===null&&iq();var i=void 0,s=Ul(In),o=!Ze,a=new Map;return Hq(()=>{var h;var u=nt,l=n8();i=l.promise;try{Promise.resolve(e()).then(l.resolve,l.reject).finally($m)}catch(p){l.reject(p),$m()}var c=Ye;if(o){if((u.f&pc)!==0)var f=m8();if(r.b.is_rendered())(h=a.get(c))==null||h.reject(Go),a.delete(c);else{for(const p of a.values())p.reject(Go);a.clear()}a.set(c,l)}const d=(p,g=void 0)=>{if(f){var m=g===Go;f(m)}if(!(g===Go||(u.f&Ii)!==0)){if(c.activate(),g)s.f|=eu,Rf(s,g);else{(s.f&eu)!==0&&(s.f^=eu),Rf(s,p);for(const[y,v]of a){if(a.delete(y),y===c)break;v.reject(Go)}}c.deactivate()}};l.promise.then(d,p=>d(null,p||"unknown"))}),F8(()=>{for(const u of a.values())u.reject(Go)}),new Promise(u=>{function l(c){function f(){c===i?u(s):l(i)}c.then(f,f)}l(i)})}function Me(e){const t=Qp(e);return I8(t),t}function PE(e){const t=Qp(e);return t.equals=a8,t}function Nq(e){var t=e.effects;if(t!==null){e.effects=null;for(var n=0;n0&&!b8&&Pq()}return t}function Pq(){b8=!1;for(const e of Qx)(e.f&An)!==0&&an(e,Es),ng(e)&&Tf(e);Qx.clear()}function x8(e,t=1){var n=w(e),r=t===1?n++:n--;return B(e,n),r}function Vh(e){B(e,e.v+1)}function _8(e,t,n){var r=e.reactions;if(r!==null)for(var i=Jp(),s=r.length,o=0;o{if(Sl===s)return a();var u=Ze,l=Sl;ji(null),D$(s);var c=a();return ji(u),D$(l),c};return r&&n.set("length",le(e.length)),new Proxy(e,{defineProperty(a,u,l){(!("value"in l)||l.configurable===!1||l.enumerable===!1||l.writable===!1)&&fq();var c=n.get(u);return c===void 0?o(()=>{var f=le(l.value);return n.set(u,f),f}):B(c,l.value,!0),!0},deleteProperty(a,u){var l=n.get(u);if(l===void 0){if(u in a){const c=o(()=>le(In));n.set(u,c),Vh(i)}}else B(l,In),Vh(i);return!0},get(a,u,l){var h;if(u===El)return e;var c=n.get(u),f=u in a;if(c===void 0&&(!f||(h=uf(a,u))!=null&&h.writable)&&(c=o(()=>{var p=at(f?a[u]:In),g=le(p);return g}),n.set(u,c)),c!==void 0){var d=w(c);return d===In?void 0:d}return Reflect.get(a,u,l)},getOwnPropertyDescriptor(a,u){var l=Reflect.getOwnPropertyDescriptor(a,u);if(l&&"value"in l){var c=n.get(u);c&&(l.value=w(c))}else if(l===void 0){var f=n.get(u),d=f==null?void 0:f.v;if(f!==void 0&&d!==In)return{enumerable:!0,configurable:!0,value:d,writable:!0}}return l},has(a,u){var d;if(u===El)return!0;var l=n.get(u),c=l!==void 0&&l.v!==In||Reflect.has(a,u);if(l!==void 0||nt!==null&&(!c||(d=uf(a,u))!=null&&d.writable)){l===void 0&&(l=o(()=>{var h=c?at(a[u]):In,p=le(h);return p}),n.set(u,l));var f=w(l);if(f===In)return!1}return c},set(a,u,l,c){var b;var f=n.get(u),d=u in a;if(r&&u==="length")for(var h=l;hle(In)),n.set(h+"",p))}if(f===void 0)(!d||(b=uf(a,u))!=null&&b.writable)&&(f=o(()=>le(void 0)),B(f,at(l)),n.set(u,f));else{d=f.v!==In;var g=o(()=>at(l));B(f,g)}var m=Reflect.getOwnPropertyDescriptor(a,u);if(m!=null&&m.set&&m.set.call(c,l),!d){if(r&&typeof u=="string"){var y=n.get("length"),v=Number(u);Number.isInteger(v)&&v>=y.v&&B(y,v+1)}Vh(i)}return!0},ownKeys(a){w(i);var u=Reflect.ownKeys(a).filter(f=>{var d=n.get(f);return d===void 0||d.v!==In});for(var[l,c]of n)c.v!==In&&!(l in a)&&u.push(l);return u},setPrototypeOf(){dq()}})}var Fm,w8,E8,A8;function Bq(){if(Fm===void 0){Fm=window,w8=/Firefox/.test(navigator.userAgent);var e=Element.prototype,t=Node.prototype,n=Text.prototype;E8=uf(t,"firstChild").get,A8=uf(t,"nextSibling").get,A$(e)&&(e.__click=void 0,e.__className=void 0,e.__attributes=null,e.__style=void 0,e.__e=void 0),A$(n)&&(n.__t=void 0)}}function ru(e=""){return document.createTextNode(e)}function so(e){return E8.call(e)}function eg(e){return A8.call(e)}function P(e,t){return so(e)}function Dt(e,t=!1){{var n=so(e);return n instanceof Comment&&n.data===""?eg(n):n}}function H(e,t=1,n=!1){let r=e;for(;t--;)r=eg(r);return r}function zq(e){e.textContent=""}function S8(){return!1}function k8(e,t,n){return document.createElementNS(t??Q6,e,void 0)}let $$=!1;function jq(){$$||($$=!0,document.addEventListener("reset",e=>{Promise.resolve().then(()=>{var t;if(!e.defaultPrevented)for(const n of e.target.elements)(t=n.__on_r)==null||t.call(n)})},{capture:!0}))}function yy(e){var t=Ze,n=nt;ji(null),go(null);try{return e()}finally{ji(t),go(n)}}function C8(e,t,n,r=n){e.addEventListener(t,()=>yy(n));const i=e.__on_r;i?e.__on_r=()=>{i(),r(!0)}:e.__on_r=()=>r(!0),jq()}function $8(e){nt===null&&(Ze===null&&uq(),aq()),cu&&oq()}function Uq(e,t){var n=t.last;n===null?t.last=t.first=e:(n.next=e,e.prev=n,t.last=e)}function So(e,t){var n=nt;n!==null&&(n.f&hi)!==0&&(e|=hi);var r={ctx:Qt,deps:null,nodes:null,f:e|Vn|Li,first:null,fn:t,last:null,next:null,parent:n,b:n&&n.b,prev:null,teardown:null,wv:0,ac:null},i=r;if((e&Df)!==0)Qc!==null?Qc.push(r):jl.ensure().schedule(r);else if(t!==null){try{Tf(r)}catch(o){throw Wr(r),o}i.deps===null&&i.teardown===null&&i.nodes===null&&i.first===i.last&&(i.f&md)===0&&(i=i.first,(e&$u)!==0&&(e&Bl)!==0&&i!==null&&(i.f|=Bl))}if(i!==null&&(i.parent=n,n!==null&&Uq(i,n),Ze!==null&&(Ze.f&Rn)!==0&&(e&Pl)===0)){var s=Ze;(s.effects??(s.effects=[])).push(i)}return r}function zE(){return Ze!==null&&!hs}function F8(e){const t=So(Zp,null);return an(t,An),t.teardown=e,t}function tn(e){$8();var t=nt.f,n=!Ze&&(t&ws)!==0&&(t&pc)===0;if(n){var r=Qt;(r.e??(r.e=[])).push(e)}else return D8(e)}function D8(e){return So(Df|i8,e)}function qq(e){return $8(),So(Zp|i8,e)}function Wq(e){jl.ensure();const t=So(Pl|md,e);return(n={})=>new Promise(r=>{n.outro?Al(t,()=>{Wr(t),r(void 0)}):(Wr(t),r(void 0))})}function M8(e){return So(Df,e)}function Hq(e){return So(OE|md,e)}function tg(e,t=0){return So(Zp|t,e)}function Ae(e,t=[],n=[],r=[]){Mq(r,t,n,i=>{So(Zp,()=>e(...i.map(w)))})}function vy(e,t=0){var n=So($u|t,e);return n}function $i(e){return So(ws|md,e)}function R8(e){var t=e.teardown;if(t!==null){const n=cu,r=Ze;F$(!0),ji(null);try{t.call(null)}finally{F$(n),ji(r)}}}function jE(e,t=!1){var n=e.first;for(e.first=e.last=null;n!==null;){const i=n.ac;i!==null&&yy(()=>{i.abort(Go)});var r=n.next;(n.f&Pl)!==0?n.parent=null:Wr(n,t),n=r}}function Gq(e){for(var t=e.first;t!==null;){var n=t.next;(t.f&ws)===0&&Wr(t),t=n}}function Wr(e,t=!0){var n=!1;(t||(e.f&eq)!==0)&&e.nodes!==null&&e.nodes.end!==null&&(T8(e.nodes.start,e.nodes.end),n=!0),an(e,Wx),jE(e,t&&!n),cp(e,0);var r=e.nodes&&e.nodes.t;if(r!==null)for(const s of r)s.stop();R8(e),e.f^=Wx,e.f|=Ii;var i=e.parent;i!==null&&i.first!==null&&N8(e),e.next=e.prev=e.teardown=e.ctx=e.deps=e.fn=e.nodes=e.ac=null}function T8(e,t){for(;e!==null;){var n=e===t?null:eg(e);e.remove(),e=n}}function N8(e){var t=e.parent,n=e.prev,r=e.next;n!==null&&(n.next=r),r!==null&&(r.prev=n),t!==null&&(t.first===e&&(t.first=r),t.last===e&&(t.last=n))}function Al(e,t,n=!0){var r=[];O8(e,r,!0);var i=()=>{n&&Wr(e),t&&t()},s=r.length;if(s>0){var o=()=>--s||i();for(var a of r)a.out(o)}else i()}function O8(e,t,n){if((e.f&hi)===0){e.f^=hi;var r=e.nodes&&e.nodes.t;if(r!==null)for(const a of r)(a.is_global||n)&&t.push(a);for(var i=e.first;i!==null;){var s=i.next,o=(i.f&Bl)!==0||(i.f&ws)!==0&&(e.f&$u)!==0;O8(i,t,o?n:!1),i=s}}}function UE(e){L8(e,!0)}function L8(e,t){if((e.f&hi)!==0){e.f^=hi,(e.f&An)===0&&(an(e,Vn),jl.ensure().schedule(e));for(var n=e.first;n!==null;){var r=n.next,i=(n.f&Bl)!==0||(n.f&ws)!==0;L8(n,i?t:!1),n=r}var s=e.nodes&&e.nodes.t;if(s!==null)for(const o of s)(o.is_global||t)&&o.in()}}function qE(e,t){if(e.nodes)for(var n=e.nodes.start,r=e.nodes.end;n!==null;){var i=n===r?null:eg(n);t.append(n),n=i}}let Z0=!1,cu=!1;function F$(e){cu=e}let Ze=null,hs=!1;function ji(e){Ze=e}let nt=null;function go(e){nt=e}let Pi=null;function I8(e){Ze!==null&&(Pi===null?Pi=[e]:Pi.push(e))}let Ir=null,ri=0,Si=null;function Yq(e){Si=e}let P8=1,pl=0,Sl=pl;function D$(e){Sl=e}function B8(){return++P8}function ng(e){var t=e.f;if((t&Vn)!==0)return!0;if(t&Rn&&(e.f&=~zl),(t&Es)!==0){for(var n=e.deps,r=n.length,i=0;ie.wv)return!0}(t&Li)!==0&&Bn===null&&an(e,An)}return!1}function z8(e,t,n=!0){var r=e.reactions;if(r!==null&&!(Pi!==null&&Ff.call(Pi,e)))for(var i=0;i{e.ac.abort(Go)}),e.ac=null);try{e.f|=Hx;var c=e.fn,f=c();e.f|=pc;var d=e.deps,h=Ye==null?void 0:Ye.is_fork;if(Ir!==null){var p;if(h||cp(e,ri),d!==null&&ri>0)for(d.length=ri+Ir.length,p=0;pn==null?void 0:n.call(this,s))}return e.startsWith("pointer")||e.startsWith("touch")||e==="wheel"?tu(()=>{t.addEventListener(e,i,r)}):t.addEventListener(e,i,r),i}function ps(e,t,n,r,i){var s={capture:r,passive:i},o=Xq(e,t,n,s);(t===document.body||t===window||t===document||t instanceof HTMLMediaElement)&&F8(()=>{t.removeEventListener(e,o,s)})}function je(e,t,n){(t[gl]??(t[gl]={}))[e]=n}function wi(e){for(var t=0;t{throw v});throw d}}finally{e[gl]=t,delete e.currentTarget,ji(c),go(f)}}}var K6;const zb=((K6=globalThis==null?void 0:globalThis.window)==null?void 0:K6.trustedTypes)&&globalThis.window.trustedTypes.createPolicy("svelte-trusted-html",{createHTML:e=>e});function Kq(e){return(zb==null?void 0:zb.createHTML(e))??e}function G8(e){var t=k8("template");return t.innerHTML=Kq(e.replaceAll("","")),t.content}function Nf(e,t){var n=nt;n.nodes===null&&(n.nodes={start:e,end:t,a:null,t:null})}function te(e,t){var n=(t&UU)!==0,r=(t&qU)!==0,i,s=!e.startsWith("");return()=>{i===void 0&&(i=G8(s?e:""+e),n||(i=so(i)));var o=r||w8?document.importNode(i,!0):i.cloneNode(!0);if(n){var a=so(o),u=o.lastChild;Nf(a,u)}else Nf(o,o);return o}}function Zq(e,t,n="svg"){var r=!e.startsWith(""),i=`<${n}>${r?e:""+e}`,s;return()=>{if(!s){var o=G8(i),a=so(o);s=so(a)}var u=s.cloneNode(!0);return Nf(u,u),u}}function Y8(e,t){return Zq(e,t,"svg")}function cs(){var e=document.createDocumentFragment(),t=document.createComment(""),n=ru();return e.append(t,n),Nf(t,n),e}function V(e,t){e!==null&&e.before(t)}const Jq=["touchstart","touchmove"];function Qq(e){return Jq.includes(e)}function $e(e,t){var n=t==null?"":typeof t=="object"?`${t}`:t;n!==(e.__t??(e.__t=e.nodeValue))&&(e.__t=n,e.nodeValue=`${n}`)}function eW(e,t){return tW(e,t)}const Qg=new Map;function tW(e,{target:t,anchor:n,props:r={},events:i,context:s,intro:o=!0,transformError:a}){Bq();var u=void 0,l=Wq(()=>{var c=n??t.appendChild(ru());kq(c,{pending:()=>{}},h=>{nn({});var p=Qt;s&&(p.c=s),i&&(r.$$events=i),u=e(h,r)||{},rn()},a);var f=new Set,d=h=>{for(var p=0;p{var m;for(var h of f)for(const y of[t,document]){var p=Qg.get(y),g=p.get(h);--g==0?(y.removeEventListener(h,n_),p.delete(h),p.size===0&&Qg.delete(y)):p.set(h,g)}t_.delete(d),c!==n&&((m=c.parentNode)==null||m.removeChild(c))}});return nW.set(u,l),u}let nW=new WeakMap;var ss,Qs,oi,wl,Xp,Kp,gy;class V8{constructor(t,n=!0){Qi(this,"anchor");tt(this,ss,new Map);tt(this,Qs,new Map);tt(this,oi,new Map);tt(this,wl,new Set);tt(this,Xp,!0);tt(this,Kp,t=>{if(Y(this,ss).has(t)){var n=Y(this,ss).get(t),r=Y(this,Qs).get(n);if(r)UE(r),Y(this,wl).delete(n);else{var i=Y(this,oi).get(n);i&&(Y(this,Qs).set(n,i.effect),Y(this,oi).delete(n),i.fragment.lastChild.remove(),this.anchor.before(i.fragment),r=i.effect)}for(const[s,o]of Y(this,ss)){if(Y(this,ss).delete(s),s===t)break;const a=Y(this,oi).get(o);a&&(Wr(a.effect),Y(this,oi).delete(o))}for(const[s,o]of Y(this,Qs)){if(s===n||Y(this,wl).has(s))continue;const a=()=>{if(Array.from(Y(this,ss).values()).includes(s)){var l=document.createDocumentFragment();qE(o,l),l.append(ru()),Y(this,oi).set(s,{effect:o,fragment:l})}else Wr(o);Y(this,wl).delete(s),Y(this,Qs).delete(s)};Y(this,Xp)||!r?(Y(this,wl).add(s),Al(o,a,!1)):a()}}});tt(this,gy,t=>{Y(this,ss).delete(t);const n=Array.from(Y(this,ss).values());for(const[r,i]of Y(this,oi))n.includes(r)||(Wr(i.effect),Y(this,oi).delete(r))});this.anchor=t,Ve(this,Xp,n)}ensure(t,n){var r=Ye,i=S8();if(n&&!Y(this,Qs).has(t)&&!Y(this,oi).has(t))if(i){var s=document.createDocumentFragment(),o=ru();s.append(o),Y(this,oi).set(t,{effect:$i(()=>n(o)),fragment:s})}else Y(this,Qs).set(t,$i(()=>n(this.anchor)));if(Y(this,ss).set(r,t),i){for(const[a,u]of Y(this,Qs))a===t?r.unskip_effect(u):r.skip_effect(u);for(const[a,u]of Y(this,oi))a===t?r.unskip_effect(u.effect):r.skip_effect(u.effect);r.oncommit(Y(this,Kp)),r.ondiscard(Y(this,gy))}else Y(this,Kp).call(this,r)}}ss=new WeakMap,Qs=new WeakMap,oi=new WeakMap,wl=new WeakMap,Xp=new WeakMap,Kp=new WeakMap,gy=new WeakMap;function R$(e,t,...n){var r=new V8(e);vy(()=>{const i=t()??null;r.ensure(i,i&&(s=>i(s,...n)))},Bl)}function vd(e){Qt===null&&rq(),yd&&Qt.l!==null?rW(Qt).m.push(e):tn(()=>{const t=Fu(e);if(typeof t=="function")return t})}function rW(e){var t=e.l;return t.u??(t.u={a:[],b:[],m:[]})}function _e(e,t,n=!1){var r=new V8(e),i=n?Bl:0;function s(o,a){r.ensure(o,a)}vy(()=>{var o=!1;t((a,u=0)=>{o=!0,s(u,a)}),o||s(-1,null)},i)}function kt(e,t){return t}function iW(e,t,n){for(var r=[],i=t.length,s,o=t.length,a=0;a{if(s){if(s.pending.delete(f),s.done.add(f),s.pending.size===0){var d=e.outrogroups;r_(e,my(s.done)),d.delete(s),d.size===0&&(e.outrogroups=null)}}else o-=1},!1)}if(o===0){var u=r.length===0&&n!==null;if(u){var l=n,c=l.parentNode;zq(c),c.append(l),e.items.clear()}r_(e,t,!u)}else s={pending:new Set(t),done:new Set},(e.outrogroups??(e.outrogroups=new Set)).add(s)}function r_(e,t,n=!0){var r;if(e.pending.size>0){r=new Set;for(const o of e.pending.values())for(const a of o)r.add(e.items.get(a).e)}for(var i=0;i{var b=n();return e8(b)?b:b==null?[]:my(b)}),d,h=new Map,p=!0;function g(b){(v.effect.f&Ii)===0&&(v.pending.delete(b),v.fallback=c,sW(v,d,o,t,r),c!==null&&(d.length===0?(c.f&io)===0?UE(c):(c.f^=io,bh(c,null,o)):Al(c,()=>{c=null})))}function m(b){v.pending.delete(b)}var y=vy(()=>{d=w(f);for(var b=d.length,x=new Set,_=Ye,A=S8(),E=0;Es(o)):(c=$i(()=>s(T$??(T$=ru()))),c.f|=io)),b>x.size&&sq(),!p)if(h.set(_,x),A){for(const[D,M]of a)x.has(D)||_.skip_effect(M.e);_.oncommit(g),_.ondiscard(m)}else g(_);w(f)}),v={effect:y,items:a,pending:h,outrogroups:null,fallback:c};p=!1}function Yd(e){for(;e!==null&&(e.f&ws)===0;)e=e.next;return e}function sW(e,t,n,r,i){var $,D,M,R,F,C,T,O,N;var s=(r&OU)!==0,o=t.length,a=e.items,u=Yd(e.effect.first),l,c=null,f,d=[],h=[],p,g,m,y;if(s)for(y=0;y0){var k=(r&J6)!==0&&o===0?n:null;if(s){for(y=0;y{var L,z;if(f!==void 0)for(m of f)(z=(L=m.nodes)==null?void 0:L.a)==null||z.apply()})}function oW(e,t,n,r,i,s,o,a){var u=(o&TU)!==0?(o&LU)===0?Iq(n,!1,!1):Ul(n):null,l=(o&NU)!==0?Ul(i):null;return{v:u,i:l,e:$i(()=>(s(t,u??n,l??i,a),()=>{e.delete(r)}))}}function bh(e,t,n){if(e.nodes)for(var r=e.nodes.start,i=e.nodes.end,s=t&&(t.f&io)===0?t.nodes.start:n;r!==null;){var o=eg(r);if(s.before(r),r===i)return;r=o}}function Ma(e,t,n){t===null?e.effect.first=n:t.next=n,n===null?e.effect.last=t:n.prev=t}function aW(e,t,n=!1,r=!1,i=!1,s=!1){var o=e,a="";if(n)var u=e;Ae(()=>{var l=nt;if(a!==(a=t()??"")){if(n){l.nodes=null,u.innerHTML=a,a!==""&&Nf(so(u),u.lastChild);return}if(l.nodes!==null&&(T8(l.nodes.start,l.nodes.end),l.nodes=null),a!==""){var c=r?WU:i?HU:void 0,f=k8(r?"svg":i?"math":"template",c);f.innerHTML=a;var d=r||i?f:f.content;if(Nf(so(d),d.lastChild),r||i)for(;so(d);)o.before(so(d));else o.before(d)}}})}function uW(e,t,n){M8(()=>{var r=Fu(()=>t(e,n==null?void 0:n())||{});if(n&&(r!=null&&r.update)){var i=!1,s={};tg(()=>{var o=n();W8(o),i&&o8(s,o)&&(s=o,r.update(o))}),i=!0}if(r!=null&&r.destroy)return()=>r.destroy()})}const N$=[...` +\r\f \v\uFEFF`];function lW(e,t,n){var r=e==null?"":""+e;if(n){for(var i of Object.keys(n))if(n[i])r=r?r+" "+i:i;else if(r.length)for(var s=i.length,o=0;(o=r.indexOf(i,o))>=0;){var a=o+s;(o===0||N$.includes(r[o-1]))&&(a===r.length||N$.includes(r[a]))?r=(o===0?"":r.substring(0,o))+r.substring(a+1):o=a}}return r===""?null:r}function O$(e,t=!1){var n=t?" !important;":";",r="";for(var i of Object.keys(e)){var s=e[i];s!=null&&s!==""&&(r+=" "+i+": "+s+n)}return r}function jb(e){return e[0]!=="-"||e[1]!=="-"?e.toLowerCase():e}function cW(e,t){if(t){var n="",r,i;if(Array.isArray(t)?(r=t[0],i=t[1]):r=t,e){e=String(e).replaceAll(/\s*\/\*.*?\*\/\s*/g,"").trim();var s=!1,o=0,a=!1,u=[];r&&u.push(...Object.keys(r).map(jb)),i&&u.push(...Object.keys(i).map(jb));var l=0,c=-1;const g=e.length;for(var f=0;f{var s=i?e.defaultValue:e.value;if(s=qb(e)?Wb(s):s,n(s),Ye!==null&&r.add(Ye),await Di(),s!==(s=t())){var o=e.selectionStart,a=e.selectionEnd,u=e.value.length;if(e.value=s??"",a!==null){var l=e.value.length;o===a&&a===u&&l>u?(e.selectionStart=l,e.selectionEnd=l):(e.selectionStart=o,e.selectionEnd=Math.min(a,l))}}}),Fu(t)==null&&e.value&&(n(qb(e)?Wb(e.value):e.value),Ye!==null&&r.add(Ye)),tg(()=>{var i=t();if(e===document.activeElement){var s=Ye;if(r.has(s))return}qb(e)&&i===Wb(e.value)||e.type==="date"&&!i&&!e.value||i!==e.value&&(e.value=i??"")})}function pW(e,t,n=t){C8(e,"change",r=>{var i=r?e.defaultChecked:e.checked;n(i)}),Fu(t)==null&&n(e.checked),tg(()=>{var r=t();e.checked=!!r})}function qb(e){var t=e.type;return t==="number"||t==="range"}function Wb(e){return e===""?null:+e}function I$(e,t){return e===t||(e==null?void 0:e[El])===t}function gs(e={},t,n,r){var i=Qt.r,s=nt;return M8(()=>{var o,a;return tg(()=>{o=a,a=[],Fu(()=>{e!==n(...a)&&(t(e,...a),o&&I$(n(...o),e)&&t(null,...o))})}),()=>{let u=s;for(;u!==i&&u.parent!==null&&u.parent.f&Wx;)u=u.parent;const l=()=>{a&&I$(n(...a),e)&&t(null,...a)},c=u.teardown;u.teardown=()=>{l(),c==null||c()}}}),e}function gW(e=!1){const t=Qt,n=t.l.u;if(!n)return;let r=()=>W8(t.s);if(e){let i=0,s={};const o=Qp(()=>{let a=!1;const u=t.s;for(const l in u)u[l]!==s[l]&&(s[l]=u[l],a=!0);return a&&i++,i});r=()=>w(o)}n.b.length&&qq(()=>{P$(t,r),Ux(n.b)}),tn(()=>{const i=Fu(()=>n.m.map(JU));return()=>{for(const s of i)typeof s=="function"&&s()}}),n.a.length&&tn(()=>{P$(t,r),Ux(n.a)})}function P$(e,t){if(e.l.s)for(const n of e.l.s)w(n);t()}function re(e,t,n,r){var b;var i=!yd||(n&PU)!==0,s=(n&zU)!==0,o=(n&jU)!==0,a=r,u=!0,l=()=>(u&&(u=!1,a=o?Fu(r):r),a);let c;if(s){var f=El in e||tq in e;c=((b=uf(e,t))==null?void 0:b.set)??(f&&t in e?x=>e[t]=x:void 0)}var d,h=!1;s?[d,h]=xq(()=>e[t]):d=e[t],d===void 0&&r!==void 0&&(d=l(),c&&(i&&cq(),c(d)));var p;if(i?p=()=>{var x=e[t];return x===void 0?l():(u=!0,x)}:p=()=>{var x=e[t];return x!==void 0&&(a=void 0),x===void 0?a:x},i&&(n&BU)===0)return p;if(c){var g=e.$$legacy;return(function(x,_){return arguments.length>0?((!i||!_||g||h)&&c(_?p():x),x):p()})}var m=!1,y=((n&IU)!==0?Qp:PE)(()=>(m=!1,p()));s&&w(y);var v=nt;return(function(x,_){if(arguments.length>0){const A=_?w(y):i&&s?at(x):x;return B(y,A),m=!0,a!==void 0&&(a=A),x}return cu&&m||(v.f&Ii)!==0?y.v:w(y)})}var mW=te(""),yW=te('');function vW(e,t){nn(t,!0);let n=re(t,"currentPage",3,"metrics");const r=[{id:"metrics",label:"Metrics"},{id:"system",label:"System Metrics"},{id:"media",label:"Media & Tables"},{id:"reports",label:"Alerts & Reports"},{id:"runs",label:"Runs"},{id:"files",label:"Files"}];function i(a){var u;(u=t.onNavigate)==null||u.call(t,a)}var s=yW(),o=H(P(s),2);Ct(o,21,()=>r,kt,(a,u)=>{var l=mW();let c;var f=P(l);Ae(()=>{c=zt(l,1,"nav-link svelte-d8j1hi",null,c,{active:n()===w(u).id}),$e(f,w(u).label)}),je("click",l,()=>i(w(u).id)),V(a,l)}),V(e,s),rn()}wi(["click"]);var bW=te(''),xW=te('
');function _W(e,t){nn(t,!0);let n=re(t,"choices",19,()=>[]),r=re(t,"selected",31,()=>at([])),i=re(t,"colors",19,()=>[]),s=re(t,"ontoggle",3,null);function o(u){var l;r().includes(u)?r(r().filter(c=>c!==u)):r([...r(),u]),(l=s())==null||l()}var a=xW();Ct(a,21,n,kt,(u,l,c)=>{var f=bW(),d=P(f),h=H(d,2),p=H(h,2),g=P(p);Ae(m=>{fp(d,m),ql(h,`background: ${(i()[c]||"#999")??""}`),jt(p,"title",w(l)),$e(g,w(l))},[()=>r().includes(w(l))]),je("change",d,()=>o(w(l))),V(u,f)}),V(e,a),rn()}wi(["change"]);var wW=te(' '),EW=te(' '),AW=te('
  • '),SW=te('
      '),kW=te('');function B$(e,t){nn(t,!0);let n=re(t,"label",3,"Dropdown"),r=re(t,"info",3,""),i=re(t,"value",15,null),s=re(t,"choices",19,()=>[]),o=re(t,"filterable",3,!0),a=re(t,"showLabel",3,!0),u,l,c=le(!1),f=le(""),d=le(null),h=le(at([])),p=le(0),g=le(null),m=le(null),y=le(300),v=Me(()=>i()!==null?s().indexOf(i()):-1);tn(()=>{i()!==null&&s().includes(i())?B(f,i(),!0):B(f,"")}),tn(()=>{B(h,s().map((z,U)=>U),!0)});function b(z){if(!z)return s().map((Q,de)=>de);const U=z.toLowerCase();return s().map((Q,de)=>Q.toLowerCase().includes(U)?de:-1).filter(Q=>Q>=0)}function x(){var z;if(B(h,s().map((U,Q)=>Q),!0),B(c,!0),u){const U=(z=u.closest(".wrap"))==null?void 0:z.getBoundingClientRect();if(U){B(p,U.width,!0);const Q=window.innerHeight-U.bottom,de=U.top;Q>=200||Q>de?(B(g,`${U.bottom}px`),B(m,null),B(y,Q-16)):(B(m,`${window.innerHeight-U.top}px`),B(g,null),B(y,de-16))}}}function _(){s().includes(w(f))?i(w(f)):i()!==null?B(f,i(),!0):B(f,""),B(c,!1),B(d,null),B(h,s().map((z,U)=>U),!0)}function A(z){const U=parseInt(z);isNaN(U)||(i(s()[U]),B(f,s()[U],!0),B(c,!1),B(d,null),u==null||u.blur())}async function E(z){if(await Di(),B(h,b(w(f)),!0),w(h).length>0&&w(d)===null&&B(d,w(h)[0],!0),z.key==="ArrowDown")if(z.preventDefault(),w(d)===null)B(d,w(h)[0]??null,!0);else{const U=w(h).indexOf(w(d));U0&&B(d,w(h)[U-1],!0)}}else z.key==="Enter"?w(d)!==null&&A(w(d)):z.key==="Escape"&&(B(c,!1),u==null||u.blur())}var S=kW(),k=P(S);{var $=z=>{var U=wW(),Q=P(U);Ae(()=>$e(Q,n())),V(z,U)};_e(k,z=>{a()&&z($)})}var D=H(k,2);{var M=z=>{var U=EW(),Q=P(U);Ae(()=>$e(Q,r())),V(z,U)};_e(D,z=>{r()&&z(M)})}var R=H(D,2);let F;var C=P(R),T=P(C),O=P(T);gs(O,z=>u=z,()=>u);var N=H(R,2);{var L=z=>{var U=SW(),Q=P(U);let de;Ct(Q,21,()=>w(h),kt,(we,ne)=>{var Ee=AW();let Ke;var fe=P(Ee);let I;var q=H(fe);Ae(()=>{Ke=zt(Ee,1,"item svelte-kgylqb",null,Ke,{selected:w(ne)===w(v),active:w(ne)===w(d)}),jt(Ee,"data-index",w(ne)),jt(Ee,"aria-selected",w(ne)===w(v)),I=zt(fe,1,"check-mark svelte-kgylqb",null,I,{hide:w(ne)!==w(v)}),$e(q,` ${s()[w(ne)]??""}`)}),V(we,Ee)}),gs(Q,we=>l=we,()=>l),Ae(()=>de=ql(Q,"",de,{top:w(g),bottom:w(m),"max-height":`${w(y)??""}px`,width:`${w(p)??""}px`})),je("mousedown",Q,we=>{var Ee;we.preventDefault();const ne=(Ee=we.target.closest("li"))==null?void 0:Ee.dataset.index;ne!==void 0&&A(ne)}),V(z,U)};_e(N,z=>{w(c)&&z(L)})}Ae(()=>{F=zt(R,1,"wrap svelte-kgylqb",null,F,{focused:w(c)}),jt(O,"aria-label",n()),O.readOnly=!o(),jt(O,"placeholder",i()===null?"Select...":"")}),je("keydown",O,E),ps("blur",O,_),ps("focus",O,x),by(O,()=>w(f),z=>B(f,z)),V(e,S),rn()}wi(["keydown","mousedown"]);var CW=te(' '),$W=te('');function e0(e,t){nn(t,!0);let n=re(t,"label",3,""),r=re(t,"checked",15,!1),i=re(t,"showLabel",3,!0);function s(c){r(c.currentTarget.checked)}var o=$W(),a=P(o),u=H(a,2);{var l=c=>{var f=CW(),d=P(f);Ae(()=>$e(d,n())),V(c,f)};_e(u,c=>{i()&&n()&&c(l)})}je("input",a,s),pW(a,r),V(e,o),rn()}wi(["input"]);var FW=te(' '),DW=te(' '),MW=te('
      ');function RW(e,t){nn(t,!0);let n=re(t,"label",3,"Slider"),r=re(t,"info",3,""),i=re(t,"value",15,0),s=re(t,"min",3,0),o=re(t,"max",3,100),a=re(t,"step",3,1),u=re(t,"showLabel",3,!0),l,c=Me(()=>i()>o()?100:i(){l&&l.style.setProperty("--range_progress",`${w(c)}%`)});var f=MW(),d=P(f),h=P(d);{var p=E=>{var S=FW(),k=P(S);Ae(()=>$e(k,n())),V(E,S)};_e(h,E=>{u()&&E(p)})}var g=H(d,2);{var m=E=>{var S=DW(),k=P(S);Ae(()=>$e(k,r())),V(E,S)};_e(g,E=>{r()&&E(m)})}var y=H(g,2),v=P(y),b=P(v),x=H(v,2);gs(x,E=>l=E,()=>l);var _=H(x,2),A=P(_);Ae(()=>{$e(b,s()),jt(x,"min",s()),jt(x,"max",o()),jt(x,"step",a()),$e(A,o())}),by(x,i),V(e,f),rn()}var TW=te(' '),NW=te(' '),OW=te('
      ');function z$(e,t){nn(t,!0);let n=re(t,"label",3,""),r=re(t,"info",3,""),i=re(t,"value",15,""),s=re(t,"placeholder",3,""),o=re(t,"showLabel",3,!0);var a=OW(),u=P(a);{var l=p=>{var g=TW(),m=P(g);Ae(()=>$e(m,n())),V(p,g)};_e(u,p=>{o()&&n()&&p(l)})}var c=H(u,2);{var f=p=>{var g=NW(),m=P(g);Ae(()=>$e(m,r())),V(p,g)};_e(c,p=>{r()&&p(f)})}var d=H(c,2),h=P(d);Ae(()=>jt(h,"placeholder",s())),by(h,i),V(e,a),rn()}const LW=["#A8769B","#E89957","#3B82F6","#10B981","#EF4444","#8B5CF6","#14B8A6","#F59E0B","#EC4899","#06B6D4"];let i_=LW;function IW(e){Array.isArray(e)&&e.length>0&&(i_=e)}function K8(e){return i_[e%i_.length]}function xy(e){const t={};return e.forEach((n,r)=>{t[n]=K8(r)}),t}const j$={"--neutral-50":"#fafafa","--neutral-100":"#f4f4f5","--neutral-200":"#e4e4e7","--neutral-300":"#d4d4d8","--neutral-400":"#bbbbc2","--neutral-500":"#71717a","--neutral-600":"#52525b","--neutral-700":"#3f3f46","--neutral-800":"#27272a","--neutral-900":"#18181b","--neutral-950":"#0f0f11","--background-fill-primary":"#0f0f11","--background-fill-secondary":"#18181b","--body-text-color":"#f4f4f5","--body-text-color-subdued":"#bbbbc2","--border-color-primary":"#3f3f46","--color-accent":"#f97316","--color-accent-soft":"#3f3f46","--input-background-fill":"#27272a","--input-background-fill-focus":"#f97316","--input-border-color":"#3f3f46","--input-border-color-focus":"#3f3f46","--input-placeholder-color":"#71717a","--input-shadow":"none","--input-shadow-focus":"none","--checkbox-background-color":"#27272a","--checkbox-background-color-focus":"#27272a","--checkbox-background-color-hover":"#27272a","--checkbox-background-color-selected":"#f97316","--checkbox-border-color":"#3f3f46","--checkbox-border-color-focus":"#f97316","--checkbox-border-color-hover":"#52525b","--checkbox-border-color-selected":"#f97316","--table-even-background-fill":"#0f0f11","--table-odd-background-fill":"#18181b","--slider-color":"#f97316","--shadow-drop":"rgba(0,0,0,0.15) 0px 1px 2px 0px","--shadow-drop-lg":"0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.2)","--shadow-inset":"rgba(0,0,0,0.15) 0px 2px 4px 0px inset","--block-title-text-color":"#bbbbc2","--block-info-text-color":"#71717a","--primary-50":"#3f3f46"};function PW(e){const t=document.documentElement;e==="dark"?(t.dataset.theme="dark",Object.entries(j$).forEach(([n,r])=>{t.style.setProperty(n,r)})):(delete t.dataset.theme,Object.keys(j$).forEach(n=>{t.style.removeProperty(n)}))}function Z8(){return document.documentElement.dataset.theme==="dark"}function J8(){return window.matchMedia&&window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"default"}var BW=Y8(''),zW=Y8(''),jW=te('
      ',1),UW=te('
      ',1),qW=te('
      ',1),WW=te(''),HW=te('

      Signed in, but this account does not have write access to this Space.

      '),GW=te('

      Required to delete or rename runs (Space owner or collaborator with write access).

      ',1),YW=te(''),VW=te(''),XW=te(''),KW=te('
      ');function ZW(e,t){nn(t,!0);let n=re(t,"open",15,!0),r=re(t,"variant",3,"full"),i=re(t,"currentPage",3,"metrics"),s=re(t,"projects",19,()=>[]),o=re(t,"selectedProject",15,null),a=re(t,"runs",19,()=>[]),u=re(t,"selectedRuns",31,()=>at([])),l=re(t,"smoothing",15,10),c=re(t,"xAxis",15,"step"),f=re(t,"logScaleX",15,!1),d=re(t,"logScaleY",15,!1),h=re(t,"metricFilter",15,""),p=re(t,"realtimeEnabled",15,!0),g=re(t,"showHeaders",15,!0),m=re(t,"filterText",15,""),y=re(t,"metricColumns",19,()=>[]),v=re(t,"spacesMode",3,!1),b=re(t,"runMutationAllowed",3,!0),x=re(t,"mutationAuth",3,"local"),_=re(t,"readOnlySource",3,null),A=re(t,"projectLocked",3,!1),E=re(t,"logoUrls",19,()=>({light:"/static/trackio/trackio_logo_type_light_transparent.png",dark:"/static/trackio/trackio_logo_type_dark_transparent.png"})),S=le(0);vd(()=>{const ne=()=>{x8(S)};return window.addEventListener("popstate",ne),()=>window.removeEventListener("popstate",ne)});let k=Me(()=>(w(S),`${window.location.origin}/oauth/hf/start`)),$=Me(()=>["step","time",...y()]);function D(){n(!n())}function M(ne,Ee){return ne.indeterminate=Ee,{update(Ke){ne.indeterminate=Ke}}}let R=Me(()=>m()?a().filter(ne=>ne.toLowerCase().includes(m().toLowerCase())):a()),F=Me(()=>xy(a())),C=le(!1);function T(){B(C,!w(C)),w(C)&&w(R).length>0?u([w(R)[w(R).length-1]]):w(C)||u([...w(R)])}var O=KW();let N;var L=P(O),z=P(L);{var U=ne=>{var Ee=BW();V(ne,Ee)},Q=ne=>{var Ee=zW();V(ne,Ee)};_e(z,ne=>{n()?ne(U):ne(Q,-1)})}var de=H(L,2);{var we=ne=>{var Ee=XW(),Ke=P(Ee),fe=P(Ke),I=P(fe),q=H(fe,2),se=P(q);{var W=Ge=>{var j=jW(),J=H(Dt(j),2),De=P(J);Ae(()=>$e(De,o()??"—")),V(Ge,j)},ve=Ge=>{B$(Ge,{label:"Project",get choices(){return s()},filterable:!0,get value(){return o()},set value(j){o(j)}})};_e(se,Ge=>{A()?Ge(W):Ge(ve,-1)})}var xe=H(q,2);{var Fe=Ge=>{var j=qW(),J=Dt(j),De=P(J),Pe=P(De),Le=P(Pe);uW(Le,(Rt,Tt)=>M==null?void 0:M(Rt,Tt),()=>u().length>0&&u().lengthw(R).map(Tt=>w(F)[Tt]??K8(Math.max(0,a().indexOf(Tt)))));_W(wn,{get choices(){return w(R)},get colors(){return w(Rt)},ontoggle:()=>{B(C,!1)},get selected(){return u()},set selected(Tt){u(Tt)}})}var Zn=H(J,2);{var Wt=Rt=>{var Tt=UW(),ti=H(Dt(Tt),2),hn=P(ti);e0(hn,{label:"Refresh metrics realtime",get checked(){return p()},set checked(Ln){p(Ln)}});var Pt=H(hn,2);e0(Pt,{label:"Show section headers",get checked(){return g()},set checked(Ln){g(Ln)}});var ni=H(ti,2),zs=P(ni);RW(zs,{label:"Smoothing Factor (0 = no smoothing)",min:0,max:20,step:1,get value(){return l()},set value(Ln){l(Ln)}});var zo=H(ni,2),Da=P(zo);B$(Da,{label:"X-axis",get choices(){return w($)},filterable:!1,get value(){return c()},set value(Ln){c(Ln)}});var Nr=H(Da,2);e0(Nr,{label:"Log scale X-axis",get checked(){return f()},set checked(Ln){f(Ln)}});var Jn=H(Nr,2);e0(Jn,{label:"Log scale Y-axis",get checked(){return d()},set checked(Ln){d(Ln)}});var Lb=H(zo,2),Ib=P(Lb);z$(Ib,{label:"Metric Filter",info:"Filter metrics using regex patterns. Leave empty to show all metrics.",placeholder:"e.g., loss|ndcg@10|gpu",get value(){return h()},set value(Ln){h(Ln)}}),V(Rt,Tt)};_e(Zn,Rt=>{(i()==="metrics"||i()==="system")&&Rt(Wt)})}Ae(()=>{fp(Le,u().length===w(R).length&&w(R).length>0),$e(Ft,`Runs (${w(R).length??""})`),fp(qe,w(C))}),je("change",Le,()=>{u().length===w(R).length?u([]):u([...w(R)]),B(C,!1)}),je("change",qe,T),V(Ge,j)};_e(xe,Ge=>{r()==="full"&&Ge(Fe)})}var ze=H(Ke,2);{var ot=Ge=>{var j=WW(),J=H(P(j),2),De=P(J);Ae(()=>{jt(J,"href",_().url),$e(De,_().url)}),V(Ge,j)},It=Ge=>{var j=YW(),J=P(j);{var De=Le=>{var et=HW();V(Le,et)},Pe=Le=>{var et=GW(),Ft=Dt(et);Ae(()=>jt(Ft,"href",w(k))),V(Le,et)};_e(J,Le=>{x()==="oauth_insufficient"?Le(De):Le(Pe,-1)})}V(Ge,j)},sn=Ge=>{var j=VW(),J=H(P(j),2);je("click",J,()=>{sessionStorage.removeItem("trackio_oauth_session")}),V(Ge,j)};_e(ze,Ge=>{_()?Ge(ot):v()&&!b()?Ge(It,1):v()&&b()&&x()==="oauth"&&Ge(sn,2)})}Ae(Ge=>jt(I,"src",Ge),[()=>Z8()?E().dark:E().light]),V(ne,Ee)};_e(de,ne=>{n()&&ne(we)})}Ae(()=>N=zt(O,1,"sidebar svelte-181dlmc",null,N,{collapsed:!n()})),je("click",L,D),V(e,O),rn()}wi(["click","change"]);var JW=te('
      '),QW=te('
      '),eH=te('
      '),tH=te('
      '),nH=te('
      ');function rH(e,t){nn(t,!0);let n=re(t,"alerts",19,()=>[]);const r={info:"🔵",warn:"🟡",error:"🔴"};let i=le(at({})),s=le(null),o=le(!1),a=Me(()=>w(s)?n().filter(d=>d.level===w(s)):n());function u(d){B(i,{...w(i),[d]:!w(i)[d]},!0)}var l=cs(),c=Dt(l);{var f=d=>{var h=nH();let p;var g=P(h),m=P(g),y=P(m),v=H(m,2);{var b=S=>{var k=JW(),$=P(k);let D;var M=H($,2);let R;var F=H(M,2);let C;var T=H(F,2);let O;Ae(()=>{D=zt($,1,"pill svelte-x5aqew",null,D,{active:w(s)===null}),R=zt(M,1,"pill svelte-x5aqew",null,R,{active:w(s)==="info"}),C=zt(F,1,"pill svelte-x5aqew",null,C,{active:w(s)==="warn"}),O=zt(T,1,"pill svelte-x5aqew",null,O,{active:w(s)==="error"})}),je("click",k,N=>N.stopPropagation()),je("click",$,()=>B(s,null)),je("click",M,()=>B(s,"info")),je("click",F,()=>B(s,"warn")),je("click",T,()=>B(s,"error")),V(S,k)};_e(v,S=>{w(o)||S(b)})}var x=H(v,2);let _;var A=H(g,2);{var E=S=>{var k=tH();Ct(k,21,()=>w(a),kt,($,D,M)=>{var R=eH();let F;var C=P(R),T=P(C),O=P(T),N=H(T,2),L=P(N),z=H(N,2),U=P(z),Q=H(C,2);{var de=we=>{var ne=QW(),Ee=P(ne);Ae(()=>$e(Ee,w(D).text)),V(we,ne)};_e(Q,we=>{w(i)[M]&&w(D).text&&we(de)})}Ae(()=>{F=zt(R,1,"alert-item svelte-x5aqew",null,F,{expanded:w(i)[M]}),$e(O,r[w(D).level]||""),$e(L,w(D).title),$e(U,w(D).meta||"")}),je("click",C,()=>u(M)),V($,R)}),V(S,k)};_e(A,S=>{w(o)||S(E)})}Ae(()=>{p=zt(h,1,"alert-panel svelte-x5aqew",null,p,{collapsed:w(o)}),$e(y,`Alerts (${n().length??""})`),_=zt(x,0,"collapse-icon svelte-x5aqew",null,_,{rotated:w(o)})}),je("click",g,()=>B(o,!w(o))),je("keydown",g,S=>S.key==="Enter"&&B(o,!w(o))),V(d,h)};_e(c,d=>{n().length>0&&d(f)})}V(e,l),rn()}wi(["click","keydown"]);function U$(){const e=window.location.pathname.replace(/\/+$/,"")||"/";switch(e==="/"?"":e.replace(/^\//,"").split("/")[0]){case"":case"metrics":return"metrics";case"system":return"system";case"media":return"media";case"reports":return"reports";case"runs":return"runs";case"run":return"run-detail";case"files":return"files";default:return"metrics"}}function Q8(e){const t=new URLSearchParams(window.location.search),r={metrics:"/",system:"/system",media:"/media",reports:"/reports",runs:"/runs","run-detail":"/run",files:"/files"}[e]||"/",i=t.toString(),s=i?`${r}?${i}`:r;window.history.pushState({},"",s),window.dispatchEvent(new PopStateEvent("popstate"))}function Ys(e){return new URLSearchParams(window.location.search).get(e)}function iH(e,t){const n=new URLSearchParams(window.location.search);t!=null&&t!==""?n.set(e,t):n.delete(e);const r=n.toString(),i=r?`${window.location.pathname}?${r}`:window.location.pathname;window.history.replaceState({},"",i)}const sH=/("(?:[^\\"]|\\.)*")|[:,]/g;function Hb(e,t={}){const n=JSON.stringify([1],void 0,t.indent===void 0?2:t.indent).slice(2,-3),r=n===""?1/0:t.maxLength===void 0?80:t.maxLength;let{replacer:i}=t;return(function s(o,a,u){o&&typeof o.toJSON=="function"&&(o=o.toJSON());const l=JSON.stringify(o,i);if(l===void 0)return l;const c=r-a.length-u;if(l.length<=c){const f=l.replace(sH,(d,h)=>h||`${d} `);if(f.length<=c)return f}if(i!=null&&(o=JSON.parse(l),i=void 0),typeof o=="object"&&o!==null){const f=a+n,d=[];let h=0,p,g;if(Array.isArray(o)){p="[",g="]";const{length:m}=o;for(;h0)return[p,n+d.join(`, +${f}`),g].join(` +${a}`)}return l})(e,"",0)}function Qr(e,t,n){return e.fields=t||[],e.fname=n,e}function en(e){return e==null?null:e.fname}function ar(e){return e==null?null:e.fields}function eR(e){return e.length===1?oH(e[0]):aH(e)}const oH=e=>function(t){return t[e]},aH=e=>{const t=e.length;return function(n){for(let r=0;ro?l():o=a+1:u==="["?(a>o&&l(),i=o=a+1):u==="]"&&(i||X("Access path missing open bracket: "+e),i>0&&l(),i=0,o=a+1)}return i&&X("Access path missing closing bracket: "+e),r&&X("Access path missing closing quote: "+e),a>o&&(a++,l()),t}function Ui(e,t,n){const r=ko(e);return e=r.length===1?r[0]:e,Qr((n&&n.get||eR)(r),[e],t||e)}const rg=Ui("id"),hr=Qr(e=>e,[],"identity"),ja=Qr(()=>0,[],"zero"),bd=Qr(()=>1,[],"one"),yi=Qr(()=>!0,[],"true"),Ta=Qr(()=>!1,[],"false"),WE=new Set(Object.getOwnPropertyNames(Object.prototype));function uH(e,t,n){const r=[t].concat([].slice.call(n));console[e].apply(console,r)}const tR=0,HE=1,GE=2,nR=3,rR=4;function YE(e,t){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:uH,r=e||tR;return{level(i){return arguments.length?(r=+i,this):r},error(){return r>=HE&&n(t||"error","ERROR",arguments),this},warn(){return r>=GE&&n(t||"warn","WARN",arguments),this},info(){return r>=nR&&n(t||"log","INFO",arguments),this},debug(){return r>=rR&&n(t||"log","DEBUG",arguments),this}}}var ee=Array.isArray;function ge(e){return e===Object(e)}const q$=e=>e!=="__proto__";function xd(){for(var e=arguments.length,t=new Array(e),n=0;n{for(const s in i)if(s==="signals")r.signals=lH(r.signals,i.signals);else{const o=s==="legend"?{layout:1}:s==="style"?!0:null;_d(r,s,i[s],o)}return r},{})}function _d(e,t,n,r){if(!q$(t))return;let i,s;if(ge(n)&&!ee(n)){s=ge(e[t])?e[t]:e[t]={};for(i in n)r&&(r===!0||r[i])?_d(s,i,n[i]):q$(i)&&(s[i]=n[i])}else e[t]=n}function lH(e,t){if(e==null)return t;const n={},r=[];function i(s){n[s.name]||(n[s.name]=1,r.push(s))}return t.forEach(i),e.forEach(i),r}function st(e){return e[e.length-1]}function sr(e){return e==null||e===""?null:+e}const iR=e=>t=>e*Math.exp(t),sR=e=>t=>Math.log(e*t),oR=e=>t=>Math.sign(t)*Math.log1p(Math.abs(t/e)),aR=e=>t=>Math.sign(t)*Math.expm1(Math.abs(t))*e,Dm=e=>t=>t<0?-Math.pow(-t,e):Math.pow(t,e);function _y(e,t,n,r){const i=n(e[0]),s=n(st(e)),o=(s-i)*t;return[r(i-o),r(s-o)]}function uR(e,t){return _y(e,t,sr,hr)}function lR(e,t){var n=Math.sign(e[0]);return _y(e,t,sR(n),iR(n))}function cR(e,t,n){return _y(e,t,Dm(n),Dm(1/n))}function fR(e,t,n){return _y(e,t,oR(n),aR(n))}function wy(e,t,n,r,i){const s=r(e[0]),o=r(st(e)),a=t!=null?r(t):(s+o)/2;return[i(a+(s-a)*n),i(a+(o-a)*n)]}function VE(e,t,n){return wy(e,t,n,sr,hr)}function XE(e,t,n){const r=Math.sign(e[0]);return wy(e,t,n,sR(r),iR(r))}function Mm(e,t,n,r){return wy(e,t,n,Dm(r),Dm(1/r))}function KE(e,t,n,r){return wy(e,t,n,oR(r),aR(r))}function dR(e){return 1+~~(new Date(e).getMonth()/3)}function hR(e){return 1+~~(new Date(e).getUTCMonth()/3)}function ye(e){return e!=null?ee(e)?e:[e]:[]}function pR(e,t,n){let r=e[0],i=e[1],s;return i=n-t?[t,n]:[r=Math.min(Math.max(r,t),n-s),r+s]}function He(e){return typeof e=="function"}const cH="descending";function ZE(e,t,n){n=n||{},t=ye(t)||[];const r=[],i=[],s={},o=n.comparator||fH;return ye(e).forEach((a,u)=>{a!=null&&(r.push(t[u]===cH?-1:1),i.push(a=He(a)?a:Ui(a,null,n)),(ar(a)||[]).forEach(l=>s[l]=1))}),i.length===0?null:Qr(o(i,r),Object.keys(s))}const wd=(e,t)=>(et||t==null)&&e!=null?1:(t=t instanceof Date?+t:t,(e=e instanceof Date?+e:e)!==e&&t===t?-1:t!==t&&e===e?1:0),fH=(e,t)=>e.length===1?dH(e[0],t[0]):hH(e,t,e.length),dH=(e,t)=>function(n,r){return wd(e(n),e(r))*t},hH=(e,t,n)=>(t.push(0),function(r,i){let s,o=0,a=-1;for(;o===0&&++ae}function JE(e,t){let n;return r=>{n&&clearTimeout(n),n=setTimeout(()=>(t(r),n=null),e)}}function We(e){for(let t,n,r=1,i=arguments.length;ro&&(o=i))}else{for(i=t(e[n]);no&&(o=i))}return[s,o]}function gR(e,t){const n=e.length;let r=-1,i,s,o,a,u;if(t==null){for(;++r=s){i=o=s;break}if(r===n)return[-1,-1];for(a=u=r;++rs&&(i=s,a=r),o=s){i=o=s;break}if(r===n)return[-1,-1];for(a=u=r;++rs&&(i=s,a=r),o{i.set(s,e[s])}),i}function mR(e,t,n,r,i,s){if(!n&&n!==0)return s;const o=+n;let a=e[0],u=st(e),l;us&&(o=i,i=s,s=o),n=n===void 0||n,r=r===void 0||r,(n?i<=e:ia.replace(/\\(.)/g,"$1")):ye(e));const r=e&&e.length,i=n&&n.get||eR,s=a=>i(t?[a]:ko(a));let o;if(!r)o=function(){return""};else if(r===1){const a=s(e[0]);o=function(u){return""+a(u)}}else{const a=e.map(s);o=function(u){let l=""+a[0](u),c=0;for(;++c{t={},n={},r=0},s=(o,a)=>(++r>e&&(n=t,t={},r=1),t[o]=a);return i(),{clear:i,has:o=>be(t,o)||be(n,o),get:o=>be(t,o)?t[o]:be(n,o)?s(o,n[o]):void 0,set:(o,a)=>be(t,o)?t[o]=a:s(o,a)}}function xR(e,t,n,r){const i=t.length,s=n.length;if(!s)return t;if(!i)return n;const o=r||new t.constructor(i+s);let a=0,u=0,l=0;for(;a0?n[u++]:t[a++];for(;a=0;)n+=e;return n}function _R(e,t,n,r){const i=n||" ",s=e+"",o=t-s.length;return o<=0?s:r==="left"?xh(i,o)+s:r==="center"?xh(i,~~(o/2))+s+xh(i,Math.ceil(o/2)):s+xh(i,o)}function ig(e){return e&&st(e)-e[0]||0}function ce(e){return ee(e)?"["+e.map(ce)+"]":ge(e)||me(e)?JSON.stringify(e).replace("\u2028","\\u2028").replace("\u2029","\\u2029"):e}function tA(e){return e==null||e===""?null:!e||e==="false"||e==="0"?!1:!!e}const gH=e=>ft(e)||iu(e)?e:Date.parse(e);function nA(e,t){return t=t||gH,e==null||e===""?null:t(e)}function rA(e){return e==null||e===""?null:e+""}function As(e){const t={},n=e.length;for(let r=0;r9999?"+"+Or(e,6):Or(e,4)}function vH(e){var t=e.getUTCHours(),n=e.getUTCMinutes(),r=e.getUTCSeconds(),i=e.getUTCMilliseconds();return isNaN(e)?"Invalid Date":yH(e.getUTCFullYear())+"-"+Or(e.getUTCMonth()+1,2)+"-"+Or(e.getUTCDate(),2)+(i?"T"+Or(t,2)+":"+Or(n,2)+":"+Or(r,2)+"."+Or(i,3)+"Z":r?"T"+Or(t,2)+":"+Or(n,2)+":"+Or(r,2)+"Z":n||t?"T"+Or(t,2)+":"+Or(n,2)+"Z":"")}function bH(e){var t=new RegExp('["'+e+` +\r]`),n=e.charCodeAt(0);function r(f,d){var h,p,g=i(f,function(m,y){if(h)return h(m,y-1);p=m,h=d?mH(m,d):ER(m)});return g.columns=p||[],g}function i(f,d){var h=[],p=f.length,g=0,m=0,y,v=p<=0,b=!1;f.charCodeAt(p-1)===Vd&&--p,f.charCodeAt(p-1)===Vb&&--p;function x(){if(v)return Gb;if(b)return b=!1,W$;var A,E=g,S;if(f.charCodeAt(E)===Yb){for(;g++=p?v=!0:(S=f.charCodeAt(g++))===Vd?b=!0:S===Vb&&(b=!0,f.charCodeAt(g)===Vd&&++g),f.slice(E+1,A-1).replace(/""/g,'"')}for(;g1)r=CH(e,t,n);else for(i=0,r=new Array(s=e.arcs.length);it?1:e>=t?0:NaN}function $H(e,t){return e==null||t==null?NaN:te?1:t>=e?0:NaN}function Ad(e){let t,n,r;e.length!==2?(t=oa,n=(a,u)=>oa(e(a),u),r=(a,u)=>e(a)-u):(t=e===oa||e===$H?e:FH,n=e,r=e);function i(a,u,l=0,c=a.length){if(l>>1;n(a[f],u)<0?l=f+1:c=f}while(l>>1;n(a[f],u)<=0?l=f+1:c=f}while(ll&&r(a[f-1],u)>-r(a[f],u)?f-1:f}return{left:i,center:o,right:s}}function FH(){return 0}function SR(e){return e===null?NaN:+e}function*DH(e,t){if(t===void 0)for(let n of e)n!=null&&(n=+n)>=n&&(yield n);else{let n=-1;for(let r of e)(r=t(r,++n,e))!=null&&(r=+r)>=r&&(yield r)}}const kR=Ad(oa),fu=kR.right,MH=kR.left;Ad(SR).center;function RH(e,t){let n=0,r,i=0,s=0;if(t===void 0)for(let o of e)o!=null&&(o=+o)>=o&&(r=o-i,i+=r/++n,s+=r*(o-i));else{let o=-1;for(let a of e)(a=t(a,++o,e))!=null&&(a=+a)>=a&&(r=a-i,i+=r/++n,s+=r*(a-i))}if(n>1)return s/(n-1)}function TH(e,t){const n=RH(e,t);return n&&Math.sqrt(n)}class kr{constructor(){this._partials=new Float64Array(32),this._n=0}add(t){const n=this._partials;let r=0;for(let i=0;i0){for(o=t[--n];n>0&&(r=o,i=t[--n],o=r+i,s=i-(o-r),!s););n>0&&(s<0&&t[n-1]<0||s>0&&t[n-1]>0)&&(i=s*2,r=o+i,i==r-o&&(o=r))}return o}}class Y$ extends Map{constructor(t,n=FR){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:n}}),t!=null)for(const[r,i]of t)this.set(r,i)}get(t){return super.get(s_(this,t))}has(t){return super.has(s_(this,t))}set(t,n){return super.set(CR(this,t),n)}delete(t){return super.delete($R(this,t))}}class Rm extends Set{constructor(t,n=FR){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:n}}),t!=null)for(const r of t)this.add(r)}has(t){return super.has(s_(this,t))}add(t){return super.add(CR(this,t))}delete(t){return super.delete($R(this,t))}}function s_({_intern:e,_key:t},n){const r=t(n);return e.has(r)?e.get(r):n}function CR({_intern:e,_key:t},n){const r=t(n);return e.has(r)?e.get(r):(e.set(r,n),n)}function $R({_intern:e,_key:t},n){const r=t(n);return e.has(r)&&(n=e.get(r),e.delete(r)),n}function FR(e){return e!==null&&typeof e=="object"?e.valueOf():e}function NH(e,t){return Array.from(t,n=>e[n])}function OH(e=oa){if(e===oa)return DR;if(typeof e!="function")throw new TypeError("compare is not a function");return(t,n)=>{const r=e(t,n);return r||r===0?r:(e(n,n)===0)-(e(t,t)===0)}}function DR(e,t){return(e==null||!(e>=e))-(t==null||!(t>=t))||(et?1:0)}const LH=Math.sqrt(50),IH=Math.sqrt(10),PH=Math.sqrt(2);function Tm(e,t,n){const r=(t-e)/Math.max(0,n),i=Math.floor(Math.log10(r)),s=r/Math.pow(10,i),o=s>=LH?10:s>=IH?5:s>=PH?2:1;let a,u,l;return i<0?(l=Math.pow(10,-i)/o,a=Math.round(e*l),u=Math.round(t*l),a/lt&&--u,l=-l):(l=Math.pow(10,i)*o,a=Math.round(e/l),u=Math.round(t/l),a*lt&&--u),u0))return[];if(e===t)return[e];const r=t=i))return[];const a=s-i+1,u=new Array(a);if(r)if(o<0)for(let l=0;l=r)&&(n=r);else{let r=-1;for(let i of e)(i=t(i,++r,e))!=null&&(n=i)&&(n=i)}return n}function u_(e,t){let n;if(t===void 0)for(const r of e)r!=null&&(n>r||n===void 0&&r>=r)&&(n=r);else{let r=-1;for(let i of e)(i=t(i,++r,e))!=null&&(n>i||n===void 0&&i>=i)&&(n=i)}return n}function MR(e,t,n=0,r=1/0,i){if(t=Math.floor(t),n=Math.floor(Math.max(0,n)),r=Math.floor(Math.min(e.length-1,r)),!(n<=t&&t<=r))return e;for(i=i===void 0?DR:OH(i);r>n;){if(r-n>600){const u=r-n+1,l=t-n+1,c=Math.log(u),f=.5*Math.exp(2*c/3),d=.5*Math.sqrt(c*f*(u-f)/u)*(l-u/2<0?-1:1),h=Math.max(n,Math.floor(t-l*f/u+d)),p=Math.min(r,Math.floor(t+(u-l)*f/u+d));MR(e,t,h,p,i)}const s=e[t];let o=n,a=r;for(Xd(e,n,t),i(e[r],s)>0&&Xd(e,n,r);o0;)--a}i(e[n],s)===0?Xd(e,n,a):(++a,Xd(e,a,r)),a<=t&&(n=a+1),t<=a&&(r=a-1)}return e}function Xd(e,t,n){const r=e[t];e[t]=e[n],e[n]=r}function l_(e,t,n){if(e=Float64Array.from(DH(e,n)),!(!(r=e.length)||isNaN(t=+t))){if(t<=0||r<2)return u_(e);if(t>=1)return kl(e);var r,i=(r-1)*t,s=Math.floor(i),o=kl(MR(e,s).subarray(0,s+1)),a=u_(e.subarray(s+1));return o+(a-o)*(i-s)}}function RR(e,t,n=SR){if(!(!(r=e.length)||isNaN(t=+t))){if(t<=0||r<2)return+n(e[0],0,e);if(t>=1)return+n(e[r-1],r-1,e);var r,i=(r-1)*t,s=Math.floor(i),o=+n(e[s],s,e),a=+n(e[s+1],s+1,e);return o+(a-o)*(i-s)}}function BH(e,t){let n=0,r=0;if(t===void 0)for(let i of e)i!=null&&(i=+i)>=i&&(++n,r+=i);else{let i=-1;for(let s of e)(s=t(s,++i,e))!=null&&(s=+s)>=s&&(++n,r+=s)}if(n)return r/n}function TR(e,t){return l_(e,.5,t)}function*zH(e){for(const t of e)yield*t}function NR(e){return Array.from(zH(e))}function ci(e,t,n){e=+e,t=+t,n=(i=arguments.length)<2?(t=e,e=0,1):i<3?1:+n;for(var r=-1,i=Math.max(0,Math.ceil((t-e)/n))|0,s=new Array(i);++r=1e21?e.toLocaleString("en").replace(/,/g,""):e.toString(10)}function Nm(e,t){if(!isFinite(e)||e===0)return null;var n=(e=t?e.toExponential(t-1):e.toExponential()).indexOf("e"),r=e.slice(0,n);return[r.length>1?r[0]+r.slice(2):r,+e.slice(n+1)]}function Of(e){return e=Nm(Math.abs(e)),e?e[1]:NaN}function HH(e,t){return function(n,r){for(var i=n.length,s=[],o=0,a=e[0],u=0;i>0&&a>0&&(u+a+1>r&&(a=Math.max(1,r-u)),s.push(n.substring(i-=a,i+a)),!((u+=a+1)>r));)a=e[o=(o+1)%e.length];return s.reverse().join(t)}}function GH(e){return function(t){return t.replace(/[0-9]/g,function(n){return e[+n]})}}var YH=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function Wl(e){if(!(t=YH.exec(e)))throw new Error("invalid format: "+e);var t;return new iA({fill:t[1],align:t[2],sign:t[3],symbol:t[4],zero:t[5],width:t[6],comma:t[7],precision:t[8]&&t[8].slice(1),trim:t[9],type:t[10]})}Wl.prototype=iA.prototype;function iA(e){this.fill=e.fill===void 0?" ":e.fill+"",this.align=e.align===void 0?">":e.align+"",this.sign=e.sign===void 0?"-":e.sign+"",this.symbol=e.symbol===void 0?"":e.symbol+"",this.zero=!!e.zero,this.width=e.width===void 0?void 0:+e.width,this.comma=!!e.comma,this.precision=e.precision===void 0?void 0:+e.precision,this.trim=!!e.trim,this.type=e.type===void 0?"":e.type+""}iA.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function VH(e){e:for(var t=e.length,n=1,r=-1,i;n0&&(r=0);break}return r>0?e.slice(0,r)+e.slice(i+1):e}var Om;function XH(e,t){var n=Nm(e,t);if(!n)return Om=void 0,e.toPrecision(t);var r=n[0],i=n[1],s=i-(Om=Math.max(-8,Math.min(8,Math.floor(i/3)))*3)+1,o=r.length;return s===o?r:s>o?r+new Array(s-o+1).join("0"):s>0?r.slice(0,s)+"."+r.slice(s):"0."+new Array(1-s).join("0")+Nm(e,Math.max(0,t+s-1))[0]}function V$(e,t){var n=Nm(e,t);if(!n)return e+"";var r=n[0],i=n[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}const X$={"%":(e,t)=>(e*100).toFixed(t),b:e=>Math.round(e).toString(2),c:e=>e+"",d:WH,e:(e,t)=>e.toExponential(t),f:(e,t)=>e.toFixed(t),g:(e,t)=>e.toPrecision(t),o:e=>Math.round(e).toString(8),p:(e,t)=>V$(e*100,t),r:V$,s:XH,X:e=>Math.round(e).toString(16).toUpperCase(),x:e=>Math.round(e).toString(16)};function K$(e){return e}var Z$=Array.prototype.map,J$=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function LR(e){var t=e.grouping===void 0||e.thousands===void 0?K$:HH(Z$.call(e.grouping,Number),e.thousands+""),n=e.currency===void 0?"":e.currency[0]+"",r=e.currency===void 0?"":e.currency[1]+"",i=e.decimal===void 0?".":e.decimal+"",s=e.numerals===void 0?K$:GH(Z$.call(e.numerals,String)),o=e.percent===void 0?"%":e.percent+"",a=e.minus===void 0?"−":e.minus+"",u=e.nan===void 0?"NaN":e.nan+"";function l(f,d){f=Wl(f);var h=f.fill,p=f.align,g=f.sign,m=f.symbol,y=f.zero,v=f.width,b=f.comma,x=f.precision,_=f.trim,A=f.type;A==="n"?(b=!0,A="g"):X$[A]||(x===void 0&&(x=12),_=!0,A="g"),(y||h==="0"&&p==="=")&&(y=!0,h="0",p="=");var E=(d&&d.prefix!==void 0?d.prefix:"")+(m==="$"?n:m==="#"&&/[boxX]/.test(A)?"0"+A.toLowerCase():""),S=(m==="$"?r:/[%p]/.test(A)?o:"")+(d&&d.suffix!==void 0?d.suffix:""),k=X$[A],$=/[defgprs%]/.test(A);x=x===void 0?6:/[gprs]/.test(A)?Math.max(1,Math.min(21,x)):Math.max(0,Math.min(20,x));function D(M){var R=E,F=S,C,T,O;if(A==="c")F=k(M)+F,M="";else{M=+M;var N=M<0||1/M<0;if(M=isNaN(M)?u:k(Math.abs(M),x),_&&(M=VH(M)),N&&+M==0&&g!=="+"&&(N=!1),R=(N?g==="("?g:a:g==="-"||g==="("?"":g)+R,F=(A==="s"&&!isNaN(M)&&Om!==void 0?J$[8+Om/3]:"")+F+(N&&g==="("?")":""),$){for(C=-1,T=M.length;++CO||O>57){F=(O===46?i+M.slice(C+1):M.slice(C))+F,M=M.slice(0,C);break}}}b&&!y&&(M=t(M,1/0));var L=R.length+M.length+F.length,z=L>1)+R+M+F+z.slice(L);break;default:M=z+R+M+F;break}return s(M)}return D.toString=function(){return f+""},D}function c(f,d){var h=Math.max(-8,Math.min(8,Math.floor(Of(d)/3)))*3,p=Math.pow(10,-h),g=l((f=Wl(f),f.type="f",f),{suffix:J$[8+h/3]});return function(m){return g(p*m)}}return{format:l,formatPrefix:c}}var n0,Ey,sA;KH({thousands:",",grouping:[3],currency:["$",""]});function KH(e){return n0=LR(e),Ey=n0.format,sA=n0.formatPrefix,n0}function IR(e){return Math.max(0,-Of(Math.abs(e)))}function PR(e,t){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(Of(t)/3)))*3-Of(Math.abs(e)))}function BR(e,t){return e=Math.abs(e),t=Math.abs(t)-e,Math.max(0,Of(t)-Of(e))+1}const Xb=new Date,Kb=new Date;function xn(e,t,n,r){function i(s){return e(s=arguments.length===0?new Date:new Date(+s)),s}return i.floor=s=>(e(s=new Date(+s)),s),i.ceil=s=>(e(s=new Date(s-1)),t(s,1),e(s),s),i.round=s=>{const o=i(s),a=i.ceil(s);return s-o(t(s=new Date(+s),o==null?1:Math.floor(o)),s),i.range=(s,o,a)=>{const u=[];if(s=i.ceil(s),a=a==null?1:Math.floor(a),!(s0))return u;let l;do u.push(l=new Date(+s)),t(s,a),e(s);while(lxn(o=>{if(o>=o)for(;e(o),!s(o);)o.setTime(o-1)},(o,a)=>{if(o>=o)if(a<0)for(;++a<=0;)for(;t(o,-1),!s(o););else for(;--a>=0;)for(;t(o,1),!s(o););}),n&&(i.count=(s,o)=>(Xb.setTime(+s),Kb.setTime(+o),e(Xb),e(Kb),Math.floor(n(Xb,Kb))),i.every=s=>(s=Math.floor(s),!isFinite(s)||!(s>0)?null:s>1?i.filter(r?o=>r(o)%s===0:o=>i.count(0,o)%s===0):i)),i}const Lf=xn(()=>{},(e,t)=>{e.setTime(+e+t)},(e,t)=>t-e);Lf.every=e=>(e=Math.floor(e),!isFinite(e)||!(e>0)?null:e>1?xn(t=>{t.setTime(Math.floor(t/e)*e)},(t,n)=>{t.setTime(+t+n*e)},(t,n)=>(n-t)/e):Lf);Lf.range;const ea=1e3,Ri=ea*60,ta=Ri*60,ga=ta*24,oA=ga*7,Q$=ga*30,Zb=ga*365,na=xn(e=>{e.setTime(e-e.getMilliseconds())},(e,t)=>{e.setTime(+e+t*ea)},(e,t)=>(t-e)/ea,e=>e.getUTCSeconds());na.range;const Ay=xn(e=>{e.setTime(e-e.getMilliseconds()-e.getSeconds()*ea)},(e,t)=>{e.setTime(+e+t*Ri)},(e,t)=>(t-e)/Ri,e=>e.getMinutes());Ay.range;const Sy=xn(e=>{e.setUTCSeconds(0,0)},(e,t)=>{e.setTime(+e+t*Ri)},(e,t)=>(t-e)/Ri,e=>e.getUTCMinutes());Sy.range;const ky=xn(e=>{e.setTime(e-e.getMilliseconds()-e.getSeconds()*ea-e.getMinutes()*Ri)},(e,t)=>{e.setTime(+e+t*ta)},(e,t)=>(t-e)/ta,e=>e.getHours());ky.range;const Cy=xn(e=>{e.setUTCMinutes(0,0,0)},(e,t)=>{e.setTime(+e+t*ta)},(e,t)=>(t-e)/ta,e=>e.getUTCHours());Cy.range;const aa=xn(e=>e.setHours(0,0,0,0),(e,t)=>e.setDate(e.getDate()+t),(e,t)=>(t-e-(t.getTimezoneOffset()-e.getTimezoneOffset())*Ri)/ga,e=>e.getDate()-1);aa.range;const su=xn(e=>{e.setUTCHours(0,0,0,0)},(e,t)=>{e.setUTCDate(e.getUTCDate()+t)},(e,t)=>(t-e)/ga,e=>e.getUTCDate()-1);su.range;const zR=xn(e=>{e.setUTCHours(0,0,0,0)},(e,t)=>{e.setUTCDate(e.getUTCDate()+t)},(e,t)=>(t-e)/ga,e=>Math.floor(e/ga));zR.range;function gc(e){return xn(t=>{t.setDate(t.getDate()-(t.getDay()+7-e)%7),t.setHours(0,0,0,0)},(t,n)=>{t.setDate(t.getDate()+n*7)},(t,n)=>(n-t-(n.getTimezoneOffset()-t.getTimezoneOffset())*Ri)/oA)}const Sd=gc(0),Lm=gc(1),ZH=gc(2),JH=gc(3),If=gc(4),QH=gc(5),eG=gc(6);Sd.range;Lm.range;ZH.range;JH.range;If.range;QH.range;eG.range;function mc(e){return xn(t=>{t.setUTCDate(t.getUTCDate()-(t.getUTCDay()+7-e)%7),t.setUTCHours(0,0,0,0)},(t,n)=>{t.setUTCDate(t.getUTCDate()+n*7)},(t,n)=>(n-t)/oA)}const kd=mc(0),Im=mc(1),tG=mc(2),nG=mc(3),Pf=mc(4),rG=mc(5),iG=mc(6);kd.range;Im.range;tG.range;nG.range;Pf.range;rG.range;iG.range;const dp=xn(e=>{e.setDate(1),e.setHours(0,0,0,0)},(e,t)=>{e.setMonth(e.getMonth()+t)},(e,t)=>t.getMonth()-e.getMonth()+(t.getFullYear()-e.getFullYear())*12,e=>e.getMonth());dp.range;const hp=xn(e=>{e.setUTCDate(1),e.setUTCHours(0,0,0,0)},(e,t)=>{e.setUTCMonth(e.getUTCMonth()+t)},(e,t)=>t.getUTCMonth()-e.getUTCMonth()+(t.getUTCFullYear()-e.getUTCFullYear())*12,e=>e.getUTCMonth());hp.range;const yo=xn(e=>{e.setMonth(0,1),e.setHours(0,0,0,0)},(e,t)=>{e.setFullYear(e.getFullYear()+t)},(e,t)=>t.getFullYear()-e.getFullYear(),e=>e.getFullYear());yo.every=e=>!isFinite(e=Math.floor(e))||!(e>0)?null:xn(t=>{t.setFullYear(Math.floor(t.getFullYear()/e)*e),t.setMonth(0,1),t.setHours(0,0,0,0)},(t,n)=>{t.setFullYear(t.getFullYear()+n*e)});yo.range;const vo=xn(e=>{e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)},(e,t)=>{e.setUTCFullYear(e.getUTCFullYear()+t)},(e,t)=>t.getUTCFullYear()-e.getUTCFullYear(),e=>e.getUTCFullYear());vo.every=e=>!isFinite(e=Math.floor(e))||!(e>0)?null:xn(t=>{t.setUTCFullYear(Math.floor(t.getUTCFullYear()/e)*e),t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)},(t,n)=>{t.setUTCFullYear(t.getUTCFullYear()+n*e)});vo.range;function jR(e,t,n,r,i,s){const o=[[na,1,ea],[na,5,5*ea],[na,15,15*ea],[na,30,30*ea],[s,1,Ri],[s,5,5*Ri],[s,15,15*Ri],[s,30,30*Ri],[i,1,ta],[i,3,3*ta],[i,6,6*ta],[i,12,12*ta],[r,1,ga],[r,2,2*ga],[n,1,oA],[t,1,Q$],[t,3,3*Q$],[e,1,Zb]];function a(l,c,f){const d=cm).right(o,d);if(h===o.length)return e.every(du(l/Zb,c/Zb,f));if(h===0)return Lf.every(Math.max(du(l,c,f),1));const[p,g]=o[d/o[h-1][2](e[t]=1+n,e),{});function uA(e){const t=ye(e).slice(),n={};return t.length||X("Missing time unit."),t.forEach(i=>{be(Jb,i)?n[i]=1:X(`Invalid time unit: ${i}.`)}),(n[mn]||n[ir]?1:0)+(n[Yr]||n[ur]||n[Vr]?1:0)+(n[bo]?1:0)>1&&X(`Incompatible time units: ${e}`),t.sort((i,s)=>Jb[i]-Jb[s]),t}const lG={[Gn]:"%Y ",[Yr]:"Q%q ",[ur]:"%b ",[Vr]:"%d ",[mn]:"W%U ",[ir]:"%a ",[bo]:"%j ",[vi]:"%H:00",[bi]:"00:%M",[qi]:":%S",[Ss]:".%L",[`${Gn}-${ur}`]:"%Y-%m ",[`${Gn}-${ur}-${Vr}`]:"%Y-%m-%d ",[`${vi}-${bi}`]:"%H:%M"};function UR(e,t){const n=We({},lG,t),r=uA(e),i=r.length;let s="",o=0,a,u;for(o=0;oo;--a)if(u=r.slice(o,a).join("-"),n[u]!=null){s+=n[u],o=a;break}return s.trim()}const al=new Date;function lA(e){return al.setFullYear(e),al.setMonth(0),al.setDate(1),al.setHours(0,0,0,0),al}function qR(e){return HR(new Date(e))}function WR(e){return c_(new Date(e))}function HR(e){return aa.count(lA(e.getFullYear())-1,e)}function c_(e){return Sd.count(lA(e.getFullYear())-1,e)}function f_(e){return lA(e).getDay()}function cG(e,t,n,r,i,s,o){if(0<=e&&e<100){const a=new Date(-1,t,n,r,i,s,o);return a.setFullYear(e),a}return new Date(e,t,n,r,i,s,o)}function GR(e){return VR(new Date(e))}function YR(e){return d_(new Date(e))}function VR(e){const t=Date.UTC(e.getUTCFullYear(),0,1);return su.count(t-1,e)}function d_(e){const t=Date.UTC(e.getUTCFullYear(),0,1);return kd.count(t-1,e)}function h_(e){return al.setTime(Date.UTC(e,0,1)),al.getUTCDay()}function fG(e,t,n,r,i,s,o){if(0<=e&&e<100){const a=new Date(Date.UTC(-1,t,n,r,i,s,o));return a.setUTCFullYear(n.y),a}return new Date(Date.UTC(e,t,n,r,i,s,o))}function XR(e,t,n,r,i){const s=t||1,o=st(e),a=(y,v,b)=>(b=b||y,dG(n[b],r[b],y===o&&s,v)),u=new Date,l=As(e),c=l[Gn]?a(Gn):pr(2012),f=l[ur]?a(ur):l[Yr]?a(Yr):ja,d=l[mn]&&l[ir]?a(ir,1,mn+ir):l[mn]?a(mn,1):l[ir]?a(ir,1):l[Vr]?a(Vr,1):l[bo]?a(bo,1):bd,h=l[vi]?a(vi):ja,p=l[bi]?a(bi):ja,g=l[qi]?a(qi):ja,m=l[Ss]?a(Ss):ja;return function(y){u.setTime(+y);const v=c(u);return i(v,f(u),d(u,v),h(u),p(u),g(u),m(u))}}function dG(e,t,n,r){const i=n<=1?e:r?(s,o)=>r+n*Math.floor((e(s,o)-r)/n):(s,o)=>n*Math.floor(e(s,o)/n);return t?(s,o)=>t(i(s,o),o):i}function Bf(e,t,n){return t+e*7-(n+6)%7}const hG={[Gn]:e=>e.getFullYear(),[Yr]:e=>Math.floor(e.getMonth()/3),[ur]:e=>e.getMonth(),[Vr]:e=>e.getDate(),[vi]:e=>e.getHours(),[bi]:e=>e.getMinutes(),[qi]:e=>e.getSeconds(),[Ss]:e=>e.getMilliseconds(),[bo]:e=>HR(e),[mn]:e=>c_(e),[mn+ir]:(e,t)=>Bf(c_(e),e.getDay(),f_(t)),[ir]:(e,t)=>Bf(1,e.getDay(),f_(t))},pG={[Yr]:e=>3*e,[mn]:(e,t)=>Bf(e,0,f_(t))};function KR(e,t){return XR(e,t||1,hG,pG,cG)}const gG={[Gn]:e=>e.getUTCFullYear(),[Yr]:e=>Math.floor(e.getUTCMonth()/3),[ur]:e=>e.getUTCMonth(),[Vr]:e=>e.getUTCDate(),[vi]:e=>e.getUTCHours(),[bi]:e=>e.getUTCMinutes(),[qi]:e=>e.getUTCSeconds(),[Ss]:e=>e.getUTCMilliseconds(),[bo]:e=>VR(e),[mn]:e=>d_(e),[ir]:(e,t)=>Bf(1,e.getUTCDay(),h_(t)),[mn+ir]:(e,t)=>Bf(d_(e),e.getUTCDay(),h_(t))},mG={[Yr]:e=>3*e,[mn]:(e,t)=>Bf(e,0,h_(t))};function ZR(e,t){return XR(e,t||1,gG,mG,fG)}const yG={[Gn]:yo,[Yr]:dp.every(3),[ur]:dp,[mn]:Sd,[Vr]:aa,[ir]:aa,[bo]:aa,[vi]:ky,[bi]:Ay,[qi]:na,[Ss]:Lf},vG={[Gn]:vo,[Yr]:hp.every(3),[ur]:hp,[mn]:kd,[Vr]:su,[ir]:su,[bo]:su,[vi]:Cy,[bi]:Sy,[qi]:na,[Ss]:Lf};function Cd(e){return yG[e]}function $d(e){return vG[e]}function JR(e,t,n){return e?e.offset(t,n):void 0}function QR(e,t,n){return JR(Cd(e),t,n)}function eT(e,t,n){return JR($d(e),t,n)}function tT(e,t,n,r){return e?e.range(t,n,r):void 0}function nT(e,t,n,r){return tT(Cd(e),t,n,r)}function rT(e,t,n,r){return tT($d(e),t,n,r)}const _h=1e3,wh=_h*60,Eh=wh*60,$y=Eh*24,bG=$y*7,eF=$y*30,p_=$y*365,iT=[Gn,ur,Vr,vi,bi,qi,Ss],Ah=iT.slice(0,-1),Sh=Ah.slice(0,-1),kh=Sh.slice(0,-1),xG=kh.slice(0,-1),_G=[Gn,mn],tF=[Gn,ur],sT=[Gn],Kd=[[Ah,1,_h],[Ah,5,5*_h],[Ah,15,15*_h],[Ah,30,30*_h],[Sh,1,wh],[Sh,5,5*wh],[Sh,15,15*wh],[Sh,30,30*wh],[kh,1,Eh],[kh,3,3*Eh],[kh,6,6*Eh],[kh,12,12*Eh],[xG,1,$y],[_G,1,bG],[tF,1,eF],[tF,3,3*eF],[sT,1,p_]];function oT(e){const t=e.extent,n=e.maxbins||40,r=Math.abs(ig(t))/n;let i=Ad(a=>a[2]).right(Kd,r),s,o;return i===Kd.length?(s=sT,o=du(t[0]/p_,t[1]/p_,n)):i?(i=Kd[r/Kd[i-1][2]53)return null;"w"in W||(W.w=1),"Z"in W?(xe=e2(Zd(W.y,0,1)),Fe=xe.getUTCDay(),xe=Fe>4||Fe===0?Im.ceil(xe):Im(xe),xe=su.offset(xe,(W.V-1)*7),W.y=xe.getUTCFullYear(),W.m=xe.getUTCMonth(),W.d=xe.getUTCDate()+(W.w+6)%7):(xe=Qb(Zd(W.y,0,1)),Fe=xe.getDay(),xe=Fe>4||Fe===0?Lm.ceil(xe):Lm(xe),xe=aa.offset(xe,(W.V-1)*7),W.y=xe.getFullYear(),W.m=xe.getMonth(),W.d=xe.getDate()+(W.w+6)%7)}else("W"in W||"U"in W)&&("w"in W||(W.w="u"in W?W.u%7:"W"in W?1:0),Fe="Z"in W?e2(Zd(W.y,0,1)).getUTCDay():Qb(Zd(W.y,0,1)).getDay(),W.m=0,W.d="W"in W?(W.w+6)%7+W.W*7-(Fe+5)%7:W.w+W.U*7-(Fe+6)%7);return"Z"in W?(W.H+=W.Z/100|0,W.M+=W.Z%100,e2(W)):Qb(W)}}function S(I,q,se,W){for(var ve=0,xe=q.length,Fe=se.length,ze,ot;ve=Fe)return-1;if(ze=q.charCodeAt(ve++),ze===37){if(ze=q.charAt(ve++),ot=_[ze in nF?q.charAt(ve++):ze],!ot||(W=ot(I,se,W))<0)return-1}else if(ze!=se.charCodeAt(W++))return-1}return W}function k(I,q,se){var W=l.exec(q.slice(se));return W?(I.p=c.get(W[0].toLowerCase()),se+W[0].length):-1}function $(I,q,se){var W=h.exec(q.slice(se));return W?(I.w=p.get(W[0].toLowerCase()),se+W[0].length):-1}function D(I,q,se){var W=f.exec(q.slice(se));return W?(I.w=d.get(W[0].toLowerCase()),se+W[0].length):-1}function M(I,q,se){var W=y.exec(q.slice(se));return W?(I.m=v.get(W[0].toLowerCase()),se+W[0].length):-1}function R(I,q,se){var W=g.exec(q.slice(se));return W?(I.m=m.get(W[0].toLowerCase()),se+W[0].length):-1}function F(I,q,se){return S(I,t,q,se)}function C(I,q,se){return S(I,n,q,se)}function T(I,q,se){return S(I,r,q,se)}function O(I){return o[I.getDay()]}function N(I){return s[I.getDay()]}function L(I){return u[I.getMonth()]}function z(I){return a[I.getMonth()]}function U(I){return i[+(I.getHours()>=12)]}function Q(I){return 1+~~(I.getMonth()/3)}function de(I){return o[I.getUTCDay()]}function we(I){return s[I.getUTCDay()]}function ne(I){return u[I.getUTCMonth()]}function Ee(I){return a[I.getUTCMonth()]}function Ke(I){return i[+(I.getUTCHours()>=12)]}function fe(I){return 1+~~(I.getUTCMonth()/3)}return{format:function(I){var q=A(I+="",b);return q.toString=function(){return I},q},parse:function(I){var q=E(I+="",!1);return q.toString=function(){return I},q},utcFormat:function(I){var q=A(I+="",x);return q.toString=function(){return I},q},utcParse:function(I){var q=E(I+="",!0);return q.toString=function(){return I},q}}}var nF={"-":"",_:" ",0:"0"},Nn=/^\s*\d+/,wG=/^%/,EG=/[\\^$*+?|[\]().{}]/g;function dt(e,t,n){var r=e<0?"-":"",i=(r?-e:e)+"",s=i.length;return r+(s[t.toLowerCase(),n]))}function SG(e,t,n){var r=Nn.exec(t.slice(n,n+1));return r?(e.w=+r[0],n+r[0].length):-1}function kG(e,t,n){var r=Nn.exec(t.slice(n,n+1));return r?(e.u=+r[0],n+r[0].length):-1}function CG(e,t,n){var r=Nn.exec(t.slice(n,n+2));return r?(e.U=+r[0],n+r[0].length):-1}function $G(e,t,n){var r=Nn.exec(t.slice(n,n+2));return r?(e.V=+r[0],n+r[0].length):-1}function FG(e,t,n){var r=Nn.exec(t.slice(n,n+2));return r?(e.W=+r[0],n+r[0].length):-1}function rF(e,t,n){var r=Nn.exec(t.slice(n,n+4));return r?(e.y=+r[0],n+r[0].length):-1}function iF(e,t,n){var r=Nn.exec(t.slice(n,n+2));return r?(e.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function DG(e,t,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(t.slice(n,n+6));return r?(e.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function MG(e,t,n){var r=Nn.exec(t.slice(n,n+1));return r?(e.q=r[0]*3-3,n+r[0].length):-1}function RG(e,t,n){var r=Nn.exec(t.slice(n,n+2));return r?(e.m=r[0]-1,n+r[0].length):-1}function sF(e,t,n){var r=Nn.exec(t.slice(n,n+2));return r?(e.d=+r[0],n+r[0].length):-1}function TG(e,t,n){var r=Nn.exec(t.slice(n,n+3));return r?(e.m=0,e.d=+r[0],n+r[0].length):-1}function oF(e,t,n){var r=Nn.exec(t.slice(n,n+2));return r?(e.H=+r[0],n+r[0].length):-1}function NG(e,t,n){var r=Nn.exec(t.slice(n,n+2));return r?(e.M=+r[0],n+r[0].length):-1}function OG(e,t,n){var r=Nn.exec(t.slice(n,n+2));return r?(e.S=+r[0],n+r[0].length):-1}function LG(e,t,n){var r=Nn.exec(t.slice(n,n+3));return r?(e.L=+r[0],n+r[0].length):-1}function IG(e,t,n){var r=Nn.exec(t.slice(n,n+6));return r?(e.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function PG(e,t,n){var r=wG.exec(t.slice(n,n+1));return r?n+r[0].length:-1}function BG(e,t,n){var r=Nn.exec(t.slice(n));return r?(e.Q=+r[0],n+r[0].length):-1}function zG(e,t,n){var r=Nn.exec(t.slice(n));return r?(e.s=+r[0],n+r[0].length):-1}function aF(e,t){return dt(e.getDate(),t,2)}function jG(e,t){return dt(e.getHours(),t,2)}function UG(e,t){return dt(e.getHours()%12||12,t,2)}function qG(e,t){return dt(1+aa.count(yo(e),e),t,3)}function uT(e,t){return dt(e.getMilliseconds(),t,3)}function WG(e,t){return uT(e,t)+"000"}function HG(e,t){return dt(e.getMonth()+1,t,2)}function GG(e,t){return dt(e.getMinutes(),t,2)}function YG(e,t){return dt(e.getSeconds(),t,2)}function VG(e){var t=e.getDay();return t===0?7:t}function XG(e,t){return dt(Sd.count(yo(e)-1,e),t,2)}function lT(e){var t=e.getDay();return t>=4||t===0?If(e):If.ceil(e)}function KG(e,t){return e=lT(e),dt(If.count(yo(e),e)+(yo(e).getDay()===4),t,2)}function ZG(e){return e.getDay()}function JG(e,t){return dt(Lm.count(yo(e)-1,e),t,2)}function QG(e,t){return dt(e.getFullYear()%100,t,2)}function eY(e,t){return e=lT(e),dt(e.getFullYear()%100,t,2)}function tY(e,t){return dt(e.getFullYear()%1e4,t,4)}function nY(e,t){var n=e.getDay();return e=n>=4||n===0?If(e):If.ceil(e),dt(e.getFullYear()%1e4,t,4)}function rY(e){var t=e.getTimezoneOffset();return(t>0?"-":(t*=-1,"+"))+dt(t/60|0,"0",2)+dt(t%60,"0",2)}function uF(e,t){return dt(e.getUTCDate(),t,2)}function iY(e,t){return dt(e.getUTCHours(),t,2)}function sY(e,t){return dt(e.getUTCHours()%12||12,t,2)}function oY(e,t){return dt(1+su.count(vo(e),e),t,3)}function cT(e,t){return dt(e.getUTCMilliseconds(),t,3)}function aY(e,t){return cT(e,t)+"000"}function uY(e,t){return dt(e.getUTCMonth()+1,t,2)}function lY(e,t){return dt(e.getUTCMinutes(),t,2)}function cY(e,t){return dt(e.getUTCSeconds(),t,2)}function fY(e){var t=e.getUTCDay();return t===0?7:t}function dY(e,t){return dt(kd.count(vo(e)-1,e),t,2)}function fT(e){var t=e.getUTCDay();return t>=4||t===0?Pf(e):Pf.ceil(e)}function hY(e,t){return e=fT(e),dt(Pf.count(vo(e),e)+(vo(e).getUTCDay()===4),t,2)}function pY(e){return e.getUTCDay()}function gY(e,t){return dt(Im.count(vo(e)-1,e),t,2)}function mY(e,t){return dt(e.getUTCFullYear()%100,t,2)}function yY(e,t){return e=fT(e),dt(e.getUTCFullYear()%100,t,2)}function vY(e,t){return dt(e.getUTCFullYear()%1e4,t,4)}function bY(e,t){var n=e.getUTCDay();return e=n>=4||n===0?Pf(e):Pf.ceil(e),dt(e.getUTCFullYear()%1e4,t,4)}function xY(){return"+0000"}function lF(){return"%"}function cF(e){return+e}function fF(e){return Math.floor(+e/1e3)}var Lc,cA,dT,fA,hT;_Y({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function _Y(e){return Lc=aT(e),cA=Lc.format,dT=Lc.parse,fA=Lc.utcFormat,hT=Lc.utcParse,Lc}function Ch(e){const t={};return n=>t[n]||(t[n]=e(n))}function wY(e,t){return n=>{const r=e(n),i=r.indexOf(t);if(i<0)return r;let s=EY(r,i);const o=si;)if(r[s]!=="0"){++s;break}return r.slice(0,s)+o}}function EY(e,t){let n=e.lastIndexOf("e"),r;if(n>0)return n;for(n=e.length;--n>t;)if(r=e.charCodeAt(n),r>=48&&r<=57)return n+1}function pT(e){const t=Ch(e.format),n=e.formatPrefix;return{format:t,formatPrefix:n,formatFloat(r){const i=Wl(r||",");if(i.precision==null){switch(i.precision=12,i.type){case"%":i.precision-=2;break;case"e":i.precision-=1;break}return wY(t(i),t(".1f")(1)[1])}else return t(i)},formatSpan(r,i,s,o){o=Wl(o??",f");const a=du(r,i,s),u=Math.max(Math.abs(r),Math.abs(i));let l;if(o.precision==null)switch(o.type){case"s":return isNaN(l=PR(a,u))||(o.precision=l),n(o,u);case"":case"e":case"g":case"p":case"r":{isNaN(l=BR(a,u))||(o.precision=l-(o.type==="e"));break}case"f":case"%":{isNaN(l=IR(a))||(o.precision=l-(o.type==="%")*2);break}}return t(o)}}}let g_;gT();function gT(){return g_=pT({format:Ey,formatPrefix:sA})}function mT(e){return pT(LR(e))}function Pm(e){return arguments.length?g_=mT(e):g_}function dF(e,t,n){n=n||{},ge(n)||X(`Invalid time multi-format specifier: ${n}`);const r=t(qi),i=t(bi),s=t(vi),o=t(Vr),a=t(mn),u=t(ur),l=t(Yr),c=t(Gn),f=e(n[Ss]||".%L"),d=e(n[qi]||":%S"),h=e(n[bi]||"%I:%M"),p=e(n[vi]||"%I %p"),g=e(n[Vr]||n[ir]||"%a %d"),m=e(n[mn]||"%b %d"),y=e(n[ur]||"%B"),v=e(n[Yr]||"%B"),b=e(n[Gn]||"%Y");return x=>(r(x)me(r)?t(r):dF(t,Cd,r),utcFormat:r=>me(r)?n(r):dF(n,$d,r),timeParse:Ch(e.parse),utcParse:Ch(e.utcParse)}}let m_;vT();function vT(){return m_=yT({format:cA,parse:dT,utcFormat:fA,utcParse:hT})}function bT(e){return yT(aT(e))}function pp(e){return arguments.length?m_=bT(e):m_}const y_=(e,t)=>We({},e,t);function xT(e,t){const n=e?mT(e):Pm(),r=t?bT(t):pp();return y_(n,r)}function dA(e,t){const n=arguments.length;return n&&n!==2&&X("defaultLocale expects either zero or two arguments."),n?y_(Pm(e),pp(t)):y_(Pm(),pp())}function AY(){return gT(),vT(),dA()}const SY=/^(data:|([A-Za-z]+:)?\/\/)/,kY=/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp|file|data):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i,CY=/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205f\u3000]/g,hF="file://";function $Y(e,t){return n=>({options:n||{},sanitize:DY,load:FY,fileAccess:!1,file:MY(),http:TY(e)})}async function FY(e,t){const n=await this.sanitize(e,t),r=n.href;return n.localFile?this.file(r):this.http(r,t)}async function DY(e,t){t=We({},this.options,t);const n=this.fileAccess,r={href:null};let i,s,o;const a=kY.test(e.replace(CY,""));(e==null||typeof e!="string"||!a)&&X("Sanitize failure, invalid URI: "+ce(e));const u=SY.test(e);return(o=t.baseURL)&&!u&&(!e.startsWith("/")&&!o.endsWith("/")&&(e="/"+e),e=o+e),s=(i=e.startsWith(hF))||t.mode==="file"||t.mode!=="http"&&!u&&n,i?e=e.slice(hF.length):e.startsWith("//")&&(t.defaultProtocol==="file"?(e=e.slice(2),s=!0):e=(t.defaultProtocol||"http")+":"+e),Object.defineProperty(r,"localFile",{value:!!s}),r.href=e,t.target&&(r.target=t.target+""),t.rel&&(r.rel=t.rel+""),t.context==="image"&&t.crossOrigin&&(r.crossOrigin=t.crossOrigin+""),r}function MY(e){return RY}async function RY(){X("No file system access.")}function TY(e){return e?async function(t,n){const r=We({},this.options.http,n),i=n&&n.response,s=await e(t,r);return s.ok?He(s[i])?s[i]():s.text():X(s.status+""+s.statusText)}:NY}async function NY(){X("No HTTP fetch method available.")}const OY=e=>e!=null&&e===e,LY=e=>e==="true"||e==="false"||e===!0||e===!1,IY=e=>!Number.isNaN(Date.parse(e)),_T=e=>!Number.isNaN(+e)&&!(e instanceof Date),PY=e=>_T(e)&&Number.isInteger(+e),v_={boolean:tA,integer:sr,number:sr,date:nA,string:rA,unknown:hr},r0=[LY,PY,_T,IY],BY=["boolean","integer","number","date"];function wT(e,t){if(!e||!e.length)return"unknown";const n=e.length,r=r0.length,i=r0.map((s,o)=>o+1);for(let s=0,o=0,a,u;ss===0?o:s,0)-1]}function ET(e,t){return t.reduce((n,r)=>(n[r]=wT(e,r),n),{})}function pF(e){const t=function(n,r){const i={delimiter:e};return hA(n,r?We(r,i):i)};return t.responseType="text",t}function hA(e,t){return t.header&&(e=t.header.map(ce).join(t.delimiter)+` +`+e),bH(t.delimiter).parse(e+"")}hA.responseType="text";function zY(e){return typeof Buffer=="function"&&He(Buffer.isBuffer)?Buffer.isBuffer(e):!1}function pA(e,t){const n=t&&t.property?Ui(t.property):hr;return ge(e)&&!zY(e)?jY(n(e),t):n(JSON.parse(e))}pA.responseType="json";function jY(e,t){return!ee(e)&&yR(e)&&(e=[...e]),t&&t.copy?JSON.parse(JSON.stringify(e)):e}const UY={interior:(e,t)=>e!==t,exterior:(e,t)=>e===t};function AT(e,t){let n,r,i,s;return e=pA(e,t),t&&t.feature?(n=EH,i=t.feature):t&&t.mesh?(n=SH,i=t.mesh,s=UY[t.filter]):X("Missing TopoJSON feature or mesh parameter."),r=(r=e.objects[i])?n(e,r,s):X("Invalid TopoJSON object: "+i),r&&r.features||[r]}AT.responseType="json";const J0={dsv:hA,csv:pF(","),tsv:pF(" "),json:pA,topojson:AT};function gA(e,t){return arguments.length>1?(J0[e]=t,this):be(J0,e)?J0[e]:null}function ST(e){const t=gA(e);return t&&t.responseType||"text"}function kT(e,t,n,r){t=t||{};const i=gA(t.type||"json");return i||X("Unknown data format type: "+t.type),e=i(e,t),t.parse&&qY(e,t.parse,n,r),be(e,"columns")&&delete e.columns,e}function qY(e,t,n,r){if(!e.length)return;const i=pp();n=n||i.timeParse,r=r||i.utcParse;let s=e.columns||Object.keys(e[0]),o,a,u,l,c,f;t==="auto"&&(t=ET(e,s)),s=Object.keys(t);const d=s.map(h=>{const p=t[h];let g,m;if(p&&(p.startsWith("date:")||p.startsWith("utc:")))return g=p.split(/:(.+)?/,2),m=g[1],(m[0]==="'"&&m[m.length-1]==="'"||m[0]==='"'&&m[m.length-1]==='"')&&(m=m.slice(1,-1)),(g[0]==="utc"?r:n)(m);if(!v_[p])throw Error("Illegal format pattern: "+h+":"+p);return v_[p]});for(u=0,c=e.length,f=s.length;u{const s=t(i);return r[s]||(r[s]=1,n.push(i)),n},n.remove=i=>{const s=t(i);if(r[s]){r[s]=0;const o=n.indexOf(i);o>=0&&n.splice(o,1)}return n},n}async function Q0(e,t){try{await t(e)}catch(n){e.error(n)}}const CT=Symbol("vega_id");let WY=1;function My(e){return!!(e&&Te(e))}function Te(e){return e[CT]}function $T(e,t){return e[CT]=t,e}function gt(e){const t=e===Object(e)?e:{data:e};return Te(t)?t:$T(t,WY++)}function mA(e){return Ry(e,gt({}))}function Ry(e,t){for(const n in e)t[n]=e[n];return t}function FT(e,t){return $T(t,Te(e))}function yc(e,t){return e?t?(n,r)=>e(n,r)||Te(t(n))-Te(t(r)):(n,r)=>e(n,r)||Te(n)-Te(r):null}function DT(e){return e&&e.constructor===Mu}function Mu(){const e=[],t=[],n=[],r=[],i=[];let s=null,o=!1;return{constructor:Mu,insert(a){const u=ye(a),l=u.length;for(let c=0;c{p(v)&&(l[Te(v)]=-1)});for(f=0,d=e.length;f0&&(y(g,p,h.value),a.modifies(p));for(f=0,d=i.length;f{p(v)&&l[Te(v)]>0&&y(v,h.field,h.value)}),a.modifies(h.field);if(o)a.mod=t.length||r.length?u.filter(v=>l[Te(v)]>0):u.slice();else for(m in c)a.mod.push(c[m]);return(s||s==null&&(t.length||r.length))&&a.clean(!0),a}}}const em="_:mod:_";function Ty(){Object.defineProperty(this,em,{writable:!0,value:{}})}Ty.prototype={set(e,t,n,r){const i=this,s=i[e],o=i[em];return t!=null&&t>=0?(s[t]!==n||r)&&(s[t]=n,o[t+":"+e]=-1,o[e]=-1):(s!==n||r)&&(i[e]=n,o[e]=ee(n)?1+n.length:-1),i},modified(e,t){const n=this[em];if(arguments.length){if(ee(e)){for(let r=0;r=0?t+1{h instanceof $t?(h!==this&&(t&&h.targets().add(this),s.push(h)),i.push({op:h,name:f,index:d})):r.set(f,d,h)};for(o in e)if(a=e[o],o===GY)ye(a).forEach(f=>{f instanceof $t?f!==this&&(f.targets().add(this),s.push(f)):X("Pulse parameters must be operator instances.")}),this.source=a;else if(ee(a))for(r.set(o,-1,Array(u=a.length)),l=0;l{const n=Date.now();return n-t>e?(t=n,1):0})},debounce(e){const t=Na();return this.targets().add(Na(null,null,JE(e,n=>{const r=n.dataflow;t.receive(n),r&&r.run&&r.run()}))),t},between(e,t){let n=!1;return e.targets().add(Na(null,null,()=>n=!0)),t.targets().add(Na(null,null,()=>n=!1)),this.filter(()=>n)},detach(){this._filter=yi,this._targets=null}};function QY(e,t,n,r){const i=this,s=Na(n,r),o=function(l){l.dataflow=i;try{s.receive(l)}catch(c){i.error(c)}finally{i.run()}};let a;typeof e=="string"&&typeof document<"u"?a=document.querySelectorAll(e):a=ye(e);const u=a.length;for(let l=0;lt=r);return n.requests=0,n.done=()=>{--n.requests===0&&(e._pending=null,t(e))},e._pending=n}const sV={skip:!0};function oV(e,t,n,r,i){return(e instanceof $t?uV:aV)(this,e,t,n,r,i),this}function aV(e,t,n,r,i,s){const o=We({},s,sV);let a,u;He(n)||(n=pr(n)),r===void 0?a=l=>e.touch(n(l)):He(r)?(u=new $t(null,r,i,!1),a=l=>{u.evaluate(l);const c=n(l),f=u.value;DT(f)?e.pulse(c,f,s):e.update(c,f,o)}):a=l=>e.update(n(l),r,o),t.apply(a)}function uV(e,t,n,r,i,s){if(r===void 0)t.targets().add(n);else{const o=s||{},a=new $t(null,lV(n,r),i,!1);a.modified(o.force),a.rank=t.rank,t.targets().add(a),n&&(a.skip(!0),a.value=n.value,a.targets().add(n),e.connect(n,[a]))}}function lV(e,t){return t=He(t)?t:pr(t),e?function(n,r){const i=t(n,r);return e.skip()||(e.skip(i!==this.value).value=i),i}:t}function cV(e){e.rank=++this._rank}function fV(e){const t=[e];let n,r,i;for(;t.length;)if(this.rank(n=t.pop()),r=n._targets)for(i=r.length;--i>=0;)t.push(n=r[i]),n===e&&X("Cycle detected in dataflow graph.")}const Bm={},Vs=1,Ia=2,Ho=4,dV=Vs|Ia,mF=Vs|Ho,Ic=Vs|Ia|Ho,yF=8,eh=16,vF=32,bF=64;function ou(e,t,n){this.dataflow=e,this.stamp=t??-1,this.add=[],this.rem=[],this.mod=[],this.fields=null,this.encode=n||null}function t2(e,t){const n=[];return La(e,t,r=>n.push(r)),n}function xF(e,t){const n={};return e.visit(t,r=>{n[Te(r)]=1}),r=>n[Te(r)]?null:r}function i0(e,t){return e?(n,r)=>e(n,r)&&t(n,r):t}ou.prototype={StopPropagation:Bm,ADD:Vs,REM:Ia,MOD:Ho,ADD_REM:dV,ADD_MOD:mF,ALL:Ic,REFLOW:yF,SOURCE:eh,NO_SOURCE:vF,NO_FIELDS:bF,fork(e){return new ou(this.dataflow).init(this,e)},clone(){const e=this.fork(Ic);return e.add=e.add.slice(),e.rem=e.rem.slice(),e.mod=e.mod.slice(),e.source&&(e.source=e.source.slice()),e.materialize(Ic|eh)},addAll(){let e=this;return!e.source||e.add===e.rem||!e.rem.length&&e.source.length===e.add.length||(e=new ou(this.dataflow).init(this),e.add=e.source,e.rem=[]),e},init(e,t){const n=this;return n.stamp=e.stamp,n.encode=e.encode,e.fields&&!(t&bF)&&(n.fields=e.fields),t&Vs?(n.addF=e.addF,n.add=e.add):(n.addF=null,n.add=[]),t&Ia?(n.remF=e.remF,n.rem=e.rem):(n.remF=null,n.rem=[]),t&Ho?(n.modF=e.modF,n.mod=e.mod):(n.modF=null,n.mod=[]),t&vF?(n.srcF=null,n.source=null):(n.srcF=e.srcF,n.source=e.source,e.cleans&&(n.cleans=e.cleans)),n},runAfter(e){this.dataflow.runAfter(e)},changed(e){const t=e||Ic;return t&Vs&&this.add.length||t&Ia&&this.rem.length||t&Ho&&this.mod.length},reflow(e){if(e)return this.fork(Ic).reflow();const t=this.add.length,n=this.source&&this.source.length;return n&&n!==t&&(this.mod=this.source,t&&this.filter(Ho,xF(this,Vs))),this},clean(e){return arguments.length?(this.cleans=!!e,this):this.cleans},modifies(e){const t=this.fields||(this.fields={});return ee(e)?e.forEach(n=>t[n]=!0):t[e]=!0,this},modified(e,t){const n=this.fields;return(t||this.mod.length)&&n?arguments.length?ee(e)?e.some(r=>n[r]):n[e]:!!n:!1},filter(e,t){const n=this;return e&Vs&&(n.addF=i0(n.addF,t)),e&Ia&&(n.remF=i0(n.remF,t)),e&Ho&&(n.modF=i0(n.modF,t)),e&eh&&(n.srcF=i0(n.srcF,t)),n},materialize(e){e=e||Ic;const t=this;return e&Vs&&t.addF&&(t.add=t2(t.add,t.addF),t.addF=null),e&Ia&&t.remF&&(t.rem=t2(t.rem,t.remF),t.remF=null),e&Ho&&t.modF&&(t.mod=t2(t.mod,t.modF),t.modF=null),e&eh&&t.srcF&&(t.source=t.source.filter(t.srcF),t.srcF=null),t},visit(e,t){const n=this,r=t;if(e&eh)return La(n.source,n.srcF,r),n;e&Vs&&La(n.add,n.addF,r),e&Ia&&La(n.rem,n.remF,r),e&Ho&&La(n.mod,n.modF,r);const i=n.source;if(e&yF&&i){const s=n.add.length+n.mod.length;s===i.length||(s?La(i,xF(n,mF),r):La(i,n.srcF,r))}return n}};function yA(e,t,n,r){const i=this;let s=0;this.dataflow=e,this.stamp=t,this.fields=null,this.encode=r||null,this.pulses=n;for(const o of n)if(o.stamp===t){if(o.fields){const a=i.fields||(i.fields={});for(const u in o.fields)a[u]=1}o.changed(i.ADD)&&(s|=i.ADD),o.changed(i.REM)&&(s|=i.REM),o.changed(i.MOD)&&(s|=i.MOD)}this.changes=s}he(yA,ou,{fork(e){const t=new ou(this.dataflow).init(this,e&this.NO_FIELDS);return e!==void 0&&(e&t.ADD&&this.visit(t.ADD,n=>t.add.push(n)),e&t.REM&&this.visit(t.REM,n=>t.rem.push(n)),e&t.MOD&&this.visit(t.MOD,n=>t.mod.push(n))),t},changed(e){return this.changes&e},modified(e){const t=this,n=t.fields;return n&&t.changes&t.MOD?ee(e)?e.some(r=>n[r]):n[e]:0},filter(){X("MultiPulse does not support filtering.")},materialize(){X("MultiPulse does not support materialization.")},visit(e,t){const n=this,r=n.pulses,i=r.length;let s=0;if(e&n.SOURCE)for(;sr._enqueue(c,!0)),r._touched=Dy(rg);let o=0,a,u,l;try{for(;r._heap.size()>0;){if(a=r._heap.pop(),a.rank!==a.qrank){r._enqueue(a,!0);continue}u=a.run(r._getPulse(a,e)),u.then?u=await u:u.async&&(i.push(u.async),u=Bm),u!==Bm&&a._targets&&a._targets.forEach(c=>r._enqueue(c)),++o}}catch(c){r._heap.clear(),l=c}if(r._input={},r._pulse=null,r.debug(`Pulse ${s}: ${o} operators`),l&&(r._postrun=[],r.error(l)),r._postrun.length){const c=r._postrun.sort((f,d)=>d.priority-f.priority);r._postrun=[];for(let f=0;fr.runAsync(null,()=>{c.forEach(f=>{try{f(r)}catch(d){r.error(d)}})})),r}async function pV(e,t,n){for(;this._running;)await this._running;const r=()=>this._running=null;return(this._running=this.evaluate(e,t,n)).then(r,r),this._running}function gV(e,t,n){return this._pulse?MT(this):(this.evaluate(e,t,n),this)}function mV(e,t,n){if(this._pulse||t)this._postrun.push({priority:n||0,callback:e});else try{e(this)}catch(r){this.error(r)}}function MT(e){return e.error("Dataflow already running. Use runAsync() to chain invocations."),e}function yV(e,t){const n=e.stampi.pulse),t):this._input[e.id]||bV(this._pulse,n&&n.pulse)}function bV(e,t){return t&&t.stamp===e.stamp?t:(e=e.fork(),t&&t!==Bm&&(e.source=t.source),e)}const vA={skip:!1,force:!1};function xV(e,t){const n=t||vA;return this._pulse?this._enqueue(e):this._touched.add(e),n.skip&&e.skip(!0),this}function _V(e,t,n){const r=n||vA;return(e.set(t)||r.force)&&this.touch(e,r),this}function wV(e,t,n){this.touch(e,n||vA);const r=new ou(this,this._clock+(this._pulse?0:1)),i=e.pulse&&e.pulse.source||[];return r.target=e,this._input[e.id]=t.pulse(r,i),this}function EV(e){let t=[];return{clear:()=>t=[],size:()=>t.length,peek:()=>t[0],push:n=>(t.push(n),RT(t,0,t.length-1,e)),pop:()=>{const n=t.pop();let r;return t.length?(r=t[0],t[0]=n,AV(t,0,e)):r=n,r}}}function RT(e,t,n,r){let i,s;const o=e[n];for(;n>t;){if(s=n-1>>1,i=e[s],r(o,i)<0){e[n]=i,n=s;continue}break}return e[n]=o}function AV(e,t,n){const r=t,i=e.length,s=e[t];let o=(t<<1)+1,a;for(;o=0&&(o=a),e[t]=e[o],t=o,o=(t<<1)+1;return e[t]=s,RT(e,r,t,n)}function lf(){this.logger(YE()),this.logLevel(HE),this._clock=0,this._rank=0,this._locale=dA();try{this._loader=Fy()}catch{}this._touched=Dy(rg),this._input={},this._pulse=null,this._heap=EV((e,t)=>e.qrank-t.qrank),this._postrun=[]}function th(e){return function(){return this._log[e].apply(this,arguments)}}lf.prototype={stamp(){return this._clock},loader(e){return arguments.length?(this._loader=e,this):this._loader},locale(e){return arguments.length?(this._locale=e,this):this._locale},logger(e){return arguments.length?(this._log=e,this):this._log},error:th("error"),warn:th("warn"),info:th("info"),debug:th("debug"),logLevel:th("level"),cleanThreshold:1e4,add:KY,connect:ZY,rank:cV,rerank:fV,pulse:wV,touch:xV,update:_V,changeset:Mu,ingest:tV,parse:eV,preload:rV,request:nV,events:QY,on:oV,evaluate:hV,run:gV,runAsync:pV,runAfter:mV,_enqueue:yV,_getPulse:vV};function G(e,t){$t.call(this,e,null,t)}he(G,$t,{run(e){if(e.stampthis.pulse=n):t!==e.StopPropagation&&(this.pulse=t),t},evaluate(e){const t=this.marshall(e.stamp),n=this.transform(t,e);return t.clear(),n},transform(){}});const zf={};function TT(e){const t=NT(e);return t&&t.Definition||null}function NT(e){return e=e&&e.toLowerCase(),be(zf,e)?zf[e]:null}function*OT(e,t){if(t==null)for(let n of e)n!=null&&n!==""&&(n=+n)>=n&&(yield n);else{let n=-1;for(let r of e)r=t(r,++n,e),r!=null&&r!==""&&(r=+r)>=r&&(yield r)}}function bA(e,t,n){const r=Float64Array.from(OT(e,n));return r.sort(oa),t.map(i=>RR(r,i))}function xA(e,t){return bA(e,[.25,.5,.75],t)}function _A(e,t){const n=e.length,r=TH(e,t),i=xA(e,t),s=(i[2]-i[0])/1.34;return 1.06*(Math.min(r,s)||r||Math.abs(i[0])||1)*Math.pow(n,-.2)}function LT(e){const t=e.maxbins||20,n=e.base||10,r=Math.log(n),i=e.divide||[5,2];let s=e.extent[0],o=e.extent[1],a,u,l,c,f,d;const h=e.span||o-s||Math.abs(s)||1;if(e.step)a=e.step;else if(e.steps){for(c=h/t,f=0,d=e.steps.length;ft;)a*=n;for(f=0,d=i.length;f=l&&h/c<=t&&(a=c)}c=Math.log(a);const p=c>=0?0:~~(-c/r)+1,g=Math.pow(n,-p-1);return(e.nice||e.nice===void 0)&&(c=Math.floor(s/a+g)*a,s=sd);const i=e.length,s=new Float64Array(i);let o=0,a=1,u=r(e[0]),l=u,c=u+t,f;for(;a=c){for(l=(u+l)/2;o>1);oi;)e[o--]=e[r]}r=i,i=s}return e}function CV(e){return function(){return e=(1103515245*e+12345)%2147483647,e/2147483647}}function $V(e,t){t==null&&(t=e,e=0);let n,r,i;const s={min(o){return arguments.length?(n=o||0,i=r-n,s):n},max(o){return arguments.length?(r=o||0,i=r-n,s):r},sample(){return n+Math.floor(i*Wi())},pdf(o){return o===Math.floor(o)&&o>=n&&o=r?1:(a-n+1)/i},icdf(o){return o>=0&&o<=1?n-1+Math.floor(o*i):NaN}};return s.min(e).max(t)}const BT=Math.sqrt(2*Math.PI),FV=Math.SQRT2;let nh=NaN;function Oy(e,t){e=e||0,t=t??1;let n=0,r=0,i,s;if(nh===nh)n=nh,nh=NaN;else{do n=Wi()*2-1,r=Wi()*2-1,i=n*n+r*r;while(i===0||i>1);s=Math.sqrt(-2*Math.log(i)/i),n*=s,nh=r*s}return e+n*t}function wA(e,t,n){n=n??1;const r=(e-(t||0))/n;return Math.exp(-.5*r*r)/(n*BT)}function Ly(e,t,n){t=t||0,n=n??1;const r=(e-t)/n,i=Math.abs(r);let s;if(i>37)s=0;else{const o=Math.exp(-i*i/2);let a;i<7.07106781186547?(a=.0352624965998911*i+.700383064443688,a=a*i+6.37396220353165,a=a*i+33.912866078383,a=a*i+112.079291497871,a=a*i+221.213596169931,a=a*i+220.206867912376,s=o*a,a=.0883883476483184*i+1.75566716318264,a=a*i+16.064177579207,a=a*i+86.7807322029461,a=a*i+296.564248779674,a=a*i+637.333633378831,a=a*i+793.826512519948,a=a*i+440.413735824752,s=s/a):(a=i+.65,a=i+4/a,a=i+3/a,a=i+2/a,a=i+1/a,s=o/a/2.506628274631)}return r>0?1-s:s}function Iy(e,t,n){return e<0||e>1?NaN:(t||0)+(n??1)*FV*DV(2*e-1)}function DV(e){let t=-Math.log((1-e)*(1+e)),n;return t<6.25?(t-=3.125,n=-364441206401782e-35,n=-16850591381820166e-35+n*t,n=128584807152564e-32+n*t,n=11157877678025181e-33+n*t,n=-1333171662854621e-31+n*t,n=20972767875968562e-33+n*t,n=6637638134358324e-30+n*t,n=-4054566272975207e-29+n*t,n=-8151934197605472e-29+n*t,n=26335093153082323e-28+n*t,n=-12975133253453532e-27+n*t,n=-5415412054294628e-26+n*t,n=10512122733215323e-25+n*t,n=-4112633980346984e-24+n*t,n=-29070369957882005e-24+n*t,n=42347877827932404e-23+n*t,n=-13654692000834679e-22+n*t,n=-13882523362786469e-21+n*t,n=.00018673420803405714+n*t,n=-.000740702534166267+n*t,n=-.006033670871430149+n*t,n=.24015818242558962+n*t,n=1.6536545626831027+n*t):t<16?(t=Math.sqrt(t)-3.25,n=22137376921775787e-25,n=9075656193888539e-23+n*t,n=-27517406297064545e-23+n*t,n=18239629214389228e-24+n*t,n=15027403968909828e-22+n*t,n=-4013867526981546e-21+n*t,n=29234449089955446e-22+n*t,n=12475304481671779e-21+n*t,n=-47318229009055734e-21+n*t,n=6828485145957318e-20+n*t,n=24031110387097894e-21+n*t,n=-.0003550375203628475+n*t,n=.0009532893797373805+n*t,n=-.0016882755560235047+n*t,n=.002491442096107851+n*t,n=-.003751208507569241+n*t,n=.005370914553590064+n*t,n=1.0052589676941592+n*t,n=3.0838856104922208+n*t):Number.isFinite(t)?(t=Math.sqrt(t)-5,n=-27109920616438573e-27,n=-2555641816996525e-25+n*t,n=15076572693500548e-25+n*t,n=-3789465440126737e-24+n*t,n=761570120807834e-23+n*t,n=-1496002662714924e-23+n*t,n=2914795345090108e-23+n*t,n=-6771199775845234e-23+n*t,n=22900482228026655e-23+n*t,n=-99298272942317e-20+n*t,n=4526062597223154e-21+n*t,n=-1968177810553167e-20+n*t,n=7599527703001776e-20+n*t,n=-.00021503011930044477+n*t,n=-.00013871931833623122+n*t,n=1.0103004648645344+n*t,n=4.849906401408584+n*t):n=1/0,n*e}function EA(e,t){let n,r;const i={mean(s){return arguments.length?(n=s||0,i):n},stdev(s){return arguments.length?(r=s??1,i):r},sample:()=>Oy(n,r),pdf:s=>wA(s,n,r),cdf:s=>Ly(s,n,r),icdf:s=>Iy(s,n,r)};return i.mean(e).stdev(t)}function AA(e,t){const n=EA();let r=0;const i={data(s){return arguments.length?(e=s,r=s?s.length:0,i.bandwidth(t)):e},bandwidth(s){return arguments.length?(t=s,!t&&e&&(t=_A(e)),i):t},sample(){return e[~~(Wi()*r)]+t*n.sample()},pdf(s){let o=0,a=0;for(;aSA(n,r),pdf:s=>kA(s,n,r),cdf:s=>CA(s,n,r),icdf:s=>$A(s,n,r)};return i.mean(e).stdev(t)}function jT(e,t){let n=0,r;function i(o){const a=[];let u=0,l;for(l=0;l=t&&e<=n?1/(n-t):0}function MA(e,t,n){return n==null&&(n=t??1,t=0),en?1:(e-t)/(n-t)}function RA(e,t,n){return n==null&&(n=t??1,t=0),e>=0&&e<=1?t+e*(n-t):NaN}function UT(e,t){let n,r;const i={min(s){return arguments.length?(n=s||0,i):n},max(s){return arguments.length?(r=s??1,i):r},sample:()=>FA(n,r),pdf:s=>DA(s,n,r),cdf:s=>MA(s,n,r),icdf:s=>RA(s,n,r)};return t==null&&(t=e??1,e=0),i.min(e).max(t)}function TA(e,t,n){let r=0,i=0;for(const s of e){const o=n(s);t(s)==null||o==null||isNaN(o)||(r+=(o-r)/++i)}return{coef:[r],predict:()=>r,rSquared:0}}function sg(e,t,n,r){const i=r-e*e,s=Math.abs(i)<1e-24?0:(n-e*t)/i;return[t-s*e,s]}function Py(e,t,n,r){e=e.filter(h=>{let p=t(h),g=n(h);return p!=null&&(p=+p)>=p&&g!=null&&(g=+g)>=g}),r&&e.sort((h,p)=>t(h)-t(p));const i=e.length,s=new Float64Array(i),o=new Float64Array(i);let a=0,u=0,l=0,c,f,d;for(d of e)s[a]=c=+t(d),o[a]=f=+n(d),++a,u+=(c-u)/a,l+=(f-l)/a;for(a=0;a=s&&o!=null&&(o=+o)>=o&&r(s,o,++i)}function Fd(e,t,n,r,i){let s=0,o=0;return og(e,t,n,(a,u)=>{const l=u-i(a),c=u-r;s+=l*l,o+=c*c}),1-s/o}function NA(e,t,n){let r=0,i=0,s=0,o=0,a=0;og(e,t,n,(c,f)=>{++a,r+=(c-r)/a,i+=(f-i)/a,s+=(c*f-s)/a,o+=(c*c-o)/a});const u=sg(r,i,s,o),l=c=>u[0]+u[1]*c;return{coef:u,predict:l,rSquared:Fd(e,t,n,i,l)}}function qT(e,t,n){let r=0,i=0,s=0,o=0,a=0;og(e,t,n,(c,f)=>{++a,c=Math.log(c),r+=(c-r)/a,i+=(f-i)/a,s+=(c*f-s)/a,o+=(c*c-o)/a});const u=sg(r,i,s,o),l=c=>u[0]+u[1]*Math.log(c);return{coef:u,predict:l,rSquared:Fd(e,t,n,i,l)}}function WT(e,t,n){const[r,i,s,o]=Py(e,t,n);let a=0,u=0,l=0,c=0,f=0,d,h,p;og(e,t,n,(v,b)=>{d=r[f++],h=Math.log(b),p=d*b,a+=(b*h-a)/f,u+=(p-u)/f,l+=(p*h-l)/f,c+=(d*p-c)/f});const[g,m]=sg(u/o,a/o,l/o,c/o),y=v=>Math.exp(g+m*(v-s));return{coef:[Math.exp(g-m*s),m],predict:y,rSquared:Fd(e,t,n,o,y)}}function HT(e,t,n){let r=0,i=0,s=0,o=0,a=0,u=0;og(e,t,n,(f,d)=>{const h=Math.log(f),p=Math.log(d);++u,r+=(h-r)/u,i+=(p-i)/u,s+=(h*p-s)/u,o+=(h*h-o)/u,a+=(d-a)/u});const l=sg(r,i,s,o),c=f=>l[0]*Math.pow(f,l[1]);return l[0]=Math.exp(l[0]),{coef:l,predict:c,rSquared:Fd(e,t,n,a,c)}}function OA(e,t,n){const[r,i,s,o]=Py(e,t,n),a=r.length;let u=0,l=0,c=0,f=0,d=0,h,p,g,m;for(h=0;h(E=E-s,b*E*E+x*E+_+o);return{coef:[_-x*s+b*s*s+o,x-2*b*s,b],predict:A,rSquared:Fd(e,t,n,o,A)}}function GT(e,t,n,r){if(r===0)return TA(e,t,n);if(r===1)return NA(e,t,n);if(r===2)return OA(e,t,n);const[i,s,o,a]=Py(e,t,n),u=i.length,l=[],c=[],f=r+1;let d,h,p,g,m;for(d=0;d{b-=o;let x=a+y[0]+y[1]*b+y[2]*b*b;for(d=3;d=0;--s)for(a=t[s],u=1,i[s]+=a,o=1;o<=s;++o)u*=(s+1-o)/o,i[s-o]+=a*Math.pow(n,o)*u;return i[0]+=r,i}function RV(e){const t=e.length-1,n=[];let r,i,s,o,a;for(r=0;rMath.abs(e[r][o])&&(o=i);for(s=r;s=r;s--)e[s][i]-=e[s][r]*e[r][i]/e[r][r]}for(i=t-1;i>=0;--i){for(a=0,s=i+1;si[b]-y?v:b;let _=0,A=0,E=0,S=0,k=0;const $=1/Math.abs(i[x]-y||1);for(let R=v;R<=b;++R){const F=i[R],C=s[R],T=TV(Math.abs(y-F)*$)*d[R],O=F*T;_+=T,A+=O,E+=C*T,S+=C*O,k+=F*O}const[D,M]=sg(A/_,E/_,S/_,k/_);c[m]=D+M*y,f[m]=Math.abs(s[m]-c[m]),NV(i,m+1,p)}if(h===_F)break;const g=TR(f);if(Math.abs(g)=1?wF:(v=1-y*y)*v}return OV(i,c,o,a)}function TV(e){return(e=1-e*e*e)*e*e}function NV(e,t,n){const r=e[t];let i=n[0],s=n[1]+1;if(!(s>=e.length))for(;t>i&&e[s]-r<=r-e[i];)n[0]=++i,n[1]=s,++s}function OV(e,t,n,r){const i=e.length,s=[];let o=0,a=0,u=[],l;for(;o[g,e(g)],s=t[0],o=t[1],a=o-s,u=a/r,l=[i(s)],c=[];if(n===r){for(let g=1;g0;)c.push(i(s+g/n*a))}let f=l[0],d=c[c.length-1];const h=1/a,p=IV(f[1],c);for(;d;){const g=i((f[0]+d[0])/2);g[0]-f[0]>=u&&PV(f,g,d,h,p)>LV?c.push(g):(f=d,l.push(d),c.pop()),d=c[c.length-1]}return l}function IV(e,t){let n=e,r=e;const i=t.length;for(let s=0;sr&&(r=o)}return 1/(r-n)}function PV(e,t,n,r,i){const s=Math.atan2(i*(n[1]-e[1]),r*(n[0]-e[0])),o=Math.atan2(i*(t[1]-e[1]),r*(t[0]-e[0]));return Math.abs(s-o)}function BV(e){return t=>{const n=e.length;let r=1,i=String(e[0](t));for(;r{},zV={init:n2,add:n2,rem:n2,idx:0},gp={values:{init:e=>e.cell.store=!0,value:e=>e.cell.data.values(),idx:-1},count:{value:e=>e.cell.num},__count__:{value:e=>e.missing+e.valid},missing:{value:e=>e.missing},valid:{value:e=>e.valid},sum:{init:e=>e.sum=0,value:e=>e.valid?e.sum:void 0,add:(e,t)=>e.sum+=+t,rem:(e,t)=>e.sum-=t},product:{init:e=>e.product=1,value:e=>e.valid?e.product:void 0,add:(e,t)=>e.product*=t,rem:(e,t)=>e.product/=t},mean:{init:e=>e.mean=0,value:e=>e.valid?e.mean:void 0,add:(e,t)=>(e.mean_d=t-e.mean,e.mean+=e.mean_d/e.valid),rem:(e,t)=>(e.mean_d=t-e.mean,e.mean-=e.valid?e.mean_d/e.valid:e.mean)},average:{value:e=>e.valid?e.mean:void 0,req:["mean"],idx:1},variance:{init:e=>e.dev=0,value:e=>e.valid>1?e.dev/(e.valid-1):void 0,add:(e,t)=>e.dev+=e.mean_d*(t-e.mean),rem:(e,t)=>e.dev-=e.mean_d*(t-e.mean),req:["mean"],idx:1},variancep:{value:e=>e.valid>1?e.dev/e.valid:void 0,req:["variance"],idx:2},stdev:{value:e=>e.valid>1?Math.sqrt(e.dev/(e.valid-1)):void 0,req:["variance"],idx:2},stdevp:{value:e=>e.valid>1?Math.sqrt(e.dev/e.valid):void 0,req:["variance"],idx:2},stderr:{value:e=>e.valid>1?Math.sqrt(e.dev/(e.valid*(e.valid-1))):void 0,req:["variance"],idx:2},distinct:{value:e=>e.cell.data.distinct(e.get),req:["values"],idx:3},ci0:{value:e=>e.cell.data.ci0(e.get),req:["values"],idx:3},ci1:{value:e=>e.cell.data.ci1(e.get),req:["values"],idx:3},median:{value:e=>e.cell.data.q2(e.get),req:["values"],idx:3},q1:{value:e=>e.cell.data.q1(e.get),req:["values"],idx:3},q3:{value:e=>e.cell.data.q3(e.get),req:["values"],idx:3},min:{init:e=>e.min=void 0,value:e=>e.min=Number.isNaN(e.min)?e.cell.data.min(e.get):e.min,add:(e,t)=>{(t{t<=e.min&&(e.min=NaN)},req:["values"],idx:4},max:{init:e=>e.max=void 0,value:e=>e.max=Number.isNaN(e.max)?e.cell.data.max(e.get):e.max,add:(e,t)=>{(t>e.max||e.max===void 0)&&(e.max=t)},rem:(e,t)=>{t>=e.max&&(e.max=NaN)},req:["values"],idx:4},argmin:{init:e=>e.argmin=void 0,value:e=>e.argmin||e.cell.data.argmin(e.get),add:(e,t,n)=>{t{t<=e.min&&(e.argmin=void 0)},req:["min","values"],idx:3},argmax:{init:e=>e.argmax=void 0,value:e=>e.argmax||e.cell.data.argmax(e.get),add:(e,t,n)=>{t>e.max&&(e.argmax=n)},rem:(e,t)=>{t>=e.max&&(e.argmax=void 0)},req:["max","values"],idx:3},exponential:{init:(e,t)=>{e.exp=0,e.exp_r=t},value:e=>e.valid?e.exp*(1-e.exp_r)/(1-e.exp_r**e.valid):void 0,add:(e,t)=>e.exp=e.exp_r*e.exp+t,rem:(e,t)=>e.exp=(e.exp-t/e.exp_r**(e.valid-1))/e.exp_r},exponentialb:{value:e=>e.valid?e.exp*(1-e.exp_r):void 0,req:["exponential"],idx:1}},ag=Object.keys(gp).filter(e=>e!=="__count__");function jV(e,t){return(n,r)=>We({name:e,aggregate_param:r,out:n||e},zV,t)}[...ag,"__count__"].forEach(e=>{gp[e]=jV(e,gp[e])});function XT(e,t,n){return gp[e](n,t)}function KT(e,t){return e.idx-t.idx}function UV(e){const t={};e.forEach(r=>t[r.name]=r);const n=r=>{r.req&&r.req.forEach(i=>{t[i]||n(t[i]=gp[i]())})};return e.forEach(n),Object.values(t).sort(KT)}function qV(){this.valid=0,this.missing=0,this._ops.forEach(e=>e.aggregate_param==null?e.init(this):e.init(this,e.aggregate_param))}function WV(e,t){if(e==null||e===""){++this.missing;return}e===e&&(++this.valid,this._ops.forEach(n=>n.add(this,e,t)))}function HV(e,t){if(e==null||e===""){--this.missing;return}e===e&&(--this.valid,this._ops.forEach(n=>n.rem(this,e,t)))}function GV(e){return this._out.forEach(t=>e[t.out]=t.value(this)),e}function ZT(e,t){const n=t||hr,r=UV(e),i=e.slice().sort(KT);function s(o){this._ops=r,this._out=i,this.cell=o,this.init()}return s.prototype.init=qV,s.prototype.add=WV,s.prototype.rem=HV,s.prototype.set=GV,s.prototype.get=n,s.fields=e.map(o=>o.out),s}function LA(e){this._key=e?Ui(e):Te,this.reset()}const Kn=LA.prototype;Kn.reset=function(){this._add=[],this._rem=[],this._ext=null,this._get=null,this._q=null};Kn.add=function(e){this._add.push(e)};Kn.rem=function(e){this._rem.push(e)};Kn.values=function(){if(this._get=null,this._rem.length===0)return this._add;const e=this._add,t=this._rem,n=this._key,r=e.length,i=t.length,s=Array(r-i),o={};let a,u,l;for(a=0;a=0;)s=e(t[r])+"",be(n,s)||(n[s]=1,++i);return i};Kn.extent=function(e){if(this._get!==e||!this._ext){const t=this.values(),n=gR(t,e);this._ext=[t[n[0]],t[n[1]]],this._get=e}return this._ext};Kn.argmin=function(e){return this.extent(e)[0]||{}};Kn.argmax=function(e){return this.extent(e)[1]||{}};Kn.min=function(e){const t=this.extent(e)[0];return t!=null?e(t):void 0};Kn.max=function(e){const t=this.extent(e)[1];return t!=null?e(t):void 0};Kn.quartile=function(e){return(this._get!==e||!this._q)&&(this._q=xA(this.values(),e),this._get=e),this._q};Kn.q1=function(e){return this.quartile(e)[0]};Kn.q2=function(e){return this.quartile(e)[1]};Kn.q3=function(e){return this.quartile(e)[2]};Kn.ci=function(e){return(this._get!==e||!this._ci)&&(this._ci=IT(this.values(),1e3,.05,e),this._get=e),this._ci};Kn.ci0=function(e){return this.ci(e)[0]};Kn.ci1=function(e){return this.ci(e)[1]};function hu(e){G.call(this,null,e),this._adds=[],this._mods=[],this._alen=0,this._mlen=0,this._drop=!0,this._cross=!1,this._dims=[],this._dnames=[],this._measures=[],this._countOnly=!1,this._counts=null,this._prev=null,this._inputs=null,this._outputs=null}hu.Definition={type:"Aggregate",metadata:{generates:!0,changes:!0},params:[{name:"groupby",type:"field",array:!0},{name:"ops",type:"enum",array:!0,values:ag},{name:"aggregate_params",type:"number",null:!0,array:!0},{name:"fields",type:"field",null:!0,array:!0},{name:"as",type:"string",null:!0,array:!0},{name:"drop",type:"boolean",default:!0},{name:"cross",type:"boolean",default:!1},{name:"key",type:"field"}]};he(hu,G,{transform(e,t){const n=this,r=t.fork(t.NO_SOURCE|t.NO_FIELDS),i=e.modified();return n.stamp=r.stamp,n.value&&(i||t.modified(n._inputs,!0))?(n._prev=n.value,n.value=i?n.init(e):Object.create(null),t.visit(t.SOURCE,s=>n.add(s))):(n.value=n.value||n.init(e),t.visit(t.REM,s=>n.rem(s)),t.visit(t.ADD,s=>n.add(s))),r.modifies(n._outputs),n._drop=e.drop!==!1,e.cross&&n._dims.length>1&&(n._drop=!1,n.cross()),t.clean()&&n._drop&&r.clean(!0).runAfter(()=>this.clean()),n.changes(r)},cross(){const e=this,t=e.value,n=e._dnames,r=n.map(()=>({})),i=n.length;function s(a){let u,l,c,f;for(u in a)for(c=a[u].tuple,l=0;l{const b=en(v);return i(v),n.push(b),b}),this.cellkey=e.key?e.key:b_(this._dims),this._countOnly=!0,this._counts=[],this._measures=[];const s=e.fields||[null],o=e.ops||["count"],a=e.aggregate_params||[null],u=e.as||[],l=s.length,c={};let f,d,h,p,g,m,y;for(l!==o.length&&X("Unmatched number of fields and aggregate ops."),y=0;yZT(v,v.field)),Object.create(null)},cellkey:b_(),cell(e,t){let n=this.value[e];return n?n.num===0&&this._drop&&n.stamp{const f=r(c);c[a]=f,c[u]=f==null?null:i+s*(1+(f-i)/s)}:c=>c[a]=r(c)),t.modifies(n?o:a)},_bins(e){if(this.value&&!e.modified())return this.value;const t=e.field,n=LT(e),r=n.step;let i=n.start,s=i+Math.ceil((n.stop-i)/r)*r,o,a;(o=e.anchor)!=null&&(a=o-(i+r*Math.floor((o-i)/r)),i+=a,s+=a);const u=function(l){let c=sr(t(l));return c==null?null:cs?1/0:(c=Math.max(i,Math.min(c,s-r)),i+r*Math.floor(YV+(c-i)/r))};return u.start=i,u.stop=n.stop,u.step=r,this.value=Qr(u,ar(t),e.name||"bin_"+en(t))}});function JT(e,t,n){const r=e;let i=t||[],s=n||[],o={},a=0;return{add:u=>s.push(u),remove:u=>o[r(u)]=++a,size:()=>i.length,data:(u,l)=>(a&&(i=i.filter(c=>!o[r(c)]),o={},a=0),l&&u&&i.sort(u),s.length&&(i=u?xR(u,i,s.sort(u)):i.concat(s),s=[]),i)}}function PA(e){G.call(this,[],e)}PA.Definition={type:"Collect",metadata:{source:!0},params:[{name:"sort",type:"compare"}]};he(PA,G,{transform(e,t){const n=t.fork(t.ALL),r=JT(Te,this.value,n.materialize(n.ADD).add),i=e.sort,s=t.changed()||i&&(e.modified("sort")||t.modified(i.fields));return n.visit(n.REM,r.remove),this.modified(s),this.value=n.source=r.data(yc(i),s),t.source&&t.source.root&&(this.value.root=t.source.root),n}});function QT(e){$t.call(this,null,VV,e)}he(QT,$t);function VV(e){return this.value&&!e.modified()?this.value:ZE(e.fields,e.orders)}function BA(e){G.call(this,null,e)}BA.Definition={type:"CountPattern",metadata:{generates:!0,changes:!0},params:[{name:"field",type:"field",required:!0},{name:"case",type:"enum",values:["upper","lower","mixed"],default:"mixed"},{name:"pattern",type:"string",default:'[\\w"]+'},{name:"stopwords",type:"string",default:""},{name:"as",type:"string",array:!0,length:2,default:["text","count"]}]};function XV(e,t,n){switch(t){case"upper":e=e.toUpperCase();break;case"lower":e=e.toLowerCase();break}return e.match(n)}he(BA,G,{transform(e,t){const n=f=>d=>{for(var h=XV(a(d),e.case,s)||[],p,g=0,m=h.length;gi[f]=1+(i[f]||0)),c=n(f=>i[f]-=1);return r?t.visit(t.SOURCE,l):(t.visit(t.ADD,l),t.visit(t.REM,c)),this._finish(t,u)},_parameterCheck(e,t){let n=!1;return(e.modified("stopwords")||!this._stop)&&(this._stop=new RegExp("^"+(e.stopwords||"")+"$","i"),n=!0),(e.modified("pattern")||!this._match)&&(this._match=new RegExp(e.pattern||"[\\w']+","g"),n=!0),(e.modified("field")||t.modified(e.field.fields))&&(n=!0),n&&(this._counts={}),n},_finish(e,t){const n=this._counts,r=this._tuples||(this._tuples={}),i=t[0],s=t[1],o=e.fork(e.NO_SOURCE|e.NO_FIELDS);let a,u,l;for(a in n)u=r[a],l=n[a]||0,!u&&l?(r[a]=u=gt({}),u[i]=a,u[s]=l,o.add.push(u)):l===0?(u&&o.rem.push(u),n[a]=null,r[a]=null):u[s]!==l&&(u[s]=l,o.mod.push(u));return o.modifies(t)}});function zA(e){G.call(this,null,e)}zA.Definition={type:"Cross",metadata:{generates:!0},params:[{name:"filter",type:"expr"},{name:"as",type:"string",array:!0,length:2,default:["a","b"]}]};he(zA,G,{transform(e,t){const n=t.fork(t.NO_SOURCE),r=e.as||["a","b"],i=r[0],s=r[1],o=!this.value||t.changed(t.ADD_REM)||e.modified("as")||e.modified("filter");let a=this.value;return o?(a&&(n.rem=a),a=t.materialize(t.SOURCE).source,n.add=this.value=KV(a,i,s,e.filter||yi)):n.mod=a,n.source=this.value,n.modifies(r)}});function KV(e,t,n,r){for(var i=[],s={},o=e.length,a=0,u,l;aeN(s,t))):typeof r[i]===AF&&r[i](e[i]);return r}function jA(e){G.call(this,null,e)}const tN=[{key:{function:"normal"},params:[{name:"mean",type:"number",default:0},{name:"stdev",type:"number",default:1}]},{key:{function:"lognormal"},params:[{name:"mean",type:"number",default:0},{name:"stdev",type:"number",default:1}]},{key:{function:"uniform"},params:[{name:"min",type:"number",default:0},{name:"max",type:"number",default:1}]},{key:{function:"kde"},params:[{name:"field",type:"field",required:!0},{name:"from",type:"data"},{name:"bandwidth",type:"number",default:0}]}],QV={key:{function:"mixture"},params:[{name:"distributions",type:"param",array:!0,params:tN},{name:"weights",type:"number",array:!0}]};jA.Definition={type:"Density",metadata:{generates:!0},params:[{name:"extent",type:"number",array:!0,length:2},{name:"steps",type:"number"},{name:"minsteps",type:"number",default:25},{name:"maxsteps",type:"number",default:200},{name:"method",type:"string",default:"pdf",values:["pdf","cdf"]},{name:"distribution",type:"param",params:tN.concat(QV)},{name:"as",type:"string",array:!0,default:["value","density"]}]};he(jA,G,{transform(e,t){const n=t.fork(t.NO_SOURCE|t.NO_FIELDS);if(!this.value||t.changed()||e.modified()){const r=eN(e.distribution,eX(t)),i=e.steps||e.minsteps||25,s=e.steps||e.maxsteps||200;let o=e.method||"pdf";o!=="pdf"&&o!=="cdf"&&X("Invalid density method: "+o),!e.extent&&!r.data&&X("Missing density extent parameter."),o=r[o];const a=e.as||["value","density"],u=e.extent||mo(r.data()),l=By(o,u,i,s).map(c=>{const f={};return f[a[0]]=c[0],f[a[1]]=c[1],gt(f)});this.value&&(n.rem=this.value),this.value=n.add=n.source=l}return n}});function eX(e){return()=>e.materialize(e.SOURCE).source}function nN(e,t){return e?e.map((n,r)=>t[r]||en(n)):null}function UA(e,t,n){const r=[],i=f=>f(u);let s,o,a,u,l,c;if(t==null)r.push(e.map(n));else for(s={},o=0,a=e.length;oig(mo(e,t))/30;he(qA,G,{transform(e,t){if(this.value&&!(e.modified()||t.changed()))return t;const n=t.materialize(t.SOURCE).source,r=UA(t.source,e.groupby,hr),i=e.smooth||!1,s=e.field,o=e.step||tX(n,s),a=yc((p,g)=>s(p)-s(g)),u=e.as||rN,l=r.length;let c=1/0,f=-1/0,d=0,h;for(;df&&(f=g),p[++h][u]=g}return this.value={start:c,stop:f,step:o},t.reflow(!0).modifies(u)}});function iN(e){$t.call(this,null,nX,e),this.modified(!0)}he(iN,$t);function nX(e){const t=e.expr;return this.value&&!e.modified("expr")?this.value:Qr(n=>t(n,e),ar(t),en(t))}function WA(e){G.call(this,[void 0,void 0],e)}WA.Definition={type:"Extent",metadata:{},params:[{name:"field",type:"field",required:!0}]};he(WA,G,{transform(e,t){const n=this.value,r=e.field,i=t.changed()||t.modified(r.fields)||e.modified("field");let s=n[0],o=n[1];if((i||s==null)&&(s=1/0,o=-1/0),t.visit(i?t.SOURCE:t.ADD,a=>{const u=sr(r(a));u!=null&&(uo&&(o=u))}),!Number.isFinite(s)||!Number.isFinite(o)){let a=en(r);a&&(a=` for field "${a}"`),t.dataflow.warn(`Infinite extent${a}: [${s}, ${o}]`),s=o=void 0}this.value=[s,o]}});function HA(e,t){$t.call(this,e),this.parent=t,this.count=0}he(HA,$t,{connect(e){return this.detachSubflow=e.detachSubflow,this.targets().add(e),e.source=this},add(e){this.count+=1,this.value.add.push(e)},rem(e){this.count-=1,this.value.rem.push(e)},mod(e){this.value.mod.push(e)},init(e){this.value.init(e,e.NO_SOURCE)},evaluate(){return this.value}});function zy(e){G.call(this,{},e),this._keys=Ed();const t=this._targets=[];t.active=0,t.forEach=n=>{for(let r=0,i=t.active;rr&&r.count>0);this.initTargets(n)}},initTargets(e){const t=this._targets,n=t.length,r=e?e.length:0;let i=0;for(;ithis.subflow(u,i,t);return this._group=e.group||{},this.initTargets(),t.visit(t.REM,u=>{const l=Te(u),c=s.get(l);c!==void 0&&(s.delete(l),a(c).rem(u))}),t.visit(t.ADD,u=>{const l=r(u);s.set(Te(u),l),a(l).add(u)}),o||t.modified(r.fields)?t.visit(t.MOD,u=>{const l=Te(u),c=s.get(l),f=r(u);c===f?a(f).mod(u):(s.set(l,f),a(c).rem(u),a(f).add(u))}):t.changed(t.MOD)&&t.visit(t.MOD,u=>{a(s.get(Te(u))).mod(u)}),o&&t.visit(t.REFLOW,u=>{const l=Te(u),c=s.get(l),f=r(u);c!==f&&(s.set(l,f),a(c).rem(u),a(f).add(u))}),t.clean()?n.runAfter(()=>{this.clean(),s.clean()}):s.empty>n.cleanThreshold&&n.runAfter(s.clean),t}});function sN(e){$t.call(this,null,rX,e)}he(sN,$t);function rX(e){return this.value&&!e.modified()?this.value:ee(e.name)?ye(e.name).map(t=>Ui(t)):Ui(e.name,e.as)}function GA(e){G.call(this,Ed(),e)}GA.Definition={type:"Filter",metadata:{changes:!0},params:[{name:"expr",type:"expr",required:!0}]};he(GA,G,{transform(e,t){const n=t.dataflow,r=this.value,i=t.fork(),s=i.add,o=i.rem,a=i.mod,u=e.expr;let l=!0;t.visit(t.REM,f=>{const d=Te(f);r.has(d)?r.delete(d):o.push(f)}),t.visit(t.ADD,f=>{u(f,e)?s.push(f):r.set(Te(f),1)});function c(f){const d=Te(f),h=u(f,e),p=r.get(d);h&&p?(r.delete(d),s.push(f)):!h&&!p?(r.set(d,1),o.push(f)):l&&h&&!p&&a.push(f)}return t.visit(t.MOD,c),e.modified()&&(l=!1,t.visit(t.REFLOW,c)),r.empty>n.cleanThreshold&&n.runAfter(r.clean),i}});function YA(e){G.call(this,[],e)}YA.Definition={type:"Flatten",metadata:{generates:!0},params:[{name:"fields",type:"field",array:!0,required:!0},{name:"index",type:"string"},{name:"as",type:"string",array:!0}]};he(YA,G,{transform(e,t){const n=t.fork(t.NO_SOURCE),r=e.fields,i=nN(r,e.as||[]),s=e.index||null,o=i.length;return n.rem=this.value,t.visit(t.SOURCE,a=>{const u=r.map(p=>p(a)),l=u.reduce((p,g)=>Math.max(p,g.length),0);let c=0,f,d,h;for(;c{for(let c=0,f;co[r]=n(o,e))}});function oN(e){G.call(this,[],e)}he(oN,G,{transform(e,t){const n=t.fork(t.ALL),r=e.generator;let i=this.value,s=e.size-i.length,o,a,u;if(s>0){for(o=[];--s>=0;)o.push(u=gt(r(e))),i.push(u);n.add=n.add.length?n.materialize(n.ADD).add.concat(o):o}else a=i.slice(0,-s),n.rem=n.rem.length?n.materialize(n.REM).rem.concat(a):a,i=i.slice(-s);return n.source=this.value=i,n}});const s0={value:"value",median:TR,mean:BH,min:u_,max:kl},iX=[];function KA(e){G.call(this,[],e)}KA.Definition={type:"Impute",metadata:{changes:!0},params:[{name:"field",type:"field",required:!0},{name:"key",type:"field",required:!0},{name:"keyvals",array:!0},{name:"groupby",type:"field",array:!0},{name:"method",type:"enum",default:"value",values:["value","mean","median","max","min"]},{name:"value",default:0}]};function sX(e){var t=e.method||s0.value,n;if(s0[t]==null)X("Unrecognized imputation method: "+t);else return t===s0.value?(n=e.value!==void 0?e.value:0,()=>n):s0[t]}function oX(e){const t=e.field;return n=>n?t(n):NaN}he(KA,G,{transform(e,t){var n=t.fork(t.ALL),r=sX(e),i=oX(e),s=en(e.field),o=en(e.key),a=(e.groupby||[]).map(en),u=aX(t.source,e.groupby,e.key,e.keyvals),l=[],c=this.value,f=u.domain.length,d,h,p,g,m,y,v,b,x,_;for(m=0,b=u.length;my(m),s=[],o=r?r.slice():[],a={},u={},l,c,f,d,h,p,g,m;for(o.forEach((y,v)=>a[y]=v+1),d=0,g=e.length;dn.add(s))):(i=n.value=n.value||this.init(e),t.visit(t.REM,s=>n.rem(s)),t.visit(t.ADD,s=>n.add(s))),n.changes(),t.visit(t.SOURCE,s=>{We(s,i[n.cellkey(s)].tuple)}),t.reflow(r).modifies(this._outputs)},changes(){const e=this._adds,t=this._mods;let n,r;for(n=0,r=this._alen;n{const p=AA(h,o)[a],g=e.counts?h.length:1,m=c||mo(h);By(p,m,f,d).forEach(y=>{const v={};for(let b=0;b(this._pending=ye(i.data),s=>s.touch(this)))}:n.request(e.url,e.format).then(r=>r2(this,t,ye(r.data)))}});function lX(e){return e.modified("async")&&!(e.modified("values")||e.modified("url")||e.modified("format"))}function r2(e,t,n){n.forEach(gt);const r=t.fork(t.NO_FIELDS&t.NO_SOURCE);return r.rem=e.value,e.value=r.source=r.add=n,e._pending=null,r.rem.length&&r.clean(!0),r}function QA(e){G.call(this,{},e)}QA.Definition={type:"Lookup",metadata:{modifies:!0},params:[{name:"index",type:"index",params:[{name:"from",type:"data",required:!0},{name:"key",type:"field",required:!0}]},{name:"values",type:"field",array:!0},{name:"fields",type:"field",array:!0,required:!0},{name:"as",type:"string",array:!0},{name:"default",default:null}]};he(QA,G,{transform(e,t){const n=e.fields,r=e.index,i=e.values,s=e.default==null?null:e.default,o=e.modified(),a=n.length;let u=o?t.SOURCE:t.ADD,l=t,c=e.as,f,d,h;return i?(d=i.length,a>1&&!c&&X('Multi-field lookup requires explicit "as" parameter.'),c&&c.length!==a*d&&X('The "as" parameter has too few output field names.'),c=c||i.map(en),f=function(p){for(var g=0,m=0,y,v;gt.modified(p.fields)),u|=h?t.MOD:0),t.visit(u,f),l.modifies(c)}});function lN(e){$t.call(this,null,cX,e)}he(lN,$t);function cX(e){if(this.value&&!e.modified())return this.value;const t=e.extents,n=t.length;let r=1/0,i=-1/0,s,o;for(s=0;si&&(i=o[1]);return[r,i]}function cN(e){$t.call(this,null,fX,e)}he(cN,$t);function fX(e){return this.value&&!e.modified()?this.value:e.values.reduce((t,n)=>t.concat(n),[])}function fN(e){G.call(this,null,e)}he(fN,G,{transform(e,t){return this.modified(e.modified()),this.value=e,t.fork(t.NO_SOURCE|t.NO_FIELDS)}});function eS(e){hu.call(this,e)}eS.Definition={type:"Pivot",metadata:{generates:!0,changes:!0},params:[{name:"groupby",type:"field",array:!0},{name:"field",type:"field",required:!0},{name:"value",type:"field",required:!0},{name:"op",type:"enum",values:ag,default:"sum"},{name:"limit",type:"number",default:0},{name:"key",type:"field"}]};he(eS,hu,{_transform:hu.prototype.transform,transform(e,t){return this._transform(dX(e,t),t)}});function dX(e,t){const n=e.field,r=e.value,i=(e.op==="count"?"__count__":e.op)||"sum",s=ar(n).concat(ar(r)),o=pX(n,e.limit||0,t);return t.changed()&&e.set("__pivot__",null,null,!0),{key:e.key,groupby:e.groupby,ops:o.map(()=>i),fields:o.map(a=>hX(a,n,r,s)),as:o.map(a=>a+""),modified:e.modified.bind(e)}}function hX(e,t,n,r){return Qr(i=>t(i)===e?n(i):NaN,r,e+"")}function pX(e,t,n){const r={},i=[];return n.visit(n.SOURCE,s=>{const o=e(s);r[o]||(r[o]=1,i.push(o))}),i.sort(wd),t?i.slice(0,t):i}function dN(e){zy.call(this,e)}he(dN,zy,{transform(e,t){const n=e.subflow,r=e.field,i=s=>this.subflow(Te(s),n,t,s);return(e.modified("field")||r&&t.modified(ar(r)))&&X("PreFacet does not support field modification."),this.initTargets(),r?(t.visit(t.MOD,s=>{const o=i(s);r(s).forEach(a=>o.mod(a))}),t.visit(t.ADD,s=>{const o=i(s);r(s).forEach(a=>o.add(gt(a)))}),t.visit(t.REM,s=>{const o=i(s);r(s).forEach(a=>o.rem(a))})):(t.visit(t.MOD,s=>i(s).mod(s)),t.visit(t.ADD,s=>i(s).add(s)),t.visit(t.REM,s=>i(s).rem(s))),t.clean()&&t.runAfter(()=>this.clean()),t}});function tS(e){G.call(this,null,e)}tS.Definition={type:"Project",metadata:{generates:!0,changes:!0},params:[{name:"fields",type:"field",array:!0},{name:"as",type:"string",null:!0,array:!0}]};he(tS,G,{transform(e,t){const n=t.fork(t.NO_SOURCE),r=e.fields,i=nN(e.fields,e.as||[]),s=r?(a,u)=>gX(a,u,r,i):Ry;let o;return this.value?o=this.value:(t=t.addAll(),o=this.value={}),t.visit(t.REM,a=>{const u=Te(a);n.rem.push(o[u]),o[u]=null}),t.visit(t.ADD,a=>{const u=s(a,gt({}));o[Te(a)]=u,n.add.push(u)}),t.visit(t.MOD,a=>{n.mod.push(s(a,o[Te(a)]))}),n}});function gX(e,t,n,r){for(let i=0,s=n.length;i{const d=bA(f,l);for(let h=0;h{const s=Te(i);n.rem.push(r[s]),r[s]=null}),t.visit(t.ADD,i=>{const s=mA(i);r[Te(i)]=s,n.add.push(s)}),t.visit(t.MOD,i=>{const s=r[Te(i)];for(const o in i)s[o]=i[o],n.modifies(o);n.mod.push(s)})),n}});function rS(e){G.call(this,[],e),this.count=0}rS.Definition={type:"Sample",metadata:{},params:[{name:"size",type:"number",default:1e3}]};he(rS,G,{transform(e,t){const n=t.fork(t.NO_SOURCE),r=e.modified("size"),i=e.size,s=this.value.reduce((c,f)=>(c[Te(f)]=1,c),{});let o=this.value,a=this.count,u=0;function l(c){let f,d;o.length=u&&(f=o[d],s[Te(f)]&&n.rem.push(f),o[d]=c)),++a}if(t.rem.length&&(t.visit(t.REM,c=>{const f=Te(c);s[f]&&(s[f]=-1,n.rem.push(c)),--a}),o=o.filter(c=>s[Te(c)]!==-1)),(t.rem.length||r)&&o.length{s[Te(c)]||l(c)}),u=-1),r&&o.length>i){const c=o.length-i;for(let f=0;f{s[Te(c)]&&n.mod.push(c)}),t.add.length&&t.visit(t.ADD,l),(t.add.length||u<0)&&(n.add=o.filter(c=>!s[Te(c)])),this.count=a,this.value=n.source=o,n}});function iS(e){G.call(this,null,e)}iS.Definition={type:"Sequence",metadata:{generates:!0,changes:!0},params:[{name:"start",type:"number",required:!0},{name:"stop",type:"number",required:!0},{name:"step",type:"number",default:1},{name:"as",type:"string",default:"data"}]};he(iS,G,{transform(e,t){if(this.value&&!e.modified())return;const n=t.materialize().fork(t.MOD),r=e.as||"data";return n.rem=this.value?t.rem.concat(this.value):t.rem,this.value=ci(e.start,e.stop,e.step||1).map(i=>{const s={};return s[r]=i,gt(s)}),n.add=t.add.concat(this.value),n}});function gN(e){G.call(this,null,e),this.modified(!0)}he(gN,G,{transform(e,t){return this.value=t.source,t.changed()?t.fork(t.NO_SOURCE|t.NO_FIELDS):t.StopPropagation}});function sS(e){G.call(this,null,e)}const mN=["unit0","unit1"];sS.Definition={type:"TimeUnit",metadata:{modifies:!0},params:[{name:"field",type:"field",required:!0},{name:"interval",type:"boolean",default:!0},{name:"units",type:"enum",values:aA,array:!0},{name:"step",type:"number",default:1},{name:"maxbins",type:"number",default:40},{name:"extent",type:"date",array:!0},{name:"timezone",type:"enum",default:"local",values:["local","utc"]},{name:"as",type:"string",array:!0,length:2,default:mN}]};he(sS,G,{transform(e,t){const n=e.field,r=e.interval!==!1,i=e.timezone==="utc",s=this._floor(e,t),o=(i?$d:Cd)(s.unit).offset,a=e.as||mN,u=a[0],l=a[1],c=s.step;let f=s.start||1/0,d=s.stop||-1/0,h=t.ADD;return(e.modified()||t.changed(t.REM)||t.modified(ar(n)))&&(t=t.reflow(!0),h=t.SOURCE,f=1/0,d=-1/0),t.visit(h,p=>{const g=n(p);let m,y;g==null?(p[u]=null,r&&(p[l]=null)):(p[u]=m=y=s(g),r&&(p[l]=y=o(m,c)),md&&(d=y))}),s.start=f,s.stop=d,t.modifies(r?a:u)},_floor(e,t){const n=e.timezone==="utc",{units:r,step:i}=e.units?{units:e.units,step:e.step||1}:oT({extent:e.extent||mo(t.materialize(t.SOURCE).source,e.field),maxbins:e.maxbins}),s=uA(r),o=this.value||{},a=(n?ZR:KR)(s,i);return a.unit=st(s),a.units=s,a.step=i,a.start=o.start,a.stop=o.stop,this.value=a}});function yN(e){G.call(this,Ed(),e)}he(yN,G,{transform(e,t){const n=t.dataflow,r=e.field,i=this.value,s=a=>i.set(r(a),a);let o=!0;return e.modified("field")||t.modified(r.fields)?(i.clear(),t.visit(t.SOURCE,s)):t.changed()?(t.visit(t.REM,a=>i.delete(r(a))),t.visit(t.ADD,s)):o=!1,this.modified(o),i.empty>n.cleanThreshold&&n.runAfter(i.clean),t.fork()}});function vN(e){G.call(this,null,e)}he(vN,G,{transform(e,t){(!this.value||e.modified("field")||e.modified("sort")||t.changed()||e.sort&&t.modified(e.sort.fields))&&(this.value=(e.sort?t.source.slice().sort(yc(e.sort)):t.source).map(e.field))}});function yX(e,t,n,r){const i=mp[e](t,n);return{init:i.init||ja,update:function(s,o){o[r]=i.next(s)}}}const mp={row_number:function(){return{next:e=>e.index+1}},rank:function(){let e;return{init:()=>e=1,next:t=>{const n=t.index,r=t.data;return n&&t.compare(r[n-1],r[n])?e=n+1:e}}},dense_rank:function(){let e;return{init:()=>e=1,next:t=>{const n=t.index,r=t.data;return n&&t.compare(r[n-1],r[n])?++e:e}}},percent_rank:function(){const e=mp.rank(),t=e.next;return{init:e.init,next:n=>(t(n)-1)/(n.data.length-1)}},cume_dist:function(){let e;return{init:()=>e=0,next:t=>{const n=t.data,r=t.compare;let i=t.index;if(e0||X("ntile num must be greater than zero.");const n=mp.cume_dist(),r=n.next;return{init:n.init,next:i=>Math.ceil(t*r(i))}},lag:function(e,t){return t=+t||1,{next:n=>{const r=n.index-t;return r>=0?e(n.data[r]):null}}},lead:function(e,t){return t=+t||1,{next:n=>{const r=n.index+t,i=n.data;return re(t.data[t.i0])}},last_value:function(e){return{next:t=>e(t.data[t.i1-1])}},nth_value:function(e,t){return t=+t,t>0||X("nth_value nth must be greater than zero."),{next:n=>{const r=n.i0+(t-1);return rt=null,next:n=>{const r=e(n.data[n.index]);return r!=null?t=r:t}}},next_value:function(e){let t,n;return{init:()=>(t=null,n=-1),next:r=>{const i=r.data;return r.index<=n?t:(n=vX(e,i,r.index))<0?(n=i.length,t=null):t=e(i[n])}}}};function vX(e,t,n){for(let r=t.length;nu[g]=1)}h(e.sort),t.forEach((p,g)=>{const m=n[g],y=r[g],v=i[g]||null,b=en(m),x=VT(p,b,s[g]);if(h(m),o.push(x),be(mp,p))a.push(yX(p,m,y,x));else{if(m==null&&p!=="count"&&X("Null aggregate field specified."),p==="count"){c.push(x);return}d=!1;let _=l[b];_||(_=l[b]=[],_.field=m,f.push(_)),_.push(XT(p,v,x))}}),(c.length||f.length)&&(this.cell=xX(f,c,d)),this.inputs=Object.keys(u)}const xN=bN.prototype;xN.init=function(){this.windows.forEach(e=>e.init()),this.cell&&this.cell.init()};xN.update=function(e,t){const n=this.cell,r=this.windows,i=e.data,s=r&&r.length;let o;if(n){for(o=e.p0;oZT(u,u.field));const r={num:0,agg:null,store:!1,count:t};if(!n)for(var i=e.length,s=r.agg=Array(i),o=0;othis.group(i(a));let o=this.state;(!o||n)&&(o=this.state=new bN(e)),n||t.modified(o.inputs)?(this.value={},t.visit(t.SOURCE,a=>s(a).add(a))):(t.visit(t.REM,a=>s(a).remove(a)),t.visit(t.ADD,a=>s(a).add(a)));for(let a=0,u=this._mlen;a0&&!i(s[n],s[n-1])&&(e.i0=t.left(s,s[n])),r1?0:e<-1?jf:Math.acos(e)}function kF(e){return e>=1?zm:e<=-1?-zm:Math.asin(e)}const x_=Math.PI,__=2*x_,il=1e-6,CX=__-il;function wN(e){this._+=e[0];for(let t=1,n=e.length;t=0))throw new Error(`invalid digits: ${e}`);if(t>15)return wN;const n=10**t;return function(r){this._+=r[0];for(let i=1,s=r.length;iil)if(!(Math.abs(f*u-l*c)>il)||!s)this._append`L${this._x1=t},${this._y1=n}`;else{let h=r-o,p=i-a,g=u*u+l*l,m=h*h+p*p,y=Math.sqrt(g),v=Math.sqrt(d),b=s*Math.tan((x_-Math.acos((g+d-m)/(2*y*v)))/2),x=b/v,_=b/y;Math.abs(x-1)>il&&this._append`L${t+x*c},${n+x*f}`,this._append`A${s},${s},0,0,${+(f*h>c*p)},${this._x1=t+_*u},${this._y1=n+_*l}`}}arc(t,n,r,i,s,o){if(t=+t,n=+n,r=+r,o=!!o,r<0)throw new Error(`negative radius: ${r}`);let a=r*Math.cos(i),u=r*Math.sin(i),l=t+a,c=n+u,f=1^o,d=o?i-s:s-i;this._x1===null?this._append`M${l},${c}`:(Math.abs(this._x1-l)>il||Math.abs(this._y1-c)>il)&&this._append`L${l},${c}`,r&&(d<0&&(d=d%__+__),d>CX?this._append`A${r},${r},0,1,${f},${t-a},${n-u}A${r},${r},0,1,${f},${this._x1=l},${this._y1=c}`:d>il&&this._append`A${r},${r},0,${+(d>=x_)},${f},${this._x1=t+r*Math.cos(s)},${this._y1=n+r*Math.sin(s)}`)}rect(t,n,r,i){this._append`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}h${r=+r}v${+i}h${-r}Z`}toString(){return this._}};function jy(){return new aS}jy.prototype=aS.prototype;function Uy(e){let t=3;return e.digits=function(n){if(!arguments.length)return t;if(n==null)t=null;else{const r=Math.floor(n);if(!(r>=0))throw new RangeError(`invalid digits: ${n}`);t=r}return e},()=>new aS(t)}function FX(e){return e.innerRadius}function DX(e){return e.outerRadius}function MX(e){return e.startAngle}function RX(e){return e.endAngle}function TX(e){return e&&e.padAngle}function NX(e,t,n,r,i,s,o,a){var u=n-e,l=r-t,c=o-i,f=a-s,d=f*u-c*l;if(!(d*dF*F+C*C&&(S=$,k=D),{cx:S,cy:k,x01:-c,y01:-f,x11:S*(i/_-1),y11:k*(i/_-1)}}function OX(){var e=FX,t=DX,n=mt(0),r=null,i=MX,s=RX,o=TX,a=null,u=Uy(l);function l(){var c,f,d=+e.apply(this,arguments),h=+t.apply(this,arguments),p=i.apply(this,arguments)-zm,g=s.apply(this,arguments)-zm,m=SF(g-p),y=g>p;if(a||(a=c=u()),htr))a.moveTo(0,0);else if(m>_N-tr)a.moveTo(h*Yu(p),h*js(p)),a.arc(0,0,h,p,g,!y),d>tr&&(a.moveTo(d*Yu(g),d*js(g)),a.arc(0,0,d,g,p,y));else{var v=p,b=g,x=p,_=g,A=m,E=m,S=o.apply(this,arguments)/2,k=S>tr&&(r?+r.apply(this,arguments):ml(d*d+h*h)),$=i2(SF(h-d)/2,+n.apply(this,arguments)),D=$,M=$,R,F;if(k>tr){var C=kF(k/d*js(S)),T=kF(k/h*js(S));(A-=C*2)>tr?(C*=y?1:-1,x+=C,_-=C):(A=0,x=_=(p+g)/2),(E-=T*2)>tr?(T*=y?1:-1,v+=T,b-=T):(E=0,v=b=(p+g)/2)}var O=h*Yu(v),N=h*js(v),L=d*Yu(_),z=d*js(_);if($>tr){var U=h*Yu(b),Q=h*js(b),de=d*Yu(x),we=d*js(x),ne;if(mtr?M>tr?(R=o0(de,we,O,N,h,M,y),F=o0(U,Q,L,z,h,M,y),a.moveTo(R.cx+R.x01,R.cy+R.y01),M<$?a.arc(R.cx,R.cy,M,Qn(R.y01,R.x01),Qn(F.y01,F.x01),!y):(a.arc(R.cx,R.cy,M,Qn(R.y01,R.x01),Qn(R.y11,R.x11),!y),a.arc(0,0,h,Qn(R.cy+R.y11,R.cx+R.x11),Qn(F.cy+F.y11,F.cx+F.x11),!y),a.arc(F.cx,F.cy,M,Qn(F.y11,F.x11),Qn(F.y01,F.x01),!y))):(a.moveTo(O,N),a.arc(0,0,h,v,b,!y)):a.moveTo(O,N),!(d>tr)||!(A>tr)?a.lineTo(L,z):D>tr?(R=o0(L,z,U,Q,d,-D,y),F=o0(O,N,de,we,d,-D,y),a.lineTo(R.cx+R.x01,R.cy+R.y01),D<$?a.arc(R.cx,R.cy,D,Qn(R.y01,R.x01),Qn(F.y01,F.x01),!y):(a.arc(R.cx,R.cy,D,Qn(R.y01,R.x01),Qn(R.y11,R.x11),!y),a.arc(0,0,d,Qn(R.cy+R.y11,R.cx+R.x11),Qn(F.cy+F.y11,F.cx+F.x11),y),a.arc(F.cx,F.cy,D,Qn(F.y11,F.x11),Qn(F.y01,F.x01),!y))):a.arc(0,0,d,_,x,y)}if(a.closePath(),c)return a=null,c+""||null}return l.centroid=function(){var c=(+e.apply(this,arguments)+ +t.apply(this,arguments))/2,f=(+i.apply(this,arguments)+ +s.apply(this,arguments))/2-jf/2;return[Yu(f)*c,js(f)*c]},l.innerRadius=function(c){return arguments.length?(e=typeof c=="function"?c:mt(+c),l):e},l.outerRadius=function(c){return arguments.length?(t=typeof c=="function"?c:mt(+c),l):t},l.cornerRadius=function(c){return arguments.length?(n=typeof c=="function"?c:mt(+c),l):n},l.padRadius=function(c){return arguments.length?(r=c==null?null:typeof c=="function"?c:mt(+c),l):r},l.startAngle=function(c){return arguments.length?(i=typeof c=="function"?c:mt(+c),l):i},l.endAngle=function(c){return arguments.length?(s=typeof c=="function"?c:mt(+c),l):s},l.padAngle=function(c){return arguments.length?(o=typeof c=="function"?c:mt(+c),l):o},l.context=function(c){return arguments.length?(a=c??null,l):a},l}function EN(e){return typeof e=="object"&&"length"in e?e:Array.from(e)}function AN(e){this._context=e}AN.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;default:this._context.lineTo(e,t);break}}};function uS(e){return new AN(e)}function SN(e){return e[0]}function kN(e){return e[1]}function CN(e,t){var n=mt(!0),r=null,i=uS,s=null,o=Uy(a);e=typeof e=="function"?e:e===void 0?SN:mt(e),t=typeof t=="function"?t:t===void 0?kN:mt(t);function a(u){var l,c=(u=EN(u)).length,f,d=!1,h;for(r==null&&(s=i(h=o())),l=0;l<=c;++l)!(l=h;--p)a.point(b[p],x[p]);a.lineEnd(),a.areaEnd()}y&&(b[d]=+e(m,d,f),x[d]=+t(m,d,f),a.point(r?+r(m,d,f):b[d],n?+n(m,d,f):x[d]))}if(v)return a=null,v+""||null}function c(){return CN().defined(i).curve(o).context(s)}return l.x=function(f){return arguments.length?(e=typeof f=="function"?f:mt(+f),r=null,l):e},l.x0=function(f){return arguments.length?(e=typeof f=="function"?f:mt(+f),l):e},l.x1=function(f){return arguments.length?(r=f==null?null:typeof f=="function"?f:mt(+f),l):r},l.y=function(f){return arguments.length?(t=typeof f=="function"?f:mt(+f),n=null,l):t},l.y0=function(f){return arguments.length?(t=typeof f=="function"?f:mt(+f),l):t},l.y1=function(f){return arguments.length?(n=f==null?null:typeof f=="function"?f:mt(+f),l):n},l.lineX0=l.lineY0=function(){return c().x(e).y(t)},l.lineY1=function(){return c().x(e).y(n)},l.lineX1=function(){return c().x(r).y(t)},l.defined=function(f){return arguments.length?(i=typeof f=="function"?f:mt(!!f),l):i},l.curve=function(f){return arguments.length?(o=f,s!=null&&(a=o(s)),l):o},l.context=function(f){return arguments.length?(f==null?s=a=null:a=o(s=f),l):s},l}const LX={draw(e,t){const n=ml(t/jf);e.moveTo(n,0),e.arc(0,0,n,0,_N)}};function IX(e,t){let n=null,r=Uy(i);e=typeof e=="function"?e:mt(e||LX),t=typeof t=="function"?t:mt(t===void 0?64:+t);function i(){let s;if(n||(n=s=r()),e.apply(this,arguments).draw(n,+t.apply(this,arguments)),s)return n=null,s+""||null}return i.type=function(s){return arguments.length?(e=typeof s=="function"?s:mt(s),i):e},i.size=function(s){return arguments.length?(t=typeof s=="function"?s:mt(+s),i):t},i.context=function(s){return arguments.length?(n=s??null,i):n},i}function pu(){}function jm(e,t,n){e._context.bezierCurveTo((2*e._x0+e._x1)/3,(2*e._y0+e._y1)/3,(e._x0+2*e._x1)/3,(e._y0+2*e._y1)/3,(e._x0+4*e._x1+t)/6,(e._y0+4*e._y1+n)/6)}function qy(e){this._context=e}qy.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:jm(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:jm(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function PX(e){return new qy(e)}function FN(e){this._context=e}FN.prototype={areaStart:pu,areaEnd:pu,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x2,this._y2),this._context.closePath();break}case 2:{this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break}case 3:{this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4);break}}},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._x2=e,this._y2=t;break;case 1:this._point=2,this._x3=e,this._y3=t;break;case 2:this._point=3,this._x4=e,this._y4=t,this._context.moveTo((this._x0+4*this._x1+e)/6,(this._y0+4*this._y1+t)/6);break;default:jm(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function BX(e){return new FN(e)}function DN(e){this._context=e}DN.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var n=(this._x0+4*this._x1+e)/6,r=(this._y0+4*this._y1+t)/6;this._line?this._context.lineTo(n,r):this._context.moveTo(n,r);break;case 3:this._point=4;default:jm(this,e,t);break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t}};function zX(e){return new DN(e)}function MN(e,t){this._basis=new qy(e),this._beta=t}MN.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var e=this._x,t=this._y,n=e.length-1;if(n>0)for(var r=e[0],i=t[0],s=e[n]-r,o=t[n]-i,a=-1,u;++a<=n;)u=a/n,this._basis.point(this._beta*e[a]+(1-this._beta)*(r+u*s),this._beta*t[a]+(1-this._beta)*(i+u*o));this._x=this._y=null,this._basis.lineEnd()},point:function(e,t){this._x.push(+e),this._y.push(+t)}};const jX=(function e(t){function n(r){return t===1?new qy(r):new MN(r,t)}return n.beta=function(r){return e(+r)},n})(.85);function Um(e,t,n){e._context.bezierCurveTo(e._x1+e._k*(e._x2-e._x0),e._y1+e._k*(e._y2-e._y0),e._x2+e._k*(e._x1-t),e._y2+e._k*(e._y1-n),e._x2,e._y2)}function lS(e,t){this._context=e,this._k=(1-t)/6}lS.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:Um(this,this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2,this._x1=e,this._y1=t;break;case 2:this._point=3;default:Um(this,e,t);break}this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const UX=(function e(t){function n(r){return new lS(r,t)}return n.tension=function(r){return e(+r)},n})(0);function cS(e,t){this._context=e,this._k=(1-t)/6}cS.prototype={areaStart:pu,areaEnd:pu,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x3,this._y3),this._context.closePath();break}case 2:{this._context.lineTo(this._x3,this._y3),this._context.closePath();break}case 3:{this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5);break}}},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._x3=e,this._y3=t;break;case 1:this._point=2,this._context.moveTo(this._x4=e,this._y4=t);break;case 2:this._point=3,this._x5=e,this._y5=t;break;default:Um(this,e,t);break}this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const qX=(function e(t){function n(r){return new cS(r,t)}return n.tension=function(r){return e(+r)},n})(0);function fS(e,t){this._context=e,this._k=(1-t)/6}fS.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:Um(this,e,t);break}this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const WX=(function e(t){function n(r){return new fS(r,t)}return n.tension=function(r){return e(+r)},n})(0);function dS(e,t,n){var r=e._x1,i=e._y1,s=e._x2,o=e._y2;if(e._l01_a>tr){var a=2*e._l01_2a+3*e._l01_a*e._l12_a+e._l12_2a,u=3*e._l01_a*(e._l01_a+e._l12_a);r=(r*a-e._x0*e._l12_2a+e._x2*e._l01_2a)/u,i=(i*a-e._y0*e._l12_2a+e._y2*e._l01_2a)/u}if(e._l23_a>tr){var l=2*e._l23_2a+3*e._l23_a*e._l12_a+e._l12_2a,c=3*e._l23_a*(e._l23_a+e._l12_a);s=(s*l+e._x1*e._l23_2a-t*e._l12_2a)/c,o=(o*l+e._y1*e._l23_2a-n*e._l12_2a)/c}e._context.bezierCurveTo(r,i,s,o,e._x2,e._y2)}function RN(e,t){this._context=e,this._alpha=t}RN.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){if(e=+e,t=+t,this._point){var n=this._x2-e,r=this._y2-t;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3;default:dS(this,e,t);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const HX=(function e(t){function n(r){return t?new RN(r,t):new lS(r,0)}return n.alpha=function(r){return e(+r)},n})(.5);function TN(e,t){this._context=e,this._alpha=t}TN.prototype={areaStart:pu,areaEnd:pu,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x3,this._y3),this._context.closePath();break}case 2:{this._context.lineTo(this._x3,this._y3),this._context.closePath();break}case 3:{this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5);break}}},point:function(e,t){if(e=+e,t=+t,this._point){var n=this._x2-e,r=this._y2-t;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=e,this._y3=t;break;case 1:this._point=2,this._context.moveTo(this._x4=e,this._y4=t);break;case 2:this._point=3,this._x5=e,this._y5=t;break;default:dS(this,e,t);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const GX=(function e(t){function n(r){return t?new TN(r,t):new cS(r,0)}return n.alpha=function(r){return e(+r)},n})(.5);function NN(e,t){this._context=e,this._alpha=t}NN.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){if(e=+e,t=+t,this._point){var n=this._x2-e,r=this._y2-t;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(n*n+r*r,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:dS(this,e,t);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=e,this._y0=this._y1,this._y1=this._y2,this._y2=t}};const YX=(function e(t){function n(r){return t?new NN(r,t):new fS(r,0)}return n.alpha=function(r){return e(+r)},n})(.5);function ON(e){this._context=e}ON.prototype={areaStart:pu,areaEnd:pu,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(e,t){e=+e,t=+t,this._point?this._context.lineTo(e,t):(this._point=1,this._context.moveTo(e,t))}};function VX(e){return new ON(e)}function CF(e){return e<0?-1:1}function $F(e,t,n){var r=e._x1-e._x0,i=t-e._x1,s=(e._y1-e._y0)/(r||i<0&&-0),o=(n-e._y1)/(i||r<0&&-0),a=(s*i+o*r)/(r+i);return(CF(s)+CF(o))*Math.min(Math.abs(s),Math.abs(o),.5*Math.abs(a))||0}function FF(e,t){var n=e._x1-e._x0;return n?(3*(e._y1-e._y0)/n-t)/2:t}function s2(e,t,n){var r=e._x0,i=e._y0,s=e._x1,o=e._y1,a=(s-r)/3;e._context.bezierCurveTo(r+a,i+a*t,s-a,o-a*n,s,o)}function qm(e){this._context=e}qm.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:s2(this,this._t0,FF(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(e,t){var n=NaN;if(e=+e,t=+t,!(e===this._x1&&t===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;break;case 2:this._point=3,s2(this,FF(this,n=$F(this,e,t)),n);break;default:s2(this,this._t0,n=$F(this,e,t));break}this._x0=this._x1,this._x1=e,this._y0=this._y1,this._y1=t,this._t0=n}}};function LN(e){this._context=new IN(e)}(LN.prototype=Object.create(qm.prototype)).point=function(e,t){qm.prototype.point.call(this,t,e)};function IN(e){this._context=e}IN.prototype={moveTo:function(e,t){this._context.moveTo(t,e)},closePath:function(){this._context.closePath()},lineTo:function(e,t){this._context.lineTo(t,e)},bezierCurveTo:function(e,t,n,r,i,s){this._context.bezierCurveTo(t,e,r,n,s,i)}};function XX(e){return new qm(e)}function KX(e){return new LN(e)}function PN(e){this._context=e}PN.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var e=this._x,t=this._y,n=e.length;if(n)if(this._line?this._context.lineTo(e[0],t[0]):this._context.moveTo(e[0],t[0]),n===2)this._context.lineTo(e[1],t[1]);else for(var r=DF(e),i=DF(t),s=0,o=1;o=0;--t)i[t]=(o[t]-i[t+1])/s[t];for(s[n-1]=(e[n]+i[n-1])/2,t=0;t=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(e,t){switch(e=+e,t=+t,this._point){case 0:this._point=1,this._line?this._context.lineTo(e,t):this._context.moveTo(e,t);break;case 1:this._point=2;default:{if(this._t<=0)this._context.lineTo(this._x,t),this._context.lineTo(e,t);else{var n=this._x*(1-this._t)+e*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,t)}break}}this._x=e,this._y=t}};function JX(e){return new Wy(e,.5)}function QX(e){return new Wy(e,0)}function eK(e){return new Wy(e,1)}function au(e,t){if(typeof document<"u"&&document.createElement){const n=document.createElement("canvas");if(n&&n.getContext)return n.width=e,n.height=t,n}return null}const tK=()=>typeof Image<"u"?Image:null;function Co(e,t){switch(arguments.length){case 0:break;case 1:this.range(e);break;default:this.range(t).domain(e);break}return this}function Ru(e,t){switch(arguments.length){case 0:break;case 1:{typeof e=="function"?this.interpolator(e):this.range(e);break}default:{this.domain(e),typeof t=="function"?this.interpolator(t):this.range(t);break}}return this}const w_=Symbol("implicit");function hS(){var e=new Y$,t=[],n=[],r=w_;function i(s){let o=e.get(s);if(o===void 0){if(r!==w_)return r;e.set(s,o=t.push(s)-1)}return n[o%n.length]}return i.domain=function(s){if(!arguments.length)return t.slice();t=[],e=new Y$;for(const o of s)e.has(o)||e.set(o,t.push(o)-1);return i},i.range=function(s){return arguments.length?(n=Array.from(s),i):n.slice()},i.unknown=function(s){return arguments.length?(r=s,i):r},i.copy=function(){return hS(t,n).unknown(r)},Co.apply(i,arguments),i}function Dd(e,t,n){e.prototype=t.prototype=n,n.constructor=e}function ug(e,t){var n=Object.create(e.prototype);for(var r in t)n[r]=t[r];return n}function Tu(){}var Hl=.7,Uf=1/Hl,cf="\\s*([+-]?\\d+)\\s*",yp="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",uo="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",nK=/^#([0-9a-f]{3,8})$/,rK=new RegExp(`^rgb\\(${cf},${cf},${cf}\\)$`),iK=new RegExp(`^rgb\\(${uo},${uo},${uo}\\)$`),sK=new RegExp(`^rgba\\(${cf},${cf},${cf},${yp}\\)$`),oK=new RegExp(`^rgba\\(${uo},${uo},${uo},${yp}\\)$`),aK=new RegExp(`^hsl\\(${yp},${uo},${uo}\\)$`),uK=new RegExp(`^hsla\\(${yp},${uo},${uo},${yp}\\)$`),MF={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};Dd(Tu,vp,{copy(e){return Object.assign(new this.constructor,this,e)},displayable(){return this.rgb().displayable()},hex:RF,formatHex:RF,formatHex8:lK,formatHsl:cK,formatRgb:TF,toString:TF});function RF(){return this.rgb().formatHex()}function lK(){return this.rgb().formatHex8()}function cK(){return BN(this).formatHsl()}function TF(){return this.rgb().formatRgb()}function vp(e){var t,n;return e=(e+"").trim().toLowerCase(),(t=nK.exec(e))?(n=t[1].length,t=parseInt(t[1],16),n===6?NF(t):n===3?new Sn(t>>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):n===8?a0(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):n===4?a0(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=rK.exec(e))?new Sn(t[1],t[2],t[3],1):(t=iK.exec(e))?new Sn(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=sK.exec(e))?a0(t[1],t[2],t[3],t[4]):(t=oK.exec(e))?a0(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=aK.exec(e))?IF(t[1],t[2]/100,t[3]/100,1):(t=uK.exec(e))?IF(t[1],t[2]/100,t[3]/100,t[4]):MF.hasOwnProperty(e)?NF(MF[e]):e==="transparent"?new Sn(NaN,NaN,NaN,0):null}function NF(e){return new Sn(e>>16&255,e>>8&255,e&255,1)}function a0(e,t,n,r){return r<=0&&(e=t=n=NaN),new Sn(e,t,n,r)}function pS(e){return e instanceof Tu||(e=vp(e)),e?(e=e.rgb(),new Sn(e.r,e.g,e.b,e.opacity)):new Sn}function gu(e,t,n,r){return arguments.length===1?pS(e):new Sn(e,t,n,r??1)}function Sn(e,t,n,r){this.r=+e,this.g=+t,this.b=+n,this.opacity=+r}Dd(Sn,gu,ug(Tu,{brighter(e){return e=e==null?Uf:Math.pow(Uf,e),new Sn(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?Hl:Math.pow(Hl,e),new Sn(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new Sn(Cl(this.r),Cl(this.g),Cl(this.b),Wm(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:OF,formatHex:OF,formatHex8:fK,formatRgb:LF,toString:LF}));function OF(){return`#${yl(this.r)}${yl(this.g)}${yl(this.b)}`}function fK(){return`#${yl(this.r)}${yl(this.g)}${yl(this.b)}${yl((isNaN(this.opacity)?1:this.opacity)*255)}`}function LF(){const e=Wm(this.opacity);return`${e===1?"rgb(":"rgba("}${Cl(this.r)}, ${Cl(this.g)}, ${Cl(this.b)}${e===1?")":`, ${e})`}`}function Wm(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function Cl(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function yl(e){return e=Cl(e),(e<16?"0":"")+e.toString(16)}function IF(e,t,n,r){return r<=0?e=t=n=NaN:n<=0||n>=1?e=t=NaN:t<=0&&(e=NaN),new fs(e,t,n,r)}function BN(e){if(e instanceof fs)return new fs(e.h,e.s,e.l,e.opacity);if(e instanceof Tu||(e=vp(e)),!e)return new fs;if(e instanceof fs)return e;e=e.rgb();var t=e.r/255,n=e.g/255,r=e.b/255,i=Math.min(t,n,r),s=Math.max(t,n,r),o=NaN,a=s-i,u=(s+i)/2;return a?(t===s?o=(n-r)/a+(n0&&u<1?0:o,new fs(o,a,u,e.opacity)}function Hm(e,t,n,r){return arguments.length===1?BN(e):new fs(e,t,n,r??1)}function fs(e,t,n,r){this.h=+e,this.s=+t,this.l=+n,this.opacity=+r}Dd(fs,Hm,ug(Tu,{brighter(e){return e=e==null?Uf:Math.pow(Uf,e),new fs(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?Hl:Math.pow(Hl,e),new fs(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*t,i=2*n-r;return new Sn(o2(e>=240?e-240:e+120,i,r),o2(e,i,r),o2(e<120?e+240:e-120,i,r),this.opacity)},clamp(){return new fs(PF(this.h),u0(this.s),u0(this.l),Wm(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const e=Wm(this.opacity);return`${e===1?"hsl(":"hsla("}${PF(this.h)}, ${u0(this.s)*100}%, ${u0(this.l)*100}%${e===1?")":`, ${e})`}`}}));function PF(e){return e=(e||0)%360,e<0?e+360:e}function u0(e){return Math.max(0,Math.min(1,e||0))}function o2(e,t,n){return(e<60?t+(n-t)*e/60:e<180?n:e<240?t+(n-t)*(240-e)/60:t)*255}const zN=Math.PI/180,jN=180/Math.PI,Gm=18,UN=.96422,qN=1,WN=.82521,HN=4/29,ff=6/29,GN=3*ff*ff,dK=ff*ff*ff;function YN(e){if(e instanceof lo)return new lo(e.l,e.a,e.b,e.opacity);if(e instanceof ra)return VN(e);e instanceof Sn||(e=pS(e));var t=c2(e.r),n=c2(e.g),r=c2(e.b),i=a2((.2225045*t+.7168786*n+.0606169*r)/qN),s,o;return t===n&&n===r?s=o=i:(s=a2((.4360747*t+.3850649*n+.1430804*r)/UN),o=a2((.0139322*t+.0971045*n+.7141733*r)/WN)),new lo(116*i-16,500*(s-i),200*(i-o),e.opacity)}function Ym(e,t,n,r){return arguments.length===1?YN(e):new lo(e,t,n,r??1)}function lo(e,t,n,r){this.l=+e,this.a=+t,this.b=+n,this.opacity=+r}Dd(lo,Ym,ug(Tu,{brighter(e){return new lo(this.l+Gm*(e??1),this.a,this.b,this.opacity)},darker(e){return new lo(this.l-Gm*(e??1),this.a,this.b,this.opacity)},rgb(){var e=(this.l+16)/116,t=isNaN(this.a)?e:e+this.a/500,n=isNaN(this.b)?e:e-this.b/200;return t=UN*u2(t),e=qN*u2(e),n=WN*u2(n),new Sn(l2(3.1338561*t-1.6168667*e-.4906146*n),l2(-.9787684*t+1.9161415*e+.033454*n),l2(.0719453*t-.2289914*e+1.4052427*n),this.opacity)}}));function a2(e){return e>dK?Math.pow(e,1/3):e/GN+HN}function u2(e){return e>ff?e*e*e:GN*(e-HN)}function l2(e){return 255*(e<=.0031308?12.92*e:1.055*Math.pow(e,1/2.4)-.055)}function c2(e){return(e/=255)<=.04045?e/12.92:Math.pow((e+.055)/1.055,2.4)}function hK(e){if(e instanceof ra)return new ra(e.h,e.c,e.l,e.opacity);if(e instanceof lo||(e=YN(e)),e.a===0&&e.b===0)return new ra(NaN,0=1?(n=1,t-1):Math.floor(n*t),i=e[r],s=e[r+1],o=r>0?e[r-1]:2*i-s,a=r()=>e;function QN(e,t){return function(n){return e+n*t}}function gK(e,t,n){return e=Math.pow(e,n),t=Math.pow(t,n)-e,n=1/n,function(r){return Math.pow(e+r*t,n)}}function Yy(e,t){var n=t-e;return n?QN(e,n>180||n<-180?n-360*Math.round(n/360):n):Gy(isNaN(e)?t:e)}function mK(e){return(e=+e)==1?kn:function(t,n){return n-t?gK(t,n,e):Gy(isNaN(t)?n:t)}}function kn(e,t){var n=t-e;return n?QN(e,n):Gy(isNaN(e)?t:e)}const A_=(function e(t){var n=mK(t);function r(i,s){var o=n((i=gu(i)).r,(s=gu(s)).r),a=n(i.g,s.g),u=n(i.b,s.b),l=kn(i.opacity,s.opacity);return function(c){return i.r=o(c),i.g=a(c),i.b=u(c),i.opacity=l(c),i+""}}return r.gamma=e,r})(1);function eO(e){return function(t){var n=t.length,r=new Array(n),i=new Array(n),s=new Array(n),o,a;for(o=0;on&&(s=t.slice(n,s),a[o]?a[o]+=s:a[++o]=s),(r=r[0])===(i=i[0])?a[o]?a[o]+=i:a[++o]=i:(a[++o]=null,u.push({i:o,x:us(r,i)})),n=f2.lastIndex;return n180?c+=360:c-l>180&&(l+=360),d.push({i:f.push(i(f)+"rotate(",null,r)-2,x:us(l,c)})):c&&f.push(i(f)+"rotate("+c+r)}function a(l,c,f,d){l!==c?d.push({i:f.push(i(f)+"skewX(",null,r)-2,x:us(l,c)}):c&&f.push(i(f)+"skewX("+c+r)}function u(l,c,f,d,h,p){if(l!==f||c!==d){var g=h.push(i(h)+"scale(",null,",",null,")");p.push({i:g-4,x:us(l,f)},{i:g-2,x:us(c,d)})}else(f!==1||d!==1)&&h.push(i(h)+"scale("+f+","+d+")")}return function(l,c){var f=[],d=[];return l=e(l),c=e(c),s(l.translateX,l.translateY,c.translateX,c.translateY,f,d),o(l.rotate,c.rotate,f,d),a(l.skewX,c.skewX,f,d),u(l.scaleX,l.scaleY,c.scaleX,c.scaleY,f,d),l=c=null,function(h){for(var p=-1,g=d.length,m;++pt&&(n=e,e=t,t=n),function(r){return Math.max(e,Math.min(t,r))}}function qK(e,t,n){var r=e[0],i=e[1],s=t[0],o=t[1];return i2?WK:qK,u=l=null,f}function f(d){return d==null||isNaN(d=+d)?s:(u||(u=a(e.map(r),t,n)))(r(o(d)))}return f.invert=function(d){return o(i((l||(l=a(t,e.map(r),us)))(d)))},f.domain=function(d){return arguments.length?(e=Array.from(d,C_),c()):e.slice()},f.range=function(d){return arguments.length?(t=Array.from(d),c()):t.slice()},f.rangeRound=function(d){return t=Array.from(d),n=lg,c()},f.clamp=function(d){return arguments.length?(o=d?!0:qr,c()):o!==qr},f.interpolate=function(d){return arguments.length?(n=d,c()):n},f.unknown=function(d){return arguments.length?(s=d,f):s},function(d,h){return r=d,i=h,c()}}function fO(){return Vy()(qr,qr)}function dO(e,t,n,r){var i=du(e,t,n),s;switch(r=Wl(r??",f"),r.type){case"s":{var o=Math.max(Math.abs(e),Math.abs(t));return r.precision==null&&!isNaN(s=PR(i,o))&&(r.precision=s),sA(r,o)}case"":case"e":case"g":case"p":case"r":{r.precision==null&&!isNaN(s=BR(i,Math.max(Math.abs(e),Math.abs(t))))&&(r.precision=s-(r.type==="e"));break}case"f":case"%":{r.precision==null&&!isNaN(s=IR(i))&&(r.precision=s-(r.type==="%")*2);break}}return Ey(r)}function vc(e){var t=e.domain;return e.ticks=function(n){var r=t();return o_(r[0],r[r.length-1],n??10)},e.tickFormat=function(n,r){var i=t();return dO(i[0],i[i.length-1],n??10,r)},e.nice=function(n){n==null&&(n=10);var r=t(),i=0,s=r.length-1,o=r[i],a=r[s],u,l,c=10;for(a0;){if(l=a_(o,a,n),l===u)return r[i]=o,r[s]=a,t(r);if(l>0)o=Math.floor(o/l)*l,a=Math.ceil(a/l)*l;else if(l<0)o=Math.ceil(o*l)/l,a=Math.floor(a*l)/l;else break;u=l}return e},e}function hO(){var e=fO();return e.copy=function(){return cg(e,hO())},Co.apply(e,arguments),vc(e)}function pO(e){var t;function n(r){return r==null||isNaN(r=+r)?t:r}return n.invert=n,n.domain=n.range=function(r){return arguments.length?(e=Array.from(r,C_),n):e.slice()},n.unknown=function(r){return arguments.length?(t=r,n):t},n.copy=function(){return pO(e).unknown(t)},e=arguments.length?Array.from(e,C_):[0,1],vc(n)}function gO(e,t){e=e.slice();var n=0,r=e.length-1,i=e[n],s=e[r],o;return sMath.pow(e,t)}function XK(e){return e===Math.E?Math.log:e===10&&Math.log10||e===2&&Math.log2||(e=Math.log(e),t=>Math.log(t)/e)}function YF(e){return(t,n)=>-e(-t,n)}function bS(e){const t=e(HF,GF),n=t.domain;let r=10,i,s;function o(){return i=XK(r),s=VK(r),n()[0]<0?(i=YF(i),s=YF(s),e(HK,GK)):e(HF,GF),t}return t.base=function(a){return arguments.length?(r=+a,o()):r},t.domain=function(a){return arguments.length?(n(a),o()):n()},t.ticks=a=>{const u=n();let l=u[0],c=u[u.length-1];const f=c0){for(;d<=h;++d)for(p=1;pc)break;y.push(g)}}else for(;d<=h;++d)for(p=r-1;p>=1;--p)if(g=d>0?p/s(-d):p*s(d),!(gc)break;y.push(g)}y.length*2{if(a==null&&(a=10),u==null&&(u=r===10?"s":","),typeof u!="function"&&(!(r%1)&&(u=Wl(u)).precision==null&&(u.trim=!0),u=Ey(u)),a===1/0)return u;const l=Math.max(1,r*a/t.ticks().length);return c=>{let f=c/s(Math.round(i(c)));return f*rn(gO(n(),{floor:a=>s(Math.floor(i(a))),ceil:a=>s(Math.ceil(i(a)))})),t}function mO(){const e=bS(Vy()).domain([1,10]);return e.copy=()=>cg(e,mO()).base(e.base()),Co.apply(e,arguments),e}function VF(e){return function(t){return Math.sign(t)*Math.log1p(Math.abs(t/e))}}function XF(e){return function(t){return Math.sign(t)*Math.expm1(Math.abs(t))*e}}function xS(e){var t=1,n=e(VF(t),XF(t));return n.constant=function(r){return arguments.length?e(VF(t=+r),XF(t)):t},vc(n)}function yO(){var e=xS(Vy());return e.copy=function(){return cg(e,yO()).constant(e.constant())},Co.apply(e,arguments)}function KF(e){return function(t){return t<0?-Math.pow(-t,e):Math.pow(t,e)}}function KK(e){return e<0?-Math.sqrt(-e):Math.sqrt(e)}function ZK(e){return e<0?-e*e:e*e}function _S(e){var t=e(qr,qr),n=1;function r(){return n===1?e(qr,qr):n===.5?e(KK,ZK):e(KF(n),KF(1/n))}return t.exponent=function(i){return arguments.length?(n=+i,r()):n},vc(t)}function wS(){var e=_S(Vy());return e.copy=function(){return cg(e,wS()).exponent(e.exponent())},Co.apply(e,arguments),e}function JK(){return wS.apply(null,arguments).exponent(.5)}function vO(){var e=[],t=[],n=[],r;function i(){var o=0,a=Math.max(1,t.length);for(n=new Array(a-1);++o0?n[a-1]:e[0],a=n?[r[n-1],t]:[r[l-1],r[l]]},o.unknown=function(u){return arguments.length&&(s=u),o},o.thresholds=function(){return r.slice()},o.copy=function(){return bO().domain([e,t]).range(i).unknown(s)},Co.apply(vc(o),arguments)}function xO(){var e=[.5],t=[0,1],n,r=1;function i(s){return s!=null&&s<=s?t[fu(e,s,0,r)]:n}return i.domain=function(s){return arguments.length?(e=Array.from(s),r=Math.min(e.length,t.length-1),i):e.slice()},i.range=function(s){return arguments.length?(t=Array.from(s),r=Math.min(e.length,t.length-1),i):t.slice()},i.invertExtent=function(s){var o=t.indexOf(s);return[e[o-1],e[o]]},i.unknown=function(s){return arguments.length?(n=s,i):n},i.copy=function(){return xO().domain(e).range(t).unknown(n)},Co.apply(i,arguments)}function QK(e){return new Date(e)}function eZ(e){return e instanceof Date?+e:+new Date(+e)}function ES(e,t,n,r,i,s,o,a,u,l){var c=fO(),f=c.invert,d=c.domain,h=l(".%L"),p=l(":%S"),g=l("%I:%M"),m=l("%I %p"),y=l("%a %d"),v=l("%b %d"),b=l("%B"),x=l("%Y");function _(A){return(u(A)0?r:1:0}const gZ="identity",qf="linear",ma="log",fg="pow",dg="sqrt",Zy="symlog",Gl="time",Yl="utc",co="sequential",Md="diverging",Wf="quantile",Jy="quantize",Qy="threshold",$S="ordinal",F_="point",kO="band",FS="bin-ordinal",_n="continuous",hg="discrete",pg="discretizing",Vi="interpolating",DS="temporal";function mZ(e){return function(t){let n=t[0],r=t[1],i;return r=r&&n[u]<=i&&(s<0&&(s=u),o=u);if(!(s<0))return r=e.invertExtent(n[s]),i=e.invertExtent(n[o]),[r[0]===void 0?r[1]:r[0],i[1]===void 0?i[0]:i[1]]}}function MS(){const e=hS().unknown(void 0),t=e.domain,n=e.range;let r=[0,1],i,s,o=!1,a=0,u=0,l=.5;delete e.unknown;function c(){const f=t().length,d=r[1]g+i*y);return n(d?m.reverse():m)}return e.domain=function(f){return arguments.length?(t(f),c()):t()},e.range=function(f){return arguments.length?(r=[+f[0],+f[1]],c()):r.slice()},e.rangeRound=function(f){return r=[+f[0],+f[1]],o=!0,c()},e.bandwidth=function(){return s},e.step=function(){return i},e.round=function(f){return arguments.length?(o=!!f,c()):o},e.padding=function(f){return arguments.length?(u=Math.max(0,Math.min(1,f)),a=u,c()):a},e.paddingInner=function(f){return arguments.length?(a=Math.max(0,Math.min(1,f)),c()):a},e.paddingOuter=function(f){return arguments.length?(u=Math.max(0,Math.min(1,f)),c()):u},e.align=function(f){return arguments.length?(l=Math.max(0,Math.min(1,f)),c()):l},e.invertRange=function(f){if(f[0]==null||f[1]==null)return;const d=r[1]r[1-d])))return y=Math.max(0,fu(h,g)-1),v=g===m?y:fu(h,m)-1,g-h[y]>s+1e-10&&++y,d&&(b=y,y=p-v,v=p-b),y>v?void 0:t().slice(y,v+1)},e.invert=function(f){const d=e.invertRange([f,f]);return d&&d[0]},e.copy=function(){return MS().domain(t()).range(r).round(o).paddingInner(a).paddingOuter(u).align(l)},c()}function CO(e){const t=e.copy;return e.padding=e.paddingOuter,delete e.paddingInner,e.copy=function(){return CO(t())},e}function vZ(){return CO(MS().paddingInner(1))}var bZ=Array.prototype.map;function xZ(e){return bZ.call(e,sr)}const _Z=Array.prototype.slice;function $O(){let e=[],t=[];function n(r){return r==null||r!==r?void 0:t[(fu(e,r)-1)%t.length]}return n.domain=function(r){return arguments.length?(e=xZ(r),n):e.slice()},n.range=function(r){return arguments.length?(t=_Z.call(r),n):t.slice()},n.tickFormat=function(r,i){return dO(e[0],st(e),r??10,i)},n.copy=function(){return $O().domain(n.domain()).range(n.range())},n}const Xm=new Map,FO=Symbol("vega_scale");function DO(e){return e[FO]=!0,e}function ZF(e){return e&&e[FO]===!0}function wZ(e,t,n){const r=function(){const s=t();return s.invertRange||(s.invertRange=s.invert?mZ(s):s.invertExtent?yZ(s):void 0),s.type=e,DO(s)};return r.metadata=As(ye(n)),r}function ht(e,t,n){return arguments.length>1?(Xm.set(e,wZ(e,t,n)),this):MO(e)?Xm.get(e):void 0}ht(gZ,pO);ht(qf,hO,_n);ht(ma,mO,[_n,ma]);ht(fg,wS,_n);ht(dg,JK,_n);ht(Zy,yO,_n);ht(Gl,tZ,[_n,DS]);ht(Yl,nZ,[_n,DS]);ht(co,AS,[_n,Vi]);ht(`${co}-${qf}`,AS,[_n,Vi]);ht(`${co}-${ma}`,_O,[_n,Vi,ma]);ht(`${co}-${fg}`,SS,[_n,Vi]);ht(`${co}-${dg}`,rZ,[_n,Vi]);ht(`${co}-${Zy}`,wO,[_n,Vi]);ht(`${Md}-${qf}`,EO,[_n,Vi]);ht(`${Md}-${ma}`,AO,[_n,Vi,ma]);ht(`${Md}-${fg}`,kS,[_n,Vi]);ht(`${Md}-${dg}`,iZ,[_n,Vi]);ht(`${Md}-${Zy}`,SO,[_n,Vi]);ht(Wf,vO,[pg,Wf]);ht(Jy,bO,pg);ht(Qy,xO,pg);ht(FS,$O,[hg,pg]);ht($S,hS,hg);ht(kO,MS,hg);ht(F_,vZ,hg);function MO(e){return Xm.has(e)}function bc(e,t){const n=Xm.get(e);return n&&n.metadata[t]}function RS(e){return bc(e,_n)}function Hf(e){return bc(e,hg)}function D_(e){return bc(e,pg)}function RO(e){return bc(e,ma)}function EZ(e){return bc(e,DS)}function TO(e){return bc(e,Vi)}function NO(e){return bc(e,Wf)}const AZ=["clamp","base","constant","exponent"];function OO(e,t){const n=t[0],r=st(t)-n;return function(i){return e(n+i*r)}}function ev(e,t,n){return vS(TS(t||"rgb",n),e)}function LO(e,t){const n=new Array(t),r=t+1;for(let i=0;ie[a]?o[a](e[a]()):0),o)}function TS(e,t){const n=zK[SZ(e)];return t!=null&&n&&n.gamma?n.gamma(t):n}function SZ(e){return"interpolate"+e.toLowerCase().split("-").map(t=>t[0].toUpperCase()+t.slice(1)).join("")}const kZ={blues:"cfe1f2bed8eca8cee58fc1de74b2d75ba3cf4592c63181bd206fb2125ca40a4a90",greens:"d3eecdc0e6baabdda594d3917bc77d60ba6c46ab5e329a512089430e7735036429",greys:"e2e2e2d4d4d4c4c4c4b1b1b19d9d9d8888887575756262624d4d4d3535351e1e1e",oranges:"fdd8b3fdc998fdb87bfda55efc9244f87f2cf06b18e4580bd14904b93d029f3303",purples:"e2e1efd4d4e8c4c5e0b4b3d6a3a0cc928ec3827cb97566ae684ea25c3696501f8c",reds:"fdc9b4fcb49afc9e80fc8767fa7051f6573fec3f2fdc2a25c81b1db21218970b13",blueGreen:"d5efedc1e8e0a7ddd18bd2be70c6a958ba9144ad77319c5d2089460e7736036429",bluePurple:"ccddecbad0e4a8c2dd9ab0d4919cc98d85be8b6db28a55a6873c99822287730f71",greenBlue:"d3eecec5e8c3b1e1bb9bd8bb82cec269c2ca51b2cd3c9fc7288abd1675b10b60a1",orangeRed:"fddcaffdcf9bfdc18afdad77fb9562f67d53ee6545e24932d32d1ebf130da70403",purpleBlue:"dbdaebc8cee4b1c3de97b7d87bacd15b9fc93a90c01e7fb70b70ab056199045281",purpleBlueGreen:"dbd8eac8cee4b0c3de93b7d872acd1549fc83892bb1c88a3097f8702736b016353",purpleRed:"dcc9e2d3b3d7ce9eccd186c0da6bb2e14da0e23189d91e6fc61159ab07498f023a",redPurple:"fccfccfcbec0faa9b8f98faff571a5ec539ddb3695c41b8aa908808d0179700174",yellowGreen:"e4f4acd1eca0b9e2949ed68880c97c62bb6e47aa5e3297502083440e723b036034",yellowOrangeBrown:"feeaa1fedd84fecc63feb746fca031f68921eb7215db5e0bc54c05ab3d038f3204",yellowOrangeRed:"fee087fed16ffebd59fea849fd903efc7335f9522bee3423de1b20ca0b22af0225",blueOrange:"134b852f78b35da2cb9dcae1d2e5eff2f0ebfce0bafbbf74e8932fc5690d994a07",brownBlueGreen:"704108a0651ac79548e3c78af3e6c6eef1eac9e9e48ed1c74da79e187a72025147",purpleGreen:"5b1667834792a67fb6c9aed3e6d6e8eff0efd9efd5aedda971bb75368e490e5e29",purpleOrange:"4114696647968f83b7b9b4d6dadbebf3eeeafce0bafbbf74e8932fc5690d994a07",redBlue:"8c0d25bf363adf745ef4ae91fbdbc9f2efeed2e5ef9dcae15da2cb2f78b3134b85",redGrey:"8c0d25bf363adf745ef4ae91fcdccbfaf4f1e2e2e2c0c0c0969696646464343434",yellowGreenBlue:"eff9bddbf1b4bde5b594d5b969c5be45b4c22c9ec02182b82163aa23479c1c3185",redYellowBlue:"a50026d4322cf16e43fcac64fedd90faf8c1dcf1ecabd6e875abd04a74b4313695",redYellowGreen:"a50026d4322cf16e43fcac63fedd8df9f7aed7ee8ea4d86e64bc6122964f006837",pinkYellowGreen:"8e0152c0267edd72adf0b3d6faddedf5f3efe1f2cab6de8780bb474f9125276419",spectral:"9e0142d13c4bf0704afcac63fedd8dfbf8b0e0f3a1a9dda269bda94288b55e4fa2",viridis:"440154470e61481a6c482575472f7d443a834144873d4e8a39568c35608d31688e2d708e2a788e27818e23888e21918d1f988b1fa08822a8842ab07f35b77943bf7154c56866cc5d7ad1518fd744a5db36bcdf27d2e21be9e51afde725",magma:"0000040404130b0924150e3720114b2c11603b0f704a107957157e651a80721f817f24828c29819a2e80a8327db6377ac43c75d1426fde4968e95462f1605df76f5cfa7f5efc8f65fe9f6dfeaf78febf84fece91fddea0fcedaffcfdbf",inferno:"0000040403130c0826170c3b240c4f330a5f420a68500d6c5d126e6b176e781c6d86216b932667a12b62ae305cbb3755c73e4cd24644dd513ae65c30ed6925f3771af8850ffb9506fca50afcb519fac62df6d645f2e661f3f484fcffa4",plasma:"0d088723069033059742039d5002a25d01a66a00a87801a88405a7900da49c179ea72198b12a90ba3488c33d80cb4779d35171da5a69e16462e76e5bed7953f2834cf68f44fa9a3dfca636fdb32ffec029fcce25f9dc24f5ea27f0f921",cividis:"00205100235800265d002961012b65042e670831690d346b11366c16396d1c3c6e213f6e26426e2c456e31476e374a6e3c4d6e42506e47536d4c566d51586e555b6e5a5e6e5e616e62646f66676f6a6a706e6d717270717573727976737c79747f7c75827f758682768985778c8877908b78938e789691789a94789e9778a19b78a59e77a9a177aea575b2a874b6ab73bbaf71c0b26fc5b66dc9b96acebd68d3c065d8c462ddc85fe2cb5ce7cf58ebd355f0d652f3da4ff7de4cfae249fce647",rainbow:"6e40aa883eb1a43db3bf3cafd83fa4ee4395fe4b83ff576eff6659ff7847ff8c38f3a130e2b72fcfcc36bee044aff05b8ff4576ff65b52f6673af27828ea8d1ddfa319d0b81cbecb23abd82f96e03d82e14c6edb5a5dd0664dbf6e40aa",sinebow:"ff4040fc582af47218e78d0bd5a703bfbf00a7d5038de70b72f41858fc2a40ff402afc5818f4720be78d03d5a700bfbf03a7d50b8de71872f42a58fc4040ff582afc7218f48d0be7a703d5bf00bfd503a7e70b8df41872fc2a58ff4040",turbo:"23171b32204a3e2a71453493493eae4b49c54a53d7485ee44569ee4074f53c7ff8378af93295f72e9ff42ba9ef28b3e926bce125c5d925cdcf27d5c629dcbc2de3b232e9a738ee9d3ff39347f68950f9805afc7765fd6e70fe667cfd5e88fc5795fb51a1f84badf545b9f140c5ec3cd0e637dae034e4d931ecd12ef4c92bfac029ffb626ffad24ffa223ff9821ff8d1fff821dff771cfd6c1af76118f05616e84b14df4111d5380fcb2f0dc0260ab61f07ac1805a313029b0f00950c00910b00",browns:"eedbbdecca96e9b97ae4a865dc9856d18954c7784cc0673fb85536ad44339f3632",tealBlues:"bce4d89dd3d181c3cb65b3c245a2b9368fae347da0306a932c5985",teals:"bbdfdfa2d4d58ac9c975bcbb61b0af4da5a43799982b8b8c1e7f7f127273006667",warmGreys:"dcd4d0cec5c1c0b8b4b3aaa7a59c9998908c8b827f7e7673726866665c5a59504e",goldGreen:"f4d166d5ca60b6c35c98bb597cb25760a6564b9c533f8f4f33834a257740146c36",goldOrange:"f4d166f8be5cf8aa4cf5983bf3852aef701be2621fd65322c54923b142239e3a26",goldRed:"f4d166f6be59f9aa51fc964ef6834bee734ae56249db5247cf4244c43141b71d3e",lightGreyRed:"efe9e6e1dad7d5cbc8c8bdb9bbaea9cd967ddc7b43e15f19df4011dc000b",lightGreyTeal:"e4eaead6dcddc8ced2b7c2c7a6b4bc64b0bf22a6c32295c11f85be1876bc",lightMulti:"e0f1f2c4e9d0b0de9fd0e181f6e072f6c053f3993ef77440ef4a3c",lightOrange:"f2e7daf7d5baf9c499fab184fa9c73f68967ef7860e8645bde515bd43d5b",lightTealBlue:"e3e9e0c0dccf9aceca7abfc859afc0389fb9328dad2f7ca0276b95255988",darkBlue:"3232322d46681a5c930074af008cbf05a7ce25c0dd38daed50f3faffffff",darkGold:"3c3c3c584b37725e348c7631ae8b2bcfa424ecc31ef9de30fff184ffffff",darkGreen:"3a3a3a215748006f4d048942489e4276b340a6c63dd2d836ffeb2cffffaa",darkMulti:"3737371f5287197d8c29a86995ce3fffe800ffffff",darkRed:"3434347036339e3c38cc4037e75d1eec8620eeab29f0ce32ffeb2c"},CZ={accent:oZ,category10:sZ,category20:"1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5",category20b:"393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6",category20c:"3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9",dark2:aZ,observable10:uZ,paired:lZ,pastel1:cZ,pastel2:fZ,set1:dZ,set2:hZ,set3:pZ,tableau10:"4c78a8f58518e4575672b7b254a24beeca3bb279a2ff9da69d755dbab0ac",tableau20:"4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5"};function PO(e){if(ee(e))return e;const t=e.length/6|0,n=new Array(t);for(let r=0;rev(PO(e)));function NS(e,t){return e=e&&e.toLowerCase(),arguments.length>1?(JF[e]=t,this):JF[e]}const tm="symbol",$Z="discrete",FZ="gradient",DZ=e=>ee(e)?e.map(t=>String(t)):String(e),MZ=(e,t)=>e[1]-t[1],RZ=(e,t)=>t[1]-e[1];function OS(e,t,n){let r;return ft(t)&&(e.bins&&(t=Math.max(t,e.bins.length)),n!=null&&(t=Math.min(t,Math.floor(ig(e.domain())/n||1)+1))),ge(t)&&(r=t.step,t=t.interval),me(t)&&(t=e.type===Gl?Cd(t):e.type==Yl?$d(t):X("Only time and utc scales accept interval strings."),r&&(t=t.every(r))),t}function zO(e,t,n){let r=e.range(),i=r[0],s=st(r),o=MZ;if(i>s&&(r=s,s=i,i=r,o=RZ),i=Math.floor(i),s=Math.ceil(s),t=t.map(a=>[a,e(a)]).filter(a=>i<=a[1]&&a[1]<=s).sort(o).map(a=>a[0]),n>0&&t.length>1){const a=[t[0],st(t)];for(;t.length>n&&t.length>=3;)t=t.filter((u,l)=>!(l%2));t.length<3&&(t=a)}return t}function LS(e,t){return e.bins?zO(e,e.bins,t):e.ticks?e.ticks(t):e.domain()}function jO(e,t,n,r,i,s){const o=t.type;let a=DZ;if(o===Gl||i===Gl)a=e.timeFormat(r);else if(o===Yl||i===Yl)a=e.utcFormat(r);else if(RO(o)){const u=e.formatFloat(r);if(s||t.bins)a=u;else{const l=UO(t,n,!1);a=c=>l(c)?u(c):""}}else if(t.tickFormat){const u=t.domain();a=e.formatSpan(u[0],u[u.length-1],n,r)}else r&&(a=e.format(r));return a}function UO(e,t,n){const r=LS(e,t),i=e.base(),s=Math.log(i),o=Math.max(1,i*t/r.length),a=u=>{let l=u/Math.pow(i,Math.round(Math.log(u)/s));return l*i1?r[1]-r[0]:r[0],o;for(o=1;oM_[e.type]||e.bins;function HO(e,t,n,r,i,s,o){const a=qO[t.type]&&s!==Gl&&s!==Yl?TZ(e,t,i):jO(e,t,n,i,s,o);return r===tm&&LZ(t)?IZ(a):r===$Z?PZ(a):BZ(a)}const IZ=e=>(t,n,r)=>{const i=QF(r[n+1],QF(r.max,1/0)),s=e5(t,e),o=e5(i,e);return s&&o?s+" – "+o:o?"< "+o:"≥ "+s},QF=(e,t)=>e??t,PZ=e=>(t,n)=>n?e(t):null,BZ=e=>t=>e(t),e5=(e,t)=>Number.isFinite(e)?t(e):null;function zZ(e){const t=e.domain(),n=t.length-1;let r=+t[0],i=+st(t),s=i-r;if(e.type===Qy){const o=n?s/n:.1;r-=o,i+=o,s=i-r}return o=>(o-r)/s}function jZ(e,t,n,r){const i=r||t.type;return me(n)&&EZ(i)&&(n=n.replace(/%a/g,"%A").replace(/%b/g,"%B")),!n&&i===Gl?e.timeFormat("%A, %d %B %Y, %X"):!n&&i===Yl?e.utcFormat("%A, %d %B %Y, %X UTC"):HO(e,t,5,null,n,r,!0)}function GO(e,t,n){n=n||{};const r=Math.max(3,n.maxlen||7),i=jZ(e,t,n.format,n.formatType);if(D_(t.type)){const s=WO(t).slice(1).map(i),o=s.length;return`${o} boundar${o===1?"y":"ies"}: ${s.join(", ")}`}else if(Hf(t.type)){const s=t.domain(),o=s.length,a=o>r?s.slice(0,r-2).map(i).join(", ")+", ending with "+s.slice(-1).map(i):s.map(i).join(", ");return`${o} value${o===1?"":"s"}: ${a}`}else{const s=t.domain();return`values from ${i(s[0])} to ${i(st(s))}`}}let YO=0;function UZ(){YO=0}const Km="p_";function IS(e){return e&&e.gradient}function VO(e,t,n){const r=e.gradient;let i=e.id,s=r==="radial"?Km:"";return i||(i=e.id="gradient_"+YO++,r==="radial"?(e.x1=Us(e.x1,.5),e.y1=Us(e.y1,.5),e.r1=Us(e.r1,0),e.x2=Us(e.x2,.5),e.y2=Us(e.y2,.5),e.r2=Us(e.r2,.5),s=Km):(e.x1=Us(e.x1,0),e.y1=Us(e.y1,0),e.x2=Us(e.x2,1),e.y2=Us(e.y2,0))),t[i]=e,"url("+(n||"")+"#"+s+i+")"}function Us(e,t){return e??t}function XO(e,t){var n=[],r;return r={gradient:"linear",x1:e?e[0]:0,y1:e?e[1]:0,x2:t?t[0]:1,y2:t?t[1]:0,stops:n,stop:function(i,s){return n.push({offset:i,color:s}),r}}}const t5={basis:{curve:PX},"basis-closed":{curve:BX},"basis-open":{curve:zX},bundle:{curve:jX,tension:"beta",value:.85},cardinal:{curve:UX,tension:"tension",value:0},"cardinal-open":{curve:WX,tension:"tension",value:0},"cardinal-closed":{curve:qX,tension:"tension",value:0},"catmull-rom":{curve:HX,tension:"alpha",value:.5},"catmull-rom-closed":{curve:GX,tension:"alpha",value:.5},"catmull-rom-open":{curve:YX,tension:"alpha",value:.5},linear:{curve:uS},"linear-closed":{curve:VX},monotone:{horizontal:KX,vertical:XX},natural:{curve:ZX},step:{curve:JX},"step-after":{curve:eK},"step-before":{curve:QX}};function PS(e,t,n){var r=be(t5,e)&&t5[e],i=null;return r&&(i=r.curve||r[t||"vertical"],r.tension&&n!=null&&(i=i[r.tension](n))),i}const qZ={m:2,l:2,h:1,v:1,z:0,c:6,s:4,q:4,t:2,a:7},WZ=/[mlhvzcsqta]([^mlhvzcsqta]+|$)/gi,HZ=/^[+-]?(([0-9]*\.[0-9]+)|([0-9]+\.)|([0-9]+))([eE][+-]?[0-9]+)?/,GZ=/^((\s+,?\s*)|(,\s*))/,YZ=/^[01]/;function Gf(e){const t=[];return(e.match(WZ)||[]).forEach(r=>{let i=r[0];const s=i.toLowerCase(),o=qZ[s],a=VZ(s,o,r.slice(1).trim()),u=a.length;if(u1&&(g=Math.sqrt(g),n*=g,r*=g);const m=d/n,y=f/n,v=-f/r,b=d/r,x=m*a+y*u,_=v*a+b*u,A=m*e+y*t,E=v*e+b*t;let k=1/((A-x)*(A-x)+(E-_)*(E-_))-.25;k<0&&(k=0);let $=Math.sqrt(k);s==i&&($=-$);const D=.5*(x+A)-$*(E-_),M=.5*(_+E)+$*(A-x),R=Math.atan2(_-M,x-D);let C=Math.atan2(E-M,A-D)-R;C<0&&s===1?C+=to:C>0&&s===0&&(C-=to);const T=Math.ceil(Math.abs(C/(ul+.001))),O=[];for(let N=0;N+e}function c0(e,t,n){return Math.max(t,Math.min(e,n))}function JO(){var e=eJ,t=tJ,n=nJ,r=rJ,i=jo(0),s=i,o=i,a=i,u=null;function l(c,f,d){var h,p=f??+e.call(this,c),g=d??+t.call(this,c),m=+n.call(this,c),y=+r.call(this,c),v=Math.min(m,y)/2,b=c0(+i.call(this,c),0,v),x=c0(+s.call(this,c),0,v),_=c0(+o.call(this,c),0,v),A=c0(+a.call(this,c),0,v);if(u||(u=h=jy()),b<=0&&x<=0&&_<=0&&A<=0)u.rect(p,g,m,y);else{var E=p+m,S=g+y;u.moveTo(p+b,g),u.lineTo(E-x,g),u.bezierCurveTo(E-Ra*x,g,E,g+Ra*x,E,g+x),u.lineTo(E,S-A),u.bezierCurveTo(E,S-Ra*A,E-Ra*A,S,E-A,S),u.lineTo(p+_,S),u.bezierCurveTo(p+Ra*_,S,p,S-Ra*_,p,S-_),u.lineTo(p,g+b),u.bezierCurveTo(p,g+Ra*b,p+Ra*b,g,p+b,g),u.closePath()}if(h)return u=null,h+""||null}return l.x=function(c){return arguments.length?(e=jo(c),l):e},l.y=function(c){return arguments.length?(t=jo(c),l):t},l.width=function(c){return arguments.length?(n=jo(c),l):n},l.height=function(c){return arguments.length?(r=jo(c),l):r},l.cornerRadius=function(c,f,d,h){return arguments.length?(i=jo(c),s=f!=null?jo(f):i,a=d!=null?jo(d):i,o=h!=null?jo(h):s,l):i},l.context=function(c){return arguments.length?(u=c??null,l):u},l}function QO(){var e,t,n,r,i=null,s,o,a,u;function l(f,d,h){const p=h/2;if(s){var g=a-d,m=f-o;if(g||m){var y=Math.hypot(g,m),v=(g/=y)*u,b=(m/=y)*u,x=Math.atan2(m,g);i.moveTo(o-v,a-b),i.lineTo(f-g*p,d-m*p),i.arc(f,d,p,x-Math.PI,x),i.lineTo(o+v,a+b),i.arc(o,a,u,x,x+Math.PI)}else i.arc(f,d,p,0,to);i.closePath()}else s=1;o=f,a=d,u=p}function c(f){var d,h=f.length,p,g=!1,m;for(i==null&&(i=m=jy()),d=0;d<=h;++d)!(de.x||0,yg=e=>e.y||0,iJ=e=>e.width||0,sJ=e=>e.height||0,oJ=e=>(e.x||0)+(e.width||0),aJ=e=>(e.y||0)+(e.height||0),uJ=e=>e.startAngle||0,lJ=e=>e.endAngle||0,cJ=e=>e.padAngle||0,fJ=e=>e.innerRadius||0,dJ=e=>e.outerRadius||0,hJ=e=>e.cornerRadius||0,pJ=e=>gg(e.cornerRadiusTopLeft,e.cornerRadius)||0,gJ=e=>gg(e.cornerRadiusTopRight,e.cornerRadius)||0,mJ=e=>gg(e.cornerRadiusBottomRight,e.cornerRadius)||0,yJ=e=>gg(e.cornerRadiusBottomLeft,e.cornerRadius)||0,vJ=e=>gg(e.size,64),bJ=e=>e.size||1,tv=e=>e.defined!==!1,xJ=e=>ZO(e.shape||"circle"),_J=OX().startAngle(uJ).endAngle(lJ).padAngle(cJ).innerRadius(fJ).outerRadius(dJ).cornerRadius(hJ),wJ=$N().x(mg).y1(yg).y0(aJ).defined(tv),EJ=$N().y(yg).x1(mg).x0(oJ).defined(tv),AJ=CN().x(mg).y(yg).defined(tv),SJ=JO().x(mg).y(yg).width(iJ).height(sJ).cornerRadius(pJ,gJ,mJ,yJ),kJ=IX().type(xJ).size(vJ),CJ=QO().x(mg).y(yg).defined(tv).size(bJ);function BS(e){return e.cornerRadius||e.cornerRadiusTopLeft||e.cornerRadiusTopRight||e.cornerRadiusBottomRight||e.cornerRadiusBottomLeft}function $J(e,t){return _J.context(e)(t)}function FJ(e,t){const n=t[0],r=n.interpolate||"linear";return(n.orient==="horizontal"?EJ:wJ).curve(PS(r,n.orient,n.tension)).context(e)(t)}function DJ(e,t){const n=t[0],r=n.interpolate||"linear";return AJ.curve(PS(r,n.orient,n.tension)).context(e)(t)}function Rd(e,t,n,r){return SJ.context(e)(t,n,r)}function MJ(e,t){return(t.mark.shape||t.shape).context(e)(t)}function RJ(e,t){return kJ.context(e)(t)}function TJ(e,t){return CJ.context(e)(t)}var e7=1;function t7(){e7=1}function zS(e,t,n){var r=t.clip,i=e._defs,s=t.clip_id||(t.clip_id="clip"+e7++),o=i.clipping[s]||(i.clipping[s]={id:s});return He(r)?o.path=r(null):BS(n)?o.path=Rd(null,n,0,0):(o.width=n.width||0,o.height=n.height||0),"url(#"+s+")"}function dn(e){this.clear(),e&&this.union(e)}dn.prototype={clone(){return new dn(this)},clear(){return this.x1=+Number.MAX_VALUE,this.y1=+Number.MAX_VALUE,this.x2=-Number.MAX_VALUE,this.y2=-Number.MAX_VALUE,this},empty(){return this.x1===+Number.MAX_VALUE&&this.y1===+Number.MAX_VALUE&&this.x2===-Number.MAX_VALUE&&this.y2===-Number.MAX_VALUE},equals(e){return this.x1===e.x1&&this.y1===e.y1&&this.x2===e.x2&&this.y2===e.y2},set(e,t,n,r){return nthis.x2&&(this.x2=e),t>this.y2&&(this.y2=t),this},expand(e){return this.x1-=e,this.y1-=e,this.x2+=e,this.y2+=e,this},round(){return this.x1=Math.floor(this.x1),this.y1=Math.floor(this.y1),this.x2=Math.ceil(this.x2),this.y2=Math.ceil(this.y2),this},scale(e){return this.x1*=e,this.y1*=e,this.x2*=e,this.y2*=e,this},translate(e,t){return this.x1+=e,this.x2+=e,this.y1+=t,this.y2+=t,this},rotate(e,t,n){const r=this.rotatedPoints(e,t,n);return this.clear().add(r[0],r[1]).add(r[2],r[3]).add(r[4],r[5]).add(r[6],r[7])},rotatedPoints(e,t,n){var{x1:r,y1:i,x2:s,y2:o}=this,a=Math.cos(e),u=Math.sin(e),l=t-t*a+n*u,c=n-t*u-n*a;return[a*r-u*i+l,u*r+a*i+c,a*r-u*o+l,u*r+a*o+c,a*s-u*i+l,u*s+a*i+c,a*s-u*o+l,u*s+a*o+c]},union(e){return e.x1this.x2&&(this.x2=e.x2),e.y2>this.y2&&(this.y2=e.y2),this},intersect(e){return e.x1>this.x1&&(this.x1=e.x1),e.y1>this.y1&&(this.y1=e.y1),e.x2=e.x2&&this.y1<=e.y1&&this.y2>=e.y2},alignsWith(e){return e&&(this.x1==e.x1||this.x2==e.x2||this.y1==e.y1||this.y2==e.y2)},intersects(e){return e&&!(this.x2e.x2||this.y2e.y2)},contains(e,t){return!(ethis.x2||tthis.y2)},width(){return this.x2-this.x1},height(){return this.y2-this.y1}};function nv(e){this.mark=e,this.bounds=this.bounds||new dn}function rv(e){nv.call(this,e),this.items=this.items||[]}he(rv,nv);class n7{constructor(t){this._pending=0,this._loader=t||Fy()}pending(){return this._pending}sanitizeURL(t){const n=this;return s5(n),n._loader.sanitize(t,{context:"href"}).then(r=>(rh(n),r)).catch(()=>(rh(n),null))}loadImage(t){const n=this,r=tK();return s5(n),n._loader.sanitize(t,{context:"image"}).then(i=>{const s=i.href;if(!s||!r)throw{url:s};const o=new r,a=be(i,"crossOrigin")?i.crossOrigin:"anonymous";return a!=null&&(o.crossOrigin=a),o.onload=()=>rh(n),o.onerror=()=>rh(n),o.src=s,o}).catch(i=>(rh(n),{complete:!1,width:0,height:0,src:i&&i.url||""}))}ready(){const t=this;return new Promise(n=>{function r(i){t.pending()?setTimeout(()=>{r(!0)},10):n(i)}r(!1)})}}function s5(e){e._pending+=1}function rh(e){e._pending-=1}function _a(e,t,n){if(t.stroke&&t.opacity!==0&&t.strokeOpacity!==0){const r=t.strokeWidth!=null?+t.strokeWidth:1;e.expand(r+(n?NJ(t,r):0))}return e}function NJ(e,t){return e.strokeJoin&&e.strokeJoin!=="miter"?0:t}const OJ=to-1e-8;let iv,nm,rm,vl,R_,im,T_,N_;const Ha=(e,t)=>iv.add(e,t),sm=(e,t)=>Ha(nm=e,rm=t),o5=e=>Ha(e,iv.y1),a5=e=>Ha(iv.x1,e),ll=(e,t)=>R_*e+T_*t,cl=(e,t)=>im*e+N_*t,g2=(e,t)=>Ha(ll(e,t),cl(e,t)),m2=(e,t)=>sm(ll(e,t),cl(e,t));function vg(e,t){return iv=e,t?(vl=t*mu,R_=N_=Math.cos(vl),im=Math.sin(vl),T_=-im):(R_=N_=1,vl=im=T_=0),LJ}const LJ={beginPath(){},closePath(){},moveTo:m2,lineTo:m2,rect(e,t,n,r){vl?(g2(e+n,t),g2(e+n,t+r),g2(e,t+r),m2(e,t)):(Ha(e+n,t+r),sm(e,t))},quadraticCurveTo(e,t,n,r){const i=ll(e,t),s=cl(e,t),o=ll(n,r),a=cl(n,r);u5(nm,i,o,o5),u5(rm,s,a,a5),sm(o,a)},bezierCurveTo(e,t,n,r,i,s){const o=ll(e,t),a=cl(e,t),u=ll(n,r),l=cl(n,r),c=ll(i,s),f=cl(i,s);l5(nm,o,u,c,o5),l5(rm,a,l,f,a5),sm(c,f)},arc(e,t,n,r,i,s){if(r+=vl,i+=vl,nm=n*Math.cos(i)+e,rm=n*Math.sin(i)+t,Math.abs(i-r)>OJ)Ha(e-n,t-n),Ha(e+n,t+n);else{const o=l=>Ha(n*Math.cos(l)+e,n*Math.sin(l)+t);let a,u;if(o(r),o(i),i!==r)if(r=r%to,r<0&&(r+=to),i=i%to,i<0&&(i+=to),ii;++u,a-=ul)o(a);else for(a=r-r%ul+ul,u=0;u<4&&aXZ?(c=o*o+a*s,c>=0&&(c=Math.sqrt(c),u=(-o+c)/s,l=(-o-c)/s)):u=.5*a/o,0d)return!1;g>f&&(f=g)}else if(h>0){if(g0?(e.globalAlpha=n,e.fillStyle=s7(e,t,t.fill),!0):!1}var PJ=[];function Vf(e,t,n){var r=(r=t.strokeWidth)!=null?r:1;return r<=0?!1:(n*=t.strokeOpacity==null?1:t.strokeOpacity,n>0?(e.globalAlpha=n,e.strokeStyle=s7(e,t,t.stroke),e.lineWidth=r,e.lineCap=t.strokeCap||"butt",e.lineJoin=t.strokeJoin||"miter",e.miterLimit=t.strokeMiterLimit||10,e.setLineDash&&(e.setLineDash(t.strokeDash||PJ),e.lineDashOffset=t.strokeDashOffset||0),!0):!1)}function BJ(e,t){return e.zindex-t.zindex||e.index-t.index}function qS(e){if(!e.zdirty)return e.zitems;var t=e.items,n=[],r,i,s;for(i=0,s=t.length;i=0;)if(r=t(n[i]))return r;if(n===s){for(n=e.items,i=n.length;--i>=0;)if(!n[i].zindex&&(r=t(n[i])))return r}return null}function WS(e){return function(t,n,r){ks(n,i=>{(!r||r.intersects(i.bounds))&&o7(e,t,i,i)})}}function zJ(e){return function(t,n,r){n.items.length&&(!r||r.intersects(n.bounds))&&o7(e,t,n.items[0],n.items)}}function o7(e,t,n,r){var i=n.opacity==null?1:n.opacity;i!==0&&(e(t,r)||(Yf(t,n),n.fill&&Zm(t,n,i)&&t.fill(),n.stroke&&Vf(t,n,i)&&t.stroke()))}function sv(e){return e=e||yi,function(t,n,r,i,s,o){return r*=t.pixelRatio,i*=t.pixelRatio,Jm(n,a=>{const u=a.bounds;if(!(u&&!u.contains(s,o)||!u)&&e(t,a,r,i,s,o))return a})}}function bg(e,t){return function(n,r,i,s){var o=Array.isArray(r)?r[0]:r,a=t??o.fill,u=o.stroke&&n.isPointInStroke,l,c;return u&&(l=o.strokeWidth,c=o.strokeCap,n.lineWidth=l??1,n.lineCap=c??"butt"),e(n,r)?!1:a&&n.isPointInPath(i,s)||u&&n.isPointInStroke(i,s)}}function HS(e){return sv(bg(e))}function Fl(e,t){return"translate("+e+","+t+")"}function GS(e){return"rotate("+e+")"}function jJ(e,t){return"scale("+e+","+t+")"}function a7(e){return Fl(e.x||0,e.y||0)}function UJ(e){return Fl(e.x||0,e.y||0)+(e.angle?" "+GS(e.angle):"")}function qJ(e){return Fl(e.x||0,e.y||0)+(e.angle?" "+GS(e.angle):"")+(e.scaleX||e.scaleY?" "+jJ(e.scaleX||1,e.scaleY||1):"")}function YS(e,t,n){function r(o,a){o("transform",UJ(a)),o("d",t(null,a))}function i(o,a){return t(vg(o,a.angle),a),_a(o,a).translate(a.x||0,a.y||0)}function s(o,a){var u=a.x||0,l=a.y||0,c=a.angle||0;o.translate(u,l),c&&o.rotate(c*=mu),o.beginPath(),t(o,a),c&&o.rotate(-c),o.translate(-u,-l)}return{type:e,tag:"path",nested:!1,attr:r,bound:i,draw:WS(s),pick:HS(s),isect:n||jS(s)}}var WJ=YS("arc",$J);function HJ(e,t){for(var n=e[0].orient==="horizontal"?t[1]:t[0],r=e[0].orient==="horizontal"?"y":"x",i=e.length,s=1/0,o,a;--i>=0;)e[i].defined!==!1&&(a=Math.abs(e[i][r]-n),a=0;)if(e[r].defined!==!1&&(i=e[r].x-t[0],s=e[r].y-t[1],o=i*i+s*s,o=0;)if(e[n].defined!==!1&&(r=e[n].x-t[0],i=e[n].y-t[1],s=r*r+i*i,r=e[n].size||1,s.5&&t<1.5?.5-Math.abs(t-1):0}function KJ(e,t){e("transform",a7(t))}function c7(e,t){const n=l7(t);e("d",Rd(null,t,n,n))}function ZJ(e,t){e("class","background"),e("aria-hidden",!0),c7(e,t)}function JJ(e,t){e("class","foreground"),e("aria-hidden",!0),t.strokeForeground?c7(e,t):e("d","")}function QJ(e,t,n){const r=t.clip?zS(n,t,t):null;e("clip-path",r)}function eQ(e,t){if(!t.clip&&t.items){const n=t.items,r=n.length;for(let i=0;i{const s=i.x||0,o=i.y||0,a=i.strokeForeground,u=i.opacity==null?1:i.opacity;(i.stroke||i.fill)&&u&&(_p(e,i,s,o),Yf(e,i),i.fill&&Zm(e,i,u)&&e.fill(),i.stroke&&!a&&Vf(e,i,u)&&e.stroke()),e.save(),e.translate(s,o),i.clip&&u7(e,i),n&&n.translate(-s,-o),ks(i,l=>{(l.marktype==="group"||r==null||r.includes(l.marktype))&&this.draw(e,l,n,r)}),n&&n.translate(s,o),e.restore(),a&&i.stroke&&u&&(_p(e,i,s,o),Yf(e,i),Vf(e,i,u)&&e.stroke())})}function sQ(e,t,n,r,i,s){if(t.bounds&&!t.bounds.contains(i,s)||!t.items)return null;const o=n*e.pixelRatio,a=r*e.pixelRatio;return Jm(t,u=>{let l,c,f;const d=u.bounds;if(d&&!d.contains(i,s))return;c=u.x||0,f=u.y||0;const h=c+(u.width||0),p=f+(u.height||0),g=u.clip;if(g&&(ih||sp))return;if(e.save(),e.translate(c,f),c=i-c,f=s-f,g&&BS(u)&&!rQ(e,u,o,a))return e.restore(),null;const m=u.strokeForeground,y=t.interactive!==!1;return y&&m&&u.stroke&&nQ(e,u,o,a)?(e.restore(),u):(l=Jm(u,v=>oQ(v,c,f)?this.pick(v,n,r,c,f):null),!l&&y&&(u.fill||!m&&u.stroke)&&tQ(e,u,o,a)&&(l=u),e.restore(),l||null)})}function oQ(e,t,n){return(e.interactive!==!1||e.marktype==="group")&&e.bounds&&e.bounds.contains(t,n)}var aQ={type:"group",tag:"g",nested:!1,attr:KJ,bound:eQ,draw:iQ,pick:sQ,isect:r7,content:QJ,background:ZJ,foreground:JJ},wp={xmlns:"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink",version:"1.1"};function XS(e,t){var n=e.image;return(!n||e.url&&e.url!==n.url)&&(n={complete:!1,width:0,height:0},t.loadImage(e.url).then(r=>{e.image=r,e.image.url=e.url})),n}function KS(e,t){return e.width!=null?e.width:!t||!t.width?0:e.aspect!==!1&&e.height?e.height*t.width/t.height:t.width}function ZS(e,t){return e.height!=null?e.height:!t||!t.height?0:e.aspect!==!1&&e.width?e.width*t.height/t.width:t.height}function ov(e,t){return e==="center"?t/2:e==="right"?t:0}function av(e,t){return e==="middle"?t/2:e==="bottom"?t:0}function uQ(e,t,n){const r=XS(t,n),i=KS(t,r),s=ZS(t,r),o=(t.x||0)-ov(t.align,i),a=(t.y||0)-av(t.baseline,s),u=!r.src&&r.toDataURL?r.toDataURL():r.src||"";e("href",u,wp["xmlns:xlink"],"xlink:href"),e("transform",Fl(o,a)),e("width",i),e("height",s),e("preserveAspectRatio",t.aspect===!1?"none":"xMidYMid")}function lQ(e,t){const n=t.image,r=KS(t,n),i=ZS(t,n),s=(t.x||0)-ov(t.align,r),o=(t.y||0)-av(t.baseline,i);return e.set(s,o,s+r,o+i)}function cQ(e,t,n){ks(t,r=>{if(n&&!n.intersects(r.bounds))return;const i=XS(r,this);let s=KS(r,i),o=ZS(r,i);if(s===0||o===0)return;let a=(r.x||0)-ov(r.align,s),u=(r.y||0)-av(r.baseline,o),l,c,f,d;r.aspect!==!1&&(c=i.width/i.height,f=r.width/r.height,c===c&&f===f&&c!==f&&(f{if(!(n&&!n.intersects(r.bounds))){var i=r.opacity==null?1:r.opacity;i&&f7(e,r,i)&&(Yf(e,r),e.stroke())}})}function wQ(e,t,n,r){return e.isPointInStroke?f7(e,t,1)&&e.isPointInStroke(n,r):!1}var EQ={type:"rule",tag:"line",nested:!1,attr:bQ,bound:xQ,draw:_Q,pick:sv(wQ),isect:i7},AQ=YS("shape",MJ),SQ=YS("symbol",RJ,US);const h5=bR();var pi={height:Fo,measureWidth:JS,estimateWidth:Qm,width:Qm,canvas:d7};d7(!0);function d7(e){pi.width=e&&uu?JS:Qm}function Qm(e,t){return h7(vu(e,t),Fo(e))}function h7(e,t){return~~(.8*e.length*t)}function JS(e,t){return Fo(e)<=0||!(t=vu(e,t))?0:p7(t,uv(e))}function p7(e,t){const n=`(${t}) ${e}`;let r=h5.get(n);return r===void 0&&(uu.font=t,r=uu.measureText(e).width,h5.set(n,r)),r}function Fo(e){return e.fontSize!=null?+e.fontSize||0:11}function yu(e){return e.lineHeight!=null?e.lineHeight:Fo(e)+2}function kQ(e){return ee(e)?e.length>1?e:e[0]:e}function xg(e){return kQ(e.lineBreak&&e.text&&!ee(e.text)?e.text.split(e.lineBreak):e.text)}function QS(e){const t=xg(e);return(ee(t)?t.length-1:0)*yu(e)}function vu(e,t){const n=t==null?"":(t+"").trim();return e.limit>0&&n.length?$Q(e,n):n}function CQ(e){if(pi.width===JS){const t=uv(e);return n=>p7(n,t)}else if(pi.width===Qm){const t=Fo(e);return n=>h7(n,t)}else return t=>pi.width(e,t)}function $Q(e,t){var n=+e.limit,r=CQ(e);if(r(t)>>1,r(t.slice(u))>n?o=u+1:a=u;return i+t.slice(o)}else{for(;o>>1),r(t.slice(0,u))Math.max(d,pi.width(t,h)),0)):f=pi.width(t,c),i==="center"?u-=f/2:i==="right"&&(u-=f),e.set(u+=o,l+=a,u+f,l+r),t.angle&&!n)e.rotate(t.angle*mu,o,a);else if(n===2)return e.rotatedPoints(t.angle*mu,o,a);return e}function MQ(e,t,n){ks(t,r=>{var i=r.opacity==null?1:r.opacity,s,o,a,u,l,c,f;if(!(n&&!n.intersects(r.bounds)||i===0||r.fontSize<=0||r.text==null||r.text.length===0)){if(e.font=uv(r),e.textAlign=r.align||"left",s=lv(r),o=s.x1,a=s.y1,r.angle&&(e.save(),e.translate(o,a),e.rotate(r.angle*mu),o=a=0),o+=r.dx||0,a+=(r.dy||0)+ek(r),c=xg(r),Yf(e,r),ee(c))for(l=yu(r),u=0;ut;)e.removeChild(n[--r]);return e}function x7(e){return"mark-"+e.marktype+(e.role?" role-"+e.role:"")+(e.name?" "+e.name:"")}function cv(e,t){const n=t.getBoundingClientRect();return[e.clientX-n.left-(t.clientLeft||0),e.clientY-n.top-(t.clientTop||0)]}function IQ(e,t,n,r){var i=e&&e.mark,s,o;if(i&&(s=xi[i.marktype]).tip){for(o=cv(t,n),o[0]-=r[0],o[1]-=r[1];e=e.mark.group;)o[0]-=e.x||0,o[1]-=e.y||0;e=s.tip(i.items,o)}return e}let rk=class{constructor(t,n){this._active=null,this._handlers={},this._loader=t||Fy(),this._tooltip=n||PQ}initialize(t,n,r){return this._el=t,this._obj=r||null,this.origin(n)}element(){return this._el}canvas(){return this._el&&this._el.firstChild}origin(t){return arguments.length?(this._origin=t||[0,0],this):this._origin.slice()}scene(t){return arguments.length?(this._scene=t,this):this._scene}on(){}off(){}_handlerIndex(t,n,r){for(let i=t?t.length:0;--i>=0;)if(t[i].type===n&&(!r||t[i].handler===r))return i;return-1}handlers(t){const n=this._handlers,r=[];if(t)r.push(...n[this.eventName(t)]);else for(const i in n)r.push(...n[i]);return r}eventName(t){const n=t.indexOf(".");return n<0?t:t.slice(0,n)}handleHref(t,n,r){this._loader.sanitize(r,{context:"href"}).then(i=>{const s=new MouseEvent(t.type,t),o=Ga(null,"a");for(const a in i)o.setAttribute(a,i[a]);o.dispatchEvent(s)}).catch(()=>{})}handleTooltip(t,n,r){if(n&&n.tooltip!=null){n=IQ(n,t,this.canvas(),this._origin);const i=r&&n&&n.tooltip||null;this._tooltip.call(this._obj,this,t,n,i)}}getItemBoundingClientRect(t){const n=this.canvas();if(!n)return;const r=n.getBoundingClientRect(),i=this._origin,s=t.bounds,o=s.width(),a=s.height();let u=s.x1+i[0]+r.left,l=s.y1+i[1]+r.top;for(;t.mark&&(t=t.mark.group);)u+=t.x||0,l+=t.y||0;return{x:u,y:l,width:o,height:a,left:u,top:l,right:u+o,bottom:l+a}}};function PQ(e,t,n,r){e.element().setAttribute("title",r||"")}class wg{constructor(t){this._el=null,this._bgcolor=null,this._loader=new n7(t)}initialize(t,n,r,i,s){return this._el=t,this.resize(n,r,i,s)}element(){return this._el}canvas(){return this._el&&this._el.firstChild}background(t){return arguments.length===0?this._bgcolor:(this._bgcolor=t,this)}resize(t,n,r,i){return this._width=t,this._height=n,this._origin=r||[0,0],this._scale=i||1,this}dirty(){}render(t,n){const r=this;return r._call=function(){r._render(t,n)},r._call(),r._call=null,r}_render(){}renderAsync(t,n){const r=this.render(t,n);return this._ready?this._ready.then(()=>r):Promise.resolve(r)}_load(t,n){var r=this,i=r._loader[t](n);if(!r._ready){const s=r._call;r._ready=r._loader.ready().then(o=>{o&&s(),r._ready=null})}return i}sanitizeURL(t){return this._load("sanitizeURL",t)}loadImage(t){return this._load("loadImage",t)}}const BQ="keydown",zQ="keypress",jQ="keyup",_7="dragenter",am="dragleave",w7="dragover",I_="pointerdown",UQ="pointerup",e1="pointermove",um="pointerout",E7="pointerover",P_="mousedown",qQ="mouseup",A7="mousemove",t1="mouseout",S7="mouseover",n1="click",WQ="dblclick",HQ="wheel",k7="mousewheel",r1="touchstart",i1="touchmove",s1="touchend",GQ=[BQ,zQ,jQ,_7,am,w7,I_,UQ,e1,um,E7,P_,qQ,A7,t1,S7,n1,WQ,HQ,k7,r1,i1,s1],B_=e1,Kh=t1,z_=n1;class Eg extends rk{constructor(t,n){super(t,n),this._down=null,this._touch=null,this._first=!0,this._events={},this.events=GQ,this.pointermove=y5([e1,A7],[E7,S7],[um,t1]),this.dragover=y5([w7],[_7],[am]),this.pointerout=v5([um,t1]),this.dragleave=v5([am])}initialize(t,n,r){return this._canvas=t&&nk(t,"canvas"),[n1,P_,I_,e1,um,am].forEach(i=>m5(this,i)),super.initialize(t,n,r)}canvas(){return this._canvas}context(){return this._canvas.getContext("2d")}DOMMouseScroll(t){this.fire(k7,t)}pointerdown(t){this._down=this._active,this.fire(I_,t)}mousedown(t){this._down=this._active,this.fire(P_,t)}click(t){this._down===this._active&&(this.fire(n1,t),this._down=null)}touchstart(t){this._touch=this.pickEvent(t.changedTouches[0]),this._first&&(this._active=this._touch,this._first=!1),this.fire(r1,t,!0)}touchmove(t){this.fire(i1,t,!0)}touchend(t){this.fire(s1,t,!0),this._touch=null}fire(t,n,r){const i=r?this._touch:this._active,s=this._handlers[t];if(n.vegaType=t,t===z_&&i&&i.href?this.handleHref(n,i,i.href):(t===B_||t===Kh)&&this.handleTooltip(n,i,t!==Kh),s)for(let o=0,a=s.length;o=0&&i.splice(s,1),this}pickEvent(t){const n=cv(t,this._canvas),r=this._origin;return this.pick(this._scene,n[0],n[1],n[0]-r[0],n[1]-r[1])}pick(t,n,r,i,s){const o=this.context();return xi[t.marktype].pick.call(this,o,t,n,r,i,s)}}const YQ=e=>e===r1||e===i1||e===s1?[r1,i1,s1]:[e];function m5(e,t){YQ(t).forEach(n=>VQ(e,n))}function VQ(e,t){const n=e.canvas();n&&!e._events[t]&&(e._events[t]=1,n.addEventListener(t,e[t]?r=>e[t](r):r=>e.fire(t,r)))}function $h(e,t,n){t.forEach(r=>e.fire(r,n))}function y5(e,t,n){return function(r){const i=this._active,s=this.pickEvent(r);s===i?$h(this,e,r):((!i||!i.exit)&&$h(this,n,r),this._active=s,$h(this,t,r),$h(this,e,r))}}function v5(e){return function(t){$h(this,e,t),this._active=null}}function XQ(){return typeof window<"u"&&window.devicePixelRatio||1}function KQ(e,t,n,r,i,s){const o=typeof HTMLElement<"u"&&e instanceof HTMLElement&&e.parentNode!=null,a=e.getContext("2d"),u=o?XQ():i;e.width=t*u,e.height=n*u;for(const l in s)a[l]=s[l];return o&&u!==1&&(e.style.width=t+"px",e.style.height=n+"px"),a.pixelRatio=u,a.setTransform(u,0,0,u,u*r[0],u*r[1]),e}class o1 extends wg{constructor(t){super(t),this._options={},this._redraw=!1,this._dirty=new dn,this._tempb=new dn}initialize(t,n,r,i,s,o){return this._options=o||{},this._canvas=this._options.externalContext?null:au(1,1,this._options.type),t&&this._canvas&&(Fi(t,0).appendChild(this._canvas),this._canvas.setAttribute("class","marks")),super.initialize(t,n,r,i,s)}resize(t,n,r,i){if(super.resize(t,n,r,i),this._canvas)KQ(this._canvas,this._width,this._height,this._origin,this._scale,this._options.context);else{const s=this._options.externalContext;s||X("CanvasRenderer is missing a valid canvas or context"),s.scale(this._scale,this._scale),s.translate(this._origin[0],this._origin[1])}return this._redraw=!0,this}canvas(){return this._canvas}context(){return this._options.externalContext||(this._canvas?this._canvas.getContext("2d"):null)}dirty(t){const n=this._tempb.clear().union(t.bounds);let r=t.mark.group;for(;r;)n.translate(r.x||0,r.y||0),r=r.mark.group;this._dirty.union(n)}_render(t,n){const r=this.context(),i=this._origin,s=this._width,o=this._height,a=this._dirty,u=ZQ(i,s,o);r.save();const l=this._redraw||a.empty()?(this._redraw=!1,u.expand(1)):JQ(r,u.intersect(a),i);return this.clear(-i[0],-i[1],s,o),this.draw(r,t,l,n),r.restore(),a.clear(),this}draw(t,n,r,i){if(n.marktype!=="group"&&i!=null&&!i.includes(n.marktype))return;const s=xi[n.marktype];n.clip&&XJ(t,n),s.draw.call(this,t,n,r,i),n.clip&&t.restore()}clear(t,n,r,i){const s=this._options,o=this.context();s.type!=="pdf"&&!s.externalContext&&o.clearRect(t,n,r,i),this._bgcolor!=null&&(o.fillStyle=this._bgcolor,o.fillRect(t,n,r,i))}}const ZQ=(e,t,n)=>new dn().set(0,0,t,n).translate(-e[0],-e[1]);function JQ(e,t,n){return t.expand(1).round(),e.pixelRatio%1&&t.scale(e.pixelRatio).round().scale(1/e.pixelRatio),t.translate(-(n[0]%1),-(n[1]%1)),e.beginPath(),e.rect(t.x1,t.y1,t.width(),t.height()),e.clip(),t}class C7 extends rk{constructor(t,n){super(t,n);const r=this;r._hrefHandler=y2(r,(i,s)=>{s&&s.href&&r.handleHref(i,s,s.href)}),r._tooltipHandler=y2(r,(i,s)=>{r.handleTooltip(i,s,i.type!==Kh)})}initialize(t,n,r){let i=this._svg;return i&&(i.removeEventListener(z_,this._hrefHandler),i.removeEventListener(B_,this._tooltipHandler),i.removeEventListener(Kh,this._tooltipHandler)),this._svg=i=t&&nk(t,"svg"),i&&(i.addEventListener(z_,this._hrefHandler),i.addEventListener(B_,this._tooltipHandler),i.addEventListener(Kh,this._tooltipHandler)),super.initialize(t,n,r)}canvas(){return this._svg}on(t,n){const r=this.eventName(t),i=this._handlers;if(this._handlerIndex(i[r],t,n)<0){const o={type:t,handler:n,listener:y2(this,n)};(i[r]||(i[r]=[])).push(o),this._svg&&this._svg.addEventListener(r,o.listener)}return this}off(t,n){const r=this.eventName(t),i=this._handlers[r],s=this._handlerIndex(i,t,n);return s>=0&&(this._svg&&this._svg.removeEventListener(r,i[s].listener),i.splice(s,1)),this}}const y2=(e,t)=>n=>{let r=n.target.__data__;r=Array.isArray(r)?r[0]:r,n.vegaType=n.type,t.call(e._obj,n,r)},$7="aria-hidden",ik="aria-label",sk="role",ok="aria-roledescription",F7="graphics-object",ak="graphics-symbol",D7=(e,t,n)=>({[sk]:e,[ok]:t,[ik]:n||void 0}),QQ=As(["axis-domain","axis-grid","axis-label","axis-tick","axis-title","legend-band","legend-entry","legend-gradient","legend-label","legend-title","legend-symbol","title"]),b5={axis:{desc:"axis",caption:nee},legend:{desc:"legend",caption:ree},"title-text":{desc:"title",caption:e=>`Title text '${_5(e)}'`},"title-subtitle":{desc:"subtitle",caption:e=>`Subtitle text '${_5(e)}'`}},x5={ariaRole:sk,ariaRoleDescription:ok,description:ik};function M7(e,t){const n=t.aria===!1;if(e($7,n||void 0),n||t.description==null)for(const r in x5)e(x5[r],void 0);else{const r=t.mark.marktype;e(ik,t.description),e(sk,t.ariaRole||(r==="group"?F7:ak)),e(ok,t.ariaRoleDescription||`${r} mark`)}}function R7(e){return e.aria===!1?{[$7]:!0}:QQ[e.role]?null:b5[e.role]?tee(e,b5[e.role]):eee(e)}function eee(e){const t=e.marktype,n=t==="group"||t==="text"||e.items.some(r=>r.description!=null&&r.aria!==!1);return D7(n?F7:ak,`${t} mark container`,e.description)}function tee(e,t){try{const n=e.items[0],r=t.caption||(()=>"");return D7(t.role||ak,t.desc,n.description||r(n))}catch{return null}}function _5(e){return ye(e.text).join(" ")}function nee(e){const t=e.datum,n=e.orient,r=t.title?T7(e):null,i=e.context,s=i.scales[t.scale].value,o=i.dataflow.locale(),a=s.type;return`${n==="left"||n==="right"?"Y":"X"}-axis`+(r?` titled '${r}'`:"")+` for a ${Hf(a)?"discrete":a} scale with ${GO(o,s,e)}`}function ree(e){const t=e.datum,n=t.title?T7(e):null,r=`${t.type||""} legend`.trim(),i=t.scales,s=Object.keys(i),o=e.context,a=o.scales[i[s[0]]].value,u=o.dataflow.locale();return see(r)+(n?` titled '${n}'`:"")+` for ${iee(s)} with ${GO(u,a,e)}`}function T7(e){try{return ye(st(e.items).items[0].text).join(" ")}catch{return null}}function iee(e){return e=e.map(t=>t+(t==="fill"||t==="stroke"?" color":"")),e.length<2?e[0]:e.slice(0,-1).join(", ")+" and "+st(e)}function see(e){return e.length?e[0].toUpperCase()+e.slice(1):e}const N7=e=>(e+"").replace(/&/g,"&").replace(//g,">"),oee=e=>N7(e).replace(/"/g,""").replace(/\t/g," ").replace(/\n/g," ").replace(/\r/g," ");function uk(){let e="",t="",n="";const r=[],i=()=>t=n="",s=u=>{t&&(e+=`${t}>${n}`,i()),r.push(u)},o=(u,l)=>(l!=null&&(t+=` ${u}="${oee(l)}"`),a),a={open(u){s(u),t="<"+u;for(var l=arguments.length,c=new Array(l>1?l-1:0),f=1;f${n}`:"/>"):e+=``,i(),a},attr:o,text:u=>(n+=N7(u),a),toString:()=>e};return a}const O7=e=>L7(uk(),e)+"";function L7(e,t){if(e.open(t.tagName),t.hasAttributes()){const n=t.attributes,r=n.length;for(let i=0;i{c.dirty=n})),!i.zdirty){if(r.exit){o.nested&&i.items.length?(l=i.items[0],l._svg&&this._update(o,l._svg,l)):r._svg&&(l=r._svg.parentNode,l&&l.removeChild(r._svg)),r._svg=null;continue}r=o.nested?i.items[0]:r,r._update!==n&&(!r._svg||!r._svg.ownerSVGElement?(this._dirtyAll=!1,E5(r,n)):this._update(o,r._svg,r),r._update=n)}return!this._dirtyAll}mark(t,n,r,i){if(!this.isDirty(n))return n._svg;const s=this._svg,o=n.marktype,a=xi[o],u=n.interactive===!1?"none":null,l=a.tag==="g",c=A5(n,t,r,"g",s);if(o!=="group"&&i!=null&&!i.includes(o))return Fi(c,0),n._svg;c.setAttribute("class",x7(n));const f=R7(n);for(const g in f)vr(c,g,f[g]);l||vr(c,"pointer-events",u),vr(c,"clip-path",n.clip?zS(this,n,n.group):null);let d=null,h=0;const p=g=>{const m=this.isDirty(g),y=A5(g,c,d,a.tag,s);m&&(this._update(a,y,g),l&&lee(this,y,g,i)),d=y,++h};return a.nested?n.items.length&&p(n.items[0]):ks(n,p),Fi(c,h),c}_update(t,n,r){ia=n,rr=n.__values__,M7(Zh,r),t.attr(Zh,r,this);const i=fee[t.type];i&&i.call(this,t,n,r),ia&&this.style(ia,r)}style(t,n){if(n!=null){for(const r in a1){let i=r==="font"?_g(n):n[r];if(i===rr[r])continue;const s=a1[r];i==null?t.removeAttribute(s):(IS(i)&&(i=VO(i,this._defs.gradient,P7())),t.setAttribute(s,i+"")),rr[r]=i}for(const r in u1)lm(t,u1[r],n[r])}}defs(){const t=this._svg,n=this._defs;let r=n.el,i=0;for(const s in n.gradient)r||(n.el=r=gn(t,ih+1,"defs",pn)),i=aee(r,n.gradient[s],i);for(const s in n.clipping)r||(n.el=r=gn(t,ih+1,"defs",pn)),i=uee(r,n.clipping[s],i);r&&(i===0?(t.removeChild(r),n.el=null):Fi(r,i))}_clearDefs(){const t=this._defs;t.gradient={},t.clipping={}}}function E5(e,t){for(;e&&e.dirty!==t;e=e.mark.group)if(e.dirty=t,e.mark&&e.mark.dirty!==t)e.mark.dirty=t;else return}function aee(e,t,n){let r,i,s;if(t.gradient==="radial"){let o=gn(e,n++,"pattern",pn);Ya(o,{id:Km+t.id,viewBox:"0,0,1,1",width:"100%",height:"100%",preserveAspectRatio:"xMidYMid slice"}),o=gn(o,0,"rect",pn),Ya(o,{width:1,height:1,fill:`url(${P7()}#${t.id})`}),e=gn(e,n++,"radialGradient",pn),Ya(e,{id:t.id,fx:t.x1,fy:t.y1,fr:t.r1,cx:t.x2,cy:t.y2,r:t.r2})}else e=gn(e,n++,"linearGradient",pn),Ya(e,{id:t.id,x1:t.x1,x2:t.x2,y1:t.y1,y2:t.y2});for(r=0,i=t.stops.length;r{i=e.mark(t,o,i,r),++s}),Fi(t,1+s)}function A5(e,t,n,r,i){let s=e._svg,o;if(!s&&(o=t.ownerDocument,s=Ga(o,r,pn),e._svg=s,e.mark&&(s.__data__=e,s.__values__={fill:"default"},r==="g"))){const a=Ga(o,"path",pn);s.appendChild(a),a.__data__=e;const u=Ga(o,"g",pn);s.appendChild(u),u.__data__=e;const l=Ga(o,"path",pn);s.appendChild(l),l.__data__=e,l.__values__={fill:"default"}}return(s.ownerSVGElement!==i||cee(s,n))&&t.insertBefore(s,n?n.nextSibling:t.firstChild),s}function cee(e,t){return e.parentNode&&e.parentNode.childNodes.length>1&&e.previousSibling!=t}let ia=null,rr=null;const fee={group(e,t,n){const r=ia=t.childNodes[2];rr=r.__values__,e.foreground(Zh,n,this),rr=t.__values__,ia=t.childNodes[1],e.content(Zh,n,this);const i=ia=t.childNodes[0];e.background(Zh,n,this);const s=n.mark.interactive===!1?"none":null;if(s!==rr.events&&(vr(r,"pointer-events",s),vr(i,"pointer-events",s),rr.events=s),n.strokeForeground&&n.stroke){const o=n.fill;vr(r,"display",null),this.style(i,n),vr(i,"stroke",null),o&&(n.fill=null),rr=r.__values__,this.style(r,n),o&&(n.fill=o),ia=null}else vr(r,"display","none")},image(e,t,n){n.smooth===!1?(lm(t,"image-rendering","optimizeSpeed"),lm(t,"image-rendering","pixelated")):lm(t,"image-rendering",null)},text(e,t,n){const r=xg(n);let i,s,o,a;ee(r)?(s=r.map(u=>vu(n,u)),i=s.join(` +`),i!==rr.text&&(Fi(t,0),o=t.ownerDocument,a=yu(n),s.forEach((u,l)=>{const c=Ga(o,"tspan",pn);c.__data__=n,c.textContent=u,l&&(c.setAttribute("x",0),c.setAttribute("dy",a)),t.appendChild(c)}),rr.text=i)):(s=vu(n,r),s!==rr.text&&(t.textContent=s,rr.text=s)),vr(t,"font-family",_g(n)),vr(t,"font-size",Fo(n)+"px"),vr(t,"font-style",n.fontStyle),vr(t,"font-variant",n.fontVariant),vr(t,"font-weight",n.fontWeight)}};function Zh(e,t,n){t!==rr[e]&&(n?dee(ia,e,t,n):vr(ia,e,t),rr[e]=t)}function lm(e,t,n){n!==rr[t]&&(n==null?e.style.removeProperty(t):e.style.setProperty(t,n+""),rr[t]=n)}function Ya(e,t){for(const n in t)vr(e,n,t[n])}function vr(e,t,n){n!=null?e.setAttribute(t,n):e.removeAttribute(t)}function dee(e,t,n,r){n!=null?e.setAttributeNS(r,t,n):e.removeAttributeNS(r,t)}function P7(){let e;return typeof window>"u"?"":(e=window.location).hash?e.href.slice(0,-e.hash.length):e.href}class B7 extends wg{constructor(t){super(t),this._text=null,this._defs={gradient:{},clipping:{}}}svg(){return this._text}_render(t){const n=uk();n.open("svg",We({},wp,{class:"marks",width:this._width*this._scale,height:this._height*this._scale,viewBox:`0 0 ${this._width} ${this._height}`}));const r=this._bgcolor;return r&&r!=="transparent"&&r!=="none"&&n.open("rect",{width:this._width,height:this._height,fill:r}).close(),n.open("g",I7,{transform:"translate("+this._origin+")"}),this.mark(n,t),n.close(),this.defs(n),this._text=n.close()+"",this}mark(t,n){const r=xi[n.marktype],i=r.tag,s=[M7,r.attr];t.open("g",{class:x7(n),"clip-path":n.clip?zS(this,n,n.group):null},R7(n),{"pointer-events":i!=="g"&&n.interactive===!1?"none":null});const o=a=>{const u=this.href(a);if(u&&t.open("a",u),t.open(i,this.attr(n,a,s,i!=="g"?i:null)),i==="text"){const l=xg(a);if(ee(l)){const c={x:0,dy:yu(a)};for(let f=0;fthis.mark(t,d)),t.close(),l&&f?(c&&(a.fill=null),a.stroke=f,t.open("path",this.attr(n,a,r.foreground,"bgrect")).close(),c&&(a.fill=c)):t.open("path",this.attr(n,a,r.foreground,"bgfore")).close()}t.close(),u&&t.close()};return r.nested?n.items&&n.items.length&&o(n.items[0]):ks(n,o),t.close()}href(t){const n=t.href;let r;if(n){if(r=this._hrefs&&this._hrefs[n])return r;this.sanitizeURL(n).then(i=>{i["xlink:href"]=i.href,i.href=null,(this._hrefs||(this._hrefs={}))[n]=i})}return null}attr(t,n,r,i){const s={},o=(a,u,l,c)=>{s[c||a]=u};return Array.isArray(r)?r.forEach(a=>a(o,n,this)):r(o,n,this),i&&hee(s,n,t,i,this._defs),s}defs(t){const n=this._defs.gradient,r=this._defs.clipping;if(Object.keys(n).length+Object.keys(r).length!==0){t.open("defs");for(const s in n){const o=n[s],a=o.stops;o.gradient==="radial"?(t.open("pattern",{id:Km+s,viewBox:"0,0,1,1",width:"100%",height:"100%",preserveAspectRatio:"xMidYMid slice"}),t.open("rect",{width:"1",height:"1",fill:"url(#"+s+")"}).close(),t.close(),t.open("radialGradient",{id:s,fx:o.x1,fy:o.y1,fr:o.r1,cx:o.x2,cy:o.y2,r:o.r2})):t.open("linearGradient",{id:s,x1:o.x1,x2:o.x2,y1:o.y1,y2:o.y2});for(let u=0;u!os.svgMarkTypes.includes(s));this._svgRenderer.render(t,os.svgMarkTypes),this._canvasRenderer.render(t,i)}resize(t,n,r,i){return super.resize(t,n,r,i),this._svgRenderer.resize(t,n,r,i),this._canvasRenderer.resize(t,n,r,i),this}background(t){return os.svgOnTop?this._canvasRenderer.background(t):this._svgRenderer.background(t),this}}class z7 extends Eg{constructor(t,n){super(t,n)}initialize(t,n,r){const i=gn(gn(t,0,"div"),os.svgOnTop?0:1,"div");return super.initialize(i,n,r)}}const j7="canvas",U7="hybrid",q7="png",W7="svg",H7="none",Va={Canvas:j7,PNG:q7,SVG:W7,Hybrid:U7,None:H7},Vl={};Vl[j7]=Vl[q7]={renderer:o1,headless:o1,handler:Eg};Vl[W7]={renderer:lk,headless:B7,handler:C7};Vl[U7]={renderer:j_,headless:j_,handler:z7};Vl[H7]={};function fv(e,t){return e=String(e||"").toLowerCase(),arguments.length>1?(Vl[e]=t,this):Vl[e]}function G7(e,t,n){const r=[],i=new dn().union(t),s=e.marktype;return s?Y7(e,i,n,r):s==="group"?V7(e,i,n,r):X("Intersect scene must be mark node or group item.")}function Y7(e,t,n,r){if(gee(e,t,n)){const i=e.items,s=e.marktype,o=i.length;let a=0;if(s==="group")for(;a=0;s--)if(n[s]!=r[s])return!1;for(s=n.length-1;s>=0;s--)if(i=n[s],!ck(e[i],t[i],i))return!1;return typeof e==typeof t}function vee(){t7(),UZ()}const Xf="top",ds="left",ms="right",bu="bottom",bee="top-left",xee="top-right",_ee="bottom-left",wee="bottom-right",fk="start",U_="middle",br="end",Eee="x",Aee="y",dv="group",dk="axis",hk="title",See="frame",kee="scope",pk="legend",J7="row-header",Q7="row-footer",e9="row-title",t9="column-header",n9="column-footer",r9="column-title",Cee="padding",$ee="symbol",i9="fit",s9="fit-x",o9="fit-y",Fee="pad",gk="none",f0="all",q_="each",mk="flush",Xa="column",Ka="row";function a9(e){G.call(this,null,e)}he(a9,G,{transform(e,t){const n=t.dataflow,r=e.mark,i=r.marktype,s=xi[i],o=s.bound;let a=r.bounds,u;if(s.nested)r.items.length&&n.dirty(r.items[0]),a=d0(r,o),r.items.forEach(l=>{l.bounds.clear().union(a)});else if(i===dv||e.modified())switch(t.visit(t.MOD,l=>n.dirty(l)),a.clear(),r.items.forEach(l=>a.union(d0(l,o))),r.role){case dk:case pk:case hk:t.reflow()}else u=t.changed(t.REM),t.visit(t.ADD,l=>{a.union(d0(l,o))}),t.visit(t.MOD,l=>{u=u||a.alignsWith(l.bounds),n.dirty(l),a.union(d0(l,o))}),u&&(a.clear(),r.items.forEach(l=>a.union(l.bounds)));return K7(r),t.modifies("bounds")}});function d0(e,t,n){return t(e.bounds.clear(),e,n)}const S5=":vega_identifier:";function yk(e){G.call(this,0,e)}yk.Definition={type:"Identifier",metadata:{modifies:!0},params:[{name:"as",type:"string",required:!0}]};he(yk,G,{transform(e,t){const n=Dee(t.dataflow),r=e.as;let i=n.value;return t.visit(t.ADD,s=>s[r]=s[r]||++i),n.set(this.value=i),t}});function Dee(e){return e._signals[S5]||(e._signals[S5]=e.add(0))}function u9(e){G.call(this,null,e)}he(u9,G,{transform(e,t){let n=this.value;n||(n=t.dataflow.scenegraph().mark(e.markdef,Mee(e),e.index),n.group.context=e.context,e.context.group||(e.context.group=n.group),n.source=this.source,n.clip=e.clip,n.interactive=e.interactive,this.value=n);const r=n.marktype===dv?rv:nv;return t.visit(t.ADD,i=>r.call(i,n)),(e.modified("clip")||e.modified("interactive"))&&(n.clip=e.clip,n.interactive=!!e.interactive,n.zdirty=!0,t.reflow()),n.items=t.source,t}});function Mee(e){const t=e.groups,n=e.parent;return t&&t.size===1?t.get(Object.keys(t.object)[0]):t&&n?t.lookup(n):null}function l9(e){G.call(this,null,e)}const k5={parity:e=>e.filter((t,n)=>n%2?t.opacity=0:1),greedy:(e,t)=>{let n;return e.filter((r,i)=>!i||!c9(n.bounds,r.bounds,t)?(n=r,1):r.opacity=0)}},c9=(e,t,n)=>n>Math.max(t.x1-e.x2,e.x1-t.x2,t.y1-e.y2,e.y1-t.y2),C5=(e,t)=>{for(var n=1,r=e.length,i=e[0].bounds,s;n{const t=e.bounds;return t.width()>1&&t.height()>1},Tee=(e,t,n)=>{var r=e.range(),i=new dn;return t===Xf||t===bu?i.set(r[0],-1/0,r[1],1/0):i.set(-1/0,r[0],1/0,r[1]),i.expand(n||1),s=>i.encloses(s.bounds)},$5=e=>(e.forEach(t=>t.opacity=1),e),F5=(e,t)=>e.reflow(t.modified()).modifies("opacity");he(l9,G,{transform(e,t){const n=k5[e.method]||k5.parity,r=e.separation||0;let i=t.materialize(t.SOURCE).source,s,o;if(!i||!i.length)return;if(!e.method)return e.modified("method")&&($5(i),t=F5(t,e)),t;if(i=i.filter(Ree),!i.length)return;if(e.sort&&(i=i.slice().sort(e.sort)),s=$5(i),t=F5(t,e),s.length>=3&&C5(s,r)){do s=n(s,r);while(s.length>=3&&C5(s,r));s.length<3&&!st(i).opacity&&(s.length>1&&(st(s).opacity=0),st(i).opacity=1)}e.boundScale&&e.boundTolerance>=0&&(o=Tee(e.boundScale,e.boundOrient,+e.boundTolerance),i.forEach(u=>{o(u)||(u.opacity=0)}));const a=s[0].mark.bounds.clear();return i.forEach(u=>{u.opacity&&a.union(u.bounds)}),t}});function f9(e){G.call(this,null,e)}he(f9,G,{transform(e,t){const n=t.dataflow;if(t.visit(t.ALL,r=>n.dirty(r)),t.fields&&t.fields.zindex){const r=t.source&&t.source[0];r&&(r.mark.zdirty=!0)}}});const nr=new dn;function nf(e,t,n){return e[t]===n?0:(e[t]=n,1)}function Nee(e){var t=e.items[0].orient;return t===ds||t===ms}function Oee(e){let t=+e.grid;return[e.ticks?t++:-1,e.labels?t++:-1,t+ +e.domain]}function Lee(e,t,n,r){var i=t.items[0],s=i.datum,o=i.translate!=null?i.translate:.5,a=i.orient,u=Oee(s),l=i.range,c=i.offset,f=i.position,d=i.minExtent,h=i.maxExtent,p=s.title&&i.items[u[2]].items[0],g=i.titlePadding,m=i.bounds,y=p&&QS(p),v=0,b=0,x,_;switch(nr.clear().union(m),m.clear(),(x=u[0])>-1&&m.union(i.items[x].bounds),(x=u[1])>-1&&m.union(i.items[x].bounds),a){case Xf:v=f||0,b=-c,_=Math.max(d,Math.min(h,-m.y1)),m.add(0,-_).add(l,0),p&&h0(e,p,_,g,y,0,-1,m);break;case ds:v=-c,b=f||0,_=Math.max(d,Math.min(h,-m.x1)),m.add(-_,0).add(0,l),p&&h0(e,p,_,g,y,1,-1,m);break;case ms:v=n+c,b=f||0,_=Math.max(d,Math.min(h,m.x2)),m.add(0,0).add(_,l),p&&h0(e,p,_,g,y,1,1,m);break;case bu:v=f||0,b=r+c,_=Math.max(d,Math.min(h,m.y2)),m.add(0,0).add(l,_),p&&h0(e,p,_,g,0,0,1,m);break;default:v=i.x,b=i.y}return _a(m.translate(v,b),i),nf(i,"x",v+o)|nf(i,"y",b+o)&&(i.bounds=nr,e.dirty(i),i.bounds=m,e.dirty(i)),i.mark.bounds.clear().union(m)}function h0(e,t,n,r,i,s,o,a){const u=t.bounds;if(t.auto){const l=o*(n+i+r);let c=0,f=0;e.dirty(t),s?c=(t.x||0)-(t.x=l):f=(t.y||0)-(t.y=l),t.mark.bounds.clear().union(u.translate(-c,-f)),e.dirty(t)}a.union(u)}const D5=(e,t)=>Math.floor(Math.min(e,t)),M5=(e,t)=>Math.ceil(Math.max(e,t));function Iee(e){var t=e.items,n=t.length,r=0,i,s;const o={marks:[],rowheaders:[],rowfooters:[],colheaders:[],colfooters:[],rowtitle:null,coltitle:null};for(;r1)for(E=0;E0&&(b[E]+=F/2);if(a&&Bt(n.center,Ka)&&c!==1)for(E=0;E0&&(x[E]+=C/2);for(E=0;Ei&&(e.warn("Grid headers exceed limit: "+i),t=t.slice(0,i)),g+=s,v=0,x=t.length;v=0&&(E=n[b])==null;b-=d);a?(S=h==null?E.x:Math.round(E.bounds.x1+h*E.bounds.width()),k=g):(S=g,k=h==null?E.y:Math.round(E.bounds.y1+h*E.bounds.height())),_.union(A.bounds.translate(S-(A.x||0),k-(A.y||0))),A.x=S,A.y=k,e.dirty(A),m=o(m,_[l])}return m}function T5(e,t,n,r,i,s){if(t){e.dirty(t);var o=n,a=n;r?o=Math.round(i.x1+s*i.width()):a=Math.round(i.y1+s*i.height()),t.bounds.translate(o-(t.x||0),a-(t.y||0)),t.mark.bounds.clear().union(t.bounds),t.x=o,t.y=a,e.dirty(t)}}function qee(e,t){const n=e[t]||{};return(r,i)=>n[r]!=null?n[r]:e[r]!=null?e[r]:i}function Wee(e,t){let n=-1/0;return e.forEach(r=>{r.offset!=null&&(n=Math.max(n,r.offset))}),n>-1/0?n:t}function Hee(e,t,n,r,i,s,o){const a=qee(n,t),u=Wee(e,a("offset",0)),l=a("anchor",fk),c=l===br?1:l===U_?.5:0,f={align:q_,bounds:a("bounds",mk),columns:a("direction")==="vertical"?1:e.length,padding:a("margin",8),center:a("center"),nodirty:!0};switch(t){case ds:f.anchor={x:Math.floor(r.x1)-u,column:br,y:c*(o||r.height()+2*r.y1),row:l};break;case ms:f.anchor={x:Math.ceil(r.x2)+u,y:c*(o||r.height()+2*r.y1),row:l};break;case Xf:f.anchor={y:Math.floor(i.y1)-u,row:br,x:c*(s||i.width()+2*i.x1),column:l};break;case bu:f.anchor={y:Math.ceil(i.y2)+u,x:c*(s||i.width()+2*i.x1),column:l};break;case bee:f.anchor={x:u,y:u};break;case xee:f.anchor={x:s-u,y:u,column:br};break;case _ee:f.anchor={x:u,y:o-u,row:br};break;case wee:f.anchor={x:s-u,y:o-u,column:br,row:br};break}return f}function Gee(e,t){var n=t.items[0],r=n.datum,i=n.orient,s=n.bounds,o=n.x,a=n.y,u,l;return n._bounds?n._bounds.clear().union(s):n._bounds=s.clone(),s.clear(),Vee(e,n,n.items[0].items[0]),s=Yee(n,s),u=2*n.padding,l=2*n.padding,s.empty()||(u=Math.ceil(s.width()+u),l=Math.ceil(s.height()+l)),r.type===$ee&&Xee(n.items[0].items[0].items[0].items),i!==gk&&(n.x=o=0,n.y=a=0),n.width=u,n.height=l,_a(s.set(o,a,o+u,a+l),n),n.mark.bounds.clear().union(s),n}function Yee(e,t){return e.items.forEach(n=>t.union(n.bounds)),t.x1=e.padding,t.y1=e.padding,t}function Vee(e,t,n){var r=t.padding,i=r-n.x,s=r-n.y;if(!t.datum.title)(i||s)&&sh(e,n,i,s);else{var o=t.items[1].items[0],a=o.anchor,u=t.titlePadding||0,l=r-o.x,c=r-o.y;switch(o.orient){case ds:i+=Math.ceil(o.bounds.width())+u;break;case ms:case bu:break;default:s+=o.bounds.height()+u}switch((i||s)&&sh(e,n,i,s),o.orient){case ds:c+=Bc(t,n,o,a,1,1);break;case ms:l+=Bc(t,n,o,br,0,0)+u,c+=Bc(t,n,o,a,1,1);break;case bu:l+=Bc(t,n,o,a,0,0),c+=Bc(t,n,o,br,-1,0,1)+u;break;default:l+=Bc(t,n,o,a,0,0)}(l||c)&&sh(e,o,l,c),(l=Math.round(o.bounds.x1-r))<0&&(sh(e,n,-l,0),sh(e,o,-l,0))}}function Bc(e,t,n,r,i,s,o){const a=e.datum.type!=="symbol",u=n.datum.vgrad,l=a&&(s||!u)&&!o?t.items[0]:t,c=l.bounds[i?"y2":"x2"]-e.padding,f=u&&s?c:0,d=u&&s?0:c,h=i<=0?0:QS(n);return Math.round(r===fk?f:r===br?d-h:.5*(c-h))}function sh(e,t,n,r){t.x+=n,t.y+=r,t.bounds.translate(n,r),t.mark.bounds.translate(n,r),e.dirty(t)}function Xee(e){const t=e.reduce((n,r)=>(n[r.column]=Math.max(r.bounds.x2-r.x,n[r.column]||0),n),{});e.forEach(n=>{n.width=t[n.column],n.height=n.bounds.y2-n.y})}function Kee(e,t,n,r,i){var s=t.items[0],o=s.frame,a=s.orient,u=s.anchor,l=s.offset,c=s.padding,f=s.items[0].items[0],d=s.items[1]&&s.items[1].items[0],h=a===ds||a===ms?r:n,p=0,g=0,m=0,y=0,v=0,b;if(o!==dv?a===ds?(p=i.y2,h=i.y1):a===ms?(p=i.y1,h=i.y2):(p=i.x1,h=i.x2):a===ds&&(p=r,h=0),b=u===fk?p:u===br?h:(p+h)/2,d&&d.text){switch(a){case Xf:case bu:v=f.bounds.height()+c;break;case ds:y=f.bounds.width()+c;break;case ms:y=-f.bounds.width()-c;break}nr.clear().union(d.bounds),nr.translate(y-(d.x||0),v-(d.y||0)),nf(d,"x",y)|nf(d,"y",v)&&(e.dirty(d),d.bounds.clear().union(nr),d.mark.bounds.clear().union(nr),e.dirty(d)),nr.clear().union(d.bounds)}else nr.clear();switch(nr.union(f.bounds),a){case Xf:g=b,m=i.y1-nr.height()-l;break;case ds:g=i.x1-nr.width()-l,m=b;break;case ms:g=i.x2+nr.width()+l,m=b;break;case bu:g=b,m=i.y2+l;break;default:g=s.x,m=s.y}return nf(s,"x",g)|nf(s,"y",m)&&(nr.translate(g,m),e.dirty(s),s.bounds.clear().union(nr),t.bounds.clear().union(nr),e.dirty(s)),s.bounds}function h9(e){G.call(this,null,e)}he(h9,G,{transform(e,t){const n=t.dataflow;return e.mark.items.forEach(r=>{e.layout&&zee(n,r,e.layout),Jee(n,r,e)}),Zee(e.mark.group)?t.reflow():t}});function Zee(e){return e&&e.mark.role!=="legend-entry"}function Jee(e,t,n){var r=t.items,i=Math.max(0,t.width||0),s=Math.max(0,t.height||0),o=new dn().set(0,0,i,s),a=o.clone(),u=o.clone(),l=[],c,f,d,h,p,g;for(p=0,g=r.length;p{d=y.orient||ms,d!==gk&&(m[d]||(m[d]=[])).push(y)});for(const y in m){const v=m[y];d9(e,v,Hee(v,y,n.legends,a,u,i,s))}l.forEach(y=>{const v=y.bounds;if(v.equals(y._bounds)||(y.bounds=y._bounds,e.dirty(y),y.bounds=v,e.dirty(y)),n.autosize&&(n.autosize.type===i9||n.autosize.type===s9||n.autosize.type===o9))switch(y.orient){case ds:case ms:o.add(v.x1,0).add(v.x2,0);break;case Xf:case bu:o.add(0,v.y1).add(0,v.y2)}else o.union(v)})}o.union(a).union(u),c&&o.union(Kee(e,c,i,s,o)),t.clip&&o.set(0,0,t.width||0,t.height||0),Qee(e,t,o,n)}function Qee(e,t,n,r){const i=r.autosize||{},s=i.type;if(e._autosize<1||!s)return;let o=e._width,a=e._height,u=Math.max(0,t.width||0),l=Math.max(0,Math.ceil(-n.x1)),c=Math.max(0,t.height||0),f=Math.max(0,Math.ceil(-n.y1));const d=Math.max(0,Math.ceil(n.x2-u)),h=Math.max(0,Math.ceil(n.y2-c));if(i.contains===Cee){const p=e.padding();o-=p.left+p.right,a-=p.top+p.bottom}s===gk?(l=0,f=0,u=o,c=a):s===i9?(u=Math.max(0,o-l-d),c=Math.max(0,a-f-h)):s===s9?(u=Math.max(0,o-l-d),a=c+f+h):s===o9?(o=u+l+d,c=Math.max(0,a-f-h)):s===Fee&&(o=u+l+d,a=c+f+h),e._resizeView(o,a,u,c,[l,f],i.resize)}const ete=Object.freeze(Object.defineProperty({__proto__:null,bound:a9,identifier:yk,mark:u9,overlap:l9,render:f9,viewlayout:h9},Symbol.toStringTag,{value:"Module"}));function p9(e){G.call(this,null,e)}he(p9,G,{transform(e,t){if(this.value&&!e.modified())return t.StopPropagation;var n=t.dataflow.locale(),r=t.fork(t.NO_SOURCE|t.NO_FIELDS),i=this.value,s=e.scale,o=e.count==null?e.values?e.values.length:10:e.count,a=OS(s,o,e.minstep),u=e.format||jO(n,s,a,e.formatSpecifier,e.formatType,!!e.values),l=e.values?zO(s,e.values,a):LS(s,a);return i&&(r.rem=i),i=l.map((c,f)=>gt({index:f/(l.length-1||1),value:c,label:u(c)})),e.extra&&i.length&&i.push(gt({index:-1,extra:{value:i[0].value},label:""})),r.source=i,r.add=i,this.value=i,r}});function g9(e){G.call(this,null,e)}function tte(){return gt({})}function nte(e){const t=Ed().test(n=>n.exit);return t.lookup=n=>t.get(e(n)),t}he(g9,G,{transform(e,t){var n=t.dataflow,r=t.fork(t.NO_SOURCE|t.NO_FIELDS),i=e.item||tte,s=e.key||Te,o=this.value;return ee(r.encode)&&(r.encode=null),o&&(e.modified("key")||t.modified(s))&&X("DataJoin does not support modified key function or fields."),o||(t=t.addAll(),this.value=o=nte(s)),t.visit(t.ADD,a=>{const u=s(a);let l=o.get(u);l?l.exit?(o.empty--,r.add.push(l)):r.mod.push(l):(l=i(a),o.set(u,l),r.add.push(l)),l.datum=a,l.exit=!1}),t.visit(t.MOD,a=>{const u=s(a),l=o.get(u);l&&(l.datum=a,r.mod.push(l))}),t.visit(t.REM,a=>{const u=s(a),l=o.get(u);a===l.datum&&!l.exit&&(r.rem.push(l),l.exit=!0,++o.empty)}),t.changed(t.ADD_MOD)&&r.modifies("datum"),(t.clean()||e.clean&&o.empty>n.cleanThreshold)&&n.runAfter(o.clean),r}});function m9(e){G.call(this,null,e)}he(m9,G,{transform(e,t){var n=t.fork(t.ADD_REM),r=e.mod||!1,i=e.encoders,s=t.encode;if(ee(s))if(n.changed()||s.every(f=>i[f]))s=s[0],n.encode=null;else return t.StopPropagation;var o=s==="enter",a=i.update||Ta,u=i.enter||Ta,l=i.exit||Ta,c=(s&&!o?i[s]:a)||Ta;if(t.changed(t.ADD)&&(t.visit(t.ADD,f=>{u(f,e),a(f,e)}),n.modifies(u.output),n.modifies(a.output),c!==Ta&&c!==a&&(t.visit(t.ADD,f=>{c(f,e)}),n.modifies(c.output))),t.changed(t.REM)&&l!==Ta&&(t.visit(t.REM,f=>{l(f,e)}),n.modifies(l.output)),o||c!==Ta){const f=t.MOD|(e.modified()?t.REFLOW:0);o?(t.visit(f,d=>{const h=u(d,e)||r;(c(d,e)||h)&&n.mod.push(d)}),n.mod.length&&n.modifies(u.output)):t.visit(f,d=>{(c(d,e)||r)&&n.mod.push(d)}),n.mod.length&&n.modifies(c.output)}return n.changed()?n:t.StopPropagation}});function y9(e){G.call(this,[],e)}he(y9,G,{transform(e,t){if(this.value!=null&&!e.modified())return t.StopPropagation;var n=t.dataflow.locale(),r=t.fork(t.NO_SOURCE|t.NO_FIELDS),i=this.value,s=e.type||tm,o=e.scale,a=+e.limit,u=OS(o,e.count==null?5:e.count,e.minstep),l=!!e.values||s===tm,c=e.format||HO(n,o,u,s,e.formatSpecifier,e.formatType,l),f=e.values||WO(o,u),d,h,p,g,m;return i&&(r.rem=i),s===tm?(a&&f.length>a?(t.dataflow.warn("Symbol legend count exceeds limit, filtering items."),i=f.slice(0,a-1),m=!0):i=f,He(p=e.size)?(!e.values&&o(i[0])===0&&(i=i.slice(1)),g=i.reduce((y,v)=>Math.max(y,p(v,e)),0)):p=pr(g=p||8),i=i.map((y,v)=>gt({index:v,label:c(y,v,i),value:y,offset:g,size:p(y,e)})),m&&(m=f[i.length],i.push(gt({index:i.length,label:`…${f.length-i.length} entries`,value:m,offset:g,size:p(m,e)})))):s===FZ?(d=o.domain(),h=IO(o,d[0],st(d)),f.length<3&&!e.values&&d[0]!==st(d)&&(f=[d[0],st(d)]),i=f.map((y,v)=>gt({index:v,label:c(y,v,f),value:y,perc:h(y)}))):(p=f.length-1,h=zZ(o),i=f.map((y,v)=>gt({index:v,label:c(y,v,f),value:y,perc:v?h(y):0,perc2:v===p?1:h(f[v+1])}))),r.source=i,r.add=i,this.value=i,r}});const rte=e=>e.source.x,ite=e=>e.source.y,ste=e=>e.target.x,ote=e=>e.target.y;function vk(e){G.call(this,{},e)}vk.Definition={type:"LinkPath",metadata:{modifies:!0},params:[{name:"sourceX",type:"field",default:"source.x"},{name:"sourceY",type:"field",default:"source.y"},{name:"targetX",type:"field",default:"target.x"},{name:"targetY",type:"field",default:"target.y"},{name:"orient",type:"enum",default:"vertical",values:["horizontal","vertical","radial"]},{name:"shape",type:"enum",default:"line",values:["line","arc","curve","diagonal","orthogonal"]},{name:"require",type:"signal"},{name:"as",type:"string",default:"path"}]};he(vk,G,{transform(e,t){var n=e.sourceX||rte,r=e.sourceY||ite,i=e.targetX||ste,s=e.targetY||ote,o=e.as||"path",a=e.orient||"vertical",u=e.shape||"line",l=N5.get(u+"-"+a)||N5.get(u);return l||X("LinkPath unsupported type: "+e.shape+(e.orient?"-"+e.orient:"")),t.visit(t.SOURCE,c=>{c[o]=l(n(c),r(c),i(c),s(c))}),t.reflow(e.modified()).modifies(o)}});const v9=(e,t,n,r)=>"M"+e+","+t+"L"+n+","+r,ate=(e,t,n,r)=>v9(t*Math.cos(e),t*Math.sin(e),r*Math.cos(n),r*Math.sin(n)),b9=(e,t,n,r)=>{var i=n-e,s=r-t,o=Math.hypot(i,s)/2,a=180*Math.atan2(s,i)/Math.PI;return"M"+e+","+t+"A"+o+","+o+" "+a+" 0 1 "+n+","+r},ute=(e,t,n,r)=>b9(t*Math.cos(e),t*Math.sin(e),r*Math.cos(n),r*Math.sin(n)),x9=(e,t,n,r)=>{const i=n-e,s=r-t,o=.2*(i+s),a=.2*(s-i);return"M"+e+","+t+"C"+(e+o)+","+(t+a)+" "+(n+a)+","+(r-o)+" "+n+","+r},lte=(e,t,n,r)=>x9(t*Math.cos(e),t*Math.sin(e),r*Math.cos(n),r*Math.sin(n)),cte=(e,t,n,r)=>"M"+e+","+t+"V"+r+"H"+n,fte=(e,t,n,r)=>"M"+e+","+t+"H"+n+"V"+r,dte=(e,t,n,r)=>{const i=Math.cos(e),s=Math.sin(e),o=Math.cos(n),a=Math.sin(n),u=Math.abs(n-e)>Math.PI?n<=e:n>e;return"M"+t*i+","+t*s+"A"+t+","+t+" 0 0,"+(u?1:0)+" "+t*o+","+t*a+"L"+r*o+","+r*a},hte=(e,t,n,r)=>{const i=(e+n)/2;return"M"+e+","+t+"C"+i+","+t+" "+i+","+r+" "+n+","+r},pte=(e,t,n,r)=>{const i=(t+r)/2;return"M"+e+","+t+"C"+e+","+i+" "+n+","+i+" "+n+","+r},gte=(e,t,n,r)=>{const i=Math.cos(e),s=Math.sin(e),o=Math.cos(n),a=Math.sin(n),u=(t+r)/2;return"M"+t*i+","+t*s+"C"+u*i+","+u*s+" "+u*o+","+u*a+" "+r*o+","+r*a},N5=Ed({line:v9,"line-radial":ate,arc:b9,"arc-radial":ute,curve:x9,"curve-radial":lte,"orthogonal-horizontal":cte,"orthogonal-vertical":fte,"orthogonal-radial":dte,"diagonal-horizontal":hte,"diagonal-vertical":pte,"diagonal-radial":gte});function bk(e){G.call(this,null,e)}bk.Definition={type:"Pie",metadata:{modifies:!0},params:[{name:"field",type:"field"},{name:"startAngle",type:"number",default:0},{name:"endAngle",type:"number",default:6.283185307179586},{name:"sort",type:"boolean",default:!1},{name:"as",type:"string",array:!0,length:2,default:["startAngle","endAngle"]}]};he(bk,G,{transform(e,t){var n=e.as||["startAngle","endAngle"],r=n[0],i=n[1],s=e.field||bd,o=e.startAngle||0,a=e.endAngle!=null?e.endAngle:2*Math.PI,u=t.source,l=u.map(s),c=l.length,f=o,d=(a-o)/OR(l),h=ci(c),p,g,m;for(e.sort&&h.sort((y,v)=>l[y]-l[v]),p=0;p-1)return r;var i=t.domain,s=e.type,o=t.zero||t.zero===void 0&&yte(e),a,u;if(!i)return 0;if((o||t.domainMin!=null||t.domainMax!=null||t.domainMid!=null)&&(a=(i=i.slice()).length-1||1,o&&(i[0]>0&&(i[0]=0),i[a]<0&&(i[a]=0)),t.domainMin!=null&&(i[0]=t.domainMin),t.domainMax!=null&&(i[a]=t.domainMax),t.domainMid!=null)){u=t.domainMid;const l=u>i[a]?a+1:ui+(s<0?-1:s>0?1:0),0));r!==t.length&&n.warn("Log scale domain includes zero: "+ce(t))}return t}function Ate(e,t,n){let r=t.bins;if(r&&!ee(r)){const i=e.domain(),s=i[0],o=st(i),a=r.step;let u=r.start==null?s:r.start,l=r.stop==null?o:r.stop;a||X("Scale bins parameter missing step property."),uo&&(l=a*Math.floor(o/a)),r=ci(u,l+a/2,a)}return r?e.bins=r:e.bins&&delete e.bins,e.type===FS&&(r?!t.domain&&!t.domainRaw&&(e.domain(r),n=r.length):e.bins=e.domain()),n}function Ste(e,t,n){var r=e.type,i=t.round||!1,s=t.range;if(t.rangeStep!=null)s=kte(r,t,n);else if(t.scheme&&(s=Cte(r,t,n),He(s))){if(e.interpolator)return e.interpolator(s);X(`Scale type ${r} does not support interpolating color schemes.`)}if(s&&TO(r))return e.interpolator(ev(W_(s,t.reverse),t.interpolate,t.interpolateGamma));s&&t.interpolate&&e.interpolate?e.interpolate(TS(t.interpolate,t.interpolateGamma)):He(e.round)?e.round(i):He(e.rangeRound)&&e.interpolate(i?lg:Nu),s&&e.range(W_(s,t.reverse))}function kte(e,t,n){e!==kO&&e!==F_&&X("Only band and point scales support rangeStep.");var r=(t.paddingOuter!=null?t.paddingOuter:t.padding)||0,i=e===F_?1:(t.paddingInner!=null?t.paddingInner:t.padding)||0;return[0,t.rangeStep*CS(n,i,r)]}function Cte(e,t,n){var r=t.schemeExtent,i,s;return ee(t.scheme)?s=ev(t.scheme,t.interpolate,t.interpolateGamma):(i=t.scheme.toLowerCase(),s=NS(i),s||X(`Unrecognized scheme name: ${t.scheme}`)),n=e===Qy?n+1:e===FS?n-1:e===Wf||e===Jy?+t.schemeCount||mte:n,TO(e)?O5(s,r,t.reverse):He(s)?LO(O5(s,r),n):e===$S?s:s.slice(0,n)}function O5(e,t,n){return He(e)&&(t||n)?OO(e,W_(t||[0,1],n)):e}function W_(e,t){return t?e.slice().reverse():e}function A9(e){G.call(this,null,e)}he(A9,G,{transform(e,t){const n=e.modified("sort")||t.changed(t.ADD)||t.modified(e.sort.fields)||t.modified("datum");return n&&t.source.sort(yc(e.sort)),this.modified(n),t}});const L5="zero",S9="center",k9="normalize",C9=["y0","y1"];function xk(e){G.call(this,null,e)}xk.Definition={type:"Stack",metadata:{modifies:!0},params:[{name:"field",type:"field"},{name:"groupby",type:"field",array:!0},{name:"sort",type:"compare"},{name:"offset",type:"enum",default:L5,values:[L5,S9,k9]},{name:"as",type:"string",array:!0,length:2,default:C9}]};he(xk,G,{transform(e,t){var n=e.as||C9,r=n[0],i=n[1],s=yc(e.sort),o=e.field||bd,a=e.offset===S9?$te:e.offset===k9?Fte:Dte,u,l,c,f;for(u=Mte(t.source,e.groupby,s,o),l=0,c=u.length,f=u.max;lg(c),o,a,u,l,c,f,d,h,p;if(t==null)i.push(e.slice());else for(o={},a=0,u=e.length;ap&&(p=h),n&&d.sort(n)}return i.max=p,i}const Rte=Object.freeze(Object.defineProperty({__proto__:null,axisticks:p9,datajoin:g9,encode:m9,legendentries:y9,linkpath:vk,pie:bk,scale:w9,sortitems:A9,stack:xk},Symbol.toStringTag,{value:"Module"}));var Oe=1e-6,l1=1e-12,Je=Math.PI,Jt=Je/2,c1=Je/4,$r=Je*2,on=180/Je,Xe=Je/180,it=Math.abs,Td=Math.atan,Hi=Math.atan2,Ie=Math.cos,g0=Math.ceil,$9=Math.exp,H_=Math.hypot,f1=Math.log,b2=Math.pow,Ne=Math.sin,Ti=Math.sign||function(e){return e>0?1:e<0?-1:0},Fr=Math.sqrt,_k=Math.tan;function F9(e){return e>1?0:e<-1?Je:Math.acos(e)}function Xr(e){return e>1?Jt:e<-1?-Jt:Math.asin(e)}function qn(){}function d1(e,t){e&&P5.hasOwnProperty(e.type)&&P5[e.type](e,t)}var I5={Feature:function(e,t){d1(e.geometry,t)},FeatureCollection:function(e,t){for(var n=e.features,r=-1,i=n.length;++r=0?1:-1,i=r*n,s=Ie(t),o=Ne(t),a=X_*o,u=V_*s+a*Ie(i),l=a*r*Ne(i);h1.add(Hi(l,u)),Y_=e,V_=s,X_=o}function Lte(e){return p1=new kr,Jo(e,xo),p1*2}function g1(e){return[Hi(e[1],e[0]),Xr(e[2])]}function Xl(e){var t=e[0],n=e[1],r=Ie(n);return[r*Ie(t),r*Ne(t),Ne(n)]}function m0(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]}function Kf(e,t){return[e[1]*t[2]-e[2]*t[1],e[2]*t[0]-e[0]*t[2],e[0]*t[1]-e[1]*t[0]]}function x2(e,t){e[0]+=t[0],e[1]+=t[1],e[2]+=t[2]}function y0(e,t){return[e[0]*t,e[1]*t,e[2]*t]}function m1(e){var t=Fr(e[0]*e[0]+e[1]*e[1]+e[2]*e[2]);e[0]/=t,e[1]/=t,e[2]/=t}var Ht,zr,Kt,ui,sl,T9,N9,df,Jh,Pa,ya,Yo={point:K_,lineStart:z5,lineEnd:j5,polygonStart:function(){Yo.point=L9,Yo.lineStart=Ite,Yo.lineEnd=Pte,Jh=new kr,xo.polygonStart()},polygonEnd:function(){xo.polygonEnd(),Yo.point=K_,Yo.lineStart=z5,Yo.lineEnd=j5,h1<0?(Ht=-(Kt=180),zr=-(ui=90)):Jh>Oe?ui=90:Jh<-Oe&&(zr=-90),ya[0]=Ht,ya[1]=Kt},sphere:function(){Ht=-(Kt=180),zr=-(ui=90)}};function K_(e,t){Pa.push(ya=[Ht=e,Kt=e]),tui&&(ui=t)}function O9(e,t){var n=Xl([e*Xe,t*Xe]);if(df){var r=Kf(df,n),i=[r[1],-r[0],0],s=Kf(i,r);m1(s),s=g1(s);var o=e-sl,a=o>0?1:-1,u=s[0]*on*a,l,c=it(o)>180;c^(a*slui&&(ui=l)):(u=(u+360)%360-180,c^(a*slui&&(ui=t))),c?eai(Ht,Kt)&&(Kt=e):ai(e,Kt)>ai(Ht,Kt)&&(Ht=e):Kt>=Ht?(eKt&&(Kt=e)):e>sl?ai(Ht,e)>ai(Ht,Kt)&&(Kt=e):ai(e,Kt)>ai(Ht,Kt)&&(Ht=e)}else Pa.push(ya=[Ht=e,Kt=e]);tui&&(ui=t),df=n,sl=e}function z5(){Yo.point=O9}function j5(){ya[0]=Ht,ya[1]=Kt,Yo.point=K_,df=null}function L9(e,t){if(df){var n=e-sl;Jh.add(it(n)>180?n+(n>0?360:-360):n)}else T9=e,N9=t;xo.point(e,t),O9(e,t)}function Ite(){xo.lineStart()}function Pte(){L9(T9,N9),xo.lineEnd(),it(Jh)>Oe&&(Ht=-(Kt=180)),ya[0]=Ht,ya[1]=Kt,df=null}function ai(e,t){return(t-=e)<0?t+360:t}function Bte(e,t){return e[0]-t[0]}function U5(e,t){return e[0]<=e[1]?e[0]<=t&&t<=e[1]:tai(r[0],r[1])&&(r[1]=i[1]),ai(i[0],r[1])>ai(r[0],r[1])&&(r[0]=i[0])):s.push(r=i);for(o=-1/0,n=s.length-1,t=0,r=s[n];t<=n;r=i,++t)i=s[t],(a=ai(r[1],i[0]))>o&&(o=a,Ht=i[0],Kt=r[1])}return Pa=ya=null,Ht===1/0||zr===1/0?[[NaN,NaN],[NaN,NaN]]:[[Ht,zr],[Kt,ui]]}var Fh,y1,v1,b1,x1,_1,w1,E1,Z_,J_,Q_,I9,P9,xr,_r,wr,ys={sphere:qn,point:wk,lineStart:q5,lineEnd:W5,polygonStart:function(){ys.lineStart=qte,ys.lineEnd=Wte},polygonEnd:function(){ys.lineStart=q5,ys.lineEnd=W5}};function wk(e,t){e*=Xe,t*=Xe;var n=Ie(t);Ag(n*Ie(e),n*Ne(e),Ne(t))}function Ag(e,t,n){++Fh,v1+=(e-v1)/Fh,b1+=(t-b1)/Fh,x1+=(n-x1)/Fh}function q5(){ys.point=jte}function jte(e,t){e*=Xe,t*=Xe;var n=Ie(t);xr=n*Ie(e),_r=n*Ne(e),wr=Ne(t),ys.point=Ute,Ag(xr,_r,wr)}function Ute(e,t){e*=Xe,t*=Xe;var n=Ie(t),r=n*Ie(e),i=n*Ne(e),s=Ne(t),o=Hi(Fr((o=_r*s-wr*i)*o+(o=wr*r-xr*s)*o+(o=xr*i-_r*r)*o),xr*r+_r*i+wr*s);y1+=o,_1+=o*(xr+(xr=r)),w1+=o*(_r+(_r=i)),E1+=o*(wr+(wr=s)),Ag(xr,_r,wr)}function W5(){ys.point=wk}function qte(){ys.point=Hte}function Wte(){B9(I9,P9),ys.point=wk}function Hte(e,t){I9=e,P9=t,e*=Xe,t*=Xe,ys.point=B9;var n=Ie(t);xr=n*Ie(e),_r=n*Ne(e),wr=Ne(t),Ag(xr,_r,wr)}function B9(e,t){e*=Xe,t*=Xe;var n=Ie(t),r=n*Ie(e),i=n*Ne(e),s=Ne(t),o=_r*s-wr*i,a=wr*r-xr*s,u=xr*i-_r*r,l=H_(o,a,u),c=Xr(l),f=l&&-c/l;Z_.add(f*o),J_.add(f*a),Q_.add(f*u),y1+=c,_1+=c*(xr+(xr=r)),w1+=c*(_r+(_r=i)),E1+=c*(wr+(wr=s)),Ag(xr,_r,wr)}function Gte(e){Fh=y1=v1=b1=x1=_1=w1=E1=0,Z_=new kr,J_=new kr,Q_=new kr,Jo(e,ys);var t=+Z_,n=+J_,r=+Q_,i=H_(t,n,r);return iJe&&(e-=Math.round(e/$r)*$r),[e,t]}tw.invert=tw;function z9(e,t,n){return(e%=$r)?t||n?ew(G5(e),Y5(t,n)):G5(e):t||n?Y5(t,n):tw}function H5(e){return function(t,n){return t+=e,it(t)>Je&&(t-=Math.round(t/$r)*$r),[t,n]}}function G5(e){var t=H5(e);return t.invert=H5(-e),t}function Y5(e,t){var n=Ie(e),r=Ne(e),i=Ie(t),s=Ne(t);function o(a,u){var l=Ie(u),c=Ie(a)*l,f=Ne(a)*l,d=Ne(u),h=d*n+c*r;return[Hi(f*i-h*s,c*n-d*r),Xr(h*i+f*s)]}return o.invert=function(a,u){var l=Ie(u),c=Ie(a)*l,f=Ne(a)*l,d=Ne(u),h=d*i-f*s;return[Hi(f*i+d*s,c*n+h*r),Xr(h*n-c*r)]},o}function Yte(e){e=z9(e[0]*Xe,e[1]*Xe,e.length>2?e[2]*Xe:0);function t(n){return n=e(n[0]*Xe,n[1]*Xe),n[0]*=on,n[1]*=on,n}return t.invert=function(n){return n=e.invert(n[0]*Xe,n[1]*Xe),n[0]*=on,n[1]*=on,n},t}function Vte(e,t,n,r,i,s){if(n){var o=Ie(t),a=Ne(t),u=r*n;i==null?(i=t+r*$r,s=t-u/2):(i=V5(o,i),s=V5(o,s),(r>0?is)&&(i+=r*$r));for(var l,c=i;r>0?c>s:c1&&e.push(e.pop().concat(e.shift()))},result:function(){var n=e;return e=[],t=null,n}}}function cm(e,t){return it(e[0]-t[0])=0;--a)i.point((f=c[a])[0],f[1]);else r(d.x,d.p.x,-1,i);d=d.p}d=d.o,c=d.z,h=!h}while(!d.v);i.lineEnd()}}}function X5(e){if(t=e.length){for(var t,n=0,r=e[0],i;++n=0?1:-1,$=k*S,D=$>Je,M=m*A;if(u.add(Hi(M*k*Ne($),y*E+M*Ie($))),o+=D?S+k*$r:S,D^p>=n^x>=n){var R=Kf(Xl(h),Xl(b));m1(R);var F=Kf(s,R);m1(F);var C=(D^S>=0?-1:1)*Xr(F[2]);(r>C||r===C&&(R[0]||R[1]))&&(a+=D^S>=0?1:-1)}}return(o<-Oe||o0){for(u||(i.polygonStart(),u=!0),i.lineStart(),A=0;A1&&x&2&&_.push(_.pop().concat(_.shift())),c.push(_.filter(Kte))}}return d}}function Kte(e){return e.length>1}function Zte(e,t){return((e=e.x)[0]<0?e[1]-Jt-Oe:Jt-e[1])-((t=t.x)[0]<0?t[1]-Jt-Oe:Jt-t[1])}const K5=q9(function(){return!0},Jte,ene,[-Je,-Jt]);function Jte(e){var t=NaN,n=NaN,r=NaN,i;return{lineStart:function(){e.lineStart(),i=1},point:function(s,o){var a=s>0?Je:-Je,u=it(s-t);it(u-Je)0?Jt:-Jt),e.point(r,n),e.lineEnd(),e.lineStart(),e.point(a,n),e.point(s,n),i=0):r!==a&&u>=Je&&(it(t-r)Oe?Td((Ne(t)*(s=Ie(r))*Ne(n)-Ne(r)*(i=Ie(t))*Ne(e))/(i*s*o)):(t+r)/2}function ene(e,t,n,r){var i;if(e==null)i=n*Jt,r.point(-Je,i),r.point(0,i),r.point(Je,i),r.point(Je,0),r.point(Je,-i),r.point(0,-i),r.point(-Je,-i),r.point(-Je,0),r.point(-Je,i);else if(it(e[0]-t[0])>Oe){var s=e[0]0,i=it(t)>Oe;function s(c,f,d,h){Vte(h,e,n,d,c,f)}function o(c,f){return Ie(c)*Ie(f)>t}function a(c){var f,d,h,p,g;return{lineStart:function(){p=h=!1,g=1},point:function(m,y){var v=[m,y],b,x=o(m,y),_=r?x?0:l(m,y):x?l(m+(m<0?Je:-Je),y):0;if(!f&&(p=h=x)&&c.lineStart(),x!==h&&(b=u(f,v),(!b||cm(f,b)||cm(v,b))&&(v[2]=1)),x!==h)g=0,x?(c.lineStart(),b=u(v,f),c.point(b[0],b[1])):(b=u(f,v),c.point(b[0],b[1],2),c.lineEnd()),f=b;else if(i&&f&&r^x){var A;!(_&d)&&(A=u(v,f,!0))&&(g=0,r?(c.lineStart(),c.point(A[0][0],A[0][1]),c.point(A[1][0],A[1][1]),c.lineEnd()):(c.point(A[1][0],A[1][1]),c.lineEnd(),c.lineStart(),c.point(A[0][0],A[0][1],3)))}x&&(!f||!cm(f,v))&&c.point(v[0],v[1]),f=v,h=x,d=_},lineEnd:function(){h&&c.lineEnd(),f=null},clean:function(){return g|(p&&h)<<1}}}function u(c,f,d){var h=Xl(c),p=Xl(f),g=[1,0,0],m=Kf(h,p),y=m0(m,m),v=m[0],b=y-v*v;if(!b)return!d&&c;var x=t*y/b,_=-t*v/b,A=Kf(g,m),E=y0(g,x),S=y0(m,_);x2(E,S);var k=A,$=m0(E,k),D=m0(k,k),M=$*$-D*(m0(E,E)-1);if(!(M<0)){var R=Fr(M),F=y0(k,(-$-R)/D);if(x2(F,E),F=g1(F),!d)return F;var C=c[0],T=f[0],O=c[1],N=f[1],L;T0^F[1]<(it(F[0]-C)Je^(C<=F[0]&&F[0]<=T)){var de=y0(k,(-$+R)/D);return x2(de,E),[F,g1(de)]}}}function l(c,f){var d=r?e:Je-e,h=0;return c<-d?h|=1:c>d&&(h|=2),f<-d?h|=4:f>d&&(h|=8),h}return q9(o,a,s,r?[0,-e]:[-Je,e-Je])}function nne(e,t,n,r,i,s){var o=e[0],a=e[1],u=t[0],l=t[1],c=0,f=1,d=u-o,h=l-a,p;if(p=n-o,!(!d&&p>0)){if(p/=d,d<0){if(p0){if(p>f)return;p>c&&(c=p)}if(p=i-o,!(!d&&p<0)){if(p/=d,d<0){if(p>f)return;p>c&&(c=p)}else if(d>0){if(p0)){if(p/=h,h<0){if(p0){if(p>f)return;p>c&&(c=p)}if(p=s-a,!(!h&&p<0)){if(p/=h,h<0){if(p>f)return;p>c&&(c=p)}else if(h>0){if(p0&&(e[0]=o+c*d,e[1]=a+c*h),f<1&&(t[0]=o+f*d,t[1]=a+f*h),!0}}}}}var Dh=1e9,b0=-Dh;function W9(e,t,n,r){function i(l,c){return e<=l&&l<=n&&t<=c&&c<=r}function s(l,c,f,d){var h=0,p=0;if(l==null||(h=o(l,f))!==(p=o(c,f))||u(l,c)<0^f>0)do d.point(h===0||h===3?e:n,h>1?r:t);while((h=(h+f+4)%4)!==p);else d.point(c[0],c[1])}function o(l,c){return it(l[0]-e)0?0:3:it(l[0]-n)0?2:1:it(l[1]-t)0?1:0:c>0?3:2}function a(l,c){return u(l.x,c.x)}function u(l,c){var f=o(l,1),d=o(c,1);return f!==d?f-d:f===0?c[1]-l[1]:f===1?l[0]-c[0]:f===2?l[1]-c[1]:c[0]-l[0]}return function(l){var c=l,f=j9(),d,h,p,g,m,y,v,b,x,_,A,E={point:S,lineStart:M,lineEnd:R,polygonStart:$,polygonEnd:D};function S(C,T){i(C,T)&&c.point(C,T)}function k(){for(var C=0,T=0,O=h.length;Tr&&(we-Q)*(r-de)>(ne-de)*(e-Q)&&++C:ne<=r&&(we-Q)*(r-de)<(ne-de)*(e-Q)&&--C;return C}function $(){c=f,d=[],h=[],A=!0}function D(){var C=k(),T=A&&C,O=(d=NR(d)).length;(T||O)&&(l.polygonStart(),T&&(l.lineStart(),s(null,null,1,l),l.lineEnd()),O&&U9(d,a,C,s,l),l.polygonEnd()),c=l,d=h=p=null}function M(){E.point=F,h&&h.push(p=[]),_=!0,x=!1,v=b=NaN}function R(){d&&(F(g,m),y&&x&&f.rejoin(),d.push(f.result())),E.point=S,x&&c.lineEnd()}function F(C,T){var O=i(C,T);if(h&&p.push([C,T]),_)g=C,m=T,y=O,_=!1,O&&(c.lineStart(),c.point(C,T));else if(O&&x)c.point(C,T);else{var N=[v=Math.max(b0,Math.min(Dh,v)),b=Math.max(b0,Math.min(Dh,b))],L=[C=Math.max(b0,Math.min(Dh,C)),T=Math.max(b0,Math.min(Dh,T))];nne(N,L,e,t,n,r)?(x||(c.lineStart(),c.point(N[0],N[1])),c.point(L[0],L[1]),O||c.lineEnd(),A=!1):O&&(c.lineStart(),c.point(C,T),A=!1)}v=C,b=T,x=O}return E}}function Z5(e,t,n){var r=ci(e,t-Oe,n).concat(t);return function(i){return r.map(function(s){return[i,s]})}}function J5(e,t,n){var r=ci(e,t-Oe,n).concat(t);return function(i){return r.map(function(s){return[s,i]})}}function rne(){var e,t,n,r,i,s,o,a,u=10,l=u,c=90,f=360,d,h,p,g,m=2.5;function y(){return{type:"MultiLineString",coordinates:v()}}function v(){return ci(g0(r/c)*c,n,c).map(p).concat(ci(g0(a/f)*f,o,f).map(g)).concat(ci(g0(t/u)*u,e,u).filter(function(b){return it(b%c)>Oe}).map(d)).concat(ci(g0(s/l)*l,i,l).filter(function(b){return it(b%f)>Oe}).map(h))}return y.lines=function(){return v().map(function(b){return{type:"LineString",coordinates:b}})},y.outline=function(){return{type:"Polygon",coordinates:[p(r).concat(g(o).slice(1),p(n).reverse().slice(1),g(a).reverse().slice(1))]}},y.extent=function(b){return arguments.length?y.extentMajor(b).extentMinor(b):y.extentMinor()},y.extentMajor=function(b){return arguments.length?(r=+b[0][0],n=+b[1][0],a=+b[0][1],o=+b[1][1],r>n&&(b=r,r=n,n=b),a>o&&(b=a,a=o,o=b),y.precision(m)):[[r,a],[n,o]]},y.extentMinor=function(b){return arguments.length?(t=+b[0][0],e=+b[1][0],s=+b[0][1],i=+b[1][1],t>e&&(b=t,t=e,e=b),s>i&&(b=s,s=i,i=b),y.precision(m)):[[t,s],[e,i]]},y.step=function(b){return arguments.length?y.stepMajor(b).stepMinor(b):y.stepMinor()},y.stepMajor=function(b){return arguments.length?(c=+b[0],f=+b[1],y):[c,f]},y.stepMinor=function(b){return arguments.length?(u=+b[0],l=+b[1],y):[u,l]},y.precision=function(b){return arguments.length?(m=+b,d=Z5(s,i,90),h=J5(t,e,m),p=Z5(a,o,90),g=J5(r,n,m),y):m},y.extentMajor([[-180,-90+Oe],[180,90-Oe]]).extentMinor([[-180,-80-Oe],[180,80+Oe]])}const Ep=e=>e;var w2=new kr,nw=new kr,H9,G9,rw,iw,Qo={point:qn,lineStart:qn,lineEnd:qn,polygonStart:function(){Qo.lineStart=ine,Qo.lineEnd=one},polygonEnd:function(){Qo.lineStart=Qo.lineEnd=Qo.point=qn,w2.add(it(nw)),nw=new kr},result:function(){var e=w2/2;return w2=new kr,e}};function ine(){Qo.point=sne}function sne(e,t){Qo.point=Y9,H9=rw=e,G9=iw=t}function Y9(e,t){nw.add(iw*e-rw*t),rw=e,iw=t}function one(){Y9(H9,G9)}var Zf=1/0,A1=Zf,Ap=-Zf,S1=Ap,k1={point:ane,lineStart:qn,lineEnd:qn,polygonStart:qn,polygonEnd:qn,result:function(){var e=[[Zf,A1],[Ap,S1]];return Ap=S1=-(A1=Zf=1/0),e}};function ane(e,t){eAp&&(Ap=e),tS1&&(S1=t)}var sw=0,ow=0,Mh=0,C1=0,$1=0,rf=0,aw=0,uw=0,Rh=0,V9,X9,no,ro,Mi={point:Kl,lineStart:Q5,lineEnd:eD,polygonStart:function(){Mi.lineStart=cne,Mi.lineEnd=fne},polygonEnd:function(){Mi.point=Kl,Mi.lineStart=Q5,Mi.lineEnd=eD},result:function(){var e=Rh?[aw/Rh,uw/Rh]:rf?[C1/rf,$1/rf]:Mh?[sw/Mh,ow/Mh]:[NaN,NaN];return sw=ow=Mh=C1=$1=rf=aw=uw=Rh=0,e}};function Kl(e,t){sw+=e,ow+=t,++Mh}function Q5(){Mi.point=une}function une(e,t){Mi.point=lne,Kl(no=e,ro=t)}function lne(e,t){var n=e-no,r=t-ro,i=Fr(n*n+r*r);C1+=i*(no+e)/2,$1+=i*(ro+t)/2,rf+=i,Kl(no=e,ro=t)}function eD(){Mi.point=Kl}function cne(){Mi.point=dne}function fne(){K9(V9,X9)}function dne(e,t){Mi.point=K9,Kl(V9=no=e,X9=ro=t)}function K9(e,t){var n=e-no,r=t-ro,i=Fr(n*n+r*r);C1+=i*(no+e)/2,$1+=i*(ro+t)/2,rf+=i,i=ro*e-no*t,aw+=i*(no+e),uw+=i*(ro+t),Rh+=i*3,Kl(no=e,ro=t)}function Z9(e){this._context=e}Z9.prototype={_radius:4.5,pointRadius:function(e){return this._radius=e,this},polygonStart:function(){this._line=0},polygonEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){this._line===0&&this._context.closePath(),this._point=NaN},point:function(e,t){switch(this._point){case 0:{this._context.moveTo(e,t),this._point=1;break}case 1:{this._context.lineTo(e,t);break}default:{this._context.moveTo(e+this._radius,t),this._context.arc(e,t,this._radius,0,$r);break}}},result:qn};var lw=new kr,E2,J9,Q9,Th,Nh,Sp={point:qn,lineStart:function(){Sp.point=hne},lineEnd:function(){E2&&eL(J9,Q9),Sp.point=qn},polygonStart:function(){E2=!0},polygonEnd:function(){E2=null},result:function(){var e=+lw;return lw=new kr,e}};function hne(e,t){Sp.point=eL,J9=Th=e,Q9=Nh=t}function eL(e,t){Th-=e,Nh-=t,lw.add(Fr(Th*Th+Nh*Nh)),Th=e,Nh=t}let tD,F1,nD,rD;class iD{constructor(t){this._append=t==null?tL:pne(t),this._radius=4.5,this._=""}pointRadius(t){return this._radius=+t,this}polygonStart(){this._line=0}polygonEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){this._line===0&&(this._+="Z"),this._point=NaN}point(t,n){switch(this._point){case 0:{this._append`M${t},${n}`,this._point=1;break}case 1:{this._append`L${t},${n}`;break}default:{if(this._append`M${t},${n}`,this._radius!==nD||this._append!==F1){const r=this._radius,i=this._;this._="",this._append`m0,${r}a${r},${r} 0 1,1 0,${-2*r}a${r},${r} 0 1,1 0,${2*r}z`,nD=r,F1=this._append,rD=this._,this._=i}this._+=rD;break}}}result(){const t=this._;return this._="",t.length?t:null}}function tL(e){let t=1;this._+=e[0];for(const n=e.length;t=0))throw new RangeError(`invalid digits: ${e}`);if(t>15)return tL;if(t!==tD){const n=10**t;tD=t,F1=function(i){let s=1;this._+=i[0];for(const o=i.length;s=0))throw new RangeError(`invalid digits: ${a}`);n=u}return t===null&&(s=new iD(n)),o},o.projection(e).digits(n).context(t)}function hv(e){return function(t){var n=new cw;for(var r in e)n[r]=e[r];return n.stream=t,n}}function cw(){}cw.prototype={constructor:cw,point:function(e,t){this.stream.point(e,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}};function Ek(e,t,n){var r=e.clipExtent&&e.clipExtent();return e.scale(150).translate([0,0]),r!=null&&e.clipExtent(null),Jo(n,e.stream(k1)),t(k1.result()),r!=null&&e.clipExtent(r),e}function pv(e,t,n){return Ek(e,function(r){var i=t[1][0]-t[0][0],s=t[1][1]-t[0][1],o=Math.min(i/(r[1][0]-r[0][0]),s/(r[1][1]-r[0][1])),a=+t[0][0]+(i-o*(r[1][0]+r[0][0]))/2,u=+t[0][1]+(s-o*(r[1][1]+r[0][1]))/2;e.scale(150*o).translate([a,u])},n)}function Ak(e,t,n){return pv(e,[[0,0],t],n)}function Sk(e,t,n){return Ek(e,function(r){var i=+t,s=i/(r[1][0]-r[0][0]),o=(i-s*(r[1][0]+r[0][0]))/2,a=-s*r[0][1];e.scale(150*s).translate([o,a])},n)}function kk(e,t,n){return Ek(e,function(r){var i=+t,s=i/(r[1][1]-r[0][1]),o=-s*r[0][0],a=(i-s*(r[1][1]+r[0][1]))/2;e.scale(150*s).translate([o,a])},n)}var sD=16,gne=Ie(30*Xe);function oD(e,t){return+t?yne(e,t):mne(e)}function mne(e){return hv({point:function(t,n){t=e(t,n),this.stream.point(t[0],t[1])}})}function yne(e,t){function n(r,i,s,o,a,u,l,c,f,d,h,p,g,m){var y=l-r,v=c-i,b=y*y+v*v;if(b>4*t&&g--){var x=o+d,_=a+h,A=u+p,E=Fr(x*x+_*_+A*A),S=Xr(A/=E),k=it(it(A)-1)t||it((y*R+v*F)/b-.5)>.3||o*d+a*h+u*p2?C[2]%360*Xe:0,R()):[a*on,u*on,l*on]},D.angle=function(C){return arguments.length?(f=C%360*Xe,R()):f*on},D.reflectX=function(C){return arguments.length?(d=C?-1:1,R()):d<0},D.reflectY=function(C){return arguments.length?(h=C?-1:1,R()):h<0},D.precision=function(C){return arguments.length?(A=oD(E,_=C*C),F()):Fr(_)},D.fitExtent=function(C,T){return pv(D,C,T)},D.fitSize=function(C,T){return Ak(D,C,T)},D.fitWidth=function(C,T){return Sk(D,C,T)},D.fitHeight=function(C,T){return kk(D,C,T)};function R(){var C=aD(n,0,0,d,h,f).apply(null,t(s,o)),T=aD(n,r-C[0],i-C[1],d,h,f);return c=z9(a,u,l),E=ew(t,T),S=ew(c,E),A=oD(E,_),F()}function F(){return k=$=null,D}return function(){return t=e.apply(this,arguments),D.invert=t.invert&&M,R()}}function Ck(e){var t=0,n=Je/3,r=rL(e),i=r(t,n);return i.parallels=function(s){return arguments.length?r(t=s[0]*Xe,n=s[1]*Xe):[t*on,n*on]},i}function _ne(e){var t=Ie(e);function n(r,i){return[r*t,Ne(i)/t]}return n.invert=function(r,i){return[r/t,Xr(i*t)]},n}function wne(e,t){var n=Ne(e),r=(n+Ne(t))/2;if(it(r)=.12&&m<.234&&g>=-.425&&g<-.214?i:m>=.166&&m<.234&&g>=-.214&&g<-.115?o:n).invert(d)},c.stream=function(d){return e&&t===d?e:e=Ene([n.stream(t=d),i.stream(d),o.stream(d)])},c.precision=function(d){return arguments.length?(n.precision(d),i.precision(d),o.precision(d),f()):n.precision()},c.scale=function(d){return arguments.length?(n.scale(d),i.scale(d*.35),o.scale(d),c.translate(n.translate())):n.scale()},c.translate=function(d){if(!arguments.length)return n.translate();var h=n.scale(),p=+d[0],g=+d[1];return r=n.translate(d).clipExtent([[p-.455*h,g-.238*h],[p+.455*h,g+.238*h]]).stream(l),s=i.translate([p-.307*h,g+.201*h]).clipExtent([[p-.425*h+Oe,g+.12*h+Oe],[p-.214*h-Oe,g+.234*h-Oe]]).stream(l),a=o.translate([p-.205*h,g+.212*h]).clipExtent([[p-.214*h+Oe,g+.166*h+Oe],[p-.115*h-Oe,g+.234*h-Oe]]).stream(l),f()},c.fitExtent=function(d,h){return pv(c,d,h)},c.fitSize=function(d,h){return Ak(c,d,h)},c.fitWidth=function(d,h){return Sk(c,d,h)},c.fitHeight=function(d,h){return kk(c,d,h)};function f(){return e=t=null,c}return c.scale(1070)}function sL(e){return function(t,n){var r=Ie(t),i=Ie(n),s=e(r*i);return s===1/0?[2,0]:[s*i*Ne(t),s*Ne(n)]}}function Sg(e){return function(t,n){var r=Fr(t*t+n*n),i=e(r),s=Ne(i),o=Ie(i);return[Hi(t*s,r*o),Xr(r&&n*s/r)]}}var oL=sL(function(e){return Fr(2/(1+e))});oL.invert=Sg(function(e){return 2*Xr(e/2)});function Sne(){return Do(oL).scale(124.75).clipAngle(180-.001)}var aL=sL(function(e){return(e=F9(e))&&e/Ne(e)});aL.invert=Sg(function(e){return e});function kne(){return Do(aL).scale(79.4188).clipAngle(180-.001)}function gv(e,t){return[e,f1(_k((Jt+t)/2))]}gv.invert=function(e,t){return[e,2*Td($9(t))-Jt]};function Cne(){return uL(gv).scale(961/$r)}function uL(e){var t=Do(e),n=t.center,r=t.scale,i=t.translate,s=t.clipExtent,o=null,a,u,l;t.scale=function(f){return arguments.length?(r(f),c()):r()},t.translate=function(f){return arguments.length?(i(f),c()):i()},t.center=function(f){return arguments.length?(n(f),c()):n()},t.clipExtent=function(f){return arguments.length?(f==null?o=a=u=l=null:(o=+f[0][0],a=+f[0][1],u=+f[1][0],l=+f[1][1]),c()):o==null?null:[[o,a],[u,l]]};function c(){var f=Je*r(),d=t(Yte(t.rotate()).invert([0,0]));return s(o==null?[[d[0]-f,d[1]-f],[d[0]+f,d[1]+f]]:e===gv?[[Math.max(d[0]-f,o),a],[Math.min(d[0]+f,u),l]]:[[o,Math.max(d[1]-f,a)],[u,Math.min(d[1]+f,l)]])}return c()}function x0(e){return _k((Jt+e)/2)}function $ne(e,t){var n=Ie(e),r=e===t?Ne(e):f1(n/Ie(t))/f1(x0(t)/x0(e)),i=n*b2(x0(e),r)/r;if(!r)return gv;function s(o,a){i>0?a<-Jt+Oe&&(a=-Jt+Oe):a>Jt-Oe&&(a=Jt-Oe);var u=i/b2(x0(a),r);return[u*Ne(r*o),i-u*Ie(r*o)]}return s.invert=function(o,a){var u=i-a,l=Ti(r)*Fr(o*o+u*u),c=Hi(o,it(u))*Ti(u);return u*r<0&&(c-=Je*Ti(o)*Ti(u)),[c/r,2*Td(b2(i/l,1/r))-Jt]},s}function Fne(){return Ck($ne).scale(109.5).parallels([30,30])}function M1(e,t){return[e,t]}M1.invert=M1;function Dne(){return Do(M1).scale(152.63)}function Mne(e,t){var n=Ie(e),r=e===t?Ne(e):(n-Ie(t))/(t-e),i=n/r+e;if(it(r)Oe&&--r>0);return[e/(.8707+(s=n*n)*(-.131979+s*(-.013791+s*s*s*(.003971-.001529*s)))),n]};function Ine(){return Do(fL).scale(175.295)}function dL(e,t){return[Ie(t)*Ne(e),Ne(t)]}dL.invert=Sg(Xr);function Pne(){return Do(dL).scale(249.5).clipAngle(90+Oe)}function hL(e,t){var n=Ie(t),r=1+Ie(e)*n;return[n*Ne(e)/r,Ne(t)/r]}hL.invert=Sg(function(e){return 2*Td(e)});function Bne(){return Do(hL).scale(250).clipAngle(142)}function pL(e,t){return[f1(_k((Jt+t)/2)),-e]}pL.invert=function(e,t){return[-t,2*Td($9(e))-Jt]};function zne(){var e=uL(pL),t=e.center,n=e.rotate;return e.center=function(r){return arguments.length?t([-r[1],r[0]]):(r=t(),[r[1],-r[0]])},e.rotate=function(r){return arguments.length?n([r[0],r[1],r.length>2?r[2]+90:90]):(r=n(),[r[0],r[1],r[2]-90])},n([0,0,90]).scale(159.155)}var jne=Math.abs,fw=Math.cos,T1=Math.sin,Une=1e-6,gL=Math.PI,dw=gL/2,uD=qne(2);function lD(e){return e>1?dw:e<-1?-dw:Math.asin(e)}function qne(e){return e>0?Math.sqrt(e):0}function Wne(e,t){var n=e*T1(t),r=30,i;do t-=i=(t+T1(t)-n)/(1+fw(t));while(jne(i)>Une&&--r>0);return t/2}function Hne(e,t,n){function r(i,s){return[e*i*fw(s=Wne(n,s)),t*T1(s)]}return r.invert=function(i,s){return s=lD(s/t),[i/(e*fw(s)),lD((2*s+T1(2*s))/n)]},r}var Gne=Hne(uD/dw,uD,gL);function Yne(){return Do(Gne).scale(169.529)}const Vne=nL(),hw=["clipAngle","clipExtent","scale","translate","center","rotate","parallels","precision","reflectX","reflectY","coefficient","distance","fraction","lobes","parallel","radius","ratio","spacing","tilt"];function Xne(e,t){return function n(){const r=t();return r.type=e,r.path=nL().projection(r),r.copy=r.copy||function(){const i=n();return hw.forEach(s=>{r[s]&&i[s](r[s]())}),i.path.pointRadius(r.path.pointRadius()),i},DO(r)}}function $k(e,t){if(!e||typeof e!="string")throw new Error("Projection type must be a name string.");return e=e.toLowerCase(),arguments.length>1?(N1[e]=Xne(e,t),this):N1[e]||null}function mL(e){return e&&e.path||Vne}const N1={albers:iL,albersusa:Ane,azimuthalequalarea:Sne,azimuthalequidistant:kne,conicconformal:Fne,conicequalarea:D1,conicequidistant:Rne,equalEarth:Nne,equirectangular:Dne,gnomonic:One,identity:Lne,mercator:Cne,mollweide:Yne,naturalEarth1:Ine,orthographic:Pne,stereographic:Bne,transversemercator:zne};for(const e in N1)$k(e,N1[e]);function Kne(){}const Uo=[[],[[[1,1.5],[.5,1]]],[[[1.5,1],[1,1.5]]],[[[1.5,1],[.5,1]]],[[[1,.5],[1.5,1]]],[[[1,1.5],[.5,1]],[[1,.5],[1.5,1]]],[[[1,.5],[1,1.5]]],[[[1,.5],[.5,1]]],[[[.5,1],[1,.5]]],[[[1,1.5],[1,.5]]],[[[.5,1],[1,.5]],[[1.5,1],[1,1.5]]],[[[1.5,1],[1,.5]]],[[[.5,1],[1.5,1]]],[[[1,1.5],[1.5,1]]],[[[.5,1],[1,1.5]]],[]];function yL(){var e=1,t=1,n=a;function r(u,l){return l.map(c=>i(u,c))}function i(u,l){var c=[],f=[];return s(u,l,d=>{n(d,u,l),Zne(d)>0?c.push([d]):f.push(d)}),f.forEach(d=>{for(var h=0,p=c.length,g;h=l,Uo[m<<1].forEach(b);++h=l,Uo[g|m<<1].forEach(b);for(Uo[m<<0].forEach(b);++p=l,y=u[p*e]>=l,Uo[m<<1|y<<2].forEach(b);++h=l,v=y,y=u[p*e+h+1]>=l,Uo[g|m<<1|y<<2|v<<3].forEach(b);Uo[m|y<<3].forEach(b)}for(h=-1,y=u[p*e]>=l,Uo[y<<2].forEach(b);++h=l,Uo[y<<2|v<<3].forEach(b);Uo[y<<3].forEach(b);function b(x){var _=[x[0][0]+h,x[0][1]+p],A=[x[1][0]+h,x[1][1]+p],E=o(_),S=o(A),k,$;(k=d[E])?($=f[S])?(delete d[k.end],delete f[$.start],k===$?(k.ring.push(A),c(k.ring)):f[k.start]=d[$.end]={start:k.start,end:$.end,ring:k.ring.concat($.ring)}):(delete d[k.end],k.ring.push(A),d[k.end=S]=k):(k=f[S])?($=d[E])?(delete f[k.start],delete d[$.end],k===$?(k.ring.push(A),c(k.ring)):f[$.start]=d[k.end]={start:$.start,end:k.end,ring:$.ring.concat(k.ring)}):(delete f[k.start],k.ring.unshift(_),f[k.start=E]=k):f[E]=d[S]={start:E,end:S,ring:[_,A]}}}function o(u){return u[0]*2+u[1]*(e+1)*4}function a(u,l,c){u.forEach(f=>{var d=f[0],h=f[1],p=d|0,g=h|0,m,y=l[g*e+p];d>0&&d0&&h=0&&c>=0||X("invalid size"),e=l,t=c,r},r.smooth=function(u){return arguments.length?(n=u?a:Kne,r):n===a},r}function Zne(e){for(var t=0,n=e.length,r=e[n-1][1]*e[0][0]-e[n-1][0]*e[0][1];++tr!=h>r&&n<(d-l)*(r-c)/(h-c)+l&&(i=-i)}return i}function ere(e,t,n){var r;return tre(e,t,n)&&nre(e[r=+(e[0]===t[0])],n[r],t[r])}function tre(e,t,n){return(t[0]-e[0])*(n[1]-e[1])===(n[0]-e[0])*(t[1]-e[1])}function nre(e,t,n){return e<=t&&t<=n||n<=t&&t<=e}function vL(e,t,n){return function(r){var i=mo(r),s=n?Math.min(i[0],0):i[0],o=i[1],a=o-s,u=t?du(s,o,e):a/(e+1);return ci(s+u,o,u)}}function Fk(e){G.call(this,null,e)}Fk.Definition={type:"Isocontour",metadata:{generates:!0},params:[{name:"field",type:"field"},{name:"thresholds",type:"number",array:!0},{name:"levels",type:"number"},{name:"nice",type:"boolean",default:!1},{name:"resolve",type:"enum",values:["shared","independent"],default:"independent"},{name:"zero",type:"boolean",default:!0},{name:"smooth",type:"boolean",default:!0},{name:"scale",type:"number",expr:!0},{name:"translate",type:"number",array:!0,expr:!0},{name:"as",type:"string",null:!0,default:"contour"}]};he(Fk,G,{transform(e,t){if(this.value&&!t.changed()&&!e.modified())return t.StopPropagation;var n=t.fork(t.NO_SOURCE|t.NO_FIELDS),r=t.materialize(t.SOURCE).source,i=e.field||hr,s=yL().smooth(e.smooth!==!1),o=e.thresholds||rre(r,i,e),a=e.as===null?null:e.as||"contour",u=[];return r.forEach(l=>{const c=i(l),f=s.size([c.width,c.height])(c.values,ee(o)?o:o(c.values));ire(f,c,l,e),f.forEach(d=>{u.push(Ry(l,gt(a!=null?{[a]:d}:d)))})}),this.value&&(n.rem=this.value),this.value=n.source=n.add=u,n}});function rre(e,t,n){const r=vL(n.levels||10,n.nice,n.zero!==!1);return n.resolve!=="shared"?r:r(e.map(i=>kl(t(i).values)))}function ire(e,t,n,r){let i=r.scale||t.scale,s=r.translate||t.translate;if(He(i)&&(i=i(n,r)),He(s)&&(s=s(n,r)),(i===1||i==null)&&!s)return;const o=(ft(i)?i:i[0])||1,a=(ft(i)?i:i[1])||1,u=s&&s[0]||0,l=s&&s[1]||0;e.forEach(bL(t,o,a,u,l))}function bL(e,t,n,r,i){const s=e.x1||0,o=e.y1||0,a=t*n<0;function u(f){f.forEach(l)}function l(f){a&&f.reverse(),f.forEach(c)}function c(f){f[0]=(f[0]-s)*t+r,f[1]=(f[1]-o)*n+i}return function(f){return f.coordinates.forEach(u),f}}function cD(e,t,n){const r=e>=0?e:_A(t,n);return Math.round((Math.sqrt(4*r*r+1)-1)/2)}function A2(e){return He(e)?e:pr(+e)}function xL(){var e=u=>u[0],t=u=>u[1],n=bd,r=[-1,-1],i=960,s=500,o=2;function a(u,l){const c=cD(r[0],u,e)>>o,f=cD(r[1],u,t)>>o,d=c?c+2:0,h=f?f+2:0,p=2*d+(i>>o),g=2*h+(s>>o),m=new Float32Array(p*g),y=new Float32Array(p*g);let v=m;u.forEach(x=>{const _=d+(+e(x)>>o),A=h+(+t(x)>>o);_>=0&&_=0&&A0&&f>0?(zc(p,g,m,y,c),jc(p,g,y,m,f),zc(p,g,m,y,c),jc(p,g,y,m,f),zc(p,g,m,y,c),jc(p,g,y,m,f)):c>0?(zc(p,g,m,y,c),zc(p,g,y,m,c),zc(p,g,m,y,c),v=y):f>0&&(jc(p,g,m,y,f),jc(p,g,y,m,f),jc(p,g,m,y,f),v=y);const b=l?Math.pow(2,-2*o):1/OR(v);for(let x=0,_=p*g;x<_;++x)v[x]*=b;return{values:v,scale:1<>o),y2:h+(s>>o)}}return a.x=function(u){return arguments.length?(e=A2(u),a):e},a.y=function(u){return arguments.length?(t=A2(u),a):t},a.weight=function(u){return arguments.length?(n=A2(u),a):n},a.size=function(u){if(!arguments.length)return[i,s];var l=+u[0],c=+u[1];return l>=0&&c>=0||X("invalid size"),i=l,s=c,a},a.cellSize=function(u){return arguments.length?((u=+u)>=1||X("invalid cell size"),o=Math.floor(Math.log(u)/Math.LN2),a):1<=i&&(a>=s&&(u-=n[a-s+o*e]),r[a-i+o*e]=u/Math.min(a+1,e-1+s-a,s))}function jc(e,t,n,r,i){const s=(i<<1)+1;for(let o=0;o=i&&(a>=s&&(u-=n[o+(a-s)*e]),r[o+(a-i)*e]=u/Math.min(a+1,t-1+s-a,s))}function Dk(e){G.call(this,null,e)}Dk.Definition={type:"KDE2D",metadata:{generates:!0},params:[{name:"size",type:"number",array:!0,length:2,required:!0},{name:"x",type:"field",required:!0},{name:"y",type:"field",required:!0},{name:"weight",type:"field"},{name:"groupby",type:"field",array:!0},{name:"cellSize",type:"number"},{name:"bandwidth",type:"number",array:!0,length:2},{name:"counts",type:"boolean",default:!1},{name:"as",type:"string",default:"grid"}]};const sre=["x","y","weight","size","cellSize","bandwidth"];function _L(e,t){return sre.forEach(n=>t[n]!=null?e[n](t[n]):0),e}he(Dk,G,{transform(e,t){if(this.value&&!t.changed()&&!e.modified())return t.StopPropagation;var n=t.fork(t.NO_SOURCE|t.NO_FIELDS),r=t.materialize(t.SOURCE).source,i=ore(r,e.groupby),s=(e.groupby||[]).map(en),o=_L(xL(),e),a=e.as||"grid",u=[];function l(c,f){for(let d=0;dgt(l({[a]:o(c,e.counts)},c.dims))),this.value&&(n.rem=this.value),this.value=n.source=n.add=u,n}});function ore(e,t){var n=[],r=c=>c(a),i,s,o,a,u,l;if(t==null)n.push(e);else for(i={},s=0,o=e.length;sn.push(a(c))),s&&o&&(t.visit(u,c=>{var f=s(c),d=o(c);f!=null&&d!=null&&(f=+f)===f&&(d=+d)===d&&r.push([f,d])}),n=n.concat({type:pw,geometry:{type:are,coordinates:r}})),this.value={type:Rk,features:n}}});function Nk(e){G.call(this,null,e)}Nk.Definition={type:"GeoPath",metadata:{modifies:!0},params:[{name:"projection",type:"projection"},{name:"field",type:"field"},{name:"pointRadius",type:"number",expr:!0},{name:"as",type:"string",default:"path"}]};he(Nk,G,{transform(e,t){var n=t.fork(t.ALL),r=this.value,i=e.field||hr,s=e.as||"path",o=n.SOURCE;!r||e.modified()?(this.value=r=mL(e.projection),n.materialize().reflow()):o=i===hr||t.modified(i.fields)?n.ADD_MOD:n.ADD;const a=ure(r,e.pointRadius);return n.visit(o,u=>u[s]=r(i(u))),r.pointRadius(a),n.modifies(s)}});function ure(e,t){const n=e.pointRadius();return e.context(null),t!=null&&e.pointRadius(t),n}function Ok(e){G.call(this,null,e)}Ok.Definition={type:"GeoPoint",metadata:{modifies:!0},params:[{name:"projection",type:"projection",required:!0},{name:"fields",type:"field",array:!0,required:!0,length:2},{name:"as",type:"string",array:!0,length:2,default:["x","y"]}]};he(Ok,G,{transform(e,t){var n=e.projection,r=e.fields[0],i=e.fields[1],s=e.as||["x","y"],o=s[0],a=s[1],u;function l(c){const f=n([r(c),i(c)]);f?(c[o]=f[0],c[a]=f[1]):(c[o]=void 0,c[a]=void 0)}return e.modified()?t=t.materialize().reflow(!0).visit(t.SOURCE,l):(u=t.modified(r.fields)||t.modified(i.fields),t.visit(u?t.ADD_MOD:t.ADD,l)),t.modifies(s)}});function Lk(e){G.call(this,null,e)}Lk.Definition={type:"GeoShape",metadata:{modifies:!0,nomod:!0},params:[{name:"projection",type:"projection"},{name:"field",type:"field",default:"datum"},{name:"pointRadius",type:"number",expr:!0},{name:"as",type:"string",default:"shape"}]};he(Lk,G,{transform(e,t){var n=t.fork(t.ALL),r=this.value,i=e.as||"shape",s=n.ADD;return(!r||e.modified())&&(this.value=r=lre(mL(e.projection),e.field||Ui("datum"),e.pointRadius),n.materialize().reflow(),s=n.SOURCE),n.visit(s,o=>o[i]=r),n.modifies(i)}});function lre(e,t,n){const r=n==null?i=>e(t(i)):i=>{var s=e.pointRadius(),o=e.pointRadius(n)(t(i));return e.pointRadius(s),o};return r.context=i=>(e.context(i),r),r}function Ik(e){G.call(this,[],e),this.generator=rne()}Ik.Definition={type:"Graticule",metadata:{changes:!0,generates:!0},params:[{name:"extent",type:"array",array:!0,length:2,content:{type:"number",array:!0,length:2}},{name:"extentMajor",type:"array",array:!0,length:2,content:{type:"number",array:!0,length:2}},{name:"extentMinor",type:"array",array:!0,length:2,content:{type:"number",array:!0,length:2}},{name:"step",type:"number",array:!0,length:2},{name:"stepMajor",type:"number",array:!0,length:2,default:[90,360]},{name:"stepMinor",type:"number",array:!0,length:2,default:[10,10]},{name:"precision",type:"number",default:2.5}]};he(Ik,G,{transform(e,t){var n=this.value,r=this.generator,i;if(!n.length||e.modified())for(const s in e)He(r[s])&&r[s](e[s]);return i=r(),n.length?t.mod.push(FT(n[0],i)):t.add.push(gt(i)),n[0]=i,t}});function Pk(e){G.call(this,null,e)}Pk.Definition={type:"heatmap",metadata:{modifies:!0},params:[{name:"field",type:"field"},{name:"color",type:"string",expr:!0},{name:"opacity",type:"number",expr:!0},{name:"resolve",type:"enum",values:["shared","independent"],default:"independent"},{name:"as",type:"string",default:"image"}]};he(Pk,G,{transform(e,t){if(!t.changed()&&!e.modified())return t.StopPropagation;var n=t.materialize(t.SOURCE).source,r=e.resolve==="shared",i=e.field||hr,s=fre(e.opacity,e),o=cre(e.color,e),a=e.as||"image",u={$x:0,$y:0,$value:0,$max:r?kl(n.map(l=>kl(i(l).values))):0};return n.forEach(l=>{const c=i(l),f=We({},l,u);r||(f.$max=kl(c.values||[])),l[a]=dre(c,f,o.dep?o:pr(o(f)),s.dep?s:pr(s(f)))}),t.reflow(!0).modifies(a)}});function cre(e,t){let n;return He(e)?(n=r=>gu(e(r,t)),n.dep=wL(e)):n=pr(gu(e||"#888")),n}function fre(e,t){let n;return He(e)?(n=r=>e(r,t),n.dep=wL(e)):e?n=pr(e):(n=r=>r.$value/r.$max||0,n.dep=!0),n}function wL(e){if(!He(e))return!1;const t=As(ar(e));return t.$x||t.$y||t.$value||t.$max}function dre(e,t,n,r){const i=e.width,s=e.height,o=e.x1||0,a=e.y1||0,u=e.x2||i,l=e.y2||s,c=e.values,f=c?m=>c[m]:ja,d=au(u-o,l-a),h=d.getContext("2d"),p=h.getImageData(0,0,u-o,l-a),g=p.data;for(let m=a,y=0;m{e[r]!=null&&fD(n,r,e[r])})):hw.forEach(r=>{e.modified(r)&&fD(n,r,e[r])}),e.pointRadius!=null&&n.path.pointRadius(e.pointRadius),e.fit&&hre(n,e),t.fork(t.NO_SOURCE|t.NO_FIELDS)}});function hre(e,t){const n=gre(t.fit);t.extent?e.fitExtent(t.extent,n):t.size&&e.fitSize(t.size,n)}function pre(e){const t=$k((e||"mercator").toLowerCase());return t||X("Unrecognized projection type: "+e),t()}function fD(e,t,n){He(e[t])&&e[t](n)}function gre(e){return e=ye(e),e.length===1?e[0]:{type:Rk,features:e.reduce((t,n)=>t.concat(mre(n)),[])}}function mre(e){return e.type===Rk?e.features:ye(e).filter(t=>t!=null).map(t=>t.type===pw?t:{type:pw,geometry:t})}const yre=Object.freeze(Object.defineProperty({__proto__:null,contour:Mk,geojson:Tk,geopath:Nk,geopoint:Ok,geoshape:Lk,graticule:Ik,heatmap:Pk,isocontour:Fk,kde2d:Dk,projection:EL},Symbol.toStringTag,{value:"Module"}));function vre(e,t){var n,r=1;e==null&&(e=0),t==null&&(t=0);function i(){var s,o=n.length,a,u=0,l=0;for(s=0;s=(f=(a+l)/2))?a=f:l=f,(m=n>=(d=(u+c)/2))?u=d:c=d,i=s,!(s=s[y=m<<1|g]))return i[y]=o,e;if(h=+e._x.call(null,s.data),p=+e._y.call(null,s.data),t===h&&n===p)return o.next=s,i?i[y]=o:e._root=o,e;do i=i?i[y]=new Array(4):e._root=new Array(4),(g=t>=(f=(a+l)/2))?a=f:l=f,(m=n>=(d=(u+c)/2))?u=d:c=d;while((y=m<<1|g)===(v=(p>=d)<<1|h>=f));return i[v]=s,i[y]=o,e}function xre(e){var t,n,r=e.length,i,s,o=new Array(r),a=new Array(r),u=1/0,l=1/0,c=-1/0,f=-1/0;for(n=0;nc&&(c=i),sf&&(f=s));if(u>c||l>f)return this;for(this.cover(u,l).cover(c,f),n=0;ne||e>=i||r>t||t>=s;)switch(l=(tc||(a=p.y0)>f||(u=p.x1)=y)<<1|e>=m)&&(p=d[d.length-1],d[d.length-1]=d[d.length-1-g],d[d.length-1-g]=p)}else{var v=e-+this._x.call(null,h.data),b=t-+this._y.call(null,h.data),x=v*v+b*b;if(x=(d=(o+u)/2))?o=d:u=d,(g=f>=(h=(a+l)/2))?a=h:l=h,t=n,!(n=n[m=g<<1|p]))return this;if(!n.length)break;(t[m+1&3]||t[m+2&3]||t[m+3&3])&&(r=t,y=m)}for(;n.data!==e;)if(i=n,!(n=n.next))return this;return(s=n.next)&&delete n.next,i?(s?i.next=s:delete i.next,this):t?(s?t[m]=s:delete t[m],(n=t[0]||t[1]||t[2]||t[3])&&n===(t[3]||t[2]||t[1]||t[0])&&!n.length&&(r?r[y]=n:this._root=n),this):(this._root=s,this)}function kre(e){for(var t=0,n=e.length;td.index){var D=h-S.x-S.vx,M=p-S.y-S.vy,R=D*D+M*M;R<$*$&&(D===0&&(D=Za(r),R+=D*D),M===0&&(M=Za(r),R+=M*M),R=($-(R=Math.sqrt(R)))/R*i,d.vx+=(D*=R)*($=(k*=k)/(m+k)),d.vy+=(M*=R)*$,S.vx-=D*($=1-$),S.vy-=M*$)}return}return x>h+$||Ap+$||El.r&&(l.r=l[c].r)}function u(){if(t){var l,c=t.length,f;for(n=new Array(c),l=0;l[t(_,A,o),_])),x;for(m=0,a=new Array(y);m{}};function SL(){for(var e=0,t=arguments.length,n={},r;e=0&&(r=n.slice(i+1),n=n.slice(0,i)),n&&!t.hasOwnProperty(n))throw new Error("unknown type: "+n);return{type:n,name:r}})}fm.prototype=SL.prototype={constructor:fm,on:function(e,t){var n=this._,r=jre(e+"",n),i,s=-1,o=r.length;if(arguments.length<2){for(;++s0)for(var n=new Array(i),r=0,i,s;r=0&&e._call.call(void 0,t),e=e._next;--Jf}function gD(){Zl=(L1=kp.now())+mv,Jf=Oh=0;try{Wre()}finally{Jf=0,Gre(),Zl=0}}function Hre(){var e=kp.now(),t=e-L1;t>kL&&(mv-=t,L1=e)}function Gre(){for(var e,t=O1,n,r=1/0;t;)t._call?(r>t._time&&(r=t._time),e=t,t=t._next):(n=t._next,t._next=null,t=e?e._next=n:O1=n);Lh=e,gw(r)}function gw(e){if(!Jf){Oh&&(Oh=clearTimeout(Oh));var t=e-Zl;t>24?(e<1/0&&(Oh=setTimeout(gD,e-kp.now()-mv)),oh&&(oh=clearInterval(oh))):(oh||(L1=kp.now(),oh=setInterval(Hre,kL)),Jf=1,CL(gD))}}function Yre(e,t,n){var r=new I1,i=t;return t==null?(r.restart(e,t,n),r):(r._restart=r.restart,r.restart=function(s,o,a){o=+o,a=a==null?jk():+a,r._restart(function u(l){l+=i,r._restart(u,i+=o,a),s(l)},o,a)},r.restart(e,t,n),r)}const Vre=1664525,Xre=1013904223,mD=4294967296;function Kre(){let e=1;return()=>(e=(Vre*e+Xre)%mD)/mD}function Zre(e){return e.x}function Jre(e){return e.y}var Qre=10,eie=Math.PI*(3-Math.sqrt(5));function tie(e){var t,n=1,r=.001,i=1-Math.pow(r,1/300),s=0,o=.6,a=new Map,u=$L(f),l=SL("tick","end"),c=Kre();e==null&&(e=[]);function f(){d(),l.call("tick",t),n1?(m==null?a.delete(g):a.set(g,p(m)),t):a.get(g)},find:function(g,m,y){var v=0,b=e.length,x,_,A,E,S;for(y==null?y=1/0:y*=y,v=0;v1?(l.on(g,m),t):l.on(g)}}}function nie(){var e,t,n,r,i=Ar(-30),s,o=1,a=1/0,u=.81;function l(h){var p,g=e.length,m=Bk(e,Zre,Jre).visitAfter(f);for(r=h,p=0;p=a)return;(h.data!==t||h.next)&&(y===0&&(y=Za(n),x+=y*y),v===0&&(v=Za(n),x+=v*v),x=0;)n.tick();else if(n.stopped()&&n.restart(),!r)return t.StopPropagation}return this.finish(e,t)},finish(e,t){const n=t.dataflow;for(let a=this._argops,u=0,l=a.length,c;ue.touch(t).run()}function aie(e,t){const n=tie(e),r=n.stop,i=n.restart;let s=!1;return n.stopped=()=>s,n.restart=()=>(s=!1,i()),n.stop=()=>(s=!0,r()),DL(n,t,!0).on("end",()=>s=!0)}function DL(e,t,n,r){var i=ye(t.forces),s,o,a,u;for(s=0,o=mw.length;st(r,n):t)}const fie=Object.freeze(Object.defineProperty({__proto__:null,force:Uk},Symbol.toStringTag,{value:"Module"}));function die(e,t){return e.parent===t.parent?1:2}function hie(e){return e.reduce(pie,0)/e.length}function pie(e,t){return e+t.x}function gie(e){return 1+e.reduce(mie,0)}function mie(e,t){return Math.max(e,t.y)}function yie(e){for(var t;t=e.children;)e=t[0];return e}function vie(e){for(var t;t=e.children;)e=t[t.length-1];return e}function bie(){var e=die,t=1,n=1,r=!1;function i(s){var o,a=0;s.eachAfter(function(d){var h=d.children;h?(d.x=hie(h),d.y=gie(h)):(d.x=o?a+=e(d,o):0,d.y=0,o=d)});var u=yie(s),l=vie(s),c=u.x-e(u,l)/2,f=l.x+e(l,u)/2;return s.eachAfter(r?function(d){d.x=(d.x-s.x)*t,d.y=(s.y-d.y)*n}:function(d){d.x=(d.x-c)/(f-c)*t,d.y=(1-(s.y?d.y/s.y:1))*n})}return i.separation=function(s){return arguments.length?(e=s,i):e},i.size=function(s){return arguments.length?(r=!1,t=+s[0],n=+s[1],i):r?null:[t,n]},i.nodeSize=function(s){return arguments.length?(r=!0,t=+s[0],n=+s[1],i):r?[t,n]:null},i}function xie(e){var t=0,n=e.children,r=n&&n.length;if(!r)t=1;else for(;--r>=0;)t+=n[r].value;e.value=t}function _ie(){return this.eachAfter(xie)}function wie(e,t){let n=-1;for(const r of this)e.call(t,r,++n,this);return this}function Eie(e,t){for(var n=this,r=[n],i,s,o=-1;n=r.pop();)if(e.call(t,n,++o,this),i=n.children)for(s=i.length-1;s>=0;--s)r.push(i[s]);return this}function Aie(e,t){for(var n=this,r=[n],i=[],s,o,a,u=-1;n=r.pop();)if(i.push(n),s=n.children)for(o=0,a=s.length;o=0;)n+=r[i].value;t.value=n})}function Cie(e){return this.eachBefore(function(t){t.children&&t.children.sort(e)})}function $ie(e){for(var t=this,n=Fie(t,e),r=[t];t!==n;)t=t.parent,r.push(t);for(var i=r.length;e!==n;)r.splice(i,0,e),e=e.parent;return r}function Fie(e,t){if(e===t)return e;var n=e.ancestors(),r=t.ancestors(),i=null;for(e=n.pop(),t=r.pop();e===t;)i=e,e=n.pop(),t=r.pop();return i}function Die(){for(var e=this,t=[e];e=e.parent;)t.push(e);return t}function Mie(){return Array.from(this)}function Rie(){var e=[];return this.eachBefore(function(t){t.children||e.push(t)}),e}function Tie(){var e=this,t=[];return e.each(function(n){n!==e&&t.push({source:n.parent,target:n})}),t}function*Nie(){var e=this,t,n=[e],r,i,s;do for(t=n.reverse(),n=[];e=t.pop();)if(yield e,r=e.children)for(i=0,s=r.length;i=0;--a)i.push(s=o[a]=new Qf(o[a])),s.parent=r,s.depth=r.depth+1;return n.eachBefore(ML)}function Oie(){return qk(this).eachBefore(Pie)}function Lie(e){return e.children}function Iie(e){return Array.isArray(e)?e[1]:null}function Pie(e){e.data.value!==void 0&&(e.value=e.data.value),e.data=e.data.data}function ML(e){var t=0;do e.height=t;while((e=e.parent)&&e.height<++t)}function Qf(e){this.data=e,this.depth=this.height=0,this.parent=null}Qf.prototype=qk.prototype={constructor:Qf,count:_ie,each:wie,eachAfter:Aie,eachBefore:Eie,find:Sie,sum:kie,sort:Cie,path:$ie,ancestors:Die,descendants:Mie,leaves:Rie,links:Tie,copy:Oie,[Symbol.iterator]:Nie};function dm(e){return e==null?null:RL(e)}function RL(e){if(typeof e!="function")throw new Error;return e}function fl(){return 0}function Kc(e){return function(){return e}}const Bie=1664525,zie=1013904223,vD=4294967296;function jie(){let e=1;return()=>(e=(Bie*e+zie)%vD)/vD}function Uie(e){return typeof e=="object"&&"length"in e?e:Array.from(e)}function qie(e,t){let n=e.length,r,i;for(;n;)i=t()*n--|0,r=e[n],e[n]=e[i],e[i]=r;return e}function Wie(e,t){for(var n=0,r=(e=qie(Array.from(e),t)).length,i=[],s,o;n0&&n*n>r*r+i*i}function S2(e,t){for(var n=0;n1e-6?(D+Math.sqrt(D*D-4*$*M))/(2*$):M/D);return{x:r+A+E*R,y:i+S+k*R,r:R}}function bD(e,t,n){var r=e.x-t.x,i,s,o=e.y-t.y,a,u,l=r*r+o*o;l?(s=t.r+n.r,s*=s,u=e.r+n.r,u*=u,s>u?(i=(l+u-s)/(2*l),a=Math.sqrt(Math.max(0,u/l-i*i)),n.x=e.x-i*r-a*o,n.y=e.y-i*o+a*r):(i=(l+s-u)/(2*l),a=Math.sqrt(Math.max(0,s/l-i*i)),n.x=t.x+i*r-a*o,n.y=t.y+i*o+a*r)):(n.x=t.x+n.r,n.y=t.y)}function xD(e,t){var n=e.r+t.r-1e-6,r=t.x-e.x,i=t.y-e.y;return n>0&&n*n>r*r+i*i}function _D(e){var t=e._,n=e.next._,r=t.r+n.r,i=(t.x*n.r+n.x*t.r)/r,s=(t.y*n.r+n.y*t.r)/r;return i*i+s*s}function w0(e){this._=e,this.next=null,this.previous=null}function Vie(e,t){if(!(s=(e=Uie(e)).length))return 0;var n,r,i,s,o,a,u,l,c,f,d;if(n=e[0],n.x=0,n.y=0,!(s>1))return n.r;if(r=e[1],n.x=-r.r,r.x=n.r,r.y=0,!(s>2))return n.r+r.r;bD(r,n,i=e[2]),n=new w0(n),r=new w0(r),i=new w0(i),n.next=i.previous=r,r.next=n.previous=i,i.next=r.previous=n;e:for(u=3;utse(n(x,_,i))),v=y.map(kD),b=new Set(y).add("");for(const x of v)b.has(x)||(b.add(x),y.push(x),v.push(kD(x)),s.push(C2));o=(x,_)=>y[_],a=(x,_)=>v[_]}for(c=0,u=s.length;c=0&&(h=s[y],h.data===C2);--y)h.data=null}if(f.parent=Jie,f.eachBefore(function(y){y.depth=y.parent.depth+1,--u}).eachBefore(ML),f.parent=null,u>0)throw new Error("cycle");return f}return r.id=function(i){return arguments.length?(e=dm(i),r):e},r.parentId=function(i){return arguments.length?(t=dm(i),r):t},r.path=function(i){return arguments.length?(n=dm(i),r):n},r}function tse(e){e=`${e}`;let t=e.length;return yw(e,t-1)&&!yw(e,t-2)&&(e=e.slice(0,-1)),e[0]==="/"?e:`/${e}`}function kD(e){let t=e.length;if(t<2)return"";for(;--t>1&&!yw(e,t););return e.slice(0,t)}function yw(e,t){if(e[t]==="/"){let n=0;for(;t>0&&e[--t]==="\\";)++n;if((n&1)===0)return!0}return!1}function nse(e,t){return e.parent===t.parent?1:2}function $2(e){var t=e.children;return t?t[0]:e.t}function F2(e){var t=e.children;return t?t[t.length-1]:e.t}function rse(e,t,n){var r=n/(t.i-e.i);t.c-=r,t.s+=n,e.c+=r,t.z+=n,t.m+=n}function ise(e){for(var t=0,n=0,r=e.children,i=r.length,s;--i>=0;)s=r[i],s.z+=t,s.m+=t,t+=s.s+(n+=s.c)}function sse(e,t,n){return e.a.parent===t.parent?e.a:n}function hm(e,t){this._=e,this.parent=null,this.children=null,this.A=null,this.a=this,this.z=0,this.m=0,this.c=0,this.s=0,this.t=null,this.i=t}hm.prototype=Object.create(Qf.prototype);function ose(e){for(var t=new hm(e,0),n,r=[t],i,s,o,a;n=r.pop();)if(s=n._.children)for(n.children=new Array(a=s.length),o=a-1;o>=0;--o)r.push(i=n.children[o]=new hm(s[o],o)),i.parent=n;return(t.parent=new hm(null,0)).children=[t],t}function ase(){var e=nse,t=1,n=1,r=null;function i(l){var c=ose(l);if(c.eachAfter(s),c.parent.m=-c.z,c.eachBefore(o),r)l.eachBefore(u);else{var f=l,d=l,h=l;l.eachBefore(function(v){v.xd.x&&(d=v),v.depth>h.depth&&(h=v)});var p=f===d?1:e(f,d)/2,g=p-f.x,m=t/(d.x+p+g),y=n/(h.depth||1);l.eachBefore(function(v){v.x=(v.x+g)*m,v.y=v.depth*y})}return l}function s(l){var c=l.children,f=l.parent.children,d=l.i?f[l.i-1]:null;if(c){ise(l);var h=(c[0].z+c[c.length-1].z)/2;d?(l.z=d.z+e(l._,d._),l.m=l.z-h):l.z=h}else d&&(l.z=d.z+e(l._,d._));l.parent.A=a(l,d,l.parent.A||f[0])}function o(l){l._.x=l.z+l.parent.m,l.m+=l.parent.m}function a(l,c,f){if(c){for(var d=l,h=l,p=c,g=d.parent.children[0],m=d.m,y=h.m,v=p.m,b=g.m,x;p=F2(p),d=$2(d),p&&d;)g=$2(g),h=F2(h),h.a=l,x=p.z+v-d.z-m+e(p._,d._),x>0&&(rse(sse(p,l,f),l,x),m+=x,y+=x),v+=p.m,m+=d.m,b+=g.m,y+=h.m;p&&!F2(h)&&(h.t=p,h.m+=v-y),d&&!$2(g)&&(g.t=d,g.m+=m-b,f=l)}return f}function u(l){l.x*=t,l.y=l.depth*n}return i.separation=function(l){return arguments.length?(e=l,i):e},i.size=function(l){return arguments.length?(r=!1,t=+l[0],n=+l[1],i):r?null:[t,n]},i.nodeSize=function(l){return arguments.length?(r=!0,t=+l[0],n=+l[1],i):r?[t,n]:null},i}function yv(e,t,n,r,i){for(var s=e.children,o,a=-1,u=s.length,l=e.value&&(i-n)/e.value;++av&&(v=l),A=m*m*_,b=Math.max(v/A,A/y),b>x){m-=l;break}x=b}o.push(u={value:m,dice:h1?r:1)},n})(LL);function use(){var e=PL,t=!1,n=1,r=1,i=[0],s=fl,o=fl,a=fl,u=fl,l=fl;function c(d){return d.x0=d.y0=0,d.x1=n,d.y1=r,d.eachBefore(f),i=[0],t&&d.eachBefore(OL),d}function f(d){var h=i[d.depth],p=d.x0+h,g=d.y0+h,m=d.x1-h,y=d.y1-h;m=d-1){var v=s[f];v.x0=p,v.y0=g,v.x1=m,v.y1=y;return}for(var b=l[f],x=h/2+b,_=f+1,A=d-1;_>>1;l[E]y-g){var $=h?(p*k+m*S)/h:m;c(f,_,S,p,g,$,y),c(_,d,k,$,g,m,y)}else{var D=h?(g*k+y*S)/h:y;c(f,_,S,p,g,m,D),c(_,d,k,p,D,m,y)}}}function cse(e,t,n,r,i){(e.depth&1?yv:kg)(e,t,n,r,i)}const fse=(function e(t){function n(r,i,s,o,a){if((u=r._squarify)&&u.ratio===t)for(var u,l,c,f,d=-1,h,p=u.length,g=r.value;++d1?r:1)},n})(LL);function vw(e,t,n){const r={};return e.each(i=>{const s=i.data;n(s)&&(r[t(s)]=i)}),e.lookup=r,e}function Wk(e){G.call(this,null,e)}Wk.Definition={type:"Nest",metadata:{treesource:!0,changes:!0},params:[{name:"keys",type:"field",array:!0},{name:"generate",type:"boolean"}]};const dse=e=>e.values;he(Wk,G,{transform(e,t){t.source||X("Nest transform requires an upstream data source.");var n=e.generate,r=e.modified(),i=t.clone(),s=this.value;return(!s||r||t.changed())&&(s&&s.each(o=>{o.children&&My(o.data)&&i.rem.push(o.data)}),this.value=s=qk({values:ye(e.keys).reduce((o,a)=>(o.key(a),o),hse()).entries(i.source)},dse),n&&s.each(o=>{o.children&&(o=gt(o.data),i.add.push(o),i.source.push(o))}),vw(s,Te,Te)),i.source.root=s,i}});function hse(){const e=[],t={entries:i=>r(n(i,0),0),key:i=>(e.push(i),t)};function n(i,s){if(s>=e.length)return i;const o=i.length,a=e[s++],u={},l={};let c=-1,f,d,h;for(;++ce.length)return i;const o=[];for(const a in i)o.push({key:a,values:r(i[a],s)});return o}return t}function wa(e){G.call(this,null,e)}const pse=(e,t)=>e.parent===t.parent?1:2;he(wa,G,{transform(e,t){(!t.source||!t.source.root)&&X(this.constructor.name+" transform requires a backing tree data source.");const n=this.layout(e.method),r=this.fields,i=t.source.root,s=e.as||r;e.field?i.sum(e.field):i.count(),e.sort&&i.sort(yc(e.sort,o=>o.data)),gse(n,this.params,e),n.separation&&n.separation(e.separation!==!1?pse:bd);try{this.value=n(i)}catch(o){X(o)}return i.each(o=>mse(o,r,s)),t.reflow(e.modified()).modifies(s).modifies("leaf")}});function gse(e,t,n){for(let r,i=0,s=t.length;is[Te(o)]=1),r.each(o=>{const a=o.data,u=o.parent&&o.parent.data;u&&s[Te(a)]&&s[Te(u)]&&i.add.push(gt({source:u,target:a}))}),this.value=i.add):t.changed(t.MOD)&&(t.visit(t.MOD,o=>s[Te(o)]=1),n.forEach(o=>{(s[Te(o.source)]||s[Te(o.target)])&&i.mod.push(o)})),i}});const $D={binary:lse,dice:kg,slice:yv,slicedice:cse,squarify:PL,resquarify:fse},ww=["x0","y0","x1","y1","depth","children"];function Kk(e){wa.call(this,e)}Kk.Definition={type:"Treemap",metadata:{tree:!0,modifies:!0},params:[{name:"field",type:"field"},{name:"sort",type:"compare"},{name:"method",type:"enum",default:"squarify",values:["squarify","resquarify","binary","dice","slice","slicedice"]},{name:"padding",type:"number",default:0},{name:"paddingInner",type:"number",default:0},{name:"paddingOuter",type:"number",default:0},{name:"paddingTop",type:"number",default:0},{name:"paddingRight",type:"number",default:0},{name:"paddingBottom",type:"number",default:0},{name:"paddingLeft",type:"number",default:0},{name:"ratio",type:"number",default:1.618033988749895},{name:"round",type:"boolean",default:!1},{name:"size",type:"number",array:!0,length:2},{name:"as",type:"string",array:!0,length:ww.length,default:ww}]};he(Kk,wa,{layout(){const e=use();return e.ratio=t=>{const n=e.tile();n.ratio&&e.tile(n.ratio(t))},e.method=t=>{be($D,t)?e.tile($D[t]):X("Unrecognized Treemap layout method: "+t)},e},params:["method","ratio","size","round","padding","paddingInner","paddingOuter","paddingTop","paddingRight","paddingBottom","paddingLeft"],fields:ww});const yse=Object.freeze(Object.defineProperty({__proto__:null,nest:Wk,pack:Hk,partition:Gk,stratify:Yk,tree:Vk,treelinks:Xk,treemap:Kk},Symbol.toStringTag,{value:"Module"})),D2=4278190080;function vse(e,t){const n=e.bitmap();return(t||[]).forEach(r=>n.set(e(r.boundary[0]),e(r.boundary[3]))),[n,void 0]}function bse(e,t,n,r,i){const s=e.width,o=e.height,a=r||i,u=au(s,o).getContext("2d"),l=au(s,o).getContext("2d"),c=a&&au(s,o).getContext("2d");n.forEach(S=>pm(u,S,!1)),pm(l,t,!1),a&&pm(c,t,!0);const f=M2(u,s,o),d=M2(l,s,o),h=a&&M2(c,s,o),p=e.bitmap(),g=a&&e.bitmap();let m,y,v,b,x,_,A,E;for(y=0;y{i.items.forEach(s=>pm(e,s.items,n))}):xi[r].draw(e,{items:n?t.map(xse):t})}function xse(e){const t=Ry(e,{});return t.stroke&&t.strokeOpacity!==0||t.fill&&t.fillOpacity!==0?{...t,strokeOpacity:1,stroke:"#000",fillOpacity:0}:t}const qo=5,mr=31,Cp=32,Ba=new Uint32Array(Cp+1),ls=new Uint32Array(Cp+1);ls[0]=0;Ba[0]=~ls[0];for(let e=1;e<=Cp;++e)ls[e]=ls[e-1]<<1|1,Ba[e]=~ls[e];function _se(e,t){const n=new Uint32Array(~~((e*t+Cp)/Cp));function r(s,o){n[s]|=o}function i(s,o){n[s]&=o}return{array:n,get:(s,o)=>{const a=o*e+s;return n[a>>>qo]&1<<(a&mr)},set:(s,o)=>{const a=o*e+s;r(a>>>qo,1<<(a&mr))},clear:(s,o)=>{const a=o*e+s;i(a>>>qo,~(1<<(a&mr)))},getRange:(s,o,a,u)=>{let l=u,c,f,d,h;for(;l>=o;--l)if(c=l*e+s,f=l*e+a,d=c>>>qo,h=f>>>qo,d===h){if(n[d]&Ba[c&mr]&ls[(f&mr)+1])return!0}else{if(n[d]&Ba[c&mr]||n[h]&ls[(f&mr)+1])return!0;for(let p=d+1;p{let l,c,f,d,h;for(;o<=u;++o)if(l=o*e+s,c=o*e+a,f=l>>>qo,d=c>>>qo,f===d)r(f,Ba[l&mr]&ls[(c&mr)+1]);else for(r(f,Ba[l&mr]),r(d,ls[(c&mr)+1]),h=f+1;h{let l,c,f,d,h;for(;o<=u;++o)if(l=o*e+s,c=o*e+a,f=l>>>qo,d=c>>>qo,f===d)i(f,ls[l&mr]|Ba[(c&mr)+1]);else for(i(f,ls[l&mr]),i(d,Ba[(c&mr)+1]),h=f+1;hs<0||o<0||u>=t||a>=e}}function wse(e,t,n){const r=Math.max(1,Math.sqrt(e*t/1e6)),i=~~((e+2*n+r)/r),s=~~((t+2*n+r)/r),o=a=>~~((a+n)/r);return o.invert=a=>a*r-n,o.bitmap=()=>_se(i,s),o.ratio=r,o.padding=n,o.width=e,o.height=t,o}function Ese(e,t,n,r){const i=e.width,s=e.height;return function(o){const a=o.datum.datum.items[r].items,u=a.length,l=o.datum.fontSize,c=pi.width(o.datum,o.datum.text);let f=0,d,h,p,g,m,y,v;for(let b=0;b=f&&(f=v,o.x=m,o.y=y);return m=c/2,y=l/2,d=o.x-m,h=o.x+m,p=o.y-y,g=o.y+y,o.align="center",d<0&&h<=i?o.align="left":0<=d&&ii||t-(o=r/2)<0||t+o>s}function Ja(e,t,n,r,i,s,o,a){const u=i*s/(r*2),l=e(t-u),c=e(t+u),f=e(n-(s=s/2)),d=e(n+s);return o.outOfBounds(l,f,c,d)||o.getRange(l,f,c,d)||a&&a.getRange(l,f,c,d)}function Ase(e,t,n,r){const i=e.width,s=e.height,o=t[0],a=t[1];function u(l,c,f,d,h){const p=e.invert(l),g=e.invert(c);let m=f,y=s,v;if(!P1(p,g,d,h,i,s)&&!Ja(e,p,g,h,d,m,o,a)&&!Ja(e,p,g,h,d,h,o,null)){for(;y-m>=1;)v=(m+y)/2,Ja(e,p,g,h,d,v,o,a)?y=v:m=v;if(m>f)return[p,g,m,!0]}}return function(l){const c=l.datum.datum.items[r].items,f=c.length,d=l.datum.fontSize,h=pi.width(l.datum,l.datum.text);let p=n?d:0,g=!1,m=!1,y=0,v,b,x,_,A,E,S,k,$,D,M,R,F,C,T,O,N;for(let L=0;Lb&&(N=v,v=b,b=N),x>_&&(N=x,x=_,_=N),$=e(v),M=e(b),D=~~(($+M)/2),R=e(x),C=e(_),F=~~((R+C)/2),S=D;S>=$;--S)for(k=F;k>=R;--k)O=u(S,k,p,h,d),O&&([l.x,l.y,p,g]=O);for(S=D;S<=M;++S)for(k=F;k<=C;++k)O=u(S,k,p,h,d),O&&([l.x,l.y,p,g]=O);!g&&!n&&(T=Math.abs(b-v+_-x),A=(v+b)/2,E=(x+_)/2,T>=y&&!P1(A,E,h,d,i,s)&&!Ja(e,A,E,d,h,d,o,null)&&(y=T,l.x=A,l.y=E,m=!0))}return g||m?(A=h/2,E=d/2,o.setRange(e(l.x-A),e(l.y-E),e(l.x+A),e(l.y+E)),l.align="center",l.baseline="middle",!0):!1}}const Sse=[-1,-1,1,1],kse=[-1,1,-1,1];function Cse(e,t,n,r){const i=e.width,s=e.height,o=t[0],a=t[1],u=e.bitmap();return function(l){const c=l.datum.datum.items[r].items,f=c.length,d=l.datum.fontSize,h=pi.width(l.datum,l.datum.text),p=[];let g=n?d:0,m=!1,y=!1,v=0,b,x,_,A,E,S,k,$,D,M,R,F;for(let C=0;C=1;)R=(D+M)/2,Ja(e,E,S,d,h,R,o,a)?M=R:D=R;D>g&&(l.x=E,l.y=S,g=D,m=!0)}}!m&&!n&&(F=Math.abs(x-b+A-_),E=(b+x)/2,S=(_+A)/2,F>=v&&!P1(E,S,h,d,i,s)&&!Ja(e,E,S,d,h,d,o,null)&&(v=F,l.x=E,l.y=S,y=!0))}return m||y?(E=h/2,S=d/2,o.setRange(e(l.x-E),e(l.y-S),e(l.x+E),e(l.y+S)),l.align="center",l.baseline="middle",!0):!1}}const $se=["right","center","left"],Fse=["bottom","middle","top"];function Dse(e,t,n,r){const i=e.width,s=e.height,o=t[0],a=t[1],u=r.length;return function(l){const c=l.boundary,f=l.datum.fontSize;if(c[2]<0||c[5]<0||c[0]>i||c[3]>s)return!1;let d=l.textWidth??0,h,p,g,m,y,v,b,x,_,A,E,S,k,$,D;for(let M=0;M>>2&3)-1,g=h===0&&p===0||r[M]<0,m=h&&p?Math.SQRT1_2:1,y=r[M]<0?-1:1,v=c[1+h]+r[M]*h*m,E=c[4+p]+y*f*p/2+r[M]*p*m,x=E-f/2,_=E+f/2,S=e(v),$=e(x),D=e(_),!d)if(FD(S,S,$,D,o,a,v,v,x,_,c,g))d=pi.width(l.datum,l.datum.text);else continue;if(A=v+y*d*h/2,v=A-d/2,b=A+d/2,S=e(v),k=e(b),FD(S,k,$,D,o,a,v,b,x,_,c,g))return l.x=h?h*y<0?b:v:A,l.y=p?p*y<0?_:x:E,l.align=$se[h*y+1],l.baseline=Fse[p*y+1],o.setRange(S,$,k,D),!0}return!1}}function FD(e,t,n,r,i,s,o,a,u,l,c,f){return!(i.outOfBounds(e,n,t,r)||(f&&s||i).getRange(e,n,t,r))}const R2=0,T2=4,N2=8,O2=0,L2=1,I2=2,Mse={"top-left":R2+O2,top:R2+L2,"top-right":R2+I2,left:T2+O2,middle:T2+L2,right:T2+I2,"bottom-left":N2+O2,bottom:N2+L2,"bottom-right":N2+I2},Rse={naive:Ese,"reduced-search":Ase,floodfill:Cse};function Tse(e,t,n,r,i,s,o,a,u,l,c){if(!e.length)return e;const f=Math.max(r.length,i.length),d=Nse(r,f),h=Ose(i,f),p=Lse(e[0].datum),g=p==="group"&&e[0].datum.items[u].marktype,m=g==="area",y=Ise(p,g,a,u),v=l===null||l===1/0,b=m&&c==="naive";let x=-1,_=-1;const A=e.map($=>{const D=v?pi.width($,$.text):void 0;return x=Math.max(x,D),_=Math.max(_,$.fontSize),{datum:$,opacity:0,x:void 0,y:void 0,align:void 0,baseline:void 0,boundary:y($),textWidth:D}});l=l===null||l===1/0?Math.max(x,_)+Math.max(...r):l;const E=wse(t[0],t[1],l);let S;if(!b){n&&A.sort((M,R)=>n(M.datum,R.datum));let $=!1;for(let M=0;MM.datum);S=s.length||D?bse(E,D||[],s,$,m):vse(E,o&&A)}const k=m?Rse[c](E,S,o,u):Dse(E,S,h,d);return A.forEach($=>$.opacity=+k($)),A}function Nse(e,t){const n=new Float64Array(t),r=e.length;for(let i=0;i[s.x,s.x,s.x,s.y,s.y,s.y];return e?e==="line"||e==="area"?s=>i(s.datum):t==="line"?s=>{const o=s.datum.items[r].items;return i(o.length?o[n==="start"?0:o.length-1]:{x:NaN,y:NaN})}:s=>{const o=s.datum.bounds;return[o.x1,(o.x1+o.x2)/2,o.x2,o.y1,(o.y1+o.y2)/2,o.y2]}:i}const Ew=["x","y","opacity","align","baseline"],BL=["top-left","left","bottom-left","top","bottom","top-right","right","bottom-right"];function Zk(e){G.call(this,null,e)}Zk.Definition={type:"Label",metadata:{modifies:!0},params:[{name:"size",type:"number",array:!0,length:2,required:!0},{name:"sort",type:"compare"},{name:"anchor",type:"string",array:!0,default:BL},{name:"offset",type:"number",array:!0,default:[1]},{name:"padding",type:"number",default:0,null:!0},{name:"lineAnchor",type:"string",values:["start","end"],default:"end"},{name:"markIndex",type:"number",default:0},{name:"avoidBaseMark",type:"boolean",default:!0},{name:"avoidMarks",type:"data",array:!0},{name:"method",type:"string",default:"naive"},{name:"as",type:"string",array:!0,length:Ew.length,default:Ew}]};he(Zk,G,{transform(e,t){function n(s){const o=e[s];return He(o)&&t.modified(o.fields)}const r=e.modified();if(!(r||t.changed(t.ADD_REM)||n("sort")))return;(!e.size||e.size.length!==2)&&X("Size parameter should be specified as a [width, height] array.");const i=e.as||Ew;return Tse(t.materialize(t.SOURCE).source||[],e.size,e.sort,ye(e.offset==null?1:e.offset),ye(e.anchor||BL),e.avoidMarks||[],e.avoidBaseMark!==!1,e.lineAnchor||"end",e.markIndex||0,e.padding===void 0?0:e.padding,e.method||"naive").forEach(s=>{const o=s.datum;o[i[0]]=s.x,o[i[1]]=s.y,o[i[2]]=s.opacity,o[i[3]]=s.align,o[i[4]]=s.baseline}),t.reflow(r).modifies(i)}});const Pse=Object.freeze(Object.defineProperty({__proto__:null,label:Zk},Symbol.toStringTag,{value:"Module"}));function zL(e,t){var n=[],r=function(c){return c(a)},i,s,o,a,u,l;if(t==null)n.push(e);else for(i={},s=0,o=e.length;s{YT(l,e.x,e.y,e.bandwidth||.3).forEach(c=>{const f={};for(let d=0;de==="poly"?t:e==="quad"?2:1;function Qk(e){G.call(this,null,e)}Qk.Definition={type:"Regression",metadata:{generates:!0},params:[{name:"x",type:"field",required:!0},{name:"y",type:"field",required:!0},{name:"groupby",type:"field",array:!0},{name:"method",type:"string",default:"linear",values:Object.keys(Aw)},{name:"order",type:"number",default:3},{name:"extent",type:"number",array:!0,length:2},{name:"params",type:"boolean",default:!1},{name:"as",type:"string",array:!0}]};he(Qk,G,{transform(e,t){const n=t.fork(t.NO_SOURCE|t.NO_FIELDS);if(!this.value||t.changed()||e.modified()){const r=t.materialize(t.SOURCE).source,i=zL(r,e.groupby),s=(e.groupby||[]).map(en),o=e.method||"linear",a=e.order==null?3:e.order,u=Bse(o,a),l=e.as||[en(e.x),en(e.y)],c=Aw[o],f=[];let d=e.extent;be(Aw,o)||X("Invalid regression method: "+o),d!=null&&o==="log"&&d[0]<=0&&(t.dataflow.warn("Ignoring extent with values <= 0 for log regression."),d=null),i.forEach(h=>{if(h.length<=u){t.dataflow.warn("Skipping regression with more parameters than data points.");return}const g=c(h,e.x,e.y,a);if(e.params){f.push(gt({keys:h.dims,coef:g.coef,rSquared:g.rSquared}));return}const m=d||mo(h,e.x),y=v=>{const b={};for(let x=0;xy([v,g.predict(v)])):By(g.predict,m,25,200).forEach(y)}),this.value&&(n.rem=this.value),this.value=n.add=n.source=f}return n}});const zse=Object.freeze(Object.defineProperty({__proto__:null,loess:Jk,regression:Qk},Symbol.toStringTag,{value:"Module"})),ua=11102230246251565e-32,er=134217729,jse=(3+8*ua)*ua;function P2(e,t,n,r,i){let s,o,a,u,l=t[0],c=r[0],f=0,d=0;c>l==c>-l?(s=l,l=t[++f]):(s=c,c=r[++d]);let h=0;if(fl==c>-l?(o=l+s,a=s-(o-l),l=t[++f]):(o=c+s,a=s-(o-c),c=r[++d]),s=o,a!==0&&(i[h++]=a);fl==c>-l?(o=s+l,u=o-s,a=s-(o-u)+(l-u),l=t[++f]):(o=s+c,u=o-s,a=s-(o-u)+(c-u),c=r[++d]),s=o,a!==0&&(i[h++]=a);for(;f=F||-R>=F||(f=e-k,a=e-(k+f)+(f-i),f=n-$,l=n-($+f)+(f-i),f=t-D,u=t-(D+f)+(f-s),f=r-M,c=r-(M+f)+(f-s),a===0&&u===0&&l===0&&c===0)||(F=Hse*o+jse*Math.abs(R),R+=k*c+M*a-(D*l+$*u),R>=F||-R>=F))return R;x=a*M,d=er*a,h=d-(d-a),p=a-h,d=er*M,g=d-(d-M),m=M-g,_=p*m-(x-h*g-p*g-h*m),A=u*$,d=er*u,h=d-(d-u),p=u-h,d=er*$,g=d-(d-$),m=$-g,E=p*m-(A-h*g-p*g-h*m),y=_-E,f=_-y,yr[0]=_-(y+f)+(f-E),v=x+y,f=v-x,b=x-(v-f)+(y-f),y=b-A,f=b-y,yr[1]=b-(y+f)+(f-A),S=v+y,f=S-v,yr[2]=v-(S-f)+(y-f),yr[3]=S;const C=P2(4,Uc,4,yr,DD);x=k*c,d=er*k,h=d-(d-k),p=k-h,d=er*c,g=d-(d-c),m=c-g,_=p*m-(x-h*g-p*g-h*m),A=D*l,d=er*D,h=d-(d-D),p=D-h,d=er*l,g=d-(d-l),m=l-g,E=p*m-(A-h*g-p*g-h*m),y=_-E,f=_-y,yr[0]=_-(y+f)+(f-E),v=x+y,f=v-x,b=x-(v-f)+(y-f),y=b-A,f=b-y,yr[1]=b-(y+f)+(f-A),S=v+y,f=S-v,yr[2]=v-(S-f)+(y-f),yr[3]=S;const T=P2(C,DD,4,yr,MD);x=a*c,d=er*a,h=d-(d-a),p=a-h,d=er*c,g=d-(d-c),m=c-g,_=p*m-(x-h*g-p*g-h*m),A=u*l,d=er*u,h=d-(d-u),p=u-h,d=er*l,g=d-(d-l),m=l-g,E=p*m-(A-h*g-p*g-h*m),y=_-E,f=_-y,yr[0]=_-(y+f)+(f-E),v=x+y,f=v-x,b=x-(v-f)+(y-f),y=b-A,f=b-y,yr[1]=b-(y+f)+(f-A),S=v+y,f=S-v,yr[2]=v-(S-f)+(y-f),yr[3]=S;const O=P2(T,MD,4,yr,RD);return RD[O-1]}function E0(e,t,n,r,i,s){const o=(t-s)*(n-i),a=(e-i)*(r-s),u=o-a,l=Math.abs(o+a);return Math.abs(u)>=qse*l?u:-Gse(e,t,n,r,i,s,l)}const TD=Math.pow(2,-52),A0=new Uint32Array(512);class B1{static from(t,n=Zse,r=Jse){const i=t.length,s=new Float64Array(i*2);for(let o=0;o>1;if(n>0&&typeof t[0]!="number")throw new Error("Expected coords to contain numbers.");this.coords=t;const r=Math.max(2*n-5,0);this._triangles=new Uint32Array(r*3),this._halfedges=new Int32Array(r*3),this._hashSize=Math.ceil(Math.sqrt(n)),this._hullPrev=new Uint32Array(n),this._hullNext=new Uint32Array(n),this._hullTri=new Uint32Array(n),this._hullHash=new Int32Array(this._hashSize),this._ids=new Uint32Array(n),this._dists=new Float64Array(n),this.update()}update(){const{coords:t,_hullPrev:n,_hullNext:r,_hullTri:i,_hullHash:s}=this,o=t.length>>1;let a=1/0,u=1/0,l=-1/0,c=-1/0;for(let k=0;kl&&(l=$),D>c&&(c=D),this._ids[k]=k}const f=(a+l)/2,d=(u+c)/2;let h,p,g;for(let k=0,$=1/0;k0&&(p=k,$=D)}let v=t[2*p],b=t[2*p+1],x=1/0;for(let k=0;kM&&(k[$++]=R,M=F)}this.hull=k.subarray(0,$),this.triangles=new Uint32Array(0),this.halfedges=new Uint32Array(0);return}if(E0(m,y,v,b,_,A)<0){const k=p,$=v,D=b;p=g,v=_,b=A,g=k,_=$,A=D}const E=Kse(m,y,v,b,_,A);this._cx=E.x,this._cy=E.y;for(let k=0;k0&&Math.abs(R-$)<=TD&&Math.abs(F-D)<=TD||($=R,D=F,M===h||M===p||M===g))continue;let C=0;for(let z=0,U=this._hashKey(R,F);z=0;)if(T=O,T===C){T=-1;break}if(T===-1)continue;let N=this._addTriangle(T,M,r[T],-1,-1,i[T]);i[M]=this._legalize(N+2),i[T]=N,S++;let L=r[T];for(;O=r[L],E0(R,F,t[2*L],t[2*L+1],t[2*O],t[2*O+1])<0;)N=this._addTriangle(L,M,O,i[M],-1,i[L]),i[M]=this._legalize(N+2),r[L]=L,S--,L=O;if(T===C)for(;O=n[T],E0(R,F,t[2*O],t[2*O+1],t[2*T],t[2*T+1])<0;)N=this._addTriangle(O,M,T,-1,i[T],i[O]),this._legalize(N+2),i[O]=N,r[T]=T,S--,T=O;this._hullStart=n[M]=T,r[T]=n[L]=M,r[M]=L,s[this._hashKey(R,F)]=M,s[this._hashKey(t[2*T],t[2*T+1])]=T}this.hull=new Uint32Array(S);for(let k=0,$=this._hullStart;k0?3-n:1+n)/4}function B2(e,t,n,r){const i=e-n,s=t-r;return i*i+s*s}function Vse(e,t,n,r,i,s,o,a){const u=e-o,l=t-a,c=n-o,f=r-a,d=i-o,h=s-a,p=u*u+l*l,g=c*c+f*f,m=d*d+h*h;return u*(f*m-g*h)-l*(c*m-g*d)+p*(c*h-f*d)<0}function Xse(e,t,n,r,i,s){const o=n-e,a=r-t,u=i-e,l=s-t,c=o*o+a*a,f=u*u+l*l,d=.5/(o*l-a*u),h=(l*c-a*f)*d,p=(o*f-u*c)*d;return h*h+p*p}function Kse(e,t,n,r,i,s){const o=n-e,a=r-t,u=i-e,l=s-t,c=o*o+a*a,f=u*u+l*l,d=.5/(o*l-a*u),h=e+(l*c-a*f)*d,p=t+(o*f-u*c)*d;return{x:h,y:p}}function sf(e,t,n,r){if(r-n<=20)for(let i=n+1;i<=r;i++){const s=e[i],o=t[s];let a=i-1;for(;a>=n&&t[e[a]]>o;)e[a+1]=e[a--];e[a+1]=s}else{const i=n+r>>1;let s=n+1,o=r;ah(e,i,s),t[e[n]]>t[e[r]]&&ah(e,n,r),t[e[s]]>t[e[r]]&&ah(e,s,r),t[e[n]]>t[e[s]]&&ah(e,n,s);const a=e[s],u=t[a];for(;;){do s++;while(t[e[s]]u);if(o=o-n?(sf(e,t,s,r),sf(e,t,n,o-1)):(sf(e,t,n,o-1),sf(e,t,s,r))}}function ah(e,t,n){const r=e[t];e[t]=e[n],e[n]=r}function Zse(e){return e[0]}function Jse(e){return e[1]}const ND=1e-6;class bl{constructor(){this._x0=this._y0=this._x1=this._y1=null,this._=""}moveTo(t,n){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}`}closePath(){this._x1!==null&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")}lineTo(t,n){this._+=`L${this._x1=+t},${this._y1=+n}`}arc(t,n,r){t=+t,n=+n,r=+r;const i=t+r,s=n;if(r<0)throw new Error("negative radius");this._x1===null?this._+=`M${i},${s}`:(Math.abs(this._x1-i)>ND||Math.abs(this._y1-s)>ND)&&(this._+="L"+i+","+s),r&&(this._+=`A${r},${r},0,1,1,${t-r},${n}A${r},${r},0,1,1,${this._x1=i},${this._y1=s}`)}rect(t,n,r,i){this._+=`M${this._x0=this._x1=+t},${this._y0=this._y1=+n}h${+r}v${+i}h${-r}Z`}value(){return this._||null}}class Sw{constructor(){this._=[]}moveTo(t,n){this._.push([t,n])}closePath(){this._.push(this._[0].slice())}lineTo(t,n){this._.push([t,n])}value(){return this._.length?this._:null}}let Qse=class{constructor(t,[n,r,i,s]=[0,0,960,500]){if(!((i=+i)>=(n=+n))||!((s=+s)>=(r=+r)))throw new Error("invalid bounds");this.delaunay=t,this._circumcenters=new Float64Array(t.points.length*2),this.vectors=new Float64Array(t.points.length*2),this.xmax=i,this.xmin=n,this.ymax=s,this.ymin=r,this._init()}update(){return this.delaunay.update(),this._init(),this}_init(){const{delaunay:{points:t,hull:n,triangles:r},vectors:i}=this;let s,o;const a=this.circumcenters=this._circumcenters.subarray(0,r.length/3*2);for(let g=0,m=0,y=r.length,v,b;g1;)s-=2;for(let o=2;o0){if(n>=this.ymax)return null;(o=(this.ymax-n)/i)0){if(t>=this.xmax)return null;(o=(this.xmax-t)/r)this.xmax?2:0)|(nthis.ymax?8:0)}_simplify(t){if(t&&t.length>4){for(let n=0;n1e-10)return!1}return!0}function ioe(e,t,n){return[e+Math.sin(e+t)*n,t+Math.cos(e-t)*n]}class eC{static from(t,n=toe,r=noe,i){return new eC("length"in t?soe(t,n,r,i):Float64Array.from(ooe(t,n,r,i)))}constructor(t){this._delaunator=new B1(t),this.inedges=new Int32Array(t.length/2),this._hullIndex=new Int32Array(t.length/2),this.points=this._delaunator.coords,this._init()}update(){return this._delaunator.update(),this._init(),this}_init(){const t=this._delaunator,n=this.points;if(t.hull&&t.hull.length>2&&roe(t)){this.collinear=Int32Array.from({length:n.length/2},(d,h)=>h).sort((d,h)=>n[2*d]-n[2*h]||n[2*d+1]-n[2*h+1]);const u=this.collinear[0],l=this.collinear[this.collinear.length-1],c=[n[2*u],n[2*u+1],n[2*l],n[2*l+1]],f=1e-8*Math.hypot(c[3]-c[1],c[2]-c[0]);for(let d=0,h=n.length/2;d0&&(this.triangles=new Int32Array(3).fill(-1),this.halfedges=new Int32Array(3).fill(-1),this.triangles[0]=i[0],o[i[0]]=1,i.length===2&&(o[i[1]]=0,this.triangles[1]=i[1],this.triangles[2]=i[1]))}voronoi(t){return new Qse(this,t)}*neighbors(t){const{inedges:n,hull:r,_hullIndex:i,halfedges:s,triangles:o,collinear:a}=this;if(a){const f=a.indexOf(t);f>0&&(yield a[f-1]),f=0&&s!==r&&s!==i;)r=s;return s}_step(t,n,r){const{inedges:i,hull:s,_hullIndex:o,halfedges:a,triangles:u,points:l}=this;if(i[t]===-1||!l.length)return(t+1)%(l.length>>1);let c=t,f=qc(n-l[t*2],2)+qc(r-l[t*2+1],2);const d=i[t];let h=d;do{let p=u[h];const g=qc(n-l[p*2],2)+qc(r-l[p*2+1],2);if(g>5)*e[1]),m=null,y=l.length,v=-1,b=[],x=l.map(A=>({text:t(A),font:n(A),style:i(A),weight:s(A),rotate:o(A),size:~~(r(A)+1e-14),padding:a(A),xoff:0,yoff:0,x1:0,y1:0,x0:0,y0:0,hasText:!1,sprite:null,datum:A})).sort((A,E)=>E.size-A.size);++v>1,_.y=e[1]*(c()+.5)>>1,doe(p,_,x,v),_.hasText&&h(g,_,m)&&(b.push(_),m?poe(m,_):m=[{x:_.x+_.x0,y:_.y+_.y0},{x:_.x+_.x1,y:_.y+_.y1}],_.x-=e[0]>>1,_.y-=e[1]>>1)}return b};function d(p){p.width=p.height=1;var g=Math.sqrt(p.getContext("2d").getImageData(0,0,1,1).data.length>>2);p.width=(Bh<<5)/g,p.height=gm/g;var m=p.getContext("2d");return m.fillStyle=m.strokeStyle="red",m.textAlign="center",{context:m,ratio:g}}function h(p,g,m){for(var y=g.x,v=g.y,b=Math.hypot(e[0],e[1]),x=u(e),_=c()<.5?1:-1,A=-_,E,S,k;(E=x(A+=_))&&(S=~~E[0],k=~~E[1],!(Math.min(Math.abs(S),Math.abs(k))>=b));)if(g.x=y+S,g.y=v+k,!(g.x+g.x0<0||g.y+g.y0<0||g.x+g.x1>e[0]||g.y+g.y1>e[1])&&(!m||!hoe(g,p,e[0]))&&(!m||goe(g,m))){for(var $=g.sprite,D=g.width>>5,M=e[0]>>5,R=g.x-(D<<4),F=R&127,C=32-F,T=g.y1-g.y0,O=(g.y+g.y0)*M+(R>>5),N,L=0;L>>F:0);O+=M}return g.sprite=null,!0}return!1}return f.words=function(p){return arguments.length?(l=p,f):l},f.size=function(p){return arguments.length?(e=[+p[0],+p[1]],f):e},f.font=function(p){return arguments.length?(n=Vu(p),f):n},f.fontStyle=function(p){return arguments.length?(i=Vu(p),f):i},f.fontWeight=function(p){return arguments.length?(s=Vu(p),f):s},f.rotate=function(p){return arguments.length?(o=Vu(p),f):o},f.text=function(p){return arguments.length?(t=Vu(p),f):t},f.spiral=function(p){return arguments.length?(u=voe[p]||p,f):u},f.fontSize=function(p){return arguments.length?(r=Vu(p),f):r},f.padding=function(p){return arguments.length?(a=Vu(p),f):a},f.random=function(p){return arguments.length?(c=p,f):c},f}function doe(e,t,n,r){if(!t.sprite){var i=e.context,s=e.ratio;i.clearRect(0,0,(Bh<<5)/s,gm/s);var o=0,a=0,u=0,l=n.length,c,f,d,h,p;for(--r;++r>5<<5,d=~~Math.max(Math.abs(v+b),Math.abs(v-b))}else c=c+31>>5<<5;if(d>u&&(u=d),o+c>=Bh<<5&&(o=0,a+=u,u=0),a+d>=gm)break;i.translate((o+(c>>1))/s,(a+(d>>1))/s),t.rotate&&i.rotate(t.rotate*z2),i.fillText(t.text,0,0),t.padding&&(i.lineWidth=2*t.padding,i.strokeText(t.text,0,0)),i.restore(),t.width=c,t.height=d,t.xoff=o,t.yoff=a,t.x1=c>>1,t.y1=d>>1,t.x0=-t.x1,t.y0=-t.y1,t.hasText=!0,o+=c}for(var _=i.getImageData(0,0,(Bh<<5)/s,gm/s).data,A=[];--r>=0;)if(t=n[r],!!t.hasText){for(c=t.width,f=c>>5,d=t.y1-t.y0,h=0;h>5),$=_[(a+p)*(Bh<<5)+(o+h)<<2]?1<<31-h%32:0;A[k]|=$,E|=$}E?S=p:(t.y0++,d--,p--,a++)}t.y1=t.y0+S,t.sprite=A.slice(0,(t.y1-t.y0)*f)}}}function hoe(e,t,n){n>>=5;for(var r=e.sprite,i=e.width>>5,s=e.x-(i<<4),o=s&127,a=32-o,u=e.y1-e.y0,l=(e.y+e.y0)*n+(s>>5),c,f=0;f>>o:0))&t[l+d])return!0;l+=n}return!1}function poe(e,t){var n=e[0],r=e[1];t.x+t.x0r.x&&(r.x=t.x+t.x1),t.y+t.y1>r.y&&(r.y=t.y+t.y1)}function goe(e,t){return e.x+e.x1>t[0].x&&e.x+e.x0t[0].y&&e.y+e.y0g(p(m))}i.forEach(p=>{p[o[0]]=NaN,p[o[1]]=NaN,p[o[3]]=0});const l=s.words(i).text(e.text).size(e.size||[500,500]).padding(e.padding||1).spiral(e.spiral||"archimedean").rotate(e.rotate||0).font(e.font||"sans-serif").fontStyle(e.fontStyle||"normal").fontWeight(e.fontWeight||"normal").fontSize(a).random(Wi).layout(),c=s.size(),f=c[0]>>1,d=c[1]>>1,h=l.length;for(let p=0,g,m;pnew Uint8Array(e),woe=e=>new Uint16Array(e),rp=e=>new Uint32Array(e);function Eoe(){let e=8,t=[],n=rp(0),r=S0(0,e),i=S0(0,e);return{data:()=>t,seen:()=>n=Aoe(n,t.length),add(s){for(let o=0,a=t.length,u=s.length,l;ot.length,curr:()=>r,prev:()=>i,reset:s=>i[s]=r[s],all:()=>e<257?255:e<65537?65535:4294967295,set(s,o){r[s]|=o},clear(s,o){r[s]&=~o},resize(s,o){const a=r.length;(s>a||o>e)&&(e=Math.max(o,e),r=S0(s,e,r),i=S0(s,e))}}}function Aoe(e,t,n){return e.length>=t?e:(n=n||new e.constructor(t),n.set(e),n)}function S0(e,t,n){const r=(t<257?_oe:t<65537?woe:rp)(e);return n&&r.set(n),r}function OD(e,t,n){const r=1<0)for(m=0;me,size:()=>n}}function Soe(e,t){return e.sort.call(t,(n,r)=>{const i=e[n],s=e[r];return is?1:0}),NH(e,t)}function koe(e,t,n,r,i,s,o,a,u){let l=0,c=0,f;for(f=0;lt.modified(r.fields));return n?this.reinit(e,t):this.eval(e,t)}else return this.init(e,t)},init(e,t){const n=e.fields,r=e.query,i=this._indices={},s=this._dims=[],o=r.length;let a=0,u,l;for(;a{const s=i.remove(t,n);for(const o in r)r[o].reindex(s)})},update(e,t,n){const r=this._dims,i=e.query,s=t.stamp,o=r.length;let a=0,u,l;for(n.filters=0,l=0;lh)for(m=h,y=Math.min(f,p);mp)for(m=Math.max(f,p),y=d;mf)for(p=f,g=Math.min(l,d);pd)for(p=Math.max(l,d),g=c;pa[c]&n?null:o[c];return s.filter(s.MOD,l),i&i-1?(s.filter(s.ADD,c=>{const f=a[c]&n;return!f&&f^u[c]&n?o[c]:null}),s.filter(s.REM,c=>{const f=a[c]&n;return f&&!(f^(f^u[c]&n))?o[c]:null})):(s.filter(s.ADD,l),s.filter(s.REM,c=>(a[c]&n)===i?o[c]:null)),s.filter(s.SOURCE,c=>l(c._index))}});const Coe=Object.freeze(Object.defineProperty({__proto__:null,crossfilter:rC,resolvefilter:iC},Symbol.toStringTag,{value:"Module"})),$oe="RawCode",Jl="Literal",Foe="Property",Doe="Identifier",Moe="ArrayExpression",Roe="BinaryExpression",qL="CallExpression",Toe="ConditionalExpression",Noe="LogicalExpression",Ooe="MemberExpression",Loe="ObjectExpression",Ioe="UnaryExpression";function Ms(e){this.type=e}Ms.prototype.visit=function(e){let t,n,r;if(e(this))return 1;for(t=Poe(this),n=0,r=t.length;n";Mo[Ql]="Identifier";Mo[Lu]="Keyword";Mo[bv]="Null";Mo[xc]="Numeric";Mo[Pr]="Punctuator";Mo[Fg]="String";Mo[Boe]="RegularExpression";var zoe="ArrayExpression",joe="BinaryExpression",Uoe="CallExpression",qoe="ConditionalExpression",WL="Identifier",Woe="Literal",Hoe="LogicalExpression",Goe="MemberExpression",Yoe="ObjectExpression",Voe="Property",Xoe="UnaryExpression",Cn="Unexpected token %0",Koe="Unexpected number",Zoe="Unexpected string",Joe="Unexpected identifier",Qoe="Unexpected reserved word",eae="Unexpected end of input",kw="Invalid regular expression",j2="Invalid regular expression: missing /",HL="Octal literals are not allowed in strict mode.",tae="Duplicate data property in object literal not allowed in strict mode",Wn="ILLEGAL",$p="Disabled.",nae=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),rae=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0300-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u0483-\\u0487\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0610-\\u061A\\u0620-\\u0669\\u066E-\\u06D3\\u06D5-\\u06DC\\u06DF-\\u06E8\\u06EA-\\u06FC\\u06FF\\u0710-\\u074A\\u074D-\\u07B1\\u07C0-\\u07F5\\u07FA\\u0800-\\u082D\\u0840-\\u085B\\u08A0-\\u08B2\\u08E4-\\u0963\\u0966-\\u096F\\u0971-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE\\u09D7\\u09DC\\u09DD\\u09DF-\\u09E3\\u09E6-\\u09F1\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A59-\\u0A5C\\u0A5E\\u0A66-\\u0A75\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B5C\\u0B5D\\u0B5F-\\u0B63\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C00-\\u0C03\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C58\\u0C59\\u0C60-\\u0C63\\u0C66-\\u0C6F\\u0C81-\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDE\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D01-\\u0D03\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D57\\u0D60-\\u0D63\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DE6-\\u0DEF\\u0DF2\\u0DF3\\u0E01-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB9\\u0EBB-\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDC-\\u0EDF\\u0F00\\u0F18\\u0F19\\u0F20-\\u0F29\\u0F35\\u0F37\\u0F39\\u0F3E-\\u0F47\\u0F49-\\u0F6C\\u0F71-\\u0F84\\u0F86-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1714\\u1720-\\u1734\\u1740-\\u1753\\u1760-\\u176C\\u176E-\\u1770\\u1772\\u1773\\u1780-\\u17D3\\u17D7\\u17DC\\u17DD\\u17E0-\\u17E9\\u180B-\\u180D\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1920-\\u192B\\u1930-\\u193B\\u1946-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u19D0-\\u19D9\\u1A00-\\u1A1B\\u1A20-\\u1A5E\\u1A60-\\u1A7C\\u1A7F-\\u1A89\\u1A90-\\u1A99\\u1AA7\\u1AB0-\\u1ABD\\u1B00-\\u1B4B\\u1B50-\\u1B59\\u1B6B-\\u1B73\\u1B80-\\u1BF3\\u1C00-\\u1C37\\u1C40-\\u1C49\\u1C4D-\\u1C7D\\u1CD0-\\u1CD2\\u1CD4-\\u1CF6\\u1CF8\\u1CF9\\u1D00-\\u1DF5\\u1DFC-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u200C\\u200D\\u203F\\u2040\\u2054\\u2071\\u207F\\u2090-\\u209C\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D7F-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2DE0-\\u2DFF\\u2E2F\\u3005-\\u3007\\u3021-\\u302F\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u3099\\u309A\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA62B\\uA640-\\uA66F\\uA674-\\uA67D\\uA67F-\\uA69D\\uA69F-\\uA6F1\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA827\\uA840-\\uA873\\uA880-\\uA8C4\\uA8D0-\\uA8D9\\uA8E0-\\uA8F7\\uA8FB\\uA900-\\uA92D\\uA930-\\uA953\\uA960-\\uA97C\\uA980-\\uA9C0\\uA9CF-\\uA9D9\\uA9E0-\\uA9FE\\uAA00-\\uAA36\\uAA40-\\uAA4D\\uAA50-\\uAA59\\uAA60-\\uAA76\\uAA7A-\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEF\\uAAF2-\\uAAF6\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABEA\\uABEC\\uABED\\uABF0-\\uABF9\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE00-\\uFE0F\\uFE20-\\uFE2D\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF10-\\uFF19\\uFF21-\\uFF3A\\uFF3F\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]");function xv(e,t){if(!e)throw new Error("ASSERT: "+t)}function Vo(e){return e>=48&&e<=57}function sC(e){return"0123456789abcdefABCDEF".includes(e)}function ip(e){return"01234567".includes(e)}function iae(e){return e===32||e===9||e===11||e===12||e===160||e>=5760&&[5760,6158,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279].includes(e)}function Fp(e){return e===10||e===13||e===8232||e===8233}function Dg(e){return e===36||e===95||e>=65&&e<=90||e>=97&&e<=122||e===92||e>=128&&nae.test(String.fromCharCode(e))}function z1(e){return e===36||e===95||e>=65&&e<=90||e>=97&&e<=122||e>=48&&e<=57||e===92||e>=128&&rae.test(String.fromCharCode(e))}const sae={if:1,in:1,do:1,var:1,for:1,new:1,try:1,let:1,this:1,else:1,case:1,void:1,with:1,enum:1,while:1,break:1,catch:1,throw:1,const:1,yield:1,class:1,super:1,return:1,typeof:1,delete:1,switch:1,export:1,import:1,public:1,static:1,default:1,finally:1,extends:1,package:1,private:1,function:1,continue:1,debugger:1,interface:1,protected:1,instanceof:1,implements:1};function GL(){for(;K1114111||e!=="}")&<({},Cn,Wn),t<=65535?String.fromCharCode(t):(n=(t-65536>>10)+55296,r=(t-65536&1023)+56320,String.fromCharCode(n,r))}function YL(){var e,t;for(e=Se.charCodeAt(K++),t=String.fromCharCode(e),e===92&&(Se.charCodeAt(K)!==117&<({},Cn,Wn),++K,e=Cw("u"),(!e||e==="\\"||!Dg(e.charCodeAt(0)))&<({},Cn,Wn),t=e);K>>=")return K+=4,{type:Pr,value:o,start:e,end:K};if(s=o.substr(0,3),s===">>>"||s==="<<="||s===">>=")return K+=3,{type:Pr,value:s,start:e,end:K};if(i=s.substr(0,2),r===i[1]&&"+-<>&|".includes(r)||i==="=>")return K+=2,{type:Pr,value:i,start:e,end:K};if(i==="//"&<({},Cn,Wn),"<>=!+-*%&|^/".includes(r))return++K,{type:Pr,value:r,start:e,end:K};lt({},Cn,Wn)}function lae(e){let t="";for(;K{if(parseInt(i,16)<=1114111)return"x";lt({},kw)}).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"x"));try{new RegExp(n)}catch{lt({},kw)}try{return new RegExp(e,t)}catch{return null}}function hae(){var e,t,n,r,i;for(e=Se[K],xv(e==="/","Regular expression literal must start with a slash"),t=Se[K++],n=!1,r=!1;K=0&<({},kw,n),{value:n,literal:t}}function gae(){var e,t,n,r;return bt=null,GL(),e=K,t=hae(),n=pae(),r=dae(t.value,n.value),{literal:t.literal+n.literal,value:r,regex:{pattern:t.value,flags:n.value},start:e,end:K}}function mae(e){return e.type===Ql||e.type===Lu||e.type===vv||e.type===bv}function VL(){if(GL(),K>=lr)return{type:$g,start:K,end:K};const e=Se.charCodeAt(K);return Dg(e)?uae():e===40||e===41||e===59?U2():e===39||e===34?fae():e===46?Vo(Se.charCodeAt(K+1))?ID():U2():Vo(e)?ID():U2()}function jr(){const e=bt;return K=e.end,bt=VL(),K=e.end,e}function XL(){const e=K;bt=VL(),K=e}function yae(e){const t=new Ms(zoe);return t.elements=e,t}function PD(e,t,n){const r=new Ms(e==="||"||e==="&&"?Hoe:joe);return r.operator=e,r.left=t,r.right=n,r}function vae(e,t){const n=new Ms(Uoe);return n.callee=e,n.arguments=t,n}function bae(e,t,n){const r=new Ms(qoe);return r.test=e,r.consequent=t,r.alternate=n,r}function oC(e){const t=new Ms(WL);return t.name=e,t}function zh(e){const t=new Ms(Woe);return t.value=e.value,t.raw=Se.slice(e.start,e.end),e.regex&&(t.raw==="//"&&(t.raw="/(?:)/"),t.regex=e.regex),t}function BD(e,t,n){const r=new Ms(Goe);return r.computed=e==="[",r.object=t,r.property=n,r.computed||(n.member=!0),r}function xae(e){const t=new Ms(Yoe);return t.properties=e,t}function zD(e,t,n){const r=new Ms(Voe);return r.key=t,r.value=n,r.kind=e,r}function _ae(e,t){const n=new Ms(Xoe);return n.operator=e,n.argument=t,n.prefix=!0,n}function lt(e,t){var n,r=Array.prototype.slice.call(arguments,2),i=t.replace(/%(\d)/g,(s,o)=>(xv(o":case"<=":case">=":case"instanceof":case"in":t=7;break;case"<<":case">>":case">>>":t=8;break;case"+":case"-":t=9;break;case"*":case"/":case"%":t=11;break}return t}function Tae(){var e,t,n,r,i,s,o,a,u,l;if(e=bt,u=mm(),r=bt,i=qD(r),i===0)return u;for(r.prec=i,jr(),t=[e,bt],o=mm(),s=[u,r,o];(i=qD(bt))>0;){for(;s.length>2&&i<=s[s.length-2].prec;)o=s.pop(),a=s.pop().value,u=s.pop(),t.pop(),n=PD(a,u,o),s.push(n);r=jr(),r.prec=i,s.push(r),t.push(bt),n=mm(),s.push(n)}for(l=s.length-1,n=s[l],t.pop();l>1;)t.pop(),n=PD(s[l-1].value,s[l-2],n),l-=2;return n}function ec(){var e,t,n;return e=Tae(),Nt("?")&&(jr(),t=ec(),cr(":"),n=ec(),e=bae(e,t,n)),e}function aC(){const e=ec();if(Nt(","))throw new Error($p);return e}function KL(e){Se=e,K=0,lr=Se.length,bt=null,XL();const t=aC();if(bt.type!==$g)throw new Error("Unexpect token after expression.");return t}var ZL={NaN:"NaN",E:"Math.E",LN2:"Math.LN2",LN10:"Math.LN10",LOG2E:"Math.LOG2E",LOG10E:"Math.LOG10E",PI:"Math.PI",SQRT1_2:"Math.SQRT1_2",SQRT2:"Math.SQRT2",MIN_VALUE:"Number.MIN_VALUE",MAX_VALUE:"Number.MAX_VALUE"};function JL(e){function t(o,a,u,l){let c=e(a[0]);return u&&(c=u+"("+c+")",u.lastIndexOf("new ",0)===0&&(c="("+c+")")),c+"."+o+(l<0?"":l===0?"()":"("+a.slice(1).map(e).join(",")+")")}function n(o,a,u){return l=>t(o,l,a,u)}const r="new Date",i="String",s="RegExp";return{isNaN:"Number.isNaN",isFinite:"Number.isFinite",abs:"Math.abs",acos:"Math.acos",asin:"Math.asin",atan:"Math.atan",atan2:"Math.atan2",ceil:"Math.ceil",cos:"Math.cos",exp:"Math.exp",floor:"Math.floor",hypot:"Math.hypot",log:"Math.log",max:"Math.max",min:"Math.min",pow:"Math.pow",random:"Math.random",round:"Math.round",sin:"Math.sin",sqrt:"Math.sqrt",tan:"Math.tan",clamp:function(o){o.length<3&&X("Missing arguments to clamp function."),o.length>3&&X("Too many arguments to clamp function.");const a=o.map(e);return"Math.max("+a[1]+", Math.min("+a[2]+","+a[0]+"))"},now:"Date.now",utc:"Date.UTC",datetime:r,date:n("getDate",r,0),day:n("getDay",r,0),year:n("getFullYear",r,0),month:n("getMonth",r,0),hours:n("getHours",r,0),minutes:n("getMinutes",r,0),seconds:n("getSeconds",r,0),milliseconds:n("getMilliseconds",r,0),time:n("getTime",r,0),timezoneoffset:n("getTimezoneOffset",r,0),utcdate:n("getUTCDate",r,0),utcday:n("getUTCDay",r,0),utcyear:n("getUTCFullYear",r,0),utcmonth:n("getUTCMonth",r,0),utchours:n("getUTCHours",r,0),utcminutes:n("getUTCMinutes",r,0),utcseconds:n("getUTCSeconds",r,0),utcmilliseconds:n("getUTCMilliseconds",r,0),length:n("length",null,-1),parseFloat:"parseFloat",parseInt:"parseInt",upper:n("toUpperCase",i,0),lower:n("toLowerCase",i,0),substring:n("substring",i),split:n("split",i),trim:n("trim",i,0),btoa:"btoa",atob:"atob",regexp:s,test:n("test",s),if:function(o){o.length<3&&X("Missing arguments to if function."),o.length>3&&X("Too many arguments to if function.");const a=o.map(e);return"("+a[0]+"?"+a[1]+":"+a[2]+")"}}}function Nae(e){const t=e&&e.length-1;return t&&(e[0]==='"'&&e[t]==='"'||e[0]==="'"&&e[t]==="'")?e.slice(1,-1):e}function QL(e){e=e||{};const t=e.allowed?As(e.allowed):{},n=e.forbidden?As(e.forbidden):{},r=e.constants||ZL,i=(e.functions||JL)(f),s=e.globalvar,o=e.fieldvar,a=He(s)?s:p=>`${s}["${p}"]`;let u={},l={},c=0;function f(p){if(me(p))return p;const g=d[p.type];return g==null&&X("Unsupported type: "+p.type),g(p)}const d={Literal:p=>p.raw,Identifier:p=>{const g=p.name;return c>0?g:be(n,g)?X("Illegal identifier: "+g):be(r,g)?r[g]:be(t,g)?g:(u[g]=1,a(g))},MemberExpression:p=>{const g=!p.computed,m=f(p.object);g&&(c+=1);const y=f(p.property);return m===o&&(l[Nae(y)]=1),g&&(c-=1),m+(g?"."+y:"["+y+"]")},CallExpression:p=>{p.callee.type!=="Identifier"&&X("Illegal callee type: "+p.callee.type);const g=p.callee.name,m=p.arguments,y=be(i,g)&&i[g];return y||X("Unrecognized function: "+g),He(y)?y(m):y+"("+m.map(f).join(",")+")"},ArrayExpression:p=>"["+p.elements.map(f).join(",")+"]",BinaryExpression:p=>"("+f(p.left)+" "+p.operator+" "+f(p.right)+")",UnaryExpression:p=>"("+p.operator+f(p.argument)+")",ConditionalExpression:p=>"("+f(p.test)+"?"+f(p.consequent)+":"+f(p.alternate)+")",LogicalExpression:p=>"("+f(p.left)+p.operator+f(p.right)+")",ObjectExpression:p=>{for(const g of p.properties){const m=g.key.name;WE.has(m)&&X("Illegal property: "+m)}return"{"+p.properties.map(f).join(",")+"}"},Property:p=>{c+=1;const g=f(p.key);return c-=1,g+":"+f(p.value)}};function h(p){const g={code:f(p),globals:Object.keys(u),fields:Object.keys(l)};return u={},l={},g}return h.functions=i,h.constants=r,h}const WD=Symbol("vega_selection_getter");function eI(e){return(!e.getter||!e.getter[WD])&&(e.getter=Ui(e.field),e.getter[WD]=!0),e.getter}const uC="intersect",HD="union",Oae="vlMulti",Lae="vlPoint",GD="or",Iae="and",eo="_vgsid_",Dp=Ui(eo),Pae="E",Bae="R",zae="R-E",jae="R-LE",Uae="R-RE",qae="E-LT",Wae="E-LTE",Hae="E-GT",Gae="E-GTE",Yae="E-VALID",Vae="E-ONE",j1="index:unit";function YD(e,t){for(var n=t.fields,r=t.values,i=n.length,s=0,o,a;s=r[s])return!1}else if(a.type===Wae){if(o>r[s])return!1}else if(a.type===Hae){if(o<=r[s])return!1}else if(a.type===Gae){if(oWe(t.fields?{values:t.fields.map(r=>eI(r)(n.datum))}:{[eo]:Dp(n.datum)},t))}function eue(e,t,n,r){for(var i=this.context.data[e],s=i?i.values.value:[],o={},a={},u={},l,c,f,d,h,p,g,m,y,v,b=s.length,x=0,_,A;x(E[c[k].field]=S,E),{})))}else h=eo,p=Dp(l),g=o[h]||(o[h]={}),m=g[d]||(g[d]=[]),m.push(p),n&&(m=a[d]||(a[d]=[]),m.push({[eo]:p}));if(t=t||HD,o[eo]?o[eo]=W2[`${eo}_${t}`](...Object.values(o[eo])):Object.keys(o).forEach(E=>{o[E]=Object.keys(o[E]).map(S=>o[E][S]).reduce((S,k)=>S===void 0?k:W2[`${u[E]}_${t}`](S,k))}),s=Object.keys(a),n&&s.length){const E=r?Lae:Oae;o[E]=t===HD?{[GD]:s.reduce((S,k)=>(S.push(...a[k]),S),[])}:{[Iae]:s.map(S=>({[GD]:a[S]}))}}return o}var W2={[`${eo}_union`]:qH,[`${eo}_intersect`]:jH,E_union:function(e,t){if(!e.length)return t;for(var n=0,r=t.length;nt.includes(n)):t},R_union:function(e,t){var n=sr(t[0]),r=sr(t[1]);return n>r&&(n=t[1],r=t[0]),e.length?(e[0]>n&&(e[0]=n),e[1]r&&(n=t[1],r=t[0]),e.length?rr&&(e[1]=r),e):[n,r]}};const tue=":",nue="@";function lC(e,t,n,r){t[0].type!==Jl&&X("First argument to selection functions must be a string literal.");const i=t[0].value,s=t.length>=2&&st(t).value,o="unit",a=nue+o,u=tue+i;s===uC&&!be(r,a)&&(r[a]=n.getData(i).indataRef(n,o)),be(r,u)||(r[u]=n.getData(i).tuplesRef())}function nI(e){const t=this.context.data[e];return t?t.values.value:[]}function rue(e,t,n){const r=this.context.data[e]["index:"+t],i=r?r.value.get(n):void 0;return i&&i.count}function iue(e,t){const n=this.context.dataflow,r=this.context.data[e],i=r.input;return n.pulse(i,n.changeset().remove(yi).insert(t)),1}function sue(e,t,n){if(e){const r=this.context.dataflow,i=e.mark.source;r.pulse(i,r.changeset().encode(e,t))}return n!==void 0?n:e}const Mg=e=>function(t,n){const r=this.context.dataflow.locale();return t===null?"null":r[e](n)(t)},oue=Mg("format"),rI=Mg("timeFormat"),aue=Mg("utcFormat"),uue=Mg("timeParse"),lue=Mg("utcParse"),k0=new Date(2e3,0,1);function wv(e,t,n){return!Number.isInteger(e)||!Number.isInteger(t)?"":(k0.setYear(2e3),k0.setMonth(e),k0.setDate(t),rI.call(this,k0,n))}function cue(e){return wv.call(this,e,1,"%B")}function fue(e){return wv.call(this,e,1,"%b")}function due(e){return wv.call(this,0,2+e,"%A")}function hue(e){return wv.call(this,0,2+e,"%a")}const pue=":",gue="@",$w="%",iI="$";function cC(e,t,n,r){t[0].type!==Jl&&X("First argument to data functions must be a string literal.");const i=t[0].value,s=pue+i;if(!be(s,r))try{r[s]=n.getData(i).tuplesRef()}catch{}}function mue(e,t,n,r){t[0].type!==Jl&&X("First argument to indata must be a string literal."),t[1].type!==Jl&&X("Second argument to indata must be a string literal.");const i=t[0].value,s=t[1].value,o=gue+s;be(o,r)||(r[o]=n.getData(i).indataRef(n,s))}function Cr(e,t,n,r){if(t[0].type===Jl)VD(n,r,t[0].value);else for(e in n.scales)VD(n,r,e)}function VD(e,t,n){const r=$w+n;if(!be(t,r))try{t[r]=e.scaleRef(n)}catch{}}function Ro(e,t){if(me(e)){const n=t.scales[e];return n&&ZF(n.value)?n.value:void 0}else if(He(e))return ZF(e)?e:void 0}function yue(e,t,n){t.__bandwidth=i=>i&&i.bandwidth?i.bandwidth():0,n._bandwidth=Cr,n._range=Cr,n._scale=Cr;const r=i=>"_["+(i.type===Jl?ce($w+i.value):ce($w)+"+"+e(i))+"]";return{_bandwidth:i=>`this.__bandwidth(${r(i[0])})`,_range:i=>`${r(i[0])}.range()`,_scale:i=>`${r(i[0])}(${e(i[1])})`}}function fC(e,t){return function(n,r,i){if(n){const s=Ro(n,(i||this).context);return s&&s.path[e](r)}else return t(r)}}const vue=fC("area",Lte),bue=fC("bounds",zte),xue=fC("centroid",Gte);function _ue(e,t){const n=Ro(e,(t||this).context);return n&&n.scale()}function wue(e){const t=this.context.group;let n=!1;if(t)for(;e;){if(e===t){n=!0;break}e=e.mark.group}return n}function dC(e,t,n){try{e[t].apply(e,["EXPRESSION"].concat([].slice.call(n)))}catch(r){e.warn(r)}return n[n.length-1]}function Eue(){return dC(this.context.dataflow,"warn",arguments)}function Aue(){return dC(this.context.dataflow,"info",arguments)}function Sue(){return dC(this.context.dataflow,"debug",arguments)}function H2(e){const t=e/255;return t<=.03928?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Fw(e){const t=gu(e),n=H2(t.r),r=H2(t.g),i=H2(t.b);return .2126*n+.7152*r+.0722*i}function kue(e,t){const n=Fw(e),r=Fw(t),i=Math.max(n,r),s=Math.min(n,r);return(i+.05)/(s+.05)}function Cue(){const e=[].slice.call(arguments);return e.unshift({}),We(...e)}function sI(e,t){return e===t||e!==e&&t!==t?!0:ee(e)?ee(t)&&e.length===t.length?$ue(e,t):!1:ge(e)&&ge(t)?oI(e,t):!1}function $ue(e,t){for(let n=0,r=e.length;noI(e,t)}function Fue(e,t,n,r,i,s){const o=this.context.dataflow,a=this.context.data[e],u=a.input,l=o.stamp();let c=a.changes,f,d;if(o._trigger===!1||!(u.value.length||t||r))return 0;if((!c||c.stamp{a.modified=!0,o.pulse(u,c).run()},!0,1)),n&&(f=n===!0?yi:ee(n)||My(n)?n:XD(n),c.remove(f)),t&&c.insert(t),r&&(f=XD(r),u.value.some(f)?c.remove(f):c.insert(r)),i)for(d in s)c.modify(i,d,s[d]);return 1}function Due(e){const t=e.touches,n=t[0].clientX-t[1].clientX,r=t[0].clientY-t[1].clientY;return Math.hypot(n,r)}function Mue(e){const t=e.touches;return Math.atan2(t[0].clientY-t[1].clientY,t[0].clientX-t[1].clientX)}const KD={};function Rue(e,t){const n=KD[t]||(KD[t]=Ui(t));return ee(e)?e.map(n):n(e)}function Ev(e){return ee(e)||ArrayBuffer.isView(e)?e:null}function hC(e){return Ev(e)||(me(e)?e:null)}function Tue(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;rs.stop(l(c),e(c))),s}function Vue(e,t,n){const r=Ro(e,(n||this).context);return function(i){return r?r.path.context(i)(t):""}}function Xue(e){let t=null;return function(n){return n?xp(n,t=t||Gf(e)):e}}const aI=e=>e.data;function uI(e,t){const n=nI.call(t,e);return n.root&&n.root.lookup||{}}function Kue(e,t,n){const r=uI(e,this),i=r[t],s=r[n];return i&&s?i.path(s).map(aI):void 0}function Zue(e,t){const n=uI(e,this)[t];return n?n.ancestors().map(aI):void 0}const lI=()=>typeof window<"u"&&window||null;function Jue(){const e=lI();return e?e.screen:{}}function Que(){const e=lI();return e?[e.innerWidth,e.innerHeight]:[void 0,void 0]}function ele(){const e=this.context.dataflow,t=e.container&&e.container();return t?[t.clientWidth,t.clientHeight]:[void 0,void 0]}function cI(e,t,n){if(!e)return[];const[r,i]=e,s=new dn().set(r[0],r[1],i[0],i[1]),o=n||this.context.dataflow.scenegraph().root;return G7(o,s,tle(t))}function tle(e){let t=null;if(e){const n=ye(e.marktype),r=ye(e.markname);t=i=>(!n.length||n.some(s=>i.marktype===s))&&(!r.length||r.some(s=>i.name===s))}return t}function nle(e,t,n){let r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:5;e=ye(e);const i=e[e.length-1];return i===void 0||Math.hypot(i[0]-t,i[1]-n)>r?[...e,[t,n]]:e}function rle(e){return ye(e).reduce((t,n,r)=>{let[i,s]=n;return t+=r==0?`M ${i},${s} `:r===e.length-1?" Z":`L ${i},${s} `},"")}function ile(e,t,n){const{x:r,y:i,mark:s}=n,o=new dn().set(Number.MAX_SAFE_INTEGER,Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER,Number.MIN_SAFE_INTEGER);for(const[u,l]of t)uo.x2&&(o.x2=u),lo.y2&&(o.y2=l);return o.translate(r,i),cI([[o.x1,o.y1],[o.x2,o.y2]],e,s).filter(u=>sle(u.x,u.y,t))}function sle(e,t,n){let r=0;for(let i=0,s=n.length-1;it!=a>t&&e<(o-u)*(t-l)/(a-l)+u&&r++}return r&1}const Mp={random(){return Wi()},cumulativeNormal:Ly,cumulativeLogNormal:CA,cumulativeUniform:MA,densityNormal:wA,densityLogNormal:kA,densityUniform:DA,quantileNormal:Iy,quantileLogNormal:$A,quantileUniform:RA,sampleNormal:Oy,sampleLogNormal:SA,sampleUniform:FA,isArray:ee,isBoolean:Du,isDate:iu,isDefined(e){return e!==void 0},isNumber:ft,isObject:ge,isRegExp:QE,isString:me,isTuple:My,isValid(e){return e!=null&&e===e},toBoolean:tA,toDate(e){return nA(e)},toNumber:sr,toString:rA,indexof:Nue,join:Tue,lastindexof:Oue,replace:Iue,reverse:Pue,sort:Bue,slice:Lue,flush:mR,lerp:vR,merge:Cue,pad:_R,peek:st,pluck:Rue,span:ig,inrange:ef,truncate:wR,rgb:gu,lab:Ym,hcl:Vm,hsl:Hm,luminance:Fw,contrast:kue,sequence:ci,format:oue,utcFormat:aue,utcParse:lue,utcOffset:eT,utcSequence:rT,timeFormat:rI,timeParse:uue,timeOffset:QR,timeSequence:nT,timeUnitSpecifier:UR,monthFormat:cue,monthAbbrevFormat:fue,dayFormat:due,dayAbbrevFormat:hue,quarter:dR,utcquarter:hR,week:WR,utcweek:YR,dayofyear:qR,utcdayofyear:GR,warn:Eue,info:Aue,debug:Sue,extent(e){return mo(e)},inScope:wue,intersect:cI,clampRange:pR,pinchDistance:Due,pinchAngle:Mue,screen:Jue,containerSize:ele,windowSize:Que,bandspace:zue,setdata:iue,pathShape:Xue,panLinear:uR,panLog:lR,panPow:cR,panSymlog:fR,zoomLinear:VE,zoomLog:XE,zoomPow:Mm,zoomSymlog:KE,encode:sue,modify:Fue,lassoAppend:nle,lassoPath:rle,intersectLasso:ile},ole=["view","item","group","xy","x","y"],ale="event.vega.",fI="this.",pC={},dI={forbidden:["_"],allowed:["datum","event","item"],fieldvar:"datum",globalvar:e=>`_[${ce(iI+e)}]`,functions:ule,constants:ZL,visitors:pC},Dw=QL(dI);function ule(e){const t=JL(e);ole.forEach(n=>t[n]=ale+n);for(const n in Mp)t[n]=fI+n;return We(t,yue(e,Mp,pC)),t}function cn(e,t,n){return arguments.length===1?Mp[e]:(Mp[e]=t,n&&(pC[e]=n),Dw&&(Dw.functions[e]=fI+e),this)}cn("bandwidth",jue,Cr);cn("copy",Uue,Cr);cn("domain",que,Cr);cn("range",Hue,Cr);cn("invert",Wue,Cr);cn("scale",Gue,Cr);cn("gradient",Yue,Cr);cn("geoArea",vue,Cr);cn("geoBounds",bue,Cr);cn("geoCentroid",xue,Cr);cn("geoShape",Vue,Cr);cn("geoScale",_ue,Cr);cn("indata",rue,mue);cn("data",nI,cC);cn("treePath",Kue,cC);cn("treeAncestors",Zue,cC);cn("vlSelectionTest",Xae,lC);cn("vlSelectionIdTest",Jae,lC);cn("vlSelectionResolve",eue,lC);cn("vlSelectionTuples",Qae);function _o(e,t){const n={};let r;try{e=me(e)?e:ce(e)+"",r=KL(e)}catch{X("Expression parse error: "+e)}r.visit(s=>{if(s.type!==qL)return;const o=s.callee.name,a=dI.visitors[o];a&&a(o,s.arguments,t,n)});const i=Dw(r);return i.globals.forEach(s=>{const o=iI+s;!be(n,o)&&t.getSignal(s)&&(n[o]=t.signalRef(s))}),{$expr:We({code:i.code},t.options.ast?{ast:r}:null),$fields:i.fields,$params:n}}function lle(e){const t=this,n=e.operators||[];return e.background&&(t.background=e.background),e.eventConfig&&(t.eventConfig=e.eventConfig),e.locale&&(t.locale=e.locale),n.forEach(r=>t.parseOperator(r)),n.forEach(r=>t.parseOperatorParameters(r)),(e.streams||[]).forEach(r=>t.parseStream(r)),(e.updates||[]).forEach(r=>t.parseUpdate(r)),t.resolve()}const cle=As(["rule"]),ZD=As(["group","image","rect"]);function fle(e,t){let n="";return cle[t]||(e.x2&&(e.x?(ZD[t]&&(n+="if(o.x>o.x2)$=o.x,o.x=o.x2,o.x2=$;"),n+="o.width=o.x2-o.x;"):n+="o.x=o.x2-(o.width||0);"),e.xc&&(n+="o.x=o.xc-(o.width||0)/2;"),e.y2&&(e.y?(ZD[t]&&(n+="if(o.y>o.y2)$=o.y,o.y=o.y2,o.y2=$;"),n+="o.height=o.y2-o.y;"):n+="o.y=o.y2-(o.height||0);"),e.yc&&(n+="o.y=o.yc-(o.height||0)/2;")),n}function gC(e){return(e+"").toLowerCase()}function dle(e){return gC(e)==="operator"}function hle(e){return gC(e)==="collect"}function uh(e,t,n){n.endsWith(";")||(n="return("+n+");");const r=Function(...t.concat(n));return e&&e.functions?r.bind(e.functions):r}function ple(e,t,n,r){return`((u = ${e}) < (v = ${t}) || u == null) && v != null ? ${n} + : (u > v || v == null) && u != null ? ${r} + : ((v = v instanceof Date ? +v : v), (u = u instanceof Date ? +u : u)) !== u && v === v ? ${n} + : v !== v && u === u ? ${r} : `}var gle={operator:(e,t)=>uh(e,["_"],t.code),parameter:(e,t)=>uh(e,["datum","_"],t.code),event:(e,t)=>uh(e,["event"],t.code),handler:(e,t)=>{const n=`var datum=event.item&&event.item.datum;return ${t.code};`;return uh(e,["_","event"],n)},encode:(e,t)=>{const{marktype:n,channels:r}=t;let i="var o=item,datum=o.datum,m=0,$;";for(const s in r){const o="o["+ce(s)+"]";i+=`$=${r[s].code};if(${o}!==$)${o}=$,m=1;`}return i+=fle(r,n),i+="return m;",uh(e,["item","_"],i)},codegen:{get(e){const t=`[${e.map(ce).join("][")}]`,n=Function("_",`return _${t};`);return n.path=t,n},comparator(e,t){let n;const r=(s,o)=>{const a=t[o];let u,l;return s.path?(u=`a${s.path}`,l=`b${s.path}`):((n=n||{})["f"+o]=s,u=`this.f${o}(a)`,l=`this.f${o}(b)`),ple(u,l,-a,a)},i=Function("a","b","var u, v; return "+e.map(r).join("")+"0;");return n?i.bind(n):i}}};function mle(e){const t=this;dle(e.type)||!e.type?t.operator(e,e.update?t.operatorExpression(e.update):null):t.transform(e,e.type)}function yle(e){const t=this;if(e.params){const n=t.get(e.id);n||X("Invalid operator id: "+e.id),t.dataflow.connect(n,n.parameters(t.parseParameters(e.params),e.react,e.initonly))}}function vle(e,t){t=t||{};const n=this;for(const r in e){const i=e[r];t[r]=ee(i)?i.map(s=>JD(s,n,t)):JD(i,n,t)}return t}function JD(e,t,n){if(!e||!ge(e))return e;for(let r=0,i=QD.length,s;ri&&i.$tupleid?Te:i);return t.fn[n]||(t.fn[n]=ZE(r,e.$order,t.expr.codegen))}function Ale(e,t){const n=e.$encode,r={};for(const i in n){const s=n[i];r[i]=Qr(t.encodeExpression(s.$expr),s.$fields),r[i].output=s.$output}return r}function Sle(e,t){return t}function kle(e,t){const n=e.$subflow;return function(r,i,s){const o=t.fork().parse(n),a=o.get(n.operators[0].id),u=o.signals.parent;return u&&u.set(s),a.detachSubflow=()=>t.detach(o),a}}function Cle(){return Te}function $le(e){var t=this,n=e.filter!=null?t.eventExpression(e.filter):void 0,r=e.stream!=null?t.get(e.stream):void 0,i;e.source?r=t.events(e.source,e.type,n):e.merge&&(i=e.merge.map(s=>t.get(s)),r=i[0].merge.apply(i[0],i.slice(1))),e.between&&(i=e.between.map(s=>t.get(s)),r=r.between(i[0],i[1])),e.filter&&(r=r.filter(n)),e.throttle!=null&&(r=r.throttle(+e.throttle)),e.debounce!=null&&(r=r.debounce(+e.debounce)),r==null&&X("Invalid stream definition: "+JSON.stringify(e)),e.consume&&r.consume(!0),t.stream(e,r)}function Fle(e){var t=this,n=ge(n=e.source)?n.$ref:n,r=t.get(n),i=null,s=e.update,o=void 0;r||X("Source not defined: "+e.source),i=e.target&&e.target.$expr?t.eventExpression(e.target.$expr):t.get(e.target),s&&s.$expr&&(s.$params&&(o=t.parseParameters(s.$params)),s=t.handlerExpression(s.$expr)),t.update(e,r,i,s,o)}const Dle={skip:!0};function Mle(e){var t=this,n={};if(e.signals){var r=n.signals={};Object.keys(t.signals).forEach(s=>{const o=t.signals[s];e.signals(s,o)&&(r[s]=o.value)})}if(e.data){var i=n.data={};Object.keys(t.data).forEach(s=>{const o=t.data[s];e.data(s,o)&&(i[s]=o.input.value)})}return t.subcontext&&e.recurse!==!1&&(n.subcontext=t.subcontext.map(s=>s.getState(e))),n}function Rle(e){var t=this,n=t.dataflow,r=e.data,i=e.signals;Object.keys(i||{}).forEach(s=>{n.update(t.signals[s],i[s],Dle)}),Object.keys(r||{}).forEach(s=>{n.pulse(t.data[s].input,n.changeset().remove(yi).insert(r[s]))}),(e.subcontext||[]).forEach((s,o)=>{const a=t.subcontext[o];a&&a.setState(s)})}function hI(e,t,n,r){return new pI(e,t,n,r)}function pI(e,t,n,r){this.dataflow=e,this.transforms=t,this.events=e.events.bind(e),this.expr=r||gle,this.signals={},this.scales={},this.nodes={},this.data={},this.fn={},n&&(this.functions=Object.create(n),this.functions.context=this)}function eM(e){this.dataflow=e.dataflow,this.transforms=e.transforms,this.events=e.events,this.expr=e.expr,this.signals=Object.create(e.signals),this.scales=Object.create(e.scales),this.nodes=Object.create(e.nodes),this.data=Object.create(e.data),this.fn=Object.create(e.fn),e.functions&&(this.functions=Object.create(e.functions),this.functions.context=this)}pI.prototype=eM.prototype={fork(){const e=new eM(this);return(this.subcontext||(this.subcontext=[])).push(e),e},detach(e){this.subcontext=this.subcontext.filter(n=>n!==e);const t=Object.keys(e.nodes);for(const n of t)e.nodes[n]._targets=null;for(const n of t)e.nodes[n].detach();e.nodes=null},get(e){return this.nodes[e]},set(e,t){return this.nodes[e]=t},add(e,t){const n=this,r=n.dataflow,i=e.value;if(n.set(e.id,t),hle(e.type)&&i&&(i.$ingest?r.ingest(t,i.$ingest,i.$format):i.$request?r.preload(t,i.$request,i.$format):r.pulse(t,r.changeset().insert(i))),e.root&&(n.root=t),e.parent){let s=n.get(e.parent.$ref);s?(r.connect(s,[t]),t.targets().add(s)):(n.unresolved=n.unresolved||[]).push(()=>{s=n.get(e.parent.$ref),r.connect(s,[t]),t.targets().add(s)})}if(e.signal&&(n.signals[e.signal]=t),e.scale&&(n.scales[e.scale]=t),e.data)for(const s in e.data){const o=n.data[s]||(n.data[s]={});e.data[s].forEach(a=>o[a]=t)}},resolve(){return(this.unresolved||[]).forEach(e=>e()),delete this.unresolved,this},operator(e,t){this.add(e,this.dataflow.add(e.value,t))},transform(e,t){this.add(e,this.dataflow.add(this.transforms[gC(t)]))},stream(e,t){this.set(e.id,t)},update(e,t,n,r,i){this.dataflow.on(t,n,r,i,e.options)},operatorExpression(e){return this.expr.operator(this,e)},parameterExpression(e){return this.expr.parameter(this,e)},eventExpression(e){return this.expr.event(this,e)},handlerExpression(e){return this.expr.handler(this,e)},encodeExpression(e){return this.expr.encode(this,e)},parse:lle,parseOperator:mle,parseOperatorParameters:yle,parseParameters:vle,parseStream:$le,parseUpdate:Fle,getState:Mle,setState:Rle};function Tle(e){const t=e.container();t&&(t.setAttribute("role","graphics-document"),t.setAttribute("aria-roleDescription","visualization"),gI(t,e.description()))}function gI(e,t){e&&(t==null?e.removeAttribute("aria-label"):e.setAttribute("aria-label",t))}function Nle(e){e.add(null,t=>(e._background=t.bg,e._resize=1,t.bg),{bg:e._signals.background})}const G2="default";function Ole(e){const t=e._signals.cursor||(e._signals.cursor=e.add({user:G2,item:null}));e.on(e.events("view","pointermove"),t,(n,r)=>{const i=t.value,s=i?me(i)?i:i.user:G2,o=r.item&&r.item.cursor||null;return i&&s===i.user&&o==i.item?i:{user:s,item:o}}),e.add(null,function(n){let r=n.cursor,i=this.value;return me(r)||(i=r.item,r=r.user),Mw(e,r&&r!==G2?r:i||r),i},{cursor:t})}function Mw(e,t){const n=e.globalCursor()?typeof document<"u"&&document.body:e.container();if(n)return t==null?n.style.removeProperty("cursor"):n.style.cursor=t}function U1(e,t){var n=e._runtime.data;return be(n,t)||X("Unrecognized data set: "+t),n[t]}function Lle(e,t){return arguments.length<2?U1(this,e).values.value:Av.call(this,e,Mu().remove(yi).insert(t))}function Av(e,t){DT(t)||X("Second argument to changes must be a changeset.");const n=U1(this,e);return n.modified=!0,this.pulse(n.input,t)}function Ile(e,t){return Av.call(this,e,Mu().insert(t))}function Ple(e,t){return Av.call(this,e,Mu().remove(t))}function mI(e){var t=e.padding();return Math.max(0,e._viewWidth+t.left+t.right)}function yI(e){var t=e.padding();return Math.max(0,e._viewHeight+t.top+t.bottom)}function Sv(e){var t=e.padding(),n=e._origin;return[t.left+n[0],t.top+n[1]]}function Ble(e){var t=Sv(e),n=mI(e),r=yI(e);e._renderer.background(e.background()),e._renderer.resize(n,r,t),e._handler.origin(t),e._resizeListeners.forEach(i=>{try{i(n,r)}catch(s){e.error(s)}})}function zle(e,t,n){var r=e._renderer,i=r&&r.canvas(),s,o,a;return i&&(a=Sv(e),o=t.changedTouches?t.changedTouches[0]:t,s=cv(o,i),s[0]-=a[0],s[1]-=a[1]),t.dataflow=e,t.item=n,t.vega=jle(e,n,s),t}function jle(e,t,n){const r=t?t.mark.marktype==="group"?t:t.mark.group:null;function i(o){var a=r,u;if(o){for(u=t;u;u=u.mark.group)if(u.mark.name===o){a=u;break}}return a&&a.mark&&a.mark.interactive?a:{}}function s(o){if(!o)return n;me(o)&&(o=i(o));const a=n.slice();for(;o;)a[0]-=o.x||0,a[1]-=o.y||0,o=o.mark&&o.mark.group;return a}return{view:pr(e),item:pr(t||{}),group:i,xy:s,x:o=>s(o)[0],y:o=>s(o)[1]}}const tM="view",Ule="timer",qle="window",Wle={trap:!1};function Hle(e){const t=We({defaults:{}},e),n=(r,i)=>{i.forEach(s=>{ee(r[s])&&(r[s]=As(r[s]))})};return n(t.defaults,["prevent","allow"]),n(t,["view","window","selector"]),t}function vI(e,t,n,r){e._eventListeners.push({type:n,sources:ye(t),handler:r})}function Gle(e,t){var n=e._eventConfig.defaults,r=n.prevent,i=n.allow;return r===!1||i===!0?!1:r===!0||i===!1?!0:r?r[t]:i?!i[t]:e.preventDefault()}function C0(e,t,n){const r=e._eventConfig&&e._eventConfig[t];return r===!1||ge(r)&&!r[n]?(e.warn(`Blocked ${t} ${n} event listener.`),!1):!0}function Yle(e,t,n){var r=this,i=new Ny(n),s=function(l,c){r.runAsync(null,()=>{e===tM&&Gle(r,t)&&l.preventDefault(),i.receive(zle(r,l,c))})},o;if(e===Ule)C0(r,"timer",t)&&r.timer(s,t);else if(e===tM)C0(r,"view",t)&&r.addEventListener(t,s,Wle);else if(e===qle?C0(r,"window",t)&&typeof window<"u"&&(o=[window]):typeof document<"u"&&C0(r,"selector",t)&&(o=Array.from(document.querySelectorAll(e))),!o)r.warn("Can not resolve event source: "+e);else{for(var a=0,u=o.length;a=0;)t[i].stop();for(i=r.length;--i>=0;)for(o=r[i],s=o.sources.length;--s>=0;)o.sources[s].removeEventListener(o.type,o.handler);for(e&&e.call(this,this._handler,null,null,null),i=n.length;--i>=0;)u=n[i].type,a=n[i].handler,this._handler.off(u,a);return this}function gi(e,t,n){const r=document.createElement(e);for(const i in t)r.setAttribute(i,t[i]);return n!=null&&(r.textContent=n),r}const Kle="vega-bind",Zle="vega-bind-name",Jle="vega-bind-radio";function Qle(e,t,n){if(!t)return;const r=n.param;let i=n.state;return i||(i=n.state={elements:null,active:!1,set:null,update:o=>{o!=e.signal(r.signal)&&e.runAsync(null,()=>{i.source=!0,e.signal(r.signal,o)})}},r.debounce&&(i.update=JE(r.debounce,i.update))),(r.input==null&&r.element?ece:nce)(i,t,r,e),i.active||(e.on(e._signals[r.signal],null,()=>{i.source?i.source=!1:i.set(e.signal(r.signal))}),i.active=!0),i}function ece(e,t,n,r){const i=n.event||"input",s=()=>e.update(t.value);r.signal(n.signal,t.value),t.addEventListener(i,s),vI(r,t,i,s),e.set=o=>{t.value=o,t.dispatchEvent(tce(i))}}function tce(e){return typeof Event<"u"?new Event(e):{type:e}}function nce(e,t,n,r){const i=r.signal(n.signal),s=gi("div",{class:Kle}),o=n.input==="radio"?s:s.appendChild(gi("label"));o.appendChild(gi("span",{class:Zle},n.name||n.signal)),t.appendChild(s);let a=rce;switch(n.input){case"checkbox":a=ice;break;case"select":a=sce;break;case"radio":a=oce;break;case"range":a=ace;break}a(e,o,n,i)}function rce(e,t,n,r){const i=gi("input");for(const s in n)s!=="signal"&&s!=="element"&&i.setAttribute(s==="input"?"type":s,n[s]);i.setAttribute("name",n.signal),i.value=r,t.appendChild(i),i.addEventListener("input",()=>e.update(i.value)),e.elements=[i],e.set=s=>i.value=s}function ice(e,t,n,r){const i={type:"checkbox",name:n.signal};r&&(i.checked=!0);const s=gi("input",i);t.appendChild(s),s.addEventListener("change",()=>e.update(s.checked)),e.elements=[s],e.set=o=>s.checked=!!o||null}function sce(e,t,n,r){const i=gi("select",{name:n.signal}),s=n.labels||[];n.options.forEach((o,a)=>{const u={value:o};q1(o,r)&&(u.selected=!0),i.appendChild(gi("option",u,(s[a]||o)+""))}),t.appendChild(i),i.addEventListener("change",()=>{e.update(n.options[i.selectedIndex])}),e.elements=[i],e.set=o=>{for(let a=0,u=n.options.length;a{const u={type:"radio",name:n.signal,value:o};q1(o,r)&&(u.checked=!0);const l=gi("input",u);l.addEventListener("change",()=>e.update(o));const c=gi("label",{},(s[a]||o)+"");return c.prepend(l),i.appendChild(c),l}),e.set=o=>{const a=e.elements,u=a.length;for(let l=0;l{u.textContent=a.value,e.update(+a.value)};a.addEventListener("input",l),a.addEventListener("change",l),e.elements=[a],e.set=c=>{a.value=c,u.textContent=c}}function q1(e,t){return e===t||e+""==t+""}function bI(e,t,n,r,i,s){return t=t||new r(e.loader()),t.initialize(n,mI(e),yI(e),Sv(e),i,s).background(e.background())}function mC(e,t){return t?function(){try{t.apply(this,arguments)}catch(n){e.error(n)}}:null}function uce(e,t,n,r){const i=new r(e.loader(),mC(e,e.tooltip())).scene(e.scenegraph().root).initialize(n,Sv(e),e);return t&&t.handlers().forEach(s=>{i.on(s.type,s.handler)}),i}function lce(e,t){const n=this,r=n._renderType,i=n._eventConfig.bind,s=fv(r);e=n._el=e?Y2(n,e,!0):null,Tle(n),s||n.error("Unrecognized renderer type: "+r);const o=s.handler||Eg,a=e?s.renderer:s.headless;return n._renderer=a?bI(n,n._renderer,e,a):null,n._handler=uce(n,n._handler,e,o),n._redraw=!0,e&&i!=="none"&&(t=t?n._elBind=Y2(n,t,!0):e.appendChild(gi("form",{class:"vega-bindings"})),n._bind.forEach(u=>{u.param.element&&i!=="container"&&(u.element=Y2(n,u.param.element,!!u.param.input))}),n._bind.forEach(u=>{Qle(n,u.element||t,u)})),n}function Y2(e,t,n){if(typeof t=="string")if(typeof document<"u"){if(t=document.querySelector(t),!t)return e.error("Signal bind element not found: "+t),null}else return e.error("DOM document instance not found."),null;if(t&&n)try{t.textContent=""}catch(r){t=null,e.error(r)}return t}const lh=e=>+e||0,cce=e=>({top:e,bottom:e,left:e,right:e});function sM(e){return ge(e)?{top:lh(e.top),bottom:lh(e.bottom),left:lh(e.left),right:lh(e.right)}:cce(lh(e))}async function yC(e,t,n,r){const i=fv(t),s=i&&i.headless;return s||X("Unrecognized renderer type: "+t),await e.runAsync(),bI(e,null,null,s,n,r).renderAsync(e._scenegraph.root)}async function fce(e,t){e!==Va.Canvas&&e!==Va.SVG&&e!==Va.PNG&&X("Unrecognized image type: "+e);const n=await yC(this,e,t);return e===Va.SVG?dce(n.svg(),"image/svg+xml"):n.canvas().toDataURL("image/png")}function dce(e,t){const n=new Blob([e],{type:t});return window.URL.createObjectURL(n)}async function hce(e,t){return(await yC(this,Va.Canvas,e,t)).canvas()}async function pce(e){return(await yC(this,Va.SVG,e)).svg()}function gce(e,t,n){return hI(e,zf,Mp,n).parse(t)}function mce(e){var t=this._runtime.scales;return be(t,e)||X("Unrecognized scale or projection: "+e),t[e].value}var xI="width",_I="height",vC="padding",oM={skip:!0};function wI(e,t){var n=e.autosize(),r=e.padding();return t-(n&&n.contains===vC?r.left+r.right:0)}function EI(e,t){var n=e.autosize(),r=e.padding();return t-(n&&n.contains===vC?r.top+r.bottom:0)}function yce(e){var t=e._signals,n=t[xI],r=t[_I],i=t[vC];function s(){e._autosize=e._resize=1}e._resizeWidth=e.add(null,a=>{e._width=a.size,e._viewWidth=wI(e,a.size),s()},{size:n}),e._resizeHeight=e.add(null,a=>{e._height=a.size,e._viewHeight=EI(e,a.size),s()},{size:r});const o=e.add(null,s,{pad:i});e._resizeWidth.rank=n.rank+1,e._resizeHeight.rank=r.rank+1,o.rank=i.rank+1}function vce(e,t,n,r,i,s){this.runAfter(o=>{let a=0;o._autosize=0,o.width()!==n&&(a=1,o.signal(xI,n,oM),o._resizeWidth.skip(!0)),o.height()!==r&&(a=1,o.signal(_I,r,oM),o._resizeHeight.skip(!0)),o._viewWidth!==e&&(o._resize=1,o._viewWidth=e),o._viewHeight!==t&&(o._resize=1,o._viewHeight=t),(o._origin[0]!==i[0]||o._origin[1]!==i[1])&&(o._resize=1,o._origin=i),a&&o.run("enter"),s&&o.runAfter(u=>u.resize())},!1,1)}function bce(e){return this._runtime.getState(e||{data:xce,signals:_ce,recurse:!0})}function xce(e,t){return t.modified&&ee(t.input.value)&&!e.startsWith("_:vega:_")}function _ce(e,t){return!(e==="parent"||t instanceof zf.proxy)}function wce(e){return this.runAsync(null,t=>{t._trigger=!1,t._runtime.setState(e)},t=>{t._trigger=!0}),this}function Ece(e,t){function n(r){e({timestamp:Date.now(),elapsed:r})}this._timers.push(Yre(n,t))}function Ace(e,t,n,r){const i=e.element();i&&i.setAttribute("title",Sce(r))}function Sce(e){return e==null?"":ee(e)?AI(e):ge(e)&&!iu(e)?kce(e):e+""}function kce(e){return Object.keys(e).map(t=>{const n=e[t];return t+": "+(ee(n)?AI(n):SI(n))}).join(` +`)}function AI(e){return"["+e.map(SI).join(", ")+"]"}function SI(e){return ee(e)?"[…]":ge(e)&&!iu(e)?"{…}":e}function Cce(){if(this.renderer()==="canvas"&&this._renderer._canvas){let e=null;const t=()=>{e!=null&&e();const n=matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);n.addEventListener("change",t),e=()=>{n.removeEventListener("change",t)},this._renderer._canvas.getContext("2d").pixelRatio=window.devicePixelRatio||1,this._redraw=!0,this._resize=1,this.resize().runAsync()};t()}}function kI(e,t){const n=this;if(t=t||{},lf.call(n),t.loader&&n.loader(t.loader),t.logger&&n.logger(t.logger),t.logLevel!=null&&n.logLevel(t.logLevel),t.locale||e.locale){const s=We({},e.locale,t.locale);n.locale(xT(s.number,s.time))}n._el=null,n._elBind=null,n._renderType=t.renderer||Va.Canvas,n._scenegraph=new b7;const r=n._scenegraph.root;n._renderer=null,n._tooltip=t.tooltip||Ace,n._redraw=!0,n._handler=new Eg().scene(r),n._globalCursor=!1,n._preventDefault=!1,n._timers=[],n._eventListeners=[],n._resizeListeners=[],n._eventConfig=Hle(e.eventConfig),n.globalCursor(n._eventConfig.globalCursor);const i=gce(n,e,t.expr);n._runtime=i,n._signals=i.signals,n._bind=(e.bindings||[]).map(s=>({state:null,param:We({},s)})),i.root&&i.root.set(r),r.source=i.data.root.input,n.pulse(i.data.root.input,n.changeset().insert(r.items)),n._width=n.width(),n._height=n.height(),n._viewWidth=wI(n,n._width),n._viewHeight=EI(n,n._height),n._origin=[0,0],n._resize=0,n._autosize=1,yce(n),Nle(n),Ole(n),n.description(e.description),t.hover&&n.hover(),t.container&&n.initialize(t.container,t.bind),t.watchPixelRatio&&n._watchPixelRatio()}function $0(e,t){return be(e._signals,t)?e._signals[t]:X("Unrecognized signal name: "+ce(t))}function CI(e,t){const n=(e._targets||[]).filter(r=>r._update&&r._update.handler===t);return n.length?n[0]:null}function aM(e,t,n,r){let i=CI(n,r);return i||(i=mC(e,()=>r(t,n.value)),i.handler=r,e.on(n,null,i)),e}function uM(e,t,n){const r=CI(t,n);return r&&t._targets.remove(r),e}he(kI,lf,{async evaluate(e,t,n){if(await lf.prototype.evaluate.call(this,e,t),this._redraw||this._resize)try{this._renderer&&(this._resize&&(this._resize=0,Ble(this)),await this._renderer.renderAsync(this._scenegraph.root)),this._redraw=!1}catch(r){this.error(r)}return n&&Q0(this,n),this},dirty(e){this._redraw=!0,this._renderer&&this._renderer.dirty(e)},description(e){if(arguments.length){const t=e!=null?e+"":null;return t!==this._desc&&gI(this._el,this._desc=t),this}return this._desc},container(){return this._el},scenegraph(){return this._scenegraph},origin(){return this._origin.slice()},signal(e,t,n){const r=$0(this,e);return arguments.length===1?r.value:this.update(r,t,n)},width(e){return arguments.length?this.signal("width",e):this.signal("width")},height(e){return arguments.length?this.signal("height",e):this.signal("height")},padding(e){return arguments.length?this.signal("padding",sM(e)):sM(this.signal("padding"))},autosize(e){return arguments.length?this.signal("autosize",e):this.signal("autosize")},background(e){return arguments.length?this.signal("background",e):this.signal("background")},renderer(e){return arguments.length?(fv(e)||X("Unrecognized renderer type: "+e),e!==this._renderType&&(this._renderType=e,this._resetRenderer()),this):this._renderType},tooltip(e){return arguments.length?(e!==this._tooltip&&(this._tooltip=e,this._resetRenderer()),this):this._tooltip},loader(e){return arguments.length?(e!==this._loader&&(lf.prototype.loader.call(this,e),this._resetRenderer()),this):this._loader},resize(){return this._autosize=1,this.touch($0(this,"autosize"))},_resetRenderer(){this._renderer&&(this._renderer=null,this.initialize(this._el,this._elBind))},_resizeView:vce,addEventListener(e,t,n){let r=t;return n&&n.trap===!1||(r=mC(this,t),r.raw=t),this._handler.on(e,r),this},removeEventListener(e,t){for(var n=this._handler.handlers(e),r=n.length,i,s;--r>=0;)if(s=n[r].type,i=n[r].handler,e===s&&(t===i||t===i.raw)){this._handler.off(s,i);break}return this},addResizeListener(e){const t=this._resizeListeners;return t.includes(e)||t.push(e),this},removeResizeListener(e){var t=this._resizeListeners,n=t.indexOf(e);return n>=0&&t.splice(n,1),this},addSignalListener(e,t){return aM(this,e,$0(this,e),t)},removeSignalListener(e,t){return uM(this,$0(this,e),t)},addDataListener(e,t){return aM(this,e,U1(this,e).values,t)},removeDataListener(e,t){return uM(this,U1(this,e).values,t)},globalCursor(e){if(arguments.length){if(this._globalCursor!==!!e){const t=Mw(this,null);this._globalCursor=!!e,t&&Mw(this,t)}return this}else return this._globalCursor},preventDefault(e){return arguments.length?(this._preventDefault=e,this):this._preventDefault},timer:Ece,events:Yle,finalize:Xle,hover:Vle,data:Lle,change:Av,insert:Ile,remove:Ple,scale:mce,initialize:lce,toImageURL:fce,toCanvas:hce,toSVG:pce,getState:bce,setState:wce,_watchPixelRatio:Cce});const $ce="view",W1="[",H1="]",$I="{",FI="}",Fce=":",DI=",",Dce="@",Mce=">",Rce=/[[\]{}]/,Tce={"*":1,arc:1,area:1,group:1,image:1,line:1,path:1,rect:1,rule:1,shape:1,symbol:1,text:1,trail:1};let MI,RI;function Iu(e,t,n){return MI=t||$ce,RI=n||Tce,TI(e.trim()).map(Rw)}function Nce(e){return RI[e]}function sp(e,t,n,r,i){const s=e.length;let o=0,a;for(;t=0?--o:r&&r.indexOf(a)>=0&&++o}return t}function TI(e){const t=[],n=e.length;let r=0,i=0;for(;i' after between selector: "+e;r=r.map(Rw);const i=Rw(e.slice(1).trim());return i.between?{between:r,stream:i}:(i.between=r,i)}function Lce(e){const t={source:MI},n=[];let r=[0,0],i=0,s=0,o=e.length,a=0,u,l;if(e[o-1]===FI){if(a=e.lastIndexOf($I),a>=0){try{r=Ice(e.substring(a+1,o-1))}catch{throw"Invalid throttle specification: "+e}e=e.slice(0,a).trim(),o=e.length}else throw"Unmatched right brace: "+e;a=0}if(!o)throw e;if(e[0]===Dce&&(i=++a),u=sp(e,a,Fce),u1?(t.type=n[1],i?t.markname=n[0].slice(1):Nce(n[0])?t.marktype=n[0]:t.source=n[0]):t.type=n[0],t.type.slice(-1)==="!"&&(t.consume=!0,t.type=t.type.slice(0,-1)),l!=null&&(t.filter=l),r[0]&&(t.throttle=r[0]),r[1]&&(t.debounce=r[1]),t}function Ice(e){const t=e.split(DI);if(!e.length||t.length>2)throw e;return t.map(n=>{const r=+n;if(r!==r)throw e;return r})}function Pce(e){return ge(e)?e:{type:e||"pad"}}const ch=e=>+e||0,Bce=e=>({top:e,bottom:e,left:e,right:e});function zce(e){return ge(e)?e.signal?e:{top:ch(e.top),bottom:ch(e.bottom),left:ch(e.left),right:ch(e.right)}:Bce(ch(e))}const $n=e=>ge(e)&&!ee(e)?We({},e):{value:e};function lM(e,t,n,r){return n!=null?(ge(n)&&!ee(n)||ee(n)&&n.length&&ge(n[0])?e.update[t]=n:e[r||"enter"][t]={value:n},1):0}function Xn(e,t,n){for(const r in t)lM(e,r,t[r]);for(const r in n)lM(e,r,n[r],"update")}function Nd(e,t,n){for(const r in t)n&&be(n,r)||(e[r]=We(e[r]||{},t[r]));return e}function Zc(e,t){return t&&(t.enter&&t.enter[e]||t.update&&t.update[e])}const bC="mark",xC="frame",_C="scope",jce="axis",Uce="axis-domain",qce="axis-grid",Wce="axis-label",Hce="axis-tick",Gce="axis-title",Yce="legend",Vce="legend-band",Xce="legend-entry",Kce="legend-gradient",NI="legend-label",Zce="legend-symbol",Jce="legend-title",Qce="title",efe="title-text",tfe="title-subtitle";function nfe(e,t,n,r,i){const s={},o={};let a,u,l,c;u="lineBreak",t==="text"&&i[u]!=null&&!Zc(u,e)&&V2(s,u,i[u]),(n=="legend"||String(n).startsWith("axis"))&&(n=null),c=n===xC?i.group:n===bC?We({},i.mark,i[t]):null;for(u in c)l=Zc(u,e)||(u==="fill"||u==="stroke")&&(Zc("fill",e)||Zc("stroke",e)),l||V2(s,u,c[u]);ye(r).forEach(f=>{const d=i.style&&i.style[f];for(const h in d)Zc(h,e)||V2(s,h,d[h])}),e=We({},e);for(u in s)c=s[u],c.signal?(a=a||{})[u]=c:o[u]=c;return e.enter=We(o,e.enter),a&&(e.update=We(a,e.update)),e}function V2(e,t,n){e[t]=n&&n.signal?{signal:n.signal}:{value:n}}const OI=e=>me(e)?ce(e):e.signal?`(${e.signal})`:LI(e);function kv(e){if(e.gradient!=null)return ife(e);let t=e.signal?`(${e.signal})`:e.color?rfe(e.color):e.field!=null?LI(e.field):e.value!==void 0?ce(e.value):void 0;return e.scale!=null&&(t=sfe(e,t)),t===void 0&&(t=null),e.exponent!=null&&(t=`pow(${t},${ym(e.exponent)})`),e.mult!=null&&(t+=`*${ym(e.mult)}`),e.offset!=null&&(t+=`+${ym(e.offset)}`),e.round&&(t=`round(${t})`),t}const F0=(e,t,n,r)=>`(${e}(${[t,n,r].map(kv).join(",")})+'')`;function rfe(e){return e.c?F0("hcl",e.h,e.c,e.l):e.h||e.s?F0("hsl",e.h,e.s,e.l):e.l||e.a?F0("lab",e.l,e.a,e.b):e.r||e.g||e.b?F0("rgb",e.r,e.g,e.b):null}function ife(e){const t=[e.start,e.stop,e.count].map(n=>n==null?null:ce(n));for(;t.length&&st(t)==null;)t.pop();return t.unshift(OI(e.gradient)),`gradient(${t.join(",")})`}function ym(e){return ge(e)?"("+kv(e)+")":e}function LI(e){return II(ge(e)?e:{datum:e})}function II(e){let t,n,r;if(e.signal)t="datum",r=e.signal;else if(e.group||e.parent){for(n=Math.max(1,e.level||1),t="item";n-- >0;)t+=".mark.group";e.parent?(r=e.parent,t+=".datum"):r=e.group}else e.datum?(t="datum",r=e.datum):X("Invalid field reference: "+ce(e));return e.signal||(r=me(r)?ko(r).map(ce).join("]["):II(r)),t+"["+r+"]"}function sfe(e,t){const n=OI(e.scale);return e.range!=null?t=`lerp(_range(${n}), ${+e.range})`:(t!==void 0&&(t=`_scale(${n}, ${t})`),e.band&&(t=(t?t+"+":"")+`_bandwidth(${n})`+(+e.band==1?"":"*"+ym(e.band)),e.extra&&(t=`(datum.extra ? _scale(${n}, datum.extra.value) : ${t})`)),t==null&&(t="0")),t}function ofe(e){let t="";return e.forEach(n=>{const r=kv(n);t+=n.test?`(${n.test})?${r}:`:r}),st(t)===":"&&(t+="null"),t}function PI(e,t,n,r,i,s){const o={};s=s||{},s.encoders={$encode:o},e=nfe(e,t,n,r,i.config);for(const a in e)o[a]=afe(e[a],t,s,i);return s}function afe(e,t,n,r){const i={},s={};for(const o in e)e[o]!=null&&(i[o]=lfe(ufe(e[o]),r,n,s));return{$expr:{marktype:t,channels:i},$fields:Object.keys(s),$output:Object.keys(e)}}function ufe(e){return ee(e)?ofe(e):kv(e)}function lfe(e,t,n,r){const i=_o(e,t);return i.$fields.forEach(s=>r[s]=1),We(n,i.$params),i.$expr}const cfe="outer",ffe=["value","update","init","react","bind"];function cM(e,t){X(e+' for "outer" push: '+ce(t))}function BI(e,t){const n=e.name;if(e.push===cfe)t.signals[n]||cM("No prior signal definition",n),ffe.forEach(r=>{e[r]!==void 0&&cM("Invalid property ",r)});else{const r=t.addSignal(n,e.value);e.react===!1&&(r.react=!1),e.bind&&t.addBinding(n,e.bind)}}function Tw(e,t,n,r){this.id=-1,this.type=e,this.value=t,this.params=n,r&&(this.parent=r)}function Cv(e,t,n,r){return new Tw(e,t,n,r)}function G1(e,t){return Cv("operator",e,t)}function Re(e){const t={$ref:e.id};return e.id<0&&(e.refs=e.refs||[]).push(t),t}function Rp(e,t){return t?{$field:e,$name:t}:{$field:e}}const Nw=Rp("key");function fM(e,t){return{$compare:e,$order:t}}function dfe(e,t){const n={$key:e};return t&&(n.$flat=!0),n}const hfe="ascending",pfe="descending";function gfe(e){return ge(e)?(e.order===pfe?"-":"+")+$v(e.op,e.field):""}function $v(e,t){return(e&&e.signal?"$"+e.signal:e||"")+(e&&t?"_":"")+(t&&t.signal?"$"+t.signal:t||"")}const wC="scope",Ow="view";function vn(e){return e&&e.signal}function mfe(e){return e&&e.expr}function vm(e){if(vn(e))return!0;if(ge(e)){for(const t in e)if(vm(e[t]))return!0}return!1}function as(e,t){return e??t}function Dl(e){return e&&e.signal||e}const dM="timer";function Tp(e,t){return(e.merge?vfe:e.stream?bfe:e.type?xfe:X("Invalid stream specification: "+ce(e)))(e,t)}function yfe(e){return e===wC?Ow:e||Ow}function vfe(e,t){const n=e.merge.map(i=>Tp(i,t)),r=EC({merge:n},e,t);return t.addStream(r).id}function bfe(e,t){const n=Tp(e.stream,t),r=EC({stream:n},e,t);return t.addStream(r).id}function xfe(e,t){let n;e.type===dM?(n=t.event(dM,e.throttle),e={between:e.between,filter:e.filter}):n=t.event(yfe(e.source),e.type);const r=EC({stream:n},e,t);return Object.keys(r).length===1?n:t.addStream(r).id}function EC(e,t,n){let r=t.between;return r&&(r.length!==2&&X('Stream "between" parameter must have 2 entries: '+ce(t)),e.between=[Tp(r[0],n),Tp(r[1],n)]),r=t.filter?[].concat(t.filter):[],(t.marktype||t.markname||t.markrole)&&r.push(_fe(t.marktype,t.markname,t.markrole)),t.source===wC&&r.push("inScope(event.item)"),r.length&&(e.filter=_o("("+r.join(")&&(")+")",n).$expr),(r=t.throttle)!=null&&(e.throttle=+r),(r=t.debounce)!=null&&(e.debounce=+r),t.consume&&(e.consume=!0),e}function _fe(e,t,n){const r="event.item";return r+(e&&e!=="*"?"&&"+r+".mark.marktype==='"+e+"'":"")+(n?"&&"+r+".mark.role==='"+n+"'":"")+(t?"&&"+r+".mark.name==='"+t+"'":"")}const wfe={code:"_.$value",ast:{type:"Identifier",value:"value"}};function Efe(e,t,n){const r=e.encode,i={target:n};let s=e.events,o=e.update,a=[];s||X("Signal update missing events specification."),me(s)&&(s=Iu(s,t.isSubscope()?wC:Ow)),s=ye(s).filter(u=>u.signal||u.scale?(a.push(u),0):1),a.length>1&&(a=[Sfe(a)]),s.length&&a.push(s.length>1?{merge:s}:s[0]),r!=null&&(o&&X("Signal encode and update are mutually exclusive."),o="encode(item(),"+ce(r)+")"),i.update=me(o)?_o(o,t):o.expr!=null?_o(o.expr,t):o.value!=null?o.value:o.signal!=null?{$expr:wfe,$params:{$value:t.signalRef(o.signal)}}:X("Invalid signal update specification."),e.force&&(i.options={force:!0}),a.forEach(u=>t.addUpdate(We(Afe(u,t),i)))}function Afe(e,t){return{source:e.signal?t.signalRef(e.signal):e.scale?t.scaleRef(e.scale):Tp(e,t)}}function Sfe(e){return{signal:"["+e.map(t=>t.scale?'scale("'+t.scale+'")':t.signal)+"]"}}function kfe(e,t){const n=t.getSignal(e.name);let r=e.update;e.init&&(r?X("Signals can not include both init and update expressions."):(r=e.init,n.initonly=!0)),r&&(r=_o(r,t),n.update=r.$expr,n.params=r.$params),e.on&&e.on.forEach(i=>Efe(i,t,n.id))}const St=e=>(t,n,r)=>Cv(e,n,t||void 0,r),zI=St("aggregate"),Cfe=St("axisticks"),jI=St("bound"),Rs=St("collect"),hM=St("compare"),$fe=St("datajoin"),UI=St("encode"),Ffe=St("expression"),Dfe=St("facet"),Mfe=St("field"),Rfe=St("key"),Tfe=St("legendentries"),Nfe=St("load"),Ofe=St("mark"),Lfe=St("multiextent"),Ife=St("multivalues"),Pfe=St("overlap"),Bfe=St("params"),qI=St("prefacet"),zfe=St("projection"),jfe=St("proxy"),Ufe=St("relay"),WI=St("render"),qfe=St("scale"),_c=St("sieve"),Wfe=St("sortitems"),HI=St("viewlayout"),Hfe=St("values");let Gfe=0;const GI={min:"min",max:"max",count:"sum"};function Yfe(e,t){const n=e.type||"linear";MO(n)||X("Unrecognized scale type: "+ce(n)),t.addScale(e.name,{type:n,domain:void 0})}function Vfe(e,t){const n=t.getScale(e.name).params;let r;n.domain=YI(e.domain,e,t),e.range!=null&&(n.range=XI(e,t,n)),e.interpolate!=null&&ide(e.interpolate,n),e.nice!=null&&(n.nice=rde(e.nice,t)),e.bins!=null&&(n.bins=nde(e.bins,t));for(r in e)be(n,r)||r==="name"||(n[r]=Ni(e[r],t))}function Ni(e,t){return ge(e)?e.signal?t.signalRef(e.signal):X("Unsupported object: "+ce(e)):e}function bm(e,t){return e.signal?t.signalRef(e.signal):e.map(n=>Ni(n,t))}function Fv(e){X("Can not find data set: "+ce(e))}function YI(e,t,n){if(!e){(t.domainMin!=null||t.domainMax!=null)&&X("No scale domain defined for domainMin/domainMax to override.");return}return e.signal?n.signalRef(e.signal):(ee(e)?Xfe:e.fields?Zfe:Kfe)(e,t,n)}function Xfe(e,t,n){return e.map(r=>Ni(r,n))}function Kfe(e,t,n){const r=n.getData(e.data);return r||Fv(e.data),Hf(t.type)?r.valuesRef(n,e.field,VI(e.sort,!1)):NO(t.type)?r.domainRef(n,e.field):r.extentRef(n,e.field)}function Zfe(e,t,n){const r=e.data,i=e.fields.reduce((s,o)=>(o=me(o)?{data:r,field:o}:ee(o)||o.signal?Jfe(o,n):o,s.push(o),s),[]);return(Hf(t.type)?Qfe:NO(t.type)?ede:tde)(e,n,i)}function Jfe(e,t){const n="_:vega:_"+Gfe++,r=Rs({});if(ee(e))r.value={$ingest:e};else if(e.signal){const i="setdata("+ce(n)+","+e.signal+")";r.params.input=t.signalRef(i)}return t.addDataPipeline(n,[r,_c({})]),{data:n,field:"data"}}function Qfe(e,t,n){const r=VI(e.sort,!0);let i,s;const o=n.map(l=>{const c=t.getData(l.data);return c||Fv(l.data),c.countsRef(t,l.field,r)}),a={groupby:Nw,pulse:o};r&&(i=r.op||"count",s=r.field?$v(i,r.field):"count",a.ops=[GI[i]],a.fields=[t.fieldRef(s)],a.as=[s]),i=t.add(zI(a));const u=t.add(Rs({pulse:Re(i)}));return s=t.add(Hfe({field:Nw,sort:t.sortRef(r),pulse:Re(u)})),Re(s)}function VI(e,t){return e&&(!e.field&&!e.op?ge(e)?e.field="key":e={field:"key"}:!e.field&&e.op!=="count"?X("No field provided for sort aggregate op: "+e.op):t&&e.field&&e.op&&!GI[e.op]&&X("Multiple domain scales can not be sorted using "+e.op)),e}function ede(e,t,n){const r=n.map(i=>{const s=t.getData(i.data);return s||Fv(i.data),s.domainRef(t,i.field)});return Re(t.add(Ife({values:r})))}function tde(e,t,n){const r=n.map(i=>{const s=t.getData(i.data);return s||Fv(i.data),s.extentRef(t,i.field)});return Re(t.add(Lfe({extents:r})))}function nde(e,t){return e.signal||ee(e)?bm(e,t):t.objectProperty(e)}function rde(e,t){return e.signal?t.signalRef(e.signal):ge(e)?{interval:Ni(e.interval),step:Ni(e.step)}:Ni(e)}function ide(e,t){t.interpolate=Ni(e.type||e),e.gamma!=null&&(t.interpolateGamma=Ni(e.gamma))}function XI(e,t,n){const r=t.config.range;let i=e.range;if(i.signal)return t.signalRef(i.signal);if(me(i)){if(r&&be(r,i))return e=We({},e,{range:r[i]}),XI(e,t,n);i==="width"?i=[0,{signal:"width"}]:i==="height"?i=Hf(e.type)?[0,{signal:"height"}]:[{signal:"height"},0]:X("Unrecognized scale range value: "+ce(i))}else if(i.scheme){n.scheme=ee(i.scheme)?bm(i.scheme,t):Ni(i.scheme,t),i.extent&&(n.schemeExtent=bm(i.extent,t)),i.count&&(n.schemeCount=Ni(i.count,t));return}else if(i.step){n.rangeStep=Ni(i.step,t);return}else{if(Hf(e.type)&&!ee(i))return YI(i,e,t);ee(i)||X("Unsupported range type: "+ce(i))}return i.map(s=>(ee(s)?bm:Ni)(s,t))}function sde(e,t){const n=t.config.projection||{},r={};for(const i in e)i!=="name"&&(r[i]=Lw(e[i],i,t));for(const i in n)r[i]==null&&(r[i]=Lw(n[i],i,t));t.addProjection(e.name,r)}function Lw(e,t,n){return ee(e)?e.map(r=>Lw(r,t,n)):ge(e)?e.signal?n.signalRef(e.signal):t==="fit"?e:X("Unsupported parameter object: "+ce(e)):e}const Ts="top",Od="left",Ld="right",xu="bottom",KI="center",ode="vertical",ade="start",ude="middle",lde="end",Iw="index",AC="label",cde="offset",ed="perc",fde="perc2",Bi="value",Rg="guide-label",SC="guide-title",dde="group-title",hde="group-subtitle",pM="symbol",xm="gradient",Pw="discrete",Bw="size",pde="shape",gde="fill",mde="stroke",yde="strokeWidth",vde="strokeDash",bde="opacity",kC=[Bw,pde,gde,mde,yde,vde,bde],Tg={name:1,style:1,interactive:1},ut={value:0},zi={value:1},Dv="group",ZI="rect",CC="rule",xde="symbol",wc="text";function Np(e){return e.type=Dv,e.interactive=e.interactive||!1,e}function ei(e,t){const n=(r,i)=>as(e[r],as(t[r],i));return n.isVertical=r=>ode===as(e.direction,t.direction||(r?t.symbolDirection:t.gradientDirection)),n.gradientLength=()=>as(e.gradientLength,t.gradientLength||t.gradientWidth),n.gradientThickness=()=>as(e.gradientThickness,t.gradientThickness||t.gradientHeight),n.entryColumns=()=>as(e.columns,as(t.columns,+n.isVertical(!0))),n}function JI(e,t){const n=t&&(t.update&&t.update[e]||t.enter&&t.enter[e]);return n&&n.signal?n:n?n.value:null}function _de(e,t,n){const r=t.config.style[n];return r&&r[e]}function Mv(e,t,n){return`item.anchor === '${ade}' ? ${e} : item.anchor === '${lde}' ? ${t} : ${n}`}const $C=Mv(ce(Od),ce(Ld),ce(KI));function wde(e){const t=e("tickBand");let n=e("tickOffset"),r,i;return t?t.signal?(r={signal:`(${t.signal}) === 'extent' ? 1 : 0.5`},i={signal:`(${t.signal}) === 'extent'`},ge(n)||(n={signal:`(${t.signal}) === 'extent' ? 0 : ${n}`})):t==="extent"?(r=1,i=!0,n=0):(r=.5,i=!1):(r=e("bandPosition"),i=e("tickExtra")),{extra:i,band:r,offset:n}}function QI(e,t){return t?e?ge(e)?Object.assign({},e,{offset:QI(e.offset,t)}):{value:e,offset:t}:t:e}function _i(e,t){return t?(e.name=t.name,e.style=t.style||e.style,e.interactive=!!t.interactive,e.encode=Nd(e.encode,t,Tg)):e.interactive=!1,e}function Ede(e,t,n,r){const i=ei(e,n),s=i.isVertical(),o=i.gradientThickness(),a=i.gradientLength();let u,l,c,f,d;s?(l=[0,1],c=[0,0],f=o,d=a):(l=[0,0],c=[1,0],f=a,d=o);const h={enter:u={opacity:ut,x:ut,y:ut,width:$n(f),height:$n(d)},update:We({},u,{opacity:zi,fill:{gradient:t,start:l,stop:c}}),exit:{opacity:ut}};return Xn(h,{stroke:i("gradientStrokeColor"),strokeWidth:i("gradientStrokeWidth")},{opacity:i("gradientOpacity")}),_i({type:ZI,role:Kce,encode:h},r)}function Ade(e,t,n,r,i){const s=ei(e,n),o=s.isVertical(),a=s.gradientThickness(),u=s.gradientLength();let l,c,f,d,h="";o?(l="y",f="y2",c="x",d="width",h="1-"):(l="x",f="x2",c="y",d="height");const p={opacity:ut,fill:{scale:t,field:Bi}};p[l]={signal:h+"datum."+ed,mult:u},p[c]=ut,p[f]={signal:h+"datum."+fde,mult:u},p[d]=$n(a);const g={enter:p,update:We({},p,{opacity:zi}),exit:{opacity:ut}};return Xn(g,{stroke:s("gradientStrokeColor"),strokeWidth:s("gradientStrokeWidth")},{opacity:s("gradientOpacity")}),_i({type:ZI,role:Vce,key:Bi,from:i,encode:g},r)}const Sde=`datum.${ed}<=0?"${Od}":datum.${ed}>=1?"${Ld}":"${KI}"`,kde=`datum.${ed}<=0?"${xu}":datum.${ed}>=1?"${Ts}":"${ude}"`;function gM(e,t,n,r){const i=ei(e,t),s=i.isVertical(),o=$n(i.gradientThickness()),a=i.gradientLength();let u=i("labelOverlap"),l,c,f,d,h="";const p={enter:l={opacity:ut},update:c={opacity:zi,text:{field:AC}},exit:{opacity:ut}};return Xn(p,{fill:i("labelColor"),fillOpacity:i("labelOpacity"),font:i("labelFont"),fontSize:i("labelFontSize"),fontStyle:i("labelFontStyle"),fontWeight:i("labelFontWeight"),limit:as(e.labelLimit,t.gradientLabelLimit)}),s?(l.align={value:"left"},l.baseline=c.baseline={signal:kde},f="y",d="x",h="1-"):(l.align=c.align={signal:Sde},l.baseline={value:"top"},f="x",d="y"),l[f]=c[f]={signal:h+"datum."+ed,mult:a},l[d]=c[d]=o,o.offset=as(e.labelOffset,t.gradientLabelOffset)||0,u=u?{separation:i("labelSeparation"),method:u,order:"datum."+Iw}:void 0,_i({type:wc,role:NI,style:Rg,key:Bi,from:r,encode:p,overlap:u},n)}function Cde(e,t,n,r,i){const s=ei(e,t),o=n.entries,a=!!(o&&o.interactive),u=o?o.name:void 0,l=s("clipHeight"),c=s("symbolOffset"),f={data:"value"},d=`(${i}) ? datum.${cde} : datum.${Bw}`,h=l?$n(l):{field:Bw},p=`datum.${Iw}`,g=`max(1, ${i})`;let m,y,v,b,x;h.mult=.5,m={enter:y={opacity:ut,x:{signal:d,mult:.5,offset:c},y:h},update:v={opacity:zi,x:y.x,y:y.y},exit:{opacity:ut}};let _=null,A=null;e.fill||(_=t.symbolBaseFillColor,A=t.symbolBaseStrokeColor),Xn(m,{fill:s("symbolFillColor",_),shape:s("symbolType"),size:s("symbolSize"),stroke:s("symbolStrokeColor",A),strokeDash:s("symbolDash"),strokeDashOffset:s("symbolDashOffset"),strokeWidth:s("symbolStrokeWidth")},{opacity:s("symbolOpacity")}),kC.forEach($=>{e[$]&&(v[$]=y[$]={scale:e[$],field:Bi})});const E=_i({type:xde,role:Zce,key:Bi,from:f,clip:l?!0:void 0,encode:m},n.symbols),S=$n(c);S.offset=s("labelOffset"),m={enter:y={opacity:ut,x:{signal:d,offset:S},y:h},update:v={opacity:zi,text:{field:AC},x:y.x,y:y.y},exit:{opacity:ut}},Xn(m,{align:s("labelAlign"),baseline:s("labelBaseline"),fill:s("labelColor"),fillOpacity:s("labelOpacity"),font:s("labelFont"),fontSize:s("labelFontSize"),fontStyle:s("labelFontStyle"),fontWeight:s("labelFontWeight"),limit:s("labelLimit")});const k=_i({type:wc,role:NI,style:Rg,key:Bi,from:f,encode:m},n.labels);return m={enter:{noBound:{value:!l},width:ut,height:l?$n(l):ut,opacity:ut},exit:{opacity:ut},update:v={opacity:zi,row:{signal:null},column:{signal:null}}},s.isVertical(!0)?(b=`ceil(item.mark.items.length / ${g})`,v.row.signal=`${p}%${b}`,v.column.signal=`floor(${p} / ${b})`,x={field:["row",p]}):(v.row.signal=`floor(${p} / ${g})`,v.column.signal=`${p} % ${g}`,x={field:p}),v.column.signal=`(${i})?${v.column.signal}:${p}`,r={facet:{data:r,name:"value",groupby:Iw}},Np({role:_C,from:r,encode:Nd(m,o,Tg),marks:[E,k],name:u,interactive:a,sort:x})}function $de(e,t){const n=ei(e,t);return{align:n("gridAlign"),columns:n.entryColumns(),center:{row:!0,column:!1},padding:{row:n("rowPadding"),column:n("columnPadding")}}}const FC='item.orient === "left"',DC='item.orient === "right"',Rv=`(${FC} || ${DC})`,Fde=`datum.vgrad && ${Rv}`,Dde=Mv('"top"','"bottom"','"middle"'),Mde=Mv('"right"','"left"','"center"'),Rde=`datum.vgrad && ${DC} ? (${Mde}) : (${Rv} && !(datum.vgrad && ${FC})) ? "left" : ${$C}`,Tde=`item._anchor || (${Rv} ? "middle" : "start")`,Nde=`${Fde} ? (${FC} ? -90 : 90) : 0`,Ode=`${Rv} ? (datum.vgrad ? (${DC} ? "bottom" : "top") : ${Dde}) : "top"`;function Lde(e,t,n,r){const i=ei(e,t),s={enter:{opacity:ut},update:{opacity:zi,x:{field:{group:"padding"}},y:{field:{group:"padding"}}},exit:{opacity:ut}};return Xn(s,{orient:i("titleOrient"),_anchor:i("titleAnchor"),anchor:{signal:Tde},angle:{signal:Nde},align:{signal:Rde},baseline:{signal:Ode},text:e.title,fill:i("titleColor"),fillOpacity:i("titleOpacity"),font:i("titleFont"),fontSize:i("titleFontSize"),fontStyle:i("titleFontStyle"),fontWeight:i("titleFontWeight"),limit:i("titleLimit"),lineHeight:i("titleLineHeight")},{align:i("titleAlign"),baseline:i("titleBaseline")}),_i({type:wc,role:Jce,style:SC,from:r,encode:s},n)}function Ide(e,t){let n;return ge(e)&&(e.signal?n=e.signal:e.path?n="pathShape("+mM(e.path)+")":e.sphere&&(n="geoShape("+mM(e.sphere)+', {type: "Sphere"})')),n?t.signalRef(n):!!e}function mM(e){return ge(e)&&e.signal?e.signal:ce(e)}function eP(e){const t=e.role||"";return t.startsWith("axis")||t.startsWith("legend")||t.startsWith("title")?t:e.type===Dv?_C:t||bC}function Pde(e){return{marktype:e.type,name:e.name||void 0,role:e.role||eP(e),zindex:+e.zindex||void 0,aria:e.aria,description:e.description}}function Bde(e,t){return e&&e.signal?t.signalRef(e.signal):e!==!1}function MC(e,t){const n=TT(e.type);n||X("Unrecognized transform type: "+ce(e.type));const r=Cv(n.type.toLowerCase(),null,tP(n,e,t));return e.signal&&t.addSignal(e.signal,t.proxy(r)),r.metadata=n.metadata||{},r}function tP(e,t,n){const r={},i=e.params.length;for(let s=0;syM(e,s,n)):yM(e,i,n)}function yM(e,t,n){const r=e.type;if(vn(t))return bM(r)?X("Expression references can not be signals."):X2(r)?n.fieldRef(t):xM(r)?n.compareRef(t):n.signalRef(t.signal);{const i=e.expr||X2(r);return i&&qde(t)?n.exprRef(t.expr,t.as):i&&Wde(t)?Rp(t.field,t.as):bM(r)?_o(t,n):Hde(r)?Re(n.getData(t).values):X2(r)?Rp(t):xM(r)?n.compareRef(t):t}}function jde(e,t,n){return me(t.from)||X('Lookup "from" parameter must be a string literal.'),n.getData(t.from).lookupRef(n,t.key)}function Ude(e,t,n){const r=t[e.name];return e.array?(ee(r)||X("Expected an array of sub-parameters. Instead: "+ce(r)),r.map(i=>vM(e,i,n))):vM(e,r,n)}function vM(e,t,n){const r=e.params.length;let i;for(let o=0;oe&&e.expr,Wde=e=>e&&e.field,Hde=e=>e==="data",bM=e=>e==="expr",X2=e=>e==="field",xM=e=>e==="compare";function Gde(e,t,n){let r,i,s,o,a;return e?(r=e.facet)&&(t||X("Only group marks can be faceted."),r.field!=null?o=a=_m(r,n):(e.data?a=Re(n.getData(e.data).aggregate):(s=MC(We({type:"aggregate",groupby:ye(r.groupby)},r.aggregate),n),s.params.key=n.keyRef(r.groupby),s.params.pulse=_m(r,n),o=a=Re(n.add(s))),i=n.keyRef(r.groupby,!0))):o=Re(n.add(Rs(null,[{}]))),o||(o=_m(e,n)),{key:i,pulse:o,parent:a}}function _m(e,t){return e.$ref?e:e.data&&e.data.$ref?e.data:Re(t.getData(e.data).output)}function tc(e,t,n,r,i){this.scope=e,this.input=t,this.output=n,this.values=r,this.aggregate=i,this.index={}}tc.fromEntries=function(e,t){const n=t.length,r=t[n-1],i=t[n-2];let s=t[0],o=null,a=1;for(s&&s.type==="load"&&(s=t[1]),e.add(t[0]);af??"null").join(",")+"),0)",c=_o(l,t);u.update=c.$expr,u.params=c.$params}function Tv(e,t){const n=eP(e),r=e.type===Dv,i=e.from&&e.from.facet,s=e.overlap;let o=e.layout||n===_C||n===xC,a,u,l,c,f,d,h;const p=n===bC||o||i,g=Gde(e.from,r,t);u=t.add($fe({key:g.key||(e.key?Rp(e.key):void 0),pulse:g.pulse,clean:!r}));const m=Re(u);u=l=t.add(Rs({pulse:m})),u=t.add(Ofe({markdef:Pde(e),interactive:Bde(e.interactive,t),clip:Ide(e.clip,t),context:{$context:!0},groups:t.lookup(),parent:t.signals.parent?t.signalRef("parent"):null,index:t.markpath(),pulse:Re(u)}));const y=Re(u);u=c=t.add(UI(PI(e.encode,e.type,n,e.style,t,{mod:!1,pulse:y}))),u.params.parent=t.encode(),e.transform&&e.transform.forEach(A=>{const E=MC(A,t),S=E.metadata;(S.generates||S.changes)&&X("Mark transforms should not generate new data."),S.nomod||(c.params.mod=!0),E.params.pulse=Re(u),t.add(u=E)}),e.sort&&(u=t.add(Wfe({sort:t.compareRef(e.sort),pulse:Re(u)})));const v=Re(u);(i||o)&&(o=t.add(HI({layout:t.objectProperty(e.layout),legends:t.legends,mark:y,pulse:v})),d=Re(o));const b=t.add(jI({mark:y,pulse:d||v}));h=Re(b),r&&(p&&(a=t.operators,a.pop(),o&&a.pop()),t.pushState(v,d||h,m),i?Yde(e,t,g):p?Vde(e,t,g):t.parse(e),t.popState(),p&&(o&&a.push(o),a.push(b))),s&&(h=Xde(s,h,t));const x=t.add(WI({pulse:h})),_=t.add(_c({pulse:Re(x)},void 0,t.parent()));e.name!=null&&(f=e.name,t.addData(f,new tc(t,l,x,_)),e.on&&e.on.forEach(A=>{(A.insert||A.remove||A.toggle)&&X("Marks only support modify triggers."),rP(A,t,f)}))}function Xde(e,t,n){const r=e.method,i=e.bound,s=e.separation,o={separation:vn(s)?n.signalRef(s.signal):s,method:vn(r)?n.signalRef(r.signal):r,pulse:t};if(e.order&&(o.sort=n.compareRef({field:e.order})),i){const a=i.tolerance;o.boundTolerance=vn(a)?n.signalRef(a.signal):+a,o.boundScale=n.scaleRef(i.scale),o.boundOrient=i.orient}return Re(n.add(Pfe(o)))}function Kde(e,t){const n=t.config.legend,r=e.encode||{},i=ei(e,n),s=r.legend||{},o=s.name||void 0,a=s.interactive,u=s.style,l={};let c=0,f,d,h;kC.forEach(b=>e[b]?(l[b]=e[b],c=c||e[b]):0),c||X("Missing valid scale for legend.");const p=Zde(e,t.scaleType(c)),g={title:e.title!=null,scales:l,type:p,vgrad:p!=="symbol"&&i.isVertical()},m=Re(t.add(Rs(null,[g]))),y={enter:{x:{value:0},y:{value:0}}},v=Re(t.add(Tfe(d={type:p,scale:t.scaleRef(c),count:t.objectProperty(i("tickCount")),limit:t.property(i("symbolLimit")),values:t.objectProperty(e.values),minstep:t.property(e.tickMinStep),formatType:t.property(e.formatType),formatSpecifier:t.property(e.format)})));return p===xm?(h=[Ede(e,c,n,r.gradient),gM(e,n,r.labels,v)],d.count=d.count||t.signalRef(`max(2,2*floor((${Dl(i.gradientLength())})/100))`)):p===Pw?h=[Ade(e,c,n,r.gradient,v),gM(e,n,r.labels,v)]:(f=$de(e,n),h=[Cde(e,n,r,v,Dl(f.columns))],d.size=ehe(e,t,h[0].marks)),h=[Np({role:Xce,from:m,encode:y,marks:h,layout:f,interactive:a})],g.title&&h.push(Lde(e,n,r.title,m)),Tv(Np({role:Yce,from:m,encode:Nd(Qde(i,e,n),s,Tg),marks:h,aria:i("aria"),description:i("description"),zindex:i("zindex"),name:o,interactive:a,style:u}),t)}function Zde(e,t){let n=e.type||pM;return!e.type&&Jde(e)===1&&(e.fill||e.stroke)&&(n=RS(t)?xm:D_(t)?Pw:pM),n!==xm?n:D_(t)?Pw:xm}function Jde(e){return kC.reduce((t,n)=>t+(e[n]?1:0),0)}function Qde(e,t,n){const r={enter:{},update:{}};return Xn(r,{orient:e("orient"),offset:e("offset"),padding:e("padding"),titlePadding:e("titlePadding"),cornerRadius:e("cornerRadius"),fill:e("fillColor"),stroke:e("strokeColor"),strokeWidth:n.strokeWidth,strokeDash:n.strokeDash,x:e("legendX"),y:e("legendY"),format:t.format,formatType:t.formatType}),r}function ehe(e,t,n){const r=Dl(wM("size",e,n)),i=Dl(wM("strokeWidth",e,n)),s=Dl(the(n[1].encode,t,Rg));return _o(`max(ceil(sqrt(${r})+${i}),${s})`,t)}function wM(e,t,n){return t[e]?`scale("${t[e]}",datum)`:JI(e,n[0].encode)}function the(e,t,n){return JI("fontSize",e)||_de("fontSize",t,n)}const nhe=`item.orient==="${Od}"?-90:item.orient==="${Ld}"?90:0`;function rhe(e,t){e=me(e)?{text:e}:e;const n=ei(e,t.config.title),r=e.encode||{},i=r.group||{},s=i.name||void 0,o=i.interactive,a=i.style,u=[],l={},c=Re(t.add(Rs(null,[l])));return u.push(ohe(e,n,ihe(e),c)),e.subtitle&&u.push(ahe(e,n,r.subtitle,c)),Tv(Np({role:Qce,from:c,encode:she(n,i),marks:u,aria:n("aria"),description:n("description"),zindex:n("zindex"),name:s,interactive:o,style:a}),t)}function ihe(e){const t=e.encode;return t&&t.title||We({name:e.name,interactive:e.interactive,style:e.style},t)}function she(e,t){const n={enter:{},update:{}};return Xn(n,{orient:e("orient"),anchor:e("anchor"),align:{signal:$C},angle:{signal:nhe},limit:e("limit"),frame:e("frame"),offset:e("offset")||0,padding:e("subtitlePadding")}),Nd(n,t,Tg)}function ohe(e,t,n,r){const i={value:0},s=e.text,o={enter:{opacity:i},update:{opacity:{value:1}},exit:{opacity:i}};return Xn(o,{text:s,align:{signal:"item.mark.group.align"},angle:{signal:"item.mark.group.angle"},limit:{signal:"item.mark.group.limit"},baseline:"top",dx:t("dx"),dy:t("dy"),fill:t("color"),font:t("font"),fontSize:t("fontSize"),fontStyle:t("fontStyle"),fontWeight:t("fontWeight"),lineHeight:t("lineHeight")},{align:t("align"),angle:t("angle"),baseline:t("baseline")}),_i({type:wc,role:efe,style:dde,from:r,encode:o},n)}function ahe(e,t,n,r){const i={value:0},s=e.subtitle,o={enter:{opacity:i},update:{opacity:{value:1}},exit:{opacity:i}};return Xn(o,{text:s,align:{signal:"item.mark.group.align"},angle:{signal:"item.mark.group.angle"},limit:{signal:"item.mark.group.limit"},baseline:"top",dx:t("dx"),dy:t("dy"),fill:t("subtitleColor"),font:t("subtitleFont"),fontSize:t("subtitleFontSize"),fontStyle:t("subtitleFontStyle"),fontWeight:t("subtitleFontWeight"),lineHeight:t("subtitleLineHeight")},{align:t("align"),angle:t("angle"),baseline:t("baseline")}),_i({type:wc,role:tfe,style:hde,from:r,encode:o},n)}function uhe(e,t){const n=[];e.transform&&e.transform.forEach(r=>{n.push(MC(r,t))}),e.on&&e.on.forEach(r=>{rP(r,t,e.name)}),t.addDataPipeline(e.name,lhe(e,t,n))}function lhe(e,t,n){const r=[];let i=null,s=!1,o=!1,a,u,l,c,f;for(e.values?vn(e.values)||vm(e.format)?(r.push(EM(t,e)),r.push(i=Xu())):r.push(i=Xu({$ingest:e.values,$format:e.format})):e.url?vm(e.url)||vm(e.format)?(r.push(EM(t,e)),r.push(i=Xu())):r.push(i=Xu({$request:e.url,$format:e.format})):e.source&&(i=a=ye(e.source).map(d=>Re(t.getData(d).output)),r.push(null)),u=0,l=n.length;ue===xu||e===Ts,Nv=(e,t,n)=>vn(e)?hhe(e.signal,t,n):e===Od||e===Ts?t:n,Fn=(e,t,n)=>vn(e)?fhe(e.signal,t,n):iP(e)?t:n,xs=(e,t,n)=>vn(e)?dhe(e.signal,t,n):iP(e)?n:t,sP=(e,t,n)=>vn(e)?phe(e.signal,t,n):e===Ts?{value:t}:{value:n},che=(e,t,n)=>vn(e)?ghe(e.signal,t,n):e===Ld?{value:t}:{value:n},fhe=(e,t,n)=>oP(`${e} === '${Ts}' || ${e} === '${xu}'`,t,n),dhe=(e,t,n)=>oP(`${e} !== '${Ts}' && ${e} !== '${xu}'`,t,n),hhe=(e,t,n)=>RC(`${e} === '${Od}' || ${e} === '${Ts}'`,t,n),phe=(e,t,n)=>RC(`${e} === '${Ts}'`,t,n),ghe=(e,t,n)=>RC(`${e} === '${Ld}'`,t,n),oP=(e,t,n)=>(t=t!=null?$n(t):t,n=n!=null?$n(n):n,AM(t)&&AM(n)?(t=t?t.signal||ce(t.value):null,n=n?n.signal||ce(n.value):null,{signal:`${e} ? (${t}) : (${n})`}):[We({test:e},t)].concat(n||[])),AM=e=>e==null||Object.keys(e).length===1,RC=(e,t,n)=>({signal:`${e} ? (${of(t)}) : (${of(n)})`}),mhe=(e,t,n,r,i)=>({signal:(r!=null?`${e} === '${Od}' ? (${of(r)}) : `:"")+(n!=null?`${e} === '${xu}' ? (${of(n)}) : `:"")+(i!=null?`${e} === '${Ld}' ? (${of(i)}) : `:"")+(t!=null?`${e} === '${Ts}' ? (${of(t)}) : `:"")+"(null)"}),of=e=>vn(e)?e.signal:e==null?null:ce(e),yhe=(e,t)=>t===0?0:vn(e)?{signal:`(${e.signal}) * ${t}`}:{value:e*t},hf=(e,t)=>{const n=e.signal;return n&&n.endsWith("(null)")?{signal:n.slice(0,-6)+t.signal}:e};function Wc(e,t,n,r){let i;if(t&&be(t,e))return t[e];if(be(n,e))return n[e];if(e.startsWith("title")){switch(e){case"titleColor":i="fill";break;case"titleFont":case"titleFontSize":case"titleFontWeight":i=e[5].toLowerCase()+e.slice(6)}return r[SC][i]}else if(e.startsWith("label")){switch(e){case"labelColor":i="fill";break;case"labelFont":case"labelFontSize":i=e[5].toLowerCase()+e.slice(6)}return r[Rg][i]}return null}function SM(e){const t={};for(const n of e)if(n)for(const r in n)t[r]=1;return Object.keys(t)}function vhe(e,t){var n=t.config,r=n.style,i=n.axis,s=t.scaleType(e.scale)==="band"&&n.axisBand,o=e.orient,a,u,l;if(vn(o)){const f=SM([n.axisX,n.axisY]),d=SM([n.axisTop,n.axisBottom,n.axisLeft,n.axisRight]);a={};for(l of f)a[l]=Fn(o,Wc(l,n.axisX,i,r),Wc(l,n.axisY,i,r));u={};for(l of d)u[l]=mhe(o.signal,Wc(l,n.axisTop,i,r),Wc(l,n.axisBottom,i,r),Wc(l,n.axisLeft,i,r),Wc(l,n.axisRight,i,r))}else a=o===Ts||o===xu?n.axisX:n.axisY,u=n["axis"+o[0].toUpperCase()+o.slice(1)];return a||u||s?We({},i,a,u,s):i}function bhe(e,t,n,r){const i=ei(e,t),s=e.orient;let o,a;const u={enter:o={opacity:ut},update:a={opacity:zi},exit:{opacity:ut}};Xn(u,{stroke:i("domainColor"),strokeCap:i("domainCap"),strokeDash:i("domainDash"),strokeDashOffset:i("domainDashOffset"),strokeWidth:i("domainWidth"),strokeOpacity:i("domainOpacity")});const l=kM(e,0),c=kM(e,1);return o.x=a.x=Fn(s,l,ut),o.x2=a.x2=Fn(s,c),o.y=a.y=xs(s,l,ut),o.y2=a.y2=xs(s,c),_i({type:CC,role:Uce,from:r,encode:u},n)}function kM(e,t){return{scale:e.scale,range:t}}function xhe(e,t,n,r,i){const s=ei(e,t),o=e.orient,a=e.gridScale,u=Nv(o,1,-1),l=_he(e.offset,u);let c,f,d;const h={enter:c={opacity:ut},update:d={opacity:zi},exit:f={opacity:ut}};Xn(h,{stroke:s("gridColor"),strokeCap:s("gridCap"),strokeDash:s("gridDash"),strokeDashOffset:s("gridDashOffset"),strokeOpacity:s("gridOpacity"),strokeWidth:s("gridWidth")});const p={scale:e.scale,field:Bi,band:i.band,extra:i.extra,offset:i.offset,round:s("tickRound")},g=Fn(o,{signal:"height"},{signal:"width"}),m=a?{scale:a,range:0,mult:u,offset:l}:{value:0,offset:l},y=a?{scale:a,range:1,mult:u,offset:l}:We(g,{mult:u,offset:l});return c.x=d.x=Fn(o,p,m),c.y=d.y=xs(o,p,m),c.x2=d.x2=xs(o,y),c.y2=d.y2=Fn(o,y),f.x=Fn(o,p),f.y=xs(o,p),_i({type:CC,role:qce,key:Bi,from:r,encode:h},n)}function _he(e,t){if(t!==1)if(!ge(e))e=vn(t)?{signal:`(${t.signal}) * (${e||0})`}:t*(e||0);else{let n=e=We({},e);for(;n.mult!=null;)if(ge(n.mult))n=n.mult=We({},n.mult);else return n.mult=vn(t)?{signal:`(${n.mult}) * (${t.signal})`}:n.mult*t,e;n.mult=t}return e}function whe(e,t,n,r,i,s){const o=ei(e,t),a=e.orient,u=Nv(a,-1,1);let l,c,f;const d={enter:l={opacity:ut},update:f={opacity:zi},exit:c={opacity:ut}};Xn(d,{stroke:o("tickColor"),strokeCap:o("tickCap"),strokeDash:o("tickDash"),strokeDashOffset:o("tickDashOffset"),strokeOpacity:o("tickOpacity"),strokeWidth:o("tickWidth")});const h=$n(i);h.mult=u;const p={scale:e.scale,field:Bi,band:s.band,extra:s.extra,offset:s.offset,round:o("tickRound")};return f.y=l.y=Fn(a,ut,p),f.y2=l.y2=Fn(a,h),c.x=Fn(a,p),f.x=l.x=xs(a,ut,p),f.x2=l.x2=xs(a,h),c.y=xs(a,p),_i({type:CC,role:Hce,key:Bi,from:r,encode:d},n)}function K2(e,t,n,r,i){return{signal:'flush(range("'+e+'"), scale("'+e+'", datum.value), '+t+","+n+","+r+","+i+")"}}function Ehe(e,t,n,r,i,s){const o=ei(e,t),a=e.orient,u=e.scale,l=Nv(a,-1,1),c=Dl(o("labelFlush")),f=Dl(o("labelFlushOffset")),d=o("labelAlign"),h=o("labelBaseline");let p=c===0||!!c,g;const m=$n(i);m.mult=l,m.offset=$n(o("labelPadding")||0),m.offset.mult=l;const y={scale:u,field:Bi,band:.5,offset:QI(s.offset,o("labelOffset"))},v=Fn(a,p?K2(u,c,'"left"','"right"','"center"'):{value:"center"},che(a,"left","right")),b=Fn(a,sP(a,"bottom","top"),p?K2(u,c,'"top"','"bottom"','"middle"'):{value:"middle"}),x=K2(u,c,`-(${f})`,f,0);p=p&&f;const _={opacity:ut,x:Fn(a,y,m),y:xs(a,y,m)},A={enter:_,update:g={opacity:zi,text:{field:AC},x:_.x,y:_.y,align:v,baseline:b},exit:{opacity:ut,x:_.x,y:_.y}};Xn(A,{dx:!d&&p?Fn(a,x):null,dy:!h&&p?xs(a,x):null}),Xn(A,{angle:o("labelAngle"),fill:o("labelColor"),fillOpacity:o("labelOpacity"),font:o("labelFont"),fontSize:o("labelFontSize"),fontWeight:o("labelFontWeight"),fontStyle:o("labelFontStyle"),limit:o("labelLimit"),lineHeight:o("labelLineHeight")},{align:d,baseline:h});const E=o("labelBound");let S=o("labelOverlap");return S=S||E?{separation:o("labelSeparation"),method:S,order:"datum.index",bound:E?{scale:u,orient:a,tolerance:E}:null}:void 0,g.align!==v&&(g.align=hf(g.align,v)),g.baseline!==b&&(g.baseline=hf(g.baseline,b)),_i({type:wc,role:Wce,style:Rg,key:Bi,from:r,encode:A,overlap:S},n)}function Ahe(e,t,n,r){const i=ei(e,t),s=e.orient,o=Nv(s,-1,1);let a,u;const l={enter:a={opacity:ut,anchor:$n(i("titleAnchor",null)),align:{signal:$C}},update:u=We({},a,{opacity:zi,text:$n(e.title)}),exit:{opacity:ut}},c={signal:`lerp(range("${e.scale}"), ${Mv(0,1,.5)})`};return u.x=Fn(s,c),u.y=xs(s,c),a.angle=Fn(s,ut,yhe(o,90)),a.baseline=Fn(s,sP(s,xu,Ts),{value:xu}),u.angle=a.angle,u.baseline=a.baseline,Xn(l,{fill:i("titleColor"),fillOpacity:i("titleOpacity"),font:i("titleFont"),fontSize:i("titleFontSize"),fontStyle:i("titleFontStyle"),fontWeight:i("titleFontWeight"),limit:i("titleLimit"),lineHeight:i("titleLineHeight")},{align:i("titleAlign"),angle:i("titleAngle"),baseline:i("titleBaseline")}),She(i,s,l,n),l.update.align=hf(l.update.align,a.align),l.update.angle=hf(l.update.angle,a.angle),l.update.baseline=hf(l.update.baseline,a.baseline),_i({type:wc,role:Gce,style:SC,from:r,encode:l},n)}function She(e,t,n,r){const i=(a,u)=>a!=null?(n.update[u]=hf($n(a),n.update[u]),!1):!Zc(u,r),s=i(e("titleX"),"x"),o=i(e("titleY"),"y");n.enter.auto=o===s?$n(o):Fn(t,$n(o),$n(s))}function khe(e,t){const n=vhe(e,t),r=e.encode||{},i=r.axis||{},s=i.name||void 0,o=i.interactive,a=i.style,u=ei(e,n),l=wde(u),c={scale:e.scale,ticks:!!u("ticks"),labels:!!u("labels"),grid:!!u("grid"),domain:!!u("domain"),title:e.title!=null},f=Re(t.add(Rs({},[c]))),d=Re(t.add(Cfe({scale:t.scaleRef(e.scale),extra:t.property(l.extra),count:t.objectProperty(e.tickCount),values:t.objectProperty(e.values),minstep:t.property(e.tickMinStep),formatType:t.property(e.formatType),formatSpecifier:t.property(e.format)}))),h=[];let p;return c.grid&&h.push(xhe(e,n,r.grid,d,l)),c.ticks&&(p=u("tickSize"),h.push(whe(e,n,r.ticks,d,p,l))),c.labels&&(p=c.ticks?p:0,h.push(Ehe(e,n,r.labels,d,p,l))),c.domain&&h.push(bhe(e,n,r.domain,f)),c.title&&h.push(Ahe(e,n,r.title,f)),Tv(Np({role:jce,from:f,encode:Nd(Che(u,e),i,Tg),marks:h,aria:u("aria"),description:u("description"),zindex:u("zindex"),name:s,interactive:o,style:a}),t)}function Che(e,t){const n={enter:{},update:{}};return Xn(n,{orient:e("orient"),offset:e("offset")||0,position:as(t.position,0),titlePadding:e("titlePadding"),minExtent:e("minExtent"),maxExtent:e("maxExtent"),range:{signal:`abs(span(range("${t.scale}")))`},translate:e("translate"),format:t.format,formatType:t.formatType}),n}function aP(e,t,n){const r=ye(e.signals),i=ye(e.scales);return n||r.forEach(s=>BI(s,t)),ye(e.projections).forEach(s=>sde(s,t)),i.forEach(s=>Yfe(s,t)),ye(e.data).forEach(s=>uhe(s,t)),i.forEach(s=>Vfe(s,t)),(n||r).forEach(s=>kfe(s,t)),ye(e.axes).forEach(s=>khe(s,t)),ye(e.marks).forEach(s=>Tv(s,t)),ye(e.legends).forEach(s=>Kde(s,t)),e.title&&rhe(e.title,t),t.parseLambdas(),t}const $he=e=>Nd({enter:{x:{value:0},y:{value:0}},update:{width:{signal:"width"},height:{signal:"height"}}},e);function Fhe(e,t){const n=t.config,r=Re(t.root=t.add(G1())),i=Dhe(e,n);i.forEach(l=>BI(l,t)),t.description=e.description||n.description,t.eventConfig=n.events,t.legends=t.objectProperty(n.legend&&n.legend.layout),t.locale=n.locale;const s=t.add(Rs()),o=t.add(UI(PI($he(e.encode),Dv,xC,e.style,t,{pulse:Re(s)}))),a=t.add(HI({layout:t.objectProperty(e.layout),legends:t.legends,autosize:t.signalRef("autosize"),mark:r,pulse:Re(o)}));t.operators.pop(),t.pushState(Re(o),Re(a),null),aP(e,t,i),t.operators.push(a);let u=t.add(jI({mark:r,pulse:Re(a)}));return u=t.add(WI({pulse:Re(u)})),u=t.add(_c({pulse:Re(u)})),t.addData("root",new tc(t,s,s,u)),t}function dh(e,t){return t&&t.signal?{name:e,update:t.signal}:{name:e,value:t}}function Dhe(e,t){const n=o=>as(e[o],t[o]),r=[dh("background",n("background")),dh("autosize",Pce(n("autosize"))),dh("padding",zce(n("padding"))),dh("width",n("width")||0),dh("height",n("height")||0)],i=r.reduce((o,a)=>(o[a.name]=a,o),{}),s={};return ye(e.signals).forEach(o=>{be(i,o.name)?o=We(i[o.name],o):r.push(o),s[o.name]=o}),ye(t.signals).forEach(o=>{!be(s,o.name)&&!be(i,o.name)&&r.push(o)}),r}function uP(e,t){this.config=e||{},this.options=t||{},this.bindings=[],this.field={},this.signals={},this.lambdas={},this.scales={},this.events={},this.data={},this.streams=[],this.updates=[],this.operators=[],this.eventConfig=null,this.locale=null,this._id=0,this._subid=0,this._nextsub=[0],this._parent=[],this._encode=[],this._lookup=[],this._markpath=[]}function CM(e){this.config=e.config,this.options=e.options,this.legends=e.legends,this.field=Object.create(e.field),this.signals=Object.create(e.signals),this.lambdas=Object.create(e.lambdas),this.scales=Object.create(e.scales),this.events=Object.create(e.events),this.data=Object.create(e.data),this.streams=[],this.updates=[],this.operators=[],this._id=0,this._subid=++e._nextsub[0],this._nextsub=e._nextsub,this._parent=e._parent.slice(),this._encode=e._encode.slice(),this._lookup=e._lookup.slice(),this._markpath=e._markpath}uP.prototype=CM.prototype={parse(e){return aP(e,this)},fork(){return new CM(this)},isSubscope(){return this._subid>0},toRuntime(){return this.finish(),{description:this.description,operators:this.operators,streams:this.streams,updates:this.updates,bindings:this.bindings,eventConfig:this.eventConfig,locale:this.locale}},id(){return(this._subid?this._subid+":":0)+this._id++},add(e){return this.operators.push(e),e.id=this.id(),e.refs&&(e.refs.forEach(t=>{t.$ref=e.id}),e.refs=null),e},proxy(e){const t=e instanceof Tw?Re(e):e;return this.add(jfe({value:t}))},addStream(e){return this.streams.push(e),e.id=this.id(),e},addUpdate(e){return this.updates.push(e),e},finish(){let e,t;this.root&&(this.root.root=!0);for(e in this.signals)this.signals[e].signal=e;for(e in this.scales)this.scales[e].scale=e;function n(r,i,s){let o,a;r&&(o=r.data||(r.data={}),a=o[i]||(o[i]=[]),a.push(s))}for(e in this.data){t=this.data[e],n(t.input,e,"input"),n(t.output,e,"output"),n(t.values,e,"values");for(const r in t.index)n(t.index[r],e,"index:"+r)}return this},pushState(e,t,n){this._encode.push(Re(this.add(_c({pulse:e})))),this._parent.push(t),this._lookup.push(n?Re(this.proxy(n)):null),this._markpath.push(-1)},popState(){this._encode.pop(),this._parent.pop(),this._lookup.pop(),this._markpath.pop()},parent(){return st(this._parent)},encode(){return st(this._encode)},lookup(){return st(this._lookup)},markpath(){const e=this._markpath;return++e[e.length-1]},fieldRef(e,t){if(me(e))return Rp(e,t);e.signal||X("Unsupported field reference: "+ce(e));const n=e.signal;let r=this.field[n];if(!r){const i={name:this.signalRef(n)};t&&(i.as=t),this.field[n]=r=Re(this.add(Mfe(i)))}return r},compareRef(e){let t=!1;const n=s=>vn(s)?(t=!0,this.signalRef(s.signal)):mfe(s)?(t=!0,this.exprRef(s.expr)):s,r=ye(e.field).map(n),i=ye(e.order).map(n);return t?Re(this.add(hM({fields:r,orders:i}))):fM(r,i)},keyRef(e,t){let n=!1;const r=s=>vn(s)?(n=!0,Re(i[s.signal])):s,i=this.signals;return e=ye(e).map(r),n?Re(this.add(Rfe({fields:e,flat:t}))):dfe(e,t)},sortRef(e){if(!e)return e;const t=$v(e.op,e.field),n=e.order||hfe;return n.signal?Re(this.add(hM({fields:t,orders:this.signalRef(n.signal)}))):fM(t,n)},event(e,t){const n=e+":"+t;if(!this.events[n]){const r=this.id();this.streams.push({id:r,source:e,type:t}),this.events[n]=r}return this.events[n]},hasOwnSignal(e){return be(this.signals,e)},addSignal(e,t){this.hasOwnSignal(e)&&X("Duplicate signal name: "+ce(e));const n=t instanceof Tw?t:this.add(G1(t));return this.signals[e]=n},getSignal(e){return this.signals[e]||X("Unrecognized signal name: "+ce(e)),this.signals[e]},signalRef(e){return this.signals[e]?Re(this.signals[e]):(be(this.lambdas,e)||(this.lambdas[e]=this.add(G1(null))),Re(this.lambdas[e]))},parseLambdas(){const e=Object.keys(this.lambdas);for(let t=0,n=e.length;t0?",":"")+(ge(i)?i.signal||TC(i):ce(i))}return n+"]"}function Rhe(e){let t="{",n=0,r,i;for(r in e)i=e[r],t+=(++n>1?",":"")+ce(r)+":"+(ge(i)?i.signal||TC(i):ce(i));return t+"}"}function The(){const e="sans-serif",r="#4c78a8",i="#000",s="#888",o="#ddd";return{description:"Vega visualization",padding:0,autosize:"pad",background:null,events:{defaults:{allow:["wheel"]}},group:null,mark:null,arc:{fill:r},area:{fill:r},image:null,line:{stroke:r,strokeWidth:2},path:{stroke:r},rect:{fill:r},rule:{stroke:i},shape:{stroke:r},symbol:{fill:r,size:64},text:{fill:i,font:e,fontSize:11},trail:{fill:r,size:2},style:{"guide-label":{fill:i,font:e,fontSize:10},"guide-title":{fill:i,font:e,fontSize:11,fontWeight:"bold"},"group-title":{fill:i,font:e,fontSize:13,fontWeight:"bold"},"group-subtitle":{fill:i,font:e,fontSize:12},point:{size:30,strokeWidth:2,shape:"circle"},circle:{size:30,strokeWidth:2},square:{size:30,strokeWidth:2,shape:"square"},cell:{fill:"transparent",stroke:o},view:{fill:"transparent"}},title:{orient:"top",anchor:"middle",offset:4,subtitlePadding:3},axis:{minExtent:0,maxExtent:200,bandPosition:.5,domain:!0,domainWidth:1,domainColor:s,grid:!1,gridWidth:1,gridColor:o,labels:!0,labelAngle:0,labelLimit:180,labelOffset:0,labelPadding:2,ticks:!0,tickColor:s,tickOffset:0,tickRound:!0,tickSize:5,tickWidth:1,titlePadding:4},axisBand:{tickOffset:-.5},projection:{type:"mercator"},legend:{orient:"right",padding:0,gridAlign:"each",columnPadding:10,rowPadding:2,symbolDirection:"vertical",gradientDirection:"vertical",gradientLength:200,gradientThickness:16,gradientStrokeColor:o,gradientStrokeWidth:0,gradientLabelOffset:2,labelAlign:"left",labelBaseline:"middle",labelLimit:160,labelOffset:4,labelOverlap:!0,symbolLimit:30,symbolType:"circle",symbolSize:100,symbolOffset:0,symbolStrokeWidth:1.5,symbolBaseFillColor:"transparent",symbolBaseStrokeColor:s,titleLimit:180,titleOrient:"top",titlePadding:5,layout:{offset:18,direction:"horizontal",left:{direction:"vertical"},right:{direction:"vertical"}}},range:{category:{scheme:"tableau10"},ordinal:{scheme:"blues"},heatmap:{scheme:"yellowgreenblue"},ramp:{scheme:"blues"},diverging:{scheme:"blueorange",extent:[1,0]},symbol:["circle","square","triangle-up","cross","diamond","triangle-right","triangle-down","triangle-left"]}}}function Nhe(e,t,n){return ge(e)||X("Input Vega specification must be an object."),t=xd(The(),t,e.config),Fhe(e,new uP(t,n)).toRuntime()}var Ohe="5.33.1";We(zf,AX,ete,Rte,yre,fie,Pse,yse,zse,coe,xoe,Coe);const Lhe=Object.freeze(Object.defineProperty({__proto__:null,Bounds:dn,CanvasHandler:Eg,CanvasRenderer:o1,DATE:Vr,DAY:ir,DAYOFYEAR:bo,Dataflow:lf,Debug:rR,DisallowedObjectProperties:WE,Error:HE,EventStream:Ny,Gradient:XO,GroupItem:rv,HOURS:vi,Handler:rk,HybridHandler:z7,HybridRenderer:j_,Info:nR,Item:nv,MILLISECONDS:Ss,MINUTES:bi,MONTH:ur,Marks:xi,MultiPulse:yA,None:tR,Operator:$t,Parameters:Ty,Pulse:ou,QUARTER:Yr,RenderType:Va,Renderer:wg,ResourceLoader:n7,SECONDS:qi,SVGHandler:C7,SVGRenderer:lk,SVGStringRenderer:B7,Scenegraph:b7,TIME_UNITS:aA,Transform:G,View:kI,WEEK:mn,Warn:GE,YEAR:Gn,accessor:Qr,accessorFields:ar,accessorName:en,array:ye,ascending:wd,bandwidthNRD:_A,bin:LT,bootstrapCI:IT,boundClip:K7,boundContext:vg,boundItem:L_,boundMark:g7,boundStroke:_a,changeset:Mu,clampRange:pR,codegenExpression:QL,compare:ZE,constant:pr,cumulativeLogNormal:CA,cumulativeNormal:Ly,cumulativeUniform:MA,dayofyear:qR,debounce:JE,defaultLocale:dA,definition:TT,densityLogNormal:kA,densityNormal:wA,densityUniform:DA,domChild:gn,domClear:Fi,domCreate:Ga,domFind:nk,dotbin:PT,error:X,expressionFunction:cn,extend:We,extent:mo,extentIndex:gR,falsy:Ta,fastmap:Ed,field:Ui,flush:mR,font:uv,fontFamily:_g,fontSize:Fo,format:J0,formatLocale:Pm,formats:gA,hasOwnProperty:be,id:rg,identity:hr,inferType:wT,inferTypes:ET,ingest:gt,inherits:he,inrange:ef,interpolate:TS,interpolateColors:ev,interpolateRange:OO,intersect:G7,intersectBoxLine:tf,intersectPath:jS,intersectPoint:US,intersectRule:i7,isArray:ee,isBoolean:Du,isDate:iu,isFunction:He,isIterable:yR,isNumber:ft,isObject:ge,isRegExp:QE,isString:me,isTuple:My,key:eA,lerp:vR,lineHeight:yu,loader:Fy,locale:xT,logger:YE,lruCache:bR,markup:uk,merge:xR,mergeConfig:xd,multiLineOffset:QS,one:bd,pad:_R,panLinear:uR,panLog:lR,panPow:cR,panSymlog:fR,parse:Nhe,parseExpression:KL,parseSelector:Iu,path:jy,pathCurves:PS,pathEqual:Z7,pathParse:Gf,pathRectangle:JO,pathRender:xp,pathSymbols:ZO,pathTrail:QO,peek:st,point:cv,projection:$k,quantileLogNormal:$A,quantileNormal:Iy,quantileUniform:RA,quantiles:bA,quantizeInterpolator:LO,quarter:dR,quartiles:xA,get random(){return Wi},randomInteger:$V,randomKDE:AA,randomLCG:CV,randomLogNormal:zT,randomMixture:jT,randomNormal:EA,randomUniform:UT,read:kT,regressionConstant:TA,regressionExp:WT,regressionLinear:NA,regressionLoess:YT,regressionLog:qT,regressionPoly:GT,regressionPow:HT,regressionQuad:OA,renderModule:fv,repeat:xh,resetDefaultLocale:AY,resetSVGClipId:t7,resetSVGDefIds:vee,responseType:ST,runtimeContext:hI,sampleCurve:By,sampleLogNormal:SA,sampleNormal:Oy,sampleUniform:FA,scale:ht,sceneEqual:ck,sceneFromJSON:y7,scenePickVisit:Jm,sceneToJSON:m7,sceneVisit:ks,sceneZOrder:qS,scheme:NS,serializeXML:O7,setHybridRendererOptions:pee,setRandom:SV,span:ig,splitAccessPath:ko,stringValue:ce,textMetrics:pi,timeBin:oT,timeFloor:KR,timeFormatLocale:pp,timeInterval:Cd,timeOffset:QR,timeSequence:nT,timeUnitSpecifier:UR,timeUnits:uA,toBoolean:tA,toDate:nA,toNumber:sr,toSet:As,toString:rA,transform:NT,transforms:zf,truncate:wR,truthy:yi,tupleid:Te,typeParsers:v_,utcFloor:ZR,utcInterval:$d,utcOffset:eT,utcSequence:rT,utcdayofyear:GR,utcquarter:hR,utcweek:YR,version:Ohe,visitArray:La,week:WR,writeConfig:_d,zero:ja,zoomLinear:VE,zoomLog:XE,zoomPow:Mm,zoomSymlog:KE},Symbol.toStringTag,{value:"Module"}));function Ihe(e,t,n){let r;t.x2&&(t.x?(n&&e.x>e.x2&&(r=e.x,e.x=e.x2,e.x2=r),e.width=e.x2-e.x):e.x=e.x2-(e.width||0)),t.xc&&(e.x=e.xc-(e.width||0)/2),t.y2&&(t.y?(n&&e.y>e.y2&&(r=e.y,e.y=e.y2,e.y2=r),e.height=e.y2-e.y):e.y=e.y2-(e.height||0)),t.yc&&(e.y=e.yc-(e.height||0)/2)}var Phe={NaN:NaN,E:Math.E,LN2:Math.LN2,LN10:Math.LN10,LOG2E:Math.LOG2E,LOG10E:Math.LOG10E,PI:Math.PI,SQRT1_2:Math.SQRT1_2,SQRT2:Math.SQRT2,MIN_VALUE:Number.MIN_VALUE,MAX_VALUE:Number.MAX_VALUE},Bhe={"*":(e,t)=>e*t,"+":(e,t)=>e+t,"-":(e,t)=>e-t,"/":(e,t)=>e/t,"%":(e,t)=>e%t,">":(e,t)=>e>t,"<":(e,t)=>ee<=t,">=":(e,t)=>e>=t,"==":(e,t)=>e==t,"!=":(e,t)=>e!=t,"===":(e,t)=>e===t,"!==":(e,t)=>e!==t,"&":(e,t)=>e&t,"|":(e,t)=>e|t,"^":(e,t)=>e^t,"<<":(e,t)=>e<>":(e,t)=>e>>t,">>>":(e,t)=>e>>>t},zhe={"+":e=>+e,"-":e=>-e,"~":e=>~e,"!":e=>!e};const jhe=Array.prototype.slice,Ku=(e,t,n)=>{const r=n?n(t[0]):t[0];return r[e].apply(r,jhe.call(t,1))},Uhe=(e,t,n,r,i,s,o)=>new Date(e,t||0,n??1,r||0,i||0,s||0,o||0);var qhe={isNaN:Number.isNaN,isFinite:Number.isFinite,abs:Math.abs,acos:Math.acos,asin:Math.asin,atan:Math.atan,atan2:Math.atan2,ceil:Math.ceil,cos:Math.cos,exp:Math.exp,floor:Math.floor,log:Math.log,max:Math.max,min:Math.min,pow:Math.pow,random:Math.random,round:Math.round,sin:Math.sin,sqrt:Math.sqrt,tan:Math.tan,clamp:(e,t,n)=>Math.max(t,Math.min(n,e)),now:Date.now,utc:Date.UTC,datetime:Uhe,date:e=>new Date(e).getDate(),day:e=>new Date(e).getDay(),year:e=>new Date(e).getFullYear(),month:e=>new Date(e).getMonth(),hours:e=>new Date(e).getHours(),minutes:e=>new Date(e).getMinutes(),seconds:e=>new Date(e).getSeconds(),milliseconds:e=>new Date(e).getMilliseconds(),time:e=>new Date(e).getTime(),timezoneoffset:e=>new Date(e).getTimezoneOffset(),utcdate:e=>new Date(e).getUTCDate(),utcday:e=>new Date(e).getUTCDay(),utcyear:e=>new Date(e).getUTCFullYear(),utcmonth:e=>new Date(e).getUTCMonth(),utchours:e=>new Date(e).getUTCHours(),utcminutes:e=>new Date(e).getUTCMinutes(),utcseconds:e=>new Date(e).getUTCSeconds(),utcmilliseconds:e=>new Date(e).getUTCMilliseconds(),length:e=>e.length,join:function(){return Ku("join",arguments)},indexof:function(){return Ku("indexOf",arguments)},lastindexof:function(){return Ku("lastIndexOf",arguments)},slice:function(){return Ku("slice",arguments)},reverse:e=>e.slice().reverse(),sort:e=>e.slice().sort(wd),parseFloat,parseInt,upper:e=>String(e).toUpperCase(),lower:e=>String(e).toLowerCase(),substring:function(){return Ku("substring",arguments,String)},split:function(){return Ku("split",arguments,String)},replace:function(){return Ku("replace",arguments,String)},trim:e=>String(e).trim(),btoa:e=>btoa(e),atob:e=>atob(e),regexp:RegExp,test:(e,t)=>RegExp(e).test(t)};const Whe=["view","item","group","xy","x","y"],zw=new Set([Function,eval,setTimeout,setInterval]);typeof setImmediate=="function"&&zw.add(setImmediate);const Hhe={Literal:(e,t)=>t.value,Identifier:(e,t)=>{const n=t.name;return e.memberDepth>0?n:n==="datum"?e.datum:n==="event"?e.event:n==="item"?e.item:Phe[n]||e.params["$"+n]},MemberExpression:(e,t)=>{const n=!t.computed,r=e(t.object);n&&(e.memberDepth+=1);const i=e(t.property);if(n&&(e.memberDepth-=1),zw.has(r[i])){console.error(`Prevented interpretation of member "${i}" which could lead to insecure code execution`);return}return r[i]},CallExpression:(e,t)=>{const n=t.arguments;let r=t.callee.name;return r.startsWith("_")&&(r=r.slice(1)),r==="if"?e(n[0])?e(n[1]):e(n[2]):(e.fn[r]||qhe[r]).apply(e.fn,n.map(e))},ArrayExpression:(e,t)=>t.elements.map(e),BinaryExpression:(e,t)=>Bhe[t.operator](e(t.left),e(t.right)),UnaryExpression:(e,t)=>zhe[t.operator](e(t.argument)),ConditionalExpression:(e,t)=>e(t.test)?e(t.consequent):e(t.alternate),LogicalExpression:(e,t)=>t.operator==="&&"?e(t.left)&&e(t.right):e(t.left)||e(t.right),ObjectExpression:(e,t)=>t.properties.reduce((n,r)=>{e.memberDepth+=1;const i=e(r.key);e.memberDepth-=1;const s=e(r.value);return WE.has(i)?console.error(`Prevented interpretation of property "${i}" which could lead to insecure code execution`):zw.has(s)?console.error(`Prevented interpretation of method "${s}" which could lead to insecure code execution`):n[i]=s,n},{})};function hh(e,t,n,r,i,s){const o=a=>Hhe[a.type](o,a);return o.memberDepth=0,o.fn=Object.create(t),o.params=n,o.datum=r,o.event=i,o.item=s,Whe.forEach(a=>o.fn[a]=function(){return i.vega[a](...arguments)}),o(e)}var Ghe={operator(e,t){const n=t.ast,r=e.functions;return i=>hh(n,r,i)},parameter(e,t){const n=t.ast,r=e.functions;return(i,s)=>hh(n,r,s,i)},event(e,t){const n=t.ast,r=e.functions;return i=>hh(n,r,void 0,void 0,i)},handler(e,t){const n=t.ast,r=e.functions;return(i,s)=>{const o=s.item&&s.item.datum;return hh(n,r,i,o,s)}},encode(e,t){const{marktype:n,channels:r}=t,i=e.functions,s=n==="group"||n==="image"||n==="rect";return(o,a)=>{const u=o.datum;let l=0,c;for(const f in r)c=hh(r[f].ast,i,a,u,void 0,o),o[f]!==c&&(o[f]=c,l=1);return n!=="rule"&&Ihe(o,r,s),l}}};const Yhe="5.23.0",Vhe={version:Yhe};function NC(e){return oe(e,"or")}function OC(e){return oe(e,"and")}function LC(e){return oe(e,"not")}function wm(e,t){if(LC(e))wm(e.not,t);else if(OC(e))for(const n of e.and)wm(n,t);else if(NC(e))for(const n of e.or)wm(n,t);else t(e)}function pf(e,t){return LC(e)?{not:pf(e.not,t)}:OC(e)?{and:e.and.map(n=>pf(n,t))}:NC(e)?{or:e.or.map(n=>pf(n,t))}:t(e)}const Be=structuredClone;function lP(e){throw new Error(e)}function td(e,t){const n={};for(const r of t)be(e,r)&&(n[r]=e[r]);return n}function Hr(e,t){const n={...e};for(const r of t)delete n[r];return n}Set.prototype.toJSON=function(){return`Set(${[...this].map(e=>At(e)).join(",")})`};function rt(e){if(ft(e))return e;const t=me(e)?e:At(e);if(t.length<250)return t;let n=0;for(let r=0;ra===0?o:`[${o}]`),s=i.map((o,a)=>i.slice(0,a+1).join(""));for(const o of s)t.add(o)}return t}function BC(e,t){return e===void 0||t===void 0?!0:PC(Uw(e),Uw(t))}function Et(e){return ie(e).length===0}const ie=Object.keys,Yn=Object.values,_u=Object.entries;function Op(e){return e===!0||e===!1}function Ut(e){const t=e.replace(/\W/g,"_");return(e.match(/^\d+/)?"_":"")+t}function op(e,t){return LC(e)?`!(${op(e.not,t)})`:OC(e)?`(${e.and.map(n=>op(n,t)).join(") && (")})`:NC(e)?`(${e.or.map(n=>op(n,t)).join(") || (")})`:t(e)}function Y1(e,t){if(t.length===0)return!0;const n=t.shift();return n in e&&Y1(e[n],t)&&delete e[n],Et(e)}function Ng(e){return e.charAt(0).toUpperCase()+e.substr(1)}function zC(e,t="datum"){const n=ko(e),r=[];for(let i=1;i<=n.length;i++){const s=`[${n.slice(0,i).map(ce).join("][")}]`;r.push(`${t}${s}`)}return r.join(" && ")}function dP(e,t="datum"){return`${t}[${ce(ko(e).join("."))}]`}function vt(e){return`datum['${e.replaceAll("'","\\'")}']`}function Zhe(e){return e.replace(/(\[|\]|\.|'|")/g,"\\$1")}function Gi(e){return`${ko(e).map(Zhe).join("\\.")}`}function nc(e,t,n){return e.replace(new RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"g"),n)}function Id(e){return`${ko(e).join(".")}`}function rd(e){return e?ko(e).length:0}function un(...e){return e.find(t=>t!==void 0)}let hP=42;function pP(e){const t=++hP;return e?String(e)+t:t}function Jhe(){hP=42}function gP(e){return mP(e)?e:`__${e}`}function mP(e){return e.startsWith("__")}function Lp(e){if(e!==void 0)return(e%360+360)%360}function Ov(e){return ft(e)?!0:!isNaN(e)&&!isNaN(parseFloat(e))}const $M=Object.getPrototypeOf(structuredClone({}));function fi(e,t){if(e===t)return!0;if(e&&t&&typeof e=="object"&&typeof t=="object"){if(e.constructor.name!==t.constructor.name)return!1;let n,r;if(Array.isArray(e)){if(n=e.length,n!=t.length)return!1;for(r=n;r--!==0;)if(!fi(e[r],t[r]))return!1;return!0}if(e instanceof Map&&t instanceof Map){if(e.size!==t.size)return!1;for(const s of e.entries())if(!t.has(s[0]))return!1;for(const s of e.entries())if(!fi(s[1],t.get(s[0])))return!1;return!0}if(e instanceof Set&&t instanceof Set){if(e.size!==t.size)return!1;for(const s of e.entries())if(!t.has(s[0]))return!1;return!0}if(ArrayBuffer.isView(e)&&ArrayBuffer.isView(t)){if(n=e.length,n!=t.length)return!1;for(r=n;r--!==0;)if(e[r]!==t[r])return!1;return!0}if(e.constructor===RegExp)return e.source===t.source&&e.flags===t.flags;if(e.valueOf!==Object.prototype.valueOf&&e.valueOf!==$M.valueOf)return e.valueOf()===t.valueOf();if(e.toString!==Object.prototype.toString&&e.toString!==$M.toString)return e.toString()===t.toString();const i=Object.keys(e);if(n=i.length,n!==Object.keys(t).length)return!1;for(r=n;r--!==0;)if(!Object.prototype.hasOwnProperty.call(t,i[r]))return!1;for(r=n;r--!==0;){const s=i[r];if(!fi(e[s],t[s]))return!1}return!0}return e!==e&&t!==t}function At(e){const t=[];return(function n(r){if(r&&r.toJSON&&typeof r.toJSON=="function"&&(r=r.toJSON()),r===void 0)return;if(typeof r=="number")return isFinite(r)?""+r:"null";if(typeof r!="object")return JSON.stringify(r);let i,s;if(Array.isArray(r)){for(s="[",i=0;iqv(e[t])?Ut(`_${t}_${_u(e[t])}`):Ut(`_${t}_${e[t]}`)).join("")}function Mt(e){return e===!0||Sc(e)&&!e.binned}function Pn(e){return e==="binned"||Sc(e)&&e.binned===!0}function Sc(e){return ge(e)}function qv(e){return oe(e,"param")}function FM(e){switch(e){case la:case ca:case Sa:case Kr:case No:case Oo:case Uu:case ka:case zu:case ju:case Zr:return 6;case qu:return 4;default:return 10}}function Pg(e){return oe(e,"expr")}function zn(e,{level:t}={level:0}){const n=ie(e||{}),r={};for(const i of n)r[i]=t===0?li(e[i]):zn(e[i],{level:t-1});return r}function DP(e){const{anchor:t,frame:n,offset:r,orient:i,angle:s,limit:o,color:a,subtitleColor:u,subtitleFont:l,subtitleFontSize:c,subtitleFontStyle:f,subtitleFontWeight:d,subtitleLineHeight:h,subtitlePadding:p,...g}=e,m={...g,...a?{fill:a}:{}},y={...t?{anchor:t}:{},...n?{frame:n}:{},...r?{offset:r}:{},...i?{orient:i}:{},...s!==void 0?{angle:s}:{},...o!==void 0?{limit:o}:{}},v={...u?{subtitleColor:u}:{},...l?{subtitleFont:l}:{},...c?{subtitleFontSize:c}:{},...f?{subtitleFontStyle:f}:{},...d?{subtitleFontWeight:d}:{},...h?{subtitleLineHeight:h}:{},...p?{subtitlePadding:p}:{}},b=td(e,["align","baseline","dx","dy","limit"]);return{titleMarkConfig:m,subtitleMarkConfig:b,nonMarkTitleProperties:y,subtitle:v}}function za(e){return me(e)||ee(e)&&me(e[0])}function Ce(e){return oe(e,"signal")}function kc(e){return oe(e,"step")}function Epe(e){return ee(e)?!1:oe(e,"fields")&&!oe(e,"data")}function Ape(e){return ee(e)?!1:oe(e,"fields")&&oe(e,"data")}function sa(e){return ee(e)?!1:oe(e,"field")&&oe(e,"data")}const Spe={aria:1,description:1,ariaRole:1,ariaRoleDescription:1,blend:1,opacity:1,fill:1,fillOpacity:1,stroke:1,strokeCap:1,strokeWidth:1,strokeOpacity:1,strokeDash:1,strokeDashOffset:1,strokeJoin:1,strokeOffset:1,strokeMiterLimit:1,startAngle:1,endAngle:1,padAngle:1,innerRadius:1,outerRadius:1,size:1,shape:1,interpolate:1,tension:1,orient:1,align:1,baseline:1,text:1,dir:1,dx:1,dy:1,ellipsis:1,limit:1,radius:1,theta:1,angle:1,font:1,fontSize:1,fontWeight:1,fontStyle:1,lineBreak:1,lineHeight:1,cursor:1,href:1,tooltip:1,cornerRadius:1,cornerRadiusTopLeft:1,cornerRadiusTopRight:1,cornerRadiusBottomLeft:1,cornerRadiusBottomRight:1,aspect:1,width:1,height:1,url:1,smooth:1},kpe=ie(Spe),Cpe={arc:1,area:1,group:1,image:1,line:1,path:1,rect:1,rule:1,shape:1,symbol:1,text:1,trail:1},qw=["cornerRadius","cornerRadiusTopLeft","cornerRadiusTopRight","cornerRadiusBottomLeft","cornerRadiusBottomRight"];function MP(e){const t=ee(e.condition)?e.condition.map(DM):DM(e.condition);return{...li(e),condition:t}}function li(e){if(Pg(e)){const{expr:t,...n}=e;return{signal:t,...n}}return e}function DM(e){if(Pg(e)){const{expr:t,...n}=e;return{signal:t,...n}}return e}function Ot(e){if(Pg(e)){const{expr:t,...n}=e;return{signal:t,...n}}return Ce(e)?e:e!==void 0?{value:e}:void 0}function $pe(e){return Ce(e)?e.signal:ce(e)}function MM(e){return Ce(e)?e.signal:ce(e.value)}function vs(e){return Ce(e)?e.signal:e==null?null:ce(e)}function Fpe(e,t,n){for(const r of n){const i=wo(r,t.markDef,t.config);i!==void 0&&(e[r]=Ot(i))}return e}function RP(e){return[].concat(e.type,e.style??[])}function wt(e,t,n,r={}){const{vgChannel:i,ignoreVgConfig:s}=r;return i&&oe(t,i)?t[i]:t[e]!==void 0?t[e]:s&&(!i||i===e)?void 0:wo(e,t,n,r)}function wo(e,t,n,{vgChannel:r}={}){const i=Ww(e,t,n.style);return un(r?i:void 0,i,r?n[t.type][r]:void 0,n[t.type][e],r?n.mark[r]:n.mark[e])}function Ww(e,t,n){return TP(e,RP(t),n)}function TP(e,t,n){t=ye(t);let r;for(const i of t){const s=n[i];oe(s,e)&&(r=s[e])}return r}function NP(e,t){return ye(e).reduce((n,r)=>(n.field.push(pe(r,t)),n.order.push(r.sort??"ascending"),n),{field:[],order:[]})}function OP(e,t){const n=[...e];return t.forEach(r=>{for(const i of n)if(fi(i,r))return;n.push(r)}),n}function LP(e,t){return fi(e,t)||!t?e:e?[...ye(e),...ye(t)].join(", "):t}function IP(e,t){const n=e.value,r=t.value;if(n==null||r===null)return{explicit:e.explicit,value:null};if((za(n)||Ce(n))&&(za(r)||Ce(r)))return{explicit:e.explicit,value:LP(n,r)};if(za(n)||Ce(n))return{explicit:e.explicit,value:n};if(za(r)||Ce(r))return{explicit:e.explicit,value:r};if(!za(n)&&!Ce(n)&&!za(r)&&!Ce(r))return{explicit:e.explicit,value:OP(n,r)};throw new Error("It should never reach here")}function KC(e){return`Invalid specification ${At(e)}. Make sure the specification includes at least one of the following properties: "mark", "layer", "facet", "hconcat", "vconcat", "concat", or "repeat".`}const Dpe='Autosize "fit" only works for single views and layered views.';function RM(e){return`${e=="width"?"Width":"Height"} "container" only works for single views and layered views.`}function TM(e){const t=e=="width"?"Width":"Height",n=e=="width"?"x":"y";return`${t} "container" only works well with autosize "fit" or "fit-${n}".`}function NM(e){return e?`Dropping "fit-${e}" because spec has discrete ${Jr(e)}.`:'Dropping "fit" because spec has discrete size.'}function ZC(e){return`Unknown field for ${e}. Cannot calculate view size.`}function OM(e){return`Cannot project a selection on encoding channel "${e}", which has no field.`}function Mpe(e,t){return`Cannot project a selection on encoding channel "${e}" as it uses an aggregate function ("${t}").`}function Rpe(e){return`The "nearest" transform is not supported for ${e} marks.`}function PP(e){return`Selection not supported for ${e} yet.`}function Tpe(e){return`Cannot find a selection named "${e}".`}const Npe="Scale bindings are currently only supported for scales with unbinned, continuous domains.",Ope="Sequntial scales are deprecated. The available quantitative scale type values are linear, log, pow, sqrt, symlog, time and utc",Lpe="Legend bindings are only supported for selections over an individual field or encoding channel.";function Ipe(e){return`Lookups can only be performed on selection parameters. "${e}" is a variable parameter.`}function Ppe(e){return`Cannot define and lookup the "${e}" selection in the same view. Try moving the lookup into a second, layered view?`}const Bpe="The same selection must be used to override scale domains in a layered view.",zpe='Interval selections should be initialized using "x", "y", "longitude", or "latitude" keys.';function jpe(e){return`Unknown repeated value "${e}".`}function LM(e){return`The "columns" property cannot be used when "${e}" has nested row/column.`}const Upe="Multiple timer selections in one unit spec are not supported. Ignoring all but the first.",JC="Animation involving facet, layer, or concat is currently unsupported.";function qpe(e){return`A "field" or "encoding" must be specified when using a selection as a scale domain. Using "field": ${ce(e)}.`}function Wpe(e,t,n,r){return(e.length?"Multiple ":"No ")+`matching ${ce(t)} encoding found for selection ${ce(n.param)}. Using "field": ${ce(r)}.`}const Hpe="Axes cannot be shared in concatenated or repeated views yet (https://github.com/vega/vega-lite/issues/2415).";function Gpe(e){return`Unrecognized parse "${e}".`}function IM(e,t,n){return`An ancestor parsed field "${e}" as ${n} but a child wants to parse the field as ${t}.`}const Ype="Attempt to add the same child twice.";function Vpe(e){return`Ignoring an invalid transform: ${At(e)}.`}const Xpe='If "from.fields" is not specified, "as" has to be a string that specifies the key to be used for the data from the secondary source.';function PM(e){return`Config.customFormatTypes is not true, thus custom format type and format for channel ${e} are dropped.`}function Kpe(e){const{parentProjection:t,projection:n}=e;return`Layer's shared projection ${At(t)} is overridden by a child projection ${At(n)}.`}const Zpe="Arc marks uses theta channel rather than angle, replacing angle with theta.";function Jpe(e){return`${e}Offset dropped because ${e} is continuous`}function Qpe(e,t,n){return`Channel ${e} is a ${t}. Converted to {value: ${At(n)}}.`}function BP(e){return`Invalid field type "${e}".`}function ege(e,t){return`Invalid field type "${e}" for aggregate: "${t}", using "quantitative" instead.`}function tge(e){return`Invalid aggregation operator "${e}".`}function zP(e,t){const{fill:n,stroke:r}=t;return`Dropping color ${e} as the plot also has ${n&&r?"fill and stroke":n?"fill":"stroke"}.`}function nge(e){return`Position range does not support relative band size for ${e}.`}function Hw(e,t){return`Dropping ${At(e)} from channel "${t}" since it does not contain any data field, datum, value, or signal.`}const rge="Line marks cannot encode size with a non-groupby field. You may want to use trail marks instead.";function Wv(e,t,n){return`${e} dropped as it is incompatible with "${t}".`}function ige(e){return`${e}-encoding is dropped as ${e} is not a valid encoding channel.`}function sge(e){return`${e} encoding should be discrete (ordinal / nominal / binned).`}function oge(e){return`${e} encoding should be discrete (ordinal / nominal / binned) or use a discretizing scale (e.g. threshold).`}function age(e){return`Facet encoding dropped as ${e.join(" and ")} ${e.length>1?"are":"is"} also specified.`}function Q2(e,t){return`Using discrete channel "${e}" to encode "${t}" field can be misleading as it does not encode ${t==="ordinal"?"order":"magnitude"}.`}function uge(e){return`The ${e} for range marks cannot be an expression`}function lge(e,t){return`Line mark is for continuous lines and thus cannot be used with ${e&&t?"x2 and y2":e?"x2":"y2"}. We will use the rule mark (line segments) instead.`}function cge(e,t){return`Specified orient "${e}" overridden with "${t}".`}function fge(e){return`Cannot use the scale property "${e}" with non-color channel.`}function dge(e){return`Cannot use the relative band size with ${e} scale.`}function hge(e){return`Using unaggregated domain with raw field has no effect (${At(e)}).`}function pge(e){return`Unaggregated domain not applicable for "${e}" since it produces values outside the origin domain of the source data.`}function gge(e){return`Unaggregated domain is currently unsupported for log scale (${At(e)}).`}function mge(e){return`Cannot apply size to non-oriented mark "${e}".`}function yge(e,t,n){return`Channel "${e}" does not work with "${t}" scale. We are using "${n}" scale instead.`}function vge(e,t){return`FieldDef does not work with "${e}" scale. We are using "${t}" scale instead.`}function jP(e,t,n){return`${n}-scale's "${t}" is dropped as it does not work with ${e} scale.`}function UP(e){return`The step for "${e}" is dropped because the ${e==="width"?"x":"y"} is continuous.`}function bge(e,t,n,r){return`Conflicting ${t.toString()} property "${e.toString()}" (${At(n)} and ${At(r)}). Using ${At(n)}.`}function xge(e,t,n,r){return`Conflicting ${t.toString()} property "${e.toString()}" (${At(n)} and ${At(r)}). Using the union of the two domains.`}function _ge(e){return`Setting the scale to be independent for "${e}" means we also have to set the guide (axis or legend) to be independent.`}function wge(e){return`Dropping sort property ${At(e)} as unioned domains only support boolean or op "count", "min", and "max".`}const BM="Domains that should be unioned has conflicting sort properties. Sort will be set to true.",Ege="Detected faceted independent scales that union domain of multiple fields from different data sources. We will use the first field. The result view size may be incorrect.",Age="Detected faceted independent scales that union domain of the same fields from different source. We will assume that this is the same field from a different fork of the same data source. However, if this is not the case, the result view size may be incorrect.",Sge="Detected faceted independent scales that union domain of multiple fields from the same data source. We will use the first field. The result view size may be incorrect.";function kge(e){return`Cannot stack "${e}" if there is already "${e}2".`}function Cge(e){return`Stack is applied to a non-linear scale (${e}).`}function $ge(e){return`Stacking is applied even though the aggregate function is non-summative ("${e}").`}function V1(e,t){return`Invalid ${e}: ${At(t)}.`}function Fge(e){return`Dropping day from datetime ${At(e)} as day cannot be combined with other units.`}function Dge(e,t){return`${t?"extent ":""}${t&&e?"and ":""}${e?"center ":""}${t&&e?"are ":"is "}not needed when data are aggregated.`}function Mge(e,t,n){return`${e} is not usually used with ${t} for ${n}.`}function Rge(e,t){return`Continuous axis should not have customized aggregation function ${e}; ${t} already agregates the axis.`}function zM(e){return`1D error band does not support ${e}.`}function qP(e){return`Channel ${e} is required for "binned" bin.`}function Tge(e){return`Channel ${e} should not be used with "binned" bin.`}function Nge(e){return`Domain for ${e} is required for threshold scale.`}const WP=YE(GE);let ic=WP;function Oge(e){return ic=e,ic}function Lge(){return ic=WP,ic}function QC(...e){ic.error(...e)}function ae(...e){ic.warn(...e)}function Ige(...e){ic.debug(...e)}function Cc(e){if(e&&ge(e)){for(const t of t3)if(oe(e,t))return!0}return!1}const HP=["january","february","march","april","may","june","july","august","september","october","november","december"],Pge=HP.map(e=>e.substr(0,3)),GP=["sunday","monday","tuesday","wednesday","thursday","friday","saturday"],Bge=GP.map(e=>e.substr(0,3));function zge(e){if(Ov(e)&&(e=+e),ft(e))return e>4&&ae(V1("quarter",e)),e-1;throw new Error(V1("quarter",e))}function jge(e){if(Ov(e)&&(e=+e),ft(e))return e-1;{const t=e.toLowerCase(),n=HP.indexOf(t);if(n!==-1)return n;const r=t.substr(0,3),i=Pge.indexOf(r);if(i!==-1)return i;throw new Error(V1("month",e))}}function Uge(e){if(Ov(e)&&(e=+e),ft(e))return e%7;{const t=e.toLowerCase(),n=GP.indexOf(t);if(n!==-1)return n;const r=t.substr(0,3),i=Bge.indexOf(r);if(i!==-1)return i;throw new Error(V1("day",e))}}function e3(e,t){const n=[];if(t&&e.day!==void 0&&ie(e).length>1&&(ae(Fge(e)),e=Be(e),delete e.day),e.year!==void 0?n.push(e.year):n.push(2012),e.month!==void 0){const r=t?jge(e.month):e.month;n.push(r)}else if(e.quarter!==void 0){const r=t?zge(e.quarter):e.quarter;n.push(ft(r)?r*3:`${r}*3`)}else n.push(0);if(e.date!==void 0)n.push(e.date);else if(e.day!==void 0){const r=t?Uge(e.day):e.day;n.push(ft(r)?r+1:`${r}+1`)}else n.push(1);for(const r of["hours","minutes","seconds","milliseconds"]){const i=e[r];n.push(typeof i>"u"?0:i)}return n}function sc(e){const n=e3(e,!0).join(", ");return e.utc?`utc(${n})`:`datetime(${n})`}function qge(e){const n=e3(e,!1).join(", ");return e.utc?`utc(${n})`:`datetime(${n})`}function Wge(e){const t=e3(e,!0);return e.utc?+new Date(Date.UTC(...t)):+new Date(...t)}const YP={year:1,quarter:1,month:1,week:1,day:1,dayofyear:1,date:1,hours:1,minutes:1,seconds:1,milliseconds:1},t3=ie(YP);function Hge(e){return be(YP,e)}function $c(e){return ge(e)?e.binned:VP(e)}function VP(e){return e&&e.startsWith("binned")}function n3(e){return e.startsWith("utc")}function Gge(e){return e.substring(3)}const Yge={"year-month":"%b %Y ","year-month-date":"%b %d, %Y "};function Hv(e){return t3.filter(t=>KP(e,t))}function XP(e){const t=Hv(e);return t[t.length-1]}function KP(e,t){const n=e.indexOf(t);return!(n<0||n>0&&t==="seconds"&&e.charAt(n-1)==="i"||e.length>n+3&&t==="day"&&e.charAt(n+3)==="o"||n>0&&t==="year"&&e.charAt(n-1)==="f")}function Vge(e,t,{end:n}={end:!1}){const r=zC(t),i=n3(e)?"utc":"";function s(u){return u==="quarter"?`(${i}quarter(${r})-1)`:`${i}${u}(${r})`}let o;const a={};for(const u of t3)KP(e,u)&&(a[u]=s(u),o=u);return n&&(a[o]+="+1"),qge(a)}function ZP(e){if(!e)return;const t=Hv(e);return`timeUnitSpecifier(${At(t)}, ${At(Yge)})`}function Xge(e,t,n){if(!e)return;const r=ZP(e);return`${n||n3(e)?"utc":"time"}Format(${t}, ${r})`}function Mn(e){if(!e)return;let t;return me(e)?VP(e)?t={unit:e.substring(6),binned:!0}:t={unit:e}:ge(e)&&(t={...e,...e.unit?{unit:e.unit}:{}}),n3(t.unit)&&(t.utc=!0,t.unit=Gge(t.unit)),t}function Kge(e){const{utc:t,...n}=Mn(e);return n.unit?(t?"utc":"")+ie(n).map(r=>Ut(`${r==="unit"?"":`_${r}_`}${n[r]}`)).join(""):(t?"utc":"")+"timeunit"+ie(n).map(r=>Ut(`_${r}_${n[r]}`)).join("")}function JP(e,t=n=>n){const n=Mn(e),r=XP(n.unit);if(r&&r!=="day"){const i={year:2001,month:1,date:1,hours:0,minutes:0,seconds:0,milliseconds:0},{step:s,part:o}=QP(r,n.step),a={...i,[o]:+i[o]+s};return`${t(sc(a))} - ${t(sc(i))}`}}const Zge={year:1,month:1,date:1,hours:1,minutes:1,seconds:1,milliseconds:1};function Jge(e){return be(Zge,e)}function QP(e,t=1){if(Jge(e))return{part:e,step:t};switch(e){case"day":case"dayofyear":return{part:"date",step:t};case"quarter":return{part:"month",step:t*3};case"week":return{part:"date",step:t*7}}}function Qge(e){return oe(e,"param")}function r3(e){return!!(e!=null&&e.field)&&e.equal!==void 0}function i3(e){return!!(e!=null&&e.field)&&e.lt!==void 0}function s3(e){return!!(e!=null&&e.field)&&e.lte!==void 0}function o3(e){return!!(e!=null&&e.field)&&e.gt!==void 0}function a3(e){return!!(e!=null&&e.field)&&e.gte!==void 0}function u3(e){if(e!=null&&e.field){if(ee(e.range)&&e.range.length===2)return!0;if(Ce(e.range))return!0}return!1}function l3(e){return!!(e!=null&&e.field)&&(ee(e.oneOf)||ee(e.in))}function e0e(e){return!!(e!=null&&e.field)&&e.valid!==void 0}function eB(e){return l3(e)||r3(e)||u3(e)||i3(e)||o3(e)||s3(e)||a3(e)}function Ws(e,t){return tb(e,{timeUnit:t,wrapTime:!0})}function t0e(e,t){return e.map(n=>Ws(n,t))}function tB(e,t=!0){const{field:n}=e,r=Mn(e.timeUnit),{unit:i,binned:s}=r||{},o=pe(e,{expr:"datum"}),a=i?`time(${s?o:Vge(i,n)})`:o;if(r3(e))return`${a}===${Ws(e.equal,i)}`;if(i3(e)){const u=e.lt;return`${a}<${Ws(u,i)}`}else if(o3(e)){const u=e.gt;return`${a}>${Ws(u,i)}`}else if(s3(e)){const u=e.lte;return`${a}<=${Ws(u,i)}`}else if(a3(e)){const u=e.gte;return`${a}>=${Ws(u,i)}`}else{if(l3(e))return`indexof([${t0e(e.oneOf,i).join(",")}], ${a}) !== -1`;if(e0e(e))return Gv(a,e.valid);if(u3(e)){const{range:u}=zn(e),l=Ce(u)?{signal:`${u.signal}[0]`}:u[0],c=Ce(u)?{signal:`${u.signal}[1]`}:u[1];if(l!==null&&c!==null&&t)return"inrange("+a+", ["+Ws(l,i)+", "+Ws(c,i)+"])";const f=[];return l!==null&&f.push(`${a} >= ${Ws(l,i)}`),c!==null&&f.push(`${a} <= ${Ws(c,i)}`),f.length>0?f.join(" && "):"true"}}throw new Error(`Invalid field predicate: ${At(e)}`)}function Gv(e,t=!0){return t?`isValid(${e}) && isFinite(+${e})`:`!isValid(${e}) || !isFinite(+${e})`}function n0e(e){return eB(e)&&e.timeUnit?{...e,timeUnit:Mn(e.timeUnit)}:e}const Bg={quantitative:"quantitative",ordinal:"ordinal",temporal:"temporal",nominal:"nominal",geojson:"geojson"};function r0e(e){return e==="quantitative"||e==="temporal"}function nB(e){return e==="ordinal"||e==="nominal"}const oc=Bg.quantitative,c3=Bg.ordinal,sd=Bg.temporal,f3=Bg.nominal,Bd=Bg.geojson;function i0e(e){if(e)switch(e=e.toLowerCase(),e){case"q":case oc:return"quantitative";case"t":case sd:return"temporal";case"o":case c3:return"ordinal";case"n":case f3:return"nominal";case Bd:return"geojson"}}const jn={LINEAR:"linear",LOG:"log",POW:"pow",SQRT:"sqrt",TIME:"time",UTC:"utc",POINT:"point",BAND:"band"},Gw={linear:"numeric",log:"numeric",pow:"numeric",sqrt:"numeric",symlog:"numeric",identity:"numeric",sequential:"numeric",time:"time",utc:"time",ordinal:"ordinal","bin-ordinal":"bin-ordinal",point:"ordinal-position",band:"ordinal-position",quantile:"discretizing",quantize:"discretizing",threshold:"discretizing"};function s0e(e,t){const n=Gw[e],r=Gw[t];return n===r||n==="ordinal-position"&&r==="time"||r==="ordinal-position"&&n==="time"}const o0e={linear:0,log:1,pow:1,sqrt:1,symlog:1,identity:1,sequential:1,time:0,utc:0,point:10,band:11,ordinal:0,"bin-ordinal":0,quantile:0,quantize:0,threshold:0};function jM(e){return o0e[e]}const rB=new Set(["linear","log","pow","sqrt","symlog"]),iB=new Set([...rB,"time","utc"]);function sB(e){return rB.has(e)}const oB=new Set(["quantile","quantize","threshold"]),a0e=new Set([...iB,...oB,"sequential","identity"]),u0e=new Set(["ordinal","bin-ordinal","point","band"]);function Tn(e){return u0e.has(e)}function Cs(e){return a0e.has(e)}function ao(e){return iB.has(e)}function od(e){return oB.has(e)}const l0e={pointPadding:.5,barBandPaddingInner:.1,rectBandPaddingInner:0,tickBandPaddingInner:.25,bandWithNestedOffsetPaddingInner:.2,bandWithNestedOffsetPaddingOuter:.2,minBandSize:2,minFontSize:8,maxFontSize:40,minOpacity:.3,maxOpacity:.8,minSize:4,minStrokeWidth:1,maxStrokeWidth:4,quantileCount:4,quantizeCount:4,zero:!0,framesPerSecond:2,animationDuration:5};function c0e(e){return!me(e)&&oe(e,"name")}function aB(e){return oe(e,"param")}function f0e(e){return oe(e,"unionWith")}function d0e(e){return ge(e)&&"field"in e}const h0e={type:1,domain:1,domainMax:1,domainMin:1,domainMid:1,domainRaw:1,align:1,range:1,rangeMax:1,rangeMin:1,scheme:1,bins:1,reverse:1,round:1,clamp:1,nice:1,base:1,exponent:1,constant:1,interpolate:1,zero:1,padding:1,paddingInner:1,paddingOuter:1},{type:$ke,domain:Fke,range:Dke,rangeMax:Mke,rangeMin:Rke,scheme:Tke,...p0e}=h0e,g0e=ie(p0e);function Yw(e,t){switch(t){case"type":case"domain":case"reverse":case"range":return!0;case"scheme":case"interpolate":return!["point","band","identity"].includes(e);case"bins":return!["point","band","identity","ordinal"].includes(e);case"round":return ao(e)||e==="band"||e==="point";case"padding":case"rangeMin":case"rangeMax":return ao(e)||["point","band"].includes(e);case"paddingOuter":case"align":return["point","band"].includes(e);case"paddingInner":return e==="band";case"domainMax":case"domainMid":case"domainMin":case"domainRaw":case"clamp":return ao(e);case"nice":return ao(e)||e==="quantize"||e==="threshold";case"exponent":return e==="pow";case"base":return e==="log";case"constant":return e==="symlog";case"zero":return Cs(e)&&!Qe(["log","time","utc","threshold","quantile"],e)}}function uB(e,t){switch(t){case"interpolate":case"scheme":case"domainMid":return gf(e)?void 0:fge(t);case"align":case"type":case"bins":case"domain":case"domainMax":case"domainMin":case"domainRaw":case"range":case"base":case"exponent":case"constant":case"nice":case"padding":case"paddingInner":case"paddingOuter":case"rangeMax":case"rangeMin":case"reverse":case"round":case"clamp":case"zero":return}}function m0e(e,t){return Qe([c3,f3],t)?e===void 0||Tn(e):t===sd?Qe([jn.TIME,jn.UTC,void 0],e):t===oc?sB(e)||od(e)||e===void 0:!0}function y0e(e,t,n=!1){if(!Io(e))return!1;switch(e){case qt:case On:case Pu:case Pd:case Xi:case Os:return ao(t)||t==="band"?!0:t==="point"?!n:!1;case Bu:return Qe(["linear","band"],t);case Sa:case Uu:case ka:case zu:case ju:case Ec:return ao(t)||od(t)||Qe(["band","point","ordinal"],t);case Kr:case No:case Oo:return t!=="band";case qu:case Zr:return t==="ordinal"||od(t)}}function v0e(e){return ge(e)&&"value"in e}const Rr={arc:"arc",area:"area",bar:"bar",image:"image",line:"line",point:"point",rect:"rect",rule:"rule",text:"text",tick:"tick",trail:"trail",circle:"circle",square:"square",geoshape:"geoshape"},lB=Rr.arc,Yv=Rr.area,Vv=Rr.bar,b0e=Rr.image,Xv=Rr.line,Kv=Rr.point,x0e=Rr.rect,X1=Rr.rule,cB=Rr.text,d3=Rr.tick,_0e=Rr.trail,h3=Rr.circle,p3=Rr.square,fB=Rr.geoshape;function Hu(e){return["line","area","trail"].includes(e)}function Ip(e){return["rect","bar","image","arc","tick"].includes(e)}const w0e=new Set(ie(Rr));function Eo(e){return oe(e,"type")}const E0e=["stroke","strokeWidth","strokeDash","strokeDashOffset","strokeOpacity","strokeJoin","strokeMiterLimit"],A0e=["fill","fillOpacity"],S0e=[...E0e,...A0e],k0e={color:1,filled:1,invalid:1,order:1,radius2:1,theta2:1,timeUnitBandSize:1,timeUnitBandPosition:1},UM=ie(k0e),ex=["binSpacing","continuousBandSize","discreteBandSize","minBandSize"],C0e={area:["line","point"],bar:ex,rect:ex,line:["point"],tick:["bandSize","thickness",...ex]},$0e={color:"#4c78a8",invalid:"break-paths-show-path-domains",timeUnitBandSize:1},F0e={mark:1,arc:1,area:1,bar:1,circle:1,image:1,line:1,point:1,rect:1,rule:1,square:1,text:1,tick:1,trail:1,geoshape:1},dB=ie(F0e);function ac(e){return oe(e,"band")}const D0e={horizontal:["cornerRadiusTopRight","cornerRadiusBottomRight"],vertical:["cornerRadiusTopLeft","cornerRadiusTopRight"]},M0e=5,g3={binSpacing:0,continuousBandSize:M0e,minBandSize:.25,timeUnitBandPosition:.5},R0e={...g3,binSpacing:1},T0e={...g3,thickness:1};function N0e(e){return Eo(e)?e.type:e}function hB(e,{isPath:t}){return e===void 0||e==="break-paths-show-path-domains"?t?"break-paths-show-domains":"filter":e===null?"show":e}function m3({markDef:e,config:t,scaleChannel:n,scaleType:r,isCountAggregate:i}){var a,u;if(!r||!Cs(r)||i)return"always-valid";const s=hB(wt("invalid",e,t),{isPath:Hu(e.type)});return((u=(a=t.scale)==null?void 0:a.invalid)==null?void 0:u[n])!==void 0?"show":s}function O0e(e){return e==="break-paths-filter-domains"||e==="break-paths-show-domains"}function pB({scaleName:e,scale:t,mode:n}){const r=`domain('${e}')`;if(!t||!e)return;const i=`${r}[0]`,s=`peek(${r})`,o=t.domainHasZero();return o==="definitely"?{scale:e,value:0}:o==="maybe"?{signal:`scale('${e}', inrange(0, ${r}) ? 0 : ${n==="zeroOrMin"?i:s})`}:{signal:`scale('${e}', ${n==="zeroOrMin"?i:s})`}}function gB({scaleChannel:e,channelDef:t,scale:n,scaleName:r,markDef:i,config:s}){var c;const o=n==null?void 0:n.get("type"),a=Fs(t),u=Uv(a==null?void 0:a.aggregate),l=m3({scaleChannel:e,markDef:i,config:s,scaleType:o,isCountAggregate:u});if(a&&l==="show"){const f=((c=s.scale.invalid)==null?void 0:c[e])??"zero-or-min";return{test:Gv(pe(a,{expr:"datum"}),!1),...L0e(f,n,r)}}}function L0e(e,t,n){if(v0e(e)){const{value:r}=e;return Ce(r)?{signal:r.signal}:{value:r}}return pB({scale:t,scaleName:n,mode:"zeroOrMin"})}function y3(e){const{channel:t,channelDef:n,markDef:r,scale:i,scaleName:s,config:o}=e,a=Ac(t),u=v3(e),l=gB({scaleChannel:a,channelDef:n,scale:i,scaleName:s,markDef:r,config:o});return l!==void 0?[l,u]:u}function I0e(e){const{datum:t}=e;return Cc(t)?sc(t):`${At(t)}`}function Ml(e,t,n,r){const i={};if(t&&(i.scale=t),Po(e)){const{datum:s}=e;Cc(s)?i.signal=sc(s):Ce(s)?i.signal=s.signal:Pg(s)?i.signal=s.expr:i.value=s}else i.field=pe(e,n);if(r){const{offset:s,band:o}=r;s&&(i.offset=s),o&&(i.band=o)}return i}function K1({scaleName:e,fieldOrDatumDef:t,fieldOrDatumDef2:n,offset:r,startSuffix:i,endSuffix:s="end",bandPosition:o=.5}){const a=!Ce(o)&&0{switch(t.fieldTitle){case"plain":return e.field;case"functional":return J0e(e);default:return Z0e(e,t)}};let $B=CB;function FB(e){$B=e}function Q0e(){FB(CB)}function mf(e,t,{allowDisabling:n,includeDefault:r=!0}){var a;const i=(a=w3(e))==null?void 0:a.title;if(!ue(e))return i??e.title;const s=e,o=r?E3(s,t):void 0;return n?un(i,s.title,o):i??s.title??o}function w3(e){if(ud(e)&&e.axis)return e.axis;if(SB(e)&&e.legend)return e.legend;if(x3(e)&&e.header)return e.header}function E3(e,t){return $B(e,t)}function Q1(e){if(kB(e)){const{format:t,formatType:n}=e;return{format:t,formatType:n}}else{const t=w3(e)??{},{format:n,formatType:r}=t;return{format:n,formatType:r}}}function eme(e,t){var s;switch(t){case"latitude":case"longitude":return"quantitative";case"row":case"column":case"facet":case"shape":case"strokeDash":return"nominal";case"order":return"ordinal"}if(_3(e)&&ee(e.sort))return"ordinal";const{aggregate:n,bin:r,timeUnit:i}=e;if(i)return"temporal";if(r||n&&!Wu(n)&&!va(n))return"quantitative";if(Fc(e)&&((s=e.scale)!=null&&s.type))switch(Gw[e.scale.type]){case"numeric":case"discretizing":return"quantitative";case"time":return"temporal"}return"nominal"}function Fs(e){if(ue(e))return e;if(Qv(e))return e.condition}function yn(e){if(Ue(e))return e;if(qg(e))return e.condition}function DB(e,t,n,r={}){if(me(e)||ft(e)||Du(e)){const i=me(e)?"string":ft(e)?"number":"boolean";return ae(Qpe(t,i,e)),{value:e}}return Ue(e)?ey(e,t,n,r):qg(e)?{...e,condition:ey(e.condition,t,n,r)}:e}function ey(e,t,n,r){if(kB(e)){const{format:i,formatType:s,...o}=e;if(uc(s)&&!n.customFormatTypes)return ae(PM(t)),ey(o,t,n,r)}else{const i=ud(e)?"axis":SB(e)?"legend":x3(e)?"header":null;if(i&&e[i]){const{format:s,formatType:o,...a}=e[i];if(uc(o)&&!n.customFormatTypes)return ae(PM(t)),ey({...e,[i]:a},t,n,r)}}return ue(e)?A3(e,t,r):tme(e)}function tme(e){let t=e.type;if(t)return e;const{datum:n}=e;return t=ft(n)?"quantitative":me(n)?"nominal":Cc(n)?"temporal":void 0,{...e,type:t}}function A3(e,t,{compositeMark:n=!1}={}){const{aggregate:r,timeUnit:i,bin:s,field:o}=e,a={...e};if(!n&&r&&!XC(r)&&!Wu(r)&&!va(r)&&(ae(tge(r)),delete a.aggregate),i&&(a.timeUnit=Mn(i)),o&&(a.field=`${o}`),Mt(s)&&(a.bin=eb(s,t)),Pn(s)&&!ln(t)&&ae(Tge(t)),Dr(a)){const{type:u}=a,l=i0e(u);u!==l&&(a.type=l),u!=="quantitative"&&Uv(r)&&(ae(ege(u,r)),a.type="quantitative")}else if(!EP(t)){const u=eme(a,t);a.type=u}if(Dr(a)){const{compatible:u,warning:l}=nme(a,t)||{};u===!1&&ae(l)}if(_3(a)&&me(a.sort)){const{sort:u}=a;if(WM(u))return{...a,sort:{encoding:u}};const l=u.substring(1);if(u.charAt(0)==="-"&&WM(l))return{...a,sort:{encoding:l,order:"descending"}}}if(x3(a)){const{header:u}=a;if(u){const{orient:l,...c}=u;if(l)return{...a,header:{...c,labelOrient:u.labelOrient||l,titleOrient:u.titleOrient||l}}}}return a}function eb(e,t){return Du(e)?{maxbins:FM(t)}:e==="binned"?{binned:!0}:!e.maxbins&&!e.step?{...e,maxbins:FM(t)}:e}const Hc={compatible:!0};function nme(e,t){const n=e.type;if(n==="geojson"&&t!=="shape")return{compatible:!1,warning:`Channel ${t} should not be used with a geojson data.`};switch(t){case la:case ca:case Lv:return J1(e)?Hc:{compatible:!1,warning:sge(t)};case qt:case On:case Pu:case Pd:case Kr:case No:case Oo:case Og:case Lg:case Iv:case rc:case Pv:case Bv:case Ec:case Xi:case Os:case zv:return Hc;case Is:case Yi:case Ls:case Ps:return n!==oc?{compatible:!1,warning:`Channel ${t} should be used with a quantitative field only, not ${e.type} field.`}:Hc;case ka:case zu:case ju:case Uu:case Sa:case Aa:case Ea:case Ns:case To:case Bu:return n==="nominal"&&!e.sort?{compatible:!1,warning:`Channel ${t} should not be used with an unsorted discrete field.`}:Hc;case Zr:case qu:return!J1(e)&&!X0e(e)?{compatible:!1,warning:oge(t)}:Hc;case id:return e.type==="nominal"&&!("sort"in e)?{compatible:!1,warning:"Channel order is inappropriate for nominal field, which has no inherent order."}:Hc}}function ld(e){const{formatType:t}=Q1(e);return t==="time"||!t&&rme(e)}function rme(e){return e&&(e.type==="temporal"||ue(e)&&!!e.timeUnit)}function tb(e,{timeUnit:t,type:n,wrapTime:r,undefinedIfExprNotRequired:i}){var u;const s=t&&((u=Mn(t))==null?void 0:u.unit);let o=s||n==="temporal",a;return Pg(e)?a=e.expr:Ce(e)?a=e.signal:Cc(e)?(o=!0,a=sc(e)):(me(e)||ft(e))&&o&&(a=`datetime(${At(e)})`,Hge(s)&&(ft(e)&&e<1e4||me(e)&&isNaN(Date.parse(e)))&&(a=sc({[s]:e}))),a?r&&o?`time(${a})`:a:i?void 0:At(e)}function MB(e,t){const{type:n}=e;return t.map(r=>{const i=ue(e)&&!$c(e.timeUnit)?e.timeUnit:void 0,s=tb(r,{timeUnit:i,type:n,undefinedIfExprNotRequired:!0});return s!==void 0?{signal:s}:r})}function Wg(e,t){return Mt(e.bin)?Io(t)&&["ordinal","nominal"].includes(e.type):(console.warn("Only call this method for binned field defs."),!1)}const YM={labelAlign:{part:"labels",vgProp:"align"},labelBaseline:{part:"labels",vgProp:"baseline"},labelColor:{part:"labels",vgProp:"fill"},labelFont:{part:"labels",vgProp:"font"},labelFontSize:{part:"labels",vgProp:"fontSize"},labelFontStyle:{part:"labels",vgProp:"fontStyle"},labelFontWeight:{part:"labels",vgProp:"fontWeight"},labelOpacity:{part:"labels",vgProp:"opacity"},labelOffset:null,labelPadding:null,gridColor:{part:"grid",vgProp:"stroke"},gridDash:{part:"grid",vgProp:"strokeDash"},gridDashOffset:{part:"grid",vgProp:"strokeDashOffset"},gridOpacity:{part:"grid",vgProp:"opacity"},gridWidth:{part:"grid",vgProp:"strokeWidth"},tickColor:{part:"ticks",vgProp:"stroke"},tickDash:{part:"ticks",vgProp:"strokeDash"},tickDashOffset:{part:"ticks",vgProp:"strokeDashOffset"},tickOpacity:{part:"ticks",vgProp:"opacity"},tickSize:null,tickWidth:{part:"ticks",vgProp:"strokeWidth"}};function Hg(e){return e==null?void 0:e.condition}const RB=["domain","grid","labels","ticks","title"],ime={grid:"grid",gridCap:"grid",gridColor:"grid",gridDash:"grid",gridDashOffset:"grid",gridOpacity:"grid",gridScale:"grid",gridWidth:"grid",orient:"main",bandPosition:"both",aria:"main",description:"main",domain:"main",domainCap:"main",domainColor:"main",domainDash:"main",domainDashOffset:"main",domainOpacity:"main",domainWidth:"main",format:"main",formatType:"main",labelAlign:"main",labelAngle:"main",labelBaseline:"main",labelBound:"main",labelColor:"main",labelFlush:"main",labelFlushOffset:"main",labelFont:"main",labelFontSize:"main",labelFontStyle:"main",labelFontWeight:"main",labelLimit:"main",labelLineHeight:"main",labelOffset:"main",labelOpacity:"main",labelOverlap:"main",labelPadding:"main",labels:"main",labelSeparation:"main",maxExtent:"main",minExtent:"main",offset:"both",position:"main",tickCap:"main",tickColor:"main",tickDash:"main",tickDashOffset:"main",tickMinStep:"both",tickOffset:"both",tickOpacity:"main",tickRound:"both",ticks:"main",tickSize:"main",tickWidth:"both",title:"main",titleAlign:"main",titleAnchor:"main",titleAngle:"main",titleBaseline:"main",titleColor:"main",titleFont:"main",titleFontSize:"main",titleFontStyle:"main",titleFontWeight:"main",titleLimit:"main",titleLineHeight:"main",titleOpacity:"main",titlePadding:"main",titleX:"main",titleY:"main",encode:"both",scale:"both",tickBand:"both",tickCount:"both",tickExtra:"both",translate:"both",values:"both",zindex:"both"},TB={orient:1,aria:1,bandPosition:1,description:1,domain:1,domainCap:1,domainColor:1,domainDash:1,domainDashOffset:1,domainOpacity:1,domainWidth:1,format:1,formatType:1,grid:1,gridCap:1,gridColor:1,gridDash:1,gridDashOffset:1,gridOpacity:1,gridWidth:1,labelAlign:1,labelAngle:1,labelBaseline:1,labelBound:1,labelColor:1,labelFlush:1,labelFlushOffset:1,labelFont:1,labelFontSize:1,labelFontStyle:1,labelFontWeight:1,labelLimit:1,labelLineHeight:1,labelOffset:1,labelOpacity:1,labelOverlap:1,labelPadding:1,labels:1,labelSeparation:1,maxExtent:1,minExtent:1,offset:1,position:1,tickBand:1,tickCap:1,tickColor:1,tickCount:1,tickDash:1,tickDashOffset:1,tickExtra:1,tickMinStep:1,tickOffset:1,tickOpacity:1,tickRound:1,ticks:1,tickSize:1,tickWidth:1,title:1,titleAlign:1,titleAnchor:1,titleAngle:1,titleBaseline:1,titleColor:1,titleFont:1,titleFontSize:1,titleFontStyle:1,titleFontWeight:1,titleLimit:1,titleLineHeight:1,titleOpacity:1,titlePadding:1,titleX:1,titleY:1,translate:1,values:1,zindex:1},sme={...TB,style:1,labelExpr:1,encoding:1};function VM(e){return be(sme,e)}const ome={axis:1,axisBand:1,axisBottom:1,axisDiscrete:1,axisLeft:1,axisPoint:1,axisQuantitative:1,axisRight:1,axisTemporal:1,axisTop:1,axisX:1,axisXBand:1,axisXDiscrete:1,axisXPoint:1,axisXQuantitative:1,axisXTemporal:1,axisY:1,axisYBand:1,axisYDiscrete:1,axisYPoint:1,axisYQuantitative:1,axisYTemporal:1},NB=ie(ome);function $a(e){return oe(e,"mark")}class nb{constructor(t,n){this.name=t,this.run=n}hasMatchingType(t){return $a(t)?N0e(t.mark)===this.name:!1}}function Rl(e,t){const n=e&&e[t];return n?ee(n)?nd(n,r=>!!r.field):ue(n)||Qv(n):!1}function OB(e,t){const n=e&&e[t];return n?ee(n)?nd(n,r=>!!r.field):ue(n)||Po(n)||qg(n):!1}function LB(e,t){if(ln(t)){const n=e[t];if((ue(n)||Po(n))&&(nB(n.type)||ue(n)&&n.timeUnit)){const r=WC(t);return OB(e,r)}}return!1}function IB(e){return nd(tpe,t=>{if(Rl(e,t)){const n=e[t];if(ee(n))return nd(n,r=>!!r.aggregate);{const r=Fs(n);return r&&!!r.aggregate}}return!1})}function PB(e,t){const n=[],r=[],i=[],s=[],o={};return S3(e,(a,u)=>{if(ue(a)){const{field:l,aggregate:c,bin:f,timeUnit:d,...h}=a;if(c||d||f){const p=w3(a),g=p==null?void 0:p.title;let m=pe(a,{forAs:!0});const y={...g?[]:{title:mf(a,t,{allowDisabling:!0})},...h,field:m};if(c){let v;if(Wu(c)?(v="argmax",m=pe({op:"argmax",field:c.argmax},{forAs:!0}),y.field=`${m}.${l}`):va(c)?(v="argmin",m=pe({op:"argmin",field:c.argmin},{forAs:!0}),y.field=`${m}.${l}`):c!=="boxplot"&&c!=="errorbar"&&c!=="errorband"&&(v=c),v){const b={op:v,as:m};l&&(b.field=l),s.push(b)}}else if(n.push(m),Dr(a)&&Mt(f)){if(r.push({bin:f,field:l,as:m}),n.push(pe(a,{binSuffix:"end"})),Wg(a,u)&&n.push(pe(a,{binSuffix:"range"})),ln(u)){const v={field:`${m}_end`};o[`${u}2`]=v}y.bin="binned",EP(u)||(y.type=oc)}else if(d&&!$c(d)){i.push({timeUnit:d,field:l,as:m});const v=Dr(a)&&a.type!==sd&&"time";v&&(u===Og||u===rc?y.formatType=v:dpe(u)?y.legend={formatType:v,...y.legend}:ln(u)&&(y.axis={formatType:v,...y.axis}))}o[u]=y}else n.push(l),o[u]=e[u]}else o[u]=e[u]}),{bins:r,timeUnits:i,aggregate:s,groupby:n,encoding:o}}function ame(e,t,n){const r=ppe(t,n);if(r){if(r==="binned"){const i=e[t===Ns?qt:On];return!!(ue(i)&&ue(e[t])&&Pn(i.bin))}}else return!1;return!0}function ume(e,t,n,r){const i={};for(const s of ie(e))wP(s)||ae(ige(s));for(let s of ape){if(!e[s])continue;const o=e[s];if(Ig(s)){const a=ope(s),u=i[a];if(ue(u)&&r0e(u.type)&&ue(o)&&!u.timeUnit){ae(Jpe(a));continue}}if(s==="angle"&&t==="arc"&&!e.theta&&(ae(Zpe),s=Xi),!ame(e,s,t)){ae(Wv(s,t));continue}if(s===Sa&&t==="line"){const a=Fs(e[s]);if(a!=null&&a.aggregate){ae(rge);continue}}if(s===Kr&&(n?"fill"in e:"stroke"in e)){ae(zP("encoding",{fill:"fill"in e,stroke:"stroke"in e}));continue}if(s===Lg||s===id&&!ee(o)&&!$s(o)||s===rc&&ee(o)){if(o){if(s===id){const a=e[s];if(AB(a)){i[s]=a;continue}}i[s]=ye(o).reduce((a,u)=>(ue(u)?a.push(A3(u,s)):ae(Hw(u,s)),a),[])}}else{if(s===rc&&o===null)i[s]=null;else if(!ue(o)&&!Po(o)&&!$s(o)&&!Ug(o)&&!Ce(o)){ae(Hw(o,s));continue}i[s]=DB(o,s,r)}}return i}function rb(e,t){const n={};for(const r of ie(e)){const i=DB(e[r],r,t,{compositeMark:!0});n[r]=i}return n}function lme(e){const t=[];for(const n of ie(e))if(Rl(e,n)){const r=e[n],i=ye(r);for(const s of i)ue(s)?t.push(s):Qv(s)&&t.push(s.condition)}return t}function S3(e,t,n){if(e)for(const r of ie(e)){const i=e[r];if(ee(i))for(const s of i)t.call(n,s,r);else t.call(n,i,r)}}function cme(e,t,n,r){return e?ie(e).reduce((i,s)=>{const o=e[s];return ee(o)?o.reduce((a,u)=>t.call(r,a,u,s),i):t.call(r,i,o,s)},n):n}function BB(e,t){return ie(t).reduce((n,r)=>{switch(r){case qt:case On:case Pv:case zv:case Bv:case Ns:case To:case Pu:case Pd:case Xi:case Aa:case Os:case Ea:case Bu:case Ls:case Is:case Ps:case Yi:case Og:case Zr:case Ec:case rc:return n;case id:if(e==="line"||e==="trail")return n;case Lg:case Iv:{const i=t[r];if(ee(i)||ue(i))for(const s of ye(i))s.aggregate||n.push(pe(s,{}));return n}case Sa:if(e==="trail")return n;case Kr:case No:case Oo:case ka:case zu:case ju:case qu:case Uu:{const i=Fs(t[r]);return i&&!i.aggregate&&n.push(pe(i,{})),n}}},[])}function fme(e){const{tooltip:t,...n}=e;if(!t)return{filteredEncoding:n};let r,i;if(ee(t)){for(const s of t)s.aggregate?(r||(r=[]),r.push(s)):(i||(i=[]),i.push(s));r&&(n.tooltip=r)}else t.aggregate?n.tooltip=t:i=t;return ee(i)&&i.length===1&&(i=i[0]),{customTooltipWithoutAggregatedField:i,filteredEncoding:n}}function Xw(e,t,n,r=!0){if("tooltip"in n)return{tooltip:n.tooltip};const i=e.map(({fieldPrefix:o,titlePrefix:a})=>{const u=r?` of ${k3(t)}`:"";return{field:o+t.field,type:t.type,title:Ce(a)?{signal:`${a}"${escape(u)}"`}:a+u}}),s=lme(n).map(Y0e);return{tooltip:[...i,...oo(s,rt)]}}function k3(e){const{title:t,field:n}=e;return un(t,n)}function C3(e,t,n,r,i){const{scale:s,axis:o}=n;return({partName:a,mark:u,positionPrefix:l,endPositionPrefix:c=void 0,extraEncoding:f={}})=>{const d=k3(n);return zB(e,a,i,{mark:u,encoding:{[t]:{field:`${l}_${n.field}`,type:n.type,...d!==void 0?{title:d}:{},...s!==void 0?{scale:s}:{},...o!==void 0?{axis:o}:{}},...me(c)?{[`${t}2`]:{field:`${c}_${n.field}`}}:{},...r,...f}})}}function zB(e,t,n,r){const{clip:i,color:s,opacity:o}=e,a=e.type;return e[t]||e[t]===void 0&&n[t]?[{...r,mark:{...n[t],...i?{clip:i}:{},...s?{color:s}:{},...o?{opacity:o}:{},...Eo(r.mark)?r.mark:{type:r.mark},style:`${a}-${String(t)}`,...Du(e[t])?{}:e[t]}}]:[]}function jB(e,t,n){const{encoding:r}=e,i=t==="vertical"?"y":"x",s=r[i],o=r[`${i}2`],a=r[`${i}Error`],u=r[`${i}Error2`];return{continuousAxisChannelDef:D0(s,n),continuousAxisChannelDef2:D0(o,n),continuousAxisChannelDefError:D0(a,n),continuousAxisChannelDefError2:D0(u,n),continuousAxis:i}}function D0(e,t){if(e!=null&&e.aggregate){const{aggregate:n,...r}=e;return n!==t&&ae(Rge(n,t)),r}else return e}function UB(e,t){const{mark:n,encoding:r}=e,{x:i,y:s}=r;if(Eo(n)&&n.orient)return n.orient;if(Qa(i)){if(Qa(s)){const o=ue(i)&&i.aggregate,a=ue(s)&&s.aggregate;if(!o&&a===t)return"vertical";if(!a&&o===t)return"horizontal";if(o===t&&a===t)throw new Error("Both x and y cannot have aggregate");return ld(s)&&!ld(i)?"horizontal":"vertical"}return"horizontal"}else{if(Qa(s))return"vertical";throw new Error(`Need a valid continuous axis for ${t}s`)}}const ty="boxplot",dme=["box","median","outliers","rule","ticks"],hme=new nb(ty,WB);function qB(e){return ft(e)?"tukey":e}function WB(e,{config:t}){e={...e,encoding:rb(e.encoding,t)};const{mark:n,encoding:r,params:i,projection:s,...o}=e,a=Eo(n)?n:{type:n};i&&ae(PP("boxplot"));const u=a.extent??t.boxplot.extent,l=wt("size",a,t),c=a.invalid,f=qB(u),{bins:d,timeUnits:h,transform:p,continuousAxisChannelDef:g,continuousAxis:m,groupby:y,aggregate:v,encodingWithoutContinuousAxis:b,ticksOrient:x,boxOrient:_,customTooltipWithoutAggregatedField:A}=pme(e,u,t),E=Id(g.field),{color:S,size:k,...$}=b,D=It=>C3(a,m,g,It,t.boxplot),M=D($),R=D(b),F=(ge(t.boxplot.box)?t.boxplot.box.color:t.mark.color)||"#4c78a8",C=D({...$,...k?{size:k}:{},color:{condition:{test:`${vt(`lower_box_${g.field}`)} >= ${vt(`upper_box_${g.field}`)}`,...S||{value:F}}}}),T=Xw([{fieldPrefix:f==="min-max"?"upper_whisker_":"max_",titlePrefix:"Max"},{fieldPrefix:"upper_box_",titlePrefix:"Q3"},{fieldPrefix:"mid_box_",titlePrefix:"Median"},{fieldPrefix:"lower_box_",titlePrefix:"Q1"},{fieldPrefix:f==="min-max"?"lower_whisker_":"min_",titlePrefix:"Min"}],g,b),O={type:"tick",color:"black",opacity:1,orient:x,invalid:c,aria:!1},N=f==="min-max"?T:Xw([{fieldPrefix:"upper_whisker_",titlePrefix:"Upper Whisker"},{fieldPrefix:"lower_whisker_",titlePrefix:"Lower Whisker"}],g,b),L=[...M({partName:"rule",mark:{type:"rule",invalid:c,aria:!1},positionPrefix:"lower_whisker",endPositionPrefix:"lower_box",extraEncoding:N}),...M({partName:"rule",mark:{type:"rule",invalid:c,aria:!1},positionPrefix:"upper_box",endPositionPrefix:"upper_whisker",extraEncoding:N}),...M({partName:"ticks",mark:O,positionPrefix:"lower_whisker",extraEncoding:N}),...M({partName:"ticks",mark:O,positionPrefix:"upper_whisker",extraEncoding:N})],z=[...f!=="tukey"?L:[],...R({partName:"box",mark:{type:"bar",...l?{size:l}:{},orient:_,invalid:c,ariaRoleDescription:"box"},positionPrefix:"lower_box",endPositionPrefix:"upper_box",extraEncoding:T}),...C({partName:"median",mark:{type:"tick",invalid:c,...ge(t.boxplot.median)&&t.boxplot.median.color?{color:t.boxplot.median.color}:{},...l?{size:l}:{},orient:x,aria:!1},positionPrefix:"mid_box",extraEncoding:T})];if(f==="min-max")return{...o,transform:(o.transform??[]).concat(p),layer:z};const U=vt(`lower_box_${g.field}`),Q=vt(`upper_box_${g.field}`),de=`(${Q} - ${U})`,we=`${U} - ${u} * ${de}`,ne=`${Q} + ${u} * ${de}`,Ee=vt(g.field),Ke={joinaggregate:HB(g.field),groupby:y},fe={transform:[{filter:`(${we} <= ${Ee}) && (${Ee} <= ${ne})`},{aggregate:[{op:"min",field:g.field,as:`lower_whisker_${E}`},{op:"max",field:g.field,as:`upper_whisker_${E}`},{op:"min",field:`lower_box_${g.field}`,as:`lower_box_${E}`},{op:"max",field:`upper_box_${g.field}`,as:`upper_box_${E}`},...v],groupby:y}],layer:L},{tooltip:I,...q}=$,{scale:se,axis:W}=g,ve=k3(g),xe=Hr(W,["title"]),Fe=zB(a,"outliers",t.boxplot,{transform:[{filter:`(${Ee} < ${we}) || (${Ee} > ${ne})`}],mark:"point",encoding:{[m]:{field:g.field,type:g.type,...ve!==void 0?{title:ve}:{},...se!==void 0?{scale:se}:{},...Et(xe)?{}:{axis:xe}},...q,...S?{color:S}:{},...A?{tooltip:A}:{}}})[0];let ze;const ot=[...d,...h,Ke];return Fe?ze={transform:ot,layer:[Fe,fe]}:(ze=fe,ze.transform.unshift(...ot)),{...o,layer:[ze,{transform:p,layer:z}]}}function HB(e){const t=Id(e);return[{op:"q1",field:e,as:`lower_box_${t}`},{op:"q3",field:e,as:`upper_box_${t}`}]}function pme(e,t,n){const r=UB(e,ty),{continuousAxisChannelDef:i,continuousAxis:s}=jB(e,r,ty),o=i.field,a=Id(o),u=qB(t),l=[...HB(o),{op:"median",field:o,as:`mid_box_${a}`},{op:"min",field:o,as:(u==="min-max"?"lower_whisker_":"min_")+a},{op:"max",field:o,as:(u==="min-max"?"upper_whisker_":"max_")+a}],c=u==="min-max"||u==="tukey"?[]:[{calculate:`${vt(`upper_box_${a}`)} - ${vt(`lower_box_${a}`)}`,as:`iqr_${a}`},{calculate:`min(${vt(`upper_box_${a}`)} + ${vt(`iqr_${a}`)} * ${t}, ${vt(`max_${a}`)})`,as:`upper_whisker_${a}`},{calculate:`max(${vt(`lower_box_${a}`)} - ${vt(`iqr_${a}`)} * ${t}, ${vt(`min_${a}`)})`,as:`lower_whisker_${a}`}],{[s]:f,...d}=e.encoding,{customTooltipWithoutAggregatedField:h,filteredEncoding:p}=fme(d),{bins:g,timeUnits:m,aggregate:y,groupby:v,encoding:b}=PB(p,n),x=r==="vertical"?"horizontal":"vertical",_=r,A=[...g,...m,{aggregate:[...y,...l],groupby:v},...c];return{bins:g,timeUnits:m,transform:A,groupby:v,aggregate:y,continuousAxisChannelDef:i,continuousAxis:s,encodingWithoutContinuousAxis:b,ticksOrient:x,boxOrient:_,customTooltipWithoutAggregatedField:h}}const $3="errorbar",gme=["ticks","rule"],mme=new nb($3,GB);function GB(e,{config:t}){e={...e,encoding:rb(e.encoding,t)};const{transform:n,continuousAxisChannelDef:r,continuousAxis:i,encodingWithoutContinuousAxis:s,ticksOrient:o,markDef:a,outerSpec:u,tooltipEncoding:l}=YB(e,$3,t);delete s.size;const c=C3(a,i,r,s,t.errorbar),f=a.thickness,d=a.size,h={type:"tick",orient:o,aria:!1,...f!==void 0?{thickness:f}:{},...d!==void 0?{size:d}:{}},p=[...c({partName:"ticks",mark:h,positionPrefix:"lower",extraEncoding:l}),...c({partName:"ticks",mark:h,positionPrefix:"upper",extraEncoding:l}),...c({partName:"rule",mark:{type:"rule",ariaRoleDescription:"errorbar",...f!==void 0?{size:f}:{}},positionPrefix:"lower",endPositionPrefix:"upper",extraEncoding:l})];return{...u,transform:n,...p.length>1?{layer:p}:{...p[0]}}}function yme(e,t){const{encoding:n}=e;if(vme(n))return{orient:UB(e,t),inputType:"raw"};const r=bme(n),i=xme(n),s=n.x,o=n.y;if(r){if(i)throw new Error(`${t} cannot be both type aggregated-upper-lower and aggregated-error`);const a=n.x2,u=n.y2;if(Ue(a)&&Ue(u))throw new Error(`${t} cannot have both x2 and y2`);if(Ue(a)){if(Qa(s))return{orient:"horizontal",inputType:"aggregated-upper-lower"};throw new Error(`Both x and x2 have to be quantitative in ${t}`)}else if(Ue(u)){if(Qa(o))return{orient:"vertical",inputType:"aggregated-upper-lower"};throw new Error(`Both y and y2 have to be quantitative in ${t}`)}throw new Error("No ranged axis")}else{const a=n.xError,u=n.xError2,l=n.yError,c=n.yError2;if(Ue(u)&&!Ue(a))throw new Error(`${t} cannot have xError2 without xError`);if(Ue(c)&&!Ue(l))throw new Error(`${t} cannot have yError2 without yError`);if(Ue(a)&&Ue(l))throw new Error(`${t} cannot have both xError and yError with both are quantiative`);if(Ue(a)){if(Qa(s))return{orient:"horizontal",inputType:"aggregated-error"};throw new Error("All x, xError, and xError2 (if exist) have to be quantitative")}else if(Ue(l)){if(Qa(o))return{orient:"vertical",inputType:"aggregated-error"};throw new Error("All y, yError, and yError2 (if exist) have to be quantitative")}throw new Error("No ranged axis")}}function vme(e){return(Ue(e.x)||Ue(e.y))&&!Ue(e.x2)&&!Ue(e.y2)&&!Ue(e.xError)&&!Ue(e.xError2)&&!Ue(e.yError)&&!Ue(e.yError2)}function bme(e){return Ue(e.x2)||Ue(e.y2)}function xme(e){return Ue(e.xError)||Ue(e.xError2)||Ue(e.yError)||Ue(e.yError2)}function YB(e,t,n){const{mark:r,encoding:i,params:s,projection:o,...a}=e,u=Eo(r)?r:{type:r};s&&ae(PP(t));const{orient:l,inputType:c}=yme(e,t),{continuousAxisChannelDef:f,continuousAxisChannelDef2:d,continuousAxisChannelDefError:h,continuousAxisChannelDefError2:p,continuousAxis:g}=jB(e,l,t),{errorBarSpecificAggregate:m,postAggregateCalculates:y,tooltipSummary:v,tooltipTitleWithFieldName:b}=_me(u,f,d,h,p,c,t,n),{[g]:x,[g==="x"?"x2":"y2"]:_,[g==="x"?"xError":"yError"]:A,[g==="x"?"xError2":"yError2"]:E,...S}=i,{bins:k,timeUnits:$,aggregate:D,groupby:M,encoding:R}=PB(S,n),F=[...D,...m],C=c!=="raw"?[]:M,T=Xw(v,f,R,b);return{transform:[...a.transform??[],...k,...$,...F.length===0?[]:[{aggregate:F,groupby:C}],...y],groupby:C,continuousAxisChannelDef:f,continuousAxis:g,encodingWithoutContinuousAxis:R,ticksOrient:l==="vertical"?"horizontal":"vertical",markDef:u,outerSpec:a,tooltipEncoding:T}}function _me(e,t,n,r,i,s,o,a){let u=[],l=[];const c=t.field;let f,d=!1;if(s==="raw"){const h=e.center?e.center:e.extent?e.extent==="iqr"?"median":"mean":a.errorbar.center,p=e.extent?e.extent:h==="mean"?"stderr":"iqr";if(h==="median"!=(p==="iqr")&&ae(Mge(h,p,o)),p==="stderr"||p==="stdev")u=[{op:p,field:c,as:`extent_${c}`},{op:h,field:c,as:`center_${c}`}],l=[{calculate:`${vt(`center_${c}`)} + ${vt(`extent_${c}`)}`,as:`upper_${c}`},{calculate:`${vt(`center_${c}`)} - ${vt(`extent_${c}`)}`,as:`lower_${c}`}],f=[{fieldPrefix:"center_",titlePrefix:Ng(h)},{fieldPrefix:"upper_",titlePrefix:XM(h,p,"+")},{fieldPrefix:"lower_",titlePrefix:XM(h,p,"-")}],d=!0;else{let g,m,y;p==="ci"?(g="mean",m="ci0",y="ci1"):(g="median",m="q1",y="q3"),u=[{op:m,field:c,as:`lower_${c}`},{op:y,field:c,as:`upper_${c}`},{op:g,field:c,as:`center_${c}`}],f=[{fieldPrefix:"upper_",titlePrefix:mf({field:c,aggregate:y,type:"quantitative"},a,{allowDisabling:!1})},{fieldPrefix:"lower_",titlePrefix:mf({field:c,aggregate:m,type:"quantitative"},a,{allowDisabling:!1})},{fieldPrefix:"center_",titlePrefix:mf({field:c,aggregate:g,type:"quantitative"},a,{allowDisabling:!1})}]}}else{(e.center||e.extent)&&ae(Dge(e.center,e.extent)),s==="aggregated-upper-lower"?(f=[],l=[{calculate:vt(n.field),as:`upper_${c}`},{calculate:vt(c),as:`lower_${c}`}]):s==="aggregated-error"&&(f=[{fieldPrefix:"",titlePrefix:c}],l=[{calculate:`${vt(c)} + ${vt(r.field)}`,as:`upper_${c}`}],i?l.push({calculate:`${vt(c)} + ${vt(i.field)}`,as:`lower_${c}`}):l.push({calculate:`${vt(c)} - ${vt(r.field)}`,as:`lower_${c}`}));for(const h of l)f.push({fieldPrefix:h.as.substring(0,6),titlePrefix:nc(nc(h.calculate,"datum['",""),"']","")})}return{postAggregateCalculates:l,errorBarSpecificAggregate:u,tooltipSummary:f,tooltipTitleWithFieldName:d}}function XM(e,t,n){return`${Ng(e)} ${n} ${t}`}const F3="errorband",wme=["band","borders"],Eme=new nb(F3,VB);function VB(e,{config:t}){e={...e,encoding:rb(e.encoding,t)};const{transform:n,continuousAxisChannelDef:r,continuousAxis:i,encodingWithoutContinuousAxis:s,markDef:o,outerSpec:a,tooltipEncoding:u}=YB(e,F3,t),l=o,c=C3(l,i,r,s,t.errorband),f=e.encoding.x!==void 0&&e.encoding.y!==void 0;let d={type:f?"area":"rect"},h={type:f?"line":"rule"};const p={...l.interpolate?{interpolate:l.interpolate}:{},...l.tension&&l.interpolate?{tension:l.tension}:{}};return f?(d={...d,...p,ariaRoleDescription:"errorband"},h={...h,...p,aria:!1}):l.interpolate?ae(zM("interpolate")):l.tension&&ae(zM("tension")),{...a,transform:n,layer:[...c({partName:"band",mark:d,positionPrefix:"lower",endPositionPrefix:"upper",extraEncoding:u}),...c({partName:"borders",mark:h,positionPrefix:"lower",extraEncoding:u}),...c({partName:"borders",mark:h,positionPrefix:"upper",extraEncoding:u})]}}const XB={};function D3(e,t,n){const r=new nb(e,t);XB[e]={normalizer:r,parts:n}}function Ame(){return ie(XB)}D3(ty,WB,dme);D3($3,GB,gme);D3(F3,VB,wme);const Sme=["gradientHorizontalMaxLength","gradientHorizontalMinLength","gradientVerticalMaxLength","gradientVerticalMinLength","unselectedOpacity"],KB={titleAlign:"align",titleAnchor:"anchor",titleAngle:"angle",titleBaseline:"baseline",titleColor:"color",titleFont:"font",titleFontSize:"fontSize",titleFontStyle:"fontStyle",titleFontWeight:"fontWeight",titleLimit:"limit",titleLineHeight:"lineHeight",titleOrient:"orient",titlePadding:"offset"},ZB={labelAlign:"align",labelAnchor:"anchor",labelAngle:"angle",labelBaseline:"baseline",labelColor:"color",labelFont:"font",labelFontSize:"fontSize",labelFontStyle:"fontStyle",labelFontWeight:"fontWeight",labelLimit:"limit",labelLineHeight:"lineHeight",labelOrient:"orient",labelPadding:"offset"},kme=ie(KB),Cme=ie(ZB),$me={header:1,headerRow:1,headerColumn:1,headerFacet:1},JB=ie($me),QB=["size","shape","fill","stroke","strokeDash","strokeWidth","opacity"],Fme={gradientHorizontalMaxLength:200,gradientHorizontalMinLength:100,gradientVerticalMaxLength:200,gradientVerticalMinLength:64,unselectedOpacity:.35},Dme={aria:1,clipHeight:1,columnPadding:1,columns:1,cornerRadius:1,description:1,direction:1,fillColor:1,format:1,formatType:1,gradientLength:1,gradientOpacity:1,gradientStrokeColor:1,gradientStrokeWidth:1,gradientThickness:1,gridAlign:1,labelAlign:1,labelBaseline:1,labelColor:1,labelFont:1,labelFontSize:1,labelFontStyle:1,labelFontWeight:1,labelLimit:1,labelOffset:1,labelOpacity:1,labelOverlap:1,labelPadding:1,labelSeparation:1,legendX:1,legendY:1,offset:1,orient:1,padding:1,rowPadding:1,strokeColor:1,symbolDash:1,symbolDashOffset:1,symbolFillColor:1,symbolLimit:1,symbolOffset:1,symbolOpacity:1,symbolSize:1,symbolStrokeColor:1,symbolStrokeWidth:1,symbolType:1,tickCount:1,tickMinStep:1,title:1,titleAlign:1,titleAnchor:1,titleBaseline:1,titleColor:1,titleFont:1,titleFontSize:1,titleFontStyle:1,titleFontWeight:1,titleLimit:1,titleLineHeight:1,titleOpacity:1,titleOrient:1,titlePadding:1,type:1,values:1,zindex:1},Ds="_vgsid_",Mme={point:{on:"click",fields:[Ds],toggle:"event.shiftKey",resolve:"global",clear:"dblclick"},interval:{on:"[pointerdown, window:pointerup] > window:pointermove!",encodings:["x","y"],translate:"[pointerdown, window:pointerup] > window:pointermove!",zoom:"wheel!",mark:{fill:"#333",fillOpacity:.125,stroke:"white"},resolve:"global",clear:"dblclick"}};function M3(e){return e==="legend"||!!(e!=null&&e.legend)}function tx(e){return M3(e)&&ge(e)}function R3(e){return!!(e!=null&&e.select)}function ez(e){const t=[];for(const n of e||[]){if(R3(n))continue;const{expr:r,bind:i,...s}=n;if(i&&r){const o={...s,bind:i,init:r};t.push(o)}else{const o={...s,...r?{update:r}:{},...i?{bind:i}:{}};t.push(o)}}return t}function Rme(e){return ib(e)||N3(e)||T3(e)}function T3(e){return oe(e,"concat")}function ib(e){return oe(e,"vconcat")}function N3(e){return oe(e,"hconcat")}function tz({step:e,offsetIsDiscrete:t}){return t?e.for??"offset":"position"}function Ao(e){return oe(e,"step")}function KM(e){return oe(e,"view")||oe(e,"width")||oe(e,"height")}const ZM=20,Tme={align:1,bounds:1,center:1,columns:1,spacing:1},Nme=ie(Tme);function Ome(e,t,n){const r=n[t],i={},{spacing:s,columns:o}=r;s!==void 0&&(i.spacing=s),o!==void 0&&(Jv(e)&&!jg(e.facet)||T3(e))&&(i.columns=o),ib(e)&&(i.columns=1);for(const a of Nme)if(e[a]!==void 0)if(a==="spacing"){const u=e[a];i[a]=ft(u)?u:{row:u.row??s,column:u.column??s}}else i[a]=e[a];return i}function Kw(e,t){return e[t]??e[t==="width"?"continuousWidth":"continuousHeight"]}function Zw(e,t){const n=ny(e,t);return Ao(n)?n.step:nz}function ny(e,t){const n=e[t]??e[t==="width"?"discreteWidth":"discreteHeight"];return un(n,{step:e.step})}const nz=20,Lme={continuousWidth:200,continuousHeight:200,step:nz},Ime={background:"white",padding:5,timeFormat:"%b %d, %Y",countTitle:"Count of Records",view:Lme,mark:$0e,arc:{},area:{},bar:R0e,circle:{},geoshape:{},image:{},line:{},point:{},rect:g3,rule:{color:"black"},square:{},text:{color:"black"},tick:T0e,trail:{},boxplot:{size:14,extent:1.5,box:{},median:{color:"white"},outliers:{},rule:{},ticks:null},errorbar:{center:"mean",rule:!0,ticks:!1},errorband:{band:{opacity:.3},borders:!1},scale:l0e,projection:{},legend:Fme,header:{titlePadding:10,labelPadding:10},headerColumn:{},headerRow:{},headerFacet:{},selection:Mme,style:{},title:{},facet:{spacing:ZM},concat:{spacing:ZM},normalizedNumberFormat:".0%"},Wo=["#4c78a8","#f58518","#e45756","#72b7b2","#54a24b","#eeca3b","#b279a2","#ff9da6","#9d755d","#bab0ac"],JM={text:11,guideLabel:10,guideTitle:11,groupTitle:13,groupSubtitle:12},QM={blue:Wo[0],orange:Wo[1],red:Wo[2],teal:Wo[3],green:Wo[4],yellow:Wo[5],purple:Wo[6],pink:Wo[7],brown:Wo[8],gray0:"#000",gray1:"#111",gray2:"#222",gray3:"#333",gray4:"#444",gray5:"#555",gray6:"#666",gray7:"#777",gray8:"#888",gray9:"#999",gray10:"#aaa",gray11:"#bbb",gray12:"#ccc",gray13:"#ddd",gray14:"#eee",gray15:"#fff"};function Pme(e={}){return{signals:[{name:"color",value:ge(e)?{...QM,...e}:QM}],mark:{color:{signal:"color.blue"}},rule:{color:{signal:"color.gray0"}},text:{color:{signal:"color.gray0"}},style:{"guide-label":{fill:{signal:"color.gray0"}},"guide-title":{fill:{signal:"color.gray0"}},"group-title":{fill:{signal:"color.gray0"}},"group-subtitle":{fill:{signal:"color.gray0"}},cell:{stroke:{signal:"color.gray8"}}},axis:{domainColor:{signal:"color.gray13"},gridColor:{signal:"color.gray8"},tickColor:{signal:"color.gray13"}},range:{category:[{signal:"color.blue"},{signal:"color.orange"},{signal:"color.red"},{signal:"color.teal"},{signal:"color.green"},{signal:"color.yellow"},{signal:"color.purple"},{signal:"color.pink"},{signal:"color.brown"},{signal:"color.grey8"}]}}}function Bme(e){return{signals:[{name:"fontSize",value:ge(e)?{...JM,...e}:JM}],text:{fontSize:{signal:"fontSize.text"}},style:{"guide-label":{fontSize:{signal:"fontSize.guideLabel"}},"guide-title":{fontSize:{signal:"fontSize.guideTitle"}},"group-title":{fontSize:{signal:"fontSize.groupTitle"}},"group-subtitle":{fontSize:{signal:"fontSize.groupSubtitle"}}}}}function zme(e){return{text:{font:e},style:{"guide-label":{font:e},"guide-title":{font:e},"group-title":{font:e},"group-subtitle":{font:e}}}}function rz(e){const t=ie(e||{}),n={};for(const r of t){const i=e[r];n[r]=Hg(i)?MP(i):li(i)}return n}function jme(e){const t=ie(e),n={};for(const r of t)n[r]=rz(e[r]);return n}const Ume=[...dB,...NB,...JB,"background","padding","legend","lineBreak","scale","style","title","view"];function iz(e={}){const{color:t,font:n,fontSize:r,selection:i,...s}=e,o=xd({},Be(Ime),n?zme(n):{},t?Pme(t):{},r?Bme(r):{},s||{});i&&_d(o,"selection",i,!0);const a=Hr(o,Ume);for(const u of["background","lineBreak","padding"])o[u]&&(a[u]=li(o[u]));for(const u of dB)o[u]&&(a[u]=zn(o[u]));for(const u of NB)o[u]&&(a[u]=rz(o[u]));for(const u of JB)o[u]&&(a[u]=zn(o[u]));if(o.legend&&(a.legend=zn(o.legend)),o.scale){const{invalid:u,...l}=o.scale,c=zn(u,{level:1});a.scale={...zn(l),...ie(c).length>0?{invalid:c}:{}}}return o.style&&(a.style=jme(o.style)),o.title&&(a.title=zn(o.title)),o.view&&(a.view=zn(o.view)),a}const qme=new Set(["view",...w0e]),Wme=["color","fontSize","background","padding","facet","concat","numberFormat","numberFormatType","normalizedNumberFormat","normalizedNumberFormatType","timeFormat","countTitle","header","axisQuantitative","axisTemporal","axisDiscrete","axisPoint","axisXBand","axisXPoint","axisXDiscrete","axisXQuantitative","axisXTemporal","axisYBand","axisYPoint","axisYDiscrete","axisYQuantitative","axisYTemporal","scale","selection","overlay"],Hme={view:["continuousWidth","continuousHeight","discreteWidth","discreteHeight","step"],...C0e};function Gme(e){e=Be(e);for(const t of Wme)delete e[t];if(e.axis)for(const t in e.axis)Hg(e.axis[t])&&delete e.axis[t];if(e.legend)for(const t of Sme)delete e.legend[t];if(e.mark){for(const t of UM)delete e.mark[t];e.mark.tooltip&&ge(e.mark.tooltip)&&delete e.mark.tooltip}e.params&&(e.signals=(e.signals||[]).concat(ez(e.params)),delete e.params);for(const t of qme){for(const r of UM)delete e[t][r];const n=Hme[t];if(n)for(const r of n)delete e[t][r];Vme(e,t)}for(const t of Ame())delete e[t];Yme(e);for(const t in e)ge(e[t])&&Et(e[t])&&delete e[t];return Et(e)?void 0:e}function Yme(e){const{titleMarkConfig:t,subtitleMarkConfig:n,subtitle:r}=DP(e.title);Et(t)||(e.style["group-title"]={...e.style["group-title"],...t}),Et(n)||(e.style["group-subtitle"]={...e.style["group-subtitle"],...n}),Et(r)?delete e.title:e.title=r}function Vme(e,t,n,r){const i=e[t];t==="view"&&(n="cell");const s={...i,...e.style[n??t]};Et(s)||(e.style[n??t]=s),delete e[t]}function sb(e){return oe(e,"layer")}function Xme(e){return oe(e,"repeat")}function Kme(e){return!ee(e.repeat)&&oe(e.repeat,"layer")}class O3{map(t,n){return Jv(t)?this.mapFacet(t,n):Xme(t)?this.mapRepeat(t,n):N3(t)?this.mapHConcat(t,n):ib(t)?this.mapVConcat(t,n):T3(t)?this.mapConcat(t,n):this.mapLayerOrUnit(t,n)}mapLayerOrUnit(t,n){if(sb(t))return this.mapLayer(t,n);if($a(t))return this.mapUnit(t,n);throw new Error(KC(t))}mapLayer(t,n){return{...t,layer:t.layer.map(r=>this.mapLayerOrUnit(r,n))}}mapHConcat(t,n){return{...t,hconcat:t.hconcat.map(r=>this.map(r,n))}}mapVConcat(t,n){return{...t,vconcat:t.vconcat.map(r=>this.map(r,n))}}mapConcat(t,n){const{concat:r,...i}=t;return{...i,concat:r.map(s=>this.map(s,n))}}mapFacet(t,n){return{...t,spec:this.map(t.spec,n)}}mapRepeat(t,n){return{...t,spec:this.map(t.spec,n)}}}const Zme={zero:1,center:1,normalize:1};function Jme(e){return be(Zme,e)}const Qme=new Set([lB,Vv,Yv,X1,Kv,h3,p3,Xv,cB,d3]),e1e=new Set([Vv,Yv,lB]);function Gc(e){return ue(e)&&ad(e)==="quantitative"&&!e.bin}function e4(e,t,{orient:n,type:r}){const i=t==="x"?"y":"radius",s=t==="x"&&["bar","area"].includes(r),o=e[t],a=e[i];if(ue(o)&&ue(a))if(Gc(o)&&Gc(a)){if(o.stack)return t;if(a.stack)return i;const u=ue(o)&&!!o.aggregate,l=ue(a)&&!!a.aggregate;if(u!==l)return u?t:i;if(s){if(n==="vertical")return i;if(n==="horizontal")return t}}else{if(Gc(o))return t;if(Gc(a))return i}else{if(Gc(o))return s&&n==="vertical"?void 0:t;if(Gc(a))return s&&n==="horizontal"?void 0:i}}function t1e(e){switch(e){case"x":return"y";case"y":return"x";case"theta":return"radius";case"radius":return"theta"}}function sz(e,t){var g,m;const n=Eo(e)?e:{type:e},r=n.type;if(!Qme.has(r))return null;const i=e4(t,"x",n)||e4(t,"theta",n);if(!i)return null;const s=t[i],o=ue(s)?pe(s,{}):void 0,a=t1e(i),u=[],l=new Set;if(t[a]){const y=t[a],v=ue(y)?pe(y,{}):void 0;v&&v!==o&&(u.push(a),l.add(v))}const c=a==="x"?"xOffset":"yOffset",f=t[c],d=ue(f)?pe(f,{}):void 0;d&&d!==o&&(u.push(c),l.add(d));const h=upe.reduce((y,v)=>{if(v!=="tooltip"&&Rl(t,v)){const b=t[v];for(const x of ye(b)){const _=Fs(x);if(_.aggregate)continue;const A=pe(_,{});(!A||!l.has(A))&&y.push({channel:v,fieldDef:_})}}return y},[]);let p;return s.stack!==void 0?Du(s.stack)?p=s.stack?"zero":null:p=s.stack:e1e.has(r)&&(p="zero"),!p||!Jme(p)||IB(t)&&h.length===0?null:((g=s==null?void 0:s.scale)!=null&&g.type&&((m=s==null?void 0:s.scale)==null?void 0:m.type)!==jn.LINEAR&&s!=null&&s.stack&&ae(Cge(s.scale.type)),Ue(t[Lo(i)])?(s.stack!==void 0&&ae(kge(i)),null):(ue(s)&&s.aggregate&&!_pe.has(s.aggregate)&&ae($ge(s.aggregate)),{groupbyChannels:u,groupbyFields:l,fieldChannel:i,impute:s.impute===null?!1:Hu(r),stackBy:h,offset:p}))}function oz(e,t,n){const r=zn(e),i=wt("orient",r,n);if(r.orient=s1e(r.type,t,i),i!==void 0&&i!==r.orient&&ae(cge(r.orient,i)),r.type==="bar"&&r.orient){const u=wt("cornerRadiusEnd",r,n);if(u!==void 0){const l=r.orient==="horizontal"&&t.x2||r.orient==="vertical"&&t.y2?["cornerRadius"]:D0e[r.orient];for(const c of l)r[c]=u;r.cornerRadiusEnd!==void 0&&delete r.cornerRadiusEnd}}const s=wt("opacity",r,n),o=wt("fillOpacity",r,n);return s===void 0&&o===void 0&&(r.opacity=r1e(r.type,t)),wt("cursor",r,n)===void 0&&(r.cursor=n1e(r,t,n)),r}function n1e(e,t,n){return t.href||e.href||wt("href",e,n)?"pointer":e.cursor}function r1e(e,t){if(Qe([Kv,d3,h3,p3],e)&&!IB(t))return .7}function i1e(e,t,{graticule:n}){if(n)return!1;const r=wo("filled",e,t),i=e.type;return un(r,i!==Kv&&i!==Xv&&i!==X1)}function s1e(e,t,n){switch(e){case Kv:case h3:case p3:case cB:case x0e:case b0e:return}const{x:r,y:i,x2:s,y2:o}=t;switch(e){case Vv:if(ue(r)&&(Pn(r.bin)||ue(i)&&i.aggregate&&!r.aggregate))return"vertical";if(ue(i)&&(Pn(i.bin)||ue(r)&&r.aggregate&&!i.aggregate))return"horizontal";if(o||s){if(n)return n;if(!s)return(ue(r)&&r.type===oc&&!Mt(r.bin)||Z1(r))&&ue(i)&&Pn(i.bin)?"horizontal":"vertical";if(!o)return(ue(i)&&i.type===oc&&!Mt(i.bin)||Z1(i))&&ue(r)&&Pn(r.bin)?"vertical":"horizontal"}case X1:if(s&&!(ue(r)&&Pn(r.bin))&&o&&!(ue(i)&&Pn(i.bin)))return;case Yv:if(o)return ue(i)&&Pn(i.bin)?"horizontal":"vertical";if(s)return ue(r)&&Pn(r.bin)?"vertical":"horizontal";if(e===X1){if(r&&!i)return"vertical";if(i&&!r)return"horizontal"}case Xv:case d3:{const a=GM(r),u=GM(i);if(n)return n;if(a&&!u)return e!=="tick"?"horizontal":"vertical";if(!a&&u)return e!=="tick"?"vertical":"horizontal";if(a&&u)return"vertical";{const l=Dr(r)&&r.type===sd,c=Dr(i)&&i.type===sd;if(l&&!c)return"vertical";if(!l&&c)return"horizontal"}return}}return"vertical"}function o1e(e){const{point:t,line:n,...r}=e;return ie(r).length>1?r:r.type}function a1e(e){for(const t of["line","area","rule","trail"])e[t]&&(e={...e,[t]:Hr(e[t],["point","line"])});return e}function nx(e,t={},n){return e.point==="transparent"?{opacity:0}:e.point?ge(e.point)?e.point:{}:e.point!==void 0?null:t.point||n.shape?ge(t.point)?t.point:{}:void 0}function t4(e,t={}){return e.line?e.line===!0?{}:e.line:e.line!==void 0?null:t.line?t.line===!0?{}:t.line:void 0}class u1e{constructor(){this.name="path-overlay"}hasMatchingType(t,n){if($a(t)){const{mark:r,encoding:i}=t,s=Eo(r)?r:{type:r};switch(s.type){case"line":case"rule":case"trail":return!!nx(s,n[s.type],i);case"area":return!!nx(s,n[s.type],i)||!!t4(s,n[s.type])}}return!1}run(t,n,r){const{config:i}=n,{params:s,projection:o,mark:a,name:u,encoding:l,...c}=t,f=rb(l,i),d=Eo(a)?a:{type:a},h=nx(d,i[d.type],f),p=d.type==="area"&&t4(d,i[d.type]),g=[{name:u,...s?{params:s}:{},mark:o1e({...d.type==="area"&&d.opacity===void 0&&d.fillOpacity===void 0?{opacity:.7}:{},...d}),encoding:Hr(f,["shape"])}],m=sz(oz(d,f,i),f);let y=f;if(m){const{fieldChannel:v,offset:b}=m;y={...f,[v]:{...f[v],...b?{stack:b}:{}}}}return y=Hr(y,["y2","x2"]),p&&g.push({...o?{projection:o}:{},mark:{type:"line",...td(d,["clip","interpolate","tension","tooltip"]),...p},encoding:y}),h&&g.push({...o?{projection:o}:{},mark:{type:"point",opacity:1,filled:!0,...td(d,["clip","tooltip"]),...h},encoding:y}),r({...c,layer:g},{...n,config:a1e(i)})}}function l1e(e,t){return t?jg(e)?uz(e,t):az(e,t):e}function rx(e,t){return t?uz(e,t):e}function Jw(e,t,n){const r=t[e];if(H0e(r)){if(r.repeat in n)return{...t,[e]:n[r.repeat]};ae(jpe(r.repeat));return}return t}function az(e,t){if(e=Jw("field",e,t),e!==void 0){if(e===null)return null;if(_3(e)&&fa(e.sort)){const n=Jw("field",e.sort,t);e={...e,...n?{sort:n}:{}}}return e}}function n4(e,t){if(ue(e))return az(e,t);{const n=Jw("datum",e,t);return n!==e&&!n.type&&(n.type="nominal"),n}}function r4(e,t){if(Ue(e)){const n=n4(e,t);if(n)return n;if(Ug(e))return{condition:e.condition}}else{if(qg(e)){const n=n4(e.condition,t);if(n)return{...e,condition:n};{const{condition:r,...i}=e;return i}}return e}}function uz(e,t){const n={};for(const r in e)if(oe(e,r)){const i=e[r];if(ee(i))n[r]=i.map(s=>r4(s,t)).filter(s=>s);else{const s=r4(i,t);s!==void 0&&(n[r]=s)}}return n}class c1e{constructor(){this.name="RuleForRangedLine"}hasMatchingType(t){if($a(t)){const{encoding:n,mark:r}=t;if(r==="line"||Eo(r)&&r.type==="line")for(const i of spe){const s=Ac(i),o=n[s];if(n[i]&&(ue(o)&&!Pn(o.bin)||Po(o)))return!0}}return!1}run(t,n,r){const{encoding:i,mark:s}=t;return ae(lge(!!i.x2,!!i.y2)),r({...t,mark:ge(s)?{...s,type:"rule"}:"rule"},n)}}class f1e extends O3{constructor(){super(...arguments),this.nonFacetUnitNormalizers=[hme,mme,Eme,new u1e,new c1e]}map(t,n){if($a(t)){const r=Rl(t.encoding,la),i=Rl(t.encoding,ca),s=Rl(t.encoding,Lv);if(r||i||s)return this.mapFacetedUnit(t,n)}return super.map(t,n)}mapUnit(t,n){const{parentEncoding:r,parentProjection:i}=n,s=rx(t.encoding,n.repeater),o={...t,...t.name?{name:[n.repeaterPrefix,t.name].filter(u=>u).join("_")}:{},...s?{encoding:s}:{}};if(r||i)return this.mapUnitWithParentEncodingOrProjection(o,n);const a=this.mapLayerOrUnit.bind(this);for(const u of this.nonFacetUnitNormalizers)if(u.hasMatchingType(o,n.config))return u.run(o,n,a);return o}mapRepeat(t,n){return Kme(t)?this.mapLayerRepeat(t,n):this.mapNonLayerRepeat(t,n)}mapLayerRepeat(t,n){const{repeat:r,spec:i,...s}=t,{row:o,column:a,layer:u}=r,{repeater:l={},repeaterPrefix:c=""}=n;return o||a?this.mapRepeat({...t,repeat:{...o?{row:o}:{},...a?{column:a}:{}},spec:{repeat:{layer:u},spec:i}},n):{...s,layer:u.map(f=>{const d={...l,layer:f},h=`${(i.name?`${i.name}_`:"")+c}child__layer_${Ut(f)}`,p=this.mapLayerOrUnit(i,{...n,repeater:d,repeaterPrefix:h});return p.name=h,p})}}mapNonLayerRepeat(t,n){const{repeat:r,spec:i,data:s,...o}=t;!ee(r)&&t.columns&&(t=Hr(t,["columns"]),ae(LM("repeat")));const a=[],{repeater:u={},repeaterPrefix:l=""}=n,c=!ee(r)&&r.row||[u?u.row:null],f=!ee(r)&&r.column||[u?u.column:null],d=ee(r)&&r||[u?u.repeat:null];for(const p of d)for(const g of c)for(const m of f){const y={repeat:p,row:g,column:m,layer:u.layer},v=(i.name?`${i.name}_`:"")+l+"child__"+(ee(r)?`${Ut(p)}`:(r.row?`row_${Ut(g)}`:"")+(r.column?`column_${Ut(m)}`:"")),b=this.map(i,{...n,repeater:y,repeaterPrefix:v});b.name=v,a.push(Hr(b,["data"]))}const h=ee(r)?t.columns:r.column?r.column.length:1;return{data:i.data??s,align:"all",...o,columns:h,concat:a}}mapFacet(t,n){const{facet:r}=t;return jg(r)&&t.columns&&(t=Hr(t,["columns"]),ae(LM("facet"))),super.mapFacet(t,n)}mapUnitWithParentEncodingOrProjection(t,n){const{encoding:r,projection:i}=t,{parentEncoding:s,parentProjection:o,config:a}=n,u=s4({parentProjection:o,projection:i}),l=i4({parentEncoding:s,encoding:rx(r,n.repeater)});return this.mapUnit({...t,...u?{projection:u}:{},...l?{encoding:l}:{}},{config:a})}mapFacetedUnit(t,n){const{row:r,column:i,facet:s,...o}=t.encoding,{mark:a,width:u,projection:l,height:c,view:f,params:d,encoding:h,...p}=t,{facetMapping:g,layout:m}=this.getFacetMappingAndLayout({row:r,column:i,facet:s},n),y=rx(o,n.repeater);return this.mapFacet({...p,...m,facet:g,spec:{...u?{width:u}:{},...c?{height:c}:{},...f?{view:f}:{},...l?{projection:l}:{},mark:a,encoding:y,...d?{params:d}:{}}},n)}getFacetMappingAndLayout(t,n){const{row:r,column:i,facet:s}=t;if(r||i){s&&ae(age([...r?[la]:[],...i?[ca]:[]]));const o={},a={};for(const u of[la,ca]){const l=t[u];if(l){const{align:c,center:f,spacing:d,columns:h,...p}=l;o[u]=p;for(const g of["align","center","spacing"])l[g]!==void 0&&(a[g]??(a[g]={}),a[g][u]=l[g])}}return{facetMapping:o,layout:a}}else{const{align:o,center:a,spacing:u,columns:l,...c}=s;return{facetMapping:l1e(c,n.repeater),layout:{...o?{align:o}:{},...a?{center:a}:{},...u?{spacing:u}:{},...l?{columns:l}:{}}}}}mapLayer(t,{parentEncoding:n,parentProjection:r,...i}){const{encoding:s,projection:o,...a}=t,u={...i,parentEncoding:i4({parentEncoding:n,encoding:s,layer:!0}),parentProjection:s4({parentProjection:r,projection:o})};return super.mapLayer({...a,...t.name?{name:[u.repeaterPrefix,t.name].filter(l=>l).join("_")}:{}},u)}}function i4({parentEncoding:e,encoding:t={},layer:n}){let r={};if(e){const i=new Set([...ie(e),...ie(t)]);for(const s of i){const o=t[s],a=e[s];if(Ue(o)){const u={...a,...o};r[s]=u}else qg(o)?r[s]={...o,condition:{...a,...o.condition}}:o||o===null?r[s]=o:(n||$s(a)||Ce(a)||Ue(a)||ee(a))&&(r[s]=a)}}else r=t;return!r||Et(r)?void 0:r}function s4(e){const{parentProjection:t,projection:n}=e;return t&&n&&ae(Kpe({parentProjection:t,projection:n})),n??t}function L3(e){return oe(e,"filter")}function d1e(e){return oe(e,"stop")}function lz(e){return oe(e,"lookup")}function h1e(e){return oe(e,"data")}function p1e(e){return oe(e,"param")}function g1e(e){return oe(e,"pivot")}function m1e(e){return oe(e,"density")}function y1e(e){return oe(e,"quantile")}function v1e(e){return oe(e,"regression")}function b1e(e){return oe(e,"loess")}function x1e(e){return oe(e,"sample")}function _1e(e){return oe(e,"window")}function w1e(e){return oe(e,"joinaggregate")}function E1e(e){return oe(e,"flatten")}function A1e(e){return oe(e,"calculate")}function cz(e){return oe(e,"bin")}function S1e(e){return oe(e,"impute")}function k1e(e){return oe(e,"timeUnit")}function C1e(e){return oe(e,"aggregate")}function $1e(e){return oe(e,"stack")}function F1e(e){return oe(e,"fold")}function D1e(e){return oe(e,"extent")&&!oe(e,"density")&&!oe(e,"regression")}function M1e(e){return e.map(t=>L3(t)?{filter:pf(t.filter,n0e)}:t)}class R1e extends O3{map(t,n){return n.emptySelections??(n.emptySelections={}),n.selectionPredicates??(n.selectionPredicates={}),t=o4(t,n),super.map(t,n)}mapLayerOrUnit(t,n){if(t=o4(t,n),t.encoding){const r={};for(const[i,s]of _u(t.encoding))r[i]=fz(s,n);t={...t,encoding:r}}return super.mapLayerOrUnit(t,n)}mapUnit(t,n){const{selection:r,...i}=t;return r?{...i,params:_u(r).map(([s,o])=>{const{init:a,bind:u,empty:l,...c}=o;c.type==="single"?(c.type="point",c.toggle=!1):c.type==="multi"&&(c.type="point"),n.emptySelections[s]=l!=="none";for(const f of Yn(n.selectionPredicates[s]??{}))f.empty=l!=="none";return{name:s,value:a,select:c,bind:u}})}:t}}function o4(e,t){const{transform:n,...r}=e;if(n){const i=n.map(s=>{if(L3(s))return{filter:Qw(s,t)};if(cz(s)&&Sc(s.bin))return{...s,bin:dz(s.bin)};if(lz(s)){const{selection:o,...a}=s.from;return o?{...s,from:{param:o,...a}}:s}return s});return{...r,transform:i}}return e}function fz(e,t){var r,i;const n=Be(e);if(ue(n)&&Sc(n.bin)&&(n.bin=dz(n.bin)),Fc(n)&&((i=(r=n.scale)==null?void 0:r.domain)!=null&&i.selection)){const{selection:s,...o}=n.scale.domain;n.scale.domain={...o,...s?{param:s}:{}}}if(Ug(n))if(ee(n.condition))n.condition=n.condition.map(s=>{const{selection:o,param:a,test:u,...l}=s;return a?s:{...l,test:Qw(s,t)}});else{const{selection:s,param:o,test:a,...u}=fz(n.condition,t);n.condition=o?n.condition:{...u,test:Qw(n.condition,t)}}return n}function dz(e){const t=e.extent;if(t!=null&&t.selection){const{selection:n,...r}=t;return{...e,extent:{...r,param:n}}}return e}function Qw(e,t){const n=r=>pf(r,i=>{var s;const o=t.emptySelections[i]??!0,a={param:i,empty:o};return(s=t.selectionPredicates)[i]??(s[i]=[]),t.selectionPredicates[i].push(a),a});return e.selection?n(e.selection):pf(e.test||e.filter,r=>r.selection?n(r.selection):r)}class eE extends O3{map(t,n){const r=n.selections??[];if(t.params&&!$a(t)){const i=[];for(const s of t.params)R3(s)?r.push(s):i.push(s);t.params=i}return n.selections=r,super.map(t,n)}mapUnit(t,n){const r=n.selections;if(!r||!r.length)return t;const i=(n.path??[]).concat(t.name),s=[];for(const o of r)if(!o.views||!o.views.length)s.push(o);else for(const a of o.views)(me(a)&&(a===t.name||i.includes(a))||ee(a)&&a.map(u=>i.indexOf(u)).every((u,l,c)=>u!==-1&&(l===0||u>c[l-1])))&&s.push(o);return s.length&&(t.params=s),t}}for(const e of["mapFacet","mapRepeat","mapHConcat","mapVConcat","mapLayer"]){const t=eE.prototype[e];eE.prototype[e]=function(n,r){return t.call(this,n,T1e(n,r))}}function T1e(e,t){return e.name?{...t,path:(t.path??[]).concat(e.name)}:t}function hz(e,t){t===void 0&&(t=iz(e.config));const n=I1e(e,t),{width:r,height:i}=e,s=P1e(n,{width:r,height:i,autosize:e.autosize},t);return{...n,...s?{autosize:s}:{}}}const N1e=new f1e,O1e=new R1e,L1e=new eE;function I1e(e,t={}){const n={config:t};return L1e.map(N1e.map(O1e.map(e,n),n),n)}function a4(e){return me(e)?{type:e}:e??{}}function P1e(e,t,n){let{width:r,height:i}=t;const s=$a(e)||sb(e),o={};s?r=="container"&&i=="container"?(o.type="fit",o.contains="padding"):r=="container"?(o.type="fit-x",o.contains="padding"):i=="container"&&(o.type="fit-y",o.contains="padding"):(r=="container"&&(ae(RM("width")),r=void 0),i=="container"&&(ae(RM("height")),i=void 0));const a={type:"pad",...o,...n?a4(n.autosize):{},...a4(e.autosize)};if(a.type==="fit"&&!s&&(ae(Dpe),a.type="pad"),r=="container"&&!(a.type=="fit"||a.type=="fit-x")&&ae(TM("width")),i=="container"&&!(a.type=="fit"||a.type=="fit-y")&&ae(TM("height")),!fi(a,{type:"pad"}))return a}function B1e(e){return["fit","fit-x","fit-y"].includes(e)}function z1e(e){return e?`fit-${jv(e)}`:"fit"}const j1e=["background","padding"];function u4(e,t){const n={};for(const r of j1e)e&&e[r]!==void 0&&(n[r]=li(e[r]));return t&&(n.params=e.params),n}class Fa{constructor(t={},n={}){this.explicit=t,this.implicit=n}clone(){return new Fa(Be(this.explicit),Be(this.implicit))}combine(){return{...this.explicit,...this.implicit}}get(t){return un(this.explicit[t],this.implicit[t])}getWithExplicit(t){return this.explicit[t]!==void 0?{explicit:!0,value:this.explicit[t]}:this.implicit[t]!==void 0?{explicit:!1,value:this.implicit[t]}:{explicit:!1,value:void 0}}setWithExplicit(t,{value:n,explicit:r}){n!==void 0&&this.set(t,n,r)}set(t,n,r){return delete this[r?"implicit":"explicit"][t],this[r?"explicit":"implicit"][t]=n,this}copyKeyFromSplit(t,{explicit:n,implicit:r}){n[t]!==void 0?this.set(t,n[t],!0):r[t]!==void 0&&this.set(t,r[t],!1)}copyKeyFromObject(t,n){n[t]!==void 0&&this.set(t,n[t],!0)}copyAll(t){for(const n of ie(t.combine())){const r=t.getWithExplicit(n);this.setWithExplicit(n,r)}}}function Xs(e){return{explicit:!0,value:e}}function ii(e){return{explicit:!1,value:e}}function pz(e){return(t,n,r,i)=>{const s=e(t.value,n.value);return s>0?t:s<0?n:ob(t,n,r,i)}}function ob(e,t,n,r){return e.explicit&&t.explicit&&ae(bge(n,r,e.value,t.value)),e}function Au(e,t,n,r,i=ob){return e===void 0||e.value===void 0?t:e.explicit&&!t.explicit?e:t.explicit&&!e.explicit?t:fi(e.value,t.value)?e:i(e,t,n,r)}class U1e extends Fa{constructor(t={},n={},r=!1){super(t,n),this.explicit=t,this.implicit=n,this.parseNothing=r}clone(){const t=super.clone();return t.parseNothing=this.parseNothing,t}}function cd(e){return oe(e,"url")}function Pp(e){return oe(e,"values")}function gz(e){return oe(e,"name")&&!cd(e)&&!Pp(e)&&!lu(e)}function lu(e){return e&&(mz(e)||yz(e)||I3(e))}function mz(e){return oe(e,"sequence")}function yz(e){return oe(e,"sphere")}function I3(e){return oe(e,"graticule")}var Vt;(function(e){e[e.Raw=0]="Raw",e[e.Main=1]="Main",e[e.Row=2]="Row",e[e.Column=3]="Column",e[e.Lookup=4]="Lookup",e[e.PreFilterInvalid=5]="PreFilterInvalid",e[e.PostFilterInvalid=6]="PostFilterInvalid"})(Vt||(Vt={}));function vz({invalid:e,isPath:t}){switch(hB(e,{isPath:t})){case"filter":return{marks:"exclude-invalid-values",scales:"exclude-invalid-values"};case"break-paths-show-domains":return{marks:t?"include-invalid-values":"exclude-invalid-values",scales:"include-invalid-values"};case"break-paths-filter-domains":return{marks:t?"include-invalid-values":"exclude-invalid-values",scales:"exclude-invalid-values"};case"show":return{marks:"include-invalid-values",scales:"include-invalid-values"}}}function q1e(e){const{marks:t,scales:n}=vz(e);return t===n?Vt.Main:n==="include-invalid-values"?Vt.PreFilterInvalid:Vt.PostFilterInvalid}class _t{constructor(t,n){this.debugName=n,this._children=[],this._parent=null,t&&(this.parent=t)}clone(){throw new Error("Cannot clone node")}get parent(){return this._parent}set parent(t){this._parent=t,t&&t.addChild(this)}get children(){return this._children}numChildren(){return this._children.length}addChild(t,n){if(this._children.includes(t)){ae(Ype);return}n!==void 0?this._children.splice(n,0,t):this._children.push(t)}removeChild(t){const n=this._children.indexOf(t);return this._children.splice(n,1),n}remove(){let t=this._parent.removeChild(this);for(const n of this._children)n._parent=this._parent,this._parent.addChild(n,t++)}insertAsParentOf(t){const n=t.parent;n.removeChild(this),this.parent=n,t.parent=this}swapWithParent(){const t=this._parent,n=t.parent;for(const i of this._children)i.parent=t;this._children=[],t.removeChild(this);const r=t.parent.removeChild(t);this._parent=n,n.addChild(this,r),t.parent=this}}class Gr extends _t{clone(){const t=new this.constructor;return t.debugName=`clone_${this.debugName}`,t._source=this._source,t._name=`clone_${this._name}`,t.type=this.type,t.refCounts=this.refCounts,t.refCounts[t._name]=0,t}constructor(t,n,r,i){super(t,n),this.type=r,this.refCounts=i,this._source=this._name=n,this.refCounts&&!(this._name in this.refCounts)&&(this.refCounts[this._name]=0)}dependentFields(){return new Set}producedFields(){return new Set}hash(){return this._hash===void 0&&(this._hash=`Output ${pP()}`),this._hash}getSource(){return this.refCounts[this._name]++,this._source}isRequired(){return!!this.refCounts[this._name]}setSource(t){this._source=t}}function ix(e){return e.as!==void 0}function l4(e){return`${e}_end`}class fo extends _t{clone(){return new fo(null,Be(this.timeUnits))}constructor(t,n){super(t),this.timeUnits=n}static makeFromEncoding(t,n){const r=n.reduceFieldDef((i,s,o)=>{const{field:a,timeUnit:u}=s;if(u){let l;if($c(u)){if(Gt(n)){const{mark:c,markDef:f,config:d}=n,h=Eu({fieldDef:s,markDef:f,config:d});(Ip(c)||h)&&(l={timeUnit:Mn(u),field:a})}}else l={as:pe(s,{forAs:!0}),field:a,timeUnit:u};if(Gt(n)){const{mark:c,markDef:f,config:d}=n,h=Eu({fieldDef:s,markDef:f,config:d});Ip(c)&&ln(o)&&h!==.5&&(l.rectBandPosition=h)}l&&(i[rt(l)]=l)}return i},{});return Et(r)?null:new fo(t,r)}static makeFromTransform(t,n){const{timeUnit:r,...i}={...n},s=Mn(r),o={...i,timeUnit:s};return new fo(t,{[rt(o)]:o})}merge(t){this.timeUnits={...this.timeUnits};for(const n in t.timeUnits)this.timeUnits[n]||(this.timeUnits[n]=t.timeUnits[n]);for(const n of t.children)t.removeChild(n),n.parent=this;t.remove()}removeFormulas(t){const n={};for(const[r,i]of _u(this.timeUnits)){const s=ix(i)?i.as:`${i.field}_end`;t.has(s)||(n[r]=i)}this.timeUnits=n}producedFields(){return new Set(Yn(this.timeUnits).map(t=>ix(t)?t.as:l4(t.field)))}dependentFields(){return new Set(Yn(this.timeUnits).map(t=>t.field))}hash(){return`TimeUnit ${rt(this.timeUnits)}`}assemble(){const t=[];for(const n of Yn(this.timeUnits)){const{rectBandPosition:r}=n,i=Mn(n.timeUnit);if(ix(n)){const{field:s,as:o}=n,{unit:a,utc:u,...l}=i,c=[o,`${o}_end`];t.push({field:Gi(s),type:"timeunit",...a?{units:Hv(a)}:{},...u?{timezone:"utc"}:{},...l,as:c}),t.push(...c4(c,r,i))}else if(n){const{field:s}=n,o=s.replaceAll("\\.","."),a=bz({timeUnit:i,field:o}),u=l4(o);t.push({type:"formula",expr:a,as:u}),t.push(...c4([o,u],r,i))}}return t}}const ab="offsetted_rect_start",ub="offsetted_rect_end";function bz({timeUnit:e,field:t,reverse:n}){const{unit:r,utc:i}=e,s=XP(r),{part:o,step:a}=QP(s,e.step);return`${i?"utcOffset":"timeOffset"}('${o}', ${vt(t)}, ${n?-a:a})`}function c4([e,t],n,r){if(n!==void 0&&n!==.5){const i=vt(e),s=vt(t);return[{type:"formula",expr:f4([bz({timeUnit:r,field:e,reverse:!0}),i],n+.5),as:`${e}_${ab}`},{type:"formula",expr:f4([i,s],n+.5),as:`${e}_${ub}`}]}return[]}function f4([e,t],n){return`${1-n} * ${e} + ${n} * ${t}`}const Gg="_tuple_fields";class W1e{constructor(...t){this.items=t,this.hasChannel={},this.hasField={},this.hasSelectionId=!1}}const H1e={defined:()=>!0,parse:(e,t,n)=>{const r=t.name,i=t.project??(t.project=new W1e),s={},o={},a=new Set,u=(p,g)=>{const m=g==="visual"?p.channel:p.field;let y=Ut(`${r}_${m}`);for(let v=1;a.has(y);v++)y=Ut(`${r}_${m}_${v}`);return a.add(y),{[g]:y}},l=t.type,c=e.config.selection[l],f=n.value!==void 0?ye(n.value):null;let{fields:d,encodings:h}=ge(n.select)?n.select:{};if(!d&&!h&&f){for(const p of f)if(ge(p))for(const g of ie(p))ipe(g)?(h||(h=[])).push(g):l==="interval"?(ae(zpe),h=c.encodings):(d??(d=[])).push(g)}!d&&!h&&(h=c.encodings,"fields"in c&&(d=c.fields));for(const p of h??[]){const g=e.fieldDef(p);if(g){let m=g.field;if(g.aggregate){ae(Mpe(p,g.aggregate));continue}else if(!m){ae(OM(p));continue}if(g.timeUnit&&!$c(g.timeUnit)){m=e.vgField(p);const y={timeUnit:g.timeUnit,as:m,field:g.field};o[rt(y)]=y}if(!s[m]){const y=l==="interval"&&Io(p)&&Cs(e.getScaleComponent(p).get("type"))?"R":g.bin?"R-RE":"E",v={field:m,channel:p,type:y,index:i.items.length};v.signals={...u(v,"data"),...u(v,"visual")},i.items.push(s[m]=v),i.hasField[m]=s[m],i.hasSelectionId=i.hasSelectionId||m===Ds,xP(p)?(v.geoChannel=p,v.channel=bP(p),i.hasChannel[v.channel]=s[m]):i.hasChannel[p]=s[m]}}else ae(OM(p))}for(const p of d??[]){if(i.hasField[p])continue;const g={type:"E",field:p,index:i.items.length};g.signals={...u(g,"data")},i.items.push(g),i.hasField[p]=g,i.hasSelectionId=i.hasSelectionId||p===Ds}f&&(t.init=f.map(p=>i.items.map(g=>ge(p)?p[g.geoChannel||g.channel]!==void 0?p[g.geoChannel||g.channel]:p[g.field]:p))),Et(o)||(i.timeUnit=new fo(null,o))},signals:(e,t,n)=>{const r=t.name+Gg;return n.filter(s=>s.name===r).length>0||t.project.hasSelectionId?n:n.concat({name:r,value:t.project.items.map(Ez)})}},xz="_curr",Em="anim_value",Jc="anim_clock",tE="eased_anim_clock",_z="min_extent",wz="max_range_extent",sx="last_tick_at",ox="is_playing",G1e=1/60*1e3,Y1e=(e,t)=>[{name:tE,update:Jc},{name:`${e}_domain`,init:`domain('${t}')`},{name:_z,init:`extent(${e}_domain)[0]`},{name:wz,init:`extent(range('${t}'))[1]`},{name:Em,update:`invert('${t}', ${tE})`}],V1e={defined:e=>e.type==="point",topLevelSignals:(e,t,n)=>(ho(t)&&(n=n.concat([{name:Jc,init:"0",on:[{events:{type:"timer",throttle:G1e},update:`${ox} ? (${Jc} + (now() - ${sx}) > ${wz} ? 0 : ${Jc} + (now() - ${sx})) : ${Jc}`}]},{name:sx,init:"now()",on:[{events:[{signal:Jc},{signal:ox}],update:"now()"}]},{name:ox,init:"true"}])),n),signals:(e,t,n)=>{const r=t.name,i=r+Gg,s=t.project,o="(item().isVoronoi ? datum.datum : datum)",a=Yn(e.component.selection??{}).reduce((c,f)=>f.type==="interval"?c.concat(f.name+yf):c,[]).map(c=>`indexof(item().mark.name, '${c}') < 0`).join(" && "),u=`datum && item().mark.marktype !== 'group' && indexof(item().mark.role, 'legend') < 0${a?` && ${a}`:""}`;let l=`unit: ${Tl(e)}, `;if(t.project.hasSelectionId)l+=`${Ds}: ${o}[${ce(Ds)}]`;else if(ho(t))l+=`fields: ${i}, values: [${Em} ? ${Em} : ${_z}]`;else{const c=s.items.map(f=>{const d=e.fieldDef(f.channel);return d!=null&&d.bin?`[${o}[${ce(e.vgField(f.channel,{}))}], ${o}[${ce(e.vgField(f.channel,{binSuffix:"end"}))}]]`:`${o}[${ce(f.field)}]`}).join(", ");l+=`fields: ${i}, values: [${c}]`}if(ho(t))return n.concat(Y1e(t.name,e.scaleName(Bu)),[{name:r+xa,on:[{events:[{signal:tE},{signal:Em}],update:`{${l}}`,force:!0}]}]);{const c=t.events;return n.concat([{name:r+xa,on:c?[{events:c,update:`${u} ? {${l}} : null`,force:!0}]:[]}])}}};function Ez(e){const{signals:t,hasLegend:n,index:r,...i}=e;return i.field=Gi(i.field),i}function lc(e,t=!0,n=hr){if(ee(e)){const r=e.map(i=>lc(i,t,n));return t?`[${r.join(", ")}]`:r}else if(Cc(e))return n(t?sc(e):Wge(e));return t?n(At(e)):e}function X1e(e,t){for(const n of Yn(e.component.selection??{})){const r=n.name;let i=`${r}${xa}, ${n.resolve==="global"?"true":`{unit: ${Tl(e)}}`}`;for(const s of cb)s.defined(n)&&(s.signals&&(t=s.signals(e,n,t)),s.modifyExpr&&(i=s.modifyExpr(e,n,i)));t.push({name:r+wye,on:[{events:{signal:n.name+xa},update:`modify(${ce(n.name+cc)}, ${i})`}]})}return P3(t)}function K1e(e,t){if(e.component.selection&&ie(e.component.selection).length){const n=ce(e.getName("cell"));t.unshift({name:"facet",value:{},on:[{events:Iu("pointermove","scope"),update:`isTuple(facet) ? facet : group(${n}).datum`}]})}return P3(t)}function Z1e(e,t){let n=!1;for(const r of Yn(e.component.selection??{})){const i=r.name,s=ce(i+cc);if(t.filter(a=>a.name===i).length===0){const a=r.resolve==="global"?"union":r.resolve,u=r.type==="point"?", true, true)":")";t.push({name:r.name,update:`${zz}(${s}, ${ce(a)}${u}`})}n=!0;for(const a of cb)a.defined(r)&&a.topLevelSignals&&(t=a.topLevelSignals(e,r,t))}return n&&t.filter(i=>i.name==="unit").length===0&&t.unshift({name:"unit",value:{},on:[{events:"pointermove",update:"isTuple(group()) ? group() : unit"}]}),P3(t)}function J1e(e,t){const n=[],r=[],i=Tl(e,{escape:!1});for(const s of Yn(e.component.selection??{})){const o={name:s.name+cc};if(s.project.hasSelectionId&&(o.transform=[{type:"collect",sort:{field:Ds}}]),s.init){const u=s.project.items.map(Ez);o.values=s.project.hasSelectionId?s.init.map(l=>({unit:i,[Ds]:lc(l,!1)[0]})):s.init.map(l=>({unit:i,fields:u,values:lc(l,!1)}))}if([...n,...t].filter(u=>u.name===s.name+cc).length||n.push(o),ho(s)&&t.length){const u=e.lookupDataSource(e.getDataName(Vt.Main)),l=t.find(f=>f.name===u),c=l.transform.find(f=>f.type==="filter"&&f.expr.includes("vlSelectionTest"));if(c){l.transform=l.transform.filter(d=>d!==c);const f={name:l.name+xz,source:l.name,transform:[c]};r.push(f)}}}return n.concat(t,r)}function Az(e,t){for(const n of Yn(e.component.selection??{}))for(const r of cb)r.defined(n)&&r.marks&&(t=r.marks(e,n,t));return t}function Q1e(e,t){for(const n of e.children)Gt(n)&&(t=Az(n,t));return t}function eye(e,t,n,r){const i=Zz(e,t.param,t);return{signal:Cs(n.get("type"))&&ee(r)&&r[0]>r[1]?`isValid(${i}) && reverse(${i})`:i}}function P3(e){return e.map(t=>(t.on&&!t.on.length&&delete t.on,t))}const da={defined:e=>e.type==="interval"&&e.resolve==="global"&&e.bind&&e.bind==="scales",parse:(e,t)=>{const n=t.scales=[];for(const r of t.project.items){const i=r.channel;if(!Io(i))continue;const s=e.getScaleComponent(i),o=s?s.get("type"):void 0;if(o=="sequential"&&ae(Ope),!s||!Cs(o)){ae(Npe);continue}s.set("selectionExtent",{param:t.name,field:r.field},!0),n.push(r)}},topLevelSignals:(e,t,n)=>{const r=t.scales.filter(o=>n.filter(a=>a.name===o.signals.data).length===0);if(!e.parent||rE(e)||r.length===0)return n;const i=n.find(o=>o.name===t.name);let s=i.update;if(s.includes(zz))i.update=`{${r.map(o=>`${ce(Gi(o.field))}: ${o.signals.data}`).join(", ")}}`;else{for(const o of r){const a=`${ce(Gi(o.field))}: ${o.signals.data}`;s.includes(a)||(s=`${s.substring(0,s.length-1)}, ${a}}`)}i.update=s}return n.concat(r.map(o=>({name:o.signals.data})))},signals:(e,t,n)=>{if(e.parent&&!rE(e))for(const r of t.scales){const i=n.find(s=>s.name===r.signals.data);i.push="outer",delete i.value,delete i.update}return n}};function nE(e,t){return`domain(${ce(e.scaleName(t))})`}function rE(e){return e.parent&&Wd(e.parent)&&(!e.parent.parent||rE(e.parent.parent))}const yf="_brush",Sz="_scale_trigger",ph="geo_interval_init_tick",kz="_init",tye="_center",nye={defined:e=>e.type==="interval",parse:(e,t,n)=>{var r;if(e.hasProjection){const i={...ge(n.select)?n.select:{}};i.fields=[Ds],i.encodings||(i.encodings=n.value?ie(n.value):[Is,Ls]),n.select={type:"interval",...i}}if(t.translate&&!da.defined(t)){const i=`!event.item || event.item.mark.name !== ${ce(t.name+yf)}`;for(const s of t.events){if(!s.between){ae(`${s} is not an ordered event stream for interval selections.`);continue}const o=ye((r=s.between[0]).filter??(r.filter=[]));o.includes(i)||o.push(i)}}},signals:(e,t,n)=>{const r=t.name,i=r+xa,s=Yn(t.project.hasChannel).filter(a=>a.channel===qt||a.channel===On),o=t.init?t.init[0]:null;if(n.push(...s.reduce((a,u)=>a.concat(rye(e,t,u,o&&o[u.index])),[])),e.hasProjection){const a=ce(e.projectionName()),u=e.projectionName()+tye,{x:l,y:c}=t.project.hasChannel,f=l&&l.signals.visual,d=c&&c.signals.visual,h=l?o&&o[l.index]:`${u}[0]`,p=c?o&&o[c.index]:`${u}[1]`,g=_=>e.getSizeSignalRef(_).signal,m=`[[${f?f+"[0]":"0"}, ${d?d+"[0]":"0"}],[${f?f+"[1]":g("width")}, ${d?d+"[1]":g("height")}]]`;o&&(n.unshift({name:r+kz,init:`[scale(${a}, [${l?h[0]:h}, ${c?p[0]:p}]), scale(${a}, [${l?h[1]:h}, ${c?p[1]:p}])]`}),(!l||!c)&&(n.find(A=>A.name===u)||n.unshift({name:u,update:`invert(${a}, [${g("width")}/2, ${g("height")}/2])`})));const y=`intersect(${m}, {markname: ${ce(e.getName("marks"))}}, unit.mark)`,v=`{unit: ${Tl(e)}}`,b=`vlSelectionTuples(${y}, ${v})`,x=s.map(_=>_.signals.visual);return n.concat({name:i,on:[{events:[...x.length?[{signal:x.join(" || ")}]:[],...o?[{signal:ph}]:[]],update:b}]})}else{if(!da.defined(t)){const l=r+Sz,c=s.map(f=>{const d=f.channel,{data:h,visual:p}=f.signals,g=ce(e.scaleName(d)),m=e.getScaleComponent(d).get("type"),y=Cs(m)?"+":"";return`(!isArray(${h}) || (${y}invert(${g}, ${p})[0] === ${y}${h}[0] && ${y}invert(${g}, ${p})[1] === ${y}${h}[1]))`});c.length&&n.push({name:l,value:{},on:[{events:s.map(f=>({scale:e.scaleName(f.channel)})),update:c.join(" && ")+` ? ${l} : {}`}]})}const a=s.map(l=>l.signals.data),u=`unit: ${Tl(e)}, fields: ${r+Gg}, values`;return n.concat({name:i,...o?{init:`{${u}: ${lc(o)}}`}:{},...a.length?{on:[{events:[{signal:a.join(" || ")}],update:`${a.join(" && ")} ? {${u}: [${a}]} : null`}]}:{}})}},topLevelSignals:(e,t,n)=>(Gt(e)&&e.hasProjection&&t.init&&(n.filter(i=>i.name===ph).length||n.unshift({name:ph,value:null,on:[{events:"timer{1}",update:`${ph} === null ? {} : ${ph}`}]})),n),marks:(e,t,n)=>{const r=t.name,{x:i,y:s}=t.project.hasChannel,o=i==null?void 0:i.signals.visual,a=s==null?void 0:s.signals.visual,u=`data(${ce(t.name+cc)})`;if(da.defined(t)||!i&&!s)return n;const l={x:i!==void 0?{signal:`${o}[0]`}:{value:0},y:s!==void 0?{signal:`${a}[0]`}:{value:0},x2:i!==void 0?{signal:`${o}[1]`}:{field:{group:"width"}},y2:s!==void 0?{signal:`${a}[1]`}:{field:{group:"height"}}};if(t.resolve==="global")for(const m of ie(l))l[m]=[{test:`${u}.length && ${u}[0].unit === ${Tl(e)}`,...l[m]},{value:0}];const{fill:c,fillOpacity:f,cursor:d,...h}=t.mark,p=ie(h).reduce((m,y)=>(m[y]=[{test:[i!==void 0&&`${o}[0] !== ${o}[1]`,s!==void 0&&`${a}[0] !== ${a}[1]`].filter(v=>v).join(" && "),value:h[y]},{value:null}],m),{}),g=d??(t.translate?"move":null);return[{name:`${r+yf}_bg`,type:"rect",clip:!0,encode:{enter:{fill:{value:c},fillOpacity:{value:f}},update:l}},...n,{name:r+yf,type:"rect",clip:!0,encode:{enter:{...g?{cursor:{value:g}}:{},fill:{value:"transparent"}},update:{...l,...p}}}]}};function rye(e,t,n,r){const i=!e.hasProjection,s=n.channel,o=n.signals.visual,a=ce(i?e.scaleName(s):e.projectionName()),u=d=>`scale(${a}, ${d})`,l=e.getSizeSignalRef(s===qt?"width":"height").signal,c=`${s}(unit)`,f=t.events.reduce((d,h)=>[...d,{events:h.between[0],update:`[${c}, ${c}]`},{events:h,update:`[${o}[0], clamp(${c}, 0, ${l})]`}],[]);if(i){const d=n.signals.data,h=da.defined(t),p=e.getScaleComponent(s),g=p?p.get("type"):void 0,m=r?{init:lc(r,!0,u)}:{value:[]};return f.push({events:{signal:t.name+Sz},update:Cs(g)?`[${u(`${d}[0]`)}, ${u(`${d}[1]`)}]`:"[0, 0]"}),h?[{name:d,on:[]}]:[{name:o,...m,on:f},{name:d,...r?{init:lc(r)}:{},on:[{events:{signal:o},update:`${o}[0] === ${o}[1] ? null : invert(${a}, ${o})`}]}]}else{const d=s===qt?0:1,h=t.name+kz,p=r?{init:`[${h}[0][${d}], ${h}[1][${d}]]`}:{value:[]};return[{name:o,...p,on:f}]}}function zd({model:e,channelDef:t,vgChannel:n,invalidValueRef:r,mainRefFn:i}){const s=Ug(t)&&t.condition;let o=[];s&&(o=ye(s).map(l=>{const c=i(l);if(W0e(l)){const{param:f,empty:d}=l;return{test:Kz(e,{param:f,empty:d}),...c}}else return{test:oy(e,l.test),...c}})),r!==void 0&&o.push(r);const a=i(t);return a!==void 0&&o.push(a),o.length>1||o.length===1&&o[0].test?{[n]:o}:o.length===1?{[n]:o[0]}:{}}function B3(e,t="text"){const n=e.encoding[t];return zd({model:e,channelDef:n,vgChannel:t,mainRefFn:r=>lb(r,e.config),invalidValueRef:void 0})}function lb(e,t,n="datum"){if(e){if($s(e))return Ot(e.value);if(Ue(e)){const{format:r,formatType:i}=Q1(e);return b3({fieldOrDatumDef:e,format:r,formatType:i,expr:n,config:t})}}}function Cz(e,t={}){const{encoding:n,markDef:r,config:i,stack:s}=e,o=n.tooltip;if(ee(o))return{tooltip:d4({tooltip:o},s,i,t)};{const a=t.reactiveGeom?"datum.datum":"datum";return zd({model:e,channelDef:o,vgChannel:"tooltip",mainRefFn:l=>{const c=lb(l,i,a);if(c)return c;if(l===null)return;let f=wt("tooltip",r,i);if(f===!0&&(f={content:"encoding"}),me(f))return{value:f};if(ge(f))return Ce(f)?f:f.content==="encoding"?d4(n,s,i,t):{signal:a}},invalidValueRef:void 0})}}function $z(e,t,n,{reactiveGeom:r}={}){const i={...n,...n.tooltipFormat},s=new Set,o=r?"datum.datum":"datum",a=[];function u(c,f){const d=Ac(f),h=Dr(c)?c:{...c,type:e[d].type},p=h.title||E3(h,i),g=ye(p).join(", ").replaceAll(/"/g,'\\"');let m;if(ln(f)){const y=f==="x"?"x2":"y2",v=Fs(e[y]);if(Pn(h.bin)&&v){const b=pe(h,{expr:o}),x=pe(v,{expr:o}),{format:_,formatType:A}=Q1(h);m=zg(b,x,_,A,i),s.add(y)}}if((ln(f)||f===Xi||f===Os)&&t&&t.fieldChannel===f&&t.offset==="normalize"){const{format:y,formatType:v}=Q1(h);m=b3({fieldOrDatumDef:h,format:y,formatType:v,expr:o,config:i,normalizeStack:!0}).signal}m??(m=lb(h,i,o).signal),a.push({channel:f,key:g,value:m})}S3(e,(c,f)=>{ue(c)?u(c,f):Qv(c)&&u(c.condition,f)});const l={};for(const{channel:c,key:f,value:d}of a)!s.has(c)&&!l[f]&&(l[f]=d);return l}function d4(e,t,n,{reactiveGeom:r}={}){const i=$z(e,t,n,{reactiveGeom:r}),s=_u(i).map(([o,a])=>`"${o}": ${a}`);return s.length>0?{signal:`{${s.join(", ")}}`}:void 0}function iye(e){const{markDef:t,config:n}=e,r=wt("aria",t,n);return r===!1?{}:{...r?{aria:r}:{},...sye(e),...oye(e)}}function sye(e){const{mark:t,markDef:n,config:r}=e;if(r.aria===!1)return{};const i=wt("ariaRoleDescription",n,r);return i!=null?{ariaRoleDescription:{value:i}}:be(Cpe,t)?{}:{ariaRoleDescription:{value:t}}}function oye(e){const{encoding:t,markDef:n,config:r,stack:i}=e,s=t.description;if(s)return zd({model:e,channelDef:s,vgChannel:"description",mainRefFn:u=>lb(u,e.config),invalidValueRef:void 0});const o=wt("description",n,r);if(o!=null)return{description:Ot(o)};if(r.aria===!1)return{};const a=$z(t,i,r);if(!Et(a))return{description:{signal:_u(a).map(([u,l],c)=>`"${c>0?"; ":""}${u}: " + (${l})`).join(" + ")}}}function Un(e,t,n={}){const{markDef:r,encoding:i,config:s}=t,{vgChannel:o}=n;let{defaultRef:a,defaultValue:u}=n;const l=i[e];a===void 0&&(u??(u=wt(e,r,s,{vgChannel:o,ignoreVgConfig:!Ug(l)})),u!==void 0&&(a=Ot(u)));const c={markDef:r,config:s,scaleName:t.scaleName(e),scale:t.getScaleComponent(e)},f=gB({...c,scaleChannel:e,channelDef:l});return zd({model:t,channelDef:l,vgChannel:o??e,invalidValueRef:f,mainRefFn:h=>v3({...c,channel:e,channelDef:h,stack:null,defaultRef:a})})}function Fz(e,t={filled:void 0}){const{markDef:n,encoding:r,config:i}=e,{type:s}=n,o=t.filled??wt("filled",n,i),a=Qe(["bar","point","circle","square","geoshape"],s)?"transparent":void 0,u=wt(o===!0?"color":void 0,n,i,{vgChannel:"fill"})??i.mark[o===!0&&"color"]??a,l=wt(o===!1?"color":void 0,n,i,{vgChannel:"stroke"})??i.mark[o===!1&&"color"],c=o?"fill":"stroke",f={...u?{fill:Ot(u)}:{},...l?{stroke:Ot(l)}:{}};return n.color&&(o?n.fill:n.stroke)&&ae(zP("property",{fill:"fill"in n,stroke:"stroke"in n})),{...f,...Un("color",e,{vgChannel:c,defaultValue:o?u:l}),...Un("fill",e,{defaultValue:r.fill?u:void 0}),...Un("stroke",e,{defaultValue:r.stroke?l:void 0})}}function aye(e){const{encoding:t,mark:n}=e,r=t.order;return!Hu(n)&&$s(r)?zd({model:e,channelDef:r,vgChannel:"zindex",mainRefFn:i=>Ot(i.value),invalidValueRef:void 0}):{}}function fd({channel:e,markDef:t,encoding:n={},model:r,bandPosition:i}){const s=`${e}Offset`,o=t[s],a=n[s];if((s==="xOffset"||s==="yOffset")&&a)return{offsetType:"encoding",offset:v3({channel:s,channelDef:a,markDef:t,config:r==null?void 0:r.config,scaleName:r.scaleName(s),scale:r.getScaleComponent(s),stack:null,defaultRef:Ot(o),bandPosition:i})};const u=t[s];return u?{offsetType:"visual",offset:u}:{}}function Sr(e,t,{defaultPos:n,vgChannel:r}){const{encoding:i,markDef:s,config:o,stack:a}=t,u=i[e],l=i[Lo(e)],c=t.scaleName(e),f=t.getScaleComponent(e),{offset:d,offsetType:h}=fd({channel:e,markDef:s,encoding:i,model:t,bandPosition:.5}),p=z3({model:t,defaultPos:n,channel:e,scaleName:c,scale:f}),g=!u&&ln(e)&&(i.latitude||i.longitude)?{field:t.getName(e)}:uye({channel:e,channelDef:u,channel2Def:l,markDef:s,config:o,scaleName:c,scale:f,stack:a,offset:d,defaultRef:p,bandPosition:h==="encoding"?0:void 0});return g?{[r||e]:g}:void 0}function uye(e){const{channel:t,channelDef:n,scaleName:r,stack:i,offset:s,markDef:o}=e;if(Ue(n)&&i&&t===i.fieldChannel){if(ue(n)){let a=n.bandPosition;if(a===void 0&&o.type==="text"&&(t==="radius"||t==="theta")&&(a=.5),a!==void 0)return K1({scaleName:r,fieldOrDatumDef:n,startSuffix:"start",bandPosition:a,offset:s})}return Ml(n,r,{suffix:"end"},{offset:s})}return y3(e)}function z3({model:e,defaultPos:t,channel:n,scaleName:r,scale:i}){const{markDef:s,config:o}=e;return()=>{const a=Ac(n),u=wu(n),l=wt(n,s,o,{vgChannel:u});if(l!==void 0)return ap(n,l);switch(t){case"zeroOrMin":return h4({scaleName:r,scale:i,mode:"zeroOrMin",mainChannel:a,config:o});case"zeroOrMax":return h4({scaleName:r,scale:i,mode:{zeroOrMax:{widthSignal:e.width.signal,heightSignal:e.height.signal}},mainChannel:a,config:o});case"mid":return{...e[Jr(n)],mult:.5}}}}function h4({mainChannel:e,config:t,...n}){const r=pB(n),{mode:i}=n;if(r)return r;switch(e){case"radius":{if(i==="zeroOrMin")return{value:0};const{widthSignal:s,heightSignal:o}=i.zeroOrMax;return{signal:`min(${s},${o})/2`}}case"theta":return i==="zeroOrMin"?{value:0}:{signal:"2*PI"};case"x":return i==="zeroOrMin"?{value:0}:{field:{group:"width"}};case"y":return i==="zeroOrMin"?{field:{group:"height"}}:{value:0}}}const lye={left:"x",center:"xc",right:"x2"},cye={top:"y",middle:"yc",bottom:"y2"};function Dz(e,t,n,r="middle"){if(e==="radius"||e==="theta")return wu(e);const i=e==="x"?"align":"baseline",s=wt(i,t,n);let o;return Ce(s)?(ae(uge(i)),o=void 0):o=s,e==="x"?lye[o||(r==="top"?"left":"center")]:cye[o||r]}function ry(e,t,{defaultPos:n,defaultPos2:r,range:i}){return i?Mz(e,t,{defaultPos:n,defaultPos2:r}):Sr(e,t,{defaultPos:n})}function Mz(e,t,{defaultPos:n,defaultPos2:r}){const{markDef:i,config:s}=t,o=Lo(e),a=Jr(e),u=fye(t,r,o),l=u[a]?Dz(e,i,s):wu(e);return{...Sr(e,t,{defaultPos:n,vgChannel:l}),...u}}function fye(e,t,n){const{encoding:r,mark:i,markDef:s,stack:o,config:a}=e,u=Ac(n),l=Jr(n),c=wu(n),f=r[u],d=e.scaleName(u),h=e.getScaleComponent(u),{offset:p}=n in r||n in s?fd({channel:n,markDef:s,encoding:r,model:e}):fd({channel:u,markDef:s,encoding:r,model:e});if(!f&&(n==="x2"||n==="y2")&&(r.latitude||r.longitude)){const m=Jr(n),y=e.markDef[m];return y!=null?{[m]:{value:y}}:{[c]:{field:e.getName(n)}}}const g=dye({channel:n,channelDef:f,channel2Def:r[n],markDef:s,config:a,scaleName:d,scale:h,stack:o,offset:p,defaultRef:void 0});return g!==void 0?{[c]:g}:M0(n,s)||M0(n,{[n]:Ww(n,s,a.style),[l]:Ww(l,s,a.style)})||M0(n,a[i])||M0(n,a.mark)||{[c]:z3({model:e,defaultPos:t,channel:n,scaleName:d,scale:h})()}}function dye({channel:e,channelDef:t,channel2Def:n,markDef:r,config:i,scaleName:s,scale:o,stack:a,offset:u,defaultRef:l}){return Ue(t)&&a&&e.charAt(0)===a.fieldChannel.charAt(0)?Ml(t,s,{suffix:"start"},{offset:u}):y3({channel:e,channelDef:n,scaleName:s,scale:o,stack:a,markDef:r,config:i,offset:u,defaultRef:l})}function M0(e,t){const n=Jr(e),r=wu(e);if(t[r]!==void 0)return{[r]:ap(e,t[r])};if(t[e]!==void 0)return{[r]:ap(e,t[e])};if(t[n]){const i=t[n];if(ac(i))ae(nge(n));else return{[n]:ap(e,i)}}}function ba(e,t){const{config:n,encoding:r,markDef:i}=e,s=i.type,o=Lo(t),a=Jr(t),u=r[t],l=r[o],c=e.getScaleComponent(t),f=c?c.get("type"):void 0,d=i.orient,h=r[a]??r.size??wt("size",i,n,{vgChannel:a}),p=AP(t),g=s==="bar"&&(t==="x"?d==="vertical":d==="horizontal")||s==="tick"&&(t==="y"?d==="vertical":d==="horizontal");return ue(u)&&(Mt(u.bin)||Pn(u.bin)||u.timeUnit&&!l)&&!(h&&!ac(h))&&!r[p]&&!Tn(f)?gye({fieldDef:u,fieldDef2:l,channel:t,model:e}):(Ue(u)&&Tn(f)||g)&&!l?pye(u,t,e):Mz(t,e,{defaultPos:"zeroOrMax",defaultPos2:"zeroOrMin"})}function hye(e,t,n,r,i,s,o){if(ac(i))if(n){const u=n.get("type");if(u==="band"){let l=`bandwidth('${t}')`;i.band!==1&&(l=`${i.band} * ${l}`);const c=wo("minBandSize",{type:o},r);return{signal:c?`max(${vs(c)}, ${l})`:l}}else i.band!==1&&(ae(dge(u)),i=void 0)}else return{mult:i.band,field:{group:e}};else{if(Ce(i))return i;if(i)return{value:i}}if(n){const u=n.get("range");if(kc(u)&&ft(u.step))return{value:u.step-2}}if(!s){const{bandPaddingInner:u,barBandPaddingInner:l,rectBandPaddingInner:c,tickBandPaddingInner:f}=r.scale,d=un(u,o==="tick"?f:o==="bar"?l:c);if(Ce(d))return{signal:`(1 - (${d.signal})) * ${e}`};if(ft(d))return{signal:`${1-d} * ${e}`}}return{value:Zw(r.view,e)-2}}function pye(e,t,n){var k,$;const{markDef:r,encoding:i,config:s,stack:o}=n,a=r.orient,u=n.scaleName(t),l=n.getScaleComponent(t),c=Jr(t),f=Lo(t),d=AP(t),h=n.scaleName(d),p=n.getScaleComponent(WC(t)),g=r.type==="tick"||a==="horizontal"&&t==="y"||a==="vertical"&&t==="x";let m;(i.size||r.size)&&(g?m=Un("size",n,{vgChannel:c,defaultRef:Ot(r.size)}):ae(mge(r.type)));const y=!!m,v=wB({channel:t,fieldDef:e,markDef:r,config:s,scaleType:(k=l||p)==null?void 0:k.get("type"),useVlSizeChannel:g});m=m||{[c]:hye(c,h||u,p||l,s,v,!!e,r.type)};const b=(($=l||p)==null?void 0:$.get("type"))==="band"&&ac(v)&&!y?"top":"middle",x=Dz(t,r,s,b),_=x==="xc"||x==="yc",{offset:A,offsetType:E}=fd({channel:t,markDef:r,encoding:i,model:n,bandPosition:_?.5:0}),S=y3({channel:t,channelDef:e,markDef:r,config:s,scaleName:u,scale:l,stack:o,offset:A,defaultRef:z3({model:n,defaultPos:"mid",channel:t,scaleName:u,scale:l}),bandPosition:_?E==="encoding"?0:.5:Ce(v)?{signal:`(1-${v})/2`}:ac(v)?(1-v.band)/2:0});if(c)return{[x]:S,...m};{const D=wu(f),M=m[c],R=A?{...M,offset:A}:M;return{[x]:S,[D]:ee(S)?[S[0],{...S[1],offset:R}]:{...S,offset:R}}}}function p4(e,t,n,r,i,s,o){if(vP(e))return 0;const a=e==="x"||e==="y2",u=a?-t/2:t/2;if(Ce(n)||Ce(i)||Ce(r)||s){const l=vs(n),c=vs(i),f=vs(r),d=vs(s),p=s?`(${o} < ${d} ? ${a?"":"-"}0.5 * (${d} - (${o})) : ${u})`:u,g=f?`${f} + `:"",m=l?`(${l} ? -1 : 1) * `:"",y=c?`(${c} + ${p})`:p;return{signal:g+m+y}}else return i=i||0,r+(n?-i-u:+i+u)}function gye({fieldDef:e,fieldDef2:t,channel:n,model:r}){var $;const{config:i,markDef:s,encoding:o}=r,a=r.getScaleComponent(n),u=r.scaleName(n),l=a?a.get("type"):void 0,c=a.get("reverse"),f=wB({channel:n,fieldDef:e,markDef:s,config:i,scaleType:l}),d=($=r.component.axes[n])==null?void 0:$[0],h=(d==null?void 0:d.get("translate"))??.5,p=ln(n)?wt("binSpacing",s,i)??0:0,g=Lo(n),m=wu(n),y=wu(g),v=wo("minBandSize",s,i),{offset:b}=fd({channel:n,markDef:s,encoding:o,model:r,bandPosition:0}),{offset:x}=fd({channel:g,markDef:s,encoding:o,model:r,bandPosition:0}),_=P0e({fieldDef:e,scaleName:u}),A=p4(n,p,c,h,b,v,_),E=p4(g,p,c,h,x??b,v,_),S=Ce(f)?{signal:`(1-${f.signal})/2`}:ac(f)?(1-f.band)/2:.5,k=Eu({fieldDef:e,fieldDef2:t,markDef:s,config:i});if(Mt(e.bin)||e.timeUnit){const D=e.timeUnit&&k!==.5;return{[y]:g4({fieldDef:e,scaleName:u,bandPosition:S,offset:E,useRectOffsetField:D}),[m]:g4({fieldDef:e,scaleName:u,bandPosition:Ce(S)?{signal:`1-${S.signal}`}:1-S,offset:A,useRectOffsetField:D})}}else if(Pn(e.bin)){const D=Ml(e,u,{},{offset:E});if(ue(t))return{[y]:D,[m]:Ml(t,u,{},{offset:A})};if(Sc(e.bin)&&e.bin.step)return{[y]:D,[m]:{signal:`scale("${u}", ${pe(e,{expr:"datum"})} + ${e.bin.step})`,offset:A}}}ae(qP(g))}function g4({fieldDef:e,scaleName:t,bandPosition:n,offset:r,useRectOffsetField:i}){return K1({scaleName:t,fieldOrDatumDef:e,bandPosition:n,offset:r,...i?{startSuffix:ab,endSuffix:ub}:{}})}const mye=new Set(["aria","width","height"]);function Ki(e,t){const{fill:n=void 0,stroke:r=void 0}=t.color==="include"?Fz(e):{};return{...yye(e.markDef,t),...m4("fill",n),...m4("stroke",r),...Un("opacity",e),...Un("fillOpacity",e),...Un("strokeOpacity",e),...Un("strokeWidth",e),...Un("strokeDash",e),...aye(e),...Cz(e),...B3(e,"href"),...iye(e)}}function m4(e,t){return t?{[e]:t}:{}}function yye(e,t){return kpe.reduce((n,r)=>(!mye.has(r)&&oe(e,r)&&t[r]!=="ignore"&&(n[r]=Ot(e[r])),n),{})}function j3(e){const{config:t,markDef:n}=e,r=new Set;if(e.forEachFieldDef((i,s)=>{var l;let o;if(!Io(s)||!(o=e.getScaleType(s)))return;const a=Uv(i.aggregate),u=m3({scaleChannel:s,markDef:n,config:t,scaleType:o,isCountAggregate:a});if(O0e(u)){const c=e.vgField(s,{expr:"datum",binSuffix:(l=e.stack)!=null&&l.impute?"mid":void 0});c&&r.add(c)}}),r.size>0)return{defined:{signal:[...r].map(s=>Gv(s,!0)).join(" && ")}}}function y4(e,t){if(t!==void 0)return{[e]:Ot(t)}}const ax="voronoi",Rz={defined:e=>e.type==="point"&&e.nearest,parse:(e,t)=>{if(t.events)for(const n of t.events)n.markname=e.getName(ax)},marks:(e,t,n)=>{const{x:r,y:i}=t.project.hasChannel,s=e.mark;if(Hu(s))return ae(Rpe(s)),n;const o={name:e.getName(ax),type:"path",interactive:!0,from:{data:e.getName("marks")},encode:{update:{fill:{value:"transparent"},strokeWidth:{value:.35},stroke:{value:"transparent"},isVoronoi:{value:!0},...Cz(e,{reactiveGeom:!0})}},transform:[{type:"voronoi",x:{expr:r||!i?"datum.datum.x || 0":"0"},y:{expr:i||!r?"datum.datum.y || 0":"0"},size:[e.getSizeSignalRef("width"),e.getSizeSignalRef("height")]}]};let a=0,u=!1;return n.forEach((l,c)=>{const f=l.name??"";f===e.component.mark[0].name?a=c:f.includes(ax)&&(u=!0)}),u||n.splice(a+1,0,o),n}},Tz={defined:e=>e.type==="point"&&e.resolve==="global"&&e.bind&&e.bind!=="scales"&&!M3(e.bind),parse:(e,t,n)=>jz(t,n),topLevelSignals:(e,t,n)=>{const r=t.name,i=t.project,s=t.bind,o=t.init&&t.init[0],a=Rz.defined(t)?"(item().isVoronoi ? datum.datum : datum)":"datum";return i.items.forEach((u,l)=>{const c=Ut(`${r}_${u.field}`);n.filter(d=>d.name===c).length||n.unshift({name:c,...o?{init:lc(o[l])}:{value:null},on:t.events?[{events:t.events,update:`datum && item().mark.marktype !== 'group' ? ${a}[${ce(u.field)}] : null`}]:[],bind:s[u.field]??s[u.channel]??s})}),n},signals:(e,t,n)=>{const r=t.name,i=t.project,s=n.find(l=>l.name===r+xa),o=r+Gg,a=i.items.map(l=>Ut(`${r}_${l.field}`)),u=a.map(l=>`${l} !== null`).join(" && ");return a.length&&(s.update=`${u} ? {fields: ${o}, values: [${a.join(", ")}]} : null`),delete s.value,delete s.on,n}},iy="_toggle",Nz={defined:e=>e.type==="point"&&!ho(e)&&!!e.toggle,signals:(e,t,n)=>n.concat({name:t.name+iy,value:!1,on:[{events:t.events,update:t.toggle}]}),modifyExpr:(e,t)=>{const n=t.name+xa,r=t.name+iy;return`${r} ? null : ${n}, `+(t.resolve==="global"?`${r} ? null : true, `:`${r} ? null : {unit: ${Tl(e)}}, `)+`${r} ? ${n} : null`}},vye={defined:e=>e.clear!==void 0&&e.clear!==!1&&!ho(e),parse:(e,t)=>{t.clear&&(t.clear=me(t.clear)?Iu(t.clear,"view"):t.clear)},topLevelSignals:(e,t,n)=>{if(Tz.defined(t))for(const r of t.project.items){const i=n.findIndex(s=>s.name===Ut(`${t.name}_${r.field}`));i!==-1&&n[i].on.push({events:t.clear,update:"null"})}return n},signals:(e,t,n)=>{function r(i,s){i!==-1&&n[i].on&&n[i].on.push({events:t.clear,update:s})}if(t.type==="interval")for(const i of t.project.items){const s=n.findIndex(o=>o.name===i.signals.visual);if(r(s,"[0, 0]"),s===-1){const o=n.findIndex(a=>a.name===i.signals.data);r(o,"null")}}else{let i=n.findIndex(s=>s.name===t.name+xa);r(i,"null"),Nz.defined(t)&&(i=n.findIndex(s=>s.name===t.name+iy),r(i,"false"))}return n}},Oz={defined:e=>{const t=e.resolve==="global"&&e.bind&&M3(e.bind),n=e.project.items.length===1&&e.project.items[0].field!==Ds;return t&&!n&&ae(Lpe),t&&n},parse:(e,t,n)=>{const r=Be(n);if(r.select=me(r.select)?{type:r.select,toggle:t.toggle}:{...r.select,toggle:t.toggle},jz(t,r),ge(n.select)&&(n.select.on||n.select.clear)){const o='event.item && indexof(event.item.mark.role, "legend") < 0';for(const a of t.events)a.filter=ye(a.filter??[]),a.filter.includes(o)||a.filter.push(o)}const i=tx(t.bind)?t.bind.legend:"click",s=me(i)?Iu(i,"view"):ye(i);t.bind={legend:{merge:s}}},topLevelSignals:(e,t,n)=>{const r=t.name,i=tx(t.bind)&&t.bind.legend,s=o=>a=>{const u=Be(a);return u.markname=o,u};for(const o of t.project.items){if(!o.hasLegend)continue;const a=`${Ut(o.field)}_legend`,u=`${r}_${a}`;if(n.filter(c=>c.name===u).length===0){const c=i.merge.map(s(`${a}_symbols`)).concat(i.merge.map(s(`${a}_labels`))).concat(i.merge.map(s(`${a}_entries`)));n.unshift({name:u,...t.init?{}:{value:null},on:[{events:c,update:"isDefined(datum.value) ? datum.value : item().items[0].items[0].datum.value",force:!0},{events:i.merge,update:`!event.item || !datum ? null : ${u}`,force:!0}]})}}return n},signals:(e,t,n)=>{const r=t.name,i=t.project,s=n.find(d=>d.name===r+xa),o=r+Gg,a=i.items.filter(d=>d.hasLegend).map(d=>Ut(`${r}_${Ut(d.field)}_legend`)),l=`${a.map(d=>`${d} !== null`).join(" && ")} ? {fields: ${o}, values: [${a.join(", ")}]} : null`;t.events&&a.length>0?s.on.push({events:a.map(d=>({signal:d})),update:l}):a.length>0&&(s.update=l,delete s.value,delete s.on);const c=n.find(d=>d.name===r+iy),f=tx(t.bind)&&t.bind.legend;return c&&(t.events?c.on.push({...c.on[0],events:f}):c.on[0].events=f),n}};function bye(e,t,n){var i;const r=(i=e.fieldDef(t))==null?void 0:i.field;for(const s of Yn(e.component.selection??{})){const o=s.project.hasField[r]??s.project.hasChannel[t];if(o&&Oz.defined(s)){const a=n.get("selections")??[];a.push(s.name),n.set("selections",a,!1),o.hasLegend=!0}}}const Lz="_translate_anchor",Iz="_translate_delta",xye={defined:e=>e.type==="interval"&&e.translate,signals:(e,t,n)=>{const r=t.name,i=da.defined(t),s=r+Lz,{x:o,y:a}=t.project.hasChannel;let u=Iu(t.translate,"scope");return i||(u=u.map(l=>(l.between[0].markname=r+yf,l))),n.push({name:s,value:{},on:[{events:u.map(l=>l.between[0]),update:"{x: x(unit), y: y(unit)"+(o!==void 0?`, extent_x: ${i?nE(e,qt):`slice(${o.signals.visual})`}`:"")+(a!==void 0?`, extent_y: ${i?nE(e,On):`slice(${a.signals.visual})`}`:"")+"}"}]},{name:r+Iz,value:{},on:[{events:u,update:`{x: ${s}.x - x(unit), y: ${s}.y - y(unit)}`}]}),o!==void 0&&v4(e,t,o,"width",n),a!==void 0&&v4(e,t,a,"height",n),n}};function v4(e,t,n,r,i){const s=t.name,o=s+Lz,a=s+Iz,u=n.channel,l=da.defined(t),c=i.find(_=>_.name===n.signals[l?"data":"visual"]),f=e.getSizeSignalRef(r).signal,d=e.getScaleComponent(u),h=d&&d.get("type"),p=d&&d.get("reverse"),g=l?u===qt?p?"":"-":p?"-":"":"",m=`${o}.extent_${u}`,y=`${g}${a}.${u} / ${l?`${f}`:`span(${m})`}`,v=!l||!d?"panLinear":h==="log"?"panLog":h==="symlog"?"panSymlog":h==="pow"?"panPow":"panLinear",b=l?h==="pow"?`, ${d.get("exponent")??1}`:h==="symlog"?`, ${d.get("constant")??1}`:"":"",x=`${v}(${m}, ${y}${b})`;c.on.push({events:{signal:a},update:l?x:`clampRange(${x}, 0, ${f})`})}const Pz="_zoom_anchor",Bz="_zoom_delta",_ye={defined:e=>e.type==="interval"&&e.zoom,signals:(e,t,n)=>{const r=t.name,i=da.defined(t),s=r+Bz,{x:o,y:a}=t.project.hasChannel,u=ce(e.scaleName(qt)),l=ce(e.scaleName(On));let c=Iu(t.zoom,"scope");return i||(c=c.map(f=>(f.markname=r+yf,f))),n.push({name:r+Pz,on:[{events:c,update:i?"{"+[u?`x: invert(${u}, x(unit))`:"",l?`y: invert(${l}, y(unit))`:""].filter(f=>f).join(", ")+"}":"{x: x(unit), y: y(unit)}"}]},{name:s,on:[{events:c,force:!0,update:"pow(1.001, event.deltaY * pow(16, event.deltaMode))"}]}),o!==void 0&&b4(e,t,o,"width",n),a!==void 0&&b4(e,t,a,"height",n),n}};function b4(e,t,n,r,i){const s=t.name,o=n.channel,a=da.defined(t),u=i.find(v=>v.name===n.signals[a?"data":"visual"]),l=e.getSizeSignalRef(r).signal,c=e.getScaleComponent(o),f=c&&c.get("type"),d=a?nE(e,o):u.name,h=s+Bz,p=`${s}${Pz}.${o}`,g=!a||!c?"zoomLinear":f==="log"?"zoomLog":f==="symlog"?"zoomSymlog":f==="pow"?"zoomPow":"zoomLinear",m=a?f==="pow"?`, ${c.get("exponent")??1}`:f==="symlog"?`, ${c.get("constant")??1}`:"":"",y=`${g}(${d}, ${p}, ${h}${m})`;u.on.push({events:{signal:h},update:a?y:`clampRange(${y}, 0, ${l})`})}const cc="_store",xa="_tuple",wye="_modify",zz="vlSelectionResolve",cb=[V1e,nye,H1e,Nz,Tz,da,Oz,vye,xye,_ye,Rz];function Eye(e){let t=e.parent;for(;t&&!mi(t);)t=t.parent;return t}function Tl(e,{escape:t}={escape:!0}){let n=t?ce(e.name):e.name;const r=Eye(e);if(r){const{facet:i}=r;for(const s of Oi)i[s]&&(n+=` + '__facet_${s}_' + (facet[${ce(r.vgField(s))}])`)}return n}function U3(e){return Yn(e.component.selection??{}).reduce((t,n)=>t||n.project.hasSelectionId,!1)}function jz(e,t){(me(t.select)||!t.select.on)&&delete e.events,(me(t.select)||!t.select.clear)&&delete e.clear,(me(t.select)||!t.select.toggle)&&delete e.toggle}function ho(e){var t;return(t=e.events)==null?void 0:t.find(n=>"type"in n&&n.type==="timer")}const Aye="RawCode",Sye="Literal",kye="Property",Cye="Identifier",$ye="ArrayExpression",Fye="BinaryExpression",Dye="CallExpression",Mye="ConditionalExpression",Rye="LogicalExpression",Tye="MemberExpression",Nye="ObjectExpression",Oye="UnaryExpression";function Bs(e){this.type=e}Bs.prototype.visit=function(e){let t,n,r;if(e(this))return 1;for(t=Lye(this),n=0,r=t.length;n";Bo[fc]="Identifier";Bo[Gu]="Keyword";Bo[db]="Null";Bo[Dc]="Numeric";Bo[Br]="Punctuator";Bo[Vg]="String";Bo[Iye]="RegularExpression";var Pye="ArrayExpression",Bye="BinaryExpression",zye="CallExpression",jye="ConditionalExpression",Uz="Identifier",Uye="Literal",qye="LogicalExpression",Wye="MemberExpression",Hye="ObjectExpression",Gye="Property",Yye="UnaryExpression",Dn="Unexpected token %0",Vye="Unexpected number",Xye="Unexpected string",Kye="Unexpected identifier",Zye="Unexpected reserved word",Jye="Unexpected end of input",iE="Invalid regular expression",ux="Invalid regular expression: missing /",qz="Octal literals are not allowed in strict mode.",Qye="Duplicate data property in object literal not allowed in strict mode",Hn="ILLEGAL",Bp="Disabled.",eve=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0-\\u08B2\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0980\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA69D\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uA9E0-\\uA9E4\\uA9E6-\\uA9EF\\uA9FA-\\uA9FE\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA7E-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]"),tve=new RegExp("[\\xAA\\xB5\\xBA\\xC0-\\xD6\\xD8-\\xF6\\xF8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0300-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u037F\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u0483-\\u0487\\u048A-\\u052F\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0610-\\u061A\\u0620-\\u0669\\u066E-\\u06D3\\u06D5-\\u06DC\\u06DF-\\u06E8\\u06EA-\\u06FC\\u06FF\\u0710-\\u074A\\u074D-\\u07B1\\u07C0-\\u07F5\\u07FA\\u0800-\\u082D\\u0840-\\u085B\\u08A0-\\u08B2\\u08E4-\\u0963\\u0966-\\u096F\\u0971-\\u0983\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BC-\\u09C4\\u09C7\\u09C8\\u09CB-\\u09CE\\u09D7\\u09DC\\u09DD\\u09DF-\\u09E3\\u09E6-\\u09F1\\u0A01-\\u0A03\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A3C\\u0A3E-\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A59-\\u0A5C\\u0A5E\\u0A66-\\u0A75\\u0A81-\\u0A83\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABC-\\u0AC5\\u0AC7-\\u0AC9\\u0ACB-\\u0ACD\\u0AD0\\u0AE0-\\u0AE3\\u0AE6-\\u0AEF\\u0B01-\\u0B03\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3C-\\u0B44\\u0B47\\u0B48\\u0B4B-\\u0B4D\\u0B56\\u0B57\\u0B5C\\u0B5D\\u0B5F-\\u0B63\\u0B66-\\u0B6F\\u0B71\\u0B82\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BBE-\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCD\\u0BD0\\u0BD7\\u0BE6-\\u0BEF\\u0C00-\\u0C03\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C39\\u0C3D-\\u0C44\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C58\\u0C59\\u0C60-\\u0C63\\u0C66-\\u0C6F\\u0C81-\\u0C83\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBC-\\u0CC4\\u0CC6-\\u0CC8\\u0CCA-\\u0CCD\\u0CD5\\u0CD6\\u0CDE\\u0CE0-\\u0CE3\\u0CE6-\\u0CEF\\u0CF1\\u0CF2\\u0D01-\\u0D03\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D-\\u0D44\\u0D46-\\u0D48\\u0D4A-\\u0D4E\\u0D57\\u0D60-\\u0D63\\u0D66-\\u0D6F\\u0D7A-\\u0D7F\\u0D82\\u0D83\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0DCA\\u0DCF-\\u0DD4\\u0DD6\\u0DD8-\\u0DDF\\u0DE6-\\u0DEF\\u0DF2\\u0DF3\\u0E01-\\u0E3A\\u0E40-\\u0E4E\\u0E50-\\u0E59\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB9\\u0EBB-\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EC8-\\u0ECD\\u0ED0-\\u0ED9\\u0EDC-\\u0EDF\\u0F00\\u0F18\\u0F19\\u0F20-\\u0F29\\u0F35\\u0F37\\u0F39\\u0F3E-\\u0F47\\u0F49-\\u0F6C\\u0F71-\\u0F84\\u0F86-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u1000-\\u1049\\u1050-\\u109D\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u135D-\\u135F\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F8\\u1700-\\u170C\\u170E-\\u1714\\u1720-\\u1734\\u1740-\\u1753\\u1760-\\u176C\\u176E-\\u1770\\u1772\\u1773\\u1780-\\u17D3\\u17D7\\u17DC\\u17DD\\u17E0-\\u17E9\\u180B-\\u180D\\u1810-\\u1819\\u1820-\\u1877\\u1880-\\u18AA\\u18B0-\\u18F5\\u1900-\\u191E\\u1920-\\u192B\\u1930-\\u193B\\u1946-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19B0-\\u19C9\\u19D0-\\u19D9\\u1A00-\\u1A1B\\u1A20-\\u1A5E\\u1A60-\\u1A7C\\u1A7F-\\u1A89\\u1A90-\\u1A99\\u1AA7\\u1AB0-\\u1ABD\\u1B00-\\u1B4B\\u1B50-\\u1B59\\u1B6B-\\u1B73\\u1B80-\\u1BF3\\u1C00-\\u1C37\\u1C40-\\u1C49\\u1C4D-\\u1C7D\\u1CD0-\\u1CD2\\u1CD4-\\u1CF6\\u1CF8\\u1CF9\\u1D00-\\u1DF5\\u1DFC-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u200C\\u200D\\u203F\\u2040\\u2054\\u2071\\u207F\\u2090-\\u209C\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D7F-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2DE0-\\u2DFF\\u2E2F\\u3005-\\u3007\\u3021-\\u302F\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u3099\\u309A\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA62B\\uA640-\\uA66F\\uA674-\\uA67D\\uA67F-\\uA69D\\uA69F-\\uA6F1\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA7AD\\uA7B0\\uA7B1\\uA7F7-\\uA827\\uA840-\\uA873\\uA880-\\uA8C4\\uA8D0-\\uA8D9\\uA8E0-\\uA8F7\\uA8FB\\uA900-\\uA92D\\uA930-\\uA953\\uA960-\\uA97C\\uA980-\\uA9C0\\uA9CF-\\uA9D9\\uA9E0-\\uA9FE\\uAA00-\\uAA36\\uAA40-\\uAA4D\\uAA50-\\uAA59\\uAA60-\\uAA76\\uAA7A-\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEF\\uAAF2-\\uAAF6\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uAB30-\\uAB5A\\uAB5C-\\uAB5F\\uAB64\\uAB65\\uABC0-\\uABEA\\uABEC\\uABED\\uABF0-\\uABF9\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE00-\\uFE0F\\uFE20-\\uFE2D\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF10-\\uFF19\\uFF21-\\uFF3A\\uFF3F\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC]");function hb(e,t){if(!e)throw new Error("ASSERT: "+t)}function Xo(e){return e>=48&&e<=57}function q3(e){return"0123456789abcdefABCDEF".includes(e)}function up(e){return"01234567".includes(e)}function nve(e){return e===32||e===9||e===11||e===12||e===160||e>=5760&&[5760,6158,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8239,8287,12288,65279].includes(e)}function zp(e){return e===10||e===13||e===8232||e===8233}function Xg(e){return e===36||e===95||e>=65&&e<=90||e>=97&&e<=122||e===92||e>=128&&eve.test(String.fromCharCode(e))}function sy(e){return e===36||e===95||e>=65&&e<=90||e>=97&&e<=122||e>=48&&e<=57||e===92||e>=128&&tve.test(String.fromCharCode(e))}const rve={if:1,in:1,do:1,var:1,for:1,new:1,try:1,let:1,this:1,else:1,case:1,void:1,with:1,enum:1,while:1,break:1,catch:1,throw:1,const:1,yield:1,class:1,super:1,return:1,typeof:1,delete:1,switch:1,export:1,import:1,public:1,static:1,default:1,finally:1,extends:1,package:1,private:1,function:1,continue:1,debugger:1,interface:1,protected:1,instanceof:1,implements:1};function Wz(){for(;Z1114111||e!=="}")&&ct({},Dn,Hn),t<=65535?String.fromCharCode(t):(n=(t-65536>>10)+55296,r=(t-65536&1023)+56320,String.fromCharCode(n,r))}function Hz(){var e,t;for(e=ke.charCodeAt(Z++),t=String.fromCharCode(e),e===92&&(ke.charCodeAt(Z)!==117&&ct({},Dn,Hn),++Z,e=sE("u"),(!e||e==="\\"||!Xg(e.charCodeAt(0)))&&ct({},Dn,Hn),t=e);Z>>=")return Z+=4,{type:Br,value:o,start:e,end:Z};if(s=o.substr(0,3),s===">>>"||s==="<<="||s===">>=")return Z+=3,{type:Br,value:s,start:e,end:Z};if(i=s.substr(0,2),r===i[1]&&"+-<>&|".includes(r)||i==="=>")return Z+=2,{type:Br,value:i,start:e,end:Z};if(i==="//"&&ct({},Dn,Hn),"<>=!+-*%&|^/".includes(r))return++Z,{type:Br,value:r,start:e,end:Z};ct({},Dn,Hn)}function ave(e){let t="";for(;Z{if(parseInt(i,16)<=1114111)return"x";ct({},iE)}).replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g,"x"));try{new RegExp(n)}catch{ct({},iE)}try{return new RegExp(e,t)}catch{return null}}function fve(){var e,t,n,r,i;for(e=ke[Z],hb(e==="/","Regular expression literal must start with a slash"),t=ke[Z++],n=!1,r=!1;Z=0&&ct({},iE,n),{value:n,literal:t}}function hve(){var e,t,n,r;return xt=null,Wz(),e=Z,t=fve(),n=dve(),r=cve(t.value,n.value),{literal:t.literal+n.literal,value:r,regex:{pattern:t.value,flags:n.value},start:e,end:Z}}function pve(e){return e.type===fc||e.type===Gu||e.type===fb||e.type===db}function Gz(){if(Wz(),Z>=fr)return{type:Yg,start:Z,end:Z};const e=ke.charCodeAt(Z);return Xg(e)?ove():e===40||e===41||e===59?lx():e===39||e===34?lve():e===46?Xo(ke.charCodeAt(Z+1))?x4():lx():Xo(e)?x4():lx()}function Ur(){const e=xt;return Z=e.end,xt=Gz(),Z=e.end,e}function Yz(){const e=Z;xt=Gz(),Z=e}function gve(e){const t=new Bs(Pye);return t.elements=e,t}function _4(e,t,n){const r=new Bs(e==="||"||e==="&&"?qye:Bye);return r.operator=e,r.left=t,r.right=n,r}function mve(e,t){const n=new Bs(zye);return n.callee=e,n.arguments=t,n}function yve(e,t,n){const r=new Bs(jye);return r.test=e,r.consequent=t,r.alternate=n,r}function W3(e){const t=new Bs(Uz);return t.name=e,t}function jh(e){const t=new Bs(Uye);return t.value=e.value,t.raw=ke.slice(e.start,e.end),e.regex&&(t.raw==="//"&&(t.raw="/(?:)/"),t.regex=e.regex),t}function w4(e,t,n){const r=new Bs(Wye);return r.computed=e==="[",r.object=t,r.property=n,r.computed||(n.member=!0),r}function vve(e){const t=new Bs(Hye);return t.properties=e,t}function E4(e,t,n){const r=new Bs(Gye);return r.key=t,r.value=n,r.kind=e,r}function bve(e,t){const n=new Bs(Yye);return n.operator=e,n.argument=t,n.prefix=!0,n}function ct(e,t){var n,r=Array.prototype.slice.call(arguments,2),i=t.replace(/%(\d)/g,(s,o)=>(hb(o":case"<=":case">=":case"instanceof":case"in":t=7;break;case"<<":case">>":case">>>":t=8;break;case"+":case"-":t=9;break;case"*":case"/":case"%":t=11;break}return t}function Mve(){var e,t,n,r,i,s,o,a,u,l;if(e=xt,u=Am(),r=xt,i=k4(r),i===0)return u;for(r.prec=i,Ur(),t=[e,xt],o=Am(),s=[u,r,o];(i=k4(xt))>0;){for(;s.length>2&&i<=s[s.length-2].prec;)o=s.pop(),a=s.pop().value,u=s.pop(),t.pop(),n=_4(a,u,o),s.push(n);r=Ur(),r.prec=i,s.push(r),t.push(xt),n=Am(),s.push(n)}for(l=s.length-1,n=s[l],t.pop();l>1;)t.pop(),n=_4(s[l-1].value,s[l-2],n),l-=2;return n}function dc(){var e,t,n;return e=Mve(),Lt("?")&&(Ur(),t=dc(),dr(":"),n=dc(),e=yve(e,t,n)),e}function H3(){const e=dc();if(Lt(","))throw new Error(Bp);return e}function Rve(e){ke=e,Z=0,fr=ke.length,xt=null,Yz();const t=H3();if(xt.type!==Yg)throw new Error("Unexpect token after expression.");return t}function oE(e){const t=[];return e.type==="Identifier"?[e.name]:e.type==="Literal"?[e.value]:(e.type==="MemberExpression"&&(t.push(...oE(e.object)),t.push(...oE(e.property))),t)}function Vz(e){return e.object.type==="MemberExpression"?Vz(e.object):e.object.name==="datum"}function Xz(e){const t=Rve(e),n=new Set;return t.visit(r=>{r.type==="MemberExpression"&&Vz(r)&&n.add(oE(r).slice(1).join("."))}),n}class jd extends _t{clone(){return new jd(null,this.model,Be(this.filter))}constructor(t,n,r){super(t),this.model=n,this.filter=r,this.expr=oy(this.model,this.filter,this),this._dependentFields=Xz(this.expr)}dependentFields(){return this._dependentFields}producedFields(){return new Set}assemble(){return{type:"filter",expr:this.expr}}hash(){return`Filter ${this.expr}`}}function Tve(e,t){const n={},r=e.config.selection;if(!t||!t.length)return n;let i=0;for(const s of t){const o=Ut(s.name),a=s.select,u=me(a)?a:a.type,l=ge(a)?Be(a):{type:u},c=r[u];for(const h in c)h==="fields"||h==="encodings"||(h==="mark"&&(l.mark={...c.mark,...l.mark}),(l[h]===void 0||l[h]===!0)&&(l[h]=Be(c[h]??l[h])));const f=n[o]={...l,name:o,type:u,init:s.value,bind:s.bind,events:me(l.on)?Iu(l.on,"scope"):ye(Be(l.on))};if(ho(f)&&(i++,i>1)){delete n[o];continue}const d=Be(s);for(const h of cb)h.defined(f)&&h.parse&&h.parse(e,f,d)}return i>1&&ae(Upe),n}function Kz(e,t,n,r="datum"){const i=me(t)?t:t.param,s=Ut(i),o=ce(s+cc);let a;try{a=e.getSelectionComponent(s,i)}catch{return`!!${s}`}if(a.project.timeUnit){const d=n??e.component.data.raw,h=a.project.timeUnit.clone();d.parent?h.insertAsParentOf(d):d.parent=h}const u=a.project.hasSelectionId?"vlSelectionIdTest(":"vlSelectionTest(",l=a.resolve==="global"?")":`, ${ce(a.resolve)})`,c=`${u}${o}, ${r}${l}`,f=`length(data(${o}))`;return t.empty===!1?`${f} && ${c}`:`!${f} || ${c}`}function Zz(e,t,n){const r=Ut(t),i=n.encoding;let s=n.field,o;try{o=e.getSelectionComponent(r,t)}catch{return r}if(!i&&!s)s=o.project.items[0].field,o.project.items.length>1&&ae(qpe(s));else if(i&&!s){const a=o.project.items.filter(u=>u.channel===i);!a.length||a.length>1?(s=o.project.items[0].field,ae(Wpe(a,i,n,s))):s=a[0].field}return`${o.name}[${ce(Gi(s))}]`}function Nve(e,t){for(const[n,r]of _u(e.component.selection??{})){const i=e.getName(`lookup_${n}`);e.component.data.outputNodes[i]=r.materialized=new Gr(new jd(t,e,{param:n}),i,Vt.Lookup,e.component.data.outputNodeRefCounts)}}function oy(e,t,n){return op(t,r=>me(r)?r:Qge(r)?Kz(e,r,n):tB(r))}function Ove(e,t){if(e)return ee(e)&&!za(e)?e.map(n=>E3(n,t)).join(", "):e}function fx(e,t,n,r){var i,s;e.encode??(e.encode={}),(i=e.encode)[t]??(i[t]={}),(s=e.encode[t]).update??(s.update={}),e.encode[t].update[n]=r}function Uh(e,t,n,r={header:!1}){var f,d;const{disable:i,orient:s,scale:o,labelExpr:a,title:u,zindex:l,...c}=e.combine();if(!i){for(const h in c){const p=h,g=ime[p],m=c[p];if(g&&g!==t&&g!=="both")delete c[p];else if(Hg(m)){const{condition:y,...v}=m,b=ye(y),x=YM[p];if(x){const{vgProp:_,part:A}=x,E=[...b.map(S=>{const{test:k,...$}=S;return{test:oy(null,k),...$}}),v];fx(c,A,_,E),delete c[p]}else if(x===null){const _={signal:b.map(A=>{const{test:E,...S}=A;return`${oy(null,E)} ? ${MM(S)} : `}).join("")+MM(v)};c[p]=_}}else if(Ce(m)){const y=YM[p];if(y){const{vgProp:v,part:b}=y;fx(c,b,v,m),delete c[p]}}Qe(["labelAlign","labelBaseline"],p)&&c[p]===null&&delete c[p]}if(t==="grid"){if(!c.grid)return;if(c.encode){const{grid:h}=c.encode;c.encode={...h?{grid:h}:{}},Et(c.encode)&&delete c.encode}return{scale:o,orient:s,...c,domain:!1,labels:!1,aria:!1,maxExtent:0,minExtent:0,ticks:!1,zindex:un(l,0)}}else{if(!r.header&&e.mainExtracted)return;if(a!==void 0){let p=a;(d=(f=c.encode)==null?void 0:f.labels)!=null&&d.update&&Ce(c.encode.labels.update.text)&&(p=nc(a,"datum.label",c.encode.labels.update.text.signal)),fx(c,"labels","text",{signal:p})}if(c.labelAlign===null&&delete c.labelAlign,c.encode){for(const p of RB)e.hasAxisPart(p)||delete c.encode[p];Et(c.encode)&&delete c.encode}const h=Ove(u,n);return{scale:o,orient:s,grid:!1,...h?{title:h}:{},...c,...n.aria===!1?{aria:!1}:{},zindex:un(l,0)}}}}function Jz(e){const{axes:t}=e.component,n=[];for(const r of Ca)if(t[r]){for(const i of t[r])if(!i.get("disable")&&!i.get("gridScale")){const s=r==="x"?"height":"width",o=e.getSizeSignalRef(s).signal;s!==o&&n.push({name:s,update:o})}}return n}function Lve(e,t){const{x:n=[],y:r=[]}=e;return[...n.map(i=>Uh(i,"grid",t)),...r.map(i=>Uh(i,"grid",t)),...n.map(i=>Uh(i,"main",t)),...r.map(i=>Uh(i,"main",t))].filter(i=>i)}function C4(e,t,n,r){return Object.assign.apply(null,[{},...e.map(i=>{if(i==="axisOrient"){const s=n==="x"?"bottom":"left",o=t[n==="x"?"axisBottom":"axisLeft"]||{},a=t[n==="x"?"axisTop":"axisRight"]||{},u=new Set([...ie(o),...ie(a)]),l={};for(const c of u.values())l[c]={signal:`${r.signal} === "${s}" ? ${vs(o[c])} : ${vs(a[c])}`};return l}return t[i]})])}function Ive(e,t,n,r){const i=t==="band"?["axisDiscrete","axisBand"]:t==="point"?["axisDiscrete","axisPoint"]:sB(t)?["axisQuantitative"]:t==="time"||t==="utc"?["axisTemporal"]:[],s=e==="x"?"axisX":"axisY",o=Ce(n)?"axisOrient":`axis${Ng(n)}`,a=[...i,...i.map(l=>s+l.substr(4))],u=["axis",o,s];return{vlOnlyAxisConfig:C4(a,r,e,n),vgAxisConfig:C4(u,r,e,n),axisConfigStyle:Pve([...u,...a],r)}}function Pve(e,t){var r;const n=[{}];for(const i of e){let s=(r=t[i])==null?void 0:r.style;if(s){s=ye(s);for(const o of s)n.push(t.style[o])}}return Object.assign.apply(null,n)}function aE(e,t,n,r={}){var s;const i=TP(e,n,t);if(i!==void 0)return{configFrom:"style",configValue:i};for(const o of["vlOnlyAxisConfig","vgAxisConfig","axisConfigStyle"])if(((s=r[o])==null?void 0:s[e])!==void 0)return{configFrom:o,configValue:r[o][e]};return{}}const $4={scale:({model:e,channel:t})=>e.scaleName(t),format:({format:e})=>e,formatType:({formatType:e})=>e,grid:({fieldOrDatumDef:e,axis:t,scaleType:n})=>t.grid??Bve(n,e),gridScale:({model:e,channel:t})=>zve(e,t),labelAlign:({axis:e,labelAngle:t,orient:n,channel:r})=>e.labelAlign||ej(t,n,r),labelAngle:({labelAngle:e})=>e,labelBaseline:({axis:e,labelAngle:t,orient:n,channel:r})=>e.labelBaseline||Qz(t,n,r),labelFlush:({axis:e,fieldOrDatumDef:t,channel:n})=>e.labelFlush??Uve(t.type,n),labelOverlap:({axis:e,fieldOrDatumDef:t,scaleType:n})=>e.labelOverlap??qve(t.type,n,ue(t)&&!!t.timeUnit,ue(t)?t.sort:void 0),orient:({orient:e})=>e,tickCount:({channel:e,model:t,axis:n,fieldOrDatumDef:r,scaleType:i})=>{const s=e==="x"?"width":e==="y"?"height":void 0,o=s?t.getSizeSignalRef(s):void 0;return n.tickCount??Hve({fieldOrDatumDef:r,scaleType:i,size:o,values:n.values})},tickMinStep:Gve,title:({axis:e,model:t,channel:n})=>{if(e.title!==void 0)return e.title;const r=tj(t,n);if(r!==void 0)return r;const i=t.typedFieldDef(n),s=n==="x"?"x2":"y2",o=t.fieldDef(s);return OP(i?[HM(i)]:[],ue(o)?[HM(o)]:[])},values:({axis:e,fieldOrDatumDef:t})=>Yve(e,t),zindex:({axis:e,fieldOrDatumDef:t,mark:n})=>e.zindex??Vve(n,t)};function Bve(e,t){return!Tn(e)&&ue(t)&&!Mt(t==null?void 0:t.bin)&&!Pn(t==null?void 0:t.bin)}function zve(e,t){const n=t==="x"?"y":"x";if(e.getScaleComponent(n))return e.scaleName(n)}function jve(e,t,n,r,i){const s=t==null?void 0:t.labelAngle;if(s!==void 0)return Ce(s)?s:Lp(s);{const{configValue:o}=aE("labelAngle",r,t==null?void 0:t.style,i);return o!==void 0?Lp(o):n===qt&&Qe([f3,c3],e.type)&&!(ue(e)&&e.timeUnit)?270:void 0}}function uE(e){return`(((${e.signal} % 360) + 360) % 360)`}function Qz(e,t,n,r){if(e!==void 0)if(n==="x"){if(Ce(e)){const i=uE(e),s=Ce(t)?`(${t.signal} === "top")`:t==="top";return{signal:`(45 < ${i} && ${i} < 135) || (225 < ${i} && ${i} < 315) ? "middle" :(${i} <= 45 || 315 <= ${i}) === ${s} ? "bottom" : "top"`}}if(45{if(Fc(r)&&_B(r.sort)){const{field:s,timeUnit:o}=r,a=r.sort,u=a.map((l,c)=>`${tB({field:s,timeUnit:o,equal:l})} ? ${c} : `).join("")+a.length;t=new dd(t,{calculate:u,as:hd(r,i,{forAs:!0})})}}),t}producedFields(){return new Set([this.transform.as])}dependentFields(){return this._dependentFields}assemble(){return{type:"formula",expr:this.transform.calculate,as:this.transform.as}}hash(){return`Calculate ${rt(this.transform)}`}}function hd(e,t,n){return pe(e,{prefix:t,suffix:"sort_index",...n})}function gb(e,t){return Qe(["top","bottom"],t)?"column":Qe(["left","right"],t)||e==="row"?"row":"column"}function pd(e,t,n,r){const i=r==="row"?n.headerRow:r==="column"?n.headerColumn:n.headerFacet;return un((t||{})[e],i[e],n.header[e])}function mb(e,t,n,r){const i={};for(const s of e){const o=pd(s,t||{},n,r);o!==void 0&&(i[s]=o)}return i}const G3=["row","column"],Y3=["header","footer"];function Xve(e,t){const n=e.component.layoutHeaders[t].title,r=e.config?e.config:void 0,i=e.component.layoutHeaders[t].facetFieldDef?e.component.layoutHeaders[t].facetFieldDef:void 0,{titleAnchor:s,titleAngle:o,titleOrient:a}=mb(["titleAnchor","titleAngle","titleOrient"],i.header,r,t),u=gb(t,a),l=Lp(o);return{name:`${t}-title`,type:"group",role:`${u}-title`,title:{text:n,...t==="row"?{orient:"left"}:{},style:"guide-title",...rj(l,u),...nj(u,l,s),...ij(r,i,t,kme,KB)}}}function nj(e,t,n="middle"){switch(n){case"start":return{align:"left"};case"end":return{align:"right"}}const r=ej(t,e==="row"?"left":"top",e==="row"?"y":"x");return r?{align:r}:{}}function rj(e,t){const n=Qz(e,t==="row"?"left":"top",t==="row"?"y":"x",!0);return n?{baseline:n}:{}}function Kve(e,t){const n=e.component.layoutHeaders[t],r=[];for(const i of Y3)if(n[i])for(const s of n[i]){const o=Jve(e,t,i,n,s);o!=null&&r.push(o)}return r}function Zve(e,t){const{sort:n}=e;return fa(n)?{field:pe(n,{expr:"datum"}),order:n.order??"ascending"}:ee(n)?{field:hd(e,t,{expr:"datum"}),order:"ascending"}:{field:pe(e,{expr:"datum"}),order:n??"ascending"}}function lE(e,t,n){const{format:r,formatType:i,labelAngle:s,labelAnchor:o,labelOrient:a,labelExpr:u}=mb(["format","formatType","labelAngle","labelAnchor","labelOrient","labelExpr"],e.header,n,t),l=b3({fieldOrDatumDef:e,format:r,formatType:i,expr:"parent",config:n}).signal,c=gb(t,a);return{text:{signal:u?nc(nc(u,"datum.label",l),"datum.value",pe(e,{expr:"parent"})):l},...t==="row"?{orient:"left"}:{},style:"guide-label",frame:"group",...rj(s,c),...nj(c,s,o),...ij(n,e,t,Cme,ZB)}}function Jve(e,t,n,r,i){if(i){let s=null;const{facetFieldDef:o}=r,a=e.config?e.config:void 0;if(o&&i.labels){const{labelOrient:f}=mb(["labelOrient"],o.header,a,t);(t==="row"&&!Qe(["top","bottom"],f)||t==="column"&&!Qe(["left","right"],f))&&(s=lE(o,t,a))}const u=mi(e)&&!jg(e.facet),l=i.axes,c=(l==null?void 0:l.length)>0;if(s||c){const f=t==="row"?"height":"width";return{name:e.getName(`${t}_${n}`),type:"group",role:`${t}-${n}`,...r.facetFieldDef?{from:{data:e.getName(`${t}_domain`)},sort:Zve(o,t)}:{},...c&&u?{from:{data:e.getName(`facet_domain_${t}`)}}:{},...s?{title:s}:{},...i.sizeSignal?{encode:{update:{[f]:i.sizeSignal}}}:{},...c?{axes:l}:{}}}}return null}const Qve={column:{start:0,end:1},row:{start:1,end:0}};function ebe(e,t){return Qve[t][e]}function tbe(e,t){const n={};for(const r of Oi){const i=e[r];if(i!=null&&i.facetFieldDef){const{titleAnchor:s,titleOrient:o}=mb(["titleAnchor","titleOrient"],i.facetFieldDef.header,t,r),a=gb(r,o),u=ebe(s,a);u!==void 0&&(n[a]=u)}}return Et(n)?void 0:n}function ij(e,t,n,r,i){const s={};for(const o of r){if(!i[o])continue;const a=pd(o,t==null?void 0:t.header,e,n);a!==void 0&&(s[i[o]]=a)}return s}function V3(e){return[...R0(e,"width"),...R0(e,"height"),...R0(e,"childWidth"),...R0(e,"childHeight")]}function R0(e,t){const n=t==="width"?"x":"y",r=e.component.layoutSize.get(t);if(!r||r==="merged")return[];const i=e.getSizeSignalRef(t).signal;if(r==="step"){const s=e.getScaleComponent(n);if(s){const o=s.get("type"),a=s.get("range");if(Tn(o)&&kc(a)){const u=e.scaleName(n);return mi(e.parent)&&e.parent.component.resolve.scale[n]==="independent"?[F4(u,a)]:[F4(u,a),{name:i,update:sj(u,s,`domain('${u}').length`)}]}}throw new Error("layout size is step although width/height is not step.")}else if(r=="container"){const s=i.endsWith("width"),o=s?"containerSize()[0]":"containerSize()[1]",a=Kw(e.config.view,s?"width":"height"),u=`isFinite(${o}) ? ${o} : ${a}`;return[{name:i,init:u,on:[{update:u,events:"window:resize"}]}]}else return[{name:i,value:r}]}function F4(e,t){const n=`${e}_step`;return Ce(t.step)?{name:n,update:t.step.signal}:{name:n,value:t.step}}function sj(e,t,n){const r=t.get("type"),i=t.get("padding"),s=un(t.get("paddingOuter"),i);let o=t.get("paddingInner");return o=r==="band"?o!==void 0?o:i:1,`bandspace(${n}, ${vs(o)}, ${vs(s)}) * ${e}_step`}function oj(e){return e==="childWidth"?"width":e==="childHeight"?"height":e}function aj(e,t){return ie(e).reduce((n,r)=>({...n,...zd({model:t,channelDef:e[r],vgChannel:r,mainRefFn:i=>Ot(i.value),invalidValueRef:void 0})}),{})}function uj(e,t){if(mi(t))return e==="theta"?"independent":"shared";if(Wd(t))return"shared";if(t$(t))return ln(e)||e==="theta"||e==="radius"?"independent":"shared";throw new Error("invalid model type for resolve")}function X3(e,t){const n=e.scale[t],r=ln(t)?"axis":"legend";return n==="independent"?(e[r][t]==="shared"&&ae(_ge(t)),"independent"):e[r][t]||"shared"}const nbe={...Dme,disable:1,labelExpr:1,selections:1,opacity:1,shape:1,stroke:1,fill:1,size:1,strokeWidth:1,strokeDash:1,encode:1},lj=ie(nbe);class rbe extends Fa{}const D4={symbols:ibe,gradient:sbe,labels:obe,entries:abe};function ibe(e,{fieldOrDatumDef:t,model:n,channel:r,legendCmpt:i,legendType:s}){if(s!=="symbol")return;const{markDef:o,encoding:a,config:u,mark:l}=n,c=o.filled&&l!=="trail";let f={...Fpe({},n,S0e),...Fz(n,{filled:c})};const d=i.get("symbolOpacity")??u.legend.symbolOpacity,h=i.get("symbolFillColor")??u.legend.symbolFillColor,p=i.get("symbolStrokeColor")??u.legend.symbolStrokeColor,g=d===void 0?cj(a.opacity)??o.opacity:void 0;if(f.fill){if(r==="fill"||c&&r===Kr)delete f.fill;else if(oe(f.fill,"field"))h?delete f.fill:(f.fill=Ot(u.legend.symbolBaseFillColor??"black"),f.fillOpacity=Ot(g??1));else if(ee(f.fill)){const m=cE(a.fill??a.color)??o.fill??(c&&o.color);m&&(f.fill=Ot(m))}}if(f.stroke){if(r==="stroke"||!c&&r===Kr)delete f.stroke;else if(oe(f.stroke,"field")||p)delete f.stroke;else if(ee(f.stroke)){const m=un(cE(a.stroke||a.color),o.stroke,c?o.color:void 0);m&&(f.stroke={value:m})}}if(r!==ka){const m=ue(t)&&dj(n,i,t);m?f.opacity=[{test:m,...Ot(g??1)},Ot(u.legend.unselectedOpacity)]:g&&(f.opacity=Ot(g))}return f={...f,...e},Et(f)?void 0:f}function sbe(e,{model:t,legendType:n,legendCmpt:r}){if(n!=="gradient")return;const{config:i,markDef:s,encoding:o}=t;let a={};const l=(r.get("gradientOpacity")??i.legend.gradientOpacity)===void 0?cj(o.opacity)||s.opacity:void 0;return l&&(a.opacity=Ot(l)),a={...a,...e},Et(a)?void 0:a}function obe(e,{fieldOrDatumDef:t,model:n,channel:r,legendCmpt:i}){const s=n.legend(r)||{},o=n.config,a=ue(t)?dj(n,i,t):void 0,u=a?[{test:a,value:1},{value:o.legend.unselectedOpacity}]:void 0,{format:l,formatType:c}=s;let f;uc(c)?f=bs({fieldOrDatumDef:t,field:"datum.value",format:l,formatType:c,config:o}):l===void 0&&c===void 0&&o.customFormatTypes&&(t.type==="quantitative"&&o.numberFormatType?f=bs({fieldOrDatumDef:t,field:"datum.value",format:o.numberFormat,formatType:o.numberFormatType,config:o}):t.type==="temporal"&&o.timeFormatType&&ue(t)&&t.timeUnit===void 0&&(f=bs({fieldOrDatumDef:t,field:"datum.value",format:o.timeFormat,formatType:o.timeFormatType,config:o})));const d={...u?{opacity:u}:{},...f?{text:f}:{},...e};return Et(d)?void 0:d}function abe(e,{legendCmpt:t}){const n=t.get("selections");return n!=null&&n.length?{...e,fill:{value:"transparent"}}:e}function cj(e){return fj(e,(t,n)=>Math.max(t,n.value))}function cE(e){return fj(e,(t,n)=>un(t,n.value))}function fj(e,t){if(G0e(e))return ye(e.condition).reduce(t,e.value);if($s(e))return e.value}function dj(e,t,n){const r=t.get("selections");if(!(r!=null&&r.length))return;const i=ce(n.field);return r.map(s=>`(!length(data(${ce(Ut(s)+cc)})) || (${s}[${i}] && indexof(${s}[${i}], datum.value) >= 0))`).join(" || ")}const M4={direction:({direction:e})=>e,format:({fieldOrDatumDef:e,legend:t,config:n})=>{const{format:r,formatType:i}=t;return vB(e,e.type,r,i,n,!1)},formatType:({legend:e,fieldOrDatumDef:t,scaleType:n})=>{const{formatType:r}=e;return bB(r,t,n)},gradientLength:e=>{const{legend:t,legendConfig:n}=e;return t.gradientLength??n.gradientLength??pbe(e)},labelOverlap:({legend:e,legendConfig:t,scaleType:n})=>e.labelOverlap??t.labelOverlap??gbe(n),symbolType:({legend:e,markDef:t,channel:n,encoding:r})=>e.symbolType??lbe(t.type,n,r.shape,t.shape),title:({fieldOrDatumDef:e,config:t})=>mf(e,t,{allowDisabling:!0}),type:({legendType:e,scaleType:t,channel:n})=>{if(gf(n)&&ao(t)){if(e==="gradient")return}else if(e==="symbol")return;return e},values:({fieldOrDatumDef:e,legend:t})=>ube(t,e)};function ube(e,t){const n=e.values;if(ee(n))return MB(t,n);if(Ce(n))return n}function lbe(e,t,n,r){if(t!=="shape"){const i=cE(n)??r;if(i)return i}switch(e){case"bar":case"rect":case"image":case"square":return"square";case"line":case"trail":case"rule":return"stroke";case"arc":case"point":case"circle":case"tick":case"geoshape":case"area":case"text":return"circle"}}function cbe(e){const{legend:t}=e;return un(t.type,fbe(e))}function fbe({channel:e,timeUnit:t,scaleType:n}){if(gf(e)){if(Qe(["quarter","month","day"],t))return"symbol";if(ao(n))return"gradient"}return"symbol"}function dbe({legendConfig:e,legendType:t,orient:n,legend:r}){return r.direction??e[t?"gradientDirection":"symbolDirection"]??hbe(n,t)}function hbe(e,t){switch(e){case"top":case"bottom":return"horizontal";case"left":case"right":case"none":case void 0:return;default:return t==="gradient"?"horizontal":void 0}}function pbe({legendConfig:e,model:t,direction:n,orient:r,scaleType:i}){const{gradientHorizontalMaxLength:s,gradientHorizontalMinLength:o,gradientVerticalMaxLength:a,gradientVerticalMinLength:u}=e;if(ao(i))return n==="horizontal"?r==="top"||r==="bottom"?R4(t,"width",o,s):o:R4(t,"height",u,a)}function R4(e,t,n,r){return{signal:`clamp(${e.getSizeSignalRef(t).signal}, ${n}, ${r})`}}function gbe(e){if(Qe(["quantile","threshold","log","symlog"],e))return"greedy"}function hj(e){const t=Gt(e)?mbe(e):xbe(e);return e.component.legends=t,t}function mbe(e){const{encoding:t}=e,n={};for(const r of[Kr,...QB]){const i=yn(t[r]);!i||!e.getScaleComponent(r)||r===Zr&&ue(i)&&i.type===Bd||(n[r]=bbe(e,r))}return n}function ybe(e,t){const n=e.scaleName(t);if(e.mark==="trail"){if(t==="color")return{stroke:n};if(t==="size")return{strokeWidth:n}}return t==="color"?e.markDef.filled?{fill:n}:{stroke:n}:{[t]:n}}function vbe(e,t,n,r){switch(t){case"disable":return n!==void 0;case"values":return!!(n!=null&&n.values);case"title":if(t==="title"&&e===(r==null?void 0:r.title))return!0}return e===(n||{})[t]}function bbe(e,t){var x;let n=e.legend(t);const{markDef:r,encoding:i,config:s}=e,o=s.legend,a=new rbe({},ybe(e,t));bye(e,t,a);const u=n!==void 0?!n:o.disable;if(a.set("disable",u,n!==void 0),u)return a;n=n||{};const l=e.getScaleComponent(t).get("type"),c=yn(i[t]),f=ue(c)?(x=Mn(c.timeUnit))==null?void 0:x.unit:void 0,d=n.orient||s.legend.orient||"right",h=cbe({legend:n,channel:t,timeUnit:f,scaleType:l}),p=dbe({legend:n,legendType:h,orient:d,legendConfig:o}),g={legend:n,channel:t,model:e,markDef:r,encoding:i,fieldOrDatumDef:c,legendConfig:o,config:s,scaleType:l,orient:d,legendType:h,direction:p};for(const _ of lj){if(h==="gradient"&&_.startsWith("symbol")||h==="symbol"&&_.startsWith("gradient"))continue;const A=_ in M4?M4[_](g):n[_];if(A!==void 0){const E=vbe(A,_,n,e.fieldDef(t));(E||s.legend[_]===void 0)&&a.set(_,A,E)}}const m=(n==null?void 0:n.encoding)??{},y=a.get("selections"),v={},b={fieldOrDatumDef:c,model:e,channel:t,legendCmpt:a,legendType:h};for(const _ of["labels","legend","title","symbols","gradient","entries"]){const A=aj(m[_]??{},e),E=_ in D4?D4[_](A,b):A;E!==void 0&&!Et(E)&&(v[_]={...y!=null&&y.length&&ue(c)?{name:`${Ut(c.field)}_legend_${_}`}:{},...y!=null&&y.length?{interactive:!!y}:{},update:E})}return Et(v)||a.set("encode",v,!!(n!=null&&n.encoding)),a}function xbe(e){const{legends:t,resolve:n}=e.component;for(const r of e.children){hj(r);for(const i of ie(r.component.legends))n.legend[i]=X3(e.component.resolve,i),n.legend[i]==="shared"&&(t[i]=pj(t[i],r.component.legends[i]),t[i]||(n.legend[i]="independent",delete t[i]))}for(const r of ie(t))for(const i of e.children)i.component.legends[r]&&n.legend[r]==="shared"&&delete i.component.legends[r];return t}function pj(e,t){var s,o,a,u;if(!e)return t.clone();const n=e.getWithExplicit("orient"),r=t.getWithExplicit("orient");if(n.explicit&&r.explicit&&n.value!==r.value)return;let i=!1;for(const l of lj){const c=Au(e.getWithExplicit(l),t.getWithExplicit(l),l,"legend",(f,d)=>{switch(l){case"symbolType":return _be(f,d);case"title":return IP(f,d);case"type":return i=!0,ii("symbol")}return ob(f,d,l,"legend")});e.setWithExplicit(l,c)}return i&&((o=(s=e.implicit)==null?void 0:s.encode)!=null&&o.gradient&&Y1(e.implicit,["encode","gradient"]),(u=(a=e.explicit)==null?void 0:a.encode)!=null&&u.gradient&&Y1(e.explicit,["encode","gradient"])),e}function _be(e,t){return t.value==="circle"?t:e}function wbe(e,t,n,r){var i,s;e.encode??(e.encode={}),(i=e.encode)[t]??(i[t]={}),(s=e.encode[t]).update??(s.update={}),e.encode[t].update[n]=r}function gj(e){const t=e.component.legends,n={};for(const i of ie(t)){const s=e.getScaleComponent(i),o=At(s.get("domains"));if(n[o])for(const a of n[o])pj(a,t[i])||n[o].push(t[i]);else n[o]=[t[i].clone()]}return Yn(n).flat().map(i=>Ebe(i,e.config)).filter(i=>i!==void 0)}function Ebe(e,t){var o,a,u;const{disable:n,labelExpr:r,selections:i,...s}=e.combine();if(!n){if(t.aria===!1&&s.aria==null&&(s.aria=!1),(o=s.encode)!=null&&o.symbols){const l=s.encode.symbols.update;l.fill&&l.fill.value!=="transparent"&&!l.stroke&&!s.stroke&&(l.stroke={value:"transparent"});for(const c of QB)s[c]&&delete l[c]}if(s.title||delete s.title,r!==void 0){let l=r;(u=(a=s.encode)==null?void 0:a.labels)!=null&&u.update&&Ce(s.encode.labels.update.text)&&(l=nc(r,"datum.label",s.encode.labels.update.text.signal)),wbe(s,"labels","text",{signal:l})}return s}}function Abe(e){return Wd(e)||t$(e)?Sbe(e):mj(e)}function Sbe(e){return e.children.reduce((t,n)=>t.concat(n.assembleProjections()),mj(e))}function mj(e){const t=e.component.projection;if(!t||t.merged)return[];const n=t.combine(),{name:r}=n;if(t.data){const i={signal:`[${t.size.map(o=>o.signal).join(", ")}]`},s=t.data.reduce((o,a)=>{const u=Ce(a)?a.signal:`data('${e.lookupDataSource(a)}')`;return Qe(o,u)||o.push(u),o},[]);if(s.length<=0)throw new Error("Projection's fit didn't find any data sources");return[{name:r,size:i,fit:{signal:s.length>1?`[${s.join(", ")}]`:s[0]},...n}]}else return[{name:r,translate:{signal:"[width / 2, height / 2]"},...n}]}const kbe=["type","clipAngle","clipExtent","center","rotate","precision","reflectX","reflectY","coefficient","distance","fraction","lobes","parallel","radius","ratio","spacing","tilt"];class yj extends Fa{constructor(t,n,r,i){super({...n},{name:t}),this.specifiedProjection=n,this.size=r,this.data=i,this.merged=!1}get isFit(){return!!this.data}}function vj(e){e.component.projection=Gt(e)?Cbe(e):Dbe(e)}function Cbe(e){if(e.hasProjection){const t=zn(e.specifiedProjection),n=!(t&&(t.scale!=null||t.translate!=null)),r=n?[e.getSizeSignalRef("width"),e.getSizeSignalRef("height")]:void 0,i=n?$be(e):void 0,s=new yj(e.projectionName(!0),{...zn(e.config.projection),...t},r,i);return s.get("type")||s.set("type","equalEarth",!1),s}}function $be(e){const t=[],{encoding:n}=e;for(const r of[[Is,Ls],[Yi,Ps]])(yn(n[r[0]])||yn(n[r[1]]))&&t.push({signal:e.getName(`geojson_${t.length}`)});return e.channelHasField(Zr)&&e.typedFieldDef(Zr).type===Bd&&t.push({signal:e.getName(`geojson_${t.length}`)}),t.length===0&&t.push(e.requestDataName(Vt.Main)),t}function Fbe(e,t){const n=IC(kbe,i=>!!(!be(e.explicit,i)&&!be(t.explicit,i)||be(e.explicit,i)&&be(t.explicit,i)&&fi(e.get(i),t.get(i))));if(fi(e.size,t.size)){if(n)return e;if(fi(e.explicit,{}))return t;if(fi(t.explicit,{}))return e}return null}function Dbe(e){if(e.children.length===0)return;let t;for(const r of e.children)vj(r);const n=IC(e.children,r=>{const i=r.component.projection;if(i)if(t){const s=Fbe(t,i);return s&&(t=s),!!s}else return t=i,!0;else return!0});if(t&&n){const r=e.projectionName(!0),i=new yj(r,t.specifiedProjection,t.size,Be(t.data));for(const s of e.children){const o=s.component.projection;o&&(o.isFit&&i.data.push(...s.component.projection.data),s.renameProjection(o.get("name"),r),o.merged=!0)}return i}}function Mbe(e,t,n,r){if(Wg(t,n)){const i=Gt(e)?e.axis(n)??e.legend(n)??{}:{},s=pe(t,{expr:"datum"}),o=pe(t,{expr:"datum",binSuffix:"end"});return{formulaAs:pe(t,{binSuffix:"range",forAs:!0}),formula:zg(s,o,i.format,i.formatType,r)}}return{}}function bj(e,t){return`${FP(e)}_${t}`}function Rbe(e,t){return{signal:e.getName(`${t}_bins`),extentSignal:e.getName(`${t}_extent`)}}function K3(e,t,n){const r=eb(n,void 0)??{},i=bj(r,t);return e.getName(`${i}_bins`)}function Tbe(e){return"as"in e}function T4(e,t,n){let r,i;Tbe(e)?r=me(e.as)?[e.as,`${e.as}_end`]:[e.as[0],e.as[1]]:r=[pe(e,{forAs:!0}),pe(e,{binSuffix:"end",forAs:!0})];const s={...eb(t,void 0)},o=bj(s,e.field),{signal:a,extentSignal:u}=Rbe(n,o);if(qv(s.extent)){const c=s.extent;i=Zz(n,c.param,c),delete s.extent}const l={bin:s,field:e.field,as:[r],...a?{signal:a}:{},...u?{extentSignal:u}:{},...i?{span:i}:{}};return{key:o,binComponent:l}}class po extends _t{clone(){return new po(null,Be(this.bins))}constructor(t,n){super(t),this.bins=n}static makeFromEncoding(t,n){const r=n.reduceFieldDef((i,s,o)=>{if(Dr(s)&&Mt(s.bin)){const{key:a,binComponent:u}=T4(s,s.bin,n);i[a]={...u,...i[a],...Mbe(n,s,o,n.config)}}return i},{});return Et(r)?null:new po(t,r)}static makeFromTransform(t,n,r){const{key:i,binComponent:s}=T4(n,n.bin,r);return new po(t,{[i]:s})}merge(t,n){for(const r of ie(t.bins))r in this.bins?(n(t.bins[r].signal,this.bins[r].signal),this.bins[r].as=oo([...this.bins[r].as,...t.bins[r].as],rt)):this.bins[r]=t.bins[r];for(const r of t.children)t.removeChild(r),r.parent=this;t.remove()}producedFields(){return new Set(Yn(this.bins).map(t=>t.as).flat(2))}dependentFields(){return new Set(Yn(this.bins).map(t=>t.field))}hash(){return`Bin ${rt(this.bins)}`}assemble(){return Yn(this.bins).flatMap(t=>{const n=[],[r,...i]=t.as,{extent:s,...o}=t.bin,a={type:"bin",field:Gi(t.field),as:r,signal:t.signal,...qv(s)?{extent:null}:{extent:s},...t.span?{span:{signal:`span(${t.span})`}}:{},...o};!s&&t.extentSignal&&(n.push({type:"extent",field:Gi(t.field),signal:t.extentSignal}),a.extent={signal:t.extentSignal}),n.push(a);for(const u of i)for(let l=0;l<2;l++)n.push({type:"formula",expr:pe({field:r[l]},{expr:"datum"}),as:u[l]});return t.formula&&n.push({type:"formula",expr:t.formula,as:t.formulaAs}),n})}}function Nbe(e,t,n,r){var s;const i=Gt(r)?r.encoding[Lo(t)]:void 0;if(Dr(n)&&Gt(r)&&EB(n,i,r.markDef,r.config)){e.add(pe(n,{})),e.add(pe(n,{suffix:"end"}));const{mark:o,markDef:a,config:u}=r,l=Eu({fieldDef:n,markDef:a,config:u});Ip(o)&&l!==.5&&ln(t)&&(e.add(pe(n,{suffix:ab})),e.add(pe(n,{suffix:ub}))),n.bin&&Wg(n,t)&&e.add(pe(n,{binSuffix:"range"}))}else if(xP(t)){const o=bP(t);e.add(r.getName(o))}else e.add(pe(n));return Fc(n)&&d0e((s=n.scale)==null?void 0:s.range)&&e.add(n.scale.range.field),e}function Obe(e,t){for(const n of ie(t)){const r=t[n];for(const i of ie(r))n in e?e[n][i]=new Set([...e[n][i]??[],...r[i]]):e[n]={[i]:r[i]}}}class _s extends _t{clone(){return new _s(null,new Set(this.dimensions),Be(this.measures))}constructor(t,n,r){super(t),this.dimensions=n,this.measures=r}get groupBy(){return this.dimensions}static makeFromEncoding(t,n){let r=!1;n.forEachFieldDef(o=>{o.aggregate&&(r=!0)});const i={},s=new Set;return!r||(n.forEachFieldDef((o,a)=>{const{aggregate:u,field:l}=o;if(u)if(u==="count")i["*"]??(i["*"]={}),i["*"].count=new Set([pe(o,{forAs:!0})]);else{if(va(u)||Wu(u)){const c=va(u)?"argmin":"argmax",f=u[c];i[f]??(i[f]={}),i[f][c]=new Set([pe({op:c,field:f},{forAs:!0})])}else i[l]??(i[l]={}),i[l][u]=new Set([pe(o,{forAs:!0})]);Io(a)&&n.scaleDomain(a)==="unaggregated"&&(i[l]??(i[l]={}),i[l].min=new Set([pe({field:l,aggregate:"min"},{forAs:!0})]),i[l].max=new Set([pe({field:l,aggregate:"max"},{forAs:!0})]))}else Nbe(s,a,o,n)}),s.size+ie(i).length===0)?null:new _s(t,s,i)}static makeFromTransform(t,n){var r;const i=new Set,s={};for(const o of n.aggregate){const{op:a,field:u,as:l}=o;a&&(a==="count"?(s["*"]??(s["*"]={}),s["*"].count=new Set([l||pe(o,{forAs:!0})])):(s[u]??(s[u]={}),(r=s[u])[a]??(r[a]=new Set),s[u][a].add(l||pe(o,{forAs:!0}))))}for(const o of n.groupby??[])i.add(o);return i.size+ie(s).length===0?null:new _s(t,i,s)}merge(t){return fP(this.dimensions,t.dimensions)?(Obe(this.measures,t.measures),!0):(Ige("different dimensions, cannot merge"),!1)}addDimensions(t){t.forEach(this.dimensions.add,this.dimensions)}dependentFields(){return new Set([...this.dimensions,...ie(this.measures)])}producedFields(){const t=new Set;for(const n of ie(this.measures))for(const r of ie(this.measures[n])){const i=this.measures[n][r];i.size===0?t.add(`${r}_${n}`):i.forEach(t.add,t)}return t}hash(){return`Aggregate ${rt({dimensions:this.dimensions,measures:this.measures})}`}assemble(){const t=[],n=[],r=[];for(const s of ie(this.measures))for(const o of ie(this.measures[s]))for(const a of this.measures[s][o])r.push(a),t.push(o),n.push(s==="*"?null:Gi(s));return{type:"aggregate",groupby:[...this.dimensions].map(Gi),ops:t,fields:n,as:r}}}class Ud extends _t{constructor(t,n,r,i){super(t),this.model=n,this.name=r,this.data=i;for(const s of Oi){const o=n.facet[s];if(o){const{bin:a,sort:u}=o;this[s]={name:n.getName(`${s}_domain`),fields:[pe(o),...Mt(a)?[pe(o,{binSuffix:"end"})]:[]],...fa(u)?{sortField:u}:ee(u)?{sortIndexField:hd(o,s)}:{}}}}this.childModel=n.child}hash(){let t="Facet";for(const n of Oi)this[n]&&(t+=` ${n.charAt(0)}:${rt(this[n])}`);return t}get fields(){var n;const t=[];for(const r of Oi)(n=this[r])!=null&&n.fields&&t.push(...this[r].fields);return t}dependentFields(){const t=new Set(this.fields);for(const n of Oi)this[n]&&(this[n].sortField&&t.add(this[n].sortField.field),this[n].sortIndexField&&t.add(this[n].sortIndexField));return t}producedFields(){return new Set}getSource(){return this.name}getChildIndependentFieldsWithStep(){const t={};for(const n of Ca){const r=this.childModel.component.scales[n];if(r&&!r.merged){const i=r.get("type"),s=r.get("range");if(Tn(i)&&kc(s)){const o=yb(this.childModel,n),a=e$(o);a?t[n]=a:ae(ZC(n))}}}return t}assembleRowColumnHeaderData(t,n,r){const i={row:"y",column:"x",facet:void 0}[t],s=[],o=[],a=[];i&&r&&r[i]&&(n?(s.push(`distinct_${r[i]}`),o.push("max")):(s.push(r[i]),o.push("distinct")),a.push(`distinct_${r[i]}`));const{sortField:u,sortIndexField:l}=this[t];if(u){const{op:c=Zv,field:f}=u;s.push(f),o.push(c),a.push(pe(u,{forAs:!0}))}else l&&(s.push(l),o.push("max"),a.push(l));return{name:this[t].name,source:n??this.data,transform:[{type:"aggregate",groupby:this[t].fields,...s.length?{fields:s,ops:o,as:a}:{}}]}}assembleFacetHeaderData(t){var u;const{columns:n}=this.model.layout,{layoutHeaders:r}=this.model.component,i=[],s={};for(const l of G3){for(const c of Y3){const f=(r[l]&&r[l][c])??[];for(const d of f)if(((u=d.axes)==null?void 0:u.length)>0){s[l]=!0;break}}if(s[l]){const c=`length(data("${this.facet.name}"))`,f=l==="row"?n?{signal:`ceil(${c} / ${n})`}:1:n?{signal:`min(${c}, ${n})`}:{signal:c};i.push({name:`${this.facet.name}_${l}`,transform:[{type:"sequence",start:0,stop:f}]})}}const{row:o,column:a}=s;return(o||a)&&i.unshift(this.assembleRowColumnHeaderData("facet",null,t)),i}assemble(){const t=[];let n=null;const r=this.getChildIndependentFieldsWithStep(),{column:i,row:s,facet:o}=this;if(i&&s&&(r.x||r.y)){n=`cross_${this.column.name}_${this.row.name}`;const a=[].concat(r.x??[],r.y??[]),u=a.map(()=>"distinct");t.push({name:n,source:this.data,transform:[{type:"aggregate",groupby:this.fields,fields:a,ops:u}]})}for(const a of[ca,la])this[a]&&t.push(this.assembleRowColumnHeaderData(a,n,r));if(o){const a=this.assembleFacetHeaderData(r);a&&t.push(...a)}return t}}function N4(e){return e.startsWith("'")&&e.endsWith("'")||e.startsWith('"')&&e.endsWith('"')?e.slice(1,-1):e}function Lbe(e,t){const n=zC(e);if(t==="number")return`toNumber(${n})`;if(t==="boolean")return`toBoolean(${n})`;if(t==="string")return`toString(${n})`;if(t==="date")return`toDate(${n})`;if(t==="flatten")return n;if(t.startsWith("date:")){const r=N4(t.slice(5,t.length));return`timeParse(${n},'${r}')`}else if(t.startsWith("utc:")){const r=N4(t.slice(4,t.length));return`utcParse(${n},'${r}')`}else return ae(Gpe(t)),null}function Ibe(e){const t={};return wm(e.filter,n=>{if(eB(n)){let r=null;r3(n)?r=li(n.equal):s3(n)?r=li(n.lte):i3(n)?r=li(n.lt):o3(n)?r=li(n.gt):a3(n)?r=li(n.gte):u3(n)?r=n.range[0]:l3(n)&&(r=(n.oneOf??n.in)[0]),r&&(Cc(r)?t[n.field]="date":ft(r)?t[n.field]="number":me(r)&&(t[n.field]="string")),n.timeUnit&&(t[n.field]="date")}}),t}function Pbe(e){const t={};function n(r){ld(r)?t[r.field]="date":r.type==="quantitative"&&xpe(r.aggregate)?t[r.field]="number":rd(r.field)>1?r.field in t||(t[r.field]="flatten"):Fc(r)&&fa(r.sort)&&rd(r.sort.field)>1&&(r.sort.field in t||(t[r.sort.field]="flatten"))}if((Gt(e)||mi(e))&&e.forEachFieldDef((r,i)=>{if(Dr(r))n(r);else{const s=Ac(i),o=e.fieldDef(s);n({...r,type:o.type})}}),Gt(e)){const{mark:r,markDef:i,encoding:s}=e;if(Hu(r)&&!e.encoding.order){const o=i.orient==="horizontal"?"y":"x",a=s[o];ue(a)&&a.type==="quantitative"&&!(a.field in t)&&(t[a.field]="number")}}return t}function Bbe(e){const t={};if(Gt(e)&&e.component.selection)for(const n of ie(e.component.selection)){const r=e.component.selection[n];for(const i of r.project.items)!i.channel&&rd(i.field)>1&&(t[i.field]="flatten")}return t}class or extends _t{clone(){return new or(null,Be(this._parse))}constructor(t,n){super(t),this._parse=n}hash(){return`Parse ${rt(this._parse)}`}static makeExplicit(t,n,r){var o;let i={};const s=n.data;return!lu(s)&&((o=s==null?void 0:s.format)!=null&&o.parse)&&(i=s.format.parse),this.makeWithAncestors(t,i,{},r)}static makeWithAncestors(t,n,r,i){for(const a of ie(r)){const u=i.getWithExplicit(a);u.value!==void 0&&(u.explicit||u.value===r[a]||u.value==="derived"||r[a]==="flatten"?delete r[a]:ae(IM(a,r[a],u.value)))}for(const a of ie(n)){const u=i.get(a);u!==void 0&&(u===n[a]?delete n[a]:ae(IM(a,n[a],u)))}const s=new Fa(n,r);i.copyAll(s);const o={};for(const a of ie(s.combine())){const u=s.get(a);u!==null&&(o[a]=u)}return ie(o).length===0||i.parseNothing?null:new or(t,o)}get parse(){return this._parse}merge(t){this._parse={...this._parse,...t.parse},t.remove()}assembleFormatParse(){const t={};for(const n of ie(this._parse)){const r=this._parse[n];rd(n)===1&&(t[n]=r)}return t}producedFields(){return new Set(ie(this._parse))}dependentFields(){return new Set(ie(this._parse))}assembleTransforms(t=!1){return ie(this._parse).filter(n=>t?rd(n)>1:!0).map(n=>{const r=Lbe(n,this._parse[n]);return r?{type:"formula",expr:r,as:Id(n)}:null}).filter(n=>n!==null)}}class Su extends _t{clone(){return new Su(null)}constructor(t){super(t)}dependentFields(){return new Set}producedFields(){return new Set([Ds])}hash(){return"Identifier"}assemble(){return{type:"identifier",as:Ds}}}class Kg extends _t{clone(){return new Kg(null,this.params)}constructor(t,n){super(t),this.params=n}dependentFields(){return new Set}producedFields(){}hash(){return`Graticule ${rt(this.params)}`}assemble(){return{type:"graticule",...this.params===!0?{}:this.params}}}class Zg extends _t{clone(){return new Zg(null,this.params)}constructor(t,n){super(t),this.params=n}dependentFields(){return new Set}producedFields(){return new Set([this.params.as??"data"])}hash(){return`Hash ${rt(this.params)}`}assemble(){return{type:"sequence",...this.params}}}class hc extends _t{constructor(t){super(null),t??(t={name:"source"});let n;if(lu(t)||(n=t.format?{...Hr(t.format,["parse"])}:{}),Pp(t))this._data={values:t.values};else if(cd(t)){if(this._data={url:t.url},!n.type){let r=/(?:\.([^.]+))?$/.exec(t.url)[1];Qe(["json","csv","tsv","dsv","topojson"],r)||(r="json"),n.type=r}}else yz(t)?this._data={values:[{type:"Sphere"}]}:(gz(t)||lu(t))&&(this._data={});this._generator=lu(t),t.name&&(this._name=t.name),n&&!Et(n)&&(this._data.format=n)}dependentFields(){return new Set}producedFields(){}get data(){return this._data}hasName(){return!!this._name}get isGenerator(){return this._generator}get dataName(){return this._name}set dataName(t){this._name=t}set parent(t){throw new Error("Source nodes have to be roots.")}remove(){throw new Error("Source nodes are roots and cannot be removed.")}hash(){throw new Error("Cannot hash sources")}assemble(){return{name:this._name,...this._data,transform:[]}}}var O4=function(e,t,n,r,i){if(r==="m")throw new TypeError("Private method is not writable");if(r==="a"&&!i)throw new TypeError("Private accessor was defined without a setter");if(typeof t=="function"?e!==t||!i:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return r==="a"?i.call(e,n):i?i.value=n:t.set(e,n),n},zbe=function(e,t,n,r){if(n==="a"&&!r)throw new TypeError("Private accessor was defined without a getter");if(typeof t=="function"?e!==t||!r:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return n==="m"?r:n==="a"?r.call(e):r?r.value:t.get(e)},qh;function Z3(e){return e instanceof hc||e instanceof Kg||e instanceof Zg}class J3{constructor(){qh.set(this,void 0),O4(this,qh,!1,"f")}setModified(){O4(this,qh,!0,"f")}get modifiedFlag(){return zbe(this,qh,"f")}}qh=new WeakMap;class Mc extends J3{getNodeDepths(t,n,r){r.set(t,n);for(const i of t.children)this.getNodeDepths(i,n+1,r);return r}optimize(t){const r=[...this.getNodeDepths(t,0,new Map).entries()].sort((i,s)=>s[1]-i[1]);for(const i of r)this.run(i[0]);return this.modifiedFlag}}class Q3 extends J3{optimize(t){this.run(t);for(const n of t.children)this.optimize(n);return this.modifiedFlag}}class jbe extends Q3{mergeNodes(t,n){const r=n.shift();for(const i of n)t.removeChild(i),i.parent=r,i.remove()}run(t){const n=t.children.map(i=>i.hash()),r={};for(let i=0;i1&&(this.setModified(),this.mergeNodes(t,r[i]))}}class Ube extends Q3{constructor(t){super(),this.requiresSelectionId=t&&U3(t)}run(t){t instanceof Su&&(this.requiresSelectionId&&(Z3(t.parent)||t.parent instanceof _s||t.parent instanceof or)||(this.setModified(),t.remove()))}}class qbe extends J3{optimize(t){return this.run(t,new Set),this.modifiedFlag}run(t,n){let r=new Set;t instanceof fo&&(r=t.producedFields(),PC(r,n)&&(this.setModified(),t.removeFormulas(n),t.producedFields.length===0&&t.remove()));for(const i of t.children)this.run(i,new Set([...n,...r]))}}class Wbe extends Q3{constructor(){super()}run(t){t instanceof Gr&&!t.isRequired()&&(this.setModified(),t.remove())}}class Hbe extends Mc{run(t){if(!Z3(t)&&!(t.numChildren()>1)){for(const n of t.children)if(n instanceof or)if(t instanceof or)this.setModified(),t.merge(n);else{if(BC(t.producedFields(),n.dependentFields()))continue;this.setModified(),n.swapWithParent()}}}}class Gbe extends Mc{run(t){const n=[...t.children],r=t.children.filter(i=>i instanceof or);if(t.numChildren()>1&&r.length>=1){const i={},s=new Set;for(const o of r){const a=o.parse;for(const u of ie(a))u in i?i[u]!==a[u]&&s.add(u):i[u]=a[u]}for(const o of s)delete i[o];if(!Et(i)){this.setModified();const o=new or(t,i);for(const a of n){if(a instanceof or)for(const u of ie(i))delete a.parse[u];t.removeChild(a),a.parent=o,a instanceof or&&ie(a.parse).length===0&&a.remove()}}}}}class Ybe extends Mc{run(t){t instanceof Gr||t.numChildren()>0||t instanceof Ud||t instanceof hc||(this.setModified(),t.remove())}}class Vbe extends Mc{run(t){const n=t.children.filter(i=>i instanceof fo),r=n.pop();for(const i of n)this.setModified(),r.merge(i)}}class Xbe extends Mc{run(t){const n=t.children.filter(i=>i instanceof _s),r={};for(const i of n){const s=rt(i.groupBy);s in r||(r[s]=[]),r[s].push(i)}for(const i of ie(r)){const s=r[i];if(s.length>1){const o=s.pop();for(const a of s)o.merge(a)&&(t.removeChild(a),a.parent=o,a.remove(),this.setModified())}}}}class Kbe extends Mc{constructor(t){super(),this.model=t}run(t){const n=!(Z3(t)||t instanceof jd||t instanceof or||t instanceof Su),r=[],i=[];for(const s of t.children)s instanceof po&&(n&&!BC(t.producedFields(),s.dependentFields())?r.push(s):i.push(s));if(r.length>0){const s=r.pop();for(const o of r)s.merge(o,this.model.renameSignal.bind(this.model));this.setModified(),t instanceof po?t.merge(s,this.model.renameSignal.bind(this.model)):s.swapWithParent()}if(i.length>1){const s=i.pop();for(const o of i)s.merge(o,this.model.renameSignal.bind(this.model));this.setModified()}}}class Zbe extends Mc{run(t){const n=[...t.children];if(!nd(n,o=>o instanceof Gr)||t.numChildren()<=1)return;const i=[];let s;for(const o of n)if(o instanceof Gr){let a=o;for(;a.numChildren()===1;){const[u]=a.children;if(u instanceof Gr)a=u;else break}i.push(...a.children),s?(t.removeChild(o),o.parent=s.parent,s.parent.removeChild(s),s.parent=a,this.setModified()):s=a}else i.push(o);if(i.length){this.setModified();for(const o of i)o.parent.removeChild(o),o.parent=s}}}class Rc extends _t{clone(){return new Rc(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n}addDimensions(t){this.transform.groupby=oo(this.transform.groupby.concat(t),n=>n)}dependentFields(){const t=new Set;return this.transform.groupby&&this.transform.groupby.forEach(t.add,t),this.transform.joinaggregate.map(n=>n.field).filter(n=>n!==void 0).forEach(t.add,t),t}producedFields(){return new Set(this.transform.joinaggregate.map(this.getDefaultName))}getDefaultName(t){return t.as??pe(t)}hash(){return`JoinAggregateTransform ${rt(this.transform)}`}assemble(){const t=[],n=[],r=[];for(const s of this.transform.joinaggregate)n.push(s.op),r.push(this.getDefaultName(s)),t.push(s.field===void 0?null:s.field);const i=this.transform.groupby;return{type:"joinaggregate",as:r,ops:n,fields:t,...i!==void 0?{groupby:i}:{}}}}class gd extends _t{clone(){return new gd(null,{...this.filter})}constructor(t,n){super(t),this.filter=n}static make(t,n,r){const{config:i,markDef:s}=n,{marks:o,scales:a}=r;if(o==="include-invalid-values"&&a==="include-invalid-values")return null;const u=n.reduceFieldDef((l,c,f)=>{const d=Io(f)&&n.getScaleComponent(f);if(d){const h=d.get("type"),{aggregate:p}=c,g=m3({scaleChannel:f,markDef:s,config:i,scaleType:h,isCountAggregate:Uv(p)});g!=="show"&&g!=="always-valid"&&(l[c.field]=c)}return l},{});return ie(u).length?new gd(t,u):null}dependentFields(){return new Set(ie(this.filter))}producedFields(){return new Set}hash(){return`FilterInvalid ${rt(this.filter)}`}assemble(){const t=ie(this.filter).reduce((n,r)=>{const i=this.filter[r],s=pe(i,{expr:"datum"});return i!==null&&(i.type==="temporal"?n.push(`(isDate(${s}) || (${fE(s)}))`):i.type==="quantitative"&&n.push(fE(s))),n},[]);return t.length>0?{type:"filter",expr:t.join(" && ")}:null}}function fE(e){return`isValid(${e}) && isFinite(+${e})`}function Jbe(e){return e.stack.stackBy.reduce((t,n)=>{const r=n.fieldDef,i=pe(r);return i&&t.push(i),t},[])}function Qbe(e){return ee(e)&&e.every(t=>me(t))&&e.length>1}class ha extends _t{clone(){return new ha(null,Be(this._stack))}constructor(t,n){super(t),this._stack=n}static makeFromTransform(t,n){const{stack:r,groupby:i,as:s,offset:o="zero"}=n,a=[],u=[];if(n.sort!==void 0)for(const f of n.sort)a.push(f.field),u.push(un(f.order,"ascending"));const l={field:a,order:u};let c;return Qbe(s)?c=s:me(s)?c=[s,`${s}_end`]:c=[`${n.stack}_start`,`${n.stack}_end`],new ha(t,{dimensionFieldDefs:[],stackField:r,groupby:i,offset:o,sort:l,facetby:[],as:c})}static makeFromEncoding(t,n){const r=n.stack,{encoding:i}=n;if(!r)return null;const{groupbyChannels:s,fieldChannel:o,offset:a,impute:u}=r,l=s.map(h=>{const p=i[h];return Fs(p)}).filter(h=>!!h),c=Jbe(n),f=n.encoding.order;let d;if(ee(f)||ue(f))d=NP(f);else{const h=AB(f)?f.sort:o==="y"?"descending":"ascending";d=c.reduce((p,g)=>(p.field.includes(g)||(p.field.push(g),p.order.push(h)),p),{field:[],order:[]})}return new ha(t,{dimensionFieldDefs:l,stackField:n.vgField(o),facetby:[],stackby:c,sort:d,offset:a,impute:u,as:[n.vgField(o,{suffix:"start",forAs:!0}),n.vgField(o,{suffix:"end",forAs:!0})]})}get stack(){return this._stack}addDimensions(t){this._stack.facetby.push(...t)}dependentFields(){const t=new Set;return t.add(this._stack.stackField),this.getGroupbyFields().forEach(t.add,t),this._stack.facetby.forEach(t.add,t),this._stack.sort.field.forEach(t.add,t),t}producedFields(){return new Set(this._stack.as)}hash(){return`Stack ${rt(this._stack)}`}getGroupbyFields(){const{dimensionFieldDefs:t,impute:n,groupby:r}=this._stack;return t.length>0?t.map(i=>i.bin?n?[pe(i,{binSuffix:"mid"})]:[pe(i,{}),pe(i,{binSuffix:"end"})]:[pe(i)]).flat():r??[]}assemble(){const t=[],{facetby:n,dimensionFieldDefs:r,stackField:i,stackby:s,sort:o,offset:a,impute:u,as:l}=this._stack;if(u)for(const c of r){const{bandPosition:f=.5,bin:d}=c;if(d){const h=pe(c,{expr:"datum"}),p=pe(c,{expr:"datum",binSuffix:"end"});t.push({type:"formula",expr:`${fE(h)} ? ${f}*${h}+${1-f}*${p} : ${h}`,as:pe(c,{binSuffix:"mid",forAs:!0})})}t.push({type:"impute",field:i,groupby:[...s,...n],key:pe(c,{binSuffix:"mid"}),method:"value",value:0})}return t.push({type:"stack",groupby:[...this.getGroupbyFields(),...n],field:i,sort:o,as:l,offset:a}),t}}class qd extends _t{clone(){return new qd(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n}addDimensions(t){this.transform.groupby=oo(this.transform.groupby.concat(t),n=>n)}dependentFields(){const t=new Set;return(this.transform.groupby??[]).forEach(t.add,t),(this.transform.sort??[]).forEach(n=>t.add(n.field)),this.transform.window.map(n=>n.field).filter(n=>n!==void 0).forEach(t.add,t),t}producedFields(){return new Set(this.transform.window.map(this.getDefaultName))}getDefaultName(t){return t.as??pe(t)}hash(){return`WindowTransform ${rt(this.transform)}`}assemble(){const t=[],n=[],r=[],i=[];for(const f of this.transform.window)n.push(f.op),r.push(this.getDefaultName(f)),i.push(f.param===void 0?null:f.param),t.push(f.field===void 0?null:f.field);const s=this.transform.frame,o=this.transform.groupby;if(s&&s[0]===null&&s[1]===null&&n.every(f=>XC(f)))return{type:"joinaggregate",as:r,ops:n,fields:t,...o!==void 0?{groupby:o}:{}};const a=[],u=[];if(this.transform.sort!==void 0)for(const f of this.transform.sort)a.push(f.field),u.push(f.order??"ascending");const l={field:a,order:u},c=this.transform.ignorePeers;return{type:"window",params:i,as:r,ops:n,fields:t,sort:l,...c!==void 0?{ignorePeers:c}:{},...o!==void 0?{groupby:o}:{},...s!==void 0?{frame:s}:{}}}}function e2e(e){function t(n){if(!(n instanceof Ud)){const r=n.clone();if(r instanceof Gr){const i=hE+r.getSource();r.setSource(i),e.model.component.data.outputNodes[i]=r}else(r instanceof _s||r instanceof ha||r instanceof qd||r instanceof Rc)&&r.addDimensions(e.fields);for(const i of n.children.flatMap(t))i.parent=r;return[r]}return n.children.flatMap(t)}return t}function dE(e){if(e instanceof Ud)if(e.numChildren()===1&&!(e.children[0]instanceof Gr)){const t=e.children[0];(t instanceof _s||t instanceof ha||t instanceof qd||t instanceof Rc)&&t.addDimensions(e.fields),t.swapWithParent(),dE(e)}else{const t=e.model.component.data.main;xj(t);const n=e2e(e),r=e.children.map(n).flat();for(const i of r)i.parent=t}else e.children.map(dE)}function xj(e){if(e instanceof Gr&&e.type===Vt.Main&&e.numChildren()===1){const t=e.children[0];t instanceof Ud||(t.swapWithParent(),xj(e))}}const hE="scale_",T0=5;function pE(e){for(const t of e){for(const n of t.children)if(n.parent!==t)return!1;if(!pE(t.children))return!1}return!0}function es(e,t){let n=!1;for(const r of t)n=e.optimize(r)||n;return n}function L4(e,t,n){let r=e.sources,i=!1;return i=es(new Wbe,r)||i,i=es(new Ube(t),r)||i,r=r.filter(s=>s.numChildren()>0),i=es(new Ybe,r)||i,r=r.filter(s=>s.numChildren()>0),n||(i=es(new Hbe,r)||i,i=es(new Kbe(t),r)||i,i=es(new qbe,r)||i,i=es(new Gbe,r)||i,i=es(new Xbe,r)||i,i=es(new Vbe,r)||i,i=es(new jbe,r)||i,i=es(new Zbe,r)||i),e.sources=r,i}function t2e(e,t){pE(e.sources);let n=0,r=0;for(let i=0;it(n))}}function _j(e){Gt(e)?n2e(e):r2e(e)}function n2e(e){const t=e.component.scales;for(const n of ie(t)){const r=s2e(e,n);if(t[n].setWithExplicit("domains",r),a2e(e,n),e.component.data.isFaceted){let s=e;for(;!mi(s)&&s.parent;)s=s.parent;if(s.component.resolve.scale[n]==="shared")for(const a of r.value)sa(a)&&(a.data=hE+a.data.replace(hE,""))}}}function r2e(e){for(const n of e.children)_j(n);const t=e.component.scales;for(const n of ie(t)){let r,i=null;for(const s of e.children){const o=s.component.scales[n];if(o){r===void 0?r=o.getWithExplicit("domains"):r=Au(r,o.getWithExplicit("domains"),"domains","scale",gE);const a=o.get("selectionExtent");i&&a&&i.param!==a.param&&ae(Bpe),i=a}}t[n].setWithExplicit("domains",r),i&&t[n].set("selectionExtent",i,!0)}}function i2e(e,t,n,r){if(e==="unaggregated"){const{valid:i,reason:s}=I4(t,n);if(!i){ae(s);return}}else if(e===void 0&&r.useUnaggregatedDomain){const{valid:i}=I4(t,n);if(i)return"unaggregated"}return e}function s2e(e,t){const n=e.getScaleComponent(t).get("type"),{encoding:r}=e,i=i2e(e.scaleDomain(t),e.typedFieldDef(t),n,e.config.scale);return i!==e.scaleDomain(t)&&(e.specifiedScales[t]={...e.specifiedScales[t],domain:i}),t==="x"&&yn(r.x2)?yn(r.x)?Au(Oa(n,i,e,"x"),Oa(n,i,e,"x2"),"domain","scale",gE):Oa(n,i,e,"x2"):t==="y"&&yn(r.y2)?yn(r.y)?Au(Oa(n,i,e,"y"),Oa(n,i,e,"y2"),"domain","scale",gE):Oa(n,i,e,"y2"):Oa(n,i,e,t)}function o2e(e,t,n){return e.map(r=>({signal:`{data: ${tb(r,{timeUnit:n,type:t})}}`}))}function dx(e,t,n){var i;const r=(i=Mn(n))==null?void 0:i.unit;return t==="temporal"||r?o2e(e,t,r):[e]}function Oa(e,t,n,r){const{encoding:i,markDef:s,mark:o,config:a,stack:u}=n,l=yn(i[r]),{type:c}=l,f=l.timeUnit,d=q1e({invalid:wo("invalid",s,a),isPath:Hu(o)});if(f0e(t)){const g=Oa(e,void 0,n,r),m=dx(t.unionWith,c,f);return Xs([...m,...g.value])}else{if(Ce(t))return Xs([t]);if(t&&t!=="unaggregated"&&!aB(t))return Xs(dx(t,c,f))}if(u&&r===u.fieldChannel){if(u.offset==="normalize")return ii([[0,1]]);const g=n.requestDataName(d);return ii([{data:g,field:n.vgField(r,{suffix:"start"})},{data:g,field:n.vgField(r,{suffix:"end"})}])}const h=Io(r)&&ue(l)?u2e(n,r,e):void 0;if(Po(l)){const g=dx([l.datum],c,f);return ii(g)}const p=l;if(t==="unaggregated"){const{field:g}=l;return ii([{data:n.requestDataName(d),field:pe({field:g,aggregate:"min"})},{data:n.requestDataName(d),field:pe({field:g,aggregate:"max"})}])}else if(Mt(p.bin)){if(Tn(e))return ii(e==="bin-ordinal"?[]:[{data:Op(h)?n.requestDataName(d):n.requestDataName(Vt.Raw),field:n.vgField(r,Wg(p,r)?{binSuffix:"range"}:{}),sort:h===!0||!ge(h)?{field:n.vgField(r,{}),op:"min"}:h}]);{const{bin:g}=p;if(Mt(g)){const m=K3(n,p.field,g);return ii([new En(()=>{const y=n.getSignalName(m);return`[${y}.start, ${y}.stop]`})])}else return ii([{data:n.requestDataName(d),field:n.vgField(r,{})}])}}else if(p.timeUnit&&Qe(["time","utc"],e)){const g=i[Lo(r)];if(EB(p,g,s,a)){const m=n.requestDataName(d),y=Eu({fieldDef:p,fieldDef2:g,markDef:s,config:a}),v=Ip(o)&&y!==.5&&ln(r);return ii([{data:m,field:n.vgField(r,v?{suffix:ab}:{})},{data:m,field:n.vgField(r,{suffix:v?ub:"end"})}])}}return ii(h?[{data:Op(h)?n.requestDataName(d):n.requestDataName(Vt.Raw),field:n.vgField(r),sort:h}]:[{data:n.requestDataName(d),field:n.vgField(r)}])}function hx(e,t){const{op:n,field:r,order:i}=e;return{op:n??(t?"sum":Zv),...r?{field:Gi(r)}:{},...i?{order:i}:{}}}function a2e(e,t){var a;const n=e.component.scales[t],r=e.specifiedScales[t].domain,i=(a=e.fieldDef(t))==null?void 0:a.bin,s=aB(r)?r:void 0,o=Sc(i)&&qv(i.extent)?i.extent:void 0;(s||o)&&n.set("selectionExtent",s??o,!0)}function u2e(e,t,n){if(!Tn(n))return;const r=e.fieldDef(t),i=r.sort;if(_B(i))return{op:"min",field:hd(r,t),order:"ascending"};const{stack:s}=e,o=s?new Set([...s.groupbyFields,...s.stackBy.map(a=>a.fieldDef.field)]):void 0;if(fa(i)){const a=s&&!o.has(i.field);return hx(i,a)}else if(q0e(i)){const{encoding:a,order:u}=i,l=e.fieldDef(a),{aggregate:c,field:f}=l,d=s&&!o.has(f);if(va(c)||Wu(c))return hx({field:pe(l),order:u},d);if(XC(c)||!c)return hx({op:c,field:f,order:u},d)}else{if(i==="descending")return{op:"min",field:e.vgField(t),order:"descending"};if(Qe(["ascending",void 0],i))return!0}}function I4(e,t){const{aggregate:n,type:r}=e;return n?me(n)&&!wpe.has(n)?{valid:!1,reason:pge(n)}:r==="quantitative"&&t==="log"?{valid:!1,reason:gge(e)}:{valid:!0}:{valid:!1,reason:hge(e)}}function gE(e,t,n,r){return e.explicit&&t.explicit&&ae(xge(n,r,e.value,t.value)),{explicit:e.explicit,value:[...e.value,...t.value]}}function l2e(e){const t=oo(e.map(o=>{if(sa(o)){const{sort:a,...u}=o;return u}return o}),rt),n=oo(e.map(o=>{if(sa(o)){const a=o.sort;return a!==void 0&&!Op(a)&&("op"in a&&a.op==="count"&&delete a.field,a.order==="ascending"&&delete a.order),a}}).filter(o=>o!==void 0),rt);if(t.length===0)return;if(t.length===1){const o=e[0];if(sa(o)&&n.length>0){let a=n[0];if(n.length>1){ae(BM);const u=n.filter(l=>ge(l)&&"op"in l&&l.op!=="min");n.every(l=>ge(l)&&"op"in l)&&u.length===1?a=u[0]:a=!0}else if(ge(a)&&"field"in a){const u=a.field;o.field===u&&(a=a.order?{order:a.order}:!0)}return{...o,sort:a}}return o}const r=oo(n.map(o=>Op(o)||!("op"in o)||me(o.op)&&be(vpe,o.op)?o:(ae(wge(o)),!0)),rt);let i;r.length===1?i=r[0]:r.length>1&&(ae(BM),i=!0);const s=oo(e.map(o=>sa(o)?o.data:null),o=>o);return s.length===1&&s[0]!==null?{data:s[0],fields:t.map(a=>a.field),...i?{sort:i}:{}}:{fields:t,...i?{sort:i}:{}}}function e$(e){if(sa(e)&&me(e.field))return e.field;if(Epe(e)){let t;for(const n of e.fields)if(sa(n)&&me(n.field)){if(!t)t=n.field;else if(t!==n.field)return ae(Ege),t}return ae(Age),t}else if(Ape(e)){ae(Sge);const t=e.fields[0];return me(t)?t:void 0}}function yb(e,t){const r=e.component.scales[t].get("domains").map(i=>(sa(i)&&(i.data=e.lookupDataSource(i.data)),i));return l2e(r)}function wj(e){return Wd(e)||t$(e)?e.children.reduce((t,n)=>t.concat(wj(n)),P4(e)):P4(e)}function P4(e){return ie(e.component.scales).reduce((t,n)=>{const r=e.component.scales[n];if(r.merged)return t;const i=r.combine(),{name:s,type:o,selectionExtent:a,domains:u,range:l,reverse:c,...f}=i,d=c2e(i.range,s,n,e),h=yb(e,n),p=a?eye(e,a,r,h):null;return t.push({name:s,type:o,...h?{domain:h}:{},...p?{domainRaw:p}:{},range:d,...c!==void 0?{reverse:c}:{},...f}),t},[])}function c2e(e,t,n,r){if(ln(n)){if(kc(e))return{step:{signal:`${t}_step`}}}else if(ge(e)&&sa(e))return{...e,data:r.lookupDataSource(e.data)};return e}class Ej extends Fa{constructor(t,n){super({},{name:t}),this.merged=!1,this.setWithExplicit("type",n)}domainHasZero(){const t=this.get("type");if(Qe([jn.LOG,jn.TIME,jn.UTC],t))return"definitely-not";const n=this.get("zero");if(n===!0||n===void 0&&Qe([jn.LINEAR,jn.SQRT,jn.POW],t))return"definitely";const r=this.get("domains");if(r.length>0){let i=!1,s=!1,o=!1;for(const a of r){if(ee(a)){const u=a[0],l=a[a.length-1];if(ft(u)&&ft(l))if(u<=0&&l>=0){i=!0;continue}else{s=!0;continue}}o=!0}if(i)return"definitely";if(s&&!o)return"definitely-not"}return"maybe"}}const f2e=["range","scheme"];function d2e(e){const t=e.component.scales;for(const n of VC){const r=t[n];if(!r)continue;const i=h2e(n,e);r.setWithExplicit("range",i)}}function B4(e,t){const n=e.fieldDef(t);if(n!=null&&n.bin){const{bin:r,field:i}=n,s=Jr(t),o=e.getName(s);if(ge(r)&&r.binned&&r.step!==void 0)return new En(()=>{const a=e.scaleName(t),u=`(domain("${a}")[1] - domain("${a}")[0]) / ${r.step}`;return`${e.getSignalName(o)} / (${u})`});if(Mt(r)){const a=K3(e,i,r);return new En(()=>{const u=e.getSignalName(a),l=`(${u}.stop - ${u}.start) / ${u}.step`;return`${e.getSignalName(o)} / (${l})`})}}}function h2e(e,t){const n=t.specifiedScales[e],{size:r}=t,s=t.getScaleComponent(e).get("type");for(const f of f2e)if(n[f]!==void 0){const d=Yw(s,f),h=uB(e,f);if(!d)ae(jP(s,f,e));else if(h)ae(h);else switch(f){case"range":{const p=n.range;if(ee(p)){if(ln(e))return Xs(p.map(g=>{if(g==="width"||g==="height"){const m=t.getName(g),y=t.getSignalName.bind(t);return En.fromName(y,m)}return g}))}else if(ge(p))return Xs({data:t.requestDataName(Vt.Main),field:p.field,sort:{op:"min",field:t.vgField(e)}});return Xs(p)}case"scheme":return Xs(p2e(n[f]))}}const o=e===qt||e==="xOffset"?"width":"height",a=r[o];if(Ao(a)){if(ln(e))if(Tn(s)){const f=Sj(a,t,e);if(f)return Xs({step:f})}else ae(UP(o));else if(Ig(e)){const f=e===Pu?"x":"y";if(t.getScaleComponent(f).get("type")==="band"){const p=kj(a,s);if(p)return Xs(p)}}}const{rangeMin:u,rangeMax:l}=n,c=g2e(e,t);return(u!==void 0||l!==void 0)&&Yw(s,"rangeMin")&&ee(c)&&c.length===2?Xs([u??c[0],l??c[1]]):ii(c)}function p2e(e){return c0e(e)?{scheme:e.name,...Hr(e,["name"])}:{scheme:e}}function Aj(e,t,n,{center:r}={}){const i=Jr(e),s=t.getName(i),o=t.getSignalName.bind(t);return e===On&&Cs(n)?r?[En.fromName(a=>`${o(a)}/2`,s),En.fromName(a=>`-${o(a)}/2`,s)]:[En.fromName(o,s),0]:r?[En.fromName(a=>`-${o(a)}/2`,s),En.fromName(a=>`${o(a)}/2`,s)]:[0,En.fromName(o,s)]}function g2e(e,t){const{size:n,config:r,mark:i,encoding:s}=t,{type:o}=yn(s[e]),u=t.getScaleComponent(e).get("type"),{domain:l,domainMid:c}=t.specifiedScales[e];switch(e){case qt:case On:{if(Qe(["point","band"],u)){const f=Cj(e,n,r.view);if(Ao(f))return{step:Sj(f,t,e)}}return Aj(e,t,u)}case Pu:case Pd:return m2e(e,t,u);case Sa:{const f=b2e(i,r),d=x2e(i,n,t,r);return od(u)?v2e(f,d,y2e(u,r,l,e)):[f,d]}case Xi:return[0,Math.PI*2];case Ec:return[0,360];case Os:return[0,new En(()=>{const f=t.getSignalName(mi(t.parent)?"child_width":"width"),d=t.getSignalName(mi(t.parent)?"child_height":"height");return`min(${f},${d})/2`})];case Bu:return{step:1e3/r.scale.framesPerSecond};case Uu:return[r.scale.minStrokeWidth,r.scale.maxStrokeWidth];case qu:return[[1,0],[4,2],[2,1],[1,1],[1,2,4,2]];case Zr:return"symbol";case Kr:case No:case Oo:return u==="ordinal"?o==="nominal"?"category":"ordinal":c!==void 0?"diverging":i==="rect"||i==="geoshape"?"heatmap":"ramp";case ka:case zu:case ju:return[r.scale.minOpacity,r.scale.maxOpacity]}}function Sj(e,t,n){const{encoding:r}=t,i=t.getScaleComponent(n),s=WC(n),o=r[s];if(tz({step:e,offsetIsDiscrete:Ue(o)&&nB(o.type)})==="offset"&&OB(r,s)){const u=t.getScaleComponent(s);let c=`domain('${t.scaleName(s)}').length`;if(u.get("type")==="band"){const d=u.get("paddingInner")??u.get("padding")??0,h=u.get("paddingOuter")??u.get("padding")??0;c=`bandspace(${c}, ${d}, ${h})`}const f=i.get("paddingInner")??i.get("padding");return{signal:`${e.step} * ${c} / (1-${$pe(f)})`}}else return e.step}function kj(e,t){if(tz({step:e,offsetIsDiscrete:Tn(t)})==="offset")return{step:e.step}}function m2e(e,t,n){const r=e===Pu?"x":"y",i=t.getScaleComponent(r);if(!i)return Aj(r,t,n,{center:!0});const s=i.get("type"),o=t.scaleName(r),{markDef:a,config:u}=t;if(s==="band"){const l=Cj(r,t.size,t.config.view);if(Ao(l)){const c=kj(l,n);if(c)return c}return[0,{signal:`bandwidth('${o}')`}]}else{const l=t.encoding[r];if(ue(l)&&l.timeUnit){const c=JP(l.timeUnit,p=>`scale('${o}', ${p})`),f=t.config.scale.bandWithNestedOffsetPaddingInner,d=Eu({fieldDef:l,markDef:a,config:u})-.5,h=d!==0?` + ${d}`:"";if(f){const p=Ce(f)?`${f.signal}/2`+h:`${f/2+d}`,g=Ce(f)?`(1 - ${f.signal}/2)`+h:`${1-f/2+d}`;return[{signal:`${p} * (${c})`},{signal:`${g} * (${c})`}]}return[0,{signal:c}]}return lP(`Cannot use ${e} scale if ${r} scale is not discrete.`)}}function Cj(e,t,n){const r=e===qt?"width":"height",i=t[r];return i||ny(n,r)}function y2e(e,t,n,r){switch(e){case"quantile":return t.scale.quantileCount;case"quantize":return t.scale.quantizeCount;case"threshold":return n!==void 0&&ee(n)?n.length+1:(ae(Nge(r)),3)}}function v2e(e,t,n){const r=()=>{const i=vs(t),s=vs(e),o=`(${i} - ${s}) / (${n} - 1)`;return`sequence(${s}, ${i} + ${o}, ${o})`};return Ce(t)?new En(r):{signal:r()}}function b2e(e,t){switch(e){case"bar":case"tick":return t.scale.minBandSize;case"line":case"trail":case"rule":return t.scale.minStrokeWidth;case"text":return t.scale.minFontSize;case"point":case"square":case"circle":return t.scale.minSize}throw new Error(Wv("size",e))}const z4=.95;function x2e(e,t,n,r){const i={x:B4(n,"x"),y:B4(n,"y")};switch(e){case"bar":case"tick":{if(r.scale.maxBandSize!==void 0)return r.scale.maxBandSize;const s=j4(t,i,r.view);return ft(s)?s-1:new En(()=>`${s.signal} - 1`)}case"line":case"trail":case"rule":return r.scale.maxStrokeWidth;case"text":return r.scale.maxFontSize;case"point":case"square":case"circle":{if(r.scale.maxSize)return r.scale.maxSize;const s=j4(t,i,r.view);return ft(s)?Math.pow(z4*s,2):new En(()=>`pow(${z4} * ${s.signal}, 2)`)}}throw new Error(Wv("size",e))}function j4(e,t,n){const r=Ao(e.width)?e.width.step:Zw(n,"width"),i=Ao(e.height)?e.height.step:Zw(n,"height");return t.x||t.y?new En(()=>`min(${[t.x?t.x.signal:r,t.y?t.y.signal:i].join(", ")})`):Math.min(r,i)}function $j(e,t){Gt(e)?_2e(e,t):Dj(e,t)}function _2e(e,t){const n=e.component.scales,{config:r,encoding:i,markDef:s,specifiedScales:o}=e;for(const a of ie(n)){const u=o[a],l=n[a],c=e.getScaleComponent(a),f=yn(i[a]),d=u[t],h=c.get("type"),p=c.get("padding"),g=c.get("paddingInner"),m=Yw(h,t),y=uB(a,t);if(d!==void 0&&(m?y&&ae(y):ae(jP(h,t,a))),m&&y===void 0)if(d!==void 0){const v=f.timeUnit,b=f.type;switch(t){case"domainMax":case"domainMin":Cc(u[t])||b==="temporal"||v?l.set(t,{signal:tb(u[t],{type:b,timeUnit:v})},!0):l.set(t,u[t],!0);break;default:l.copyKeyFromObject(t,u)}}else{const v=oe(U4,t)?U4[t]({model:e,channel:a,fieldOrDatumDef:f,scaleType:h,scalePadding:p,scalePaddingInner:g,domain:u.domain,domainMin:u.domainMin,domainMax:u.domainMax,markDef:s,config:r,hasNestedOffsetScale:LB(i,a),hasSecondaryRangeChannel:!!i[Lo(a)]}):r.scale[t];v!==void 0&&l.set(t,v,!1)}}}const U4={bins:({model:e,fieldOrDatumDef:t})=>ue(t)?w2e(e,t):void 0,interpolate:({channel:e,fieldOrDatumDef:t})=>E2e(e,t.type),nice:({scaleType:e,channel:t,domain:n,domainMin:r,domainMax:i,fieldOrDatumDef:s})=>A2e(e,t,n,r,i,s),padding:({channel:e,scaleType:t,fieldOrDatumDef:n,markDef:r,config:i})=>S2e(e,t,i.scale,n,r,i.bar),paddingInner:({scalePadding:e,channel:t,markDef:n,scaleType:r,config:i,hasNestedOffsetScale:s})=>k2e(e,t,n.type,r,i.scale,s),paddingOuter:({scalePadding:e,channel:t,scaleType:n,scalePaddingInner:r,config:i,hasNestedOffsetScale:s})=>C2e(e,t,n,r,i.scale,s),reverse:({fieldOrDatumDef:e,scaleType:t,channel:n,config:r})=>{const i=ue(e)?e.sort:void 0;return $2e(t,i,n,r.scale)},zero:({channel:e,fieldOrDatumDef:t,domain:n,markDef:r,scaleType:i,config:s,hasSecondaryRangeChannel:o})=>F2e(e,t,n,r,i,s.scale,o)};function Fj(e){Gt(e)?d2e(e):Dj(e,"range")}function Dj(e,t){const n=e.component.scales;for(const r of e.children)t==="range"?Fj(r):$j(r,t);for(const r of ie(n)){let i;for(const s of e.children){const o=s.component.scales[r];if(o){const a=o.getWithExplicit(t);i=Au(i,a,t,"scale",pz((u,l)=>{switch(t){case"range":return u.step&&l.step?u.step-l.step:0}return 0}))}}n[r].setWithExplicit(t,i)}}function w2e(e,t){const n=t.bin;if(Mt(n)){const r=K3(e,t.field,n);return new En(()=>e.getSignalName(r))}else if(Pn(n)&&Sc(n)&&n.step!==void 0)return{step:n.step}}function E2e(e,t){if(Qe([Kr,No,Oo],e)&&t!=="nominal")return"hcl"}function A2e(e,t,n,r,i,s){var o;if(!((o=Fs(s))!=null&&o.bin||ee(n)||i!=null||r!=null||Qe([jn.TIME,jn.UTC],e)))return ln(t)?!0:void 0}function S2e(e,t,n,r,i,s){if(ln(e)){if(ao(t)){if(n.continuousPadding!==void 0)return n.continuousPadding;const{type:o,orient:a}=i;if(o==="bar"&&!(ue(r)&&(r.bin||r.timeUnit))&&(a==="vertical"&&e==="x"||a==="horizontal"&&e==="y"))return s.continuousBandSize}if(t===jn.POINT)return n.pointPadding}}function k2e(e,t,n,r,i,s=!1){if(e===void 0){if(ln(t)){const{bandPaddingInner:o,barBandPaddingInner:a,rectBandPaddingInner:u,tickBandPaddingInner:l,bandWithNestedOffsetPaddingInner:c}=i;return s?c:un(o,n==="bar"?a:n==="tick"?l:u)}else if(Ig(t)&&r===jn.BAND)return i.offsetBandPaddingInner}}function C2e(e,t,n,r,i,s=!1){if(e===void 0){if(ln(t)){const{bandPaddingOuter:o,bandWithNestedOffsetPaddingOuter:a}=i;if(s)return a;if(n===jn.BAND)return un(o,Ce(r)?{signal:`${r.signal}/2`}:r/2)}else if(Ig(t)){if(n===jn.POINT)return .5;if(n===jn.BAND)return i.offsetBandPaddingOuter}}}function $2e(e,t,n,r){if(n==="x"&&r.xReverse!==void 0)return Cs(e)&&t==="descending"?Ce(r.xReverse)?{signal:`!${r.xReverse.signal}`}:!r.xReverse:r.xReverse;if(Cs(e)&&t==="descending")return!0}function F2e(e,t,n,r,i,s,o){if(!!n&&n!=="unaggregated"&&Cs(i)){if(ee(n)){const u=n[0],l=n[n.length-1];if(ft(u)&&u<=0&&ft(l)&&l>=0)return!0}return!1}if(e==="size"&&t.type==="quantitative"&&!od(i))return!0;if(!(ue(t)&&t.bin)&&Qe([...Ca,...lpe],e)){const{orient:u,type:l}=r;return Qe(["bar","area","line","trail"],l)&&(u==="horizontal"&&e==="y"||u==="vertical"&&e==="x")?!1:Qe(["bar","area"],l)&&!o?!0:s==null?void 0:s.zero}return!1}function D2e(e,t,n,r,i=!1){const s=M2e(t,n,r,i),{type:o}=e;return Io(t)?o!==void 0?y0e(t,o)?ue(n)&&!m0e(o,n.type)?(ae(vge(o,s)),s):o:(ae(yge(t,o,s)),s):s:null}function M2e(e,t,n,r){var i;switch(t.type){case"nominal":case"ordinal":{if(gf(e)||J2(e)==="discrete")return e==="shape"&&t.type==="ordinal"&&ae(Q2(e,"ordinal")),"ordinal";if(Z2(e))return"band";if(ln(e)||Ig(e)){if(Qe(["rect","bar","image","rule","tick"],n.type)||r)return"band"}else if(n.type==="arc"&&e in YC)return"band";const s=n[Jr(e)];return ac(s)||ud(t)&&((i=t.axis)!=null&&i.tickBand)?"band":"point"}case"temporal":return gf(e)?"time":J2(e)==="discrete"?(ae(Q2(e,"temporal")),"ordinal"):ue(t)&&t.timeUnit&&Mn(t.timeUnit).utc?"utc":Z2(e)?"band":"time";case"quantitative":return gf(e)?ue(t)&&Mt(t.bin)?"bin-ordinal":"linear":J2(e)==="discrete"?(ae(Q2(e,"quantitative")),"ordinal"):Z2(e)?"band":"linear";case"geojson":return}throw new Error(BP(t.type))}function R2e(e,{ignoreRange:t}={}){Mj(e),_j(e);for(const n of g0e)$j(e,n);t||Fj(e)}function Mj(e){Gt(e)?e.component.scales=T2e(e):e.component.scales=O2e(e)}function T2e(e){const{encoding:t,mark:n,markDef:r}=e,i={};for(const s of VC){const o=yn(t[s]);if(o&&n===fB&&s===Zr&&o.type===Bd)continue;let a=o&&o.scale;if(o&&a!==null&&a!==!1){a??(a={});const u=LB(t,s),l=D2e(a,s,o,r,u);i[s]=new Ej(e.scaleName(`${s}`,!0),{value:l,explicit:a.type===l})}}return i}const N2e=pz((e,t)=>jM(e)-jM(t));function O2e(e){var t;const n=e.component.scales={},r={},i=e.component.resolve;for(const s of e.children){Mj(s);for(const o of ie(s.component.scales))if((t=i.scale)[o]??(t[o]=uj(o,e)),i.scale[o]==="shared"){const a=r[o],u=s.component.scales[o].getWithExplicit("type");a?s0e(a.value,u.value)?r[o]=Au(a,u,"type","scale",N2e):(i.scale[o]="independent",delete r[o]):r[o]=u}}for(const s of ie(r)){const o=e.scaleName(s,!0),a=r[s];n[s]=new Ej(o,a);for(const u of e.children){const l=u.component.scales[s];l&&(u.renameScale(l.get("name"),o),l.merged=!0)}}return n}class px{constructor(){this.nameMap={}}rename(t,n){this.nameMap[t]=n}has(t){return this.nameMap[t]!==void 0}get(t){for(;this.nameMap[t]&&t!==this.nameMap[t];)t=this.nameMap[t];return t}}function Gt(e){return(e==null?void 0:e.type)==="unit"}function mi(e){return(e==null?void 0:e.type)==="facet"}function t$(e){return(e==null?void 0:e.type)==="concat"}function Wd(e){return(e==null?void 0:e.type)==="layer"}class n${constructor(t,n,r,i,s,o,a){this.type=n,this.parent=r,this.config=s,this.parent=r,this.config=s,this.view=zn(a),this.name=t.name??i,this.title=za(t.title)?{text:t.title}:t.title?zn(t.title):void 0,this.scaleNameMap=r?r.scaleNameMap:new px,this.projectionNameMap=r?r.projectionNameMap:new px,this.signalNameMap=r?r.signalNameMap:new px,this.data=t.data,this.description=t.description,this.transforms=M1e(t.transform??[]),this.layout=n==="layer"||n==="unit"?{}:Ome(t,n,s),this.component={data:{sources:r?r.component.data.sources:[],outputNodes:r?r.component.data.outputNodes:{},outputNodeRefCounts:r?r.component.data.outputNodeRefCounts:{},isFaceted:Jv(t)||(r==null?void 0:r.component.data.isFaceted)&&t.data===void 0},layoutSize:new Fa,layoutHeaders:{row:{},column:{},facet:{}},mark:null,resolve:{scale:{},axis:{},legend:{},...o?Be(o):{}},selection:null,scales:null,projection:null,axes:{},legends:{}}}get width(){return this.getSizeSignalRef("width")}get height(){return this.getSizeSignalRef("height")}parse(){this.parseScale(),this.parseLayoutSize(),this.renameTopLevelLayoutSizeSignal(),this.parseSelections(),this.parseProjection(),this.parseData(),this.parseAxesAndHeaders(),this.parseLegends(),this.parseMarkGroup()}parseScale(){R2e(this)}parseProjection(){vj(this)}renameTopLevelLayoutSizeSignal(){this.getName("width")!=="width"&&this.renameSignal(this.getName("width"),"width"),this.getName("height")!=="height"&&this.renameSignal(this.getName("height"),"height")}parseLegends(){hj(this)}assembleEncodeFromView(t){const{style:n,...r}=t,i={};for(const s of ie(r)){const o=r[s];o!==void 0&&(i[s]=Ot(o))}return i}assembleGroupEncodeEntry(t){let n={};return this.view&&(n=this.assembleEncodeFromView(this.view)),!t&&(this.description&&(n.description=Ot(this.description)),this.type==="unit"||this.type==="layer")?{width:this.getSizeSignalRef("width"),height:this.getSizeSignalRef("height"),...n}:Et(n)?void 0:n}assembleLayout(){if(!this.layout)return;const{spacing:t,...n}=this.layout,{component:r,config:i}=this,s=tbe(r.layoutHeaders,i);return{padding:t,...this.assembleDefaultLayout(),...n,...s?{titleBand:s}:{}}}assembleDefaultLayout(){return{}}assembleHeaderMarks(){const{layoutHeaders:t}=this.component;let n=[];for(const r of Oi)t[r].title&&n.push(Xve(this,r));for(const r of G3)n=n.concat(Kve(this,r));return n}assembleAxes(){return Lve(this.component.axes,this.config)}assembleLegends(){return gj(this)}assembleProjections(){return Abe(this)}assembleTitle(){const{encoding:t,...n}=this.title??{},r={...DP(this.config.title).nonMarkTitleProperties,...n,...t?{encode:{update:t}}:{}};if(r.text)return Qe(["unit","layer"],this.type)?Qe(["middle",void 0],r.anchor)&&(r.frame??(r.frame="group")):r.anchor??(r.anchor="start"),Et(r)?void 0:r}assembleGroup(t=[]){const n={};t=t.concat(this.assembleSignals()),t.length>0&&(n.signals=t);const r=this.assembleLayout();r&&(n.layout=r),n.marks=[].concat(this.assembleHeaderMarks(),this.assembleMarks());const i=!this.parent||mi(this.parent)?wj(this):[];i.length>0&&(n.scales=i);const s=this.assembleAxes();s.length>0&&(n.axes=s);const o=this.assembleLegends();return o.length>0&&(n.legends=o),n}getName(t){return Ut((this.name?`${this.name}_`:"")+t)}getDataName(t){return this.getName(Vt[t].toLowerCase())}requestDataName(t){const n=this.getDataName(t),r=this.component.data.outputNodeRefCounts;return r[n]=(r[n]||0)+1,n}getSizeSignalRef(t){if(mi(this.parent)){const n=oj(t),r=jv(n),i=this.component.scales[r];if(i&&!i.merged){const s=i.get("type"),o=i.get("range");if(Tn(s)&&kc(o)){const a=i.get("name"),u=yb(this,r),l=e$(u);if(l){const c=pe({aggregate:"distinct",field:l},{expr:"datum"});return{signal:sj(a,i,c)}}else return ae(ZC(r)),null}}}return{signal:this.signalNameMap.get(this.getName(t))}}lookupDataSource(t){const n=this.component.data.outputNodes[t];return n?n.getSource():t}getSignalName(t){return this.signalNameMap.get(t)}renameSignal(t,n){this.signalNameMap.rename(t,n)}renameScale(t,n){this.scaleNameMap.rename(t,n)}renameProjection(t,n){this.projectionNameMap.rename(t,n)}scaleName(t,n){if(n)return this.getName(t);if(wP(t)&&Io(t)&&this.component.scales[t]||this.scaleNameMap.has(this.getName(t)))return this.scaleNameMap.get(this.getName(t))}projectionName(t){if(t)return this.getName("projection");if(this.component.projection&&!this.component.projection.merged||this.projectionNameMap.has(this.getName("projection")))return this.projectionNameMap.get(this.getName("projection"))}getScaleComponent(t){if(!this.component.scales)throw new Error("getScaleComponent cannot be called before parseScale(). Make sure you have called parseScale or use parseUnitModelWithScale().");const n=this.component.scales[t];return n&&!n.merged?n:this.parent?this.parent.getScaleComponent(t):void 0}getScaleType(t){const n=this.getScaleComponent(t);return n?n.get("type"):void 0}getSelectionComponent(t,n){let r=this.component.selection[t];if(!r&&this.parent&&(r=this.parent.getSelectionComponent(t,n)),!r)throw new Error(Tpe(n));return r}hasAxisOrientSignalRef(){var t,n;return((t=this.component.axes.x)==null?void 0:t.some(r=>r.hasOrientSignalRef()))||((n=this.component.axes.y)==null?void 0:n.some(r=>r.hasOrientSignalRef()))}}class Rj extends n${vgField(t,n={}){const r=this.fieldDef(t);if(r)return pe(r,n)}reduceFieldDef(t,n){return cme(this.getMapping(),(r,i,s)=>{const o=Fs(i);return o?t(r,o,s):r},n)}forEachFieldDef(t,n){S3(this.getMapping(),(r,i)=>{const s=Fs(r);s&&t(s,i)},n)}}class vb extends _t{clone(){return new vb(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Be(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??"value",r[1]??"density"];const i=this.transform.resolve??"shared";this.transform.resolve=i}dependentFields(){return new Set([this.transform.density,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`DensityTransform ${rt(this.transform)}`}assemble(){const{density:t,...n}=this.transform,r={type:"kde",field:t,...n};return r.resolve=this.transform.resolve,r}}class bb extends _t{clone(){return new bb(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Be(n)}dependentFields(){return new Set([this.transform.extent])}producedFields(){return new Set([])}hash(){return`ExtentTransform ${rt(this.transform)}`}assemble(){const{extent:t,param:n}=this.transform;return{type:"extent",field:t,signal:n}}}class xb extends _t{clone(){return new xb(this.parent,Be(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Be(n);const{flatten:r,as:i=[]}=this.transform;this.transform.as=r.map((s,o)=>i[o]??s)}dependentFields(){return new Set(this.transform.flatten)}producedFields(){return new Set(this.transform.as)}hash(){return`FlattenTransform ${rt(this.transform)}`}assemble(){const{flatten:t,as:n}=this.transform;return{type:"flatten",fields:t,as:n}}}class _b extends _t{clone(){return new _b(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Be(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??"key",r[1]??"value"]}dependentFields(){return new Set(this.transform.fold)}producedFields(){return new Set(this.transform.as)}hash(){return`FoldTransform ${rt(this.transform)}`}assemble(){const{fold:t,as:n}=this.transform;return{type:"fold",fields:t,as:n}}}class vf extends _t{clone(){return new vf(null,Be(this.fields),this.geojson,this.signal)}static parseAll(t,n){if(n.component.projection&&!n.component.projection.isFit)return t;let r=0;for(const i of[[Is,Ls],[Yi,Ps]]){const s=i.map(o=>{const a=yn(n.encoding[o]);return ue(a)?a.field:Po(a)?{expr:`${a.datum}`}:$s(a)?{expr:`${a.value}`}:void 0});(s[0]||s[1])&&(t=new vf(t,s,null,n.getName(`geojson_${r++}`)))}if(n.channelHasField(Zr)){const i=n.typedFieldDef(Zr);i.type===Bd&&(t=new vf(t,null,i.field,n.getName(`geojson_${r++}`)))}return t}constructor(t,n,r,i){super(t),this.fields=n,this.geojson=r,this.signal=i}dependentFields(){const t=(this.fields??[]).filter(me);return new Set([...this.geojson?[this.geojson]:[],...t])}producedFields(){return new Set}hash(){return`GeoJSON ${this.geojson} ${this.signal} ${rt(this.fields)}`}assemble(){return[...this.geojson?[{type:"filter",expr:`isValid(datum["${this.geojson}"])`}]:[],{type:"geojson",...this.fields?{fields:this.fields}:{},...this.geojson?{geojson:this.geojson}:{},signal:this.signal}]}}class jp extends _t{clone(){return new jp(null,this.projection,Be(this.fields),Be(this.as))}constructor(t,n,r,i){super(t),this.projection=n,this.fields=r,this.as=i}static parseAll(t,n){if(!n.projectionName())return t;for(const r of[[Is,Ls],[Yi,Ps]]){const i=r.map(o=>{const a=yn(n.encoding[o]);return ue(a)?a.field:Po(a)?{expr:`${a.datum}`}:$s(a)?{expr:`${a.value}`}:void 0}),s=r[0]===Yi?"2":"";(i[0]||i[1])&&(t=new jp(t,n.projectionName(),i,[n.getName(`x${s}`),n.getName(`y${s}`)]))}return t}dependentFields(){return new Set(this.fields.filter(me))}producedFields(){return new Set(this.as)}hash(){return`Geopoint ${this.projection} ${rt(this.fields)} ${rt(this.as)}`}assemble(){return{type:"geopoint",projection:this.projection,fields:this.fields,as:this.as}}}class Nl extends _t{clone(){return new Nl(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n}dependentFields(){return new Set([this.transform.impute,this.transform.key,...this.transform.groupby??[]])}producedFields(){return new Set([this.transform.impute])}processSequence(t){const{start:n=0,stop:r,step:i}=t;return{signal:`sequence(${[n,r,...i?[i]:[]].join(",")})`}}static makeFromTransform(t,n){return new Nl(t,n)}static makeFromEncoding(t,n){const r=n.encoding,i=r.x,s=r.y;if(ue(i)&&ue(s)){const o=i.impute?i:s.impute?s:void 0;if(o===void 0)return;const a=i.impute?s:s.impute?i:void 0,{method:u,value:l,frame:c,keyvals:f}=o.impute,d=BB(n.mark,r);return new Nl(t,{impute:o.field,key:a.field,...u?{method:u}:{},...l!==void 0?{value:l}:{},...c?{frame:c}:{},...f!==void 0?{keyvals:f}:{},...d.length?{groupby:d}:{}})}return null}hash(){return`Impute ${rt(this.transform)}`}assemble(){const{impute:t,key:n,keyvals:r,method:i,groupby:s,value:o,frame:a=[null,null]}=this.transform,u={type:"impute",field:t,key:n,...r?{keyvals:d1e(r)?this.processSequence(r):r}:{},method:"value",...s?{groupby:s}:{},value:!i||i==="value"?o:null};if(i&&i!=="value"){const l={type:"window",as:[`imputed_${t}_value`],ops:[i],fields:[t],frame:a,ignorePeers:!1,...s?{groupby:s}:{}},c={type:"formula",expr:`datum.${t} === null ? datum.imputed_${t}_value : datum.${t}`,as:t};return[u,l,c]}else return[u]}}class wb extends _t{clone(){return new wb(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Be(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??n.on,r[1]??n.loess]}dependentFields(){return new Set([this.transform.loess,this.transform.on,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`LoessTransform ${rt(this.transform)}`}assemble(){const{loess:t,on:n,...r}=this.transform;return{type:"loess",x:n,y:t,...r}}}class Up extends _t{clone(){return new Up(null,Be(this.transform),this.secondary)}constructor(t,n,r){super(t),this.transform=n,this.secondary=r}static make(t,n,r,i){const s=n.component.data.sources,{from:o}=r;let a=null;if(h1e(o)){let u=Oj(o.data,s);u||(u=new hc(o.data),s.push(u));const l=n.getName(`lookup_${i}`);a=new Gr(u,l,Vt.Lookup,n.component.data.outputNodeRefCounts),n.component.data.outputNodes[l]=a}else if(p1e(o)){const u=o.param;r={as:u,...r};let l;try{l=n.getSelectionComponent(Ut(u),u)}catch{throw new Error(Ipe(u))}if(a=l.materialized,!a)throw new Error(Ppe(u))}return new Up(t,r,a.getSource())}dependentFields(){return new Set([this.transform.lookup])}producedFields(){return new Set(this.transform.as?ye(this.transform.as):this.transform.from.fields)}hash(){return`Lookup ${rt({transform:this.transform,secondary:this.secondary})}`}assemble(){let t;if(this.transform.from.fields)t={values:this.transform.from.fields,...this.transform.as?{as:ye(this.transform.as)}:{}};else{let n=this.transform.as;me(n)||(ae(Xpe),n="_lookup"),t={as:[n]}}return{type:"lookup",from:this.secondary,key:this.transform.from.key,fields:[this.transform.lookup],...t,...this.transform.default?{default:this.transform.default}:{}}}}class Eb extends _t{clone(){return new Eb(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Be(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??"prob",r[1]??"value"]}dependentFields(){return new Set([this.transform.quantile,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`QuantileTransform ${rt(this.transform)}`}assemble(){const{quantile:t,...n}=this.transform;return{type:"quantile",field:t,...n}}}class Ab extends _t{clone(){return new Ab(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n,this.transform=Be(n);const r=this.transform.as??[void 0,void 0];this.transform.as=[r[0]??n.on,r[1]??n.regression]}dependentFields(){return new Set([this.transform.regression,this.transform.on,...this.transform.groupby??[]])}producedFields(){return new Set(this.transform.as)}hash(){return`RegressionTransform ${rt(this.transform)}`}assemble(){const{regression:t,on:n,...r}=this.transform;return{type:"regression",x:n,y:t,...r}}}class Sb extends _t{clone(){return new Sb(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n}addDimensions(t){this.transform.groupby=oo((this.transform.groupby??[]).concat(t),n=>n)}producedFields(){}dependentFields(){return new Set([this.transform.pivot,this.transform.value,...this.transform.groupby??[]])}hash(){return`PivotTransform ${rt(this.transform)}`}assemble(){const{pivot:t,value:n,groupby:r,limit:i,op:s}=this.transform;return{type:"pivot",field:t,value:n,...i!==void 0?{limit:i}:{},...s!==void 0?{op:s}:{},...r!==void 0?{groupby:r}:{}}}}class kb extends _t{clone(){return new kb(null,Be(this.transform))}constructor(t,n){super(t),this.transform=n}dependentFields(){return new Set}producedFields(){return new Set}hash(){return`SampleTransform ${rt(this.transform)}`}assemble(){return{type:"sample",size:this.transform.sample}}}function Tj(e){let t=0;function n(r,i){if(r instanceof hc&&!r.isGenerator&&!cd(r.data)&&(e.push(i),i={name:null,source:i.name,transform:[]}),r instanceof or&&(r.parent instanceof hc&&!i.source?(i.format={...i.format,parse:r.assembleFormatParse()},i.transform.push(...r.assembleTransforms(!0))):i.transform.push(...r.assembleTransforms())),r instanceof Ud){i.name||(i.name=`data_${t++}`),!i.source||i.transform.length>0?(e.push(i),r.data=i.name):r.data=i.source,e.push(...r.assemble());return}switch((r instanceof Kg||r instanceof Zg||r instanceof gd||r instanceof jd||r instanceof dd||r instanceof jp||r instanceof _s||r instanceof Up||r instanceof qd||r instanceof Rc||r instanceof _b||r instanceof xb||r instanceof vb||r instanceof wb||r instanceof Eb||r instanceof Ab||r instanceof Su||r instanceof kb||r instanceof Sb||r instanceof bb)&&i.transform.push(r.assemble()),(r instanceof po||r instanceof fo||r instanceof Nl||r instanceof ha||r instanceof vf)&&i.transform.push(...r.assemble()),r instanceof Gr&&(i.source&&i.transform.length===0?r.setSource(i.source):r.parent instanceof Gr?r.setSource(i.name):(i.name||(i.name=`data_${t++}`),r.setSource(i.name),r.numChildren()===1&&(e.push(i),i={name:null,source:i.name,transform:[]}))),r.numChildren()){case 0:r instanceof Gr&&(!i.source||i.transform.length>0)&&e.push(i);break;case 1:n(r.children[0],i);break;default:{i.name||(i.name=`data_${t++}`);let s=i.name;!i.source||i.transform.length>0?e.push(i):s=i.source;for(const o of r.children)n(o,{name:null,source:s,transform:[]});break}}}return n}function L2e(e){const t=[],n=Tj(t);for(const r of e.children)n(r,{source:e.name,name:null,transform:[]});return t}function I2e(e,t){const n=[],r=Tj(n);let i=0;for(const o of e.sources){o.hasName()||(o.dataName=`source_${i++}`);const a=o.assemble();r(o,a)}for(const o of n)o.transform.length===0&&delete o.transform;let s=0;for(const[o,a]of n.entries())(a.transform??[]).length===0&&!a.source&&n.splice(s++,0,n.splice(o,1)[0]);for(const o of n)for(const a of o.transform??[])a.type==="lookup"&&(a.from=e.outputNodes[a.from].getSource());for(const o of n)o.name in t&&(o.values=t[o.name]);return n}function P2e(e){return e==="top"||e==="left"||Ce(e)?"header":"footer"}function B2e(e){for(const t of Oi)z2e(e,t);q4(e,"x"),q4(e,"y")}function z2e(e,t){var o;const{facet:n,config:r,child:i,component:s}=e;if(e.channelHasField(t)){const a=n[t],u=pd("title",null,r,t);let l=mf(a,r,{allowDisabling:!0,includeDefault:u===void 0||!!u});i.component.layoutHeaders[t].title&&(l=ee(l)?l.join(", "):l,l+=` / ${i.component.layoutHeaders[t].title}`,i.component.layoutHeaders[t].title=null);const c=pd("labelOrient",a.header,r,t),f=a.header!==null?un((o=a.header)==null?void 0:o.labels,r.header.labels,!0):!1,d=Qe(["bottom","right"],c)?"footer":"header";s.layoutHeaders[t]={title:a.header!==null?l:null,facetFieldDef:a,[d]:t==="facet"?[]:[Nj(e,t,f)]}}}function Nj(e,t,n){const r=t==="row"?"height":"width";return{labels:n,sizeSignal:e.child.component.layoutSize.get(r)?e.child.getSizeSignalRef(r):void 0,axes:[]}}function q4(e,t){const{child:n}=e;if(n.component.axes[t]){const{layoutHeaders:r,resolve:i}=e.component;if(i.axis[t]=X3(i,t),i.axis[t]==="shared"){const s=t==="x"?"column":"row",o=r[s];for(const a of n.component.axes[t]){const u=P2e(a.get("orient"));o[u]??(o[u]=[Nj(e,s,!1)]);const l=Uh(a,"main",e.config,{header:!0});l&&o[u][0].axes.push(l),a.mainExtracted=!0}}}}function j2e(e){r$(e),ay(e,"width"),ay(e,"height")}function U2e(e){r$(e);const t=e.layout.columns===1?"width":"childWidth",n=e.layout.columns===void 0?"height":"childHeight";ay(e,t),ay(e,n)}function r$(e){for(const t of e.children)t.parseLayoutSize()}function ay(e,t){const n=oj(t),r=jv(n),i=e.component.resolve,s=e.component.layoutSize;let o;for(const a of e.children){const u=a.component.layoutSize.getWithExplicit(n),l=i.scale[r]??uj(r,e);if(l==="independent"&&u.value==="step"){o=void 0;break}if(o){if(l==="independent"&&o.value!==u.value){o=void 0;break}o=Au(o,u,n,"")}else o=u}if(o){for(const a of e.children)e.renameSignal(a.getName(n),e.getName(t)),a.component.layoutSize.set(n,"merged",!1);s.setWithExplicit(t,o)}else s.setWithExplicit(t,{explicit:!1,value:void 0})}function q2e(e){const{size:t,component:n}=e;for(const r of Ca){const i=Jr(r);if(t[i]){const s=t[i];n.layoutSize.set(i,Ao(s)?"step":s,!0)}else{const s=W2e(e,i);n.layoutSize.set(i,s,!1)}}}function W2e(e,t){const n=t==="width"?"x":"y",r=e.config,i=e.getScaleComponent(n);if(i){const s=i.get("type"),o=i.get("range");if(Tn(s)){const a=ny(r.view,t);return kc(o)||Ao(a)?"step":a}else return Kw(r.view,t)}else{if(e.hasProjection||e.mark==="arc")return Kw(r.view,t);{const s=ny(r.view,t);return Ao(s)?s.step:s}}}function mE(e,t,n){return pe(t,{suffix:`by_${pe(e)}`,...n})}class lp extends Rj{constructor(t,n,r,i){super(t,"facet",n,r,i,t.resolve),this.child=u$(t.spec,this,this.getName("child"),void 0,i),this.children=[this.child],this.facet=this.initFacet(t.facet)}initFacet(t){if(!jg(t))return{facet:this.initFacetFieldDef(t,"facet")};const n=ie(t),r={};for(const i of n){if(![la,ca].includes(i)){ae(Wv(i,"facet"));break}const s=t[i];if(s.field===void 0){ae(Hw(s,i));break}r[i]=this.initFacetFieldDef(s,i)}return r}initFacetFieldDef(t,n){const r=A3(t,n);return r.header?r.header=zn(r.header):r.header===null&&(r.header=null),r}channelHasField(t){return oe(this.facet,t)}fieldDef(t){return this.facet[t]}parseData(){this.component.data=Cb(this),this.child.parseData()}parseLayoutSize(){r$(this)}parseSelections(){this.child.parseSelections(),this.component.selection=this.child.component.selection,Object.values(this.component.selection).some(t=>ho(t))&&QC(JC)}parseMarkGroup(){this.child.parseMarkGroup()}parseAxesAndHeaders(){this.child.parseAxesAndHeaders(),B2e(this)}assembleSelectionTopLevelSignals(t){return this.child.assembleSelectionTopLevelSignals(t)}assembleSignals(){return this.child.assembleSignals(),[]}assembleSelectionData(t){return this.child.assembleSelectionData(t)}getHeaderLayoutMixins(){const t={};for(const n of Oi)for(const r of Y3){const i=this.component.layoutHeaders[n],s=i[r],{facetFieldDef:o}=i;if(o){const a=pd("titleOrient",o.header,this.config,n);if(["right","bottom"].includes(a)){const u=gb(n,a);t.titleAnchor??(t.titleAnchor={}),t.titleAnchor[u]="end"}}if(s!=null&&s[0]){const a=n==="row"?"height":"width",u=r==="header"?"headerBand":"footerBand";n!=="facet"&&!this.child.component.layoutSize.get(a)&&(t[u]??(t[u]={}),t[u][n]=.5),i.title&&(t.offset??(t.offset={}),t.offset[n==="row"?"rowTitle":"columnTitle"]=10)}}return t}assembleDefaultLayout(){const{column:t,row:n}=this.facet,r=t?this.columnDistinctSignal():n?1:void 0;let i="all";return(!n&&this.component.resolve.scale.x==="independent"||!t&&this.component.resolve.scale.y==="independent")&&(i="none"),{...this.getHeaderLayoutMixins(),...r?{columns:r}:{},bounds:"full",align:i}}assembleLayoutSignals(){return this.child.assembleLayoutSignals()}columnDistinctSignal(){if(!(this.parent&&this.parent instanceof lp))return{signal:`length(data('${this.getName("column_domain")}'))`}}assembleGroupStyle(){}assembleGroup(t){return this.parent&&this.parent instanceof lp?{...this.channelHasField("column")?{encode:{update:{columns:{field:pe(this.facet.column,{prefix:"distinct"})}}}}:{},...super.assembleGroup(t)}:super.assembleGroup(t)}getCardinalityAggregateForChild(){const t=[],n=[],r=[];if(this.child instanceof lp){if(this.child.channelHasField("column")){const i=pe(this.child.facet.column);t.push(i),n.push("distinct"),r.push(`distinct_${i}`)}}else for(const i of Ca){const s=this.child.component.scales[i];if(s&&!s.merged){const o=s.get("type"),a=s.get("range");if(Tn(o)&&kc(a)){const u=yb(this.child,i),l=e$(u);l?(t.push(l),n.push("distinct"),r.push(`distinct_${l}`)):ae(ZC(i))}}}return{fields:t,ops:n,as:r}}assembleFacet(){const{name:t,data:n}=this.component.data.facetRoot,{row:r,column:i}=this.facet,{fields:s,ops:o,as:a}=this.getCardinalityAggregateForChild(),u=[];for(const c of Oi){const f=this.facet[c];if(f){u.push(pe(f));const{bin:d,sort:h}=f;if(Mt(d)&&u.push(pe(f,{binSuffix:"end"})),fa(h)){const{field:p,op:g=Zv}=h,m=mE(f,h);r&&i?(s.push(m),o.push("max"),a.push(m)):(s.push(p),o.push(g),a.push(m))}else if(ee(h)){const p=hd(f,c);s.push(p),o.push("max"),a.push(p)}}}const l=!!r&&!!i;return{name:t,data:n,groupby:u,...l||s.length>0?{aggregate:{...l?{cross:l}:{},...s.length?{fields:s,ops:o,as:a}:{}}}:{}}}facetSortFields(t){const{facet:n}=this,r=n[t];return r?fa(r.sort)?[mE(r,r.sort,{expr:"datum"})]:ee(r.sort)?[hd(r,t,{expr:"datum"})]:[pe(r,{expr:"datum"})]:[]}facetSortOrder(t){const{facet:n}=this,r=n[t];if(r){const{sort:i}=r;return[(fa(i)?i.order:!ee(i)&&i)||"ascending"]}return[]}assembleLabelTitle(){var i;const{facet:t,config:n}=this;if(t.facet)return lE(t.facet,"facet",n);const r={row:["top","bottom"],column:["left","right"]};for(const s of G3)if(t[s]){const o=pd("labelOrient",(i=t[s])==null?void 0:i.header,n,s);if(r[s].includes(o))return lE(t[s],s,n)}}assembleMarks(){const{child:t}=this,n=this.component.data.facetRoot,r=L2e(n),i=t.assembleGroupEncodeEntry(!1),s=this.assembleLabelTitle()||t.assembleTitle(),o=t.assembleGroupStyle();return[{name:this.getName("cell"),type:"group",...s?{title:s}:{},...o?{style:o}:{},from:{facet:this.assembleFacet()},sort:{field:Oi.map(u=>this.facetSortFields(u)).flat(),order:Oi.map(u=>this.facetSortOrder(u)).flat()},...r.length>0?{data:r}:{},...i?{encode:{update:i}}:{},...t.assembleGroup(K1e(this,[]))}]}getMapping(){return this.facet}}function H2e(e,t){const{row:n,column:r}=t;if(n&&r){let i=null;for(const s of[n,r])if(fa(s.sort)){const{field:o,op:a=Zv}=s.sort;e=i=new Rc(e,{joinaggregate:[{op:a,field:o,as:mE(s,s.sort,{forAs:!0})}],groupby:[pe(s)]})}return i}return null}function Oj(e,t){var n,r,i,s;for(const o of t){const a=o.data;if(e.name&&o.hasName()&&e.name!==o.dataName)continue;const u=(n=e.format)==null?void 0:n.mesh,l=(r=a.format)==null?void 0:r.feature;if(u&&l)continue;const c=(i=e.format)==null?void 0:i.feature;if((c||l)&&c!==l)continue;const f=(s=a.format)==null?void 0:s.mesh;if(!((u||f)&&u!==f)){if(Pp(e)&&Pp(a)){if(fi(e.values,a.values))return o}else if(cd(e)&&cd(a)){if(e.url===a.url)return o}else if(gz(e)&&e.name===o.dataName)return o}}return null}function G2e(e,t){if(e.data||!e.parent){if(e.data===null){const r=new hc({values:[]});return t.push(r),r}const n=Oj(e.data,t);if(n)return lu(e.data)||(n.data.format=cP({},e.data.format,n.data.format)),!n.hasName()&&e.data.name&&(n.dataName=e.data.name),n;{const r=new hc(e.data);return t.push(r),r}}else return e.parent.component.data.facetRoot?e.parent.component.data.facetRoot:e.parent.component.data.main}function Y2e(e,t,n){let r=0;for(const i of t.transforms){let s,o;if(A1e(i))o=e=new dd(e,i),s="derived";else if(L3(i)){const a=Ibe(i);o=e=or.makeWithAncestors(e,{},a,n)??e,e=new jd(e,t,i.filter)}else if(cz(i))o=e=po.makeFromTransform(e,i,t),s="number";else if(k1e(i))s="date",n.getWithExplicit(i.field).value===void 0&&(e=new or(e,{[i.field]:s}),n.set(i.field,s,!1)),o=e=fo.makeFromTransform(e,i);else if(C1e(i))o=e=_s.makeFromTransform(e,i),s="number",U3(t)&&(e=new Su(e));else if(lz(i))o=e=Up.make(e,t,i,r++),s="derived";else if(_1e(i))o=e=new qd(e,i),s="number";else if(w1e(i))o=e=new Rc(e,i),s="number";else if($1e(i))o=e=ha.makeFromTransform(e,i),s="derived";else if(F1e(i))o=e=new _b(e,i),s="derived";else if(D1e(i))o=e=new bb(e,i),s="derived";else if(E1e(i))o=e=new xb(e,i),s="derived";else if(g1e(i))o=e=new Sb(e,i),s="derived";else if(x1e(i))e=new kb(e,i);else if(S1e(i))o=e=Nl.makeFromTransform(e,i),s="derived";else if(m1e(i))o=e=new vb(e,i),s="derived";else if(y1e(i))o=e=new Eb(e,i),s="derived";else if(v1e(i))o=e=new Ab(e,i),s="derived";else if(b1e(i))o=e=new wb(e,i),s="derived";else{ae(Vpe(i));continue}if(o&&s!==void 0)for(const a of o.producedFields()??[])n.set(a,s,!1)}return e}function Cb(e){var m;let t=G2e(e,e.component.data.sources);const{outputNodes:n,outputNodeRefCounts:r}=e.component.data,i=e.data,o=!(i&&(lu(i)||cd(i)||Pp(i)))&&e.parent?e.parent.component.data.ancestorParse.clone():new U1e;lu(i)?(mz(i)?t=new Zg(t,i.sequence):I3(i)&&(t=new Kg(t,i.graticule)),o.parseNothing=!0):((m=i==null?void 0:i.format)==null?void 0:m.parse)===null&&(o.parseNothing=!0),t=or.makeExplicit(t,e,o)??t,t=new Su(t);const a=e.parent&&Wd(e.parent);(Gt(e)||mi(e))&&a&&(t=po.makeFromEncoding(t,e)??t),e.transforms.length>0&&(t=Y2e(t,e,o));const u=Bbe(e),l=Pbe(e);t=or.makeWithAncestors(t,{},{...u,...l},o)??t,Gt(e)&&(t=vf.parseAll(t,e),t=jp.parseAll(t,e)),(Gt(e)||mi(e))&&(a||(t=po.makeFromEncoding(t,e)??t),t=fo.makeFromEncoding(t,e)??t,t=dd.parseAllForSortIndex(t,e));const c=t=N0(Vt.Raw,e,t);if(Gt(e)){const y=_s.makeFromEncoding(t,e);y&&(t=y,U3(e)&&(t=new Su(t))),t=Nl.makeFromEncoding(t,e)??t,t=ha.makeFromEncoding(t,e)??t}let f,d;if(Gt(e)){const{markDef:y,mark:v,config:b}=e,x=wt("invalid",y,b),{marks:_,scales:A}=d=vz({invalid:x,isPath:Hu(v)});_!==A&&A==="include-invalid-values"&&(f=t=N0(Vt.PreFilterInvalid,e,t)),_==="exclude-invalid-values"&&(t=gd.make(t,e,d)??t)}const h=t=N0(Vt.Main,e,t);let p;if(Gt(e)&&d){const{marks:y,scales:v}=d;y==="include-invalid-values"&&v==="exclude-invalid-values"&&(t=gd.make(t,e,d)??t,p=t=N0(Vt.PostFilterInvalid,e,t))}Gt(e)&&Nve(e,h);let g=null;if(mi(e)){const y=e.getName("facet");t=H2e(t,e.facet)??t,g=new Ud(t,e,y,h.getSource()),n[y]=g}return{...e.component.data,outputNodes:n,outputNodeRefCounts:r,raw:c,main:h,facetRoot:g,ancestorParse:o,preFilterInvalid:f,postFilterInvalid:p}}function N0(e,t,n){const{outputNodes:r,outputNodeRefCounts:i}=t.component.data,s=t.getDataName(e),o=new Gr(n,s,e,i);return r[s]=o,o}class V2e extends n${constructor(t,n,r,i){var s,o,a,u;super(t,"concat",n,r,i,t.resolve),(((o=(s=t.resolve)==null?void 0:s.axis)==null?void 0:o.x)==="shared"||((u=(a=t.resolve)==null?void 0:a.axis)==null?void 0:u.y)==="shared")&&ae(Hpe),this.children=this.getChildren(t).map((l,c)=>u$(l,this,this.getName(`concat_${c}`),void 0,i))}parseData(){this.component.data=Cb(this);for(const t of this.children)t.parseData()}parseSelections(){this.component.selection={};for(const t of this.children){t.parseSelections();for(const n of ie(t.component.selection))this.component.selection[n]=t.component.selection[n]}Object.values(this.component.selection).some(t=>ho(t))&&QC(JC)}parseMarkGroup(){for(const t of this.children)t.parseMarkGroup()}parseAxesAndHeaders(){for(const t of this.children)t.parseAxesAndHeaders()}getChildren(t){return ib(t)?t.vconcat:N3(t)?t.hconcat:t.concat}parseLayoutSize(){U2e(this)}parseAxisGroup(){return null}assembleSelectionTopLevelSignals(t){return this.children.reduce((n,r)=>r.assembleSelectionTopLevelSignals(n),t)}assembleSignals(){return this.children.forEach(t=>t.assembleSignals()),[]}assembleLayoutSignals(){const t=V3(this);for(const n of this.children)t.push(...n.assembleLayoutSignals());return t}assembleSelectionData(t){return this.children.reduce((n,r)=>r.assembleSelectionData(n),t)}assembleMarks(){return this.children.map(t=>{const n=t.assembleTitle(),r=t.assembleGroupStyle(),i=t.assembleGroupEncodeEntry(!1);return{type:"group",name:t.getName("group"),...n?{title:n}:{},...r?{style:r}:{},...i?{encode:{update:i}}:{},...t.assembleGroup()}})}assembleGroupStyle(){}assembleDefaultLayout(){const t=this.layout.columns;return{...t!=null?{columns:t}:{},bounds:"full",align:"each"}}}function X2e(e){return e===!1||e===null}const K2e={disable:1,gridScale:1,scale:1,...TB,labelExpr:1,encode:1},Lj=ie(K2e);class i$ extends Fa{constructor(t={},n={},r=!1){super(),this.explicit=t,this.implicit=n,this.mainExtracted=r}clone(){return new i$(Be(this.explicit),Be(this.implicit),this.mainExtracted)}hasAxisPart(t){return t==="axis"?!0:t==="grid"||t==="title"?!!this.get(t):!X2e(this.get(t))}hasOrientSignalRef(){return Ce(this.explicit.orient)}}function Z2e(e,t,n){const{encoding:r,config:i}=e,s=yn(r[t])??yn(r[Lo(t)]),o=e.axis(t)||{},{format:a,formatType:u}=o;if(uc(u))return{text:bs({fieldOrDatumDef:s,field:"datum.value",format:a,formatType:u,config:i}),...n};if(a===void 0&&u===void 0&&i.customFormatTypes){if(ad(s)==="quantitative"){if(ud(s)&&s.stack==="normalize"&&i.normalizedNumberFormatType)return{text:bs({fieldOrDatumDef:s,field:"datum.value",format:i.normalizedNumberFormat,formatType:i.normalizedNumberFormatType,config:i}),...n};if(i.numberFormatType)return{text:bs({fieldOrDatumDef:s,field:"datum.value",format:i.numberFormat,formatType:i.numberFormatType,config:i}),...n}}if(ad(s)==="temporal"&&i.timeFormatType&&ue(s)&&!s.timeUnit)return{text:bs({fieldOrDatumDef:s,field:"datum.value",format:i.timeFormat,formatType:i.timeFormatType,config:i}),...n}}return n}function J2e(e){return Ca.reduce((t,n)=>(e.component.scales[n]&&(t[n]=[sxe(n,e)]),t),{})}const Q2e={bottom:"top",top:"bottom",left:"right",right:"left"};function exe(e){const{axes:t,resolve:n}=e.component,r={top:0,bottom:0,right:0,left:0};for(const i of e.children){i.parseAxesAndHeaders();for(const s of ie(i.component.axes))n.axis[s]=X3(e.component.resolve,s),n.axis[s]==="shared"&&(t[s]=txe(t[s],i.component.axes[s]),t[s]||(n.axis[s]="independent",delete t[s]))}for(const i of Ca){for(const s of e.children)if(s.component.axes[i]){if(n.axis[i]==="independent"){t[i]=(t[i]??[]).concat(s.component.axes[i]);for(const o of s.component.axes[i]){const{value:a,explicit:u}=o.getWithExplicit("orient");if(!Ce(a)){if(r[a]>0&&!u){const l=Q2e[a];r[a]>r[l]&&o.set("orient",l,!1)}r[a]++}}}delete s.component.axes[i]}if(n.axis[i]==="independent"&&t[i]&&t[i].length>1)for(const[s,o]of(t[i]||[]).entries())s>0&&o.get("grid")&&!o.explicit.grid&&(o.implicit.grid=!1)}}function txe(e,t){if(e){if(e.length!==t.length)return;const n=e.length;for(let r=0;rn.clone());return e}function nxe(e,t){for(const n of Lj){const r=Au(e.getWithExplicit(n),t.getWithExplicit(n),n,"axis",(i,s)=>{switch(n){case"title":return IP(i,s);case"gridScale":return{explicit:i.explicit,value:un(i.value,s.value)}}return ob(i,s,n,"axis")});e.setWithExplicit(n,r)}return e}function rxe(e,t,n,r,i){if(t==="disable")return n!==void 0;switch(n=n||{},t){case"titleAngle":case"labelAngle":return e===(Ce(n.labelAngle)?n.labelAngle:Lp(n.labelAngle));case"values":return!!n.values;case"encode":return!!n.encoding||!!n.labelAngle;case"title":if(e===tj(r,i))return!0}return e===n[t]}const ixe=new Set(["grid","translate","format","formatType","orient","labelExpr","tickCount","position","tickMinStep"]);function sxe(e,t){var y,v;let n=t.axis(e);const r=new i$,i=yn(t.encoding[e]),{mark:s,config:o}=t,a=(n==null?void 0:n.orient)||((y=o[e==="x"?"axisX":"axisY"])==null?void 0:y.orient)||((v=o.axis)==null?void 0:v.orient)||Wve(e),u=t.getScaleComponent(e).get("type"),l=Ive(e,u,a,t.config),c=n!==void 0?!n:aE("disable",o.style,n==null?void 0:n.style,l).configValue;if(r.set("disable",c,n!==void 0),c)return r;n=n||{};const f=jve(i,n,e,o.style,l),d=bB(n.formatType,i,u),h=vB(i,i.type,n.format,n.formatType,o,!0),p={fieldOrDatumDef:i,axis:n,channel:e,model:t,scaleType:u,orient:a,labelAngle:f,format:h,formatType:d,mark:s,config:o};for(const b of Lj){const x=b in $4?$4[b](p):VM(b)?n[b]:void 0,_=x!==void 0,A=rxe(x,b,n,t,e);if(_&&A)r.set(b,x,A);else{const{configValue:E=void 0,configFrom:S=void 0}=VM(b)&&b!=="values"?aE(b,o.style,n.style,l):{},k=E!==void 0;_&&!k?r.set(b,x,A):(S!=="vgAxisConfig"||ixe.has(b)&&k||Hg(E)||Ce(E))&&r.set(b,E,!1)}}const g=n.encoding??{},m=RB.reduce((b,x)=>{if(!r.hasAxisPart(x))return b;const _=aj(g[x]??{},t),A=x==="labels"?Z2e(t,e,_):_;return A!==void 0&&!Et(A)&&(b[x]={update:A}),b},{});return Et(m)||r.set("encode",m,!!n.encoding||n.labelAngle!==void 0),r}function oxe({encoding:e,size:t}){for(const n of Ca){const r=Jr(n);Ao(t[r])&&Qa(e[n])&&(delete t[r],ae(UP(r)))}return t}const axe={vgMark:"arc",encodeEntry:e=>({...Ki(e,{align:"ignore",baseline:"ignore",color:"include",size:"ignore",orient:"ignore",theta:"ignore"}),...Sr("x",e,{defaultPos:"mid"}),...Sr("y",e,{defaultPos:"mid"}),...ba(e,"radius"),...ba(e,"theta")})},uxe={vgMark:"area",encodeEntry:e=>({...Ki(e,{align:"ignore",baseline:"ignore",color:"include",orient:"include",size:"ignore",theta:"ignore"}),...ry("x",e,{defaultPos:"zeroOrMin",defaultPos2:"zeroOrMin",range:e.markDef.orient==="horizontal"}),...ry("y",e,{defaultPos:"zeroOrMin",defaultPos2:"zeroOrMin",range:e.markDef.orient==="vertical"}),...j3(e)})},lxe={vgMark:"rect",encodeEntry:e=>({...Ki(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...ba(e,"x"),...ba(e,"y")})},cxe={vgMark:"shape",encodeEntry:e=>({...Ki(e,{align:"ignore",baseline:"ignore",color:"include",size:"ignore",orient:"ignore",theta:"ignore"})}),postEncodingTransform:e=>{const{encoding:t}=e,n=t.shape;return[{type:"geoshape",projection:e.projectionName(),...n&&ue(n)&&n.type===Bd?{field:pe(n,{expr:"datum"})}:{}}]}},fxe={vgMark:"image",encodeEntry:e=>({...Ki(e,{align:"ignore",baseline:"ignore",color:"ignore",orient:"ignore",size:"ignore",theta:"ignore"}),...ba(e,"x"),...ba(e,"y"),...B3(e,"url")})},dxe={vgMark:"line",encodeEntry:e=>({...Ki(e,{align:"ignore",baseline:"ignore",color:"include",size:"ignore",orient:"ignore",theta:"ignore"}),...Sr("x",e,{defaultPos:"mid"}),...Sr("y",e,{defaultPos:"mid"}),...Un("size",e,{vgChannel:"strokeWidth"}),...j3(e)})},hxe={vgMark:"trail",encodeEntry:e=>({...Ki(e,{align:"ignore",baseline:"ignore",color:"include",size:"include",orient:"ignore",theta:"ignore"}),...Sr("x",e,{defaultPos:"mid"}),...Sr("y",e,{defaultPos:"mid"}),...Un("size",e),...j3(e)})};function s$(e,t){const{config:n}=e;return{...Ki(e,{align:"ignore",baseline:"ignore",color:"include",size:"include",orient:"ignore",theta:"ignore"}),...Sr("x",e,{defaultPos:"mid"}),...Sr("y",e,{defaultPos:"mid"}),...Un("size",e),...Un("angle",e),...pxe(e,n,t)}}function pxe(e,t,n){return n?{shape:{value:n}}:Un("shape",e)}const gxe={vgMark:"symbol",encodeEntry:e=>s$(e)},mxe={vgMark:"symbol",encodeEntry:e=>s$(e,"circle")},yxe={vgMark:"symbol",encodeEntry:e=>s$(e,"square")},vxe={vgMark:"rect",encodeEntry:e=>({...Ki(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...ba(e,"x"),...ba(e,"y")})},bxe={vgMark:"rule",encodeEntry:e=>{const{markDef:t}=e,n=t.orient;return!e.encoding.x&&!e.encoding.y&&!e.encoding.latitude&&!e.encoding.longitude?{}:{...Ki(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...ry("x",e,{defaultPos:n==="horizontal"?"zeroOrMax":"mid",defaultPos2:"zeroOrMin",range:n!=="vertical"}),...ry("y",e,{defaultPos:n==="vertical"?"zeroOrMax":"mid",defaultPos2:"zeroOrMin",range:n!=="horizontal"}),...Un("size",e,{vgChannel:"strokeWidth"})}}},xxe={vgMark:"text",encodeEntry:e=>{const{config:t,encoding:n}=e;return{...Ki(e,{align:"include",baseline:"include",color:"include",size:"ignore",orient:"ignore",theta:"include"}),...Sr("x",e,{defaultPos:"mid"}),...Sr("y",e,{defaultPos:"mid"}),...B3(e),...Un("size",e,{vgChannel:"fontSize"}),...Un("angle",e),...y4("align",_xe(e.markDef,n,t)),...y4("baseline",wxe(e.markDef,n,t)),...Sr("radius",e,{defaultPos:null}),...Sr("theta",e,{defaultPos:null})}}};function _xe(e,t,n){if(wt("align",e,n)===void 0)return"center"}function wxe(e,t,n){if(wt("baseline",e,n)===void 0)return"middle"}const Exe={vgMark:"rect",encodeEntry:e=>{const{config:t,markDef:n}=e,r=n.orient,i=r==="horizontal"?"x":"y",s=r==="horizontal"?"y":"x",o=r==="horizontal"?"height":"width";return{...Ki(e,{align:"ignore",baseline:"ignore",color:"include",orient:"ignore",size:"ignore",theta:"ignore"}),...ba(e,i),...Sr(s,e,{defaultPos:"mid",vgChannel:s==="y"?"yc":"xc"}),[o]:Ot(wt("thickness",n,t))}}},O0={arc:axe,area:uxe,bar:lxe,circle:mxe,geoshape:cxe,image:fxe,line:dxe,point:gxe,rect:vxe,rule:bxe,square:yxe,text:xxe,tick:Exe,trail:hxe};function Axe(e){if(Qe([Xv,Yv,_0e],e.mark)){const t=BB(e.mark,e.encoding);if(t.length>0)return Sxe(e,t)}else if(e.mark===Vv){const t=qw.some(n=>wt(n,e.markDef,e.config));if(e.stack&&!e.fieldDef("size")&&t)return kxe(e)}return o$(e)}const W4="faceted_path_";function Sxe(e,t){return[{name:e.getName("pathgroup"),type:"group",from:{facet:{name:W4+e.requestDataName(Vt.Main),data:e.requestDataName(Vt.Main),groupby:t}},encode:{update:{width:{field:{group:"width"}},height:{field:{group:"height"}}}},marks:o$(e,{fromPrefix:W4})}]}const H4="stack_group_";function kxe(e){var l;const[t]=o$(e,{fromPrefix:H4}),n=e.scaleName(e.stack.fieldChannel),r=(c={})=>e.vgField(e.stack.fieldChannel,c),i=(c,f)=>{const d=[r({prefix:"min",suffix:"start",expr:f}),r({prefix:"max",suffix:"start",expr:f}),r({prefix:"min",suffix:"end",expr:f}),r({prefix:"max",suffix:"end",expr:f})];return`${c}(${d.map(h=>`scale('${n}',${h})`).join(",")})`};let s,o;e.stack.fieldChannel==="x"?(s={...td(t.encode.update,["y","yc","y2","height",...qw]),x:{signal:i("min","datum")},x2:{signal:i("max","datum")},clip:{value:!0}},o={x:{field:{group:"x"},mult:-1},height:{field:{group:"height"}}},t.encode.update={...Hr(t.encode.update,["y","yc","y2"]),height:{field:{group:"height"}}}):(s={...td(t.encode.update,["x","xc","x2","width"]),y:{signal:i("min","datum")},y2:{signal:i("max","datum")},clip:{value:!0}},o={y:{field:{group:"y"},mult:-1},width:{field:{group:"width"}}},t.encode.update={...Hr(t.encode.update,["x","xc","x2"]),width:{field:{group:"width"}}});for(const c of qw){const f=wo(c,e.markDef,e.config);t.encode.update[c]?(s[c]=t.encode.update[c],delete t.encode.update[c]):f&&(s[c]=Ot(f)),f&&(t.encode.update[c]={value:0})}const a=[];if(((l=e.stack.groupbyChannels)==null?void 0:l.length)>0)for(const c of e.stack.groupbyChannels){const f=e.fieldDef(c),d=pe(f);d&&a.push(d),(f!=null&&f.bin||f!=null&&f.timeUnit)&&a.push(pe(f,{binSuffix:"end"}))}return s=["stroke","strokeWidth","strokeJoin","strokeCap","strokeDash","strokeDashOffset","strokeMiterLimit","strokeOpacity"].reduce((c,f)=>{if(t.encode.update[f])return{...c,[f]:t.encode.update[f]};{const d=wo(f,e.markDef,e.config);return d!==void 0?{...c,[f]:Ot(d)}:c}},s),s.stroke&&(s.strokeForeground={value:!0},s.strokeOffset={value:0}),[{type:"group",from:{facet:{data:e.requestDataName(Vt.Main),name:H4+e.requestDataName(Vt.Main),groupby:a,aggregate:{fields:[r({suffix:"start"}),r({suffix:"start"}),r({suffix:"end"}),r({suffix:"end"})],ops:["min","max","min","max"]}}},encode:{update:s},marks:[{type:"group",encode:{update:o},marks:[t]}]}]}function Cxe(e){const{encoding:t,stack:n,mark:r,markDef:i,config:s}=e,o=t.order;if(!(!ee(o)&&$s(o)&&jw(o.value)||!o&&jw(wt("order",i,s)))){if((ee(o)||ue(o))&&!n)return NP(o,{expr:"datum"});if(Hu(r)){const a=i.orient==="horizontal"?"y":"x",u=t[a];if(ue(u))return{field:a}}}}function o$(e,t={fromPrefix:""}){const{mark:n,markDef:r,encoding:i,config:s}=e,o=un(r.clip,$xe(e),Fxe(e)),a=RP(r),u=i.key,l=Cxe(e),c=Dxe(e),f=wt("aria",r,s),d=O0[n].postEncodingTransform?O0[n].postEncodingTransform(e):null;return[{name:e.getName("marks"),type:O0[n].vgMark,...o?{clip:o}:{},...a?{style:a}:{},...u?{key:u.field}:{},...l?{sort:l}:{},...c||{},...f===!1?{aria:f}:{},from:{data:t.fromPrefix+e.requestDataName(Vt.Main)},encode:{update:O0[n].encodeEntry(e)},...d?{transform:d}:{}}]}function $xe(e){const t=e.getScaleComponent("x"),n=e.getScaleComponent("y");return t!=null&&t.get("selectionExtent")||n!=null&&n.get("selectionExtent")?!0:void 0}function Fxe(e){const t=e.component.projection;return t&&!t.isFit?!0:void 0}function Dxe(e){if(!e.component.selection)return null;const t=ie(e.component.selection).length;let n=t,r=e.parent;for(;r&&n===0;)n=ie(r.component.selection).length,r=r.parent;return n?{interactive:t>0||e.mark==="geoshape"||!!e.encoding.tooltip||!!e.markDef.tooltip}:null}class Ij extends Rj{constructor(t,n,r,i={},s){super(t,"unit",n,r,s,void 0,KM(t)?t.view:void 0),this.specifiedScales={},this.specifiedAxes={},this.specifiedLegends={},this.specifiedProjection={},this.selection=[],this.children=[],this.correctDataNames=l=>{var c,f,d;return(c=l.from)!=null&&c.data&&(l.from.data=this.lookupDataSource(l.from.data),"time"in this.encoding&&(l.from.data=l.from.data+xz)),(d=(f=l.from)==null?void 0:f.facet)!=null&&d.data&&(l.from.facet.data=this.lookupDataSource(l.from.facet.data)),l};const o=Eo(t.mark)?{...t.mark}:{type:t.mark},a=o.type;o.filled===void 0&&(o.filled=i1e(o,s,{graticule:t.data&&I3(t.data)}));const u=this.encoding=ume(t.encoding||{},a,o.filled,s);this.markDef=oz(o,u,s),this.size=oxe({encoding:u,size:KM(t)?{...i,...t.width?{width:t.width}:{},...t.height?{height:t.height}:{}}:i}),this.stack=sz(this.markDef,u),this.specifiedScales=this.initScales(a,u),this.specifiedAxes=this.initAxes(u),this.specifiedLegends=this.initLegends(u),this.specifiedProjection=t.projection,this.selection=(t.params??[]).filter(l=>R3(l))}get hasProjection(){const{encoding:t}=this,n=this.mark===fB,r=t&&epe.some(i=>Ue(t[i]));return n||r}scaleDomain(t){const n=this.specifiedScales[t];return n?n.domain:void 0}axis(t){return this.specifiedAxes[t]}legend(t){return this.specifiedLegends[t]}initScales(t,n){return VC.reduce((r,i)=>{const s=yn(n[i]);return s&&(r[i]=this.initScale(s.scale??{})),r},{})}initScale(t){const{domain:n,range:r}=t,i=zn(t);return ee(n)&&(i.domain=n.map(li)),ee(r)&&(i.range=r.map(li)),i}initAxes(t){return Ca.reduce((n,r)=>{const i=t[r];if(Ue(i)||r===qt&&Ue(t.x2)||r===On&&Ue(t.y2)){const s=Ue(i)?i.axis:void 0;n[r]=s&&this.initAxis({...s})}return n},{})}initAxis(t){const n=ie(t),r={};for(const i of n){const s=t[i];r[i]=Hg(s)?MP(s):li(s)}return r}initLegends(t){return fpe.reduce((n,r)=>{const i=yn(t[r]);if(i&&hpe(r)){const s=i.legend;n[r]=s&&zn(s)}return n},{})}parseData(){this.component.data=Cb(this)}parseLayoutSize(){q2e(this)}parseSelections(){this.component.selection=Tve(this,this.selection)}parseMarkGroup(){this.component.mark=Axe(this)}parseAxesAndHeaders(){this.component.axes=J2e(this)}assembleSelectionTopLevelSignals(t){return Z1e(this,t)}assembleSignals(){return[...Jz(this),...X1e(this,[])]}assembleSelectionData(t){return J1e(this,t)}assembleLayout(){return null}assembleLayoutSignals(){return V3(this)}assembleMarks(){let t=this.component.mark??[];return(!this.parent||!Wd(this.parent))&&(t=Az(this,t)),t.map(this.correctDataNames)}assembleGroupStyle(){const{style:t}=this.view||{};return t!==void 0?t:this.encoding.x||this.encoding.y?"cell":"view"}getMapping(){return this.encoding}get mark(){return this.markDef.type}channelHasField(t){return Rl(this.encoding,t)}fieldDef(t){const n=this.encoding[t];return Fs(n)}typedFieldDef(t){const n=this.fieldDef(t);return Dr(n)?n:null}}class a$ extends n${constructor(t,n,r,i,s){super(t,"layer",n,r,s,t.resolve,t.view);const o={...i,...t.width?{width:t.width}:{},...t.height?{height:t.height}:{}};this.children=t.layer.map((a,u)=>{if(sb(a))return new a$(a,this,this.getName(`layer_${u}`),o,s);if($a(a))return new Ij(a,this,this.getName(`layer_${u}`),o,s);throw new Error(KC(a))})}parseData(){this.component.data=Cb(this);for(const t of this.children)t.parseData()}parseLayoutSize(){j2e(this)}parseSelections(){this.component.selection={};for(const t of this.children){t.parseSelections();for(const n of ie(t.component.selection))this.component.selection[n]=t.component.selection[n]}Object.values(this.component.selection).some(t=>ho(t))&&QC(JC)}parseMarkGroup(){for(const t of this.children)t.parseMarkGroup()}parseAxesAndHeaders(){exe(this)}assembleSelectionTopLevelSignals(t){return this.children.reduce((n,r)=>r.assembleSelectionTopLevelSignals(n),t)}assembleSignals(){return this.children.reduce((t,n)=>t.concat(n.assembleSignals()),Jz(this))}assembleLayoutSignals(){return this.children.reduce((t,n)=>t.concat(n.assembleLayoutSignals()),V3(this))}assembleSelectionData(t){return this.children.reduce((n,r)=>r.assembleSelectionData(n),t)}assembleGroupStyle(){const t=new Set;for(const r of this.children)for(const i of ye(r.assembleGroupStyle()))t.add(i);const n=Array.from(t);return n.length>1?n:n.length===1?n[0]:void 0}assembleTitle(){let t=super.assembleTitle();if(t)return t;for(const n of this.children)if(t=n.assembleTitle(),t)return t}assembleLayout(){return null}assembleMarks(){return Q1e(this,this.children.flatMap(t=>t.assembleMarks()))}assembleLegends(){return this.children.reduce((t,n)=>t.concat(n.assembleLegends()),gj(this))}}function u$(e,t,n,r,i){if(Jv(e))return new lp(e,t,n,i);if(sb(e))return new a$(e,t,n,r,i);if($a(e))return new Ij(e,t,n,r,i);if(Rme(e))return new V2e(e,t,n,i);throw new Error(KC(e))}function Mxe(e,t={}){t.logger&&Oge(t.logger),t.fieldTitle&&FB(t.fieldTitle);try{const n=iz(xd(t.config,e.config)),r=hz(e,n),i=u$(r,null,"",void 0,n);return i.parse(),t2e(i.component.data,i),{spec:Txe(i,Rxe(e,r.autosize,n,i),e.datasets,e.usermeta),normalized:r}}finally{t.logger&&Lge(),t.fieldTitle&&Q0e()}}function Rxe(e,t,n,r){const i=r.component.layoutSize.get("width"),s=r.component.layoutSize.get("height");if(t===void 0?(t={type:"pad"},r.hasAxisOrientSignalRef()&&(t.resize=!0)):me(t)&&(t={type:t}),i&&s&&B1e(t.type)){if(i==="step"&&s==="step")ae(NM()),t.type="pad";else if(i==="step"||s==="step"){const o=i==="step"?"width":"height";ae(NM(jv(o)));const a=o==="width"?"height":"width";t.type=z1e(a)}}return{...ie(t).length===1&&t.type?t.type==="pad"?{}:{autosize:t.type}:{autosize:t},...u4(n,!1),...u4(e,!0)}}function Txe(e,t,n={},r){const i=e.config?Gme(e.config):void 0,s=I2e(e.component.data,n),o=e.assembleSelectionData(s),a=e.assembleProjections(),u=e.assembleTitle(),l=e.assembleGroupStyle(),c=e.assembleGroupEncodeEntry(!0);let f=e.assembleLayoutSignals();f=f.filter(p=>(p.name==="width"||p.name==="height")&&p.value!==void 0?(t[p.name]=+p.value,!1):!0);const{params:d,...h}=t;return{$schema:"https://vega.github.io/schema/vega/v5.json",...e.description?{description:e.description}:{},...h,...u?{title:u}:{},...l?{style:l}:{},...c?{encode:{update:c}}:{},data:o,...a.length>0?{projections:a}:{},...e.assembleGroup([...f,...e.assembleSelectionTopLevelSignals([]),...ez(d)]),...i?{config:i}:{},...r?{usermeta:r}:{}}}const Nxe=Vhe.version,Oxe=Object.freeze(Object.defineProperty({__proto__:null,accessPathDepth:rd,accessPathWithDatum:zC,accessWithDatumToUnescapedPath:vt,compile:Mxe,contains:Qe,deepEqual:fi,deleteNestedProperty:Y1,duplicate:Be,entries:_u,every:IC,fieldIntersection:BC,flatAccessWithDatum:dP,getFirstDefined:un,hasIntersection:PC,hasProperty:oe,hash:rt,internalField:gP,isBoolean:Op,isEmpty:Et,isEqual:Khe,isInternalField:mP,isNullOrFalse:jw,isNumeric:Ov,keys:ie,logicalExpr:op,mergeDeep:cP,never:lP,normalize:hz,normalizeAngle:Lp,omit:Hr,pick:td,prefixGenerator:Uw,removePathFromField:Id,replaceAll:nc,replacePathInField:Gi,resetIdCounter:Jhe,setEqual:fP,some:nd,stringify:At,titleCase:Ng,unique:oo,uniqueId:pP,vals:Yn,varName:Ut,version:Nxe},Symbol.toStringTag,{value:"Module"}));function Pj(e){const[t,n]=/schema\/([\w-]+)\/([\w\.\-]+)\.json$/g.exec(e).slice(1,3);return{library:t,version:n}}var Lxe="2.15.0",Ixe={version:Lxe};const Yc="#fff",G4="#888",Pxe={background:"#333",view:{stroke:G4},title:{color:Yc,subtitleColor:Yc},style:{"guide-label":{fill:Yc},"guide-title":{fill:Yc}},axis:{domainColor:Yc,gridColor:G4,tickColor:Yc}},Zu="#4572a7",Bxe={background:"#fff",arc:{fill:Zu},area:{fill:Zu},line:{stroke:Zu,strokeWidth:2},path:{stroke:Zu},rect:{fill:Zu},shape:{stroke:Zu},symbol:{fill:Zu,strokeWidth:1.5,size:50},axis:{bandPosition:.5,grid:!0,gridColor:"#000000",gridOpacity:1,gridWidth:.5,labelPadding:10,tickSize:5,tickWidth:.5},axisBand:{grid:!1,tickExtra:!0},legend:{labelBaseline:"middle",labelFontSize:11,symbolSize:50,symbolType:"square"},range:{category:["#4572a7","#aa4643","#8aa453","#71598e","#4598ae","#d98445","#94aace","#d09393","#b9cc98","#a99cbc"]}},Ju="#30a2da",gx="#cbcbcb",zxe="#999",jxe="#333",Y4="#f0f0f0",V4="#333",Uxe={arc:{fill:Ju},area:{fill:Ju},axis:{domainColor:gx,grid:!0,gridColor:gx,gridWidth:1,labelColor:zxe,labelFontSize:10,titleColor:jxe,tickColor:gx,tickSize:10,titleFontSize:14,titlePadding:10,labelPadding:4},axisBand:{grid:!1},background:Y4,group:{fill:Y4},legend:{labelColor:V4,labelFontSize:11,padding:1,symbolSize:30,symbolType:"square",titleColor:V4,titleFontSize:14,titlePadding:10},line:{stroke:Ju,strokeWidth:2},path:{stroke:Ju,strokeWidth:.5},rect:{fill:Ju},range:{category:["#30a2da","#fc4f30","#e5ae38","#6d904f","#8b8b8b","#b96db8","#ff9e27","#56cc60","#52d2ca","#52689e","#545454","#9fe4f8"],diverging:["#cc0020","#e77866","#f6e7e1","#d6e8ed","#91bfd9","#1d78b5"],heatmap:["#d6e8ed","#cee0e5","#91bfd9","#549cc6","#1d78b5"]},point:{filled:!0,shape:"circle"},shape:{stroke:Ju},bar:{binSpacing:2,fill:Ju,stroke:null},title:{anchor:"start",fontSize:24,fontWeight:600,offset:20}},Qu="#000",qxe={group:{fill:"#e5e5e5"},arc:{fill:Qu},area:{fill:Qu},line:{stroke:Qu},path:{stroke:Qu},rect:{fill:Qu},shape:{stroke:Qu},symbol:{fill:Qu,size:40},axis:{domain:!1,grid:!0,gridColor:"#FFFFFF",gridOpacity:1,labelColor:"#7F7F7F",labelPadding:4,tickColor:"#7F7F7F",tickSize:5.67,titleFontSize:16,titleFontWeight:"normal"},legend:{labelBaseline:"middle",labelFontSize:11,symbolSize:40},range:{category:["#000000","#7F7F7F","#1A1A1A","#999999","#333333","#B0B0B0","#4D4D4D","#C9C9C9","#666666","#DCDCDC"]}},Wxe=22,Hxe="normal",X4="Benton Gothic, sans-serif",K4=11.5,Gxe="normal",el="#82c6df",mx="Benton Gothic Bold, sans-serif",Z4="normal",J4=13,gh={"category-6":["#ec8431","#829eb1","#c89d29","#3580b1","#adc839","#ab7fb4"],"fire-7":["#fbf2c7","#f9e39c","#f8d36e","#f4bb6a","#e68a4f","#d15a40","#ab4232"],"fireandice-6":["#e68a4f","#f4bb6a","#f9e39c","#dadfe2","#a6b7c6","#849eae"]},Yxe={background:"#ffffff",title:{anchor:"start",color:"#000000",font:mx,fontSize:Wxe,fontWeight:Hxe},arc:{fill:el},area:{fill:el},line:{stroke:el,strokeWidth:2},path:{stroke:el},rect:{fill:el},shape:{stroke:el},symbol:{fill:el,size:30},axis:{labelFont:X4,labelFontSize:K4,labelFontWeight:Gxe,titleFont:mx,titleFontSize:J4,titleFontWeight:Z4},axisX:{labelAngle:0,labelPadding:4,tickSize:3},axisY:{labelBaseline:"middle",maxExtent:45,minExtent:45,tickSize:2,titleAlign:"left",titleAngle:0,titleX:-45,titleY:-11},legend:{labelFont:X4,labelFontSize:K4,symbolType:"square",titleFont:mx,titleFontSize:J4,titleFontWeight:Z4},range:{category:gh["category-6"],diverging:gh["fireandice-6"],heatmap:gh["fire-7"],ordinal:gh["fire-7"],ramp:gh["fire-7"]}},tl="#ab5787",L0="#979797",Vxe={background:"#f9f9f9",arc:{fill:tl},area:{fill:tl},line:{stroke:tl},path:{stroke:tl},rect:{fill:tl},shape:{stroke:tl},symbol:{fill:tl,size:30},axis:{domainColor:L0,domainWidth:.5,gridWidth:.2,labelColor:L0,tickColor:L0,tickWidth:.2,titleColor:L0},axisBand:{grid:!1},axisX:{grid:!0,tickSize:10},axisY:{domain:!1,grid:!0,tickSize:0},legend:{labelFontSize:11,padding:1,symbolSize:30,symbolType:"square"},range:{category:["#ab5787","#51b2e5","#703c5c","#168dd9","#d190b6","#00609f","#d365ba","#154866","#666666","#c4c4c4"]}},nl="#3e5c69",Xxe={background:"#fff",arc:{fill:nl},area:{fill:nl},line:{stroke:nl},path:{stroke:nl},rect:{fill:nl},shape:{stroke:nl},symbol:{fill:nl},axis:{domainWidth:.5,grid:!0,labelPadding:2,tickSize:5,tickWidth:.5,titleFontWeight:"normal"},axisBand:{grid:!1},axisX:{gridWidth:.2},axisY:{gridDash:[3],gridWidth:.4},legend:{labelFontSize:11,padding:1,symbolType:"square"},range:{category:["#3e5c69","#6793a6","#182429","#0570b0","#3690c0","#74a9cf","#a6bddb","#e2ddf2"]}},Ai="#1696d2",Q4="#000000",Kxe="#FFFFFF",I0="Lato",yx="Lato",Zxe="Lato",Jxe="#DEDDDD",Qxe=18,mh={"shades-blue":["#CFE8F3","#A2D4EC","#73BFE2","#46ABDB","#1696D2","#12719E","#0A4C6A","#062635"],"six-groups-cat-1":["#1696d2","#ec008b","#fdbf11","#000000","#d2d2d2","#55b748"],"six-groups-seq":["#cfe8f3","#a2d4ec","#73bfe2","#46abdb","#1696d2","#12719e"],"diverging-colors":["#ca5800","#fdbf11","#fdd870","#fff2cf","#cfe8f3","#73bfe2","#1696d2","#0a4c6a"]},e_e={background:Kxe,title:{anchor:"start",fontSize:Qxe,font:I0},axisX:{domain:!0,domainColor:Q4,domainWidth:1,grid:!1,labelFontSize:12,labelFont:yx,labelAngle:0,tickColor:Q4,tickSize:5,titleFontSize:12,titlePadding:10,titleFont:I0},axisY:{domain:!1,domainWidth:1,grid:!0,gridColor:Jxe,gridWidth:1,labelFontSize:12,labelFont:yx,labelPadding:8,ticks:!1,titleFontSize:12,titlePadding:10,titleFont:I0,titleAngle:0,titleY:-10,titleX:18},legend:{labelFontSize:12,labelFont:yx,symbolSize:100,titleFontSize:12,titlePadding:10,titleFont:I0,orient:"right",offset:10},view:{stroke:"transparent"},range:{category:mh["six-groups-cat-1"],diverging:mh["diverging-colors"],heatmap:mh["diverging-colors"],ordinal:mh["six-groups-seq"],ramp:mh["shades-blue"]},area:{fill:Ai},rect:{fill:Ai},line:{color:Ai,stroke:Ai,strokeWidth:5},trail:{color:Ai,stroke:Ai,strokeWidth:0,size:1},path:{stroke:Ai,strokeWidth:.5},point:{filled:!0},text:{font:Zxe,color:Ai,fontSize:11,align:"center",fontWeight:400,size:11},style:{bar:{fill:Ai,stroke:null}},arc:{fill:Ai},shape:{stroke:Ai},symbol:{fill:Ai,size:30}},rl="#3366CC",e6="#ccc",P0="Arial, sans-serif",t_e={arc:{fill:rl},area:{fill:rl},path:{stroke:rl},rect:{fill:rl},shape:{stroke:rl},symbol:{stroke:rl},circle:{fill:rl},background:"#fff",padding:{top:10,right:10,bottom:10,left:10},style:{"guide-label":{font:P0,fontSize:12},"guide-title":{font:P0,fontSize:12},"group-title":{font:P0,fontSize:12}},title:{font:P0,fontSize:14,fontWeight:"bold",dy:-3,anchor:"start"},axis:{gridColor:e6,tickColor:e6,domain:!1,grid:!0},range:{category:["#4285F4","#DB4437","#F4B400","#0F9D58","#AB47BC","#00ACC1","#FF7043","#9E9D24","#5C6BC0","#F06292","#00796B","#C2185B"],heatmap:["#c6dafc","#5e97f6","#2a56c6"]}},l$=e=>e*(1/3+1),t6=l$(9),n6=l$(10),r6=l$(12),yh="Segoe UI",i6="wf_standard-font, helvetica, arial, sans-serif",s6="#252423",vh="#605E5C",o6="transparent",n_e="#C8C6C4",ns="#118DFF",r_e="#12239E",i_e="#E66C37",s_e="#6B007B",o_e="#E044A7",a_e="#744EC2",u_e="#D9B300",l_e="#D64550",Bj=ns,zj="#DEEFFF",a6=[zj,Bj],c_e=[zj,"#c7e4ff","#b0d9ff","#9aceff","#83c3ff","#6cb9ff","#55aeff","#3fa3ff","#2898ff",Bj],f_e={view:{stroke:o6},background:o6,font:yh,header:{titleFont:i6,titleFontSize:r6,titleColor:s6,labelFont:yh,labelFontSize:n6,labelColor:vh},axis:{ticks:!1,grid:!1,domain:!1,labelColor:vh,labelFontSize:t6,titleFont:i6,titleColor:s6,titleFontSize:r6,titleFontWeight:"normal"},axisQuantitative:{tickCount:3,grid:!0,gridColor:n_e,gridDash:[1,5],labelFlush:!1},axisBand:{tickExtra:!0},axisX:{labelPadding:5},axisY:{labelPadding:10},bar:{fill:ns},line:{stroke:ns,strokeWidth:3,strokeCap:"round",strokeJoin:"round"},text:{font:yh,fontSize:t6,fill:vh},arc:{fill:ns},area:{fill:ns,line:!0,opacity:.6},path:{stroke:ns},rect:{fill:ns},point:{fill:ns,filled:!0,size:75},shape:{stroke:ns},symbol:{fill:ns,strokeWidth:1.5,size:50},legend:{titleFont:yh,titleFontWeight:"bold",titleColor:vh,labelFont:yh,labelFontSize:n6,labelColor:vh,symbolType:"circle",symbolSize:75},range:{category:[ns,r_e,i_e,s_e,o_e,a_e,u_e,l_e],diverging:a6,heatmap:a6,ordinal:c_e}},vx='IBM Plex Sans,system-ui,-apple-system,BlinkMacSystemFont,".sfnstext-regular",sans-serif',d_e='IBM Plex Sans Condensed, system-ui, -apple-system, BlinkMacSystemFont, ".SFNSText-Regular", sans-serif',bx=400,B0={textPrimary:{g90:"#f4f4f4",g100:"#f4f4f4",white:"#161616",g10:"#161616"},textSecondary:{g90:"#c6c6c6",g100:"#c6c6c6",white:"#525252",g10:"#525252"},layerAccent01:{white:"#e0e0e0",g10:"#e0e0e0",g90:"#525252",g100:"#393939"},gridBg:{white:"#ffffff",g10:"#ffffff",g90:"#161616",g100:"#161616"}},h_e=["#8a3ffc","#33b1ff","#007d79","#ff7eb6","#fa4d56","#fff1f1","#6fdc8c","#4589ff","#d12771","#d2a106","#08bdba","#bae6ff","#ba4e00","#d4bbff"],p_e=["#6929c4","#1192e8","#005d5d","#9f1853","#fa4d56","#570408","#198038","#002d9c","#ee538b","#b28600","#009d9a","#012749","#8a3800","#a56eff"];function $b({theme:e,background:t}){const n=["white","g10"].includes(e)?"light":"dark",r=B0.gridBg[e],i=B0.textPrimary[e],s=B0.textSecondary[e],o=n==="dark"?h_e:p_e,a=n==="dark"?"#d4bbff":"#6929c4";return{background:t,arc:{fill:a},area:{fill:a},path:{stroke:a},rect:{fill:a},shape:{stroke:a},symbol:{stroke:a},circle:{fill:a},view:{fill:r,stroke:r},group:{fill:r},title:{color:i,anchor:"start",dy:-15,fontSize:16,font:vx,fontWeight:600},axis:{labelColor:s,labelFontSize:12,labelFont:d_e,labelFontWeight:bx,titleColor:i,titleFontWeight:600,titleFontSize:12,grid:!0,gridColor:B0.layerAccent01[e],labelAngle:0},axisX:{titlePadding:10},axisY:{titlePadding:2.5},style:{"guide-label":{font:vx,fill:s,fontWeight:bx},"guide-title":{font:vx,fill:s,fontWeight:bx}},range:{category:o,diverging:["#750e13","#a2191f","#da1e28","#fa4d56","#ff8389","#ffb3b8","#ffd7d9","#fff1f1","#e5f6ff","#bae6ff","#82cfff","#33b1ff","#1192e8","#0072c3","#00539a","#003a6d"],heatmap:["#f6f2ff","#e8daff","#d4bbff","#be95ff","#a56eff","#8a3ffc","#6929c4","#491d8b","#31135e","#1c0f30"]}}}const g_e=$b({theme:"white",background:"#ffffff"}),m_e=$b({theme:"g10",background:"#f4f4f4"}),y_e=$b({theme:"g90",background:"#262626"}),v_e=$b({theme:"g100",background:"#161616"}),b_e=Ixe.version,x_e=Object.freeze(Object.defineProperty({__proto__:null,carbong10:m_e,carbong100:v_e,carbong90:y_e,carbonwhite:g_e,dark:Pxe,excel:Bxe,fivethirtyeight:Uxe,ggplot2:qxe,googlecharts:t_e,latimes:Yxe,powerbi:f_e,quartz:Vxe,urbaninstitute:e_e,version:b_e,vox:Xxe},Symbol.toStringTag,{value:"Module"}));function __e(e,t,n,r){if(ee(e))return`[${e.map(i=>t(me(i)?i:u6(i,n))).join(", ")}]`;if(ge(e)){let i="";const{title:s,image:o,...a}=e;s&&(i+=`

      ${t(s)}

      `),o&&(i+=``);const u=Object.keys(a);if(u.length>0){i+="";for(const l of u){let c=a[l];c!==void 0&&(ge(c)&&(c=u6(c,n)),i+=``)}i+="
      ${t(l)}${t(c)}
      "}return i||"{}"}return t(e)}function w_e(e){const t=[];return function(n,r){if(typeof r!="object"||r===null)return r;const i=t.indexOf(this)+1;return t.length=i,t.length>e?"[Object]":t.indexOf(r)>=0?"[Circular]":(t.push(r),r)}}function u6(e,t){return JSON.stringify(e,w_e(t))}var E_e=`#vg-tooltip-element { + visibility: hidden; + padding: 8px; + position: fixed; + z-index: 1000; + font-family: sans-serif; + font-size: 11px; + border-radius: 3px; + box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); + /* The default theme is the light theme. */ + background-color: rgba(255, 255, 255, 0.95); + border: 1px solid #d9d9d9; + color: black; +} +#vg-tooltip-element.visible { + visibility: visible; +} +#vg-tooltip-element h2 { + margin-top: 0; + margin-bottom: 10px; + font-size: 13px; +} +#vg-tooltip-element table { + border-spacing: 0; +} +#vg-tooltip-element table tr { + border: none; +} +#vg-tooltip-element table tr td { + overflow: hidden; + text-overflow: ellipsis; + padding-top: 2px; + padding-bottom: 2px; +} +#vg-tooltip-element table tr td.key { + color: #808080; + max-width: 150px; + text-align: right; + padding-right: 4px; +} +#vg-tooltip-element table tr td.value { + display: block; + max-width: 300px; + max-height: 7em; + text-align: left; +} +#vg-tooltip-element.dark-theme { + background-color: rgba(32, 32, 32, 0.9); + border: 1px solid #f5f5f5; + color: white; +} +#vg-tooltip-element.dark-theme td.key { + color: #bfbfbf; +} +`;const jj="vg-tooltip-element",A_e={offsetX:10,offsetY:10,id:jj,styleId:"vega-tooltip-style",theme:"light",disableDefaultStyle:!1,sanitize:S_e,maxDepth:2,formatTooltip:__e,baseURL:"",anchor:"cursor",position:["top","bottom","left","right","top-left","top-right","bottom-left","bottom-right"]};function S_e(e){return String(e).replace(/&/g,"&").replace(/=0&&e.y>=0&&e.x+t.width<=window.innerWidth&&e.y+t.height<=window.innerHeight}function F_e(e,t,n){return e.clientX>=t.x&&e.clientX<=t.x+n.width&&e.clientY>=t.y&&e.clientY<=t.y+n.height}class D_e{constructor(t){this.options={...A_e,...t};const n=this.options.id;if(this.el=null,this.call=this.tooltipHandler.bind(this),!this.options.disableDefaultStyle&&!document.getElementById(this.options.styleId)){const r=document.createElement("style");r.setAttribute("id",this.options.styleId),r.innerHTML=k_e(n);const i=document.head;i.childNodes.length>0?i.insertBefore(r,i.childNodes[0]):i.appendChild(r)}}tooltipHandler(t,n,r,i){if(this.el=document.getElementById(this.options.id),this.el||(this.el=document.createElement("div"),this.el.setAttribute("id",this.options.id),this.el.classList.add("vg-tooltip"),(document.fullscreenElement??document.body).appendChild(this.el)),i==null||i===""){this.el.classList.remove("visible",`${this.options.theme}-theme`);return}this.el.innerHTML=this.options.formatTooltip(i,this.options.sanitize,this.options.maxDepth,this.options.baseURL),this.el.classList.add("visible",`${this.options.theme}-theme`);const{x:s,y:o}=this.options.anchor==="mark"?C_e(t,n,r,this.el.getBoundingClientRect(),this.options):Uj(n,this.el.getBoundingClientRect(),this.options);this.el.style.top=`${o}px`,this.el.style.left=`${s}px`}}var xx={};/*! + * https://github.com/Starcounter-Jack/JSON-Patch + * (c) 2017-2022 Joachim Wester + * MIT licensed + */var M_e=(function(){var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(r,i){r.__proto__=i}||function(r,i){for(var s in i)i.hasOwnProperty(s)&&(r[s]=i[s])},e(t,n)};return function(t,n){e(t,n);function r(){this.constructor=t}t.prototype=n===null?Object.create(n):(r.prototype=n.prototype,new r)}})(),R_e=Object.prototype.hasOwnProperty;function yE(e,t){return R_e.call(e,t)}function vE(e){if(Array.isArray(e)){for(var t=new Array(e.length),n=0;n=48&&r<=57){t++;continue}return!1}return!0}function ol(e){return e.indexOf("/")===-1&&e.indexOf("~")===-1?e:e.replace(/~/g,"~0").replace(/\//g,"~1")}function Hj(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function xE(e){if(e===void 0)return!0;if(e){if(Array.isArray(e)){for(var t=0,n=e.length;t0&&u[c-1]=="constructor"))throw new TypeError("JSON-Patch: modifying `__proto__` or `constructor/prototype` prop is banned for security reasons, if this was on purpose, please set `banPrototypeModifications` flag false and pass it to this function. More info in fast-json-patch README");if(n&&d===void 0&&(l[h]===void 0?d=u.slice(0,c).join("/"):c==f-1&&(d=t.path),d!==void 0&&p(t,0,e,d)),c++,Array.isArray(l)){if(h==="-")h=l.length;else{if(n&&!bE(h))throw new Zt("Expected an unsigned base-10 integer value, making the new referenced value the array element with the zero-based index","OPERATION_PATH_ILLEGAL_ARRAY_INDEX",s,t,e);bE(h)&&(h=~~h)}if(c>=f){if(n&&t.op==="add"&&h>l.length)throw new Zt("The specified index MUST NOT be greater than the number of elements in the array","OPERATION_VALUE_OUT_OF_BOUNDS",s,t,e);var o=N_e[t.op].call(t,l,h,e);if(o.test===!1)throw new Zt("Test operation failed","TEST_OPERATION_FAILED",s,t,e);return o}}else if(c>=f){var o=af[t.op].call(t,l,h,e);if(o.test===!1)throw new Zt("Test operation failed","TEST_OPERATION_FAILED",s,t,e);return o}if(l=l[h],n&&c0)throw new Zt('Operation `path` property must start with "/"',"OPERATION_PATH_INVALID",t,e,n);if((e.op==="move"||e.op==="copy")&&typeof e.from!="string")throw new Zt("Operation `from` property is not present (applicable in `move` and `copy` operations)","OPERATION_FROM_REQUIRED",t,e,n);if((e.op==="add"||e.op==="replace"||e.op==="test")&&e.value===void 0)throw new Zt("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_REQUIRED",t,e,n);if((e.op==="add"||e.op==="replace"||e.op==="test")&&xE(e.value))throw new Zt("Operation `value` property is not present (applicable in `add`, `replace` and `test` operations)","OPERATION_VALUE_CANNOT_CONTAIN_UNDEFINED",t,e,n);if(n){if(e.op=="add"){var i=e.path.split("/").length,s=r.split("/").length;if(i!==s+1&&i!==s)throw new Zt("Cannot perform an `add` operation at the desired path","OPERATION_PATH_CANNOT_ADD",t,e,n)}else if(e.op==="replace"||e.op==="remove"||e.op==="_get"){if(e.path!==r)throw new Zt("Cannot perform the operation at a path that does not exist","OPERATION_PATH_UNRESOLVABLE",t,e,n)}else if(e.op==="move"||e.op==="copy"){var o={op:"_get",path:e.from,value:void 0},a=Yj([o],n);if(a&&a.name==="OPERATION_PATH_UNRESOLVABLE")throw new Zt("Cannot perform the operation from a path that does not exist","OPERATION_FROM_UNRESOLVABLE",t,e,n)}}}else throw new Zt("Operation `op` property is not one of operations defined in RFC-6902","OPERATION_OP_INVALID",t,e,n)}function Yj(e,t,n){try{if(!Array.isArray(e))throw new Zt("Patch sequence must be an array","SEQUENCE_NOT_AN_ARRAY");if(t)Fb(di(t),di(e),n||!0);else{n=n||ly;for(var r=0;r0&&(e.patches=[],e.callback&&e.callback(r)),r}function f$(e,t,n,r,i){if(t!==e){typeof t.toJSON=="function"&&(t=t.toJSON());for(var s=vE(t),o=vE(e),a=!1,u=o.length-1;u>=0;u--){var l=o[u],c=e[l];if(yE(t,l)&&!(t[l]===void 0&&c!==void 0&&Array.isArray(t)===!1)){var f=t[l];typeof c=="object"&&c!=null&&typeof f=="object"&&f!=null&&Array.isArray(c)===Array.isArray(f)?f$(c,f,n,r+"/"+ol(l),i):c!==f&&(i&&n.push({op:"test",path:r+"/"+ol(l),value:di(c)}),n.push({op:"replace",path:r+"/"+ol(l),value:di(f)}))}else Array.isArray(e)===Array.isArray(t)?(i&&n.push({op:"test",path:r+"/"+ol(l),value:di(c)}),n.push({op:"remove",path:r+"/"+ol(l)}),a=!0):(i&&n.push({op:"test",path:r,value:e}),n.push({op:"replace",path:r,value:t}))}if(!(!a&&s.length==o.length))for(var u=0;u=this.max){const s=this.map.keys().next().value;this.delete(s)}this.map.set(n,r)}return this}}return _x=e,_x}var wx,f6;function d$(){if(f6)return wx;f6=1;const e=Object.freeze({loose:!0}),t=Object.freeze({});return wx=r=>r?typeof r!="object"?e:r:t,wx}var z0={exports:{}},Ex,d6;function h$(){if(d6)return Ex;d6=1;const e="2.0.0",t=256,n=Number.MAX_SAFE_INTEGER||9007199254740991,r=16,i=t-6;return Ex={MAX_LENGTH:t,MAX_SAFE_COMPONENT_LENGTH:r,MAX_SAFE_BUILD_LENGTH:i,MAX_SAFE_INTEGER:n,RELEASE_TYPES:["major","premajor","minor","preminor","patch","prepatch","prerelease"],SEMVER_SPEC_VERSION:e,FLAG_INCLUDE_PRERELEASE:1,FLAG_LOOSE:2},Ex}var Ax,h6;function Db(){return h6||(h6=1,Ax=typeof process=="object"&&xx&&xx.NODE_DEBUG&&/\bsemver\b/i.test(xx.NODE_DEBUG)?(...t)=>console.error("SEMVER",...t):()=>{}),Ax}var p6;function p$(){return p6||(p6=1,(function(e,t){const{MAX_SAFE_COMPONENT_LENGTH:n,MAX_SAFE_BUILD_LENGTH:r,MAX_LENGTH:i}=h$(),s=Db();t=e.exports={};const o=t.re=[],a=t.safeRe=[],u=t.src=[],l=t.t={};let c=0;const f="[a-zA-Z0-9-]",d=[["\\s",1],["\\d",i],[f,r]],h=g=>{for(const[m,y]of d)g=g.split(`${m}*`).join(`${m}{0,${y}}`).split(`${m}+`).join(`${m}{1,${y}}`);return g},p=(g,m,y)=>{const v=h(m),b=c++;s(g,b,m),l[g]=b,u[b]=m,o[b]=new RegExp(m,y?"g":void 0),a[b]=new RegExp(v,y?"g":void 0)};p("NUMERICIDENTIFIER","0|[1-9]\\d*"),p("NUMERICIDENTIFIERLOOSE","\\d+"),p("NONNUMERICIDENTIFIER",`\\d*[a-zA-Z-]${f}*`),p("MAINVERSION",`(${u[l.NUMERICIDENTIFIER]})\\.(${u[l.NUMERICIDENTIFIER]})\\.(${u[l.NUMERICIDENTIFIER]})`),p("MAINVERSIONLOOSE",`(${u[l.NUMERICIDENTIFIERLOOSE]})\\.(${u[l.NUMERICIDENTIFIERLOOSE]})\\.(${u[l.NUMERICIDENTIFIERLOOSE]})`),p("PRERELEASEIDENTIFIER",`(?:${u[l.NUMERICIDENTIFIER]}|${u[l.NONNUMERICIDENTIFIER]})`),p("PRERELEASEIDENTIFIERLOOSE",`(?:${u[l.NUMERICIDENTIFIERLOOSE]}|${u[l.NONNUMERICIDENTIFIER]})`),p("PRERELEASE",`(?:-(${u[l.PRERELEASEIDENTIFIER]}(?:\\.${u[l.PRERELEASEIDENTIFIER]})*))`),p("PRERELEASELOOSE",`(?:-?(${u[l.PRERELEASEIDENTIFIERLOOSE]}(?:\\.${u[l.PRERELEASEIDENTIFIERLOOSE]})*))`),p("BUILDIDENTIFIER",`${f}+`),p("BUILD",`(?:\\+(${u[l.BUILDIDENTIFIER]}(?:\\.${u[l.BUILDIDENTIFIER]})*))`),p("FULLPLAIN",`v?${u[l.MAINVERSION]}${u[l.PRERELEASE]}?${u[l.BUILD]}?`),p("FULL",`^${u[l.FULLPLAIN]}$`),p("LOOSEPLAIN",`[v=\\s]*${u[l.MAINVERSIONLOOSE]}${u[l.PRERELEASELOOSE]}?${u[l.BUILD]}?`),p("LOOSE",`^${u[l.LOOSEPLAIN]}$`),p("GTLT","((?:<|>)?=?)"),p("XRANGEIDENTIFIERLOOSE",`${u[l.NUMERICIDENTIFIERLOOSE]}|x|X|\\*`),p("XRANGEIDENTIFIER",`${u[l.NUMERICIDENTIFIER]}|x|X|\\*`),p("XRANGEPLAIN",`[v=\\s]*(${u[l.XRANGEIDENTIFIER]})(?:\\.(${u[l.XRANGEIDENTIFIER]})(?:\\.(${u[l.XRANGEIDENTIFIER]})(?:${u[l.PRERELEASE]})?${u[l.BUILD]}?)?)?`),p("XRANGEPLAINLOOSE",`[v=\\s]*(${u[l.XRANGEIDENTIFIERLOOSE]})(?:\\.(${u[l.XRANGEIDENTIFIERLOOSE]})(?:\\.(${u[l.XRANGEIDENTIFIERLOOSE]})(?:${u[l.PRERELEASELOOSE]})?${u[l.BUILD]}?)?)?`),p("XRANGE",`^${u[l.GTLT]}\\s*${u[l.XRANGEPLAIN]}$`),p("XRANGELOOSE",`^${u[l.GTLT]}\\s*${u[l.XRANGEPLAINLOOSE]}$`),p("COERCEPLAIN",`(^|[^\\d])(\\d{1,${n}})(?:\\.(\\d{1,${n}}))?(?:\\.(\\d{1,${n}}))?`),p("COERCE",`${u[l.COERCEPLAIN]}(?:$|[^\\d])`),p("COERCEFULL",u[l.COERCEPLAIN]+`(?:${u[l.PRERELEASE]})?(?:${u[l.BUILD]})?(?:$|[^\\d])`),p("COERCERTL",u[l.COERCE],!0),p("COERCERTLFULL",u[l.COERCEFULL],!0),p("LONETILDE","(?:~>?)"),p("TILDETRIM",`(\\s*)${u[l.LONETILDE]}\\s+`,!0),t.tildeTrimReplace="$1~",p("TILDE",`^${u[l.LONETILDE]}${u[l.XRANGEPLAIN]}$`),p("TILDELOOSE",`^${u[l.LONETILDE]}${u[l.XRANGEPLAINLOOSE]}$`),p("LONECARET","(?:\\^)"),p("CARETTRIM",`(\\s*)${u[l.LONECARET]}\\s+`,!0),t.caretTrimReplace="$1^",p("CARET",`^${u[l.LONECARET]}${u[l.XRANGEPLAIN]}$`),p("CARETLOOSE",`^${u[l.LONECARET]}${u[l.XRANGEPLAINLOOSE]}$`),p("COMPARATORLOOSE",`^${u[l.GTLT]}\\s*(${u[l.LOOSEPLAIN]})$|^$`),p("COMPARATOR",`^${u[l.GTLT]}\\s*(${u[l.FULLPLAIN]})$|^$`),p("COMPARATORTRIM",`(\\s*)${u[l.GTLT]}\\s*(${u[l.LOOSEPLAIN]}|${u[l.XRANGEPLAIN]})`,!0),t.comparatorTrimReplace="$1$2$3",p("HYPHENRANGE",`^\\s*(${u[l.XRANGEPLAIN]})\\s+-\\s+(${u[l.XRANGEPLAIN]})\\s*$`),p("HYPHENRANGELOOSE",`^\\s*(${u[l.XRANGEPLAINLOOSE]})\\s+-\\s+(${u[l.XRANGEPLAINLOOSE]})\\s*$`),p("STAR","(<|>)?=?\\s*\\*"),p("GTE0","^\\s*>=\\s*0\\.0\\.0\\s*$"),p("GTE0PRE","^\\s*>=\\s*0\\.0\\.0-0\\s*$")})(z0,z0.exports)),z0.exports}var Sx,g6;function V_e(){if(g6)return Sx;g6=1;const e=/^[0-9]+$/,t=(r,i)=>{const s=e.test(r),o=e.test(i);return s&&o&&(r=+r,i=+i),r===i?0:s&&!o?-1:o&&!s?1:rt(i,r)},Sx}var kx,m6;function g$(){if(m6)return kx;m6=1;const e=Db(),{MAX_LENGTH:t,MAX_SAFE_INTEGER:n}=h$(),{safeRe:r,t:i}=p$(),s=d$(),{compareIdentifiers:o}=V_e();class a{constructor(l,c){if(c=s(c),l instanceof a){if(l.loose===!!c.loose&&l.includePrerelease===!!c.includePrerelease)return l;l=l.version}else if(typeof l!="string")throw new TypeError(`Invalid version. Must be a string. Got type "${typeof l}".`);if(l.length>t)throw new TypeError(`version is longer than ${t} characters`);e("SemVer",l,c),this.options=c,this.loose=!!c.loose,this.includePrerelease=!!c.includePrerelease;const f=l.trim().match(c.loose?r[i.LOOSE]:r[i.FULL]);if(!f)throw new TypeError(`Invalid Version: ${l}`);if(this.raw=l,this.major=+f[1],this.minor=+f[2],this.patch=+f[3],this.major>n||this.major<0)throw new TypeError("Invalid major version");if(this.minor>n||this.minor<0)throw new TypeError("Invalid minor version");if(this.patch>n||this.patch<0)throw new TypeError("Invalid patch version");f[4]?this.prerelease=f[4].split(".").map(d=>{if(/^[0-9]+$/.test(d)){const h=+d;if(h>=0&&h=0;)typeof this.prerelease[h]=="number"&&(this.prerelease[h]++,h=-2);if(h===-1){if(c===this.prerelease.join(".")&&f===!1)throw new Error("invalid increment argument: identifier already exists");this.prerelease.push(d)}}if(c){let h=[c,d];f===!1&&(h=[c]),o(this.prerelease[0],c)===0?isNaN(this.prerelease[1])&&(this.prerelease=h):this.prerelease=h}break}default:throw new Error(`invalid increment argument: ${l}`)}return this.raw=this.format(),this.build.length&&(this.raw+=`+${this.build.join(".")}`),this}}return kx=a,kx}var Cx,y6;function Hd(){if(y6)return Cx;y6=1;const e=g$();return Cx=(n,r,i)=>new e(n,i).compare(new e(r,i)),Cx}var $x,v6;function X_e(){if(v6)return $x;v6=1;const e=Hd();return $x=(n,r,i)=>e(n,r,i)===0,$x}var Fx,b6;function K_e(){if(b6)return Fx;b6=1;const e=Hd();return Fx=(n,r,i)=>e(n,r,i)!==0,Fx}var Dx,x6;function Z_e(){if(x6)return Dx;x6=1;const e=Hd();return Dx=(n,r,i)=>e(n,r,i)>0,Dx}var Mx,_6;function J_e(){if(_6)return Mx;_6=1;const e=Hd();return Mx=(n,r,i)=>e(n,r,i)>=0,Mx}var Rx,w6;function Q_e(){if(w6)return Rx;w6=1;const e=Hd();return Rx=(n,r,i)=>e(n,r,i)<0,Rx}var Tx,E6;function ewe(){if(E6)return Tx;E6=1;const e=Hd();return Tx=(n,r,i)=>e(n,r,i)<=0,Tx}var Nx,A6;function twe(){if(A6)return Nx;A6=1;const e=X_e(),t=K_e(),n=Z_e(),r=J_e(),i=Q_e(),s=ewe();return Nx=(a,u,l,c)=>{switch(u){case"===":return typeof a=="object"&&(a=a.version),typeof l=="object"&&(l=l.version),a===l;case"!==":return typeof a=="object"&&(a=a.version),typeof l=="object"&&(l=l.version),a!==l;case"":case"=":case"==":return e(a,l,c);case"!=":return t(a,l,c);case">":return n(a,l,c);case">=":return r(a,l,c);case"<":return i(a,l,c);case"<=":return s(a,l,c);default:throw new TypeError(`Invalid operator: ${u}`)}},Nx}var Ox,S6;function nwe(){if(S6)return Ox;S6=1;const e=Symbol("SemVer ANY");class t{static get ANY(){return e}constructor(c,f){if(f=n(f),c instanceof t){if(c.loose===!!f.loose)return c;c=c.value}c=c.trim().split(/\s+/).join(" "),o("comparator",c,f),this.options=f,this.loose=!!f.loose,this.parse(c),this.semver===e?this.value="":this.value=this.operator+this.semver.version,o("comp",this)}parse(c){const f=this.options.loose?r[i.COMPARATORLOOSE]:r[i.COMPARATOR],d=c.match(f);if(!d)throw new TypeError(`Invalid comparator: ${c}`);this.operator=d[1]!==void 0?d[1]:"",this.operator==="="&&(this.operator=""),d[2]?this.semver=new a(d[2],this.options.loose):this.semver=e}toString(){return this.value}test(c){if(o("Comparator.test",c,this.options.loose),this.semver===e||c===e)return!0;if(typeof c=="string")try{c=new a(c,this.options)}catch{return!1}return s(c,this.operator,this.semver,this.options)}intersects(c,f){if(!(c instanceof t))throw new TypeError("a Comparator is required");return this.operator===""?this.value===""?!0:new u(c.value,f).test(this.value):c.operator===""?c.value===""?!0:new u(this.value,f).test(c.semver):(f=n(f),f.includePrerelease&&(this.value==="<0.0.0-0"||c.value==="<0.0.0-0")||!f.includePrerelease&&(this.value.startsWith("<0.0.0")||c.value.startsWith("<0.0.0"))?!1:!!(this.operator.startsWith(">")&&c.operator.startsWith(">")||this.operator.startsWith("<")&&c.operator.startsWith("<")||this.semver.version===c.semver.version&&this.operator.includes("=")&&c.operator.includes("=")||s(this.semver,"<",c.semver,f)&&this.operator.startsWith(">")&&c.operator.startsWith("<")||s(this.semver,">",c.semver,f)&&this.operator.startsWith("<")&&c.operator.startsWith(">")))}}Ox=t;const n=d$(),{safeRe:r,t:i}=p$(),s=twe(),o=Db(),a=g$(),u=Vj();return Ox}var Lx,k6;function Vj(){if(k6)return Lx;k6=1;const e=/\s+/g;class t{constructor(C,T){if(T=i(T),C instanceof t)return C.loose===!!T.loose&&C.includePrerelease===!!T.includePrerelease?C:new t(C.raw,T);if(C instanceof s)return this.raw=C.value,this.set=[[C]],this.formatted=void 0,this;if(this.options=T,this.loose=!!T.loose,this.includePrerelease=!!T.includePrerelease,this.raw=C.trim().replace(e," "),this.set=this.raw.split("||").map(O=>this.parseRange(O.trim())).filter(O=>O.length),!this.set.length)throw new TypeError(`Invalid SemVer Range: ${this.raw}`);if(this.set.length>1){const O=this.set[0];if(this.set=this.set.filter(N=>!g(N[0])),this.set.length===0)this.set=[O];else if(this.set.length>1){for(const N of this.set)if(N.length===1&&m(N[0])){this.set=[N];break}}}this.formatted=void 0}get range(){if(this.formatted===void 0){this.formatted="";for(let C=0;C0&&(this.formatted+="||");const T=this.set[C];for(let O=0;O0&&(this.formatted+=" "),this.formatted+=T[O].toString().trim()}}return this.formatted}format(){return this.range}toString(){return this.range}parseRange(C){const O=((this.options.includePrerelease&&h)|(this.options.loose&&p))+":"+C,N=r.get(O);if(N)return N;const L=this.options.loose,z=L?u[l.HYPHENRANGELOOSE]:u[l.HYPHENRANGE];C=C.replace(z,M(this.options.includePrerelease)),o("hyphen replace",C),C=C.replace(u[l.COMPARATORTRIM],c),o("comparator trim",C),C=C.replace(u[l.TILDETRIM],f),o("tilde trim",C),C=C.replace(u[l.CARETTRIM],d),o("caret trim",C);let U=C.split(" ").map(ne=>v(ne,this.options)).join(" ").split(/\s+/).map(ne=>D(ne,this.options));L&&(U=U.filter(ne=>(o("loose invalid filter",ne,this.options),!!ne.match(u[l.COMPARATORLOOSE])))),o("range list",U);const Q=new Map,de=U.map(ne=>new s(ne,this.options));for(const ne of de){if(g(ne))return[ne];Q.set(ne.value,ne)}Q.size>1&&Q.has("")&&Q.delete("");const we=[...Q.values()];return r.set(O,we),we}intersects(C,T){if(!(C instanceof t))throw new TypeError("a Range is required");return this.set.some(O=>y(O,T)&&C.set.some(N=>y(N,T)&&O.every(L=>N.every(z=>L.intersects(z,T)))))}test(C){if(!C)return!1;if(typeof C=="string")try{C=new a(C,this.options)}catch{return!1}for(let T=0;TF.value==="<0.0.0-0",m=F=>F.value==="",y=(F,C)=>{let T=!0;const O=F.slice();let N=O.pop();for(;T&&O.length;)T=O.every(L=>N.intersects(L,C)),N=O.pop();return T},v=(F,C)=>(o("comp",F,C),F=A(F,C),o("caret",F),F=x(F,C),o("tildes",F),F=S(F,C),o("xrange",F),F=$(F,C),o("stars",F),F),b=F=>!F||F.toLowerCase()==="x"||F==="*",x=(F,C)=>F.trim().split(/\s+/).map(T=>_(T,C)).join(" "),_=(F,C)=>{const T=C.loose?u[l.TILDELOOSE]:u[l.TILDE];return F.replace(T,(O,N,L,z,U)=>{o("tilde",F,O,N,L,z,U);let Q;return b(N)?Q="":b(L)?Q=`>=${N}.0.0 <${+N+1}.0.0-0`:b(z)?Q=`>=${N}.${L}.0 <${N}.${+L+1}.0-0`:U?(o("replaceTilde pr",U),Q=`>=${N}.${L}.${z}-${U} <${N}.${+L+1}.0-0`):Q=`>=${N}.${L}.${z} <${N}.${+L+1}.0-0`,o("tilde return",Q),Q})},A=(F,C)=>F.trim().split(/\s+/).map(T=>E(T,C)).join(" "),E=(F,C)=>{o("caret",F,C);const T=C.loose?u[l.CARETLOOSE]:u[l.CARET],O=C.includePrerelease?"-0":"";return F.replace(T,(N,L,z,U,Q)=>{o("caret",F,N,L,z,U,Q);let de;return b(L)?de="":b(z)?de=`>=${L}.0.0${O} <${+L+1}.0.0-0`:b(U)?L==="0"?de=`>=${L}.${z}.0${O} <${L}.${+z+1}.0-0`:de=`>=${L}.${z}.0${O} <${+L+1}.0.0-0`:Q?(o("replaceCaret pr",Q),L==="0"?z==="0"?de=`>=${L}.${z}.${U}-${Q} <${L}.${z}.${+U+1}-0`:de=`>=${L}.${z}.${U}-${Q} <${L}.${+z+1}.0-0`:de=`>=${L}.${z}.${U}-${Q} <${+L+1}.0.0-0`):(o("no pr"),L==="0"?z==="0"?de=`>=${L}.${z}.${U}${O} <${L}.${z}.${+U+1}-0`:de=`>=${L}.${z}.${U}${O} <${L}.${+z+1}.0-0`:de=`>=${L}.${z}.${U} <${+L+1}.0.0-0`),o("caret return",de),de})},S=(F,C)=>(o("replaceXRanges",F,C),F.split(/\s+/).map(T=>k(T,C)).join(" ")),k=(F,C)=>{F=F.trim();const T=C.loose?u[l.XRANGELOOSE]:u[l.XRANGE];return F.replace(T,(O,N,L,z,U,Q)=>{o("xRange",F,O,N,L,z,U,Q);const de=b(L),we=de||b(z),ne=we||b(U),Ee=ne;return N==="="&&Ee&&(N=""),Q=C.includePrerelease?"-0":"",de?N===">"||N==="<"?O="<0.0.0-0":O="*":N&&Ee?(we&&(z=0),U=0,N===">"?(N=">=",we?(L=+L+1,z=0,U=0):(z=+z+1,U=0)):N==="<="&&(N="<",we?L=+L+1:z=+z+1),N==="<"&&(Q="-0"),O=`${N+L}.${z}.${U}${Q}`):we?O=`>=${L}.0.0${Q} <${+L+1}.0.0-0`:ne&&(O=`>=${L}.${z}.0${Q} <${L}.${+z+1}.0-0`),o("xRange return",O),O})},$=(F,C)=>(o("replaceStars",F,C),F.trim().replace(u[l.STAR],"")),D=(F,C)=>(o("replaceGTE0",F,C),F.trim().replace(u[C.includePrerelease?l.GTE0PRE:l.GTE0],"")),M=F=>(C,T,O,N,L,z,U,Q,de,we,ne,Ee)=>(b(O)?T="":b(N)?T=`>=${O}.0.0${F?"-0":""}`:b(L)?T=`>=${O}.${N}.0${F?"-0":""}`:z?T=`>=${T}`:T=`>=${T}${F?"-0":""}`,b(de)?Q="":b(we)?Q=`<${+de+1}.0.0-0`:b(ne)?Q=`<${de}.${+we+1}.0-0`:Ee?Q=`<=${de}.${we}.${ne}-${Ee}`:F?Q=`<${de}.${we}.${+ne+1}-0`:Q=`<=${Q}`,`${T} ${Q}`.trim()),R=(F,C,T)=>{for(let O=0;O0){const N=F[O].semver;if(N.major===C.major&&N.minor===C.minor&&N.patch===C.patch)return!0}return!1}return!0};return Lx}var Ix,C6;function rwe(){if(C6)return Ix;C6=1;const e=Vj();return Ix=(n,r,i)=>{try{r=new e(r,i)}catch{return!1}return r.test(n)},Ix}var iwe=rwe(),Xj=G_e(iwe);function swe(e,t,n){const r=e.open(t),i=250,{origin:s}=new URL(t);let o=40;function a(l){l.source===r&&(o=0,e.removeEventListener("message",a,!1))}e.addEventListener("message",a,!1);function u(){o<=0||(r.postMessage(n,s),setTimeout(u,i),o-=1)}setTimeout(u,i)}var owe=`.vega-embed { + position: relative; + display: inline-block; + box-sizing: border-box; +} +.vega-embed.has-actions { + padding-right: 38px; +} +.vega-embed details:not([open]) > :not(summary) { + display: none !important; +} +.vega-embed summary { + list-style: none; + position: absolute; + top: 0; + right: 0; + padding: 6px; + z-index: 1000; + background: white; + box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1); + color: #1b1e23; + border: 1px solid #aaa; + border-radius: 999px; + opacity: 0.2; + transition: opacity 0.4s ease-in; + cursor: pointer; + line-height: 0px; +} +.vega-embed summary::-webkit-details-marker { + display: none; +} +.vega-embed summary:active { + box-shadow: #aaa 0px 0px 0px 1px inset; +} +.vega-embed summary svg { + width: 14px; + height: 14px; +} +.vega-embed details[open] summary { + opacity: 0.7; +} +.vega-embed:hover summary, .vega-embed:focus-within summary { + opacity: 1 !important; + transition: opacity 0.2s ease; +} +.vega-embed .vega-actions { + position: absolute; + z-index: 1001; + top: 35px; + right: -9px; + display: flex; + flex-direction: column; + padding-bottom: 8px; + padding-top: 8px; + border-radius: 4px; + box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2); + border: 1px solid #d9d9d9; + background: white; + animation-duration: 0.15s; + animation-name: scale-in; + animation-timing-function: cubic-bezier(0.2, 0, 0.13, 1.5); + text-align: left; +} +.vega-embed .vega-actions a { + padding: 8px 16px; + font-family: sans-serif; + font-size: 14px; + font-weight: 600; + white-space: nowrap; + color: #434a56; + text-decoration: none; +} +.vega-embed .vega-actions a:hover, .vega-embed .vega-actions a:focus { + background-color: #f7f7f9; + color: black; +} +.vega-embed .vega-actions::before, .vega-embed .vega-actions::after { + content: ""; + display: inline-block; + position: absolute; +} +.vega-embed .vega-actions::before { + left: auto; + right: 14px; + top: -16px; + border: 8px solid rgba(0, 0, 0, 0); + border-bottom-color: #d9d9d9; +} +.vega-embed .vega-actions::after { + left: auto; + right: 15px; + top: -14px; + border: 7px solid rgba(0, 0, 0, 0); + border-bottom-color: #fff; +} +.vega-embed .chart-wrapper.fit-x { + width: 100%; +} +.vega-embed .chart-wrapper.fit-y { + height: 100%; +} + +.vega-embed-wrapper { + max-width: 100%; + overflow: auto; + padding-right: 14px; +} + +@keyframes scale-in { + from { + opacity: 0; + transform: scale(0.6); + } + to { + opacity: 1; + transform: scale(1); + } +} +`;function Kj(e,...t){for(const n of t)awe(e,n);return e}function awe(e,t){for(const n of Object.keys(t))_d(e,n,t[n],!0)}const Hs=Lhe;let Wp=Oxe;const j0=typeof window<"u"?window:void 0;var Z6;Wp===void 0&&((Z6=j0==null?void 0:j0.vl)!=null&&Z6.compile)&&(Wp=j0.vl);const uwe={export:{svg:!0,png:!0},source:!0,compiled:!0,editor:!0},lwe={CLICK_TO_VIEW_ACTIONS:"Click to view actions",COMPILED_ACTION:"View Compiled Vega",EDITOR_ACTION:"Open in Vega Editor",PNG_ACTION:"Save as PNG",SOURCE_ACTION:"View Source",SVG_ACTION:"Save as SVG"},Wh={vega:"Vega","vega-lite":"Vega-Lite"},cy={vega:Hs.version,"vega-lite":Wp?Wp.version:"not available"},cwe={vega:e=>e,"vega-lite":(e,t)=>Wp.compile(e,{config:t}).spec},fwe=` + + + + +`,dwe="chart-wrapper";function hwe(e){return typeof e=="function"}function $6(e,t,n,r){const i=`${t}
      `,s=`
      ${n}`,o=window.open("");o.document.write(i+e+s),o.document.title=`${Wh[r]} JSON Source`}function pwe(e,t){if(e.$schema){const n=Pj(e.$schema);t&&t!==n.library&&console.warn(`The given visualization spec is written in ${Wh[n.library]}, but mode argument sets ${Wh[t]??t}.`);const r=n.library;return Xj(cy[r],`^${n.version.slice(1)}`)||console.warn(`The input spec uses ${Wh[r]} ${n.version}, but the current version of ${Wh[r]} is v${cy[r]}.`),r}return"mark"in e||"encoding"in e||"layer"in e||"hconcat"in e||"vconcat"in e||"facet"in e||"repeat"in e?"vega-lite":"marks"in e||"signals"in e||"scales"in e||"axes"in e?"vega":t??"vega"}function Zj(e){return!!(e&&"load"in e)}function F6(e){return Zj(e)?e:Hs.loader(e)}function gwe(e){var n;const t=((n=e.usermeta)==null?void 0:n.embedOptions)??{};return me(t.defaultStyle)&&(t.defaultStyle=!1),t}async function Jj(e,t,n={}){let r,i;me(t)?(i=F6(n.loader),r=JSON.parse(await i.load(t))):r=t;const s=gwe(r),o=s.loader;(!i||o)&&(i=F6(n.loader??o));const a=await D6(s,i),u=await D6(n,i),l={...Kj(u,a),config:xd(u.config??{},a.config??{})};return await ywe(e,r,l,i)}async function D6(e,t){const n=me(e.config)?JSON.parse(await t.load(e.config)):e.config??{},r=me(e.patch)?JSON.parse(await t.load(e.patch)):e.patch;return{...e,...r?{patch:r}:{},...n?{config:n}:{}}}function mwe(e){const t=e.getRootNode?e.getRootNode():document;return t instanceof ShadowRoot?{root:t,rootContainer:t}:{root:document,rootContainer:document.head??document.body}}async function ywe(e,t,n={},r){const i=n.theme?xd(x_e[n.theme],n.config??{}):n.config,s=Du(n.actions)?n.actions:Kj({},uwe,n.actions??{}),o={...lwe,...n.i18n},a=n.renderer??"canvas",u=n.logLevel??Hs.Warn,l=n.downloadFileName??"visualization",c=typeof e=="string"?document.querySelector(e):e;if(!c)throw new Error(`${e} does not exist`);if(n.defaultStyle!==!1){const _="vega-embed-style",{root:A,rootContainer:E}=mwe(c);if(!A.getElementById(_)){const S=document.createElement("style");S.id=_,S.innerHTML=n.defaultStyle===void 0||n.defaultStyle===!0?owe.toString():n.defaultStyle,E.appendChild(S)}}const f=pwe(t,n.mode);let d=cwe[f](t,i);if(f==="vega-lite"&&d.$schema){const _=Pj(d.$schema);Xj(cy.vega,`^${_.version.slice(1)}`)||console.warn(`The compiled spec uses Vega ${_.version}, but current version is v${cy.vega}.`)}c.classList.add("vega-embed"),s&&c.classList.add("has-actions"),c.innerHTML="";let h=c;if(s){const _=document.createElement("div");_.classList.add(dwe),c.appendChild(_),h=_}const p=n.patch;if(p&&(d=p instanceof Function?p(d):Fb(d,p,!0,!1).newDocument),n.formatLocale&&Hs.formatLocale(n.formatLocale),n.timeFormatLocale&&Hs.timeFormatLocale(n.timeFormatLocale),n.expressionFunctions)for(const _ in n.expressionFunctions){const A=n.expressionFunctions[_];"fn"in A?Hs.expressionFunction(_,A.fn,A.visitor):A instanceof Function&&Hs.expressionFunction(_,A)}const{ast:g}=n,m=Hs.parse(d,f==="vega-lite"?{}:i,{ast:g}),y=new(n.viewClass||Hs.View)(m,{loader:r,logLevel:u,renderer:a,...g?{expr:Hs.expressionInterpreter??n.expr??Ghe}:{}});if(y.addSignalListener("autosize",(_,A)=>{const{type:E}=A;E=="fit-x"?(h.classList.add("fit-x"),h.classList.remove("fit-y")):E=="fit-y"?(h.classList.remove("fit-x"),h.classList.add("fit-y")):E=="fit"?h.classList.add("fit-x","fit-y"):h.classList.remove("fit-x","fit-y")}),n.tooltip!==!1){const{loader:_,tooltip:A}=n,E=_&&!Zj(_)?_==null?void 0:_.baseURL:void 0,S=hwe(A)?A:new D_e({baseURL:E,...A===!0?{}:A}).call;y.tooltip(S)}let{hover:v}=n;if(v===void 0&&(v=f==="vega"),v){const{hoverSet:_,updateSet:A}=typeof v=="boolean"?{}:v;y.hover(_,A)}n&&(n.width!=null&&y.width(n.width),n.height!=null&&y.height(n.height),n.padding!=null&&y.padding(n.padding)),await y.initialize(h,n.bind).runAsync();let b;if(s!==!1){let _=c;if(n.defaultStyle!==!1||n.forceActionsMenu){const E=document.createElement("details");E.title=o.CLICK_TO_VIEW_ACTIONS,c.append(E),_=E;const S=document.createElement("summary");S.innerHTML=fwe,E.append(S),b=k=>{E.contains(k.target)||E.removeAttribute("open")},document.addEventListener("click",b)}const A=document.createElement("div");if(_.append(A),A.classList.add("vega-actions"),s===!0||s.export!==!1){for(const E of["svg","png"])if(s===!0||s.export===!0||s.export[E]){const S=o[`${E.toUpperCase()}_ACTION`],k=document.createElement("a"),$=ge(n.scaleFactor)?n.scaleFactor[E]:n.scaleFactor;k.text=S,k.href="#",k.target="_blank",k.download=`${l}.${E}`,k.addEventListener("mousedown",async function(D){D.preventDefault();const M=await y.toImageURL(E,$);this.href=M}),A.append(k)}}if(s===!0||s.source!==!1){const E=document.createElement("a");E.text=o.SOURCE_ACTION,E.href="#",E.addEventListener("click",function(S){$6(Hb(t),n.sourceHeader??"",n.sourceFooter??"",f),S.preventDefault()}),A.append(E)}if(f==="vega-lite"&&(s===!0||s.compiled!==!1)){const E=document.createElement("a");E.text=o.COMPILED_ACTION,E.href="#",E.addEventListener("click",function(S){$6(Hb(d),n.sourceHeader??"",n.sourceFooter??"","vega"),S.preventDefault()}),A.append(E)}if(s===!0||s.editor!==!1){const E=n.editorUrl??"https://vega.github.io/editor/",S=document.createElement("a");S.text=o.EDITOR_ACTION,S.href="#",S.addEventListener("click",function(k){swe(window,E,{config:i,mode:p?"vega":f,renderer:a,spec:Hb(p?d:t)}),k.preventDefault()}),A.append(S)}}function x(){b&&document.removeEventListener("click",b),y.finalize()}return{view:y,spec:t,vgSpec:d,finalize:x,embedOptions:n}}const Qj=["project","run","timestamp","step","time","metrics"];function vwe(e,t,n,r,i,s){if(!e||e.length===0)return null;let o=e.map(c=>({...c}));Object.hasOwn(o[0],"step")||o.forEach((c,f)=>c.step=f);let a="step";if(r==="time"&&Object.hasOwn(o[0],"timestamp")){const c=new Date(o[0].timestamp).getTime();o.forEach(f=>{f.time=(new Date(f.timestamp).getTime()-c)/1e3}),a="time"}else r!=="step"&&(a=r);i&&o.forEach(c=>{if(c[a]!=null){const f=c[a];c[a]=f<=0?Math.log10(Math.max(f,0)+1):Math.log10(f)}});const l=eU(o).filter(c=>!Qj.includes(c)&&c!==a);if(s&&o.forEach(c=>{l.forEach(f=>{if(c[f]!=null&&typeof c[f]=="number"){const d=c[f];c[f]=d<=0?Math.log10(Math.max(d,0)+1):Math.log10(d)}})}),n>0){const c=o.map(d=>({...d,run:t,data_type:"original"})),f=bwe(o,l,n).map(d=>({...d,run:t,data_type:"smoothed"}));return{rows:[...c,...f],xColumn:a}}return{rows:o.map(c=>({...c,run:t,data_type:"original"})),xColumn:a}}function bwe(e,t,n){const r=Math.max(3,Math.min(n,e.length)),i=Math.floor(r/2);return e.map((s,o)=>{const a={...s};return t.forEach(u=>{const l=Math.max(0,o-i),c=Math.min(e.length,o+i+1);let f=0,d=0;for(let h=l;h0?f/d:s[u]}),a})}function eU(e){if(!e||e.length===0)return[];const t=new Set;return e.forEach(n=>{Object.keys(n).forEach(r=>{typeof n[r]=="number"&&isFinite(n[r])&&t.add(r)})}),Array.from(t)}function xwe(e){return eU(e).filter(t=>!Qj.includes(t))}function wE(e,t,n,r){let i=e.filter(a=>a[n]!=null&&a[n]!==void 0);if(r){const a=new Map;for(const l of i){const c=`${l.run||""}\0${l.data_type||"original"}`;a.has(c)||a.set(c,[]),a.get(c).push(l)}const u=[];for(const[,l]of a){l.sort((d,h)=>d[t]-h[t]);let c=0,f=l.length-1;for(;c=0&&l[f][t]>r[1];)f--;c=Math.max(0,c-1),f=Math.min(l.length-1,f+1),u.push(...l.slice(c,f+1))}i=u}const s=i.filter(a=>a.data_type==="original"||!a.data_type);let o;if(s.length>0){let a=1/0,u=-1/0;for(const l of s){const c=l[n];c!=null&&(cu&&(u=c))}a!==1/0&&(o=[a,u])}return{data:_we(i,t,n,"run",r).data,yExtent:o}}function M6(e,t,n,r,i){const s=[t,n];Object.hasOwn(e[0],r)&&s.push(r);let o=e.map(h=>{const p={};return s.forEach(g=>p[g]=h[g]),h.data_type&&(p.data_type=h.data_type),h.run&&(p.run=h.run),p});const a=Math.min(...o.map(h=>h[t]).filter(h=>h!=null)),u=Math.max(...o.map(h=>h[t]).filter(h=>h!=null));let l=i;if(i){const[h,p]=[i[0]??a,i[1]??u];l=[h,p]}const c={};o.forEach(h=>{const p=h[r]||"__default";c[p]||(c[p]=[]),c[p].push(h)});const f=[],d=100;return Object.values(c).forEach(h=>{if(h.sort((v,b)=>(v[t]||0)-(b[t]||0)),h.length<500){f.push(...h);return}const p=l?l[0]:a,g=l?l[1]:u;if(p===g){f.push(...h);return}const m=(g-p)/d,y=new Map;h.forEach(v=>{const b=v[t];if(b==null)return;const x=Math.min(Math.floor((b-p)/m),d-1);y.has(x)||y.set(x,[]),y.get(x).push(v)}),y.forEach(v=>{if(v.length===0)return;let b=v[0],x=v[0];v.forEach(_=>{_[n]x[n]&&(x=_)}),f.push(b),b!==x&&f.push(x)})}),f.sort((h,p)=>(h[t]||0)-(p[t]||0)),{data:f,xLim:l}}function _we(e,t,n,r,i){if(!e||e.length===0)return{data:e,xLim:i};if(e.some(o=>o.data_type)&&r&&e[0]&&Object.hasOwn(e[0],r)){const o=new Map;for(const l of e){const c=`${l[r]??"__default"}\0${l.data_type??"original"}`;o.has(c)||o.set(c,[]),o.get(c).push(l)}const a=[];let u=i;for(const l of o.values()){const c=M6(l,t,n,r,i);a.push(...c.data),u=c.xLim}return a.sort((l,c)=>(l[t]||0)-(c[t]||0)),{data:a,xLim:u}}return M6(e,t,n,r,i)}function tU(e,t=[]){const n=[],r={};e.forEach(l=>{if(l.includes("/")){const c=l.split("/"),f=c[0];if(r[f]||(r[f]={direct:[],subgroups:{}}),c.length===2)r[f].direct.push(l);else{const d=c[1];r[f].subgroups[d]||(r[f].subgroups[d]=[]),r[f].subgroups[d].push(l)}}else n.push(l)});function i(l){if(!t||t.length===0)return l.sort();const c=[],f=[...l];for(const d of t)for(let h=f.length-1;h>=0;h--)s(f[h],d)&&(c.push(f[h]),f.splice(h,1));return f.sort(),[...c,...f]}function s(l,c){return c===l||c.endsWith("/*")&&l.startsWith(c.slice(0,-1))?!0:c.includes("*")?new RegExp("^"+c.replace(/\*/g,".*")+"$").test(l):!1}function o(l){if(!t||t.length===0)return 1/0;for(let c=0;c0&&(a.charts={direct:i(n),subgroups:{}});const u=Object.keys(r);if(u.sort((l,c)=>{const f=o(l),d=o(c);return f!==d?f-d:l.localeCompare(c)}),u.forEach(l=>{const c=r[l];c.direct=i(c.direct),Object.keys(c.subgroups).forEach(f=>{c.subgroups[f]=i(c.subgroups[f])}),a[l]=c}),"charts"in a){const l=o("charts");if(l<1/0){const c=Object.entries(a);c.sort(([d],[h])=>{const p=d==="charts"?l:o(d),g=h==="charts"?l:o(h);return p!==g?p-g:d.localeCompare(h)});const f={};return c.forEach(([d,h])=>{f[d]=h}),f}}return a}function nU(e,t,n){if(!t||!e||e.length===0)return"";const r=new Set,i=[];for(const s of e){const o=s[t];o&&!r.has(o)&&(r.add(o),i.push(`${o}:${n[o]??"#999"}`))}return i.sort(),i.join("|")}function wwe(e,t){if(!t||!t.trim())return e;try{const n=new RegExp(t,"i");return e.filter(r=>n.test(r))}catch{return e.filter(n=>n.toLowerCase().includes(t.toLowerCase()))}}var Ewe=te('
      '),Awe=te(''),Swe=te(' '),kwe=te('
      '),Cwe=te('
      ',1),$we=te(''),Fwe=te(' '),Dwe=te('
      '),Mwe=te('
      '),Rwe=te('
      ',1);function EE(e,t){nn(t,!0);let n=re(t,"data",19,()=>[]),r=re(t,"x",3,"step"),i=re(t,"y",3,""),s=re(t,"colorField",3,"run"),o=re(t,"colorMap",19,()=>({})),a=re(t,"title",3,""),u=re(t,"xLim",3,null),l=re(t,"yExtent",3,void 0),c=re(t,"onSelect",3,null),f=re(t,"onResetZoom",3,null),d=re(t,"draggable",3,!1),h=re(t,"ondragstart",3,null),p=re(t,"ondragover",3,null),g=re(t,"ondrop",3,null),m=le(null),y=le(null),v=le(null),b=le(null),x=le(!1),_=null,A=!1,E=Me(()=>{if(!s()||!n()||n().length===0)return[];const j=new Set,J=[];for(const De of n()){const Pe=De[s()];Pe&&!j.has(Pe)&&(j.add(Pe),J.push({name:Pe,color:o()[Pe]||"#999"}))}return J}),S=Me(()=>nU(n(),s(),o()));function k(j,J){return getComputedStyle(document.documentElement).getPropertyValue(j).trim()||J}function $(){const j=n().filter(De=>De.data_type==="original"||!De.data_type),J=n().filter(De=>De.data_type==="smoothed");return{originalData:j,smoothedData:J,hasSmoothed:J.length>0}}function D(j){const J=j.map(De=>De[r()]).filter(De=>De!=null);if(u())return[u()[0],u()[1]];if(J.length>0)return[Math.min(...J),Math.max(...J)]}function M(){const j=s()&&n().length>0&&Object.hasOwn(n()[0],s()),J=j?[...new Set(n().map(Pt=>Pt[s()]))]:[],De=[...new Set(J)],Pe=De,Le=De.map(Pt=>o()[Pt]||"#999"),{originalData:et,smoothedData:Ft,hasSmoothed:Xt}=$();A=Xt;const qe=D(et),yt={field:r(),type:"quantitative",scale:{zero:!1,...qe?{domain:qe}:{}}},pt={field:i(),type:"quantitative",...l()?{scale:{domain:l()}}:{}},wn=j?{color:{field:s(),type:"nominal",scale:{domain:Pe,range:Le},legend:null}}:{},Zn=[],Wt=(Pt={})=>({type:"line",clip:!0,strokeWidth:2,...Pt}),Rt=i().includes("/")?i().split("/").pop():i(),Tt=[{field:s(),type:"nominal",title:"Run"},{field:r(),type:"quantitative",title:r()},{field:i(),type:"quantitative",title:Rt}],ti=[{name:"hover",select:{type:"point",on:"pointerover",nearest:!0,clear:"pointerout"}}],hn=(Pt,ni)=>({...Pt,mark:{type:"circle",clip:!0,size:60,opacity:0},encoding:{x:yt,y:pt,...wn,tooltip:Tt,opacity:{condition:{param:"hover",empty:!1,value:1},value:0}},params:ti,name:ni});return Xt?(Zn.push({data:{name:"data_original",values:et},mark:Wt({strokeWidth:1,opacity:.3}),encoding:{x:yt,y:pt,...wn},name:"original"}),Zn.push({data:{name:"data_smoothed",values:Ft},mark:Wt(),encoding:{x:yt,y:pt,...wn},name:"plot"}),Zn.push(hn({data:{name:"data_smoothed",values:Ft}},"hover_points"))):(Zn.push({data:{name:"data_plot",values:n()},mark:Wt(),encoding:{x:yt,y:pt,...wn},name:"plot"}),Zn.push(hn({data:{name:"data_plot",values:n()}},"hover_points"))),{$schema:"https://vega.github.io/schema/vega-lite/v5.json",title:{text:a(),fontSize:13,color:k("--body-text-color","#374151")},width:"container",height:w(x)?"container":250,autosize:{type:"fit",contains:"padding"},layer:Zn,...c()?{params:[{name:"brush",select:{type:"interval",encodings:["x"],mark:{fill:"gray",fillOpacity:.3,stroke:"none"}},views:["plot"]}]}:{},config:{background:"transparent",axis:{labelColor:k("--body-text-color-subdued","#6b7280"),titleColor:k("--body-text-color","#374151"),gridColor:k("--border-color-primary","#f3f4f6")},view:{stroke:"transparent"},mark:{cursor:c()?"crosshair":void 0}},encoding:{y:{title:Rt}}}}function R(){const{originalData:j}=$(),J=D(j),De=J?`${J[0]},${J[1]}`:"auto",Pe=l()?`${l()[0]},${l()[1]}`:"auto";return`${i()}\0${r()}\0${w(S)}\0${a()}\0${w(x)}\0${!!c()}\0${De}\0${Pe}`}function F(j,J,De){const Pe=Mu().remove(yi).insert(De);j.change(J,Pe)}function C(){if(!w(b))return!1;const{originalData:j,smoothedData:J,hasSmoothed:De}=$();if(De!==A)return!1;try{return De?(F(w(b),"data_original",j),F(w(b),"data_smoothed",J)):F(w(b),"data_plot",n()),w(b).run(),A=De,!0}catch{return!1}}async function T(){if(await Di(),!w(m)||!n()||n().length===0||!i())return;const j=M();try{w(b)&&(w(b).finalize(),B(b,null));const J=await Jj(w(m),j,{actions:!1,renderer:"canvas"});if(B(b,J.view,!0),_=R(),requestAnimationFrame(()=>{J.view.resize()}),c()){let De=0,Pe=null;J.view.addSignalListener("brush",(Le,et)=>{if(Date.now()-De<1e3||!et||Object.keys(et).length===0)return;clearTimeout(Pe);const Ft=et[Object.keys(et)[0]];!Ft||Ft.length!==2||(Pe=setTimeout(()=>{De=Date.now(),c()(Ft)},250))})}}catch(J){console.error("Vega render error:",J)}}async function O(){if(!w(m)||!n()||n().length===0||!i())return;const j=R();w(b)&&j===_&&C()||await T()}function N(){if(!n()||n().length===0)return;const j=n().filter(qe=>qe.data_type==="original"||!qe.data_type);if(j.length===0)return;const J=Object.keys(j[0]).filter(qe=>qe!=="data_type"),De=J.map(qe=>/[,"]/.test(qe)?`"${qe.replace(/"/g,'""')}"`:qe).join(","),Pe=j.map(qe=>J.map(yt=>{const pt=qe[yt];return pt==null?"":typeof pt=="string"&&(pt.includes(",")||pt.includes('"'))?`"${pt.replace(/"/g,'""')}"`:pt}).join(",")),Le=[De,...Pe].join(` +`),et=new Blob([Le],{type:"text/csv"}),Ft=URL.createObjectURL(et),Xt=document.createElement("a");Xt.href=Ft,Xt.download=`${(i()||"data").replace(/\//g,"_")}.csv`,document.body.appendChild(Xt),Xt.click(),document.body.removeChild(Xt),URL.revokeObjectURL(Ft)}async function L(){if(w(b))try{const j=await w(b).toImageURL("png",4),J=document.createElement("a");J.href=j,J.download=`${(i()||"chart").replace(/\//g,"_")}.png`,document.body.appendChild(J),J.click(),document.body.removeChild(J)}catch(j){console.error("Failed to export image:",j)}}function z(j){if(!j)return Promise.reject(new Error("no element"));const J=j.requestFullscreen||j.webkitRequestFullscreen||j.mozRequestFullScreen||j.msRequestFullscreen;return J?J.call(j):Promise.reject(new Error("no fullscreen"))}function U(){const j=document.exitFullscreen||document.webkitExitFullscreen||document.mozCancelFullScreen||document.msExitFullscreen;return j?j.call(document):Promise.resolve()}async function Q(){var j;B(x,!0),document.body.style.overflow="hidden",await Di(),await Di();try{await z(w(v)),await Di(),(j=w(b))==null||j.resize()}catch{document.body.style.overflow="",B(x,!1)}}async function de(){try{await U()}catch{}document.body.style.overflow="",B(x,!1)}async function we(){w(x)?await de():await Q()}function ne(){const j=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;!j&&w(x)&&(document.body.style.overflow="",B(x,!1)),j&&w(x)&&Di().then(()=>{var J;return(J=w(b))==null?void 0:J.resize()})}function Ee(j){j.key==="Escape"&&w(x)&&de()}tn(()=>{n(),i(),r(),w(S),u(),l(),a(),w(x),w(m),O()}),tn(()=>{if(!w(m))return;const j=new ResizeObserver(()=>{queueMicrotask(()=>{var J;(J=w(b))==null||J.resize()})});return j.observe(w(m)),()=>j.disconnect()}),vd(()=>(document.addEventListener("fullscreenchange",ne),document.addEventListener("webkitfullscreenchange",ne),document.addEventListener("mozfullscreenchange",ne),document.addEventListener("MSFullscreenChange",ne),()=>{document.removeEventListener("fullscreenchange",ne),document.removeEventListener("webkitfullscreenchange",ne),document.removeEventListener("mozfullscreenchange",ne),document.removeEventListener("MSFullscreenChange",ne),w(b)&&w(b).finalize(),document.body.style.overflow=""}));function Ke(j){h()&&h()(j)}var fe=Rwe();ps("keydown",Fm,Ee);var I=Dt(fe);let q;var se=P(I),W=P(se),ve=H(W,2),xe=H(ve,2),Fe=H(se,2);{var ze=j=>{var J=Ewe();V(j,J)};_e(Fe,j=>{d()&&j(ze)})}var ot=H(Fe,2);{var It=j=>{var J=Cwe(),De=Dt(J),Pe=P(De);gs(Pe,qe=>B(m,qe),()=>w(m));var Le=H(Pe,2);{var et=qe=>{var yt=Awe();je("click",yt,pt=>{pt.stopPropagation(),f()()}),V(qe,yt)};_e(Le,qe=>{u()&&f()&&qe(et)})}var Ft=H(De,2);{var Xt=qe=>{var yt=kwe(),pt=P(yt),wn=P(pt),Zn=H(pt,2);Ct(Zn,17,()=>w(E),kt,(Wt,Rt)=>{var Tt=Swe(),ti=P(Tt),hn=H(ti,2),Pt=P(hn);Ae(()=>{ql(ti,`background: ${w(Rt).color??""}`),$e(Pt,w(Rt).name)}),V(Wt,Tt)}),Ae(()=>$e(wn,s())),V(qe,yt)};_e(Ft,qe=>{w(E).length>0&&qe(Xt)})}V(j,J)};_e(ot,j=>{w(x)||j(It)})}gs(I,j=>B(y,j),()=>w(y));var sn=H(I,2);{var Ge=j=>{var J=Mwe(),De=P(J),Pe=P(De),Le=H(Pe,2),et=H(Le,2),Ft=H(De,2),Xt=P(Ft),qe=P(Xt);gs(qe,Wt=>B(m,Wt),()=>w(m));var yt=H(qe,2);{var pt=Wt=>{var Rt=$we();je("click",Rt,Tt=>{Tt.stopPropagation(),f()()}),V(Wt,Rt)};_e(yt,Wt=>{u()&&f()&&Wt(pt)})}var wn=H(Ft,2);{var Zn=Wt=>{var Rt=Dwe(),Tt=P(Rt),ti=P(Tt),hn=H(Tt,2);Ct(hn,17,()=>w(E),kt,(Pt,ni)=>{var zs=Fwe(),zo=P(zs),Da=H(zo,2),Nr=P(Da);Ae(()=>{ql(zo,`background: ${w(ni).color??""}`),$e(Nr,w(ni).name)}),V(Pt,zs)}),Ae(()=>$e(ti,s())),V(Wt,Rt)};_e(wn,Wt=>{w(E).length>0&&Wt(Zn)})}gs(J,Wt=>B(v,Wt),()=>w(v)),je("click",Pe,N),je("click",Le,L),je("click",et,()=>de()),V(j,J)};_e(sn,j=>{w(x)&&j(Ge)})}Ae(()=>{q=zt(I,1,"plot-container svelte-9thu1j",null,q,{"hidden-plot":w(x)}),jt(I,"draggable",d()?"true":void 0)}),ps("dragstart",I,function(...j){var J;(J=d()?Ke:void 0)==null||J.apply(this,j)}),ps("dragover",I,function(...j){var J;(J=d()?p():void 0)==null||J.apply(this,j)}),ps("drop",I,function(...j){var J;(J=d()?g():void 0)==null||J.apply(this,j)}),je("click",W,N),je("click",ve,L),je("click",xe,we),V(e,fe),rn()}wi(["click"]);var Twe=te('
      '),Nwe=te(' '),Owe=te('
      '),Lwe=te('
      ',1),Iwe=te(' '),Pwe=te('
      '),Bwe=te(`
      `),zwe=te(`
      `,1);function R6(e,t){nn(t,!0);let n=re(t,"data",19,()=>[]),r=re(t,"y",3,""),i=re(t,"colorField",3,"run"),s=re(t,"colorMap",19,()=>({})),o=re(t,"title",3,""),a=re(t,"draggable",3,!1),u=re(t,"ondragstart",3,null),l=re(t,"ondragover",3,null),c=re(t,"ondrop",3,null),f=le(null),d=le(null),h=le(null),p=le(null),g=le(!1),m=Me(()=>{if(!i()||!n()||n().length===0)return[];const I=new Set,q=[];for(const se of n()){const W=se[i()];W&&!I.has(W)&&(I.add(W),q.push({name:W,color:s()[W]||"#999"}))}return q}),y=Me(()=>nU(n(),i(),s()));function v(){const I=new Map;for(const q of n()){if(q.data_type==="smoothed")continue;const se=q[i()];se&&q[r()]!=null&&I.set(se,q[r()])}return Array.from(I,([q,se])=>({run:q,value:se}))}function b(I,q){return getComputedStyle(document.documentElement).getPropertyValue(I).trim()||q}function x(I){const q=I.map(ve=>ve.run),se=q.map(ve=>s()[ve]||"#999"),W=r().includes("/")?r().split("/").pop():r();return{$schema:"https://vega.github.io/schema/vega-lite/v5.json",title:{text:o(),fontSize:13,color:b("--body-text-color","#374151")},width:"container",height:w(g)?"container":250,autosize:{type:"fit",contains:"padding"},data:{values:I},mark:{type:"bar",cornerRadiusTopLeft:3,cornerRadiusTopRight:3},encoding:{x:{field:"run",type:"nominal",sort:q,axis:{labelAngle:q.length>4?-45:0,labelLimit:120},title:null},y:{field:"value",type:"quantitative",title:W,scale:{zero:!0}},color:{field:"run",type:"nominal",scale:{domain:q,range:se},legend:null},tooltip:[{field:"run",type:"nominal",title:"Run"},{field:"value",type:"quantitative",title:W}]},config:{background:"transparent",axis:{labelColor:b("--body-text-color-subdued","#6b7280"),titleColor:b("--body-text-color","#374151"),gridColor:b("--border-color-primary","#f3f4f6")},view:{stroke:"transparent"}}}}async function _(){if(await Di(),!w(f)||!n()||n().length===0||!r())return;const I=v();if(I.length===0)return;const q=x(I);try{w(p)&&(w(p).finalize(),B(p,null));const se=await Jj(w(f),q,{actions:!1,renderer:"canvas"});B(p,se.view,!0),requestAnimationFrame(()=>{se.view.resize()})}catch(se){console.error("Vega render error:",se)}}function A(){const I=v();if(I.length===0)return;const se="run,"+(/[,"]/.test(r())?`"${r().replace(/"/g,'""')}"`:r()),W=I.map(ot=>`${typeof ot.run=="string"&&(ot.run.includes(",")||ot.run.includes('"'))?`"${ot.run.replace(/"/g,'""')}"`:ot.run},${ot.value}`),ve=[se,...W].join(` +`),xe=new Blob([ve],{type:"text/csv"}),Fe=URL.createObjectURL(xe),ze=document.createElement("a");ze.href=Fe,ze.download=`${(r()||"data").replace(/\//g,"_")}.csv`,document.body.appendChild(ze),ze.click(),document.body.removeChild(ze),URL.revokeObjectURL(Fe)}async function E(){if(w(p))try{const I=await w(p).toImageURL("png",4),q=document.createElement("a");q.href=I,q.download=`${(r()||"chart").replace(/\//g,"_")}.png`,document.body.appendChild(q),q.click(),document.body.removeChild(q)}catch(I){console.error("Failed to export image:",I)}}function S(I){if(!I)return Promise.reject(new Error("no element"));const q=I.requestFullscreen||I.webkitRequestFullscreen||I.mozRequestFullScreen||I.msRequestFullscreen;return q?q.call(I):Promise.reject(new Error("no fullscreen"))}function k(){const I=document.exitFullscreen||document.webkitExitFullscreen||document.mozCancelFullScreen||document.msExitFullscreen;return I?I.call(document):Promise.resolve()}async function $(){var I;B(g,!0),document.body.style.overflow="hidden",await Di(),await Di();try{await S(w(h)),await Di(),(I=w(p))==null||I.resize()}catch{document.body.style.overflow="",B(g,!1)}}async function D(){try{await k()}catch{}document.body.style.overflow="",B(g,!1)}async function M(){w(g)?await D():await $()}function R(){const I=document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement;!I&&w(g)&&(document.body.style.overflow="",B(g,!1)),I&&w(g)&&Di().then(()=>{var q;return(q=w(p))==null?void 0:q.resize()})}function F(I){I.key==="Escape"&&w(g)&&D()}tn(()=>{n(),r(),w(y),o(),w(g),w(f),_()}),tn(()=>{if(!w(f))return;const I=new ResizeObserver(()=>{queueMicrotask(()=>{var q;(q=w(p))==null||q.resize()})});return I.observe(w(f)),()=>I.disconnect()}),vd(()=>(document.addEventListener("fullscreenchange",R),document.addEventListener("webkitfullscreenchange",R),document.addEventListener("mozfullscreenchange",R),document.addEventListener("MSFullscreenChange",R),()=>{document.removeEventListener("fullscreenchange",R),document.removeEventListener("webkitfullscreenchange",R),document.removeEventListener("mozfullscreenchange",R),document.removeEventListener("MSFullscreenChange",R),w(p)&&w(p).finalize(),document.body.style.overflow=""}));function C(I){u()&&u()(I)}var T=zwe();ps("keydown",Fm,F);var O=Dt(T);let N;var L=P(O),z=P(L),U=H(z,2),Q=H(U,2),de=H(L,2);{var we=I=>{var q=Twe();V(I,q)};_e(de,I=>{a()&&I(we)})}var ne=H(de,2);{var Ee=I=>{var q=Lwe(),se=Dt(q),W=P(se);gs(W,Fe=>B(f,Fe),()=>w(f));var ve=H(se,2);{var xe=Fe=>{var ze=Owe(),ot=P(ze),It=P(ot),sn=H(ot,2);Ct(sn,17,()=>w(m),kt,(Ge,j)=>{var J=Nwe(),De=P(J),Pe=H(De,2),Le=P(Pe);Ae(()=>{ql(De,`background: ${w(j).color??""}`),$e(Le,w(j).name)}),V(Ge,J)}),Ae(()=>$e(It,i())),V(Fe,ze)};_e(ve,Fe=>{w(m).length>0&&Fe(xe)})}V(I,q)};_e(ne,I=>{w(g)||I(Ee)})}gs(O,I=>B(d,I),()=>w(d));var Ke=H(O,2);{var fe=I=>{var q=Bwe(),se=P(q),W=P(se),ve=H(W,2),xe=H(ve,2),Fe=H(se,2),ze=P(Fe),ot=P(ze);gs(ot,Ge=>B(f,Ge),()=>w(f));var It=H(Fe,2);{var sn=Ge=>{var j=Pwe(),J=P(j),De=P(J),Pe=H(J,2);Ct(Pe,17,()=>w(m),kt,(Le,et)=>{var Ft=Iwe(),Xt=P(Ft),qe=H(Xt,2),yt=P(qe);Ae(()=>{ql(Xt,`background: ${w(et).color??""}`),$e(yt,w(et).name)}),V(Le,Ft)}),Ae(()=>$e(De,i())),V(Ge,j)};_e(It,Ge=>{w(m).length>0&&Ge(sn)})}gs(q,Ge=>B(h,Ge),()=>w(h)),je("click",W,A),je("click",ve,E),je("click",xe,()=>D()),V(I,q)};_e(Ke,I=>{w(g)&&I(fe)})}Ae(()=>{N=zt(O,1,"plot-container bar-plot svelte-1swghqy",null,N,{"hidden-plot":w(g)}),jt(O,"draggable",a()?"true":void 0)}),ps("dragstart",O,function(...I){var q;(q=a()?C:void 0)==null||q.apply(this,I)}),ps("dragover",O,function(...I){var q;(q=a()?l():void 0)==null||q.apply(this,I)}),ps("drop",O,function(...I){var q;(q=a()?c():void 0)==null||q.apply(this,I)}),je("click",z,A),je("click",U,E),je("click",Q,M),V(e,T),rn()}wi(["click"]);var jwe=te('
      '),Uwe=te('
      '),qwe=te('
      ');function AE(e,t){nn(t,!0);let n=re(t,"label",3,""),r=re(t,"open",15,!0),i=re(t,"hidden",3,!1);function s(){r(!r())}var o=cs(),a=Dt(o);{var u=c=>{var f=jwe(),d=P(f);{var h=p=>{var g=cs(),m=Dt(g);R$(m,()=>t.children),V(p,g)};_e(d,p=>{t.children&&p(h)})}V(c,f)},l=c=>{var f=qwe(),d=P(f),h=P(d);let p;var g=H(h,2),m=P(g),y=H(d,2);{var v=b=>{var x=Uwe(),_=P(x);{var A=E=>{var S=cs(),k=Dt(S);R$(k,()=>t.children),V(E,S)};_e(_,E=>{t.children&&E(A)})}V(b,x)};_e(y,b=>{r()&&b(v)})}Ae(()=>{p=zt(h,1,"arrow svelte-1jep0a",null,p,{rotated:r()}),$e(m,n())}),je("click",d,s),V(c,f)};_e(a,c=>{i()?c(u):c(l,-1)})}V(e,o),rn()}wi(["click"]);yq();var Wwe=te('
      Loading
      ');function Tc(e,t){nn(t,!1);const r=Z8()||new URLSearchParams(window.location.search).get("__theme")==="dark"||J8()==="dark"?"/static/trackio/trackio_logo_dark.png":"/static/trackio/trackio_logo_light.png";gW();var i=Wwe(),s=P(i),o=P(s),a=P(o),u=H(o,2),l=P(u);Ae(()=>{jt(a,"src",r),jt(l,"src",r)}),V(e,i),rn()}const T6=["BOOLEAN","INT32","INT64","INT96","FLOAT","DOUBLE","BYTE_ARRAY","FIXED_LEN_BYTE_ARRAY"],dl=["PLAIN","GROUP_VAR_INT","PLAIN_DICTIONARY","RLE","BIT_PACKED","DELTA_BINARY_PACKED","DELTA_LENGTH_BYTE_ARRAY","DELTA_BYTE_ARRAY","RLE_DICTIONARY","BYTE_STREAM_SPLIT"],Hwe=["REQUIRED","OPTIONAL","REPEATED"],Gwe=["UTF8","MAP","MAP_KEY_VALUE","LIST","ENUM","DECIMAL","DATE","TIME_MILLIS","TIME_MICROS","TIMESTAMP_MILLIS","TIMESTAMP_MICROS","UINT_8","UINT_16","UINT_32","UINT_64","INT_8","INT_16","INT_32","INT_64","JSON","BSON","INTERVAL"],Ywe=["UNCOMPRESSED","SNAPPY","GZIP","LZO","BROTLI","LZ4","ZSTD","LZ4_RAW"],rU=["DATA_PAGE","INDEX_PAGE","DICTIONARY_PAGE","DATA_PAGE_V2"],Vwe=["SPHERICAL","VINCENTY","THOMAS","ANDOYER","KARNEY"];function SE(e){const t=U0(e);if(t.type===1)return{type:"Point",coordinates:kE(e,t)};if(t.type===2)return{type:"LineString",coordinates:CE(e,t)};if(t.type===3)return{type:"Polygon",coordinates:N6(e,t)};if(t.type===4){const n=[];for(let r=0;r1&&i<=7&&(o=t.getUint32(e.offset,n),e.offset+=4);let a=2;return s&&a++,s===3&&a++,{littleEndian:n,type:i,dim:a,count:o}}function kE(e,t){const n=[];for(let r=0;r{var d;return((d=f.element.logical_type)==null?void 0:d.type)==="VARIANT"}))&&o==="BYTE_ARRAY"&&a!=="UTF8"&&(u==null?void 0:u.type)!=="STRING")return e;if(a==="DECIMAL"){const d=10**-(n.scale||0),h=new Array(e.length);for(let p=0;pr.timestampFromNanoseconds(Xwe(f)));if(a==="DATE")return Array.from(e).map(f=>r.dateFromDays(f));if(a==="TIMESTAMP_MILLIS")return Array.from(e).map(f=>r.timestampFromMilliseconds(f));if(a==="TIMESTAMP_MICROS")return Array.from(e).map(f=>r.timestampFromMicroseconds(f));if(a==="JSON")return e.map(f=>JSON.parse(iU.decode(f)));if(a==="BSON")throw new Error("parquet bson not supported");if(a==="INTERVAL")throw new Error("parquet interval not supported");if((u==null?void 0:u.type)==="GEOMETRY")return e.map(f=>r.geometryFromBytes(f));if((u==null?void 0:u.type)==="GEOGRAPHY")return e.map(f=>r.geographyFromBytes(f));if(a==="UTF8"||(u==null?void 0:u.type)==="STRING"||i&&o==="BYTE_ARRAY")return e.map(f=>r.stringFromBytes(f));if(a==="UINT_64"||(u==null?void 0:u.type)==="INTEGER"&&u.bitWidth===64&&!u.isSigned){if(e instanceof BigInt64Array)return new BigUint64Array(e.buffer,e.byteOffset,e.length);const f=l?new Array(e.length):new BigUint64Array(e.length);for(let d=0;d=2n**BigInt(n-1)&&(t-=2n**BigInt(n)),Number(t)}function Xwe(e){const t=(e>>64n)-2440588n,n=e&0xffffffffffffffffn;return t*86400000000000n+n}function aU(e){if(!e)return;const t=e[1]<<8|e[0],n=t>>15?-1:1,r=t>>10&31,i=t&1023;return r===0?n*2**-14*(i/1024):r===31?i?NaN:n*(1/0):n*2**(r-15)*(1+i/1024)}function uU(e,t,n){const r=e[t],i=[];let s=1;if(r.num_children)for(;i.lengtho.element.name===i);if(!s)throw new Error(`parquet schema element not found: ${t}`);r.push(s),n=s}return r}function Kwe(e){const t=[];function n(r){if(r.children.length)for(const i of r.children)n(i);else t.push(r.path.join("."))}return n(e),t}function cU(e){let t=0;for(const{element:n}of e)n.repetition_type==="REPEATED"&&t++;return t}function m$(e){let t=0;for(const{element:n}of e.slice(1))n.repetition_type!=="REQUIRED"&&t++;return t}function Zwe(e){if(!e||e.element.converted_type!=="LIST"||e.children.length>1)return!1;const t=e.children[0];return!(t.children.length>1||t.element.repetition_type!=="REPEATED")}function Jwe(e){if(!e||e.element.converted_type!=="MAP"||e.children.length>1)return!1;const t=e.children[0];if(t.children.length!==2||t.element.repetition_type!=="REPEATED")return!1;const n=t.children.find(i=>i.element.name==="key");if((n==null?void 0:n.element.repetition_type)==="REPEATED")return!1;const r=t.children.find(i=>i.element.name==="value");return(r==null?void 0:r.element.repetition_type)!=="REPEATED"}function fU(e){if(e.length!==2)return!1;const[,t]=e;return!(t.element.repetition_type==="REPEATED"||t.children.length)}const Qwe=0,L6=1,I6=2,P6=3,eEe=4,tEe=5,nEe=6,rEe=7,iEe=8,sEe=9,oEe=12;function Rb(e){const t={};let n=0;for(;e.offset>4;n=s?n+s:dU(e),t[`field_${n}`]=$E(e,i)}return t}function $E(e,t){switch(t){case L6:return!0;case I6:return!1;case P6:return e.view.getInt8(e.offset++);case eEe:case tEe:return dU(e);case nEe:return FE(e);case rEe:{const n=e.view.getFloat64(e.offset,!0);return e.offset+=8,n}case iEe:{const n=Ll(e),r=new Uint8Array(e.view.buffer,e.view.byteOffset+e.offset,n);return e.offset+=n,r}case sEe:{const n=e.view.getUint8(e.offset++),r=n&15;let i=n>>4;i===15&&(i=Ll(e));const s=r===L6||r===I6,o=new Array(i);for(let a=0;a>>1^-(t&1)}function FE(e){const t=aEe(e);return t>>1n^-(t&1n)}function uEe(e,t){var s,o,a,u,l;const n=new Map,r=(s=t==null?void 0:t.find(({key:c})=>c==="geo"))==null?void 0:s.value,i=(r&&((o=JSON.parse(r))==null?void 0:o.columns))??{};for(const[c,f]of Object.entries(i)){if(f.encoding!=="WKB")continue;const d=f.edges==="spherical"?"GEOGRAPHY":"GEOMETRY",h=((a=f.crs)==null?void 0:a.id)??((l=(u=f.crs)==null?void 0:u.ids)==null?void 0:l[0]),p=h?`${h.authority}:${h.code.toString()}`:void 0;n.set(c,{type:d,crs:p})}for(let c=1;c=0))throw new Error("parquet expected AsyncBuffer");const i=Math.max(0,e.byteLength-n),s=await e.slice(i,e.byteLength),o=new DataView(s);if(o.getUint32(s.byteLength-4,!0)!==827474256)throw new Error("parquet file invalid (footer != PAR1)");const a=o.getUint32(s.byteLength-8,!0);if(a>e.byteLength-8)throw new Error(`parquet metadata length ${a} exceeds available buffer ${e.byteLength-8}`);if(a+8>n){const u=e.byteLength-a-8,l=await e.slice(u,i),c=new ArrayBuffer(a+8),f=new Uint8Array(c);return f.set(new Uint8Array(l)),f.set(new Uint8Array(s),i-u),B6(c,{parsers:t,geoparquet:r})}else return B6(s,{parsers:t,geoparquet:r})}function B6(e,{parsers:t,geoparquet:n=!0}={}){var m;if(!(e instanceof ArrayBuffer))throw new Error("parquet expected ArrayBuffer");const r=new DataView(e);if(t={...Mb,...t},r.byteLength<8)throw new Error("parquet file is too short");if(r.getUint32(r.byteLength-4,!0)!==827474256)throw new Error("parquet file invalid (footer != PAR1)");const i=r.byteLength-8,s=r.getUint32(i,!0);if(s>r.byteLength-8)throw new Error(`parquet metadata length ${s} exceeds available buffer ${r.byteLength-8}`);const o=i-s,u=Rb({view:r,offset:o}),l=u.field_1,c=u.field_2.map(y=>({type:T6[y.field_1],type_length:y.field_2,repetition_type:Hwe[y.field_3],name:Gs(y.field_4),num_children:y.field_5,converted_type:Gwe[y.field_6],scale:y.field_7,precision:y.field_8,field_id:y.field_9,logical_type:dEe(y.field_10)})),f=c.filter(y=>y.type),d=u.field_3,h=u.field_4.map(y=>{var v;return{columns:y.field_1.map((b,x)=>{var _,A,E;return{file_path:Gs(b.field_1),file_offset:b.field_2,meta_data:b.field_3&&{type:T6[b.field_3.field_1],encodings:(_=b.field_3.field_2)==null?void 0:_.map(S=>dl[S]),path_in_schema:b.field_3.field_3.map(Gs),codec:Ywe[b.field_3.field_4],num_values:b.field_3.field_5,total_uncompressed_size:b.field_3.field_6,total_compressed_size:b.field_3.field_7,key_value_metadata:(A=b.field_3.field_8)==null?void 0:A.map(S=>({key:Gs(S.field_1),value:Gs(S.field_2)})),data_page_offset:b.field_3.field_9,index_page_offset:b.field_3.field_10,dictionary_page_offset:b.field_3.field_11,statistics:hEe(b.field_3.field_12,f[x],t),encoding_stats:(E=b.field_3.field_13)==null?void 0:E.map(S=>({page_type:rU[S.field_1],encoding:dl[S.field_2],count:S.field_3})),bloom_filter_offset:b.field_3.field_14,bloom_filter_length:b.field_3.field_15,size_statistics:b.field_3.field_16&&{unencoded_byte_array_data_bytes:b.field_3.field_16.field_1,repetition_level_histogram:b.field_3.field_16.field_2,definition_level_histogram:b.field_3.field_16.field_3},geospatial_statistics:b.field_3.field_17&&{bbox:b.field_3.field_17.field_1&&{xmin:b.field_3.field_17.field_1.field_1,xmax:b.field_3.field_17.field_1.field_2,ymin:b.field_3.field_17.field_1.field_3,ymax:b.field_3.field_17.field_1.field_4,zmin:b.field_3.field_17.field_1.field_5,zmax:b.field_3.field_17.field_1.field_6,mmin:b.field_3.field_17.field_1.field_7,mmax:b.field_3.field_17.field_1.field_8},geospatial_types:b.field_3.field_17.field_2}},offset_index_offset:b.field_4,offset_index_length:b.field_5,column_index_offset:b.field_6,column_index_length:b.field_7,crypto_metadata:b.field_8,encrypted_column_metadata:b.field_9}}),total_byte_size:y.field_2,num_rows:y.field_3,sorting_columns:(v=y.field_4)==null?void 0:v.map(b=>({column_idx:b.field_1,descending:b.field_2,nulls_first:b.field_3})),file_offset:y.field_5,total_compressed_size:y.field_6,ordinal:y.field_7}}),p=(m=u.field_5)==null?void 0:m.map(y=>({key:Gs(y.field_1),value:Gs(y.field_2)})),g=Gs(u.field_6);return n&&uEe(c,p),{version:l,schema:c,num_rows:d,row_groups:h,key_value_metadata:p,created_by:g,metadata_length:s}}function DE({schema:e}){return lU(e,[])[0]}function dEe(e){return e!=null&&e.field_1?{type:"STRING"}:e!=null&&e.field_2?{type:"MAP"}:e!=null&&e.field_3?{type:"LIST"}:e!=null&&e.field_4?{type:"ENUM"}:e!=null&&e.field_5?{type:"DECIMAL",scale:e.field_5.field_1,precision:e.field_5.field_2}:e!=null&&e.field_6?{type:"DATE"}:e!=null&&e.field_7?{type:"TIME",isAdjustedToUTC:e.field_7.field_1,unit:z6(e.field_7.field_2)}:e!=null&&e.field_8?{type:"TIMESTAMP",isAdjustedToUTC:e.field_8.field_1,unit:z6(e.field_8.field_2)}:e!=null&&e.field_10?{type:"INTEGER",bitWidth:e.field_10.field_1,isSigned:e.field_10.field_2}:e!=null&&e.field_11?{type:"NULL"}:e!=null&&e.field_12?{type:"JSON"}:e!=null&&e.field_13?{type:"BSON"}:e!=null&&e.field_14?{type:"UUID"}:e!=null&&e.field_15?{type:"FLOAT16"}:e!=null&&e.field_16?{type:"VARIANT",specification_version:e.field_16.field_1}:e!=null&&e.field_17?{type:"GEOMETRY",crs:Gs(e.field_17.field_1)}:e!=null&&e.field_18?{type:"GEOGRAPHY",crs:Gs(e.field_18.field_1),algorithm:Vwe[e.field_18.field_2]}:e}function z6(e){if(e.field_1)return"MILLIS";if(e.field_2)return"MICROS";if(e.field_3)return"NANOS";throw new Error("parquet time unit required")}function hEe(e,t,n){return e&&{max:q0(e.field_1,t,n),min:q0(e.field_2,t,n),null_count:e.field_3,distinct_count:e.field_4,max_value:q0(e.field_5,t,n),min_value:q0(e.field_6,t,n),is_max_value_exact:e.field_7,is_min_value_exact:e.field_8}}function q0(e,t,n){const{type:r,converted_type:i,logical_type:s}=t;if(e===void 0)return e;if(r==="BOOLEAN")return e[0]===1;if(r==="BYTE_ARRAY")return n.stringFromBytes(e);const o=new DataView(e.buffer,e.byteOffset,e.byteLength);return r==="FLOAT"&&o.byteLength===4?o.getFloat32(0,!0):r==="DOUBLE"&&o.byteLength===8?o.getFloat64(0,!0):r==="INT32"&&i==="DATE"?n.dateFromDays(o.getInt32(0,!0)):r==="INT64"&&i==="TIMESTAMP_MILLIS"?n.timestampFromMilliseconds(o.getBigInt64(0,!0)):r==="INT64"&&i==="TIMESTAMP_MICROS"?n.timestampFromMicroseconds(o.getBigInt64(0,!0)):r==="INT64"&&(s==null?void 0:s.type)==="TIMESTAMP"&&(s==null?void 0:s.unit)==="NANOS"?n.timestampFromNanoseconds(o.getBigInt64(0,!0)):r==="INT64"&&(s==null?void 0:s.type)==="TIMESTAMP"&&(s==null?void 0:s.unit)==="MICROS"?n.timestampFromMicroseconds(o.getBigInt64(0,!0)):r==="INT64"&&(s==null?void 0:s.type)==="TIMESTAMP"?n.timestampFromMilliseconds(o.getBigInt64(0,!0)):r==="INT32"&&o.byteLength===4?o.getInt32(0,!0):r==="INT64"&&o.byteLength===8?o.getBigInt64(0,!0):i==="DECIMAL"?oU(e)*10**-(t.scale||0):(s==null?void 0:s.type)==="FLOAT16"?aU(e):e}function pEe(e){const t=Rb(e);return{page_locations:t.field_1.map(gEe),unencoded_byte_array_data_bytes:t.field_2}}function gEe(e){return{offset:e.field_1,compressed_page_size:e.field_2,first_row_index:e.field_3}}function hU(e,t){for(let r=0;rn.split(".")[0])),[...new Set(t)]}function Hh(e,t,n=!0){return"$and"in t&&Array.isArray(t.$and)?t.$and.every(r=>Hh(e,r,n)):"$or"in t&&Array.isArray(t.$or)?t.$or.some(r=>Hh(e,r,n)):"$nor"in t&&Array.isArray(t.$nor)?!t.$nor.some(r=>Hh(e,r,n)):Object.entries(t).every(([r,i])=>{const s=mEe(e,r);return typeof i!="object"||i===null||Array.isArray(i)?pa(s,i,n):Object.entries(i||{}).every(([o,a])=>o==="$gt"?s>a:o==="$gte"?s>=a:o==="$lt"?sME({rowGroup:e,physicalColumns:t,filter:s,strict:r}));if("$or"in n&&Array.isArray(n.$or))return n.$or.every(s=>ME({rowGroup:e,physicalColumns:t,filter:s,strict:r}));if("$nor"in n&&Array.isArray(n.$nor))return!1;for(const[s,o]of Object.entries(n)){const a=t.indexOf(s);if(a===-1)continue;const u=(i=e.columns[a].meta_data)==null?void 0:i.statistics;if(!u)continue;const{min:l,max:c,min_value:f,max_value:d}=u,h=f!==void 0?f:l,p=d!==void 0?d:c;if(!(h===void 0||p===void 0)){for(const[g,m]of Object.entries(o||{}))if(g==="$gt"&&p<=m||g==="$gte"&&p=m||g==="$lte"&&h>m||g==="$eq"&&(mp)||g==="$ne"&&pa(h,p,r)&&pa(h,m,r)||g==="$in"&&Array.isArray(m)&&m.every(y=>yp)||g==="$nin"&&Array.isArray(m)&&pa(h,p,r)&&m.includes(h))return!0}}return!1}function mEe(e,t){let n=e;for(const r of t.split("."))n=n==null?void 0:n[r];return n}const yEe=1<<21;function vEe({metadata:e,rowStart:t=0,rowEnd:n=1/0,columns:r,filter:i,filterStrict:s=!0,useOffsetIndex:o=!1}){if(!e)throw new Error("parquetPlan requires metadata");const a=[],u=[],l=[],c=Kwe(DE(e));let f=0;for(const d of e.row_groups){const h=Number(d.num_rows),p=f+h;if(h>0&&p>t&&fe.slice(r,i));return{byteLength:e.byteLength,slice(r,i=e.byteLength){const s=t.findIndex(({startByte:o,endByte:a})=>o<=r&&i<=a);if(s<0)return e.slice(r,i);if(t[s].startByte!==r||t[s].endByte!==i){const o=r-t[s].startByte,a=i-t[s].startByte;return n[s]instanceof Promise?n[s].then(u=>u.slice(o,a)):n[s].slice(o,a)}else return n[s]}}}const y$=new TextDecoder,j6=new WeakMap;function gU(e,t=Mb){if(Array.isArray(e))return e.map(n=>gU(n,t));if(typeof e!="object")return e;if("metadata"in e){const n=xEe(e.metadata),r=e.typed_value&&km(e.typed_value,n,t),i=e.value&&Hp(fy(e.value),n,t);return r&&i?{...i,...r}:r??i}return e}function km(e,t,n){if(e&&typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Uint8Array)){if("typed_value"in e)return km(e.typed_value,t,n);if("value"in e&&e.value instanceof Uint8Array)return Hp(fy(e.value),t,n);const r={};for(const[i,s]of Object.entries(e))r[i]=km(s,t,n);return r}return e instanceof Uint8Array?Hp(fy(e),t,n):Array.isArray(e)?e.map(r=>km(r,t,n)):e}function fy(e){return{view:new DataView(e.buffer,e.byteOffset,e.byteLength),offset:0}}function xEe(e){let t=j6.get(e.buffer);t||(t=new Map,j6.set(e.buffer,t));const n=`${e.byteOffset}:${e.byteLength}`,r=t.get(n);if(r)return r;const i=fy(e),s=i.view.getUint8(i.offset++),o=s&15;if(o!==1)throw new Error(`parquet unsupported variant metadata version: ${o}`);const a=(s>>4&1)===1,u=(s>>6&3)+1,l=Il(i,u),c=new Array(l+1);for(let p=0;p>2;if(i===0)return _Ee(e,s,n);if(i===2)return wEe(e,s,t,n);if(i===3)return EEe(e,s,t,n);const o=new Uint8Array(e.view.buffer,e.view.byteOffset+e.offset,s);return e.offset+=s,y$.decode(o)}function _Ee(e,t,n){switch(t){case 0:return null;case 1:return!0;case 2:return!1;case 3:{const r=e.view.getInt8(e.offset);return e.offset+=1,r}case 4:{const r=e.view.getInt16(e.offset,!0);return e.offset+=2,r}case 5:{const r=e.view.getInt32(e.offset,!0);return e.offset+=4,r}case 6:{const r=e.view.getBigInt64(e.offset,!0);return e.offset+=8,r}case 7:{const r=e.view.getFloat64(e.offset,!0);return e.offset+=8,r}case 8:return Px(e,4);case 9:return Px(e,8);case 10:return Px(e,16);case 11:{const r=e.view.getInt32(e.offset,!0);return e.offset+=4,n.dateFromDays(r)}case 12:case 13:{const r=e.view.getBigInt64(e.offset,!0);return e.offset+=8,n.timestampFromMicroseconds(r)}case 14:{const r=e.view.getFloat32(e.offset,!0);return e.offset+=4,r}case 15:return U6(e);case 16:{const r=U6(e);return y$.decode(r)}case 17:{const r=e.view.getBigInt64(e.offset,!0);return e.offset+=8,r}case 18:case 19:{const r=e.view.getBigInt64(e.offset,!0);return e.offset+=8,n.timestampFromNanoseconds(r)}case 20:{const r=new Uint8Array(e.view.buffer,e.view.byteOffset+e.offset,16);e.offset+=16;const i=Array.from(r,s=>s.toString(16).padStart(2,"0")).join("");return`${i.slice(0,8)}-${i.slice(8,12)}-${i.slice(12,16)}-${i.slice(16,20)}-${i.slice(20)}`}default:throw new Error(`parquet unsupported variant primitive type: ${t}`)}}function wEe(e,t,n,r){const i=(t&3)+1,s=(t>>2&3)+1,a=t>>4&1?Il(e,4):e.view.getUint8(e.offset++),u=new Array(a);for(let f=0;f>2&1,o=i+1,a=Il(e,s?4:1),u=new Array(a+1);for(let f=0;fp.repetition_type);let u=0;const l=[e];let c=e,f=0,d=0,h=0;if(n[0])for(;f>h&g;for(h+=d;h>=8;)h-=8n,e.offset++,h&&(m|=BigInt(e.view.getUint8(e.offset))<>>1;SEe(e,a,t,n,s),s+=a}}e.offset=i+r}function SEe(e,t,n,r,i){const s=n+7>>3;let o=0;for(let a=0;a>1<<3;const o=(1<8?(l-=8,u-=8,a>>>=8):u-l>l&o),s--,l+=n);return i}function bU(e,t,n,r){const i=CEe(n,r),s=new Uint8Array(t*i);for(let o=0;o=n)throw new Error("invalid snappy length header");for(;i=n)throw new Error("missing eof marker");if((o&3)===0){let u=(o>>>2)+1;if(u>60){if(i+3>=n)throw new Error("snappy error literal pos + 3 >= inputLength");const l=u-60;u=e[i]+(e[i+1]<<8)+(e[i+2]<<16)+(e[i+3]<<24),u=(u&LEe[l])+1,i+=l}if(i+u>n)throw new Error("snappy error literal exceeds input length");W6(e,i,t,s,u),i+=u,s+=u}else{let u=0;switch(o&3){case 1:a=(o>>>2&7)+4,u=e[i]+(o>>>5<<8),i++;break;case 2:if(n<=i+1)throw new Error("snappy error end of input");a=(o>>>2)+1,u=e[i]+(e[i+1]<<8),i+=2;break;case 3:if(n<=i+3)throw new Error("snappy error end of input");a=(o>>>2)+1,u=e[i]+(e[i+1]<<8)+(e[i+2]<<16)+(e[i+3]<<24),i+=4;break}if(u===0||isNaN(u))throw new Error(`invalid offset ${u} pos ${i} inputLength ${n}`);if(u>s)throw new Error("cannot copy from before start of buffer");W6(t,s-u,t,s,a),s+=a}}if(s!==r)throw new Error("premature end of input")}function PEe(e,t,{type:n,element:r,schemaPath:i}){const s=new DataView(e.buffer,e.byteOffset,e.byteLength),o={view:s,offset:0};let a;const u=BEe(o,t,i),{definitionLevels:l,numNulls:c}=zEe(o,t,i),f=t.num_values-c;if(t.encoding==="PLAIN")a=v$(o,n,f,r.type_length);else if(t.encoding==="PLAIN_DICTIONARY"||t.encoding==="RLE_DICTIONARY"||t.encoding==="RLE"){const d=n==="BOOLEAN"?1:s.getUint8(o.offset++);d?(a=new Array(f),n==="BOOLEAN"?(ku(o,d,a),a=a.map(h=>!!h)):ku(o,d,a,s.byteLength-o.offset)):a=new Uint8Array(f)}else if(t.encoding==="BYTE_STREAM_SPLIT")a=bU(o,f,n,r.type_length);else if(t.encoding==="DELTA_BINARY_PACKED")a=n==="INT32"?new Int32Array(f):new BigInt64Array(f),Gp(o,f,a);else if(t.encoding==="DELTA_LENGTH_BYTE_ARRAY")a=new Array(f),vU(o,f,a);else throw new Error(`parquet unsupported encoding: ${t.encoding}`);return{definitionLevels:l,repetitionLevels:u,dataPage:a}}function BEe(e,t,n){if(n.length>1){const r=cU(n);if(r){const i=new Array(t.num_values);return ku(e,Tb(r),i),i}}return[]}function zEe(e,t,n){const r=m$(n);if(!r)return{definitionLevels:[],numNulls:0};const i=new Array(t.num_values);ku(e,Tb(r),i);let s=t.num_values;for(const o of i)o===r&&s--;return s===0&&(i.length=0),{definitionLevels:i,numNulls:s}}function RE(e,t,n,r){let i;const s=r==null?void 0:r[n];if(n==="UNCOMPRESSED")i=e;else if(s)i=s(e,t);else if(n==="SNAPPY")i=new Uint8Array(t),IEe(e,i);else throw new Error(`parquet unsupported compression codec: ${n}`);if((i==null?void 0:i.length)!==t)throw new Error(`parquet decompressed page length ${i==null?void 0:i.length} does not match header ${t}`);return i}function jEe(e,t,n){const i={view:new DataView(e.buffer,e.byteOffset,e.byteLength),offset:0},{type:s,element:o,schemaPath:a,codec:u,compressors:l}=n,c=t.data_page_header_v2;if(!c)throw new Error("parquet data page header v2 is undefined");const f=UEe(i,c,a);i.offset=c.repetition_levels_byte_length;const d=qEe(i,c,a),h=t.uncompressed_page_size-c.definition_levels_byte_length-c.repetition_levels_byte_length;let p=e.subarray(i.offset);c.is_compressed!==!1&&(p=RE(p,h,u,l));const g=new DataView(p.buffer,p.byteOffset,p.byteLength),m={view:g,offset:0};let y;const v=c.num_values-c.num_nulls;if(c.encoding==="PLAIN")y=v$(m,s,v,o.type_length);else if(c.encoding==="RLE")y=new Array(v),ku(m,1,y),y=y.map(b=>!!b);else if(c.encoding==="PLAIN_DICTIONARY"||c.encoding==="RLE_DICTIONARY"){const b=g.getUint8(m.offset++);y=new Array(v),ku(m,b,y,h-1)}else if(c.encoding==="DELTA_BINARY_PACKED")y=s==="INT32"?new Int32Array(v):new BigInt64Array(v),Gp(m,v,y);else if(c.encoding==="DELTA_LENGTH_BYTE_ARRAY")y=new Array(v),vU(m,v,y);else if(c.encoding==="DELTA_BYTE_ARRAY")y=new Array(v),AEe(m,v,y);else if(c.encoding==="BYTE_STREAM_SPLIT")y=bU(m,v,s,o.type_length);else throw new Error(`parquet unsupported encoding: ${c.encoding}`);return{definitionLevels:d,repetitionLevels:f,dataPage:y}}function UEe(e,t,n){const r=cU(n);if(!r)return[];const i=new Array(t.num_values);return ku(e,Tb(r),i,t.repetition_levels_byte_length),i}function qEe(e,t,n){const r=m$(n);if(r){const i=new Array(t.num_values);return ku(e,Tb(r),i,t.definition_levels_byte_length),i}}function H6(e,{groupStart:t,selectStart:n,selectEnd:r},i,s){const{pathInSchema:o,schemaPath:a}=i,u=fU(a),l=[];let c,f,d=0,h=0;const p=s&&(()=>{f&&s({pathInSchema:o,columnData:f,rowStart:t+d-f.length,rowEnd:t+d})});for(;(u?d=e.view.byteLength-1);){const g=WEe(e);if(g.type==="DICTIONARY_PAGE"){const{data:m}=G6(e,g,i,c,void 0,0);m&&(c=sU(m,i))}else{const m=(f==null?void 0:f.length)||0,y=G6(e,g,i,c,f,n-d);y.skipped?(l.length||(h+=y.skipped),d+=y.skipped):y.data&&f===y.data?d+=y.data.length-m:y.data&&y.data.length&&(p==null||p(),l.push(y.data),d+=y.data.length,f=y.data)}}return p==null||p(),{data:l,skipped:h}}function G6(e,t,n,r,i,s){const{type:o,element:a,schemaPath:u,codec:l,compressors:c}=n,f=new Uint8Array(e.view.buffer,e.view.byteOffset+e.offset,t.compressed_page_size);if(e.offset+=t.compressed_page_size,t.type==="DATA_PAGE"){const d=t.data_page_header;if(!d)throw new Error("parquet data page header is undefined");if(s>d.num_values&&fU(u))return{skipped:d.num_values};const h=RE(f,Number(t.uncompressed_page_size),l,c),{definitionLevels:p,repetitionLevels:g,dataPage:m}=PEe(h,d,n),y=O6(m,r,d.encoding,n),v=Array.isArray(i)?i:[];return{skipped:0,data:q6(v,p,g,y,u)}}else if(t.type==="DATA_PAGE_V2"){const d=t.data_page_header_v2;if(!d)throw new Error("parquet data page header v2 is undefined");if(s>d.num_rows)return{skipped:d.num_values};const{definitionLevels:h,repetitionLevels:p,dataPage:g}=jEe(f,t,n),m=O6(g,r,d.encoding,n),y=Array.isArray(i)?i:[];return{skipped:0,data:q6(y,h,p,m,u)}}else if(t.type==="DICTIONARY_PAGE"){const d=t.dictionary_page_header;if(!d)throw new Error("parquet dictionary page header is undefined");const h=RE(f,Number(t.uncompressed_page_size),l,c),p={view:new DataView(h.buffer,h.byteOffset,h.byteLength),offset:0};return{skipped:0,data:v$(p,o,d.num_values,a.type_length)}}else throw new Error(`parquet unsupported page type: ${t.type}`)}function WEe(e){const t=Rb(e),n=rU[t.field_1],r=t.field_2,i=t.field_3,s=t.field_4,o=t.field_5&&{num_values:t.field_5.field_1,encoding:dl[t.field_5.field_2],definition_level_encoding:dl[t.field_5.field_3],repetition_level_encoding:dl[t.field_5.field_4],statistics:t.field_5.field_5&&{max:t.field_5.field_5.field_1,min:t.field_5.field_5.field_2,null_count:t.field_5.field_5.field_3,distinct_count:t.field_5.field_5.field_4,max_value:t.field_5.field_5.field_5,min_value:t.field_5.field_5.field_6}},a=t.field_6,u=t.field_7&&{num_values:t.field_7.field_1,encoding:dl[t.field_7.field_2],is_sorted:t.field_7.field_3},l=t.field_8&&{num_values:t.field_8.field_1,num_nulls:t.field_8.field_2,num_rows:t.field_8.field_3,encoding:dl[t.field_8.field_4],definition_levels_byte_length:t.field_8.field_5,repetition_levels_byte_length:t.field_8.field_6,is_compressed:t.field_8.field_7===void 0?!0:t.field_8.field_7,statistics:t.field_8.field_8};return{type:n,uncompressed_page_size:r,compressed_page_size:i,crc:s,data_page_header:o,index_page_header:a,dictionary_page_header:u,data_page_header_v2:l}}function HEe(e,{metadata:t},n){const{file:r,compressors:i,utf8:s}=e,o=[],a={...Mb,...e.parsers};for(const u of n.chunks){const{columnMetadata:l}=u,c=lU(t.schema,l.path_in_schema),f={pathInSchema:l.path_in_schema,type:l.type,element:c[c.length-1].element,schemaPath:c,codec:l.codec,parsers:a,compressors:i,utf8:s};if(!("offsetIndex"in u)){o.push({pathInSchema:l.path_in_schema,data:Promise.resolve(r.slice(u.range.startByte,u.range.endByte)).then(d=>{const h={view:new DataView(d),offset:0};return H6(h,n,f,e.onPage)})});continue}o.push({pathInSchema:l.path_in_schema,data:Promise.resolve(r.slice(u.offsetIndex.startByte,u.offsetIndex.endByte)).then(async d=>{const h=pEe({view:new DataView(d),offset:0}),{selectStart:p,selectEnd:g}=n,m=h.page_locations;let y=NaN,v=NaN,b=0;for(let k=0;kp&&(Number.isNaN(y)&&(y=Number($.offset),b=D),v=Number($.offset)+$.compressed_page_size)}const x=await r.slice(y,v),_={view:new DataView(x),offset:0},A=b?{...n,groupStart:n.groupStart+b,selectStart:n.selectStart-b,selectEnd:n.selectEnd-b}:n,{data:E,skipped:S}=H6(_,A,f,e.onPage);return{data:E,skipped:b+S}})})}return{groupStart:n.groupStart,groupRows:n.groupRows,asyncColumns:o}}async function Y6({asyncColumns:e},t,n,r,i){const s=await Promise.all(e.map(async({data:f})=>{const d=await f;return{...d,data:pU(d.data)}})),o=e.map(f=>f.pathInSchema[0]).filter(f=>!r||r.includes(f)),a=r??o,u=a.map(f=>e.findIndex(d=>d.pathInSchema[0]===f)),l=n-t;if(i==="object"){const f=Array(l);for(let d=0;d=0){const{data:m,skipped:y}=s[g];h[p]=m[d-y]}}c[f]=h}return c}function GEe(e,t,n){const{asyncColumns:r}=e;n={...Mb,...n};const i=[];for(const s of t.children)if(s.children.length){const o=r.filter(l=>l.pathInSchema[0]===s.element.name);if(!o.length)continue;const a=new Map,u=Promise.all(o.map(l=>l.data.then(({data:c})=>{a.set(l.pathInSchema.join("."),pU(c))}))).then(()=>{Gh(a,s,n);const l=a.get(s.path.join("."));if(!l)throw new Error("parquet column data not assembled");return{data:[l],skipped:0}});i.push({pathInSchema:s.path,data:u})}else{const o=r.find(a=>a.pathInSchema[0]===s.element.name);o&&i.push(o)}return{...e,asyncColumns:i}}async function YEe(e){e.metadata??(e.metadata=await fEe(e.file,e));const{rowStart:t=0,rowEnd:n,columns:r,onChunk:i,onComplete:s,rowFormat:o,filter:a,filterStrict:u=!0}=e;if(a&&o!=="object")throw new Error('parquet filter requires rowFormat: "object"');const l=Sm(a);if(l.length){const m=DE(e.metadata).children.map(v=>v.element.name),y=l.filter(v=>!m.includes(v));if(y.length)throw new Error(`parquet filter columns not found: ${y.join(", ")}`)}let c=r,f=!1;if(r&&a){const m=l.filter(y=>!r.includes(y));m.length&&(c=[...r,...m],f=!0)}const d=c!==r?{...e,columns:c}:e,h=VEe(d);if(!s&&!i){for(const{asyncColumns:m}of h)for(const{data:y}of m)await y;return}const p=DE(e.metadata),g=h.map(m=>GEe(m,p,e.parsers));if(i)for(const m of g)for(const y of m.asyncColumns)y.data.then(({data:v,skipped:b})=>{let x=m.groupStart+b;for(const _ of v)i({columnName:y.pathInSchema[0],columnData:_,rowStart:x,rowEnd:x+_.length}),x+=_.length});if(s){const m=[];for(const y of g){const v=Math.max(t-y.groupStart,0),b=Math.min((n??1/0)-y.groupStart,y.groupRows),x=o==="object"?await Y6(y,v,b,c,"object"):await Y6(y,v,b,r,"array");if(a){for(const _ of x)if(Hh(_,a,u)){if(f&&r)for(const A of l)r.includes(A)||delete _[A];m.push(_)}}else hU(m,x)}s(m)}else for(const{asyncColumns:m}of g)for(const{data:y}of m)await y}function VEe(e){if(!e.metadata)throw new Error("parquet requires metadata");const t=vEe(e);return e.file=bEe(e.file,t),t.groups.map(n=>HEe(e,t,n))}const W0=new Map;function XEe(e){const t={};for(const n in e){const r=e[n];t[n]=typeof r=="bigint"?Number(r):r}return t}async function b$(e,t={}){if(W0.has(e))return W0.get(e);const n=await fetch(e,{headers:t});if(!n.ok){if(n.status===404)return W0.set(e,[]),[];throw new Error(`Failed to fetch ${e}: ${n.status}`)}const r=await n.arrayBuffer();let i=[];return await YEe({file:r,rowFormat:"object",onComplete:s=>{i=s.map(XEe)}}),W0.set(e,i),i}let Yt=null,H0=null,G0=null,Y0=null,Vc=null,Xc=null,qs=null;function Nc(e){return Yt.bucket_id?`https://huggingface.co/buckets/${Yt.bucket_id}/resolve/${e}`:`https://huggingface.co/datasets/${Yt.dataset_id}/resolve/main/${e}`}function Cu(){return Yt.hf_token?{Authorization:`Bearer ${Yt.hf_token}`}:{}}async function KEe(e){Yt=e}function ZEe(){return!Yt||Yt.mode!=="static"?null:Yt.bucket_id?{url:`https://huggingface.co/buckets/${Yt.bucket_id}`}:Yt.dataset_id?{url:`https://huggingface.co/datasets/${Yt.dataset_id}`}:null}async function xU(){return H0||(H0=await b$(Nc("metrics.parquet"),Cu()),H0)}async function JEe(){return G0||(G0=await b$(Nc("aux/system_metrics.parquet"),Cu()),G0)}async function QEe(){return Y0||(Y0=await b$(Nc("aux/configs.parquet"),Cu()),Y0)}async function x$(){if(Vc)return Vc;const e=await fetch(Nc("runs.json"),{headers:Cu()});return e.ok?(Vc=await e.json(),Vc):(Vc=[],Vc)}async function eAe(){if(Xc)return Xc;const e=await fetch(Nc("settings.json"),{headers:Cu()});return e.ok?(Xc=await e.json(),Xc):(Xc={},Xc)}const _$=new Set(["id","run_name","timestamp","step","log_id","space_id","created_at"]);function Ob(e){return!e||e.length===0?{rows:[],columns:[]}:{rows:e,columns:Object.keys(e[0])}}async function tAe(){return[Yt.project]}async function nAe(){return(await x$()).map(t=>t.name)}async function rAe(e,t){const n=await xU(),{rows:r,columns:i}=Ob(n),s=i.filter(u=>!_$.has(u)),o=r.filter(u=>u.run_name===t),a=new Set;for(const u of o)for(const l of s)u[l]!==null&&u[l]!==void 0&&a.add(l);return[...a]}async function iAe(e,t){const n=await xU(),{rows:r}=Ob(n);return r.filter(s=>s.run_name===t).map(s=>{const o={};for(const[a,u]of Object.entries(s))if(!_$.has(a)&&u!=null)if(typeof u=="string"&&u.startsWith("{")&&u.includes("_type"))try{o[a]=JSON.parse(u)}catch{o[a]=u}else o[a]=u;return o.timestamp=s.timestamp,o.step=s.step,o})}async function sAe(){const e=await x$(),t=e.map(r=>r.name),n=e.map(r=>r.last_step||0);return{project:Yt.project,num_runs:e.length,runs:t,last_activity:n.length?Math.max(...n):null}}async function oAe(e,t){const r=(await x$()).find(l=>l.name===t);if(!r)return{project:Yt.project,run:t,num_logs:0,metrics:[],config:null,last_step:null};const i=await rAe(Yt.project,t);let s=null;const o=await QEe(),{rows:a}=Ob(o),u=a.find(l=>l.run_name===t);if(u){s={};for(const[l,c]of Object.entries(u))l!=="id"&&l!=="run_name"&&l!=="created_at"&&(s[l]=c)}return{project:Yt.project,run:t,num_logs:r.log_count||0,metrics:i,config:s,last_step:r.last_step}}async function aAe(){return[]}async function uAe(e,t){const n=await JEe(),{rows:r}=Ob(n);return r.filter(s=>s.run_name===t).map(s=>{const o={};for(const[a,u]of Object.entries(s))_$.has(a)||u!=null&&(o[a]=u);return o.timestamp=s.timestamp,o})}async function lAe(){const e=await eAe();return{logo_urls:{light:"/assets/trackio_logo_type_light_transparent.png",dark:"/assets/trackio_logo_type_dark_transparent.png"},color_palette:e.color_palette||[],plot_order:e.plot_order||[],table_truncate_length:250}}async function cAe(){if(qs)return qs;if(Yt.bucket_id){const r=await fetch(`https://huggingface.co/api/buckets/${Yt.bucket_id}/tree?prefix=media/files/&recursive=true`,{headers:Cu()});if(!r.ok)return qs=[],qs;const i=await r.json();return qs=(Array.isArray(i)?i:[]).filter(s=>s.type==="file").map(s=>({name:s.path.split("/").at(-1)??s.path,path:s.path.slice(6)})),qs}const e=await fetch(`https://huggingface.co/api/datasets/${Yt.dataset_id}`,{headers:Cu()});if(!e.ok)return qs=[],qs;const t=await e.json();return qs=(Array.isArray(t==null?void 0:t.siblings)?t.siblings:[]).map(r=>r==null?void 0:r.rfilename).filter(r=>typeof r=="string"&&r.startsWith("media/files/")).map(r=>({name:r.split("/").at(-1)??r,path:r.slice(6)})),qs}async function fAe(){return{allowed:!1}}async function dAe(){throw new Error("Not supported in static mode")}async function hAe(){throw new Error("Not supported in static mode")}function _U(e){return Yt.project&&e.startsWith(Yt.project+"/")?e.slice(Yt.project.length+1):e}const Bx=new Map;async function pAe(e){const t=_U(e),n=Nc(`media/${t}`);if(Bx.has(n))return Bx.get(n);const r=await fetch(n,{headers:Cu()});if(!r.ok)return n;const i=await r.blob(),s=URL.createObjectURL(i);return Bx.set(n,s),s}function wU(e){const t=_U(e);return Nc(`media/${t}`)}const Yp=window.__trackio_base||"";let bf=null,zx=null,EU="";async function gAe(){try{const e=await fetch(`${Yp}/config.json`);if(e.ok){const t=await e.json();if(t.mode==="static")return await KEe(t),!0}}catch{}return!1}async function Tr(){return bf!==null?bf:(zx||(zx=gAe().then(e=>(bf=e,e))),zx)}function mAe(){const e=sessionStorage.getItem("trackio_oauth_session");return e?{"x-trackio-oauth-session":e}:{}}async function Zi(e,t={}){const n=`${Yp}/gradio_api/call${e}`,r=await fetch(n,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...mAe()},body:JSON.stringify({data:Object.values(t)})});if(!r.ok)throw new Error(`API call ${e} failed: ${r.status}`);const s=(await r.json()).event_id,o=await fetch(`${Yp}/gradio_api/call${e}/${s}`,{credentials:"include"});if(!o.ok)throw new Error(`API result ${e} failed: ${o.status}`);const u=(await o.text()).trim().split(` +`);for(let l=0;l

      No projects

      Create a project by calling trackio.init(project="…") in your training script.

      '),FAe=te('

      No run selected

      Select one or more runs in the sidebar.

      '),DAe=te('

      Start logging with Trackio

      You can create a new project by calling trackio.init():

      Then call trackio.log() to log metrics:

      Finally, call trackio.finish() to finish the run:

      '),MAe=te('
      '),RAe=te('
      '),TAe=te('
      ',1),NAe=te('
      ');function OAe(e,t){nn(t,!0);let n=re(t,"project",3,null),r=re(t,"selectedRuns",19,()=>[]),i=re(t,"allRuns",19,()=>[]),s=re(t,"smoothing",3,10),o=re(t,"xAxis",3,"step"),a=re(t,"logScaleX",3,!1),u=re(t,"logScaleY",3,!1),l=re(t,"metricFilter",3,""),c=re(t,"showHeaders",3,!0),f=re(t,"appBootstrapReady",3,!1),d=re(t,"plotOrder",19,()=>[]),h=re(t,"metricColumns",31,()=>at([])),p=le(at([])),g=le("step"),m=le(at([])),y=le(at(new Set)),v=le(null),b=le(!1),x=le(at({})),_=le(at({group:null,index:-1})),A=new Map,E=null,S=Me(()=>xy(i())),k=Me(()=>{let fe=l()?wwe(w(m),l()):w(m);return tU(fe,d())}),$=Me(()=>Object.keys(w(k))),D=Me(()=>{const fe=new Map,I=w(p),q=w(g),se=w(v);for(const W of Object.values(w(k))){for(const ve of W.direct)fe.has(ve)||fe.set(ve,wE(I,q,ve,se));for(const ve of Object.values(W.subgroups))for(const xe of ve)fe.has(xe)||fe.set(xe,wE(I,q,xe,se))}return fe});function M(fe,I){const q=w(x)[fe];if(!q)return I;const se=[];for(const W of q)I.includes(W)&&se.push(W);for(const W of I)se.includes(W)||se.push(W);return se}function R(fe,I,q){B(_,{group:fe,index:I},!0),q.dataTransfer.effectAllowed="move",q.dataTransfer.setData("text/plain","")}function F(fe,I,q){w(_).group===fe&&(q.preventDefault(),q.dataTransfer.dropEffect="move")}function C(fe,I,q,se){if(se.preventDefault(),w(_).group!==fe||w(_).index===I){B(_,{group:null,index:-1},!0);return}const W=[...q],[ve]=W.splice(w(_).index,1);W.splice(I,0,ve),B(x,{...w(x),[fe]:W},!0),B(_,{group:null,index:-1},!0)}function T(){if(!n()||r().length===0){B(p,[],!0),B(m,[],!0);return}const fe=[];for(const ve of r()){const xe=A.get(ve);if(!xe)continue;const Fe=vwe(xe,ve,s(),o(),a(),u());Fe&&(fe.push(...Fe.rows),B(g,Fe.xColumn,!0))}B(p,fe,!0);const I=fe.filter(ve=>ve.data_type==="original"||!ve.data_type),q=xwe(I).filter(ve=>ve!==w(g)&&ve!=="run"&&ve!=="data_type"&&ve!=="x_axis");B(m,q,!0),h(q);const se=new Map;for(const ve of I){const xe=ve.run;for(const Fe of q){if(ve[Fe]==null)continue;const ze=`${Fe}\0${xe}`;se.set(ze,(se.get(ze)||0)+1)}}const W=new Set(q);for(const[ve,xe]of se)xe>1&&W.delete(ve.split("\0")[0]);B(y,W,!0)}async function O(){if(!f()){B(b,!1);return}if(!n()||r().length===0){B(p,[],!0),B(m,[],!0),B(b,!0);return}let fe=!1;for(const I of r())if(!A.has(I)){const q=await dy(n(),I);A.set(I,q),fe=!0}(fe||!w(b))&&T(),B(b,!0)}async function N(){if(!n()||r().length===0)return;let fe=!1;for(const I of r()){const q=await dy(n(),I),se=A.get(I);(!se||q.length!==se.length)&&(A.set(I,q),fe=!0)}fe&&T()}tn(()=>{n(),r(),f(),A=n()?A:new Map,O()}),tn(()=>{s(),o(),a(),u(),w(b)&&T()}),vd(()=>{const fe=Ys("xmin"),I=Ys("xmax");if(fe!=null&&fe!==""&&I!=null&&I!==""){const q=parseFloat(fe),se=parseFloat(I);!Number.isNaN(q)&&!Number.isNaN(se)&&q{E&&clearInterval(E)}});function L(fe){fe&&fe.length===2&&B(v,fe,!0)}function z(){B(v,null)}var U=NAe(),Q=P(U);{var de=fe=>{Tc(fe,{})},we=fe=>{var I=$Ae();V(fe,I)},ne=fe=>{var I=FAe();V(fe,I)},Ee=fe=>{var I=DAe(),q=H(P(I),4),se=P(q);se.textContent=`import trackio +trackio.init(project="my-project")`;var W=H(q,4),ve=P(W);ve.textContent=`for i in range(10): + trackio.log({"loss": 1/(i+1)})`;var xe=H(W,4),Fe=P(xe);Fe.textContent="trackio.finish()",V(fe,I)},Ke=fe=>{var I=cs(),q=Dt(I);Ct(q,17,()=>w($),kt,(se,W)=>{const ve=Me(()=>w(k)[w(W)]),xe=Me(()=>`${w(W)}:direct`),Fe=Me(()=>M(w(xe),w(ve).direct)),ze=Me(()=>w(ve).direct.length),ot=Me(()=>Object.values(w(ve).subgroups).reduce((sn,Ge)=>sn+Ge.length,0)),It=Me(()=>w(ze)+w(ot));{let sn=Me(()=>!c());AE(se,{get label(){return`${w(W)??""} (${w(It)??""})`},open:!0,get hidden(){return w(sn)},children:(Ge,j)=>{var J=TAe(),De=Dt(J);{var Pe=et=>{var Ft=MAe();Ct(Ft,21,()=>w(Fe),kt,(Xt,qe,yt)=>{const pt=Me(()=>w(D).get(w(qe))??{data:[],yExtent:void 0}),wn=Me(()=>w(pt).data),Zn=Me(()=>w(pt).yExtent),Wt=Me(()=>w(y).has(w(qe))),Rt=Me(()=>c()&&w(qe).split("/").slice(1).join("/")||w(qe));var Tt=cs(),ti=Dt(Tt);{var hn=Pt=>{var ni=cs(),zs=Dt(ni);{var zo=Nr=>{R6(Nr,{get data(){return w(wn)},get y(){return w(qe)},get title(){return w(Rt)},get colorMap(){return w(S)},draggable:!0,ondragstart:Jn=>R(w(xe),yt,Jn),ondragover:Jn=>F(w(xe),yt,Jn),ondrop:Jn=>C(w(xe),yt,w(Fe),Jn)})},Da=Nr=>{EE(Nr,{get data(){return w(wn)},get x(){return w(g)},get y(){return w(qe)},get title(){return w(Rt)},get colorMap(){return w(S)},get xLim(){return w(v)},get yExtent(){return w(Zn)},onSelect:L,onResetZoom:z,draggable:!0,ondragstart:Jn=>R(w(xe),yt,Jn),ondragover:Jn=>F(w(xe),yt,Jn),ondrop:Jn=>C(w(xe),yt,w(Fe),Jn)})};_e(zs,Nr=>{w(Wt)?Nr(zo):Nr(Da,-1)})}V(Pt,ni)};_e(ti,Pt=>{w(wn).length>0&&Pt(hn)})}V(Xt,Tt)}),V(et,Ft)};_e(De,et=>{w(Fe).length>0&&et(Pe)})}var Le=H(De,2);Ct(Le,21,()=>Object.entries(w(ve).subgroups),kt,(et,Ft)=>{var Xt=Me(()=>QU(w(Ft),2));let qe=()=>w(Xt)[0],yt=()=>w(Xt)[1];const pt=Me(()=>`${w(W)}:${qe()}`),wn=Me(()=>M(w(pt),yt()));{let Zn=Me(()=>!c());AE(et,{get label(){return`${qe()??""} (${yt().length??""})`},open:!0,get hidden(){return w(Zn)},children:(Wt,Rt)=>{var Tt=RAe();Ct(Tt,21,()=>w(wn),kt,(ti,hn,Pt)=>{const ni=Me(()=>w(D).get(w(hn))??{data:[],yExtent:void 0}),zs=Me(()=>w(ni).data),zo=Me(()=>w(ni).yExtent),Da=Me(()=>w(y).has(w(hn))),Nr=Me(()=>c()&&w(hn).split("/").slice(2).join("/")||w(hn));var Jn=cs(),Lb=Dt(Jn);{var Ib=Ln=>{var w$=cs(),CU=Dt(w$);{var $U=Oc=>{R6(Oc,{get data(){return w(zs)},get y(){return w(hn)},get title(){return w(Nr)},get colorMap(){return w(S)},draggable:!0,ondragstart:Ji=>R(w(pt),Pt,Ji),ondragover:Ji=>F(w(pt),Pt,Ji),ondrop:Ji=>C(w(pt),Pt,w(wn),Ji)})},FU=Oc=>{EE(Oc,{get data(){return w(zs)},get x(){return w(g)},get y(){return w(hn)},get title(){return w(Nr)},get colorMap(){return w(S)},get xLim(){return w(v)},get yExtent(){return w(zo)},onSelect:L,onResetZoom:z,draggable:!0,ondragstart:Ji=>R(w(pt),Pt,Ji),ondragover:Ji=>F(w(pt),Pt,Ji),ondrop:Ji=>C(w(pt),Pt,w(wn),Ji)})};_e(CU,Oc=>{w(Da)?Oc($U):Oc(FU,-1)})}V(Ln,w$)};_e(Lb,Ln=>{w(zs).length>0&&Ln(Ib)})}V(ti,Jn)}),V(Wt,Tt)},$$slots:{default:!0}})}}),V(Ge,J)},$$slots:{default:!0}})}}),V(fe,I)};_e(Q,fe=>{!f()||!w(b)?fe(de):n()?r().length===0?fe(ne,2):w(p).length===0?fe(Ee,3):fe(Ke,-1):fe(we,1)})}V(e,U),rn()}var LAe=te('

      No projects

      Create a project by calling trackio.init(project="…") in your training script.

      '),IAe=te('

      No run selected

      Select one or more runs in the sidebar.

      '),PAe=te('

      No System Metrics Available

      System metrics will appear here once logged. To enable automatic logging:

      Setup:

      • NVIDIA GPU: pip install trackio[gpu] (requires nvidia-ml-py)
      • Apple Silicon: pip install trackio[apple-gpu] (requires psutil)
      '),BAe=te('
      '),zAe=te('
      ');function jAe(e,t){nn(t,!0);let n=re(t,"project",3,null),r=re(t,"selectedRuns",19,()=>[]),i=re(t,"smoothing",3,5),s=re(t,"appBootstrapReady",3,!1),o=le(at([])),a=le(at([])),u=le(null),l=le(!1),c=le(at({})),f=le(at({group:null,index:-1})),d=new Map,h=null,p=Me(()=>xy(r())),g=Me(()=>tU(w(a))),m=Me(()=>Object.keys(w(g))),y=Me(()=>{const N=new Map,L=w(u);for(const z of w(a))N.set(z,wE(w(o),"time",z,L));return N});function v(N,L){const z=w(c)[N];if(!z)return L;const U=[];for(const Q of z)L.includes(Q)&&U.push(Q);for(const Q of L)U.includes(Q)||U.push(Q);return U}function b(N,L,z){B(f,{group:N,index:L},!0),z.dataTransfer.effectAllowed="move",z.dataTransfer.setData("text/plain","")}function x(N,L,z){w(f).group===N&&(z.preventDefault(),z.dataTransfer.dropEffect="move")}function _(N,L,z,U){if(U.preventDefault(),w(f).group!==N||w(f).index===L){B(f,{group:null,index:-1},!0);return}const Q=[...z],[de]=Q.splice(w(f).index,1);Q.splice(L,0,de),B(c,{...w(c),[N]:Q},!0),B(f,{group:null,index:-1},!0)}function A(){if(!n()||r().length===0){B(o,[],!0),B(a,[],!0);return}const N=[],L=new Set;for(const z of r()){const U=d.get(z);if(!U||U.length===0)continue;const Q=new Date(U[0].timestamp).getTime();U.forEach(de=>{const we=(new Date(de.timestamp).getTime()-Q)/1e3;Object.keys(de).forEach(ne=>{typeof de[ne]=="number"&&ne!=="step"&&ne!=="time"&&L.add(ne)}),N.push({...de,time:we,run:z,data_type:"original"})})}B(a,Array.from(L).sort(),!0),B(o,N,!0)}async function E(){if(!s()){B(l,!1);return}if(!n()||r().length===0){B(o,[],!0),B(a,[],!0),B(l,!0);return}let N=!1;for(const L of r())if(!d.has(L)){const z=await V6(n(),L);d.set(L,z),N=!0}(N||!w(l))&&A(),B(l,!0)}async function S(){if(!n()||r().length===0)return;let N=!1;for(const L of r()){const z=await V6(n(),L),U=d.get(L);(!U||z.length!==U.length)&&(d.set(L,z),N=!0)}N&&A()}tn(()=>{n(),r(),s(),d=n()?d:new Map,E()}),tn(()=>{i(),w(l)&&A()}),vd(()=>(h=setInterval(S,1e3),()=>{h&&clearInterval(h)}));function k(N){N&&N.length===2&&B(u,N,!0)}function $(){B(u,null)}var D=zAe(),M=P(D);{var R=N=>{Tc(N,{})},F=N=>{var L=LAe();V(N,L)},C=N=>{var L=IAe();V(N,L)},T=N=>{var L=PAe(),z=H(P(L),4),U=P(z);U.textContent=`import trackio + +# Auto-enabled when hardware is detected (NVIDIA GPU or Apple Silicon) +run = trackio.init(project="my-project") + +# Or explicitly enable it: +run = trackio.init(project="my-project", auto_log_gpu=True) + +# You can also manually log system metrics: +trackio.log_gpu()`,V(N,L)},O=N=>{var L=cs(),z=Dt(L);Ct(z,17,()=>w(m),kt,(U,Q)=>{const de=Me(()=>w(g)[w(Q)]),we=Me(()=>`sys:${w(Q)}`),ne=Me(()=>v(w(we),w(de).direct));AE(U,{get label(){return w(Q)},open:!0,children:(Ee,Ke)=>{var fe=BAe();Ct(fe,21,()=>w(ne),kt,(I,q,se)=>{const W=Me(()=>w(y).get(w(q))??{data:[],yExtent:void 0}),ve=Me(()=>w(W).data),xe=Me(()=>w(W).yExtent);var Fe=cs(),ze=Dt(Fe);{var ot=It=>{EE(It,{get data(){return w(ve)},x:"time",get y(){return w(q)},get title(){return w(q)},get colorMap(){return w(p)},get xLim(){return w(u)},get yExtent(){return w(xe)},onSelect:k,onResetZoom:$,draggable:!0,ondragstart:sn=>b(w(we),se,sn),ondragover:sn=>x(w(we),se,sn),ondrop:sn=>_(w(we),se,w(ne),sn)})};_e(ze,It=>{w(ve).length>0&&It(ot)})}V(I,Fe)}),V(Ee,fe)},$$slots:{default:!0}})}),V(N,L)};_e(M,N=>{!s()||!w(l)?N(R):n()?r().length===0?N(C,2):w(o).length===0?N(T,3):N(O,-1):N(F,1)})}V(e,D),rn()}var UAe=te('

      '),qAe=te(''),WAe=te('
      '),HAe=te(''),GAe=te(" "),YAe=te(""),VAe=te('
      ');function XAe(e,t){nn(t,!0);let n=re(t,"headers",19,()=>[]),r=re(t,"rows",19,()=>[]),i=re(t,"selectable",3,!1),s=re(t,"selectedIndices",31,()=>at(new Set)),o=re(t,"onrowclick",3,null),a=re(t,"label",3,""),u=le(null),l=le("asc");function c(k){w(u)===k?B(l,w(l)==="asc"?"desc":"asc",!0):(B(u,k,!0),B(l,"asc"))}let f=Me(()=>{if(w(u)===null)return r();const k=n().indexOf(w(u));return k===-1?r():[...r()].sort(($,D)=>{const M=$[k],R=D[k];if(M==null&&R==null)return 0;if(M==null)return 1;if(R==null)return-1;if(typeof M=="number"&&typeof R=="number")return w(l)==="asc"?M-R:R-M;const F=String(M),C=String(R);return w(l)==="asc"?F.localeCompare(C):C.localeCompare(F)})});function d(){s().size===r().length?s(new Set):s(new Set(r().map((k,$)=>$)))}function h(k){const $=new Set(s());$.has(k)?$.delete(k):$.add(k),s($)}var p=VAe(),g=P(p);{var m=k=>{var $=UAe(),D=P($),M=P(D);Ae(()=>$e(M,a())),V(k,$)};_e(g,k=>{a()&&k(m)})}var y=H(g,2),v=P(y),b=P(v),x=P(b),_=P(x);{var A=k=>{var $=qAe(),D=P($);Ae(()=>fp(D,s().size===r().length&&r().length>0)),je("change",D,d),V(k,$)};_e(_,k=>{i()&&k(A)})}var E=H(_);Ct(E,17,n,kt,(k,$,D)=>{var M=WAe();let R;var F=P(M),C=P(F),T=P(C),O=H(C,2);let N;var L=P(O);Ae(()=>{R=zt(M,1,"svelte-1cp60rw",null,R,{first:D===0&&!i(),last:D===n().length-1}),$e(T,w($)),N=zt(O,1,"sort-arrow svelte-1cp60rw",null,N,{visible:w(u)===w($)}),$e(L,w(u)===w($)?w(l)==="asc"?"↑":"↓":"↑")}),je("click",M,()=>c(w($))),V(k,M)});var S=H(b);Ct(S,21,()=>w(f),kt,(k,$,D)=>{var M=YAe();let R;var F=P(M);{var C=O=>{var N=HAe(),L=P(N);Ae(z=>fp(L,z),[()=>s().has(D)]),je("click",N,z=>z.stopPropagation()),je("change",L,()=>h(D)),V(O,N)};_e(F,O=>{i()&&O(C)})}var T=H(F);Ct(T,17,()=>w($),kt,(O,N,L)=>{var z=GAe();let U;var Q=P(z);Ae(()=>{U=zt(z,1,"svelte-1cp60rw",null,U,{first:L===0&&!i(),last:L===w($).length-1}),$e(Q,w(N)??"")}),V(O,z)}),Ae(O=>R=zt(M,1,"svelte-1cp60rw",null,R,O),[()=>({"row-odd":D%2===1,selected:s().has(D)})]),je("click",M,()=>{var O;return(O=o())==null?void 0:O(w($),D)}),V(k,M)}),V(e,p),rn()}wi(["change","click"]);var KAe=te('

      Select a project

      Pick a project in the sidebar to browse media and tables for a run.

      ',1),ZAe=te('

      No runs selected

      Select runs in the sidebar to browse media and tables.

      ',1),JAe=te('

      No media or tables in this run

      Log images, video, audio, and tables by passing Trackio objects to trackio.log():

      Each type appears in its own section here once logged.

      ',1),QAe=te('
      '),eSe=te('
      '),tSe=te(''),nSe=te('

      '),rSe=te('',2),iSe=te('

      '),sSe=te('
      '),oSe=te('

      '),aSe=te('
      '),uSe=te('

      '),lSe=te(" ",1),cSe=te('
      ');function fSe(e,t){nn(t,!0);let n=re(t,"project",3,null),r=re(t,"selectedRuns",19,()=>[]),i=re(t,"tableTruncateLength",3,250),s=le(at({images:[],videos:[],audios:[],tables:[]})),o=le(!1);async function a(){if(!n()||r().length===0){B(s,{images:[],videos:[],audios:[],tables:[]},!0);return}B(o,!0);try{const p=r(),g=[];for(const _ of p){const A=await dy(n(),_);A&&g.push(...A.map(E=>({...E,_run:_})))}const m=g,y=[],v=[],b=[],x=[];if(m&&m.forEach((_,A)=>{Object.entries(_).forEach(([E,S])=>{if(S&&typeof S=="object"&&S._type){const k={key:E,step:_.step||A,...S};switch(S._type){case"trackio.image":y.push(k);break;case"trackio.video":v.push(k);break;case"trackio.audio":b.push(k);break;case"trackio.table":x.push(k);break}}})}),await Tr()){const _=A=>Promise.all(A.map(async E=>(E.file_path&&(E._resolvedUrl=await CAe(E.file_path)),E)));await Promise.all([_(y),_(v),_(b)])}B(s,{images:y,videos:v,audios:b,tables:x},!0)}catch(p){console.error("Failed to load media:",p)}finally{B(o,!1)}}tn(()=>{n(),r(),a()});function u(p){return p._resolvedUrl?p._resolvedUrl:p.file_path?kU(p.file_path):""}var l=cSe(),c=P(l);{var f=p=>{Tc(p,{})},d=p=>{var g=QAe(),m=P(g);{var y=x=>{var _=KAe();V(x,_)},v=x=>{var _=ZAe(),A=H(Dt(_),4),E=P(A);E.textContent=`import trackio +trackio.init(project="my-project") +trackio.log({"loss": 0.5}) +trackio.finish()`,V(x,_)},b=x=>{var _=JAe(),A=H(Dt(_),4),E=P(A);E.textContent=`import trackio + +trackio.init(project="my-project") +trackio.log({"plot": trackio.Image("figure.png")}) +trackio.log({"clip": trackio.Video("output.mp4")}) +trackio.log({"audio": trackio.Audio("speech.wav")}) + +import pandas as pd +df = pd.DataFrame({"epoch": [0, 1], "acc": [0.9, 0.95]}) +trackio.log({"samples": trackio.Table(dataframe=df)})`,V(x,_)};_e(m,x=>{n()?r().length===0?x(v,1):x(b,-1):x(y)})}V(p,g)},h=p=>{var g=lSe(),m=Dt(g);{var y=S=>{var k=nSe(),$=P(k),D=P($),M=H($,2);Ct(M,21,()=>w(s).images,kt,(R,F)=>{var C=tSe(),T=P(C),O=H(T,2);{var N=U=>{var Q=eSe(),de=P(Q);Ae(()=>$e(de,w(F).caption)),V(U,Q)};_e(O,U=>{w(F).caption&&U(N)})}var L=H(O,2),z=P(L);Ae(U=>{jt(T,"src",U),jt(T,"alt",w(F).caption||w(F).key),$e(z,`Step ${w(F).step??""}`)},[()=>u(w(F))]),V(R,C)}),Ae(()=>$e(D,`Images (${w(s).images.length??""})`)),V(S,k)};_e(m,S=>{w(s).images.length>0&&S(y)})}var v=H(m,2);{var b=S=>{var k=iSe(),$=P(k),D=P($),M=H($,2);Ct(M,21,()=>w(s).videos,kt,(R,F)=>{var C=rSe(),T=P(C),O=H(T,2),N=P(O);Ae(L=>{jt(T,"src",L),$e(N,`Step ${w(F).step??""}`)},[()=>u(w(F))]),V(R,C)}),Ae(()=>$e(D,`Videos (${w(s).videos.length??""})`)),V(S,k)};_e(v,S=>{w(s).videos.length>0&&S(b)})}var x=H(v,2);{var _=S=>{var k=oSe(),$=P(k),D=P($),M=H($,2);Ct(M,21,()=>w(s).audios,kt,(R,F)=>{var C=sSe(),T=P(C),O=P(T),N=H(T,2);Ae(L=>{$e(O,`${w(F).key??""} (step ${w(F).step??""})`),jt(N,"src",L)},[()=>u(w(F))]),V(R,C)}),Ae(()=>$e(D,`Audio (${w(s).audios.length??""})`)),V(S,k)};_e(x,S=>{w(s).audios.length>0&&S(_)})}var A=H(x,2);{var E=S=>{var k=uSe(),$=P(k),D=P($),M=H($,2);Ct(M,17,()=>w(s).tables,kt,(R,F)=>{var C=aSe(),T=P(C);{var O=N=>{{let L=Me(()=>Object.keys(w(F)._value[0])),z=Me(()=>w(F)._value.map(U=>Object.values(U).map(Q=>typeof Q=="string"&&Q.length>i()?Q.slice(0,i())+"…":Q)));XAe(N,{get label(){return`${w(F).key??""} (step ${w(F).step??""})`},get headers(){return w(L)},get rows(){return w(z)}})}};_e(T,N=>{w(F)._value&&w(F)._value.length>0&&N(O)})}V(R,C)}),Ae(()=>$e(D,`Tables (${w(s).tables.length??""})`)),V(S,k)};_e(A,S=>{w(s).tables.length>0&&S(E)})}V(p,g)};_e(c,p=>{w(o)?p(f):w(s).images.length===0&&w(s).videos.length===0&&w(s).audios.length===0&&w(s).tables.length===0?p(d,1):p(h,-1)})}V(e,l),rn()}var dSe=te(`

      No alerts or reports yet

      Alerts are recorded when your training script calls trackio.alert(). + Reports are logged as Markdown via trackio.log().

      `),hSe=te('
      '),pSe=te('

      '),gSe=te('

      No alerts for this level.

      '),mSe=te(' '),ySe=te(' '),vSe=te(''),bSe=te('
      '),xSe=te('

      '),_Se=te(" ",1),wSe=te('
      ');function ESe(e,t){nn(t,!0);let n=re(t,"project",3,null),r=re(t,"selectedRuns",19,()=>[]),i=le(at([])),s=le(at([])),o=le(null),a=le(!1);const u={info:"🔵",warn:"🟡",error:"🔴"};function l(x){if(!x)return"";let _=x.replace(/&/g,"&").replace(//g,">");return _=_.replace(/^### (.+)$/gm,"

      $1

      "),_=_.replace(/^## (.+)$/gm,"

      $1

      "),_=_.replace(/^# (.+)$/gm,"

      $1

      "),_=_.replace(/\*\*(.+?)\*\*/g,"$1"),_=_.replace(/`([^`]+)`/g,"$1"),_=_.replace(/^- (.+)$/gm,"
    • $1
    • "),_=_.replace(/(
    • .*<\/li>\n?)+/gs,A=>`
        ${A}
      `),_=_.replace(/\n{2,}/g,"

      "),_=`

      ${_}

      `,_=_.replace(/

      \s*()/g,"$1"),_=_.replace(/(<\/h[234]>)\s*<\/p>/g,"$1"),_=_.replace(/

      \s*(

        )/g,"$1"),_=_.replace(/(<\/ul>)\s*<\/p>/g,"$1"),_=_.replace(/

        \s*<\/p>/g,""),_}let c=Me(()=>w(o)?w(i).filter(x=>x.level===w(o)):w(i));async function f(){if(!n()){B(i,[],!0),B(s,[],!0);return}B(a,!0);try{const x=await SU(n(),null,null,null),_=new Set(r());B(i,(x||[]).filter(S=>!S.run||_.has(S.run)),!0);const A=r(),E=[];for(const S of A)try{const k=await dy(n(),S);if(k)for(const $ of k)for(const[D,M]of Object.entries($))M&&typeof M=="object"&&M._type==="trackio.markdown"&&E.push({key:D,run:S,step:$.step,content:M._value||""})}catch{}B(s,E,!0)}catch(x){console.error("Failed to load alerts:",x),B(i,[],!0)}finally{B(a,!1)}}tn(()=>{n(),r(),f()});function d(x){if(!x)return"";try{return new Date(x).toLocaleString()}catch{return x}}let h=["Level","Run","Title","Text","Step","Time"],p=Me(()=>w(c).map(x=>[`${u[x.level]||""} ${x.level}`,x.run||"",x.title,x.text||"",x.step??"",d(x.timestamp)]));var g=wSe(),m=P(g);{var y=x=>{Tc(x,{})},v=x=>{var _=dSe(),A=H(P(_),4),E=P(A);E.textContent=`import trackio +from trackio import AlertLevel + +trackio.init(project="my-project") +trackio.alert("Low validation loss", text="Consider saving a checkpoint.", level=AlertLevel.INFO) +trackio.log({"reports/summary": trackio.Markdown("# My Report\\nResults look good.")})`,V(x,_)},b=x=>{var _=_Se(),A=Dt(_);{var E=$=>{var D=pSe(),M=P(D),R=P(M),F=H(M,2);Ct(F,17,()=>w(s),kt,(C,T)=>{var O=hSe(),N=P(O),L=P(N),z=H(N,2);aW(z,()=>l(w(T).content),!0),Ae(()=>$e(L,`${w(T).key??""} · ${w(T).run??""} · step ${w(T).step??""}`)),V(C,O)}),Ae(()=>$e(R,`Reports (${w(s).length??""})`)),V($,D)};_e(A,$=>{w(s).length>0&&$(E)})}var S=H(A,2);{var k=$=>{var D=xSe(),M=P(D),R=P(M),F=H(M,2),C=P(F),T=P(C),O=P(T);let N;var L=H(O,2);let z;var U=H(L,2);let Q;var de=H(U,2);let we;var ne=H(F,2);{var Ee=fe=>{var I=gSe();V(fe,I)},Ke=fe=>{var I=bSe(),q=P(I),se=P(q);Ct(se,21,()=>h,kt,(ve,xe)=>{var Fe=mSe(),ze=P(Fe);Ae(()=>$e(ze,w(xe))),V(ve,Fe)});var W=H(q);Ct(W,21,()=>w(p),kt,(ve,xe)=>{var Fe=vSe();Ct(Fe,21,()=>w(xe),kt,(ze,ot)=>{var It=ySe(),sn=P(It);Ae(()=>$e(sn,w(ot))),V(ze,It)}),V(ve,Fe)}),V(fe,I)};_e(ne,fe=>{w(c).length===0?fe(Ee):fe(Ke,-1)})}Ae(()=>{$e(R,`Alerts (${w(i).length??""})`),N=zt(O,1,"pill svelte-iufsej",null,N,{active:w(o)===null}),z=zt(L,1,"pill svelte-iufsej",null,z,{active:w(o)==="info"}),Q=zt(U,1,"pill svelte-iufsej",null,Q,{active:w(o)==="warn"}),we=zt(de,1,"pill svelte-iufsej",null,we,{active:w(o)==="error"})}),je("click",O,()=>B(o,null)),je("click",L,()=>B(o,"info")),je("click",U,()=>B(o,"warn")),je("click",de,()=>B(o,"error")),V($,D)};_e(S,$=>{w(i).length>0&&$(k)})}V(x,_)};_e(m,x=>{w(a)?x(y):w(i).length===0&&w(s).length===0?x(v,1):x(b,-1)})}V(e,g),rn()}wi(["click"]);var ASe=te('

        No runs in this project

        Runs are created when you call trackio.init() and log at least one step. Example:

        Refresh this page or wait for the dashboard to poll; new runs appear in the table with step counts.

        '),SSe=te(''),kSe=te('
        '),CSe=te(' '),$Se=te('
        ActionsRun NameStepsLast Step
        '),FSe=te('
        ');function DSe(e,t){nn(t,!0);let n=re(t,"project",3,null),r=re(t,"runs",19,()=>[]),i=re(t,"onRunsChanged",3,null),s=re(t,"runMutationAllowed",3,!0),o=Me(s),a=Me(()=>xy(r())),u=le(at([])),l=le(!1),c=le(-1),f=le("");async function d(){if(!n()){B(u,[],!0);return}B(l,!0);try{const E=(await bAe(n())).runs||[],k=(await Promise.all(E.map($=>AU(n(),$)))).map(($,D)=>({name:E[D],numSteps:$.num_logs||0,lastStep:$.last_step||0}));B(u,k,!0)}catch(A){console.error("Failed to load runs:",A)}finally{B(l,!1)}}tn(()=>{n(),d()});async function h(A){if(w(o)&&confirm(`Delete run "${A}"? This cannot be undone.`))try{await EAe(n(),A),await d(),i()&&i()()}catch(E){console.error("Failed to delete run:",E)}}function p(A,E){w(o)&&(B(c,A,!0),B(f,E,!0))}async function g(A){if(!w(o))return;const E=w(f).trim();if(!E||E===A){B(c,-1);return}try{await AAe(n(),A,E),B(c,-1),await d(),i()&&i()()}catch(S){console.error("Failed to rename run:",S)}}function m(A,E){A.key==="Enter"&&g(E),A.key==="Escape"&&B(c,-1)}var y=FSe(),v=P(y);{var b=A=>{Tc(A,{})},x=A=>{var E=ASe(),S=H(P(E),4),k=P(S);k.textContent=`import trackio +trackio.init(project="my-project") +for i in range(10): + trackio.log({"loss": 1 / (i + 1)}) +trackio.finish()`,V(A,E)},_=A=>{var E=$Se(),S=H(P(E));Ct(S,21,()=>w(u),kt,(k,$,D)=>{var M=CSe(),R=P(M),F=P(R),C=H(F,2),T=H(R),O=P(T);{var N=we=>{var ne=SSe();je("keydown",ne,Ee=>m(Ee,w($).name)),ps("blur",ne,()=>g(w($).name)),by(ne,()=>w(f),Ee=>B(f,Ee)),V(we,ne)},L=we=>{var ne=kSe(),Ee=P(ne);let Ke;var fe=H(Ee,2),I=P(fe);Ae(()=>{Ke=ql(Ee,"",Ke,{background:w(a)[w($).name]??"#9ca3af"}),$e(I,w($).name)}),je("click",fe,()=>{iH("selected_run",w($).name),Q8("run-detail")}),V(we,ne)};_e(O,we=>{w(c)===D?we(N):we(L,-1)})}var z=H(T),U=P(z),Q=H(z),de=P(Q);Ae(()=>{jt(F,"title",w(o)?"Rename":"Sign in with Hugging Face (write access) to rename runs"),F.disabled=!w(o),jt(C,"title",w(o)?"Delete":"Sign in with Hugging Face (write access) to delete runs"),C.disabled=!w(o),$e(U,w($).numSteps),$e(de,w($).lastStep)}),je("click",F,()=>p(D,w($).name)),je("click",C,()=>h(w($).name)),V(k,M)}),V(A,E)};_e(v,A=>{w(l)?A(b):w(u).length===0?A(x,1):A(_,-1)})}V(e,y),rn()}wi(["click","keydown"]);var MSe=te(`

        Open a run

        Choose a run from the Runs page or follow a run name from the sidebar. This view shows the + project name, log count, last step, metric keys, and any logged config.

        Config passed to trackio.init() appears under Configuration when present.

        `),RSe=te('

        Configuration

         
        ',1),TSe=te('

        Project
        Total Logs
        Last Step
        Metrics
        '),NSe=te('
        ');function OSe(e,t){nn(t,!0);let n=re(t,"project",3,null),r=le(null),i=le(null),s=le(!1);tn(()=>{B(r,Ys("selected_run"),!0)});async function o(){if(!n()||!w(r)){B(i,null);return}B(s,!0);try{B(i,await AU(n(),w(r)),!0)}catch(d){console.error("Failed to load run detail:",d)}finally{B(s,!1)}}tn(()=>{n(),w(r),o()});var a=NSe(),u=P(a);{var l=d=>{Tc(d,{})},c=d=>{var h=MSe(),p=H(P(h),4),g=P(p);g.textContent=`import trackio +trackio.init(project="my-project", config={"lr": 1e-3}) +trackio.log({"loss": 0.5}) +trackio.finish()`,V(d,h)},f=d=>{var h=TSe(),p=P(h),g=P(p),m=H(p,2),y=P(m),v=H(P(y),2),b=P(v),x=H(y,2),_=H(P(x),2),A=P(_),E=H(x,2),S=H(P(E),2),k=P(S),$=H(E,2),D=H(P($),2),M=P(D),R=H(m,2);{var F=C=>{var T=RSe(),O=H(Dt(T),2),N=P(O);Ae(L=>$e(N,L),[()=>JSON.stringify(w(i).config,null,2)]),V(C,T)};_e(R,C=>{w(i).config&&C(F)})}Ae(C=>{$e(g,w(i).run),$e(b,w(i).project),$e(A,w(i).num_logs),$e(k,w(i).last_step??"N/A"),$e(M,C)},[()=>w(i).metrics?w(i).metrics.join(", "):"None"]),V(d,h)};_e(u,d=>{w(s)?d(l):w(i)?d(f,-1):d(c,1)})}V(e,a),rn()}var LSe=te('

        No project files yet

        Files are stored at the project level (not tied to a single run). After trackio.init(), copy artifacts into the project with trackio.save():

        Paths can be a single file or a glob. Saved files will list here for download.

        '),ISe=te(' '),PSe=te('
        Loading preview...
        '),BSe=te('
         
        '),zSe=te('
        Preview not available. Download the file instead.
        '),jSe=te('
        '),USe=te('
        '),qSe=te('

        Files

        Showing files saved across all runs in this project.

        ',1),WSe=te('
        ');function HSe(e,t){nn(t,!0);let n=re(t,"project",3,null),r=le(at([])),i=le(!1),s=le(null),o=le(null),a=le(!1);const u=new Set(["txt","md","json","yml","yaml","toml","ini","cfg","csv","tsv","xml","html","css","js","py","sh","log","conf","env","gitignore","dockerfile"]);function l(v){const b=v.split(".").pop().toLowerCase();return u.has(b)}function c(v){return v==null?"":v<1024?`${v} B`:v<1024*1024?`${(v/1024).toFixed(1)} KB`:`${(v/(1024*1024)).toFixed(1)} MB`}async function f(v){if(w(s)===v.name){B(s,null),B(o,null);return}if(B(s,v.name,!0),!l(v.name)){B(o,null);return}B(a,!0);try{const b=jx(v.path),x=await fetch(b);if(!x.ok)throw new Error("fetch failed");const _=await x.text();B(o,_.length>5e4?_.slice(0,5e4)+` + +… (truncated)`:_,!0)}catch{B(o,null)}finally{B(a,!1)}}async function d(){if(!n()){B(r,[],!0);return}B(i,!0);try{B(r,await _Ae(n()),!0)}catch{B(r,[],!0)}finally{B(i,!1)}}tn(()=>{n(),d()});var h=WSe(),p=P(h);{var g=v=>{Tc(v,{})},m=v=>{var b=LSe(),x=H(P(b),4),_=P(x);_.textContent=`import trackio + +trackio.init(project="my-project") +trackio.save("config.yaml") +trackio.save("checkpoints/*.pt")`,V(v,b)},y=v=>{var b=qSe(),x=H(Dt(b),4);Ct(x,21,()=>w(r),kt,(_,A)=>{var E=USe();let S;var k=P(E),$=P(k),D=P($),M=P(D),R=H(D),F=H($,2),C=P(F);{var T=z=>{var U=ISe(),Q=P(U);Ae(de=>$e(Q,de),[()=>c(w(A).size)]),V(z,U)};_e(C,z=>{w(A).size!=null&&z(T)})}var O=H(C,2),N=H(k,2);{var L=z=>{var U=jSe(),Q=P(U);{var de=Ee=>{var Ke=PSe();V(Ee,Ke)},we=Ee=>{var Ke=BSe(),fe=P(Ke);Ae(()=>$e(fe,w(o))),V(Ee,Ke)},ne=Ee=>{var Ke=zSe(),fe=H(P(Ke));Ae(I=>jt(fe,"href",I),[()=>jx(w(A).path)]),V(Ee,Ke)};_e(Q,Ee=>{w(a)?Ee(de):w(o)!=null?Ee(we,1):Ee(ne,-1)})}V(z,U)};_e(N,z=>{w(s)===w(A).name&&z(L)})}Ae((z,U)=>{S=zt(E,1,"file-item svelte-1xvfk9n",null,S,{expanded:w(s)===w(A).name}),$e(M,z),$e(R,` ${w(A).name??""}`),jt(O,"href",U)},[()=>l(w(A).name)?"📄":"📦",()=>jx(w(A).path)]),je("click",$,()=>f(w(A))),V(_,E)}),V(v,b)};_e(p,v=>{w(i)?v(g):w(r).length===0?v(m,1):v(y,-1)})}V(e,h),rn()}wi(["click"]);var GSe=te('
        ');function YSe(e,t){nn(t,!0),PW(Ys("__theme")||J8());let n=le("metrics"),r=le(at([])),i=le(null),s=le(at([])),o=le(at([])),a=le(10),u=le("step"),l=le(!1),c=le(!1),f=le(""),d=le(!0),h=le(!0),p=le(""),g=le(at([])),m=le(!0),y=le(!1),v=le(0),b=le(at([])),x=le(null),_=le(at({spaces:!1,allowed:!0,auth:"local"})),A=le(null),E=le(!1),S=le(at({light:"/static/trackio/trackio_logo_type_light_transparent.png",dark:"/static/trackio/trackio_logo_type_dark_transparent.png"})),k=le(at([])),$=le(250),D=le(null);function M(j){B(n,j,!0),Q8(j)}function R(){return Ys("project")||Ys("selected_project")}function F(){const j=R();j&&w(r).includes(j)&&B(i,j,!0)}async function C(){try{const j=await yAe();if(B(r,j||[],!0),w(r).length>0&&!w(i)){const J=R();B(i,J&&w(r).includes(J)?J:w(r)[0],!0)}F()}catch(j){console.error("Failed to load projects:",j)}}async function T(){await O(),await U()}async function O(){if(!w(i)){B(s,[],!0),B(o,[],!0);return}try{const J=await vAe(w(i))||[],De=new Set(J);if(JSON.stringify(w(s))!==JSON.stringify(J)){const Pe=new Set(w(o));B(s,J,!0);const Le=w(o).filter(et=>De.has(et));Le.length===0&&w(o).length===0?B(o,[...J],!0):B(o,[...Le,...J.filter(et=>!new Set([...Le,...Array.from(Pe)]).has(et))],!0)}}catch(j){console.error("Failed to load runs:",j)}}async function N(){if(w(i))try{const j=await SU(w(i),null,null,null);B(b,(j||[]).slice(-20),!0)}catch{}}function L(){w(x)&&clearInterval(w(x)),B(x,setInterval(async()=>{w(d)&&(await O(),await N())},1e3),!0)}function z(){const j=new URLSearchParams(window.location.search);let J=!1;const De=j.get("write_token");De&&(document.cookie=`trackio_write_token=${encodeURIComponent(De)}; path=/; max-age=604800; SameSite=Lax`,j.delete("write_token"),J=!0);const Pe=j.get("oauth_session");if(Pe&&(sessionStorage.setItem("trackio_oauth_session",Pe),j.delete("oauth_session"),J=!0),J){const Le=j.toString(),et=window.location.pathname+(Le?`?${Le}`:"");window.history.replaceState({},"",et)}}async function U(){try{const j=await wAe();B(_,{spaces:!!j.spaces,allowed:!!j.allowed,auth:j.auth??"none"},!0)}catch{B(_,{spaces:!1,allowed:!0,auth:"local"},!0)}}function Q(){w(A)&&clearInterval(w(A)),B(A,setInterval(()=>{U()},12e4),!0)}tn(()=>{w(i),O()}),vd(()=>{const j=Ys("sidebar");j==="hidden"?(B(y,!0),B(m,!1)):j==="collapsed"?(B(y,!1),B(m,!1)):B(y,!1);const J=Ys("smoothing");if(J){const Pe=parseInt(J,10);Number.isNaN(Pe)||B(a,Pe,!0)}const De=Ys("metrics");if(De){const Pe=De.split(",").map(Le=>Le.trim()).filter(Boolean);Pe.length&&B(f,Pe.map(Le=>`^${Le.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}$`).join("|"),!0)}return Ys("accordion")==="hidden"&&B(h,!1),B(n,U$(),!0),window.addEventListener("popstate",()=>{B(n,U$(),!0),x8(v),F()}),z(),(async()=>{const Pe=await Tr();Pe?(B(d,!1),B(_,{spaces:!1,allowed:!1,auth:"static"},!0),B(D,await kAe(),!0)):(U(),Q(),window.addEventListener("focus",U));try{try{const Le=await xAe();Le&&(Le.logo_urls&&B(S,Le.logo_urls,!0),Le.color_palette&&IW(Le.color_palette),Le.plot_order&&B(k,Le.plot_order,!0),Le.table_truncate_length&&B($,Le.table_truncate_length,!0),Le.media_dir&&SAe(Le.media_dir))}catch{}await C(),await O(),await N()}catch(Le){console.error("Failed to load projects:",Le)}finally{B(E,!0)}Pe||L()})(),()=>{w(x)&&clearInterval(w(x)),w(A)&&clearInterval(w(A)),window.removeEventListener("focus",U)}});let de=Me(()=>{w(v);const j=R();return!!(j&&w(r).includes(j))});tn(()=>{w(r),w(v),w(de)&&F()});let we=Me(()=>w(n)==="metrics"||w(n)==="system"||w(n)==="media"||w(n)==="reports"||w(n)==="runs"||w(n)==="run-detail"||w(n)==="files"),ne=Me(()=>w(n)==="runs"||w(n)==="files"?"compact":"full");var Ee=GSe(),Ke=P(Ee);{var fe=j=>{ZW(j,{get variant(){return w(ne)},get currentPage(){return w(n)},get spacesMode(){return w(_).spaces},get runMutationAllowed(){return w(_).allowed},get mutationAuth(){return w(_).auth},get readOnlySource(){return w(D)},get projects(){return w(r)},get projectLocked(){return w(de)},get runs(){return w(s)},get metricColumns(){return w(g)},get logoUrls(){return w(S)},get open(){return w(m)},set open(J){B(m,J,!0)},get selectedProject(){return w(i)},set selectedProject(J){B(i,J,!0)},get selectedRuns(){return w(o)},set selectedRuns(J){B(o,J,!0)},get smoothing(){return w(a)},set smoothing(J){B(a,J,!0)},get xAxis(){return w(u)},set xAxis(J){B(u,J,!0)},get logScaleX(){return w(l)},set logScaleX(J){B(l,J,!0)},get logScaleY(){return w(c)},set logScaleY(J){B(c,J,!0)},get metricFilter(){return w(f)},set metricFilter(J){B(f,J,!0)},get realtimeEnabled(){return w(d)},set realtimeEnabled(J){B(d,J,!0)},get showHeaders(){return w(h)},set showHeaders(J){B(h,J,!0)},get filterText(){return w(p)},set filterText(J){B(p,J,!0)}})};_e(Ke,j=>{w(we)&&!w(y)&&j(fe)})}var I=H(Ke,2),q=P(I);vW(q,{get currentPage(){return w(n)},onNavigate:M});var se=H(q,2),W=P(se);{var ve=j=>{OAe(j,{get project(){return w(i)},get selectedRuns(){return w(o)},get allRuns(){return w(s)},get smoothing(){return w(a)},get xAxis(){return w(u)},get logScaleX(){return w(l)},get logScaleY(){return w(c)},get metricFilter(){return w(f)},get showHeaders(){return w(h)},get appBootstrapReady(){return w(E)},get plotOrder(){return w(k)},get metricColumns(){return w(g)},set metricColumns(J){B(g,J,!0)}})},xe=j=>{jAe(j,{get project(){return w(i)},get selectedRuns(){return w(o)},get smoothing(){return w(a)},get appBootstrapReady(){return w(E)}})},Fe=j=>{fSe(j,{get project(){return w(i)},get selectedRuns(){return w(o)},get tableTruncateLength(){return w($)}})},ze=j=>{ESe(j,{get project(){return w(i)},get selectedRuns(){return w(o)}})},ot=j=>{DSe(j,{get project(){return w(i)},get runs(){return w(s)},onRunsChanged:T,get runMutationAllowed(){return w(_).allowed}})},It=j=>{OSe(j,{get project(){return w(i)}})},sn=j=>{HSe(j,{get project(){return w(i)}})};_e(W,j=>{w(n)==="metrics"?j(ve):w(n)==="system"?j(xe,1):w(n)==="media"?j(Fe,2):w(n)==="reports"?j(ze,3):w(n)==="runs"?j(ot,4):w(n)==="run-detail"?j(It,5):w(n)==="files"&&j(sn,6)})}var Ge=H(I,2);rH(Ge,{get alerts(){return w(b)}}),V(e,Ee),rn()}eW(YSe,{target:document.getElementById("app")}); diff --git a/trackio/frontend/dist/index.html b/trackio/frontend/dist/index.html new file mode 100644 index 0000000000000000000000000000000000000000..f1f680e45356a35e0131b843ebe5cb900358f66e --- /dev/null +++ b/trackio/frontend/dist/index.html @@ -0,0 +1,14 @@ + + + + + + Trackio Dashboard + + + + + +
        + + diff --git a/trackio/frontend/eslint.config.js b/trackio/frontend/eslint.config.js new file mode 100644 index 0000000000000000000000000000000000000000..c0bd968851d9ee35d98943b9c2b04b91af245322 --- /dev/null +++ b/trackio/frontend/eslint.config.js @@ -0,0 +1,42 @@ +import js from "@eslint/js"; +import svelte from "eslint-plugin-svelte"; +import svelteParser from "svelte-eslint-parser"; +import globals from "globals"; + +export default [ + { ignores: ["dist/**", "node_modules/**"] }, + { + files: ["**/*.js"], + languageOptions: { + globals: { + ...globals.browser, + ...globals.es2021, + $state: "readonly", + $derived: "readonly", + $effect: "readonly", + $props: "readonly", + $bindable: "readonly", + $inspect: "readonly", + }, + }, + rules: { + ...js.configs.recommended.rules, + "no-unused-vars": ["error", { argsIgnorePattern: "^_" }], + "no-empty": "off", + }, + }, + { + files: ["**/*.svelte"], + languageOptions: { + parser: svelteParser, + globals: { ...globals.browser, ...globals.es2021 }, + }, + plugins: { svelte }, + rules: { + ...js.configs.recommended.rules, + ...svelte.configs.recommended.rules, + "no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^\\$" }], + "no-empty": "off", + }, + }, +]; diff --git a/trackio/frontend/index.html b/trackio/frontend/index.html new file mode 100644 index 0000000000000000000000000000000000000000..c3d5e2df6bb7db117ed1d554ea7d8d180b076799 --- /dev/null +++ b/trackio/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + Trackio Dashboard + + + +
        + + + diff --git a/trackio/frontend_server.py b/trackio/frontend_server.py new file mode 100644 index 0000000000000000000000000000000000000000..89df244cf7f630a5e87c14e8f6b4744f9476ebf3 --- /dev/null +++ b/trackio/frontend_server.py @@ -0,0 +1,63 @@ +"""Serves the built Svelte frontend alongside the Gradio API.""" + +import logging +import re +from pathlib import Path + +from starlette.responses import HTMLResponse +from starlette.routing import Mount, Route +from starlette.staticfiles import StaticFiles + +FRONTEND_DIR = Path(__file__).parent / "frontend" / "dist" +ASSETS_DIR = Path(__file__).parent / "assets" + +_logger = logging.getLogger(__name__) + +_SPA_SEGMENTS = ( + "metrics", + "system", + "media", + "reports", + "runs", + "run", + "files", +) + + +def mount_frontend(app): + if not FRONTEND_DIR.exists(): + _logger.warning( + "Trackio dashboard UI was not mounted: %s is missing. " + "Build the frontend with `npm ci && npm run build` in trackio/frontend.", + FRONTEND_DIR, + ) + return + + index_html_path = FRONTEND_DIR / "index.html" + if not index_html_path.exists(): + _logger.warning( + "Trackio dashboard UI was not mounted: %s is missing.", + index_html_path, + ) + return + + index_html_content = index_html_path.read_text() + patched_html = re.sub( + r'/assets/(index-[^"]+)', + r"/assets/app/\1", + index_html_content, + ) + + async def serve_frontend(request): + return HTMLResponse(patched_html) + + vite_assets = StaticFiles(directory=str(FRONTEND_DIR / "assets")) + static_assets = StaticFiles(directory=str(ASSETS_DIR)) + + app.routes.insert(0, Mount("/static/trackio", app=static_assets)) + app.routes.insert(0, Mount("/assets/app", app=vite_assets)) + + for seg in reversed(_SPA_SEGMENTS): + app.routes.insert(0, Route(f"/{seg}/", serve_frontend, methods=["GET"])) + app.routes.insert(0, Route(f"/{seg}", serve_frontend, methods=["GET"])) + app.routes.insert(0, Route("/", serve_frontend, methods=["GET"])) diff --git a/trackio/gpu.py b/trackio/gpu.py new file mode 100644 index 0000000000000000000000000000000000000000..dbe6d2c5d6d1eb1559ba1d3907d58e63b9237247 --- /dev/null +++ b/trackio/gpu.py @@ -0,0 +1,357 @@ +import os +import threading +import warnings +from typing import TYPE_CHECKING, Any + +if TYPE_CHECKING: + from trackio.run import Run + +pynvml: Any = None +PYNVML_AVAILABLE = False +_nvml_initialized = False +_nvml_lock = threading.Lock() +_energy_baseline: dict[int, float] = {} + + +def _ensure_pynvml(): + global PYNVML_AVAILABLE, pynvml + if PYNVML_AVAILABLE: + return pynvml + try: + import pynvml as _pynvml + + pynvml = _pynvml + PYNVML_AVAILABLE = True + return pynvml + except ImportError: + raise ImportError( + "nvidia-ml-py is required for GPU monitoring. " + "Install it with: pip install nvidia-ml-py" + ) + + +def _init_nvml() -> bool: + global _nvml_initialized + with _nvml_lock: + if _nvml_initialized: + return True + try: + nvml = _ensure_pynvml() + nvml.nvmlInit() + _nvml_initialized = True + return True + except Exception: + return False + + +def get_gpu_count() -> tuple[int, list[int]]: + """ + Get the number of GPUs visible to this process and their physical indices. + Respects CUDA_VISIBLE_DEVICES environment variable. + + Returns: + Tuple of (count, physical_indices) where: + - count: Number of visible GPUs + - physical_indices: List mapping logical index to physical GPU index. + e.g., if CUDA_VISIBLE_DEVICES=2,3 returns (2, [2, 3]) + meaning logical GPU 0 = physical GPU 2, logical GPU 1 = physical GPU 3 + """ + if not _init_nvml(): + return 0, [] + + cuda_visible = os.environ.get("CUDA_VISIBLE_DEVICES") + if cuda_visible is not None and cuda_visible.strip(): + try: + indices = [int(x.strip()) for x in cuda_visible.split(",") if x.strip()] + return len(indices), indices + except ValueError: + pass + + try: + total = pynvml.nvmlDeviceGetCount() + return total, list(range(total)) + except Exception: + return 0, [] + + +def gpu_available() -> bool: + """ + Check if GPU monitoring is available. + + Returns True if nvidia-ml-py is installed and at least one NVIDIA GPU is detected. + This is used for auto-detection of GPU logging. + """ + try: + _ensure_pynvml() + count, _ = get_gpu_count() + return count > 0 + except ImportError: + return False + except Exception: + return False + + +def reset_energy_baseline(): + """Reset the energy baseline for all GPUs. Called when a new run starts.""" + global _energy_baseline + _energy_baseline = {} + + +def collect_gpu_metrics(device: int | None = None) -> dict: + """ + Collect GPU metrics for visible GPUs. + + Args: + device: CUDA device index to collect metrics from. If None, collects + from all GPUs visible to this process (respects CUDA_VISIBLE_DEVICES). + The device index is the logical CUDA index (0, 1, 2...), not the + physical GPU index. + + Returns: + Dictionary of GPU metrics. Keys use logical device indices (gpu/0/, gpu/1/, etc.) + which correspond to CUDA device indices, not physical GPU indices. + """ + if not _init_nvml(): + return {} + + gpu_count, visible_gpus = get_gpu_count() + if gpu_count == 0: + return {} + + if device is not None: + if device < 0 or device >= gpu_count: + return {} + gpu_indices = [(device, visible_gpus[device])] + else: + gpu_indices = list(enumerate(visible_gpus)) + + metrics = {} + total_util = 0.0 + total_mem_used_gib = 0.0 + total_power = 0.0 + max_temp = 0.0 + valid_util_count = 0 + + for logical_idx, physical_idx in gpu_indices: + prefix = f"gpu/{logical_idx}" + try: + handle = pynvml.nvmlDeviceGetHandleByIndex(physical_idx) + + try: + util = pynvml.nvmlDeviceGetUtilizationRates(handle) + metrics[f"{prefix}/utilization"] = util.gpu + metrics[f"{prefix}/memory_utilization"] = util.memory + total_util += util.gpu + valid_util_count += 1 + except Exception: + pass + + try: + mem = pynvml.nvmlDeviceGetMemoryInfo(handle) + mem_used_gib = mem.used / (1024**3) + mem_total_gib = mem.total / (1024**3) + metrics[f"{prefix}/allocated_memory"] = mem_used_gib + metrics[f"{prefix}/total_memory"] = mem_total_gib + if mem.total > 0: + metrics[f"{prefix}/memory_usage"] = mem.used / mem.total + total_mem_used_gib += mem_used_gib + except Exception: + pass + + try: + power_mw = pynvml.nvmlDeviceGetPowerUsage(handle) + power_w = power_mw / 1000.0 + metrics[f"{prefix}/power"] = power_w + total_power += power_w + except Exception: + pass + + try: + power_limit_mw = pynvml.nvmlDeviceGetPowerManagementLimit(handle) + power_limit_w = power_limit_mw / 1000.0 + metrics[f"{prefix}/power_limit"] = power_limit_w + if power_limit_w > 0 and f"{prefix}/power" in metrics: + metrics[f"{prefix}/power_percent"] = ( + metrics[f"{prefix}/power"] / power_limit_w + ) * 100 + except Exception: + pass + + try: + temp = pynvml.nvmlDeviceGetTemperature( + handle, pynvml.NVML_TEMPERATURE_GPU + ) + metrics[f"{prefix}/temp"] = temp + max_temp = max(max_temp, temp) + except Exception: + pass + + try: + sm_clock = pynvml.nvmlDeviceGetClockInfo(handle, pynvml.NVML_CLOCK_SM) + metrics[f"{prefix}/sm_clock"] = sm_clock + except Exception: + pass + + try: + mem_clock = pynvml.nvmlDeviceGetClockInfo(handle, pynvml.NVML_CLOCK_MEM) + metrics[f"{prefix}/memory_clock"] = mem_clock + except Exception: + pass + + try: + fan_speed = pynvml.nvmlDeviceGetFanSpeed(handle) + metrics[f"{prefix}/fan_speed"] = fan_speed + except Exception: + pass + + try: + pstate = pynvml.nvmlDeviceGetPerformanceState(handle) + metrics[f"{prefix}/performance_state"] = pstate + except Exception: + pass + + try: + energy_mj = pynvml.nvmlDeviceGetTotalEnergyConsumption(handle) + if logical_idx not in _energy_baseline: + _energy_baseline[logical_idx] = energy_mj + energy_consumed_mj = energy_mj - _energy_baseline[logical_idx] + metrics[f"{prefix}/energy_consumed"] = energy_consumed_mj / 1000.0 + except Exception: + pass + + try: + pcie_tx = pynvml.nvmlDeviceGetPcieThroughput( + handle, pynvml.NVML_PCIE_UTIL_TX_BYTES + ) + pcie_rx = pynvml.nvmlDeviceGetPcieThroughput( + handle, pynvml.NVML_PCIE_UTIL_RX_BYTES + ) + metrics[f"{prefix}/pcie_tx"] = pcie_tx / 1024.0 + metrics[f"{prefix}/pcie_rx"] = pcie_rx / 1024.0 + except Exception: + pass + + try: + throttle = pynvml.nvmlDeviceGetCurrentClocksThrottleReasons(handle) + metrics[f"{prefix}/throttle_thermal"] = int( + bool(throttle & pynvml.nvmlClocksThrottleReasonSwThermalSlowdown) + ) + metrics[f"{prefix}/throttle_power"] = int( + bool(throttle & pynvml.nvmlClocksThrottleReasonSwPowerCap) + ) + metrics[f"{prefix}/throttle_hw_slowdown"] = int( + bool(throttle & pynvml.nvmlClocksThrottleReasonHwSlowdown) + ) + metrics[f"{prefix}/throttle_apps"] = int( + bool( + throttle + & pynvml.nvmlClocksThrottleReasonApplicationsClocksSetting + ) + ) + except Exception: + pass + + try: + ecc_corrected = pynvml.nvmlDeviceGetTotalEccErrors( + handle, + pynvml.NVML_MEMORY_ERROR_TYPE_CORRECTED, + pynvml.NVML_VOLATILE_ECC, + ) + metrics[f"{prefix}/corrected_memory_errors"] = ecc_corrected + except Exception: + pass + + try: + ecc_uncorrected = pynvml.nvmlDeviceGetTotalEccErrors( + handle, + pynvml.NVML_MEMORY_ERROR_TYPE_UNCORRECTED, + pynvml.NVML_VOLATILE_ECC, + ) + metrics[f"{prefix}/uncorrected_memory_errors"] = ecc_uncorrected + except Exception: + pass + + except Exception: + continue + + if valid_util_count > 0: + metrics["gpu/mean_utilization"] = total_util / valid_util_count + if total_mem_used_gib > 0: + metrics["gpu/total_allocated_memory"] = total_mem_used_gib + if total_power > 0: + metrics["gpu/total_power"] = total_power + if max_temp > 0: + metrics["gpu/max_temp"] = max_temp + + return metrics + + +class GpuMonitor: + def __init__(self, run: "Run", interval: float = 10.0): + self._run = run + self._interval = interval + self._stop_flag = threading.Event() + self._thread: "threading.Thread | None" = None + + def start(self): + count, _ = get_gpu_count() + if count == 0: + warnings.warn( + "auto_log_gpu=True but no NVIDIA GPUs detected. GPU logging disabled." + ) + return + + reset_energy_baseline() + self._thread = threading.Thread(target=self._monitor_loop, daemon=True) + self._thread.start() + + def stop(self): + self._stop_flag.set() + if self._thread is not None: + self._thread.join(timeout=2.0) + + def _monitor_loop(self): + while not self._stop_flag.is_set(): + try: + metrics = collect_gpu_metrics() + if metrics: + self._run.log_system(metrics) + except Exception: + pass + + self._stop_flag.wait(timeout=self._interval) + + +def log_gpu(run: "Run | None" = None, device: int | None = None) -> dict: + """ + Log GPU metrics to the current or specified run as system metrics. + + Args: + run: Optional Run instance. If None, uses current run from context. + device: CUDA device index to collect metrics from. If None, collects + from all GPUs visible to this process (respects CUDA_VISIBLE_DEVICES). + + Returns: + dict: The GPU metrics that were logged. + + Example: + ```python + import trackio + + run = trackio.init(project="my-project") + trackio.log({"loss": 0.5}) + trackio.log_gpu() # logs all visible GPUs + trackio.log_gpu(device=0) # logs only CUDA device 0 + ``` + """ + from trackio import context_vars + + if run is None: + run = context_vars.current_run.get() + if run is None: + raise RuntimeError("Call trackio.init() before trackio.log_gpu().") + + metrics = collect_gpu_metrics(device=device) + if metrics: + run.log_system(metrics) + return metrics diff --git a/trackio/histogram.py b/trackio/histogram.py new file mode 100644 index 0000000000000000000000000000000000000000..1e00477907d55f7f5dcc1bf2bff05029d43b3ac1 --- /dev/null +++ b/trackio/histogram.py @@ -0,0 +1,71 @@ +from typing import Sequence + +import numpy as np + + +class Histogram: + """ + Histogram data type for Trackio, compatible with wandb.Histogram. + + Args: + sequence (`np.ndarray` or `Sequence[float]` or `Sequence[int]`, *optional*): + Sequence of values to create the histogram from. + np_histogram (`tuple`, *optional*): + Pre-computed NumPy histogram as a `(hist, bins)` tuple. + num_bins (`int`, *optional*, defaults to `64`): + Number of bins for the histogram (maximum `512`). + + Example: + ```python + import trackio + import numpy as np + + # Create histogram from sequence + data = np.random.randn(1000) + trackio.log({"distribution": trackio.Histogram(data)}) + + # Create histogram from numpy histogram + hist, bins = np.histogram(data, bins=30) + trackio.log({"distribution": trackio.Histogram(np_histogram=(hist, bins))}) + + # Specify custom number of bins + trackio.log({"distribution": trackio.Histogram(data, num_bins=50)}) + ``` + """ + + TYPE = "trackio.histogram" + + def __init__( + self, + sequence: np.ndarray | Sequence[float] | Sequence[int] | None = None, + np_histogram: tuple | None = None, + num_bins: int = 64, + ): + if sequence is None and np_histogram is None: + raise ValueError("Must provide either sequence or np_histogram") + + if sequence is not None and np_histogram is not None: + raise ValueError("Cannot provide both sequence and np_histogram") + + num_bins = min(num_bins, 512) + + if np_histogram is not None: + self.histogram, self.bins = np_histogram + self.histogram = np.asarray(self.histogram) + self.bins = np.asarray(self.bins) + else: + data = np.asarray(sequence).flatten() + data = data[np.isfinite(data)] + if len(data) == 0: + self.histogram = np.array([]) + self.bins = np.array([]) + else: + self.histogram, self.bins = np.histogram(data, bins=num_bins) + + def _to_dict(self) -> dict: + """Convert histogram to dictionary for storage.""" + return { + "_type": self.TYPE, + "bins": self.bins.tolist(), + "values": self.histogram.tolist(), + } diff --git a/trackio/imports.py b/trackio/imports.py new file mode 100644 index 0000000000000000000000000000000000000000..96c54b266f5a8e5ab779ccee52b49ce859e62e43 --- /dev/null +++ b/trackio/imports.py @@ -0,0 +1,290 @@ +import os +from pathlib import Path + +import pandas as pd + +from trackio import deploy, utils +from trackio.sqlite_storage import SQLiteStorage + + +def import_csv( + csv_path: str | Path, + project: str, + name: str | None = None, + space_id: str | None = None, + dataset_id: str | None = None, + private: bool | None = None, + force: bool = False, +) -> None: + """ + Imports a CSV file into a Trackio project. The CSV file must contain a `"step"` + column, may optionally contain a `"timestamp"` column, and any other columns will be + treated as metrics. It should also include a header row with the column names. + + TODO: call init() and return a Run object so that the user can continue to log metrics to it. + + Args: + csv_path (`str` or `Path`): + The str or Path to the CSV file to import. + project (`str`): + The name of the project to import the CSV file into. Must not be an existing + project. + name (`str`, *optional*): + The name of the Run to import the CSV file into. If not provided, a default + name will be generated. + name (`str`, *optional*): + The name of the run (if not provided, a default name will be generated). + space_id (`str`, *optional*): + If provided, the project will be logged to a Hugging Face Space instead of a + local directory. Should be a complete Space name like `"username/reponame"` + or `"orgname/reponame"`, or just `"reponame"` in which case the Space will + be created in the currently-logged-in Hugging Face user's namespace. If the + Space does not exist, it will be created. If the Space already exists, the + project will be logged to it. + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + private (`bool`, *optional*): + Whether to make the Space private. If None (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. + """ + if SQLiteStorage.get_runs(project): + raise ValueError( + f"Project '{project}' already exists. Cannot import CSV into existing project." + ) + + csv_path = Path(csv_path) + if not csv_path.exists(): + raise FileNotFoundError(f"CSV file not found: {csv_path}") + + df = pd.read_csv(csv_path) + if df.empty: + raise ValueError("CSV file is empty") + + column_mapping = utils.simplify_column_names(df.columns.tolist()) + df = df.rename(columns=column_mapping) + + step_column = None + for col in df.columns: + if col.lower() == "step": + step_column = col + break + + if step_column is None: + raise ValueError("CSV file must contain a 'step' or 'Step' column") + + if name is None: + name = csv_path.stem + + metrics_list = [] + steps = [] + timestamps = [] + + numeric_columns = [] + for column in df.columns: + if column == step_column: + continue + if column == "timestamp": + continue + + try: + pd.to_numeric(df[column], errors="raise") + numeric_columns.append(column) + except (ValueError, TypeError): + continue + + for _, row in df.iterrows(): + metrics = {} + for column in numeric_columns: + value = row[column] + if bool(pd.notna(value)): + metrics[column] = float(value) + + if metrics: + metrics_list.append(metrics) + steps.append(int(row[step_column])) + + if "timestamp" in df.columns and bool(pd.notna(row["timestamp"])): + timestamps.append(str(row["timestamp"])) + else: + timestamps.append("") + + if metrics_list: + SQLiteStorage.bulk_log( + project=project, + run=name, + metrics_list=metrics_list, + steps=steps, + timestamps=timestamps, + ) + + print( + f"* Imported {len(metrics_list)} rows from {csv_path} into project '{project}' as run '{name}'" + ) + print(f"* Metrics found: {', '.join(metrics_list[0].keys())}") + + space_id, dataset_id, _ = utils.preprocess_space_and_dataset_ids( + space_id, dataset_id + ) + if dataset_id is not None: + os.environ["TRACKIO_DATASET_ID"] = dataset_id + print(f"* Trackio metrics will be synced to Hugging Face Dataset: {dataset_id}") + + if space_id is None: + utils.print_dashboard_instructions(project) + else: + deploy.create_space_if_not_exists( + space_id=space_id, dataset_id=dataset_id, private=private + ) + deploy.wait_until_space_exists(space_id=space_id) + deploy.upload_db_to_space(project=project, space_id=space_id, force=force) + print( + f"* View dashboard by going to: {deploy.SPACE_URL.format(space_id=space_id)}" + ) + + +def import_tf_events( + log_dir: str | Path, + project: str, + name: str | None = None, + space_id: str | None = None, + dataset_id: str | None = None, + private: bool | None = None, + force: bool = False, +) -> None: + """ + Imports TensorFlow Events files from a directory into a Trackio project. Each + subdirectory in the log directory will be imported as a separate run. + + Args: + log_dir (`str` or `Path`): + The str or Path to the directory containing TensorFlow Events files. + project (`str`): + The name of the project to import the TensorFlow Events files into. Must not + be an existing project. + name (`str`, *optional*): + The name prefix for runs (if not provided, will use directory names). Each + subdirectory will create a separate run. + space_id (`str`, *optional*): + If provided, the project will be logged to a Hugging Face Space instead of a + local directory. Should be a complete Space name like `"username/reponame"` + or `"orgname/reponame"`, or just `"reponame"` in which case the Space will + be created in the currently-logged-in Hugging Face user's namespace. If the + Space does not exist, it will be created. If the Space already exists, the + project will be logged to it. + dataset_id (`str`, *optional*): + Deprecated. Use `bucket_id` instead. + private (`bool`, *optional*): + Whether to make the Space private. If None (default), the repo will be + public unless the organization's default is private. This value is ignored + if the repo already exists. + """ + try: + from tbparse import SummaryReader + except ImportError: + raise ImportError( + "The `tbparse` package is not installed but is required for `import_tf_events`. Please install trackio with the `tensorboard` extra: `pip install trackio[tensorboard]`." + ) + + if SQLiteStorage.get_runs(project): + raise ValueError( + f"Project '{project}' already exists. Cannot import TF events into existing project." + ) + + path = Path(log_dir) + if not path.exists(): + raise FileNotFoundError(f"TF events directory not found: {path}") + + # Use tbparse to read all tfevents files in the directory structure + reader = SummaryReader(str(path), extra_columns={"dir_name"}) + df = reader.scalars + + if df.empty: + raise ValueError(f"No TensorFlow events data found in {path}") + + total_imported = 0 + imported_runs = [] + + # Group by dir_name to create separate runs + for dir_name, group_df in df.groupby("dir_name"): + try: + # Determine run name based on directory name + if dir_name == "": + run_name = "main" # For files in the root directory + else: + run_name = dir_name # Use directory name + + if name: + run_name = f"{name}_{run_name}" + + if group_df.empty: + print(f"* Skipping directory {dir_name}: no scalar data found") + continue + + metrics_list = [] + steps = [] + timestamps = [] + + for _, row in group_df.iterrows(): + # Convert row values to appropriate types + tag = str(row["tag"]) + value = float(row["value"]) + step = int(row["step"]) + + metrics = {tag: value} + metrics_list.append(metrics) + steps.append(step) + + # Use wall_time if present, else fallback + if "wall_time" in group_df.columns and not bool( + pd.isna(row["wall_time"]) + ): + timestamps.append(str(row["wall_time"])) + else: + timestamps.append("") + + if metrics_list: + SQLiteStorage.bulk_log( + project=project, + run=str(run_name), + metrics_list=metrics_list, + steps=steps, + timestamps=timestamps, + ) + + total_imported += len(metrics_list) + imported_runs.append(run_name) + + print( + f"* Imported {len(metrics_list)} scalar events from directory '{dir_name}' as run '{run_name}'" + ) + print(f"* Metrics in this run: {', '.join(set(group_df['tag']))}") + + except Exception as e: + print(f"* Error processing directory {dir_name}: {e}") + continue + + if not imported_runs: + raise ValueError("No valid TensorFlow events data could be imported") + + print(f"* Total imported events: {total_imported}") + print(f"* Created runs: {', '.join(imported_runs)}") + + space_id, dataset_id, _ = utils.preprocess_space_and_dataset_ids( + space_id, dataset_id + ) + if dataset_id is not None: + os.environ["TRACKIO_DATASET_ID"] = dataset_id + print(f"* Trackio metrics will be synced to Hugging Face Dataset: {dataset_id}") + + if space_id is None: + utils.print_dashboard_instructions(project) + else: + deploy.create_space_if_not_exists( + space_id, dataset_id=dataset_id, private=private + ) + deploy.wait_until_space_exists(space_id) + deploy.upload_db_to_space(project, space_id, force=force) + print( + f"* View dashboard by going to: {deploy.SPACE_URL.format(space_id=space_id)}" + ) diff --git a/trackio/launch.py b/trackio/launch.py new file mode 100644 index 0000000000000000000000000000000000000000..c9650d392d20e1a3f3dbb76af96774b2305a28bc --- /dev/null +++ b/trackio/launch.py @@ -0,0 +1,211 @@ +from __future__ import annotations + +import os +import secrets +import socket +import threading +import time +import warnings +from typing import Any + +import httpx +import uvicorn +from uvicorn.config import Config + +from trackio.launch_utils import colab_check, is_hosted_notebook + +INITIAL_PORT_VALUE = int(os.getenv("GRADIO_SERVER_PORT", "7860")) +TRY_NUM_PORTS = int(os.getenv("GRADIO_NUM_PORTS", "100")) +LOCALHOST_NAME = os.getenv("GRADIO_SERVER_NAME", "127.0.0.1") + + +class _UvicornServer(uvicorn.Server): + def install_signal_handlers(self) -> None: + pass + + def run_in_thread(self) -> None: + self.thread = threading.Thread(target=self.run, daemon=True) + self.thread.start() + start = time.time() + while not self.started: + time.sleep(1e-3) + if time.time() - start > 60: + raise RuntimeError( + "Server failed to start. Please check that the port is available." + ) + + +def _bind_host(server_name: str) -> str: + if server_name.startswith("[") and server_name.endswith("]"): + return server_name[1:-1] + return server_name + + +def start_server( + app: Any, + server_name: str | None = None, + server_port: int | None = None, + ssl_keyfile: str | None = None, + ssl_certfile: str | None = None, + ssl_keyfile_password: str | None = None, +) -> tuple[str, int, str, _UvicornServer]: + server_name = server_name or LOCALHOST_NAME + url_host_name = "localhost" if server_name == "0.0.0.0" else server_name + + host = _bind_host(server_name) + + server_ports = ( + [server_port] + if server_port is not None + else range(INITIAL_PORT_VALUE, INITIAL_PORT_VALUE + TRY_NUM_PORTS) + ) + + port_used = None + server = None + for port in server_ports: + try: + s = socket.socket() + s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + s.bind((LOCALHOST_NAME, port)) + s.close() + config = Config( + app=app, + port=port, + host=host, + log_level="warning", + ssl_keyfile=ssl_keyfile, + ssl_certfile=ssl_certfile, + ssl_keyfile_password=ssl_keyfile_password, + ) + server = _UvicornServer(config=config) + server.run_in_thread() + port_used = port + break + except (OSError, RuntimeError): + continue + else: + raise OSError( + f"Cannot find empty port in range: {min(server_ports)}-{max(server_ports)}. " + "Set GRADIO_SERVER_PORT or pass server_port to trackio.show()." + ) + + assert port_used is not None and server is not None + + if ssl_keyfile is not None: + path_to_local_server = f"https://{url_host_name}:{port_used}/" + else: + path_to_local_server = f"http://{url_host_name}:{port_used}/" + + return server_name, port_used, path_to_local_server, server + + +def launch_trackio_dashboard( + starlette_app: Any, + *, + server_name: str | None = None, + server_port: int | None = None, + share: bool | None = None, + share_server_address: str | None = None, + share_server_protocol: str | None = None, + share_server_tls_certificate: str | None = None, + mcp_server: bool = False, + ssl_verify: bool = True, + quiet: bool = False, +) -> tuple[str | None, str | None, str | None, Any]: + from pathlib import Path + + from trackio._vendor.networking import normalize_share_url, setup_tunnel + from trackio._vendor.tunneling import BINARY_PATH + + is_colab = colab_check() + is_hosted_nb = is_hosted_notebook() + space_id = os.getenv("SPACE_ID") + + if share is None: + if is_colab or is_hosted_nb: + if not quiet: + print( + "It looks like you are running Trackio on a hosted Jupyter notebook, which requires " + "`share=True`. Automatically setting `share=True` " + "(set `share=False` in `show()` to disable).\n" + ) + share = True + else: + share = os.getenv("GRADIO_SHARE", "").lower() == "true" + + sn = server_name + if sn is None and os.getenv("SYSTEM") == "spaces": + sn = "0.0.0.0" + elif sn is None: + sn = LOCALHOST_NAME + + server_name_r, server_port_r, local_url, uv_server = start_server( + starlette_app, + server_name=sn, + server_port=server_port, + ) + + local_api_url = f"{local_url.rstrip('/')}/gradio_api/" + try: + httpx.get(f"{local_api_url}startup-events", verify=ssl_verify, timeout=10) + except Exception as e: + raise RuntimeError( + f"Could not reach startup-events at {local_api_url}startup-events: {e}" + ) from e + + if share and space_id: + warnings.warn("Setting share=True is not supported on Hugging Face Spaces") + share = False + + share_url: str | None = None + if share: + try: + share_tok = secrets.token_urlsafe(32) + proto = share_server_protocol or ( + "http" if share_server_address is not None else "https" + ) + raw = setup_tunnel( + local_host=server_name_r, + local_port=server_port_r, + share_token=share_tok, + share_server_address=share_server_address, + share_server_tls_certificate=share_server_tls_certificate, + ) + share_url = normalize_share_url(raw, proto) + if not quiet: + print(f"* Running on public URL: {share_url}") + print( + "\nThis share link expires in 1 week. For permanent hosting, deploy to Hugging Face Spaces." + ) + except Exception as e: + share_url = None + if not quiet: + from trackio._vendor.gradio_exceptions import ChecksumMismatchError + + if isinstance(e, ChecksumMismatchError): + print( + "\nCould not create share link. Checksum mismatch for frpc binary." + ) + elif Path(BINARY_PATH).exists(): + print( + "\nCould not create share link. Check your internet connection or https://status.gradio.app." + ) + else: + print( + f"\nCould not create share link. Missing frpc at {BINARY_PATH}. {e}" + ) + + if not share_url and not quiet: + print("* To create a public link, set `share=True` in `trackio.show()`.") + + if mcp_server and not quiet: + base = share_url or local_url.rstrip("/") + print(f"\n* MCP streamable HTTP: {base}/gradio_api/mcp/") + + return local_url, share_url, local_api_url, uv_server + + +def url_ok_local(local_url: str) -> bool: + from trackio._vendor.networking import url_ok + + return url_ok(local_url) diff --git a/trackio/launch_utils.py b/trackio/launch_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..b535eb421708278a48e2693c177d377e58a58289 --- /dev/null +++ b/trackio/launch_utils.py @@ -0,0 +1,33 @@ +import os + + +def colab_check() -> bool: + is_colab = False + try: + from IPython.core.getipython import get_ipython + + from_ipynb = get_ipython() + if "google.colab" in str(from_ipynb): + is_colab = True + except (ImportError, NameError): + pass + return is_colab + + +def is_hosted_notebook() -> bool: + return bool( + os.environ.get("KAGGLE_KERNEL_RUN_TYPE") + or os.path.exists("/home/ec2-user/SageMaker") + ) + + +def ipython_check() -> bool: + is_ipython = False + try: + from IPython.core.getipython import get_ipython + + if get_ipython() is not None: + is_ipython = True + except (ImportError, NameError): + pass + return is_ipython diff --git a/trackio/markdown.py b/trackio/markdown.py new file mode 100644 index 0000000000000000000000000000000000000000..910a7749517980578449801da53a279f3f5c11d1 --- /dev/null +++ b/trackio/markdown.py @@ -0,0 +1,21 @@ +class Markdown: + """ + Markdown report data type for Trackio. + + Args: + text (`str`): + Markdown content to log. + """ + + TYPE = "trackio.markdown" + + def __init__(self, text: str = ""): + if not isinstance(text, str): + raise ValueError("Markdown text must be a string") + self.text = text + + def _to_dict(self) -> dict: + return { + "_type": self.TYPE, + "_value": self.text, + } diff --git a/trackio/mcp_setup.py b/trackio/mcp_setup.py new file mode 100644 index 0000000000000000000000000000000000000000..c5baf5e02a1f377251c96a4a129300be0eb78ba8 --- /dev/null +++ b/trackio/mcp_setup.py @@ -0,0 +1,6 @@ +from contextlib import asynccontextmanager + + +@asynccontextmanager +async def mcp_lifespan_context(app): + yield diff --git a/trackio/media/__init__.py b/trackio/media/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..0fb247008abc2493044fe0a66a691f2d23a909c2 --- /dev/null +++ b/trackio/media/__init__.py @@ -0,0 +1,27 @@ +""" +Media module for Trackio. + +This module contains all media-related functionality including: +- TrackioImage, TrackioVideo, TrackioAudio classes +- Video writing utilities +- Audio conversion utilities +""" + +from trackio.media.audio import TrackioAudio +from trackio.media.image import TrackioImage +from trackio.media.media import TrackioMedia +from trackio.media.utils import get_project_media_path +from trackio.media.video import TrackioVideo + +write_audio = TrackioAudio.write_audio +write_video = TrackioVideo.write_video + +__all__ = [ + "TrackioMedia", + "TrackioImage", + "TrackioVideo", + "TrackioAudio", + "get_project_media_path", + "write_video", + "write_audio", +] diff --git a/trackio/media/audio.py b/trackio/media/audio.py new file mode 100644 index 0000000000000000000000000000000000000000..90026d7be9d5620786034b41c31d55161a80a28a --- /dev/null +++ b/trackio/media/audio.py @@ -0,0 +1,167 @@ +import os +import shutil +import warnings +from pathlib import Path +from typing import Literal + +import numpy as np +from pydub import AudioSegment + +from trackio.media.media import TrackioMedia +from trackio.media.utils import check_ffmpeg_installed, check_path + +SUPPORTED_FORMATS = ["wav", "mp3"] +AudioFormatType = Literal["wav", "mp3"] +TrackioAudioSourceType = str | Path | np.ndarray + + +class TrackioAudio(TrackioMedia): + """ + Initializes an Audio object. + + Example: + ```python + import trackio + import numpy as np + + # Generate a 1-second 440 Hz sine wave (mono) + sr = 16000 + t = np.linspace(0, 1, sr, endpoint=False) + wave = 0.2 * np.sin(2 * np.pi * 440 * t) + audio = trackio.Audio(wave, caption="A4 sine", sample_rate=sr, format="wav") + trackio.log({"tone": audio}) + + # Stereo from numpy array (shape: samples, 2) + stereo = np.stack([wave, wave], axis=1) + audio = trackio.Audio(stereo, caption="Stereo", sample_rate=sr, format="mp3") + trackio.log({"stereo": audio}) + + # From an existing file + audio = trackio.Audio("path/to/audio.wav", caption="From file") + trackio.log({"file_audio": audio}) + ``` + + Args: + value (`str`, `Path`, or `numpy.ndarray`, *optional*): + A path to an audio file, or a numpy array. + The array should be shaped `(samples,)` for mono or `(samples, 2)` for stereo. + Float arrays will be peak-normalized and converted to 16-bit PCM; integer arrays will be converted to 16-bit PCM as needed. + caption (`str`, *optional*): + A string caption for the audio. + sample_rate (`int`, *optional*): + Sample rate in Hz. Required when `value` is a numpy array. + format (`Literal["wav", "mp3"]`, *optional*): + Audio format used when `value` is a numpy array. Default is "wav". + """ + + TYPE = "trackio.audio" + + def __init__( + self, + value: TrackioAudioSourceType, + caption: str | None = None, + sample_rate: int | None = None, + format: AudioFormatType | None = None, + ): + super().__init__(value, caption) + if isinstance(value, np.ndarray): + if sample_rate is None: + raise ValueError("Sample rate is required when value is an ndarray") + if format is None: + format = "wav" + self._format = format + self._sample_rate = sample_rate + + def _save_media(self, file_path: Path): + if isinstance(self._value, np.ndarray): + TrackioAudio.write_audio( + data=self._value, + sample_rate=self._sample_rate, + filename=file_path, + format=self._format, + ) + elif isinstance(self._value, str | Path): + if os.path.isfile(self._value): + shutil.copy(self._value, file_path) + else: + raise ValueError(f"File not found: {self._value}") + + @staticmethod + def ensure_int16_pcm(data: np.ndarray) -> np.ndarray: + """ + Convert input audio array to contiguous int16 PCM. + Peak normalization is applied to floating inputs. + """ + arr = np.asarray(data) + if arr.ndim not in (1, 2): + raise ValueError("Audio data must be 1D (mono) or 2D ([samples, channels])") + + if arr.dtype != np.int16: + warnings.warn( + f"Converting {arr.dtype} audio to int16 PCM; pass int16 to avoid conversion.", + stacklevel=2, + ) + + arr = np.nan_to_num(arr, copy=False) + + # Floating types: normalize to peak 1.0, then scale to int16 + if np.issubdtype(arr.dtype, np.floating): + max_abs = float(np.max(np.abs(arr))) if arr.size else 0.0 + if max_abs > 0.0: + arr = arr / max_abs + out = (arr * 32767.0).clip(-32768, 32767).astype(np.int16, copy=False) + return np.ascontiguousarray(out) + + converters: dict[np.dtype, callable] = { + np.dtype(np.int16): lambda a: a, + np.dtype(np.int32): lambda a: (a.astype(np.int32) // 65536).astype( + np.int16, copy=False + ), + np.dtype(np.uint16): lambda a: (a.astype(np.int32) - 32768).astype( + np.int16, copy=False + ), + np.dtype(np.uint8): lambda a: (a.astype(np.int32) * 257 - 32768).astype( + np.int16, copy=False + ), + np.dtype(np.int8): lambda a: (a.astype(np.int32) * 256).astype( + np.int16, copy=False + ), + } + + conv = converters.get(arr.dtype) + if conv is not None: + out = conv(arr) + return np.ascontiguousarray(out) + raise TypeError(f"Unsupported audio dtype: {arr.dtype}") + + @staticmethod + def write_audio( + data: np.ndarray, + sample_rate: int, + filename: str | Path, + format: AudioFormatType = "wav", + ) -> None: + if not isinstance(sample_rate, int) or sample_rate <= 0: + raise ValueError(f"Invalid sample_rate: {sample_rate}") + if format not in SUPPORTED_FORMATS: + raise ValueError( + f"Unsupported format: {format}. Supported: {SUPPORTED_FORMATS}" + ) + + check_path(filename) + + pcm = TrackioAudio.ensure_int16_pcm(data) + + if format != "wav": + check_ffmpeg_installed() + + channels = 1 if pcm.ndim == 1 else pcm.shape[1] + audio = AudioSegment( + pcm.tobytes(), + frame_rate=sample_rate, + sample_width=2, # int16 + channels=channels, + ) + + file = audio.export(str(filename), format=format) + file.close() diff --git a/trackio/media/image.py b/trackio/media/image.py new file mode 100644 index 0000000000000000000000000000000000000000..0f070df0fe4e05dbbaed34867a360abc483d2e72 --- /dev/null +++ b/trackio/media/image.py @@ -0,0 +1,84 @@ +import os +import shutil +from pathlib import Path + +import numpy as np +from PIL import Image as PILImage + +from trackio.media.media import TrackioMedia + +TrackioImageSourceType = str | Path | np.ndarray | PILImage.Image + + +class TrackioImage(TrackioMedia): + """ + Initializes an Image object. + + Example: + ```python + import trackio + import numpy as np + from PIL import Image + + # Create an image from numpy array + image_data = np.random.randint(0, 255, (64, 64, 3), dtype=np.uint8) + image = trackio.Image(image_data, caption="Random image") + trackio.log({"my_image": image}) + + # Create an image from PIL Image + pil_image = Image.new('RGB', (100, 100), color='red') + image = trackio.Image(pil_image, caption="Red square") + trackio.log({"red_image": image}) + + # Create an image from file path + image = trackio.Image("path/to/image.jpg", caption="Photo from file") + trackio.log({"file_image": image}) + ``` + + Args: + value (`str`, `Path`, `numpy.ndarray`, or `PIL.Image`, *optional*): + A path to an image, a PIL Image, or a numpy array of shape (height, width, channels). + If numpy array, should be of type `np.uint8` with RGB values in the range `[0, 255]`. + caption (`str`, *optional*): + A string caption for the image. + """ + + TYPE = "trackio.image" + + def __init__(self, value: TrackioImageSourceType, caption: str | None = None): + super().__init__(value, caption) + self._format: str | None = None + + if not isinstance(self._value, TrackioImageSourceType): + raise ValueError( + f"Invalid value type, expected {TrackioImageSourceType}, got {type(self._value)}" + ) + if isinstance(self._value, np.ndarray) and self._value.dtype != np.uint8: + raise ValueError( + f"Invalid value dtype, expected np.uint8, got {self._value.dtype}" + ) + if ( + isinstance(self._value, np.ndarray | PILImage.Image) + and self._format is None + ): + self._format = "png" + + def _as_pil(self) -> PILImage.Image | None: + try: + if isinstance(self._value, np.ndarray): + arr = np.asarray(self._value).astype("uint8") + return PILImage.fromarray(arr).convert("RGBA") + if isinstance(self._value, PILImage.Image): + return self._value.convert("RGBA") + except Exception as e: + raise ValueError(f"Failed to process image data: {self._value}") from e + return None + + def _save_media(self, file_path: Path): + if pil := self._as_pil(): + pil.save(file_path, format=self._format) + elif isinstance(self._value, str | Path): + if os.path.isfile(self._value): + shutil.copy(self._value, file_path) + else: + raise ValueError(f"File not found: {self._value}") diff --git a/trackio/media/media.py b/trackio/media/media.py new file mode 100644 index 0000000000000000000000000000000000000000..6ec3d65939c81d2e32089a6fb3d192fbab0e4209 --- /dev/null +++ b/trackio/media/media.py @@ -0,0 +1,79 @@ +import os +import uuid +from abc import ABC, abstractmethod +from pathlib import Path + +from trackio.media.utils import get_project_media_path +from trackio.utils import MEDIA_DIR + + +class TrackioMedia(ABC): + """ + Abstract base class for Trackio media objects + Provides shared functionality for file handling and serialization. + """ + + TYPE: str + + def __init_subclass__(cls, **kwargs): + """Ensure subclasses define the TYPE attribute.""" + super().__init_subclass__(**kwargs) + if not hasattr(cls, "TYPE") or cls.TYPE is None: + raise TypeError(f"Class {cls.__name__} must define TYPE attribute") + + def __init__(self, value, caption: str | None = None): + """ + Saves the value and caption, and if the value is a file path, checks if the file exists. + """ + self.caption = caption + self._value = value + self._file_path: Path | None = None + + if isinstance(self._value, str | Path): + if not os.path.isfile(self._value): + raise ValueError(f"File not found: {self._value}") + + def _file_extension(self) -> str: + if self._file_path: + return self._file_path.suffix[1:].lower() + if isinstance(self._value, str | Path): + path = Path(self._value) + return path.suffix[1:].lower() + if hasattr(self, "_format") and self._format: + return self._format + return "unknown" + + def _get_relative_file_path(self) -> Path | None: + return self._file_path + + def _get_absolute_file_path(self) -> Path | None: + if self._file_path: + return MEDIA_DIR / self._file_path + return None + + def _save(self, project: str, run: str, step: int = 0): + if self._file_path: + return + + media_dir = get_project_media_path(project=project, run=run, step=step) + filename = f"{uuid.uuid4()}.{self._file_extension()}" + file_path = media_dir / filename + + self._save_media(file_path) + self._file_path = file_path.relative_to(MEDIA_DIR) + + @abstractmethod + def _save_media(self, file_path: Path): + """ + Performs the actual media saving logic. + """ + pass + + def _to_dict(self) -> dict: + if not self._file_path: + raise ValueError("Media must be saved to file before serialization") + return { + "_type": self.TYPE, + "file_path": str(self._get_relative_file_path()), + "caption": self.caption, + } diff --git a/trackio/media/utils.py b/trackio/media/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..4e86cb23760cc74c11e404f092564a18d4dc1c73 --- /dev/null +++ b/trackio/media/utils.py @@ -0,0 +1,60 @@ +import shutil +from pathlib import Path + +from trackio.utils import MEDIA_DIR + + +def check_path(file_path: str | Path) -> None: + """Raise an error if the parent directory does not exist.""" + file_path = Path(file_path) + if not file_path.parent.exists(): + try: + file_path.parent.mkdir(parents=True, exist_ok=True) + except OSError as e: + raise ValueError( + f"Failed to create parent directory {file_path.parent}: {e}" + ) + + +def check_ffmpeg_installed() -> None: + """Raise an error if ffmpeg is not available on the system PATH.""" + if shutil.which("ffmpeg") is None: + raise RuntimeError( + "ffmpeg is required to write video but was not found on your system. " + "Please install ffmpeg and ensure it is available on your PATH." + ) + + +def get_project_media_path( + project: str, + run: str | None = None, + step: int | None = None, + relative_path: str | Path | None = None, +) -> Path: + """ + Get the full path where uploaded files are stored for a Trackio project (and create the directory if it doesn't exist). + If a run is not provided, the files are stored in a project-level directory with the given relative path. + + Args: + project: The project name + run: The run name + step: The step number + relative_path: The relative path within the directory (only used if run is not provided) + + Returns: + The full path to the media file + """ + if step is not None and run is None: + raise ValueError("Uploading files at a specific step requires a run") + + path = MEDIA_DIR / project + if run: + path /= run + if step is not None: + path /= str(step) + else: + path /= "files" + if relative_path: + path /= relative_path + path.mkdir(parents=True, exist_ok=True) + return path diff --git a/trackio/media/video.py b/trackio/media/video.py new file mode 100644 index 0000000000000000000000000000000000000000..01210bca73d801322e9c4450917f9fc71556f634 --- /dev/null +++ b/trackio/media/video.py @@ -0,0 +1,246 @@ +import os +import shutil +import subprocess +from pathlib import Path +from typing import Literal + +import numpy as np + +from trackio.media.media import TrackioMedia +from trackio.media.utils import check_ffmpeg_installed, check_path + +TrackioVideoSourceType = str | Path | np.ndarray +TrackioVideoFormatType = Literal["gif", "mp4", "webm"] +VideoCodec = Literal["h264", "vp9", "gif"] + + +class TrackioVideo(TrackioMedia): + """ + Initializes a Video object. + + Example: + ```python + import trackio + import numpy as np + + # Create a simple video from numpy array + frames = np.random.randint(0, 255, (10, 3, 64, 64), dtype=np.uint8) + video = trackio.Video(frames, caption="Random video", fps=30) + + # Create a batch of videos + batch_frames = np.random.randint(0, 255, (3, 10, 3, 64, 64), dtype=np.uint8) + batch_video = trackio.Video(batch_frames, caption="Batch of videos", fps=15) + + # Create video from file path + video = trackio.Video("path/to/video.mp4", caption="Video from file") + ``` + + Args: + value (`str`, `Path`, or `numpy.ndarray`, *optional*): + A path to a video file, or a numpy array. + If numpy array, should be of type `np.uint8` with RGB values in the range `[0, 255]`. + It is expected to have shape of either (frames, channels, height, width) or (batch, frames, channels, height, width). + For the latter, the videos will be tiled into a grid. + caption (`str`, *optional*): + A string caption for the video. + fps (`int`, *optional*): + Frames per second for the video. Only used when value is an ndarray. Default is `24`. + format (`Literal["gif", "mp4", "webm"]`, *optional*): + Video format ("gif", "mp4", or "webm"). Only used when value is an ndarray. Default is "gif". + """ + + TYPE = "trackio.video" + + def __init__( + self, + value: TrackioVideoSourceType, + caption: str | None = None, + fps: int | None = None, + format: TrackioVideoFormatType | None = None, + ): + super().__init__(value, caption) + + if not isinstance(self._value, TrackioVideoSourceType): + raise ValueError( + f"Invalid value type, expected {TrackioVideoSourceType}, got {type(self._value)}" + ) + if isinstance(self._value, np.ndarray): + if self._value.dtype != np.uint8: + raise ValueError( + f"Invalid value dtype, expected np.uint8, got {self._value.dtype}" + ) + if format is None: + format = "gif" + if fps is None: + fps = 24 + self._fps = fps + self._format = format + + @staticmethod + def _check_array_format(video: np.ndarray) -> None: + """Raise an error if the array is not in the expected format.""" + if not (video.ndim == 4 and video.shape[-1] == 3): + raise ValueError( + f"Expected RGB input shaped (F, H, W, 3), got {video.shape}. " + f"Input has {video.ndim} dimensions, expected 4." + ) + if video.dtype != np.uint8: + raise TypeError( + f"Expected dtype=uint8, got {video.dtype}. " + "Please convert your video data to uint8 format." + ) + + @staticmethod + def write_video( + file_path: str | Path, video: np.ndarray, fps: float, codec: VideoCodec + ) -> None: + """RGB uint8 only, shape (F, H, W, 3).""" + check_ffmpeg_installed() + check_path(file_path) + + if codec not in {"h264", "vp9", "gif"}: + raise ValueError("Unsupported codec. Use h264, vp9, or gif.") + + arr = np.asarray(video) + TrackioVideo._check_array_format(arr) + + frames = np.ascontiguousarray(arr) + _, height, width, _ = frames.shape + out_path = str(file_path) + + cmd = [ + "ffmpeg", + "-y", + "-f", + "rawvideo", + "-s", + f"{width}x{height}", + "-pix_fmt", + "rgb24", + "-r", + str(fps), + "-i", + "-", + "-an", + ] + + if codec == "gif": + video_filter = "split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" + cmd += [ + "-vf", + video_filter, + "-loop", + "0", + ] + elif codec == "h264": + cmd += [ + "-vcodec", + "libx264", + "-pix_fmt", + "yuv420p", + "-movflags", + "+faststart", + ] + elif codec == "vp9": + bpp = 0.08 + bps = int(width * height * fps * bpp) + if bps >= 1_000_000: + bitrate = f"{round(bps / 1_000_000)}M" + elif bps >= 1_000: + bitrate = f"{round(bps / 1_000)}k" + else: + bitrate = str(max(bps, 1)) + cmd += [ + "-vcodec", + "libvpx-vp9", + "-b:v", + bitrate, + "-pix_fmt", + "yuv420p", + ] + cmd += [out_path] + proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stderr=subprocess.PIPE) + try: + for frame in frames: + proc.stdin.write(frame.tobytes()) + finally: + if proc.stdin: + proc.stdin.close() + stderr = ( + proc.stderr.read().decode("utf-8", errors="ignore") + if proc.stderr + else "" + ) + ret = proc.wait() + if ret != 0: + raise RuntimeError(f"ffmpeg failed with code {ret}\n{stderr}") + + @property + def _codec(self) -> str: + match self._format: + case "gif": + return "gif" + case "mp4": + return "h264" + case "webm": + return "vp9" + case _: + raise ValueError(f"Unsupported format: {self._format}") + + def _save_media(self, file_path: Path): + if isinstance(self._value, np.ndarray): + video = TrackioVideo._process_ndarray(self._value) + TrackioVideo.write_video(file_path, video, fps=self._fps, codec=self._codec) + elif isinstance(self._value, str | Path): + if os.path.isfile(self._value): + shutil.copy(self._value, file_path) + else: + raise ValueError(f"File not found: {self._value}") + + @staticmethod + def _process_ndarray(value: np.ndarray) -> np.ndarray: + # Verify value is either 4D (single video) or 5D array (batched videos). + # Expected format: (frames, channels, height, width) or (batch, frames, channels, height, width) + if value.ndim < 4: + raise ValueError( + "Video requires at least 4 dimensions (frames, channels, height, width)" + ) + if value.ndim > 5: + raise ValueError( + "Videos can have at most 5 dimensions (batch, frames, channels, height, width)" + ) + if value.ndim == 4: + # Reshape to 5D with single batch: (1, frames, channels, height, width) + value = value[np.newaxis, ...] + + value = TrackioVideo._tile_batched_videos(value) + return value + + @staticmethod + def _tile_batched_videos(video: np.ndarray) -> np.ndarray: + """ + Tiles a batch of videos into a grid of videos. + + Input format: (batch, frames, channels, height, width) - original FCHW format + Output format: (frames, total_height, total_width, channels) + """ + batch_size, frames, channels, height, width = video.shape + + next_pow2 = 1 << (batch_size - 1).bit_length() + if batch_size != next_pow2: + pad_len = next_pow2 - batch_size + pad_shape = (pad_len, frames, channels, height, width) + padding = np.zeros(pad_shape, dtype=video.dtype) + video = np.concatenate((video, padding), axis=0) + batch_size = next_pow2 + + n_rows = 1 << ((batch_size.bit_length() - 1) // 2) + n_cols = batch_size // n_rows + + # Reshape to grid layout: (n_rows, n_cols, frames, channels, height, width) + video = video.reshape(n_rows, n_cols, frames, channels, height, width) + + # Rearrange dimensions to (frames, total_height, total_width, channels) + video = video.transpose(2, 0, 4, 1, 5, 3) + video = video.reshape(frames, n_rows * height, n_cols * width, channels) + return video diff --git a/trackio/package.json b/trackio/package.json new file mode 100644 index 0000000000000000000000000000000000000000..3b98c4265c449d9d5262622a8d2a6e4c2b15f69f --- /dev/null +++ b/trackio/package.json @@ -0,0 +1,6 @@ +{ + "name": "trackio", + "version": "0.22.0", + "description": "", + "python": "true" +} diff --git a/trackio/py.typed b/trackio/py.typed new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/trackio/remote_client.py b/trackio/remote_client.py new file mode 100644 index 0000000000000000000000000000000000000000..452302b6b0e5984d1e01c6960a2e221f8ce16233 --- /dev/null +++ b/trackio/remote_client.py @@ -0,0 +1,28 @@ +from __future__ import annotations + +from gradio_client import Client + + +class RemoteClient: + def __init__(self, space: str, hf_token: str | None = None): + self._space = space + kwargs: dict = {"verbose": False} + if hf_token: + kwargs["hf_token"] = hf_token + try: + self._client = Client(space, **kwargs) + except Exception as e: + raise ConnectionError( + f"Could not connect to Space '{space}'. Is it running?\n{e}" + ) + + def predict(self, *args, api_name: str): + try: + return self._client.predict(*args, api_name=api_name) + except Exception as e: + if "API Not Found" in str(e) or "api_name" in str(e): + raise RuntimeError( + f"Space '{self._space}' does not support '{api_name}'. " + "Redeploy with `trackio sync`." + ) + raise diff --git a/trackio/run.py b/trackio/run.py new file mode 100644 index 0000000000000000000000000000000000000000..6102dfa61f26a97652c6f56a89043cafb8bdc983 --- /dev/null +++ b/trackio/run.py @@ -0,0 +1,739 @@ +import os +import shutil +import threading +import uuid +import warnings +from datetime import datetime, timezone +from pathlib import Path + +import huggingface_hub +from gradio_client import Client, handle_file + +from trackio import utils +from trackio.alerts import ( + AlertLevel, + format_alert_terminal, + resolve_webhook_min_level, + send_webhook, + should_send_webhook, +) +from trackio.apple_gpu import AppleGpuMonitor, apple_gpu_available +from trackio.gpu import GpuMonitor, gpu_available +from trackio.histogram import Histogram +from trackio.markdown import Markdown +from trackio.media import TrackioMedia, get_project_media_path +from trackio.sqlite_storage import SQLiteStorage +from trackio.table import Table +from trackio.typehints import AlertEntry, LogEntry, SystemLogEntry, UploadEntry +from trackio.utils import _get_default_namespace + +BATCH_SEND_INTERVAL = 0.5 +MAX_BACKOFF = 30 + + +class Run: + def __init__( + self, + url: str | None, + project: str, + client: Client | None, + name: str | None = None, + group: str | None = None, + config: dict | None = None, + space_id: str | None = None, + auto_log_gpu: bool = False, + gpu_log_interval: float = 10.0, + webhook_url: str | None = None, + webhook_min_level: AlertLevel | str | None = None, + ): + """ + Initialize a Run for logging metrics to Trackio. + + Args: + url: The URL of the Trackio server (local Gradio app or HF Space). + project: The name of the project to log metrics to. + client: A pre-configured gradio_client.Client instance, or None to + create one automatically in a background thread with retry logic. + Passing None is recommended for normal usage. Passing a client + is useful for testing (e.g., injecting a mock client). + name: The name of this run. If None, a readable name like + "brave-sunset-0" is auto-generated. If space_id is provided, + generates a "username-timestamp" format instead. + group: Optional group name to organize related runs together. + config: A dictionary of configuration/hyperparameters for this run. + Keys starting with '_' are reserved for internal use. + space_id: The HF Space ID if logging to a Space (e.g., "user/space"). + If provided, media files will be uploaded to the Space. + auto_log_gpu: Whether to automatically log GPU metrics (utilization, + memory, temperature) at regular intervals. + gpu_log_interval: The interval in seconds between GPU metric logs. + Only used when auto_log_gpu is True. + webhook_url: A webhook URL to POST alert payloads to. Supports + Slack and Discord webhook URLs natively. Can also be set via + the TRACKIO_WEBHOOK_URL environment variable. + webhook_min_level: Minimum alert level that should trigger webhook + delivery. For example, `AlertLevel.WARN` sends only WARN and + ERROR alerts to webhook destinations. Can also be set via + `TRACKIO_WEBHOOK_MIN_LEVEL`. + """ + self.url = url + self.project = project + self._client_lock = threading.Lock() + self._client_thread = None + self._client = client + self._space_id = space_id + self.name = name or utils.generate_readable_name( + SQLiteStorage.get_runs(project), space_id + ) + self.group = group + self.config = utils.to_json_safe(config or {}) + + if isinstance(self.config, dict): + for key in self.config: + if key.startswith("_"): + raise ValueError( + f"Config key '{key}' is reserved (keys starting with '_' are reserved for internal use)" + ) + + self.config["_Username"] = self._get_username() + self.config["_Created"] = datetime.now(timezone.utc).isoformat() + self.config["_Group"] = self.group + + self._queued_logs: list[LogEntry] = [] + self._queued_system_logs: list[SystemLogEntry] = [] + self._queued_uploads: list[UploadEntry] = [] + self._queued_alerts: list[AlertEntry] = [] + self._stop_flag = threading.Event() + self._config_logged = False + max_step = SQLiteStorage.get_max_step_for_run(self.project, self.name) + self._next_step = 0 if max_step is None else max_step + 1 + self._has_local_buffer = False + + self._is_local = space_id is None + self._webhook_url = webhook_url or os.environ.get("TRACKIO_WEBHOOK_URL") + self._webhook_min_level = resolve_webhook_min_level( + webhook_min_level or os.environ.get("TRACKIO_WEBHOOK_MIN_LEVEL") + ) + + if self._is_local: + self._local_sender_thread = threading.Thread( + target=self._local_batch_sender + ) + self._local_sender_thread.daemon = True + self._local_sender_thread.start() + else: + self._client_thread = threading.Thread(target=self._init_client_background) + self._client_thread.daemon = True + self._client_thread.start() + + self._gpu_monitor: "GpuMonitor | AppleGpuMonitor | None" = None + if auto_log_gpu: + if gpu_available(): + self._gpu_monitor = GpuMonitor(self, interval=gpu_log_interval) + self._gpu_monitor.start() + elif apple_gpu_available(): + self._gpu_monitor = AppleGpuMonitor(self, interval=gpu_log_interval) + self._gpu_monitor.start() + + def _get_username(self) -> str | None: + try: + return _get_default_namespace() + except Exception: + return None + + def _local_batch_sender(self): + while ( + not self._stop_flag.is_set() + or len(self._queued_logs) > 0 + or len(self._queued_system_logs) > 0 + or len(self._queued_alerts) > 0 + ): + if not self._stop_flag.is_set(): + self._stop_flag.wait(timeout=BATCH_SEND_INTERVAL) + + with self._client_lock: + if self._queued_logs: + logs_to_send = self._queued_logs.copy() + self._queued_logs.clear() + self._write_logs_to_sqlite(logs_to_send) + + if self._queued_system_logs: + system_logs_to_send = self._queued_system_logs.copy() + self._queued_system_logs.clear() + self._write_system_logs_to_sqlite(system_logs_to_send) + + if self._queued_alerts: + alerts_to_send = self._queued_alerts.copy() + self._queued_alerts.clear() + self._write_alerts_to_sqlite(alerts_to_send) + + def _write_logs_to_sqlite(self, logs: list[LogEntry]): + logs_by_run: dict[tuple, dict] = {} + for entry in logs: + key = (entry["project"], entry["run"]) + if key not in logs_by_run: + logs_by_run[key] = { + "metrics": [], + "steps": [], + "log_ids": [], + "config": None, + } + logs_by_run[key]["metrics"].append(entry["metrics"]) + logs_by_run[key]["steps"].append(entry.get("step")) + logs_by_run[key]["log_ids"].append(entry.get("log_id")) + if entry.get("config") and logs_by_run[key]["config"] is None: + logs_by_run[key]["config"] = entry["config"] + + for (project, run), data in logs_by_run.items(): + has_log_ids = any(lid is not None for lid in data["log_ids"]) + SQLiteStorage.bulk_log( + project=project, + run=run, + metrics_list=data["metrics"], + steps=data["steps"], + config=data["config"], + log_ids=data["log_ids"] if has_log_ids else None, + ) + + def _write_system_logs_to_sqlite(self, logs: list[SystemLogEntry]): + logs_by_run: dict[tuple, dict] = {} + for entry in logs: + key = (entry["project"], entry["run"]) + if key not in logs_by_run: + logs_by_run[key] = {"metrics": [], "timestamps": [], "log_ids": []} + logs_by_run[key]["metrics"].append(entry["metrics"]) + logs_by_run[key]["timestamps"].append(entry.get("timestamp")) + logs_by_run[key]["log_ids"].append(entry.get("log_id")) + + for (project, run), data in logs_by_run.items(): + has_log_ids = any(lid is not None for lid in data["log_ids"]) + SQLiteStorage.bulk_log_system( + project=project, + run=run, + metrics_list=data["metrics"], + timestamps=data["timestamps"], + log_ids=data["log_ids"] if has_log_ids else None, + ) + + def _write_alerts_to_sqlite(self, alerts: list[AlertEntry]): + alerts_by_run: dict[tuple, dict] = {} + for entry in alerts: + key = (entry["project"], entry["run"]) + if key not in alerts_by_run: + alerts_by_run[key] = { + "titles": [], + "texts": [], + "levels": [], + "steps": [], + "timestamps": [], + "alert_ids": [], + } + alerts_by_run[key]["titles"].append(entry["title"]) + alerts_by_run[key]["texts"].append(entry.get("text")) + alerts_by_run[key]["levels"].append(entry["level"]) + alerts_by_run[key]["steps"].append(entry.get("step")) + alerts_by_run[key]["timestamps"].append(entry.get("timestamp")) + alerts_by_run[key]["alert_ids"].append(entry.get("alert_id")) + + for (project, run), data in alerts_by_run.items(): + has_alert_ids = any(aid is not None for aid in data["alert_ids"]) + SQLiteStorage.bulk_alert( + project=project, + run=run, + titles=data["titles"], + texts=data["texts"], + levels=data["levels"], + steps=data["steps"], + timestamps=data["timestamps"], + alert_ids=data["alert_ids"] if has_alert_ids else None, + ) + + def _batch_sender(self): + consecutive_failures = 0 + while ( + not self._stop_flag.is_set() + or len(self._queued_logs) > 0 + or len(self._queued_system_logs) > 0 + or len(self._queued_uploads) > 0 + or len(self._queued_alerts) > 0 + or self._has_local_buffer + ): + if not self._stop_flag.is_set(): + if consecutive_failures: + sleep_time = min( + BATCH_SEND_INTERVAL * (2**consecutive_failures), MAX_BACKOFF + ) + else: + sleep_time = BATCH_SEND_INTERVAL + self._stop_flag.wait(timeout=sleep_time) + elif self._has_local_buffer: + self._stop_flag.wait(timeout=BATCH_SEND_INTERVAL) + + with self._client_lock: + if self._client is None: + if self._stop_flag.is_set(): + if self._queued_logs: + self._persist_logs_locally(self._queued_logs) + self._queued_logs.clear() + if self._queued_system_logs: + self._persist_system_logs_locally(self._queued_system_logs) + self._queued_system_logs.clear() + if self._queued_uploads: + self._persist_uploads_locally(self._queued_uploads) + self._queued_uploads.clear() + if self._queued_alerts: + self._write_alerts_to_sqlite(self._queued_alerts) + self._queued_alerts.clear() + return + + failed = False + + if self._queued_logs: + logs_to_send = self._queued_logs.copy() + self._queued_logs.clear() + try: + self._client.predict( + api_name="/bulk_log", + logs=logs_to_send, + hf_token=huggingface_hub.utils.get_token(), + ) + except Exception: + self._persist_logs_locally(logs_to_send) + failed = True + + if self._queued_system_logs: + system_logs_to_send = self._queued_system_logs.copy() + self._queued_system_logs.clear() + try: + self._client.predict( + api_name="/bulk_log_system", + logs=system_logs_to_send, + hf_token=huggingface_hub.utils.get_token(), + ) + except Exception: + self._persist_system_logs_locally(system_logs_to_send) + failed = True + + if self._queued_uploads: + uploads_to_send = self._queued_uploads.copy() + self._queued_uploads.clear() + try: + self._client.predict( + api_name="/bulk_upload_media", + uploads=uploads_to_send, + hf_token=huggingface_hub.utils.get_token(), + ) + except Exception: + self._persist_uploads_locally(uploads_to_send) + failed = True + + if self._queued_alerts: + alerts_to_send = self._queued_alerts.copy() + self._queued_alerts.clear() + try: + self._client.predict( + api_name="/bulk_alert", + alerts=alerts_to_send, + hf_token=huggingface_hub.utils.get_token(), + ) + except Exception: + self._write_alerts_to_sqlite(alerts_to_send) + failed = True + + if failed: + consecutive_failures += 1 + else: + consecutive_failures = 0 + if self._has_local_buffer: + self._flush_local_buffer() + + def _persist_logs_locally(self, logs: list[LogEntry]): + if not self._space_id: + return + logs_by_run: dict[tuple, dict] = {} + for entry in logs: + key = (entry["project"], entry["run"]) + if key not in logs_by_run: + logs_by_run[key] = { + "metrics": [], + "steps": [], + "log_ids": [], + "config": None, + } + logs_by_run[key]["metrics"].append(entry["metrics"]) + logs_by_run[key]["steps"].append(entry.get("step")) + logs_by_run[key]["log_ids"].append(entry.get("log_id")) + if entry.get("config") and logs_by_run[key]["config"] is None: + logs_by_run[key]["config"] = entry["config"] + + for (project, run), data in logs_by_run.items(): + SQLiteStorage.bulk_log( + project=project, + run=run, + metrics_list=data["metrics"], + steps=data["steps"], + log_ids=data["log_ids"], + config=data["config"], + space_id=self._space_id, + ) + self._has_local_buffer = True + + def _persist_system_logs_locally(self, logs: list[SystemLogEntry]): + if not self._space_id: + return + logs_by_run: dict[tuple, dict] = {} + for entry in logs: + key = (entry["project"], entry["run"]) + if key not in logs_by_run: + logs_by_run[key] = {"metrics": [], "timestamps": [], "log_ids": []} + logs_by_run[key]["metrics"].append(entry["metrics"]) + logs_by_run[key]["timestamps"].append(entry.get("timestamp")) + logs_by_run[key]["log_ids"].append(entry.get("log_id")) + + for (project, run), data in logs_by_run.items(): + SQLiteStorage.bulk_log_system( + project=project, + run=run, + metrics_list=data["metrics"], + timestamps=data["timestamps"], + log_ids=data["log_ids"], + space_id=self._space_id, + ) + self._has_local_buffer = True + + def _persist_uploads_locally(self, uploads: list[UploadEntry]): + if not self._space_id: + return + for entry in uploads: + file_data = entry.get("uploaded_file") + file_path = "" + if isinstance(file_data, dict): + file_path = file_data.get("path", "") + elif hasattr(file_data, "path"): + file_path = str(file_data.path) + else: + file_path = str(file_data) + SQLiteStorage.add_pending_upload( + project=entry["project"], + space_id=self._space_id, + run_name=entry.get("run"), + step=entry.get("step"), + file_path=file_path, + relative_path=entry.get("relative_path"), + ) + self._has_local_buffer = True + + def _flush_local_buffer(self): + try: + buffered_logs = SQLiteStorage.get_pending_logs(self.project) + if buffered_logs: + self._client.predict( + api_name="/bulk_log", + logs=buffered_logs["logs"], + hf_token=huggingface_hub.utils.get_token(), + ) + SQLiteStorage.clear_pending_logs(self.project, buffered_logs["ids"]) + + buffered_sys = SQLiteStorage.get_pending_system_logs(self.project) + if buffered_sys: + self._client.predict( + api_name="/bulk_log_system", + logs=buffered_sys["logs"], + hf_token=huggingface_hub.utils.get_token(), + ) + SQLiteStorage.clear_pending_system_logs( + self.project, buffered_sys["ids"] + ) + + buffered_uploads = SQLiteStorage.get_pending_uploads(self.project) + if buffered_uploads: + upload_entries = [] + for u in buffered_uploads["uploads"]: + fp = u["file_path"] + if Path(fp).exists(): + upload_entries.append( + { + "project": u["project"], + "run": u["run"], + "step": u["step"], + "relative_path": u["relative_path"], + "uploaded_file": handle_file(fp), + } + ) + if upload_entries: + self._client.predict( + api_name="/bulk_upload_media", + uploads=upload_entries, + hf_token=huggingface_hub.utils.get_token(), + ) + SQLiteStorage.clear_pending_uploads( + self.project, buffered_uploads["ids"] + ) + + self._has_local_buffer = False + except Exception: + pass + + def _init_client_background(self): + if self._client is None: + fib = utils.fibo() + for sleep_coefficient in fib: + if self._stop_flag.is_set(): + break + try: + client = Client(self.url, verbose=False) + + with self._client_lock: + self._client = client + break + except Exception: + pass + sleep_time = min(0.1 * sleep_coefficient, MAX_BACKOFF) + self._stop_flag.wait(timeout=sleep_time) + + self._batch_sender() + + def _queue_upload( + self, + file_path, + step: int | None, + relative_path: str | None = None, + use_run_name: bool = True, + ): + if self._is_local: + self._save_upload_locally(file_path, step, relative_path, use_run_name) + else: + upload_entry: UploadEntry = { + "project": self.project, + "run": self.name if use_run_name else None, + "step": step, + "relative_path": relative_path, + "uploaded_file": handle_file(file_path), + } + with self._client_lock: + self._queued_uploads.append(upload_entry) + + def _save_upload_locally( + self, + file_path, + step: int | None, + relative_path: str | None = None, + use_run_name: bool = True, + ): + media_path = get_project_media_path( + project=self.project, + run=self.name if use_run_name else None, + step=step, + relative_path=relative_path, + ) + src = Path(file_path) + if src.exists() and str(src.resolve()) != str(Path(media_path).resolve()): + shutil.copy(str(src), str(media_path)) + + def _process_media(self, value: TrackioMedia, step: int | None) -> dict: + value._save(self.project, self.name, step if step is not None else 0) + if self._space_id: + self._queue_upload(value._get_absolute_file_path(), step) + return value._to_dict() + + def _scan_and_queue_media_uploads(self, table_dict: dict, step: int | None): + if not self._space_id: + return + + table_data = table_dict.get("_value", []) + for row in table_data: + for value in row.values(): + if isinstance(value, dict) and value.get("_type") in [ + "trackio.image", + "trackio.video", + "trackio.audio", + ]: + file_path = value.get("file_path") + if file_path: + from trackio.utils import MEDIA_DIR + + absolute_path = MEDIA_DIR / file_path + self._queue_upload(absolute_path, step) + elif isinstance(value, list): + for item in value: + if isinstance(item, dict) and item.get("_type") in [ + "trackio.image", + "trackio.video", + "trackio.audio", + ]: + file_path = item.get("file_path") + if file_path: + from trackio.utils import MEDIA_DIR + + absolute_path = MEDIA_DIR / file_path + self._queue_upload(absolute_path, step) + + def _ensure_sender_alive(self): + if self._is_local: + if ( + hasattr(self, "_local_sender_thread") + and not self._local_sender_thread.is_alive() + and not self._stop_flag.is_set() + ): + self._local_sender_thread = threading.Thread( + target=self._local_batch_sender + ) + self._local_sender_thread.daemon = True + self._local_sender_thread.start() + else: + if ( + self._client_thread is not None + and not self._client_thread.is_alive() + and not self._stop_flag.is_set() + ): + self._client_thread = threading.Thread( + target=self._init_client_background + ) + self._client_thread.daemon = True + self._client_thread.start() + + def log(self, metrics: dict, step: int | None = None): + renamed_keys = [] + new_metrics = {} + + for k, v in metrics.items(): + if k in utils.RESERVED_KEYS or k.startswith("__"): + new_key = f"__{k}" + renamed_keys.append(k) + new_metrics[new_key] = v + else: + new_metrics[k] = v + + if renamed_keys: + warnings.warn(f"Reserved keys renamed: {renamed_keys} → '__{{key}}'") + + metrics = new_metrics + for key, value in metrics.items(): + if isinstance(value, Table): + metrics[key] = value._to_dict( + project=self.project, run=self.name, step=step + ) + self._scan_and_queue_media_uploads(metrics[key], step) + elif isinstance(value, Histogram): + metrics[key] = value._to_dict() + elif isinstance(value, Markdown): + metrics[key] = value._to_dict() + elif isinstance(value, TrackioMedia): + metrics[key] = self._process_media(value, step) + metrics = utils.serialize_values(metrics) + + if step is None: + step = self._next_step + self._next_step = max(self._next_step, step + 1) + + config_to_log = None + if not self._config_logged and self.config: + config_to_log = utils.to_json_safe(self.config) + self._config_logged = True + + log_entry: LogEntry = { + "project": self.project, + "run": self.name, + "metrics": metrics, + "step": step, + "config": config_to_log, + "log_id": uuid.uuid4().hex, + } + + with self._client_lock: + self._queued_logs.append(log_entry) + self._ensure_sender_alive() + + def alert( + self, + title: str, + text: str | None = None, + level: AlertLevel = AlertLevel.WARN, + step: int | None = None, + webhook_url: str | None = None, + ): + if step is None: + step = max(self._next_step - 1, 0) + timestamp = datetime.now(timezone.utc).isoformat() + + print(format_alert_terminal(level, title, text, step)) + + alert_entry: AlertEntry = { + "project": self.project, + "run": self.name, + "title": title, + "text": text, + "level": level.value, + "step": step, + "timestamp": timestamp, + "alert_id": uuid.uuid4().hex, + } + + with self._client_lock: + self._queued_alerts.append(alert_entry) + self._ensure_sender_alive() + + url = webhook_url or self._webhook_url + if url and should_send_webhook(level, self._webhook_min_level): + t = threading.Thread( + target=send_webhook, + args=( + url, + level, + title, + text, + self.project, + self.name, + step, + timestamp, + ), + daemon=True, + ) + t.start() + + def log_system(self, metrics: dict): + metrics = utils.serialize_values(metrics) + timestamp = datetime.now(timezone.utc).isoformat() + + system_log_entry: SystemLogEntry = { + "project": self.project, + "run": self.name, + "metrics": metrics, + "timestamp": timestamp, + "log_id": uuid.uuid4().hex, + } + + with self._client_lock: + self._queued_system_logs.append(system_log_entry) + self._ensure_sender_alive() + + def finish(self): + if self._gpu_monitor is not None: + self._gpu_monitor.stop() + + self._stop_flag.set() + + if self._is_local: + if hasattr(self, "_local_sender_thread"): + print("* Run finished. Uploading logs to Trackio (please wait...)") + self._local_sender_thread.join(timeout=30) + if self._local_sender_thread.is_alive(): + warnings.warn( + "Could not flush all logs within 30s. Some data may be buffered locally." + ) + else: + if self._client_thread is not None: + print( + "* Run finished. Uploading logs to Trackio Space (please wait...)" + ) + self._client_thread.join(timeout=30) + if self._client_thread.is_alive(): + warnings.warn( + "Could not flush all logs within 30s. Some data may be buffered locally." + ) + if SQLiteStorage.has_pending_data(self.project): + warnings.warn( + f"* Some logs could not be sent to the Space (it may still be starting up). " + f"They have been saved locally and will be sent automatically next time you call: " + f'trackio.init(project="{self.project}", space_id="{self._space_id}")' + ) diff --git a/trackio/server.py b/trackio/server.py new file mode 100644 index 0000000000000000000000000000000000000000..a8ca4b9d14b9894921c59206e1797d0ca4013370 --- /dev/null +++ b/trackio/server.py @@ -0,0 +1,769 @@ +"""The main API layer for the Trackio UI.""" + +import base64 +import logging +import os +import re +import secrets +import shutil +import sqlite3 +import threading +import time +from collections import deque +from functools import lru_cache +from typing import Any +from urllib.parse import urlencode + +import httpx +import huggingface_hub as hf +from starlette.requests import Request +from starlette.responses import RedirectResponse +from starlette.routing import Route + +import trackio.utils as utils +from trackio.asgi_app import create_trackio_starlette_app +from trackio.exceptions import TrackioAPIError +from trackio.media import get_project_media_path +from trackio.sqlite_storage import SQLiteStorage +from trackio.typehints import AlertEntry, LogEntry, SystemLogEntry, UploadEntry + +HfApi = hf.HfApi() + +logger = logging.getLogger("trackio") + +_write_queue: deque[tuple[str, Any]] = deque() +_flush_thread: threading.Thread | None = None +_flush_lock = threading.Lock() +_FLUSH_INTERVAL = 2.0 +_MAX_RETRIES = 30 + + +def _enqueue_write(kind: str, payload: Any) -> None: + _write_queue.append((kind, payload)) + _ensure_flush_thread() + + +def _ensure_flush_thread() -> None: + global _flush_thread + with _flush_lock: + if _flush_thread is not None and _flush_thread.is_alive(): + return + _flush_thread = threading.Thread(target=_flush_loop, daemon=True) + _flush_thread.start() + + +def _flush_loop() -> None: + retries = 0 + while _write_queue and retries < _MAX_RETRIES: + kind, payload = _write_queue[0] + try: + if kind == "bulk_log": + SQLiteStorage.bulk_log(**payload) + elif kind == "bulk_log_system": + SQLiteStorage.bulk_log_system(**payload) + elif kind == "bulk_alert": + SQLiteStorage.bulk_alert(**payload) + _write_queue.popleft() + retries = 0 + except sqlite3.OperationalError as e: + msg = str(e).lower() + if "disk i/o error" in msg or "readonly" in msg: + retries += 1 + logger.warning( + "write queue: flush failed (%s), retry %d/%d", + e, + retries, + _MAX_RETRIES, + ) + time.sleep(min(_FLUSH_INTERVAL * retries, 15.0)) + else: + logger.error("write queue: non-retryable error (%s), dropping entry", e) + _write_queue.popleft() + retries = 0 + if _write_queue: + logger.error( + "write queue: giving up after %d retries, %d entries dropped", + _MAX_RETRIES, + len(_write_queue), + ) + _write_queue.clear() + + +write_token = secrets.token_urlsafe(32) + +OAUTH_CALLBACK_PATH = "/login/callback" +OAUTH_START_PATH = "/oauth/hf/start" + + +def _hf_access_token(request: Request) -> str | None: + session_id = None + try: + session_id = request.headers.get("x-trackio-oauth-session") + except (AttributeError, TypeError): + pass + if session_id and session_id in _oauth_sessions: + token, created = _oauth_sessions[session_id] + if time.monotonic() - created <= _OAUTH_SESSION_TTL: + return token + del _oauth_sessions[session_id] + cookie_header = "" + try: + cookie_header = request.headers.get("cookie", "") + except (AttributeError, TypeError): + pass + if cookie_header: + for cookie in cookie_header.split(";"): + parts = cookie.strip().split("=", 1) + if len(parts) == 2 and parts[0] == "trackio_hf_access_token": + return parts[1] or None + return None + + +def _oauth_redirect_uri(request: Request) -> str: + space_host = os.getenv("SPACE_HOST") + if space_host: + space_host = space_host.split(",")[0] + return f"https://{space_host}{OAUTH_CALLBACK_PATH}" + return str(request.base_url).rstrip("/") + OAUTH_CALLBACK_PATH + + +_OAUTH_STATE_TTL = 86400 +_OAUTH_SESSION_TTL = 86400 * 30 +_pending_oauth_states: dict[str, float] = {} +_oauth_sessions: dict[str, tuple[str, float]] = {} + + +def _evict_expired_oauth(): + now = time.monotonic() + expired_states = [ + k for k, t in _pending_oauth_states.items() if now - t > _OAUTH_STATE_TTL + ] + for k in expired_states: + del _pending_oauth_states[k] + expired_sessions = [ + k for k, (_, t) in _oauth_sessions.items() if now - t > _OAUTH_SESSION_TTL + ] + for k in expired_sessions: + del _oauth_sessions[k] + + +def oauth_hf_start(request: Request): + client_id = os.getenv("OAUTH_CLIENT_ID") + if not client_id: + return RedirectResponse(url="/", status_code=302) + _evict_expired_oauth() + state = secrets.token_urlsafe(32) + _pending_oauth_states[state] = time.monotonic() + redirect_uri = _oauth_redirect_uri(request) + scope = os.getenv("OAUTH_SCOPES", "openid profile").strip() + url = "https://huggingface.co/oauth/authorize?" + urlencode( + { + "client_id": client_id, + "redirect_uri": redirect_uri, + "response_type": "code", + "scope": scope, + "state": state, + } + ) + return RedirectResponse(url=url, status_code=302) + + +def oauth_hf_callback(request: Request): + client_id = os.getenv("OAUTH_CLIENT_ID") + client_secret = os.getenv("OAUTH_CLIENT_SECRET") + err = "/?oauth_error=1" + if not client_id or not client_secret: + return RedirectResponse(url=err, status_code=302) + got_state = request.query_params.get("state") + code = request.query_params.get("code") + if not got_state or got_state not in _pending_oauth_states or not code: + return RedirectResponse(url=err, status_code=302) + state_created = _pending_oauth_states.pop(got_state) + if time.monotonic() - state_created > _OAUTH_STATE_TTL: + return RedirectResponse(url=err, status_code=302) + redirect_uri = _oauth_redirect_uri(request) + auth_b64 = base64.b64encode(f"{client_id}:{client_secret}".encode()).decode() + try: + with httpx.Client() as client: + token_resp = client.post( + "https://huggingface.co/oauth/token", + headers={"Authorization": f"Basic {auth_b64}"}, + data={ + "grant_type": "authorization_code", + "code": code, + "redirect_uri": redirect_uri, + "client_id": client_id, + }, + ) + token_resp.raise_for_status() + access_token = token_resp.json()["access_token"] + except Exception: + return RedirectResponse(url=err, status_code=302) + session_id = secrets.token_urlsafe(32) + _oauth_sessions[session_id] = (access_token, time.monotonic()) + on_spaces = os.getenv("SYSTEM") == "spaces" + resp = RedirectResponse(url=f"/?oauth_session={session_id}", status_code=302) + resp.set_cookie( + key="trackio_hf_access_token", + value=access_token, + httponly=True, + samesite="none" if on_spaces else "lax", + max_age=86400 * 30, + path="/", + secure=on_spaces, + ) + return resp + + +def oauth_logout(request: Request): + on_spaces = os.getenv("SYSTEM") == "spaces" + resp = RedirectResponse(url="/", status_code=302) + resp.delete_cookie( + "trackio_hf_access_token", + path="/", + samesite="none" if on_spaces else "lax", + secure=on_spaces, + ) + return resp + + +@lru_cache(maxsize=32) +def check_hf_token_has_write_access(hf_token: str | None) -> None: + """ + Checks if the provided hf_token has write access to the space. If it does not + have write access, a PermissionError is raised. Otherwise, the function returns None. + + The function is cached in two separate caches to avoid unnecessary API calls to /whoami-v2 which is heavily rate-limited: + - A cache of the whoami response for the hf_token using .whoami(token=hf_token, cache=True). + - This entire function is cached using @lru_cache(maxsize=32). + """ + if os.getenv("SYSTEM") == "spaces": + if hf_token is None: + raise PermissionError( + "Expected a HF_TOKEN to be provided when logging to a Space" + ) + space_token = os.getenv("HF_TOKEN") + if space_token and hf_token == space_token: + # If the HF_TOKEN is the same as the space token, we can assume that the user has write access. + # This avoids unnecessary API calls to /whoami-v2 which is heavily rate-limited. + return + who = HfApi.whoami(token=hf_token, cache=True) + owner_name = os.getenv("SPACE_AUTHOR_NAME") + repo_name = os.getenv("SPACE_REPO_NAME") + orgs = [o["name"] for o in who["orgs"]] + if owner_name != who["name"] and owner_name not in orgs: + raise PermissionError( + "Expected the provided hf_token to be the user owner of the space, or be a member of the org owner of the space" + ) + access_token = who["auth"]["accessToken"] + if access_token["role"] == "fineGrained": + matched = False + for item in access_token["fineGrained"]["scoped"]: + if ( + item["entity"]["type"] == "space" + and item["entity"]["name"] == f"{owner_name}/{repo_name}" + and "repo.write" in item["permissions"] + ): + matched = True + break + if ( + ( + item["entity"]["type"] == "user" + or item["entity"]["type"] == "org" + ) + and item["entity"]["name"] == owner_name + and "repo.write" in item["permissions"] + ): + matched = True + break + if not matched: + raise PermissionError( + "Expected the provided hf_token with fine grained permissions to provide write access to the space" + ) + elif access_token["role"] != "write": + raise PermissionError( + "Expected the provided hf_token to provide write permissions" + ) + + +_oauth_write_cache: dict[str, tuple[bool, float]] = {} +_OAUTH_WRITE_CACHE_TTL = 300 + + +def check_oauth_token_has_write_access(oauth_token: str | None) -> None: + if not os.getenv("SYSTEM") == "spaces": + return + if oauth_token is None: + raise PermissionError( + "Expected an oauth to be provided when logging to a Space" + ) + now = time.monotonic() + cached = _oauth_write_cache.get(oauth_token) + if cached is not None: + allowed, ts = cached + if now - ts < _OAUTH_WRITE_CACHE_TTL: + if not allowed: + raise PermissionError( + "Expected the oauth token to be the user owner of the space, or be a member of the org owner of the space" + ) + return + who = HfApi.whoami(oauth_token, cache=True) + user_name = who["name"] + owner_name = os.getenv("SPACE_AUTHOR_NAME") + if user_name == owner_name: + _oauth_write_cache[oauth_token] = (True, now) + return + for org in who["orgs"]: + if org["name"] == owner_name and org["roleInOrg"] == "write": + _oauth_write_cache[oauth_token] = (True, now) + return + _oauth_write_cache[oauth_token] = (False, now) + raise PermissionError( + "Expected the oauth token to be the user owner of the space, or be a member of the org owner of the space" + ) + + +def check_write_access(request: Request, token: str) -> bool: + cookies = request.headers.get("cookie", "") + if cookies: + for cookie in cookies.split(";"): + parts = cookie.strip().split("=", 1) + if len(parts) == 2 and parts[0] == "trackio_write_token": + return parts[1] == token + if hasattr(request, "query_params") and request.query_params: + qp = request.query_params.get("write_token") + return qp == token + return False + + +def assert_can_mutate_runs(request: Request) -> None: + if os.getenv("SYSTEM") != "spaces": + if check_write_access(request, write_token): + return + raise TrackioAPIError( + "A write_token is required to delete or rename runs. " + "Open the dashboard using the link that includes the write_token query parameter." + ) + hf_tok = _hf_access_token(request) + if hf_tok is not None: + try: + check_oauth_token_has_write_access(hf_tok) + except PermissionError as e: + raise TrackioAPIError(str(e)) from e + return + if check_write_access(request, write_token): + return + raise TrackioAPIError( + "Sign in with Hugging Face to delete or rename runs. You need write access to this Space, " + "or open the dashboard using a link that includes the write_token query parameter." + ) + + +def get_run_mutation_status(request: Request) -> dict[str, Any]: + if os.getenv("SYSTEM") != "spaces": + if check_write_access(request, write_token): + return {"spaces": False, "allowed": True, "auth": "local"} + return {"spaces": False, "allowed": False, "auth": "none"} + hf_tok = _hf_access_token(request) + if hf_tok is not None: + try: + check_oauth_token_has_write_access(hf_tok) + return {"spaces": True, "allowed": True, "auth": "oauth"} + except PermissionError: + return {"spaces": True, "allowed": False, "auth": "oauth_insufficient"} + if check_write_access(request, write_token): + return {"spaces": True, "allowed": True, "auth": "write_token"} + return {"spaces": True, "allowed": False, "auth": "none"} + + +def upload_db_to_space(project: str, uploaded_db: dict, hf_token: str | None) -> None: + check_hf_token_has_write_access(hf_token) + db_project_path = SQLiteStorage.get_project_db_path(project) + os.makedirs(os.path.dirname(db_project_path), exist_ok=True) + shutil.copy(uploaded_db["path"], db_project_path) + + +def bulk_upload_media(uploads: list[UploadEntry], hf_token: str | None) -> None: + check_hf_token_has_write_access(hf_token) + for upload in uploads: + media_path = get_project_media_path( + project=upload["project"], + run=upload["run"], + step=upload["step"], + relative_path=upload["relative_path"], + ) + shutil.copy(upload["uploaded_file"]["path"], media_path) + + +def log( + project: str, + run: str, + metrics: dict[str, Any], + step: int | None, + hf_token: str | None, +) -> None: + check_hf_token_has_write_access(hf_token) + SQLiteStorage.log(project=project, run=run, metrics=metrics, step=step) + + +def bulk_log( + logs: list[LogEntry], + hf_token: str | None, +) -> None: + check_hf_token_has_write_access(hf_token) + + logs_by_run = {} + for log_entry in logs: + key = (log_entry["project"], log_entry["run"]) + if key not in logs_by_run: + logs_by_run[key] = { + "metrics": [], + "steps": [], + "log_ids": [], + "config": None, + } + logs_by_run[key]["metrics"].append(log_entry["metrics"]) + logs_by_run[key]["steps"].append(log_entry.get("step")) + logs_by_run[key]["log_ids"].append(log_entry.get("log_id")) + if log_entry.get("config") and logs_by_run[key]["config"] is None: + logs_by_run[key]["config"] = log_entry["config"] + + for (project, run), data in logs_by_run.items(): + has_log_ids = any(lid is not None for lid in data["log_ids"]) + payload = dict( + project=project, + run=run, + metrics_list=data["metrics"], + steps=data["steps"], + config=data["config"], + log_ids=data["log_ids"] if has_log_ids else None, + ) + try: + SQLiteStorage.bulk_log(**payload) + except sqlite3.OperationalError: + _enqueue_write("bulk_log", payload) + + +def bulk_log_system( + logs: list[SystemLogEntry], + hf_token: str | None, +) -> None: + check_hf_token_has_write_access(hf_token) + + logs_by_run = {} + for log_entry in logs: + key = (log_entry["project"], log_entry["run"]) + if key not in logs_by_run: + logs_by_run[key] = {"metrics": [], "timestamps": [], "log_ids": []} + logs_by_run[key]["metrics"].append(log_entry["metrics"]) + logs_by_run[key]["timestamps"].append(log_entry.get("timestamp")) + logs_by_run[key]["log_ids"].append(log_entry.get("log_id")) + + for (project, run), data in logs_by_run.items(): + has_log_ids = any(lid is not None for lid in data["log_ids"]) + payload = dict( + project=project, + run=run, + metrics_list=data["metrics"], + timestamps=data["timestamps"], + log_ids=data["log_ids"] if has_log_ids else None, + ) + try: + SQLiteStorage.bulk_log_system(**payload) + except sqlite3.OperationalError: + _enqueue_write("bulk_log_system", payload) + + +def bulk_alert( + alerts: list[AlertEntry], + hf_token: str | None, +) -> None: + check_hf_token_has_write_access(hf_token) + + alerts_by_run: dict[tuple, dict] = {} + for entry in alerts: + key = (entry["project"], entry["run"]) + if key not in alerts_by_run: + alerts_by_run[key] = { + "titles": [], + "texts": [], + "levels": [], + "steps": [], + "timestamps": [], + "alert_ids": [], + } + alerts_by_run[key]["titles"].append(entry["title"]) + alerts_by_run[key]["texts"].append(entry.get("text")) + alerts_by_run[key]["levels"].append(entry["level"]) + alerts_by_run[key]["steps"].append(entry.get("step")) + alerts_by_run[key]["timestamps"].append(entry.get("timestamp")) + alerts_by_run[key]["alert_ids"].append(entry.get("alert_id")) + + for (project, run), data in alerts_by_run.items(): + has_alert_ids = any(aid is not None for aid in data["alert_ids"]) + payload = dict( + project=project, + run=run, + titles=data["titles"], + texts=data["texts"], + levels=data["levels"], + steps=data["steps"], + timestamps=data["timestamps"], + alert_ids=data["alert_ids"] if has_alert_ids else None, + ) + try: + SQLiteStorage.bulk_alert(**payload) + except sqlite3.OperationalError: + _enqueue_write("bulk_alert", payload) + + +def get_alerts( + project: str, + run: str | None = None, + level: str | None = None, + since: str | None = None, +) -> list[dict]: + return SQLiteStorage.get_alerts(project, run_name=run, level=level, since=since) + + +def get_metric_values( + project: str, + run: str, + metric_name: str, + step: int | None = None, + around_step: int | None = None, + at_time: str | None = None, + window: int | None = None, +) -> list[dict]: + return SQLiteStorage.get_metric_values( + project, + run, + metric_name, + step=step, + around_step=around_step, + at_time=at_time, + window=window, + ) + + +def get_runs_for_project(project: str) -> list[str]: + return SQLiteStorage.get_runs(project) + + +def get_metrics_for_run(project: str, run: str) -> list[str]: + return SQLiteStorage.get_all_metrics_for_run(project, run) + + +def filter_metrics_by_regex(metrics: list[str], filter_pattern: str) -> list[str]: + if not filter_pattern.strip(): + return metrics + try: + pattern = re.compile(filter_pattern, re.IGNORECASE) + return [metric for metric in metrics if pattern.search(metric)] + except re.error: + return [ + metric for metric in metrics if filter_pattern.lower() in metric.lower() + ] + + +def get_all_projects() -> list[str]: + return SQLiteStorage.get_projects() + + +def get_project_summary(project: str) -> dict: + runs = SQLiteStorage.get_runs(project) + if not runs: + return {"project": project, "num_runs": 0, "runs": [], "last_activity": None} + + last_steps = SQLiteStorage.get_max_steps_for_runs(project) + + return { + "project": project, + "num_runs": len(runs), + "runs": runs, + "last_activity": max(last_steps.values()) if last_steps else None, + } + + +def get_run_summary(project: str, run: str) -> dict: + num_logs = SQLiteStorage.get_log_count(project, run) + if num_logs == 0: + return { + "project": project, + "run": run, + "num_logs": 0, + "metrics": [], + "config": None, + "last_step": None, + } + + metrics = SQLiteStorage.get_all_metrics_for_run(project, run) + config = SQLiteStorage.get_run_config(project, run) + last_step = SQLiteStorage.get_last_step(project, run) + + return { + "project": project, + "run": run, + "num_logs": num_logs, + "metrics": metrics, + "config": config, + "last_step": last_step, + } + + +def get_system_metrics_for_run(project: str, run: str) -> list[str]: + return SQLiteStorage.get_all_system_metrics_for_run(project, run) + + +def get_system_logs(project: str, run: str) -> list[dict]: + return SQLiteStorage.get_system_logs(project, run) + + +def get_snapshot( + project: str, + run: str, + step: int | None = None, + around_step: int | None = None, + at_time: str | None = None, + window: int | None = None, +) -> dict: + return SQLiteStorage.get_snapshot( + project, run, step=step, around_step=around_step, at_time=at_time, window=window + ) + + +def get_logs(project: str, run: str) -> list[dict]: + return SQLiteStorage.get_logs(project, run, max_points=1500) + + +def get_settings() -> dict: + return { + "logo_urls": utils.get_logo_urls(), + "color_palette": utils.get_color_palette(), + "plot_order": [ + item.strip() + for item in os.environ.get("TRACKIO_PLOT_ORDER", "").split(",") + if item.strip() + ], + "table_truncate_length": int( + os.environ.get("TRACKIO_TABLE_TRUNCATE_LENGTH", "250") + ), + "media_dir": str(utils.MEDIA_DIR), + } + + +def get_project_files(project: str) -> list[dict]: + files_dir = utils.MEDIA_DIR / project / "files" + if not files_dir.exists(): + return [] + results = [] + for file_path in sorted(files_dir.rglob("*")): + if file_path.is_file(): + relative = file_path.relative_to(files_dir) + results.append( + { + "name": str(relative), + "path": str(file_path), + "size": file_path.stat().st_size, + } + ) + return results + + +def delete_run(request: Request, project: str, run: str) -> bool: + assert_can_mutate_runs(request) + return SQLiteStorage.delete_run(project, run) + + +def rename_run( + request: Request, + project: str, + old_name: str, + new_name: str, +) -> bool: + assert_can_mutate_runs(request) + SQLiteStorage.rename_run(project, old_name, new_name) + return True + + +def force_sync() -> bool: + if os.environ.get("TRACKIO_BUCKET_ID"): + return True + SQLiteStorage._dataset_import_attempted = True + SQLiteStorage.export_to_parquet() + scheduler = SQLiteStorage.get_scheduler() + scheduler.trigger().result() + return True + + +CSS = "" +HEAD = "" + + +def _api_registry() -> dict[str, Any]: + return { + "get_run_mutation_status": get_run_mutation_status, + "upload_db_to_space": upload_db_to_space, + "bulk_upload_media": bulk_upload_media, + "log": log, + "bulk_log": bulk_log, + "bulk_log_system": bulk_log_system, + "bulk_alert": bulk_alert, + "get_alerts": get_alerts, + "get_metric_values": get_metric_values, + "get_runs_for_project": get_runs_for_project, + "get_metrics_for_run": get_metrics_for_run, + "get_all_projects": get_all_projects, + "get_project_summary": get_project_summary, + "get_run_summary": get_run_summary, + "get_system_metrics_for_run": get_system_metrics_for_run, + "get_system_logs": get_system_logs, + "get_snapshot": get_snapshot, + "get_logs": get_logs, + "get_settings": get_settings, + "get_project_files": get_project_files, + "delete_run": delete_run, + "rename_run": rename_run, + "force_sync": force_sync, + } + + +class TrackioDashboardApp: + def __init__(self, starlette_app, uvicorn_server: Any, write_token: str) -> None: + self.app = starlette_app + self._uvicorn_server = uvicorn_server + self.write_token = write_token + + def close(self, verbose: bool = True) -> None: + if self._uvicorn_server is not None: + self._uvicorn_server.should_exit = True + + +def build_starlette_app_only(mcp_server: bool = False) -> tuple[Any, str]: + oauth_routes = [ + Route(OAUTH_START_PATH, oauth_hf_start, methods=["GET"]), + Route(OAUTH_CALLBACK_PATH, oauth_hf_callback, methods=["GET"]), + Route("/oauth/logout", oauth_logout, methods=["GET"]), + ] + mcp_lifespan = None + if mcp_server: + try: + from trackio.mcp_setup import mcp_lifespan_context + + mcp_lifespan = mcp_lifespan_context + except ImportError: + pass + starlette_app = create_trackio_starlette_app( + oauth_routes, + _api_registry(), + mcp_lifespan=mcp_lifespan, + ) + from trackio.frontend_server import mount_frontend + + mount_frontend(starlette_app) + return starlette_app, write_token + + +def make_trackio_server(mcp_server: bool = False) -> TrackioDashboardApp: + app, wt = build_starlette_app_only(mcp_server=mcp_server) + return TrackioDashboardApp(app, None, wt) diff --git a/trackio/sqlite_storage.py b/trackio/sqlite_storage.py new file mode 100644 index 0000000000000000000000000000000000000000..c26dc4cb816d869914c9d4c3b41293fcca0c99ab --- /dev/null +++ b/trackio/sqlite_storage.py @@ -0,0 +1,1920 @@ +import json as json_mod +import os +import shutil +import sqlite3 +import time +from collections.abc import Iterator +from contextlib import contextmanager +from datetime import datetime, timezone +from pathlib import Path +from threading import Lock + +try: + import fcntl +except ImportError: + fcntl = None + +try: + import msvcrt as _msvcrt +except ImportError: + _msvcrt = None + +import huggingface_hub as hf +import orjson +import pandas as pd + +from trackio.commit_scheduler import CommitScheduler +from trackio.dummy_commit_scheduler import DummyCommitScheduler +from trackio.utils import ( + MEDIA_DIR, + TRACKIO_DIR, + deserialize_values, + get_color_palette, + serialize_values, +) + +DB_EXT = ".db" + +_JOURNAL_MODE_WHITELIST = frozenset( + {"wal", "delete", "truncate", "persist", "memory", "off"} +) + + +def _configure_sqlite_pragmas(conn: sqlite3.Connection) -> None: + override = os.environ.get("TRACKIO_SQLITE_JOURNAL_MODE", "").strip().lower() + if override in _JOURNAL_MODE_WHITELIST: + journal = override.upper() + elif os.environ.get("SYSTEM") == "spaces": + journal = "DELETE" + else: + journal = "WAL" + conn.execute(f"PRAGMA journal_mode = {journal}") + conn.execute("PRAGMA synchronous = NORMAL") + conn.execute("PRAGMA temp_store = MEMORY") + conn.execute("PRAGMA cache_size = -20000") + + +class ProcessLock: + """A file-based lock that works across processes using fcntl (Unix) or msvcrt (Windows).""" + + def __init__(self, lockfile_path: Path): + self.lockfile_path = lockfile_path + self.lockfile = None + + def __enter__(self): + if fcntl is None and _msvcrt is None: + return self + self.lockfile_path.parent.mkdir(parents=True, exist_ok=True) + self.lockfile = open(self.lockfile_path, "w") + + max_retries = 100 + for attempt in range(max_retries): + try: + if fcntl is not None: + fcntl.flock(self.lockfile.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB) + else: + _msvcrt.locking(self.lockfile.fileno(), _msvcrt.LK_NBLCK, 1) + return self + except (IOError, OSError): + if attempt < max_retries - 1: + time.sleep(0.1) + else: + raise IOError("Could not acquire database lock after 10 seconds") + + def __exit__(self, exc_type, exc_val, exc_tb): + if self.lockfile: + try: + if fcntl is not None: + fcntl.flock(self.lockfile.fileno(), fcntl.LOCK_UN) + elif _msvcrt is not None: + _msvcrt.locking(self.lockfile.fileno(), _msvcrt.LK_UNLCK, 1) + except (IOError, OSError): + pass + self.lockfile.close() + + +class SQLiteStorage: + _dataset_import_attempted = False + _current_scheduler: CommitScheduler | DummyCommitScheduler | None = None + _scheduler_lock = Lock() + + @staticmethod + @contextmanager + def _get_connection( + db_path: Path, + *, + timeout: float = 30.0, + configure_pragmas: bool = True, + row_factory=sqlite3.Row, + ) -> Iterator[sqlite3.Connection]: + conn = sqlite3.connect(str(db_path), timeout=timeout) + try: + if configure_pragmas: + _configure_sqlite_pragmas(conn) + if row_factory is not None: + conn.row_factory = row_factory + with conn: + yield conn + finally: + conn.close() + + @staticmethod + def _get_process_lock(project: str) -> ProcessLock: + lockfile_path = TRACKIO_DIR / f"{project}.lock" + return ProcessLock(lockfile_path) + + @staticmethod + def get_project_db_filename(project: str) -> str: + """Get the database filename for a specific project.""" + safe_project_name = "".join( + c for c in project if c.isalnum() or c in ("-", "_") + ).rstrip() + if not safe_project_name: + safe_project_name = "default" + return f"{safe_project_name}{DB_EXT}" + + @staticmethod + def get_project_db_path(project: str) -> Path: + """Get the database path for a specific project.""" + filename = SQLiteStorage.get_project_db_filename(project) + return TRACKIO_DIR / filename + + @staticmethod + def init_db(project: str) -> Path: + """ + Initialize the SQLite database with required tables. + Returns the database path. + """ + SQLiteStorage._ensure_hub_loaded() + db_path = SQLiteStorage.get_project_db_path(project) + db_path.parent.mkdir(parents=True, exist_ok=True) + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path, row_factory=None) as conn: + cursor = conn.cursor() + cursor.execute( + """ + CREATE TABLE IF NOT EXISTS metrics ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp TEXT NOT NULL, + run_name TEXT NOT NULL, + step INTEGER NOT NULL, + metrics TEXT NOT NULL + ) + """ + ) + cursor.execute( + """ + CREATE TABLE IF NOT EXISTS configs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + run_name TEXT NOT NULL, + config TEXT NOT NULL, + created_at TEXT NOT NULL, + UNIQUE(run_name) + ) + """ + ) + cursor.execute( + """ + CREATE INDEX IF NOT EXISTS idx_metrics_run_step + ON metrics(run_name, step) + """ + ) + cursor.execute( + """ + CREATE INDEX IF NOT EXISTS idx_configs_run_name + ON configs(run_name) + """ + ) + cursor.execute( + """ + CREATE INDEX IF NOT EXISTS idx_metrics_run_timestamp + ON metrics(run_name, timestamp) + """ + ) + cursor.execute( + """ + CREATE TABLE IF NOT EXISTS system_metrics ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp TEXT NOT NULL, + run_name TEXT NOT NULL, + metrics TEXT NOT NULL + ) + """ + ) + cursor.execute( + """ + CREATE INDEX IF NOT EXISTS idx_system_metrics_run_timestamp + ON system_metrics(run_name, timestamp) + """ + ) + + cursor.execute( + """ + CREATE TABLE IF NOT EXISTS project_metadata ( + key TEXT PRIMARY KEY, + value TEXT NOT NULL + ) + """ + ) + + cursor.execute( + """ + CREATE TABLE IF NOT EXISTS pending_uploads ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + space_id TEXT NOT NULL, + run_name TEXT, + step INTEGER, + file_path TEXT NOT NULL, + relative_path TEXT, + created_at TEXT NOT NULL + ) + """ + ) + + cursor.execute( + """ + CREATE TABLE IF NOT EXISTS alerts ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + timestamp TEXT NOT NULL, + run_name TEXT NOT NULL, + title TEXT NOT NULL, + text TEXT, + level TEXT NOT NULL DEFAULT 'warn', + step INTEGER, + alert_id TEXT + ) + """ + ) + cursor.execute( + """ + CREATE INDEX IF NOT EXISTS idx_alerts_run + ON alerts(run_name) + """ + ) + cursor.execute( + """ + CREATE INDEX IF NOT EXISTS idx_alerts_timestamp + ON alerts(timestamp) + """ + ) + cursor.execute( + """ + CREATE UNIQUE INDEX IF NOT EXISTS idx_alerts_alert_id + ON alerts(alert_id) WHERE alert_id IS NOT NULL + """ + ) + + for table in ("metrics", "system_metrics"): + for col in ("log_id TEXT", "space_id TEXT"): + try: + cursor.execute(f"ALTER TABLE {table} ADD COLUMN {col}") + except sqlite3.OperationalError: + pass + cursor.execute( + f"""CREATE UNIQUE INDEX IF NOT EXISTS idx_{table}_log_id + ON {table}(log_id) WHERE log_id IS NOT NULL""" + ) + cursor.execute( + f"""CREATE INDEX IF NOT EXISTS idx_{table}_pending + ON {table}(space_id) WHERE space_id IS NOT NULL""" + ) + + conn.commit() + return db_path + + @staticmethod + def _flatten_json_column(df: pd.DataFrame, col: str) -> pd.DataFrame: + if df.empty: + return df + expanded = df[col].copy() + expanded = pd.DataFrame( + expanded.apply( + lambda x: deserialize_values(orjson.loads(x)) + ).values.tolist(), + index=df.index, + ) + df = df.drop(columns=[col]) + expanded = expanded.loc[:, ~expanded.columns.isin(df.columns)] + return pd.concat([df, expanded], axis=1) + + @staticmethod + def _read_table(db_path: Path, table: str) -> pd.DataFrame: + try: + with SQLiteStorage._get_connection( + db_path, timeout=5.0, configure_pragmas=False, row_factory=None + ) as conn: + return pd.read_sql(f"SELECT * FROM {table}", conn) + except Exception: + return pd.DataFrame() + + @staticmethod + def _flatten_and_write_parquet( + db_path: Path, table: str, json_col: str, parquet_path: Path + ) -> None: + if ( + parquet_path.exists() + and db_path.stat().st_mtime <= parquet_path.stat().st_mtime + ): + return + df = SQLiteStorage._read_table(db_path, table) + if df.empty: + return + df = SQLiteStorage._flatten_json_column(df, json_col) + df.to_parquet( + parquet_path, + write_page_index=True, + use_content_defined_chunking=True, + ) + + @staticmethod + def export_to_parquet(): + """ + Exports all projects' DB files as Parquet under the same path but with extension ".parquet". + Also exports system_metrics to separate parquet files with "_system.parquet" suffix. + Also exports configs to separate parquet files with "_configs.parquet" suffix. + """ + if not SQLiteStorage._dataset_import_attempted: + return + if not TRACKIO_DIR.exists(): + return + + all_paths = os.listdir(TRACKIO_DIR) + db_names = [f for f in all_paths if f.endswith(DB_EXT)] + for db_name in db_names: + db_path = TRACKIO_DIR / db_name + SQLiteStorage._flatten_and_write_parquet( + db_path, "metrics", "metrics", db_path.with_suffix(".parquet") + ) + SQLiteStorage._flatten_and_write_parquet( + db_path, + "system_metrics", + "metrics", + TRACKIO_DIR / (db_path.stem + "_system.parquet"), + ) + SQLiteStorage._flatten_and_write_parquet( + db_path, + "configs", + "config", + TRACKIO_DIR / (db_path.stem + "_configs.parquet"), + ) + + @staticmethod + def export_for_static_space( + project: str, output_dir: Path, db_path_override: Path | None = None + ) -> None: + """ + Exports a single project's data as Parquet + JSON files for static Space deployment. + + Args: + project: The project name. + output_dir: Directory to write the exported files to. + db_path_override: If provided, read from this DB file instead of the + default local project path. Useful when exporting from a downloaded + remote database. + """ + db_path = db_path_override or SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + raise FileNotFoundError(f"No database found for project '{project}'") + + output_dir.mkdir(parents=True, exist_ok=True) + aux_dir = output_dir / "aux" + aux_dir.mkdir(parents=True, exist_ok=True) + + metrics_df = SQLiteStorage._read_table(db_path, "metrics") + if not metrics_df.empty: + flat = SQLiteStorage._flatten_json_column(metrics_df.copy(), "metrics") + flat.to_parquet(output_dir / "metrics.parquet") + + sys_df = SQLiteStorage._read_table(db_path, "system_metrics") + if not sys_df.empty: + flat = SQLiteStorage._flatten_json_column(sys_df.copy(), "metrics") + flat.to_parquet(aux_dir / "system_metrics.parquet") + + configs_df = SQLiteStorage._read_table(db_path, "configs") + if not configs_df.empty: + flat = SQLiteStorage._flatten_json_column(configs_df.copy(), "config") + flat.to_parquet(aux_dir / "configs.parquet") + + try: + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + cursor.execute( + """SELECT run_name, MAX(step) as last_step, COUNT(*) as log_count + FROM metrics GROUP BY run_name ORDER BY MIN(timestamp) ASC""" + ) + rows = cursor.fetchall() + runs_meta = [ + { + "name": row["run_name"], + "last_step": row["last_step"], + "log_count": row["log_count"], + } + for row in rows + ] + except sqlite3.OperationalError: + runs_meta = [] + with open(output_dir / "runs.json", "w") as f: + json_mod.dump(runs_meta, f) + + settings = { + "color_palette": get_color_palette(), + "plot_order": [ + item.strip() + for item in os.environ.get("TRACKIO_PLOT_ORDER", "").split(",") + if item.strip() + ], + } + with open(output_dir / "settings.json", "w") as f: + json_mod.dump(settings, f) + + @staticmethod + def _cleanup_wal_sidecars(db_path: Path) -> None: + """Remove leftover -wal/-shm files for a DB basename (prevents disk I/O errors).""" + for suffix in ("-wal", "-shm"): + sidecar = Path(str(db_path) + suffix) + try: + if sidecar.exists(): + sidecar.unlink() + except Exception: + pass + + @staticmethod + def import_from_parquet(): + """ + Imports to all DB files that have matching files under the same path but with extension ".parquet". + Also imports system_metrics from "_system.parquet" files. + Also imports configs from "_configs.parquet" files. + """ + if not TRACKIO_DIR.exists(): + return + + all_paths = os.listdir(TRACKIO_DIR) + parquet_names = [ + f + for f in all_paths + if f.endswith(".parquet") + and not f.endswith("_system.parquet") + and not f.endswith("_configs.parquet") + ] + imported_projects = {Path(name).stem for name in parquet_names} + for pq_name in parquet_names: + parquet_path = TRACKIO_DIR / pq_name + db_path = parquet_path.with_suffix(DB_EXT) + + SQLiteStorage._cleanup_wal_sidecars(db_path) + + df = pd.read_parquet(parquet_path) + if "metrics" not in df.columns: + metrics = df.copy() + structural_cols = [ + "id", + "timestamp", + "run_name", + "step", + "log_id", + "space_id", + ] + df = df[[c for c in structural_cols if c in df.columns]] + for col in structural_cols: + if col in metrics.columns: + del metrics[col] + metrics = orjson.loads(metrics.to_json(orient="records")) + df["metrics"] = [orjson.dumps(serialize_values(row)) for row in metrics] + + with SQLiteStorage._get_connection( + db_path, configure_pragmas=False, row_factory=None + ) as conn: + df.to_sql("metrics", conn, if_exists="replace", index=False) + conn.commit() + + system_parquet_names = [f for f in all_paths if f.endswith("_system.parquet")] + for pq_name in system_parquet_names: + parquet_path = TRACKIO_DIR / pq_name + db_name = pq_name.replace("_system.parquet", DB_EXT) + db_path = TRACKIO_DIR / db_name + project_name = db_path.stem + if project_name not in imported_projects and not db_path.exists(): + continue + + df = pd.read_parquet(parquet_path) + if "metrics" not in df.columns: + metrics = df.copy() + other_cols = ["id", "timestamp", "run_name"] + df = df[[c for c in other_cols if c in df.columns]] + for col in other_cols: + if col in metrics.columns: + del metrics[col] + metrics = orjson.loads(metrics.to_json(orient="records")) + df["metrics"] = [orjson.dumps(serialize_values(row)) for row in metrics] + + with SQLiteStorage._get_connection( + db_path, configure_pragmas=False, row_factory=None + ) as conn: + df.to_sql("system_metrics", conn, if_exists="replace", index=False) + conn.commit() + + configs_parquet_names = [f for f in all_paths if f.endswith("_configs.parquet")] + for pq_name in configs_parquet_names: + parquet_path = TRACKIO_DIR / pq_name + db_name = pq_name.replace("_configs.parquet", DB_EXT) + db_path = TRACKIO_DIR / db_name + project_name = db_path.stem + if project_name not in imported_projects and not db_path.exists(): + continue + + df = pd.read_parquet(parquet_path) + if "config" not in df.columns: + config_data = df.copy() + other_cols = ["id", "run_name", "created_at"] + df = df[[c for c in other_cols if c in df.columns]] + for col in other_cols: + if col in config_data.columns: + del config_data[col] + config_data = orjson.loads(config_data.to_json(orient="records")) + df["config"] = [ + orjson.dumps(serialize_values(row)) for row in config_data + ] + + with SQLiteStorage._get_connection( + db_path, configure_pragmas=False, row_factory=None + ) as conn: + df.to_sql("configs", conn, if_exists="replace", index=False) + conn.commit() + + @staticmethod + def get_scheduler(): + """ + Get the scheduler for the database based on the environment variables. + This applies to both local and Spaces. + """ + with SQLiteStorage._scheduler_lock: + if SQLiteStorage._current_scheduler is not None: + return SQLiteStorage._current_scheduler + hf_token = os.environ.get("HF_TOKEN") + dataset_id = os.environ.get("TRACKIO_DATASET_ID") + space_repo_name = os.environ.get("SPACE_REPO_NAME") + if dataset_id is not None and space_repo_name is not None: + scheduler = CommitScheduler( + repo_id=dataset_id, + repo_type="dataset", + folder_path=TRACKIO_DIR, + private=True, + allow_patterns=[ + "*.parquet", + "*_system.parquet", + "*_configs.parquet", + "media/**/*", + ], + squash_history=True, + token=hf_token, + on_before_commit=SQLiteStorage.export_to_parquet, + ) + else: + scheduler = DummyCommitScheduler() + SQLiteStorage._current_scheduler = scheduler + return scheduler + + @staticmethod + def log(project: str, run: str, metrics: dict, step: int | None = None): + """ + Safely log metrics to the database. Before logging, this method will ensure the database exists + and is set up with the correct tables. It also uses a cross-process lock to prevent + database locking errors when multiple processes access the same database. + + This method is not used in the latest versions of Trackio (replaced by bulk_log) but + is kept for backwards compatibility for users who are connecting to a newer version of + a Trackio Spaces dashboard with an older version of Trackio installed locally. + """ + db_path = SQLiteStorage.init_db(project) + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + cursor.execute( + """ + SELECT MAX(step) + FROM metrics + WHERE run_name = ? + """, + (run,), + ) + last_step = cursor.fetchone()[0] + current_step = ( + 0 + if step is None and last_step is None + else (step if step is not None else last_step + 1) + ) + current_timestamp = datetime.now(timezone.utc).isoformat() + cursor.execute( + """ + INSERT INTO metrics + (timestamp, run_name, step, metrics) + VALUES (?, ?, ?, ?) + """, + ( + current_timestamp, + run, + current_step, + orjson.dumps(serialize_values(metrics)), + ), + ) + conn.commit() + + @staticmethod + def bulk_log( + project: str, + run: str, + metrics_list: list[dict], + steps: list[int] | None = None, + timestamps: list[str] | None = None, + config: dict | None = None, + log_ids: list[str] | None = None, + space_id: str | None = None, + ): + """ + Safely log bulk metrics to the database. Before logging, this method will ensure the database exists + and is set up with the correct tables. It also uses a cross-process lock to prevent + database locking errors when multiple processes access the same database. + """ + if not metrics_list: + return + + if timestamps is None: + timestamps = [datetime.now(timezone.utc).isoformat()] * len(metrics_list) + + db_path = SQLiteStorage.init_db(project) + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + + if steps is None: + steps = list(range(len(metrics_list))) + elif any(s is None for s in steps): + cursor.execute( + "SELECT MAX(step) FROM metrics WHERE run_name = ?", (run,) + ) + last_step = cursor.fetchone()[0] + current_step = 0 if last_step is None else last_step + 1 + processed_steps = [] + for step in steps: + if step is None: + processed_steps.append(current_step) + current_step += 1 + else: + processed_steps.append(step) + steps = processed_steps + + if len(metrics_list) != len(steps) or len(metrics_list) != len( + timestamps + ): + raise ValueError( + "metrics_list, steps, and timestamps must have the same length" + ) + + data = [] + for i, metrics in enumerate(metrics_list): + lid = log_ids[i] if log_ids else None + data.append( + ( + timestamps[i], + run, + steps[i], + orjson.dumps(serialize_values(metrics)), + lid, + space_id, + ) + ) + + cursor.executemany( + """ + INSERT OR IGNORE INTO metrics + (timestamp, run_name, step, metrics, log_id, space_id) + VALUES (?, ?, ?, ?, ?, ?) + """, + data, + ) + + if config: + current_timestamp = datetime.now(timezone.utc).isoformat() + cursor.execute( + """ + INSERT OR REPLACE INTO configs + (run_name, config, created_at) + VALUES (?, ?, ?) + """, + ( + run, + orjson.dumps(serialize_values(config)), + current_timestamp, + ), + ) + + conn.commit() + + @staticmethod + def bulk_log_system( + project: str, + run: str, + metrics_list: list[dict], + timestamps: list[str] | None = None, + log_ids: list[str] | None = None, + space_id: str | None = None, + ): + """ + Log system metrics (GPU, etc.) to the database without step numbers. + These metrics use timestamps for the x-axis instead of steps. + """ + if not metrics_list: + return + + if timestamps is None: + timestamps = [datetime.now(timezone.utc).isoformat()] * len(metrics_list) + + if len(metrics_list) != len(timestamps): + raise ValueError("metrics_list and timestamps must have the same length") + + db_path = SQLiteStorage.init_db(project) + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + data = [] + for i, metrics in enumerate(metrics_list): + lid = log_ids[i] if log_ids else None + data.append( + ( + timestamps[i], + run, + orjson.dumps(serialize_values(metrics)), + lid, + space_id, + ) + ) + + cursor.executemany( + """ + INSERT OR IGNORE INTO system_metrics + (timestamp, run_name, metrics, log_id, space_id) + VALUES (?, ?, ?, ?, ?) + """, + data, + ) + conn.commit() + + @staticmethod + def bulk_alert( + project: str, + run: str, + titles: list[str], + texts: list[str | None], + levels: list[str], + steps: list[int | None], + timestamps: list[str] | None = None, + alert_ids: list[str] | None = None, + ): + if not titles: + return + + if timestamps is None: + timestamps = [datetime.now(timezone.utc).isoformat()] * len(titles) + + db_path = SQLiteStorage.init_db(project) + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + data = [] + for i in range(len(titles)): + aid = alert_ids[i] if alert_ids else None + data.append( + ( + timestamps[i], + run, + titles[i], + texts[i], + levels[i], + steps[i], + aid, + ) + ) + + cursor.executemany( + """ + INSERT OR IGNORE INTO alerts + (timestamp, run_name, title, text, level, step, alert_id) + VALUES (?, ?, ?, ?, ?, ?, ?) + """, + data, + ) + conn.commit() + + @staticmethod + def get_alerts( + project: str, + run_name: str | None = None, + level: str | None = None, + since: str | None = None, + ) -> list[dict]: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return [] + + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + query = ( + "SELECT timestamp, run_name, title, text, level, step FROM alerts" + ) + conditions = [] + params = [] + if run_name is not None: + conditions.append("run_name = ?") + params.append(run_name) + if level is not None: + conditions.append("level = ?") + params.append(level) + if since is not None: + conditions.append("timestamp > ?") + params.append(since) + if conditions: + query += " WHERE " + " AND ".join(conditions) + query += " ORDER BY timestamp DESC" + cursor.execute(query, params) + + rows = cursor.fetchall() + return [ + { + "timestamp": row["timestamp"], + "run": row["run_name"], + "title": row["title"], + "text": row["text"], + "level": row["level"], + "step": row["step"], + } + for row in rows + ] + except sqlite3.OperationalError as e: + if "no such table: alerts" in str(e): + return [] + raise + + @staticmethod + def get_alert_count(project: str) -> int: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return 0 + + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute("SELECT COUNT(*) FROM alerts") + return cursor.fetchone()[0] + except sqlite3.OperationalError: + return 0 + + @staticmethod + def get_system_logs(project: str, run: str) -> list[dict]: + """Retrieve system metrics for a specific run. Returns metrics with timestamps (no steps).""" + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return [] + + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute( + """ + SELECT timestamp, metrics + FROM system_metrics + WHERE run_name = ? + ORDER BY timestamp + """, + (run,), + ) + + rows = cursor.fetchall() + results = [] + for row in rows: + metrics = orjson.loads(row["metrics"]) + metrics = deserialize_values(metrics) + metrics["timestamp"] = row["timestamp"] + results.append(metrics) + return results + except sqlite3.OperationalError as e: + if "no such table: system_metrics" in str(e): + return [] + raise + + @staticmethod + def get_all_system_metrics_for_run(project: str, run: str) -> list[str]: + """Get all system metric names for a specific project/run.""" + return SQLiteStorage._get_metric_names( + project, run, "system_metrics", exclude_keys={"timestamp"} + ) + + @staticmethod + def has_system_metrics(project: str) -> bool: + """Check if a project has any system metrics logged.""" + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return False + + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute("SELECT COUNT(*) FROM system_metrics LIMIT 1") + count = cursor.fetchone()[0] + return count > 0 + except sqlite3.OperationalError: + return False + + @staticmethod + def get_log_count(project: str, run: str) -> int: + SQLiteStorage._ensure_hub_loaded() + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return 0 + try: + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + cursor.execute( + "SELECT COUNT(*) FROM metrics WHERE run_name = ?", + (run,), + ) + return cursor.fetchone()[0] + except sqlite3.OperationalError as e: + if "no such table: metrics" in str(e): + return 0 + raise + + @staticmethod + def get_last_step(project: str, run: str) -> int | None: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return None + try: + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + cursor.execute( + "SELECT MAX(step) FROM metrics WHERE run_name = ?", + (run,), + ) + row = cursor.fetchone() + return row[0] if row and row[0] is not None else None + except sqlite3.OperationalError as e: + if "no such table: metrics" in str(e): + return None + raise + + @staticmethod + def get_logs(project: str, run: str, max_points: int | None = None) -> list[dict]: + """Retrieve logs for a specific run. Logs include the step count (int) and the timestamp (datetime object).""" + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return [] + + try: + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + cursor.execute( + """ + SELECT timestamp, step, metrics + FROM metrics + WHERE run_name = ? + ORDER BY timestamp + """, + (run,), + ) + + rows = cursor.fetchall() + if max_points is not None and len(rows) > max_points: + step = len(rows) / max_points + indices = {int(i * step) for i in range(max_points)} + indices.add(len(rows) - 1) + rows = [rows[i] for i in sorted(indices)] + + results = [] + for row in rows: + metrics = orjson.loads(row["metrics"]) + metrics = deserialize_values(metrics) + metrics["timestamp"] = row["timestamp"] + metrics["step"] = row["step"] + results.append(metrics) + return results + except sqlite3.OperationalError as e: + if "no such table: metrics" in str(e): + return [] + raise + + @staticmethod + def load_from_dataset(): + bucket_id = os.environ.get("TRACKIO_BUCKET_ID") + if bucket_id is not None: + if not SQLiteStorage._dataset_import_attempted: + from trackio.bucket_storage import download_bucket_to_trackio_dir + + try: + download_bucket_to_trackio_dir(bucket_id) + except Exception: + pass + SQLiteStorage._dataset_import_attempted = True + return + dataset_id = os.environ.get("TRACKIO_DATASET_ID") + space_repo_name = os.environ.get("SPACE_REPO_NAME") + if dataset_id is not None and space_repo_name is not None: + hfapi = hf.HfApi() + updated = False + if not TRACKIO_DIR.exists(): + TRACKIO_DIR.mkdir(parents=True, exist_ok=True) + with SQLiteStorage.get_scheduler().lock: + try: + files = hfapi.list_repo_files(dataset_id, repo_type="dataset") + for file in files: + # Download parquet and media assets + if not (file.endswith(".parquet") or file.startswith("media/")): + continue + if (TRACKIO_DIR / file).exists(): + continue + hf.hf_hub_download( + dataset_id, file, repo_type="dataset", local_dir=TRACKIO_DIR + ) + updated = True + except hf.errors.EntryNotFoundError: + pass + except hf.errors.RepositoryNotFoundError: + pass + if updated: + SQLiteStorage.import_from_parquet() + SQLiteStorage._dataset_import_attempted = True + + @staticmethod + def _ensure_hub_loaded(): + if not SQLiteStorage._dataset_import_attempted: + SQLiteStorage.load_from_dataset() + + @staticmethod + def get_projects() -> list[str]: + """ + Get list of all projects by scanning the database files in the trackio directory. + """ + SQLiteStorage._ensure_hub_loaded() + + projects: set[str] = set() + if not TRACKIO_DIR.exists(): + return [] + + for db_file in TRACKIO_DIR.glob(f"*{DB_EXT}"): + project_name = db_file.stem + projects.add(project_name) + return sorted(projects) + + @staticmethod + def get_runs(project: str) -> list[str]: + """Get list of all runs for a project, ordered by creation time.""" + SQLiteStorage._ensure_hub_loaded() + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return [] + + try: + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + cursor.execute( + """ + SELECT run_name + FROM metrics + GROUP BY run_name + ORDER BY MIN(timestamp) ASC + """, + ) + return [row[0] for row in cursor.fetchall()] + except sqlite3.OperationalError as e: + if "no such table: metrics" in str(e): + return [] + raise + + @staticmethod + def get_max_steps_for_runs(project: str) -> dict[str, int]: + """Get the maximum step for each run in a project.""" + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return {} + + try: + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + cursor.execute( + """ + SELECT run_name, MAX(step) as max_step + FROM metrics + GROUP BY run_name + """ + ) + + results = {} + for row in cursor.fetchall(): + results[row["run_name"]] = row["max_step"] + + return results + except sqlite3.OperationalError as e: + if "no such table: metrics" in str(e): + return {} + raise + + @staticmethod + def get_max_step_for_run(project: str, run: str) -> int | None: + """Get the maximum step for a specific run, or None if no logs exist.""" + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return None + + try: + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + cursor.execute( + "SELECT MAX(step) FROM metrics WHERE run_name = ?", (run,) + ) + result = cursor.fetchone()[0] + return result + except sqlite3.OperationalError as e: + if "no such table: metrics" in str(e): + return None + raise + + @staticmethod + def get_run_config(project: str, run: str) -> dict | None: + """Get configuration for a specific run.""" + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return None + + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute( + """ + SELECT config FROM configs WHERE run_name = ? + """, + (run,), + ) + + row = cursor.fetchone() + if row: + config = orjson.loads(row["config"]) + return deserialize_values(config) + return None + except sqlite3.OperationalError as e: + if "no such table: configs" in str(e): + return None + raise + + @staticmethod + def delete_run(project: str, run: str) -> bool: + """Delete a run from the database (metrics, config, and system_metrics).""" + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return False + + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute("DELETE FROM metrics WHERE run_name = ?", (run,)) + cursor.execute("DELETE FROM configs WHERE run_name = ?", (run,)) + try: + cursor.execute( + "DELETE FROM system_metrics WHERE run_name = ?", (run,) + ) + except sqlite3.OperationalError: + pass + try: + cursor.execute("DELETE FROM alerts WHERE run_name = ?", (run,)) + except sqlite3.OperationalError: + pass + conn.commit() + return True + except sqlite3.Error: + return False + + @staticmethod + def _update_media_paths(obj, old_prefix, new_prefix): + """Update media file paths in nested data structures.""" + if isinstance(obj, dict): + if obj.get("_type") in [ + "trackio.image", + "trackio.video", + "trackio.audio", + ]: + old_path = obj.get("file_path", "") + if isinstance(old_path, str): + normalized_path = old_path.replace("\\", "/") + if normalized_path.startswith(old_prefix): + new_path = normalized_path.replace(old_prefix, new_prefix, 1) + return {**obj, "file_path": new_path} + return { + key: SQLiteStorage._update_media_paths(value, old_prefix, new_prefix) + for key, value in obj.items() + } + elif isinstance(obj, list): + return [ + SQLiteStorage._update_media_paths(item, old_prefix, new_prefix) + for item in obj + ] + return obj + + @staticmethod + def _rewrite_metrics_rows(metrics_rows, new_run_name, old_prefix, new_prefix): + """Deserialize metrics rows, update media paths, and reserialize.""" + result = [] + for row in metrics_rows: + metrics_data = orjson.loads(row["metrics"]) + metrics_deserialized = deserialize_values(metrics_data) + updated = SQLiteStorage._update_media_paths( + metrics_deserialized, old_prefix, new_prefix + ) + result.append( + ( + row["timestamp"], + new_run_name, + row["step"], + orjson.dumps(serialize_values(updated)), + ) + ) + return result + + @staticmethod + def _move_media_dir(source: Path, target: Path): + """Move a media directory from source to target.""" + if source.exists(): + target.parent.mkdir(parents=True, exist_ok=True) + if target.exists(): + shutil.rmtree(target) + shutil.move(str(source), str(target)) + + @staticmethod + def rename_run(project: str, old_name: str, new_name: str) -> None: + """Rename a run within the same project. + + Raises: + ValueError: If the new name is empty, the old run doesn't exist, + or a run with the new name already exists. + RuntimeError: If the database operation fails. + """ + if not new_name or not new_name.strip(): + raise ValueError("New run name cannot be empty") + + new_name = new_name.strip() + + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + raise ValueError(f"Project '{project}' does not exist") + + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + + cursor.execute( + "SELECT COUNT(*) FROM metrics WHERE run_name = ?", (old_name,) + ) + if cursor.fetchone()[0] == 0: + raise ValueError( + f"Run '{old_name}' does not exist in project '{project}'" + ) + + cursor.execute( + "SELECT COUNT(*) FROM metrics WHERE run_name = ?", (new_name,) + ) + if cursor.fetchone()[0] > 0: + raise ValueError( + f"A run named '{new_name}' already exists in project '{project}'" + ) + + try: + cursor.execute( + "SELECT timestamp, step, metrics FROM metrics WHERE run_name = ?", + (old_name,), + ) + metrics_rows = cursor.fetchall() + + old_prefix = f"{project}/{old_name}/" + new_prefix = f"{project}/{new_name}/" + + updated_rows = SQLiteStorage._rewrite_metrics_rows( + metrics_rows, new_name, old_prefix, new_prefix + ) + + cursor.execute( + "DELETE FROM metrics WHERE run_name = ?", (old_name,) + ) + cursor.executemany( + "INSERT INTO metrics (timestamp, run_name, step, metrics) VALUES (?, ?, ?, ?)", + updated_rows, + ) + + cursor.execute( + "UPDATE configs SET run_name = ? WHERE run_name = ?", + (new_name, old_name), + ) + + try: + cursor.execute( + "UPDATE system_metrics SET run_name = ? WHERE run_name = ?", + (new_name, old_name), + ) + except sqlite3.OperationalError: + pass + + try: + cursor.execute( + "UPDATE alerts SET run_name = ? WHERE run_name = ?", + (new_name, old_name), + ) + except sqlite3.OperationalError: + pass + + conn.commit() + + SQLiteStorage._move_media_dir( + MEDIA_DIR / project / old_name, + MEDIA_DIR / project / new_name, + ) + except sqlite3.Error as e: + raise RuntimeError( + f"Database error while renaming run '{old_name}' to '{new_name}': {e}" + ) from e + + @staticmethod + def move_run(project: str, run: str, new_project: str) -> bool: + """Move a run from one project to another.""" + source_db_path = SQLiteStorage.get_project_db_path(project) + if not source_db_path.exists(): + return False + + target_db_path = SQLiteStorage.init_db(new_project) + + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_process_lock(new_project): + with SQLiteStorage._get_connection(source_db_path) as source_conn: + source_cursor = source_conn.cursor() + + source_cursor.execute( + "SELECT timestamp, step, metrics FROM metrics WHERE run_name = ?", + (run,), + ) + metrics_rows = source_cursor.fetchall() + + source_cursor.execute( + "SELECT config, created_at FROM configs WHERE run_name = ?", + (run,), + ) + config_row = source_cursor.fetchone() + + try: + source_cursor.execute( + "SELECT timestamp, metrics FROM system_metrics WHERE run_name = ?", + (run,), + ) + system_metrics_rows = source_cursor.fetchall() + except sqlite3.OperationalError: + system_metrics_rows = [] + + try: + source_cursor.execute( + "SELECT timestamp, title, text, level, step, alert_id FROM alerts WHERE run_name = ?", + (run,), + ) + alert_rows = source_cursor.fetchall() + except sqlite3.OperationalError: + alert_rows = [] + + if not metrics_rows and not config_row and not system_metrics_rows: + return False + + with SQLiteStorage._get_connection(target_db_path) as target_conn: + target_cursor = target_conn.cursor() + + old_prefix = f"{project}/{run}/" + new_prefix = f"{new_project}/{run}/" + updated_rows = SQLiteStorage._rewrite_metrics_rows( + metrics_rows, run, old_prefix, new_prefix + ) + + target_cursor.executemany( + "INSERT INTO metrics (timestamp, run_name, step, metrics) VALUES (?, ?, ?, ?)", + updated_rows, + ) + + if config_row: + target_cursor.execute( + """ + INSERT OR REPLACE INTO configs (run_name, config, created_at) + VALUES (?, ?, ?) + """, + (run, config_row["config"], config_row["created_at"]), + ) + + for row in system_metrics_rows: + try: + target_cursor.execute( + """ + INSERT INTO system_metrics (timestamp, run_name, metrics) + VALUES (?, ?, ?) + """, + (row["timestamp"], run, row["metrics"]), + ) + except sqlite3.OperationalError: + pass + + for row in alert_rows: + try: + target_cursor.execute( + """ + INSERT OR IGNORE INTO alerts (timestamp, run_name, title, text, level, step, alert_id) + VALUES (?, ?, ?, ?, ?, ?, ?) + """, + ( + row["timestamp"], + run, + row["title"], + row["text"], + row["level"], + row["step"], + row["alert_id"], + ), + ) + except sqlite3.OperationalError: + pass + + target_conn.commit() + + SQLiteStorage._move_media_dir( + MEDIA_DIR / project / run, + MEDIA_DIR / new_project / run, + ) + + source_cursor.execute( + "DELETE FROM metrics WHERE run_name = ?", (run,) + ) + source_cursor.execute( + "DELETE FROM configs WHERE run_name = ?", (run,) + ) + try: + source_cursor.execute( + "DELETE FROM system_metrics WHERE run_name = ?", (run,) + ) + except sqlite3.OperationalError: + pass + try: + source_cursor.execute( + "DELETE FROM alerts WHERE run_name = ?", (run,) + ) + except sqlite3.OperationalError: + pass + source_conn.commit() + + return True + + @staticmethod + def get_all_run_configs(project: str) -> dict[str, dict]: + """Get configurations for all runs in a project.""" + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return {} + + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute( + """ + SELECT run_name, config FROM configs + """ + ) + + results = {} + for row in cursor.fetchall(): + config = orjson.loads(row["config"]) + results[row["run_name"]] = deserialize_values(config) + return results + except sqlite3.OperationalError as e: + if "no such table: configs" in str(e): + return {} + raise + + @staticmethod + def get_metric_values( + project: str, + run: str, + metric_name: str, + step: int | None = None, + around_step: int | None = None, + at_time: str | None = None, + window: int | float | None = None, + ) -> list[dict]: + """Get values for a specific metric in a project/run with optional filtering. + + Filtering modes: + - step: return the single row at exactly this step + - around_step + window: return rows where step is in [around_step - window, around_step + window] + - at_time + window: return rows within ±window seconds of the ISO timestamp + - No filters: return all rows + """ + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return [] + + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + query = "SELECT timestamp, step, metrics FROM metrics WHERE run_name = ?" + params: list = [run] + + if step is not None: + query += " AND step = ?" + params.append(step) + elif around_step is not None and window is not None: + query += " AND step >= ? AND step <= ?" + params.extend([around_step - int(window), around_step + int(window)]) + elif at_time is not None and window is not None: + query += ( + " AND timestamp >= datetime(?, '-' || ? || ' seconds')" + " AND timestamp <= datetime(?, '+' || ? || ' seconds')" + ) + params.extend([at_time, int(window), at_time, int(window)]) + + query += " ORDER BY timestamp" + cursor.execute(query, params) + + rows = cursor.fetchall() + results = [] + for row in rows: + metrics = orjson.loads(row["metrics"]) + metrics = deserialize_values(metrics) + if metric_name in metrics: + results.append( + { + "timestamp": row["timestamp"], + "step": row["step"], + "value": metrics[metric_name], + } + ) + return results + + @staticmethod + def get_snapshot( + project: str, + run: str, + step: int | None = None, + around_step: int | None = None, + at_time: str | None = None, + window: int | float | None = None, + ) -> dict[str, list[dict]]: + """Get all metrics at/around a point in time or step. + + Returns a dict mapping metric names to lists of {timestamp, step, value}. + """ + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return {} + + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + query = "SELECT timestamp, step, metrics FROM metrics WHERE run_name = ?" + params: list = [run] + + if step is not None: + query += " AND step = ?" + params.append(step) + elif around_step is not None and window is not None: + query += " AND step >= ? AND step <= ?" + params.extend([around_step - int(window), around_step + int(window)]) + elif at_time is not None and window is not None: + query += ( + " AND timestamp >= datetime(?, '-' || ? || ' seconds')" + " AND timestamp <= datetime(?, '+' || ? || ' seconds')" + ) + params.extend([at_time, int(window), at_time, int(window)]) + + query += " ORDER BY timestamp" + cursor.execute(query, params) + + result: dict[str, list[dict]] = {} + for row in cursor.fetchall(): + metrics = orjson.loads(row["metrics"]) + metrics = deserialize_values(metrics) + for key, value in metrics.items(): + if key not in result: + result[key] = [] + result[key].append( + { + "timestamp": row["timestamp"], + "step": row["step"], + "value": value, + } + ) + return result + + @staticmethod + def get_all_metrics_for_run(project: str, run: str) -> list[str]: + """Get all metric names for a specific project/run.""" + return SQLiteStorage._get_metric_names( + project, run, "metrics", exclude_keys={"timestamp", "step"} + ) + + @staticmethod + def _get_metric_names( + project: str, run: str, table: str, exclude_keys: set[str] + ) -> list[str]: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return [] + + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute( + f""" + SELECT metrics + FROM {table} + WHERE run_name = ? + ORDER BY timestamp + """, + (run,), + ) + + rows = cursor.fetchall() + all_metrics = set() + for row in rows: + metrics = orjson.loads(row["metrics"]) + metrics = deserialize_values(metrics) + for key in metrics.keys(): + if key not in exclude_keys: + all_metrics.add(key) + return sorted(list(all_metrics)) + except sqlite3.OperationalError as e: + if f"no such table: {table}" in str(e): + return [] + raise + + @staticmethod + def set_project_metadata(project: str, key: str, value: str) -> None: + db_path = SQLiteStorage.init_db(project) + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + conn.execute( + "INSERT OR REPLACE INTO project_metadata (key, value) VALUES (?, ?)", + (key, value), + ) + conn.commit() + + @staticmethod + def get_project_metadata(project: str, key: str) -> str | None: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return None + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute( + "SELECT value FROM project_metadata WHERE key = ?", (key,) + ) + row = cursor.fetchone() + return row[0] if row else None + except sqlite3.OperationalError: + return None + + @staticmethod + def get_space_id(project: str) -> str | None: + return SQLiteStorage.get_project_metadata(project, "space_id") + + @staticmethod + def has_pending_data(project: str) -> bool: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return False + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute( + "SELECT EXISTS(SELECT 1 FROM metrics WHERE space_id IS NOT NULL LIMIT 1)" + ) + if cursor.fetchone()[0]: + return True + except sqlite3.OperationalError: + pass + try: + cursor.execute( + "SELECT EXISTS(SELECT 1 FROM system_metrics WHERE space_id IS NOT NULL LIMIT 1)" + ) + if cursor.fetchone()[0]: + return True + except sqlite3.OperationalError: + pass + try: + cursor.execute("SELECT EXISTS(SELECT 1 FROM pending_uploads LIMIT 1)") + if cursor.fetchone()[0]: + return True + except sqlite3.OperationalError: + pass + return False + + @staticmethod + def get_pending_logs(project: str) -> dict | None: + return SQLiteStorage._get_pending( + project, "metrics", extra_fields=["step"], include_config=True + ) + + @staticmethod + def clear_pending_logs(project: str, metric_ids: list[int]) -> None: + SQLiteStorage._clear_pending(project, "metrics", metric_ids) + + @staticmethod + def get_pending_system_logs(project: str) -> dict | None: + return SQLiteStorage._get_pending(project, "system_metrics") + + @staticmethod + def _get_pending( + project: str, + table: str, + extra_fields: list[str] | None = None, + include_config: bool = False, + ) -> dict | None: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return None + extra_cols = ", ".join(extra_fields) + ", " if extra_fields else "" + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute( + f"""SELECT id, timestamp, run_name, {extra_cols}metrics, log_id, space_id + FROM {table} WHERE space_id IS NOT NULL""" + ) + except sqlite3.OperationalError: + return None + rows = cursor.fetchall() + if not rows: + return None + logs = [] + ids = [] + for row in rows: + metrics = deserialize_values(orjson.loads(row["metrics"])) + entry = { + "project": project, + "run": row["run_name"], + "metrics": metrics, + "timestamp": row["timestamp"], + "log_id": row["log_id"], + } + for field in extra_fields or []: + entry[field] = row[field] + if include_config: + entry["config"] = None + logs.append(entry) + ids.append(row["id"]) + return {"logs": logs, "ids": ids, "space_id": rows[0]["space_id"]} + + @staticmethod + def clear_pending_system_logs(project: str, metric_ids: list[int]) -> None: + SQLiteStorage._clear_pending(project, "system_metrics", metric_ids) + + @staticmethod + def _clear_pending(project: str, table: str, ids: list[int]) -> None: + if not ids: + return + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + placeholders = ",".join("?" * len(ids)) + conn.execute( + f"UPDATE {table} SET space_id = NULL WHERE id IN ({placeholders})", + ids, + ) + conn.commit() + + @staticmethod + def get_pending_uploads(project: str) -> dict | None: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return None + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute( + """SELECT id, space_id, run_name, step, file_path, relative_path + FROM pending_uploads""" + ) + except sqlite3.OperationalError: + return None + rows = cursor.fetchall() + if not rows: + return None + uploads = [] + ids = [] + for row in rows: + uploads.append( + { + "project": project, + "run": row["run_name"], + "step": row["step"], + "file_path": row["file_path"], + "relative_path": row["relative_path"], + } + ) + ids.append(row["id"]) + return {"uploads": uploads, "ids": ids, "space_id": rows[0]["space_id"]} + + @staticmethod + def clear_pending_uploads(project: str, upload_ids: list[int]) -> None: + if not upload_ids: + return + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + placeholders = ",".join("?" * len(upload_ids)) + conn.execute( + f"DELETE FROM pending_uploads WHERE id IN ({placeholders})", + upload_ids, + ) + conn.commit() + + @staticmethod + def add_pending_upload( + project: str, + space_id: str, + run_name: str | None, + step: int | None, + file_path: str, + relative_path: str | None, + ) -> None: + db_path = SQLiteStorage.init_db(project) + with SQLiteStorage._get_process_lock(project): + with SQLiteStorage._get_connection(db_path) as conn: + conn.execute( + """INSERT INTO pending_uploads + (space_id, run_name, step, file_path, relative_path, created_at) + VALUES (?, ?, ?, ?, ?, ?)""", + ( + space_id, + run_name, + step, + file_path, + relative_path, + datetime.now(timezone.utc).isoformat(), + ), + ) + conn.commit() + + @staticmethod + def get_all_logs_for_sync(project: str) -> list[dict]: + return SQLiteStorage._get_all_for_sync( + project, + "metrics", + order_by="run_name, step", + extra_fields=["step"], + include_config=True, + ) + + @staticmethod + def get_all_system_logs_for_sync(project: str) -> list[dict]: + return SQLiteStorage._get_all_for_sync( + project, "system_metrics", order_by="run_name, timestamp" + ) + + @staticmethod + def _get_all_for_sync( + project: str, + table: str, + order_by: str, + extra_fields: list[str] | None = None, + include_config: bool = False, + ) -> list[dict]: + db_path = SQLiteStorage.get_project_db_path(project) + if not db_path.exists(): + return [] + extra_cols = ", ".join(extra_fields) + ", " if extra_fields else "" + with SQLiteStorage._get_connection(db_path) as conn: + cursor = conn.cursor() + try: + cursor.execute( + f"""SELECT timestamp, run_name, {extra_cols}metrics, log_id + FROM {table} ORDER BY {order_by}""" + ) + except sqlite3.OperationalError: + return [] + rows = cursor.fetchall() + results = [] + for row in rows: + metrics = deserialize_values(orjson.loads(row["metrics"])) + entry = { + "project": project, + "run": row["run_name"], + "metrics": metrics, + "timestamp": row["timestamp"], + "log_id": row["log_id"], + } + for field in extra_fields or []: + entry[field] = row[field] + if include_config: + entry["config"] = None + results.append(entry) + return results diff --git a/trackio/table.py b/trackio/table.py new file mode 100644 index 0000000000000000000000000000000000000000..272b0eb4c103a1efd87cf1a951db0e1a4b5eaaec --- /dev/null +++ b/trackio/table.py @@ -0,0 +1,173 @@ +import os +from typing import Any, Literal + +from pandas import DataFrame + +from trackio.media.media import TrackioMedia +from trackio.utils import MEDIA_DIR + + +class Table: + """ + Initializes a Table object. + + Tables can be used to log tabular data including images, numbers, and text. + + Args: + columns (`list[str]`, *optional*): + Names of the columns in the table. Optional if `data` is provided. Not + expected if `dataframe` is provided. Currently ignored. + data (`list[list[Any]]`, *optional*): + 2D row-oriented array of values. Each value can be a number, a string + (treated as Markdown and truncated if too long), or a `Trackio.Image` or + list of `Trackio.Image` objects. + dataframe (`pandas.DataFrame`, *optional*): + DataFrame used to create the table. When set, `data` and `columns` + arguments are ignored. + rows (`list[list[Any]]`, *optional*): + Currently ignored. + optional (`bool` or `list[bool]`, *optional*, defaults to `True`): + Currently ignored. + allow_mixed_types (`bool`, *optional*, defaults to `False`): + Currently ignored. + log_mode: (`Literal["IMMUTABLE", "MUTABLE", "INCREMENTAL"]` or `None`, *optional*, defaults to `"IMMUTABLE"`): + Currently ignored. + """ + + TYPE = "trackio.table" + + def __init__( + self, + columns: list[str] | None = None, + data: list[list[Any]] | None = None, + dataframe: DataFrame | None = None, + rows: list[list[Any]] | None = None, + optional: bool | list[bool] = True, + allow_mixed_types: bool = False, + log_mode: Literal["IMMUTABLE", "MUTABLE", "INCREMENTAL"] | None = "IMMUTABLE", + ): + # TODO: implement support for columns, dtype, optional, allow_mixed_types, and log_mode. + # for now (like `rows`) they are included for API compat but don't do anything. + if dataframe is None: + self.data = DataFrame(data) if data is not None else DataFrame() + else: + self.data = dataframe + + def _has_media_objects(self, dataframe: DataFrame) -> bool: + """Check if dataframe contains any TrackioMedia objects or lists of TrackioMedia objects.""" + for col in dataframe.columns: + if dataframe[col].apply(lambda x: isinstance(x, TrackioMedia)).any(): + return True + if ( + dataframe[col] + .apply( + lambda x: ( + isinstance(x, list) + and len(x) > 0 + and isinstance(x[0], TrackioMedia) + ) + ) + .any() + ): + return True + return False + + def _process_data(self, project: str, run: str, step: int = 0): + """Convert dataframe to dict format, processing any TrackioMedia objects if present.""" + df = self.data + if not self._has_media_objects(df): + return df.to_dict(orient="records") + + processed_df = df.copy() + for col in processed_df.columns: + for idx in processed_df.index: + value = processed_df.at[idx, col] + if isinstance(value, TrackioMedia): + value._save(project, run, step) + processed_df.at[idx, col] = value._to_dict() + if ( + isinstance(value, list) + and len(value) > 0 + and isinstance(value[0], TrackioMedia) + ): + [v._save(project, run, step) for v in value] + processed_df.at[idx, col] = [v._to_dict() for v in value] + + return processed_df.to_dict(orient="records") + + @staticmethod + def to_display_format(table_data: list[dict]) -> list[dict]: + """ + Converts stored table data to display format for UI rendering. + + Note: + This does not use the `self.data` attribute, but instead uses the + `table_data` parameter, which is what the UI receives. + + Args: + table_data (`list[dict]`): + List of dictionaries representing table rows (from stored `_value`). + + Returns: + `list[dict]`: Table data with images converted to markdown syntax and long + text truncated. + """ + truncate_length = int(os.getenv("TRACKIO_TABLE_TRUNCATE_LENGTH", "250")) + + def convert_image_to_markdown(image_data: dict) -> str: + relative_path = image_data.get("file_path", "") + caption = image_data.get("caption", "") + absolute_path = MEDIA_DIR / relative_path + return f'{caption}' + + processed_data = [] + for row in table_data: + processed_row = {} + for key, value in row.items(): + if isinstance(value, dict) and value.get("_type") == "trackio.image": + processed_row[key] = convert_image_to_markdown(value) + elif ( + isinstance(value, list) + and len(value) > 0 + and isinstance(value[0], dict) + and value[0].get("_type") == "trackio.image" + ): + # This assumes that if the first item is an image, all items are images. Ok for now since we don't support mixed types in a single cell. + processed_row[key] = ( + '
        ' + + "".join([convert_image_to_markdown(item) for item in value]) + + "
        " + ) + elif isinstance(value, str) and len(value) > truncate_length: + truncated = value[:truncate_length] + full_text = value.replace("<", "<").replace(">", ">") + processed_row[key] = ( + f'
        ' + f'{truncated}…(truncated, click to expand)' + f'
        ' + f'
        {full_text}
        ' + f"
        " + f"
        " + ) + else: + processed_row[key] = value + processed_data.append(processed_row) + return processed_data + + def _to_dict(self, project: str, run: str, step: int = 0): + """ + Converts the table to a dictionary representation. + + Args: + project (`str`): + Project name for saving media files. + run (`str`): + Run name for saving media files. + step (`int`, *optional*, defaults to `0`): + Step number for saving media files. + """ + data = self._process_data(project, run, step) + return { + "_type": self.TYPE, + "_value": data, + } diff --git a/trackio/typehints.py b/trackio/typehints.py new file mode 100644 index 0000000000000000000000000000000000000000..274fb1d25831672e92c59d24ed86ffb31d862220 --- /dev/null +++ b/trackio/typehints.py @@ -0,0 +1,39 @@ +from typing import Any, TypedDict + +from gradio_client import FileData + + +class LogEntry(TypedDict, total=False): + project: str + run: str + metrics: dict[str, Any] + step: int | None + config: dict[str, Any] | None + log_id: str | None + + +class SystemLogEntry(TypedDict, total=False): + project: str + run: str + metrics: dict[str, Any] + timestamp: str + log_id: str | None + + +class AlertEntry(TypedDict, total=False): + project: str + run: str + title: str + text: str | None + level: str + step: int | None + timestamp: str + alert_id: str | None + + +class UploadEntry(TypedDict): + project: str + run: str | None + step: int | None + relative_path: str | None + uploaded_file: FileData diff --git a/trackio/utils.py b/trackio/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..e92a85a8dc817a6742b808033600dcaedea7d6df --- /dev/null +++ b/trackio/utils.py @@ -0,0 +1,927 @@ +import math +import os +import re +import secrets +import time +import warnings +from datetime import datetime, timezone +from pathlib import Path +from typing import TYPE_CHECKING +from urllib.parse import urlencode + +import huggingface_hub +import numpy as np +import pandas as pd +from huggingface_hub.constants import HF_HOME + +if TYPE_CHECKING: + from trackio.commit_scheduler import CommitScheduler + from trackio.dummy_commit_scheduler import DummyCommitScheduler + +RESERVED_KEYS = ["project", "run", "timestamp", "step", "time", "metrics"] + +TRACKIO_LOGO_DIR = Path(__file__).parent / "assets" + + +def get_logo_urls() -> dict[str, str]: + """Get logo URLs from environment variables or use defaults.""" + light_url = os.environ.get( + "TRACKIO_LOGO_LIGHT_URL", + f"/gradio_api/file={TRACKIO_LOGO_DIR}/trackio_logo_type_light_transparent.png", + ) + dark_url = os.environ.get( + "TRACKIO_LOGO_DARK_URL", + f"/gradio_api/file={TRACKIO_LOGO_DIR}/trackio_logo_type_dark_transparent.png", + ) + return {"light": light_url, "dark": dark_url} + + +def order_metrics_by_plot_preference(metrics: list[str]) -> tuple[list[str], dict]: + """ + Order metrics based on TRACKIO_PLOT_ORDER environment variable and group them. + + Args: + metrics: List of metric names to order and group + + Returns: + Tuple of (ordered_group_names, grouped_metrics_dict) + """ + plot_order_env = os.environ.get("TRACKIO_PLOT_ORDER", "") + if not plot_order_env.strip(): + plot_order = [] + else: + plot_order = [ + item.strip() for item in plot_order_env.split(",") if item.strip() + ] + + def get_metric_priority(metric: str) -> tuple[int, int, str]: + if not plot_order: + return (float("inf"), float("inf"), metric) + + group_prefix = metric.split("/")[0] if "/" in metric else "charts" + no_match_priority = len(plot_order) + + group_priority = no_match_priority + for i, pattern in enumerate(plot_order): + pattern_group = pattern.split("/")[0] if "/" in pattern else "charts" + if pattern_group == group_prefix: + group_priority = i + break + + within_group_priority = no_match_priority + for i, pattern in enumerate(plot_order): + if pattern == metric: + within_group_priority = i + break + elif pattern.endswith("/*") and within_group_priority == no_match_priority: + pattern_prefix = pattern[:-2] + if metric.startswith(pattern_prefix + "/"): + within_group_priority = i + len(plot_order) + + return (group_priority, within_group_priority, metric) + + result = {} + for metric in metrics: + if "/" not in metric: + if "charts" not in result: + result["charts"] = {"direct_metrics": [], "subgroups": {}} + result["charts"]["direct_metrics"].append(metric) + else: + parts = metric.split("/") + main_prefix = parts[0] + if main_prefix not in result: + result[main_prefix] = {"direct_metrics": [], "subgroups": {}} + if len(parts) == 2: + result[main_prefix]["direct_metrics"].append(metric) + else: + subprefix = parts[1] + if subprefix not in result[main_prefix]["subgroups"]: + result[main_prefix]["subgroups"][subprefix] = [] + result[main_prefix]["subgroups"][subprefix].append(metric) + + for group_data in result.values(): + group_data["direct_metrics"].sort(key=get_metric_priority) + for subgroup_name in group_data["subgroups"]: + group_data["subgroups"][subgroup_name].sort(key=get_metric_priority) + + if "charts" in result and not result["charts"]["direct_metrics"]: + del result["charts"] + + def get_group_priority(group_name: str) -> tuple[int, str]: + if not plot_order: + return (float("inf"), group_name) + + min_priority = len(plot_order) + for i, pattern in enumerate(plot_order): + pattern_group = pattern.split("/")[0] if "/" in pattern else "charts" + if pattern_group == group_name: + min_priority = min(min_priority, i) + return (min_priority, group_name) + + ordered_groups = sorted(result.keys(), key=get_group_priority) + + return ordered_groups, result + + +def persistent_storage_enabled() -> bool: + return ( + os.environ.get("PERSISTANT_STORAGE_ENABLED") == "true" + ) # typo in the name of the environment variable + + +def _get_trackio_dir() -> Path: + if persistent_storage_enabled(): + return Path("/data/trackio") + if os.environ.get("TRACKIO_DIR"): + return Path(os.environ.get("TRACKIO_DIR")) + return Path(HF_HOME) / "trackio" + + +TRACKIO_DIR = _get_trackio_dir() +MEDIA_DIR = TRACKIO_DIR / "media" + + +def get_or_create_project_hash(project: str) -> str: + hash_path = TRACKIO_DIR / f"{project}.hash" + if hash_path.exists(): + return hash_path.read_text().strip() + hash_value = secrets.token_urlsafe(8) + TRACKIO_DIR.mkdir(parents=True, exist_ok=True) + hash_path.write_text(hash_value) + return hash_value + + +def generate_readable_name(used_names: list[str], space_id: str | None = None) -> str: + """ + Generates a random, readable name like "dainty-sunset-0". + If space_id is provided, generates username-timestamp format instead. + """ + if space_id is not None: + username = _get_default_namespace() + timestamp = int(time.time()) + return f"{username}-{timestamp}" + adjectives = [ + "dainty", + "brave", + "calm", + "eager", + "fancy", + "gentle", + "happy", + "jolly", + "kind", + "lively", + "merry", + "nice", + "proud", + "quick", + "hugging", + "silly", + "tidy", + "witty", + "zealous", + "bright", + "shy", + "bold", + "clever", + "daring", + "elegant", + "faithful", + "graceful", + "honest", + "inventive", + "jovial", + "keen", + "lucky", + "modest", + "noble", + "optimistic", + "patient", + "quirky", + "resourceful", + "sincere", + "thoughtful", + "upbeat", + "valiant", + "warm", + "youthful", + "zesty", + "adventurous", + "breezy", + "cheerful", + "delightful", + "energetic", + "fearless", + "glad", + "hopeful", + "imaginative", + "joyful", + "kindly", + "luminous", + "mysterious", + "neat", + "outgoing", + "playful", + "radiant", + "spirited", + "tranquil", + "unique", + "vivid", + "wise", + "zany", + "artful", + "bubbly", + "charming", + "dazzling", + "earnest", + "festive", + "gentlemanly", + "hearty", + "intrepid", + "jubilant", + "knightly", + "lively", + "magnetic", + "nimble", + "orderly", + "peaceful", + "quick-witted", + "robust", + "sturdy", + "trusty", + "upstanding", + "vibrant", + "whimsical", + ] + nouns = [ + "sunset", + "forest", + "river", + "mountain", + "breeze", + "meadow", + "ocean", + "valley", + "sky", + "field", + "cloud", + "star", + "rain", + "leaf", + "stone", + "flower", + "bird", + "tree", + "wave", + "trail", + "island", + "desert", + "hill", + "lake", + "pond", + "grove", + "canyon", + "reef", + "bay", + "peak", + "glade", + "marsh", + "cliff", + "dune", + "spring", + "brook", + "cave", + "plain", + "ridge", + "wood", + "blossom", + "petal", + "root", + "branch", + "seed", + "acorn", + "pine", + "willow", + "cedar", + "elm", + "falcon", + "eagle", + "sparrow", + "robin", + "owl", + "finch", + "heron", + "crane", + "duck", + "swan", + "fox", + "wolf", + "bear", + "deer", + "moose", + "otter", + "beaver", + "lynx", + "hare", + "badger", + "butterfly", + "bee", + "ant", + "beetle", + "dragonfly", + "firefly", + "ladybug", + "moth", + "spider", + "worm", + "coral", + "kelp", + "shell", + "pebble", + "face", + "boulder", + "cobble", + "sand", + "wavelet", + "tide", + "current", + "mist", + ] + number = 0 + name = f"{adjectives[0]}-{nouns[0]}-{number}" + while name in used_names: + number += 1 + adjective = adjectives[number % len(adjectives)] + noun = nouns[number % len(nouns)] + name = f"{adjective}-{noun}-{number}" + return name + + +def is_in_notebook(): + """ + Detect if code is running in a notebook environment (Jupyter, Colab, etc.). + """ + try: + from IPython import get_ipython + + if get_ipython() is not None: + return get_ipython().__class__.__name__ in [ + "ZMQInteractiveShell", # Jupyter notebook/lab + "Shell", # IPython terminal + ] or "google.colab" in str(get_ipython()) + except ImportError: + pass + return False + + +def block_main_thread_until_keyboard_interrupt(): + try: + while True: + time.sleep(0.1) + except (KeyboardInterrupt, OSError): + print("Keyboard interruption in main thread... closing dashboard.") + + +def simplify_column_names(columns: list[str]) -> dict[str, str]: + """ + Simplifies column names to first 10 alphanumeric or "/" characters with unique suffixes. + + Args: + columns: List of original column names + + Returns: + Dictionary mapping original column names to simplified names + """ + simplified_names = {} + used_names = set() + + for col in columns: + alphanumeric = re.sub(r"[^a-zA-Z0-9/]", "", col) + base_name = alphanumeric[:10] if alphanumeric else f"col_{len(used_names)}" + + final_name = base_name + suffix = 1 + while final_name in used_names: + final_name = f"{base_name}_{suffix}" + suffix += 1 + + simplified_names[col] = final_name + used_names.add(final_name) + + return simplified_names + + +def print_dashboard_instructions(project: str) -> None: + """ + Prints instructions for viewing the Trackio dashboard. + + Args: + project: The name of the project to show dashboard for. + """ + ORANGE = "\033[38;5;208m" + BOLD = "\033[1m" + RESET = "\033[0m" + + print("* View dashboard by running in your terminal:") + print(f'{BOLD}{ORANGE}trackio show --project "{project}"{RESET}') + print(f'* or by running in Python: trackio.show(project="{project}")') + + +def preprocess_space_and_dataset_ids( + space_id: str | None, + dataset_id: str | None, + bucket_id: str | None = None, +) -> tuple[str | None, str | None, str | None]: + """ + Preprocesses the Space and Bucket names to ensure they are valid + "username/name" format. When space_id is provided and bucket_id is not + explicitly set, auto-generates a bucket_id. + """ + if space_id is not None and "/" not in space_id: + username = _get_default_namespace() + space_id = f"{username}/{space_id}" + if dataset_id is not None: + warnings.warn( + "`dataset_id` is deprecated. Use `bucket_id` instead.", + DeprecationWarning, + stacklevel=3, + ) + if dataset_id is not None and "/" not in dataset_id: + username = _get_default_namespace() + dataset_id = f"{username}/{dataset_id}" + if bucket_id is not None and "/" not in bucket_id: + username = _get_default_namespace() + bucket_id = f"{username}/{bucket_id}" + if space_id is not None and dataset_id is None and bucket_id is None: + bucket_id = f"{space_id}-bucket" + return space_id, dataset_id, bucket_id + + +def fibo(): + """Generator for Fibonacci backoff: 1, 1, 2, 3, 5, 8, ...""" + a, b = 1, 1 + while True: + yield a + a, b = b, a + b + + +def format_timestamp(timestamp_str): + """Convert ISO timestamp to human-readable format like '3 minutes ago'.""" + if not timestamp_str or pd.isna(timestamp_str): + return "Unknown" + + try: + created_time = datetime.fromisoformat(timestamp_str.replace("Z", "+00:00")) + if created_time.tzinfo is None: + created_time = created_time.replace(tzinfo=timezone.utc) + + now = datetime.now(timezone.utc) + diff = now - created_time + + seconds = int(diff.total_seconds()) + if seconds < 60: + return "Just now" + elif seconds < 3600: + minutes = seconds // 60 + return f"{minutes} minute{'s' if minutes != 1 else ''} ago" + elif seconds < 86400: + hours = seconds // 3600 + return f"{hours} hour{'s' if hours != 1 else ''} ago" + else: + days = seconds // 86400 + return f"{days} day{'s' if days != 1 else ''} ago" + except Exception: + return "Unknown" + + +DEFAULT_COLOR_PALETTE = [ + "#A8769B", + "#E89957", + "#3B82F6", + "#10B981", + "#EF4444", + "#8B5CF6", + "#14B8A6", + "#F59E0B", + "#EC4899", + "#06B6D4", +] + + +def get_color_palette() -> list[str]: + """Get the color palette from environment variable or use default.""" + env_palette = os.environ.get("TRACKIO_COLOR_PALETTE") + if env_palette: + return [color.strip() for color in env_palette.split(",")] + return DEFAULT_COLOR_PALETTE + + +def get_color_mapping( + runs: list[str], smoothing: bool, color_palette: list[str] | None = None +) -> dict[str, str]: + """Generate color mapping for runs, with transparency for original data when smoothing is enabled.""" + if color_palette is None: + color_palette = get_color_palette() + + color_map = {} + + for i, run in enumerate(runs): + base_color = color_palette[i % len(color_palette)] + + if smoothing: + color_map[run] = base_color + "4D" + color_map[f"{run}_smoothed"] = base_color + else: + color_map[run] = base_color + + return color_map + + +def downsample( + df: pd.DataFrame, + x: str, + y: str, + color: str | None, + x_lim: tuple[float | None, float | None] | None = None, +) -> tuple[pd.DataFrame, tuple[float, float] | None]: + """ + Downsample the dataframe to reduce the number of points plotted. + Also updates the x-axis limits to the data min/max if either of the x-axis limits are None. + + Args: + df: The dataframe to downsample. + x: The column name to use for the x-axis. + y: The column name to use for the y-axis. + color: The column name to use for the color. + x_lim: The x-axis limits to use. + + Returns: + A tuple containing the downsampled dataframe and the updated x-axis limits. + """ + if df.empty: + if x_lim is not None: + x_lim = (x_lim[0] or 0, x_lim[1] or 0) + return df, x_lim + + columns_to_keep = [x, y] + if color is not None and color in df.columns: + columns_to_keep.append(color) + df = df[columns_to_keep].copy() + + data_x_min = df[x].min() + data_x_max = df[x].max() + + if x_lim is not None: + x_min, x_max = x_lim + if x_min is None: + x_min = data_x_min + if x_max is None: + x_max = data_x_max + updated_x_lim = (x_min, x_max) + else: + updated_x_lim = None + + n_bins = 100 + + if color is not None and color in df.columns: + groups = df.groupby(color) + else: + groups = [(None, df)] + + downsampled_indices = [] + + for _, group_df in groups: + if group_df.empty: + continue + + group_df = group_df.sort_values(x) + + if updated_x_lim is not None: + x_min, x_max = updated_x_lim + before_point = group_df[group_df[x] < x_min].tail(1) + after_point = group_df[group_df[x] > x_max].head(1) + group_df = group_df[(group_df[x] >= x_min) & (group_df[x] <= x_max)] + else: + before_point = after_point = None + x_min = group_df[x].min() + x_max = group_df[x].max() + + if before_point is not None and not before_point.empty: + downsampled_indices.extend(before_point.index.tolist()) + if after_point is not None and not after_point.empty: + downsampled_indices.extend(after_point.index.tolist()) + + if group_df.empty: + continue + + if x_min == x_max: + min_y_idx = group_df[y].idxmin() + max_y_idx = group_df[y].idxmax() + if min_y_idx != max_y_idx: + downsampled_indices.extend([min_y_idx, max_y_idx]) + else: + downsampled_indices.append(min_y_idx) + continue + + if len(group_df) < 500: + downsampled_indices.extend(group_df.index.tolist()) + continue + + bins = np.linspace(x_min, x_max, n_bins + 1) + group_df["bin"] = pd.cut( + group_df[x], bins=bins, labels=False, include_lowest=True + ) + + for bin_idx in group_df["bin"].dropna().unique(): + bin_data = group_df[group_df["bin"] == bin_idx] + if bin_data.empty: + continue + + min_y_idx = bin_data[y].idxmin() + max_y_idx = bin_data[y].idxmax() + + downsampled_indices.append(min_y_idx) + if min_y_idx != max_y_idx: + downsampled_indices.append(max_y_idx) + + unique_indices = list(set(downsampled_indices)) + + downsampled_df = df.loc[unique_indices].copy() + + if color is not None: + downsampled_df = ( + downsampled_df.groupby(color, sort=False)[downsampled_df.columns] + .apply(lambda group: group.sort_values(x)) + .reset_index(drop=True) + ) + else: + downsampled_df = downsampled_df.sort_values(x).reset_index(drop=True) + + downsampled_df = downsampled_df.drop(columns=["bin"], errors="ignore") + + return downsampled_df, updated_x_lim + + +def sort_metrics_by_prefix(metrics: list[str]) -> list[str]: + """ + Sort metrics by grouping prefixes together for dropdown/list display. + Metrics without prefixes come first, then grouped by prefix. + + Args: + metrics: List of metric names + + Returns: + List of metric names sorted by prefix + + Example: + Input: ["train/loss", "loss", "train/acc", "val/loss"] + Output: ["loss", "train/acc", "train/loss", "val/loss"] + """ + groups = group_metrics_by_prefix(metrics) + result = [] + + if "charts" in groups: + result.extend(groups["charts"]) + + for group_name in sorted(groups.keys()): + if group_name != "charts": + result.extend(groups[group_name]) + + return result + + +def group_metrics_by_prefix(metrics: list[str]) -> dict[str, list[str]]: + """ + Group metrics by their prefix. Metrics without prefix go to 'charts' group. + + Args: + metrics: List of metric names + + Returns: + Dictionary with prefix names as keys and lists of metrics as values + + Example: + Input: ["loss", "accuracy", "train/loss", "train/acc", "val/loss"] + Output: { + "charts": ["loss", "accuracy"], + "train": ["train/loss", "train/acc"], + "val": ["val/loss"] + } + """ + no_prefix = [] + with_prefix = [] + + for metric in metrics: + if "/" in metric: + with_prefix.append(metric) + else: + no_prefix.append(metric) + + no_prefix.sort() + + prefix_groups = {} + for metric in with_prefix: + prefix = metric.split("/")[0] + if prefix not in prefix_groups: + prefix_groups[prefix] = [] + prefix_groups[prefix].append(metric) + + for prefix in prefix_groups: + prefix_groups[prefix].sort() + + groups = {} + if no_prefix: + groups["charts"] = no_prefix + + for prefix in sorted(prefix_groups.keys()): + groups[prefix] = prefix_groups[prefix] + + return groups + + +def get_sync_status(scheduler: "CommitScheduler | DummyCommitScheduler") -> int | None: + """Get the sync status from the CommitScheduler in an integer number of minutes, or None if not synced yet.""" + if getattr( + scheduler, "last_push_time", None + ): # DummyCommitScheduler doesn't have last_push_time + time_diff = time.time() - scheduler.last_push_time + return int(time_diff / 60) + else: + return None + + +def generate_share_url( + project: str, + metrics: str, + selected_runs: list = None, + hide_headers: bool = False, +) -> str: + """Generate the shareable Space URL based on current settings.""" + space_host = os.environ.get("SPACE_HOST", "") + if not space_host: + return "" + + params: dict[str, str] = {} + + if project: + params["project"] = project + + if metrics and metrics.strip(): + params["metrics"] = metrics + + if selected_runs: + params["runs"] = ",".join(selected_runs) + + if hide_headers: + params["accordion"] = "hidden" + params["sidebar"] = "hidden" + params["navbar"] = "hidden" + + query_string = urlencode(params) + return f"https://{space_host}?{query_string}" + + +def generate_embed_code( + project: str, + metrics: str, + selected_runs: list = None, + hide_headers: bool = False, +) -> str: + """Generate the embed iframe code based on current settings.""" + embed_url = generate_share_url(project, metrics, selected_runs, hide_headers) + if not embed_url: + return "" + + return f'' + + +def serialize_values(metrics): + """ + Serialize infinity and NaN values in metrics dict to make it JSON-compliant. + Only handles top-level float values. + + Converts: + - float('inf') -> "Infinity" + - float('-inf') -> "-Infinity" + - float('nan') -> "NaN" + + Example: + {"loss": float('inf'), "accuracy": 0.95} -> {"loss": "Infinity", "accuracy": 0.95} + """ + if not isinstance(metrics, dict): + return metrics + + result = {} + for key, value in metrics.items(): + if isinstance(value, float): + if math.isinf(value): + result[key] = "Infinity" if value > 0 else "-Infinity" + elif math.isnan(value): + result[key] = "NaN" + else: + result[key] = value + elif isinstance(value, np.floating): + float_val = float(value) + if math.isinf(float_val): + result[key] = "Infinity" if float_val > 0 else "-Infinity" + elif math.isnan(float_val): + result[key] = "NaN" + else: + result[key] = float_val + else: + result[key] = value + return result + + +def deserialize_values(metrics): + """ + Deserialize infinity and NaN string values back to their numeric forms. + Only handles top-level string values. + + Converts: + - "Infinity" -> float('inf') + - "-Infinity" -> float('-inf') + - "NaN" -> float('nan') + + Example: + {"loss": "Infinity", "accuracy": 0.95} -> {"loss": float('inf'), "accuracy": 0.95} + """ + if not isinstance(metrics, dict): + return metrics + + result = {} + for key, value in metrics.items(): + if value == "Infinity": + result[key] = float("inf") + elif value == "-Infinity": + result[key] = float("-inf") + elif value == "NaN": + result[key] = float("nan") + else: + result[key] = value + return result + + +def get_full_url( + base_url: str, project: str | None, write_token: str, footer: bool = True +) -> str: + params = [] + if project: + params.append(f"project={project}") + params.append(f"write_token={write_token}") + if not footer: + params.append("footer=false") + return base_url + "?" + "&".join(params) + + +def embed_url_in_notebook(url: str) -> None: + try: + from IPython.display import HTML, display + + embed_code = HTML( + f'
        ' + ) + display(embed_code) + except ImportError: + pass + + +def to_json_safe(obj): + if isinstance(obj, (str, int, float, bool, type(None))): + return obj + if isinstance(obj, np.generic): + return obj.item() + if isinstance(obj, dict): + return {str(k): to_json_safe(v) for k, v in obj.items()} + if isinstance(obj, (list, tuple, set)): + return [to_json_safe(v) for v in obj] + if hasattr(obj, "to_dict") and callable(obj.to_dict): + return to_json_safe(obj.to_dict()) + if hasattr(obj, "__dict__"): + return { + str(k): to_json_safe(v) + for k, v in vars(obj).items() + if not k.startswith("_") + } + return str(obj) + + +def get_space() -> str | None: + """ + Get the space ID ("user/space") if Trackio is running in a Space, or None if not. + """ + return os.environ.get("SPACE_ID") + + +def ordered_subset(items: list[str], subset: list[str] | None) -> list[str]: + subset_set = set(subset or []) + return [item for item in items if item in subset_set] + + +def _get_default_namespace() -> str: + """Get the default namespace (username). + + This function uses caching to avoid repeated API calls to /whoami-v2. + """ + token = huggingface_hub.get_token() + return huggingface_hub.whoami(token=token, cache=True)["name"]