diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 00000000..bc13bb50 --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 329586684616b8808802a9193d4ac9f2 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..9cf671e2 --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +lumen.holoviz.org diff --git a/PyodideServiceWorker.js b/PyodideServiceWorker.js new file mode 100644 index 00000000..c2bae45c --- /dev/null +++ b/PyodideServiceWorker.js @@ -0,0 +1,57 @@ +const appName = 'Lumen' +const appCacheName = 'Lumen-0.6.0'; + +const preCacheFiles = []; + +const cachePatterns = ['https://cdn.holoviz.org/panel/1.3.1/dist/', 'https://cdn.bokeh.org/bokeh/', 'https://cdn.jsdelivr.net/pyodide/', 'https://files.pythonhosted.org/packages/', 'https://pypi.org/pypi/']; + +self.addEventListener('install', (e) => { + console.log('[Service Worker] Install'); + self.skipWaiting(); + e.waitUntil((async () => { + const cacheNames = await caches.keys(); + for (const cacheName of cacheNames) { + if (cacheName.startsWith(appName) && cacheName !== appCacheName) { + console.log(`[Service Worker] Delete old cache ${cacheName}`); + caches.delete(cacheName); + } + } + const cache = await caches.open(appCacheName); + if (preCacheFiles.length) { + console.log('[Service Worker] Precaching '); + } + preCacheFiles.forEach(async (cacheFile) => { + const request = new Request(cacheFile); + const response = await fetch(request); + if (response.ok || response.type == 'opaque') { + cache.put(request, response); + } + }) + })()); +}); + +self.addEventListener('activate', (event) => { + console.log('[Service Worker] Activating'); + return self.clients.claim(); +}); + +self.addEventListener('fetch', (e) => { + if (e.request.method !== 'GET') { + return + } + e.respondWith((async () => { + const cache = await caches.open(appCacheName); + let response = await cache.match(e.request); + console.log(`[Service Worker] Fetching resource: ${e.request.url}`); + if (response) { + return response; + } + response = await fetch(e.request); + if (!response.ok && !(response.type == 'opaque')) { + throw Error(`[Service Worker] Fetching resource ${e.request.url} failed with response: ${response.status}`); + } + console.log(`[Service Worker] Caching new resource: ${e.request.url}`); + cache.put(e.request, response.clone()); + return response; + })()); +}); \ No newline at end of file diff --git a/_images/1.png b/_images/1.png new file mode 100644 index 00000000..8aaa4e31 Binary files /dev/null and b/_images/1.png differ diff --git a/_images/2.png b/_images/2.png new file mode 100644 index 00000000..fb569bb5 Binary files /dev/null and b/_images/2.png differ diff --git a/_images/3.png b/_images/3.png new file mode 100644 index 00000000..d9d2739a Binary files /dev/null and b/_images/3.png differ diff --git a/_images/bikes.png b/_images/bikes.png new file mode 100644 index 00000000..803908b2 Binary files /dev/null and b/_images/bikes.png differ diff --git a/_images/branch_yaml_00_firstTable.png b/_images/branch_yaml_00_firstTable.png new file mode 100644 index 00000000..645ef964 Binary files /dev/null and b/_images/branch_yaml_00_firstTable.png differ diff --git a/_images/branch_yaml_01_finalDashboard.png b/_images/branch_yaml_01_finalDashboard.png new file mode 100644 index 00000000..b5e6d27b Binary files /dev/null and b/_images/branch_yaml_01_finalDashboard.png differ diff --git a/_images/build_app_00.png b/_images/build_app_00.png new file mode 100644 index 00000000..bc1bf029 Binary files /dev/null and b/_images/build_app_00.png differ diff --git a/_images/build_app_01.png b/_images/build_app_01.png new file mode 100644 index 00000000..a9c9b6f1 Binary files /dev/null and b/_images/build_app_01.png differ diff --git a/_images/build_app_02.png b/_images/build_app_02.png new file mode 100644 index 00000000..8de25ed9 Binary files /dev/null and b/_images/build_app_02.png differ diff --git a/_images/build_app_03.png b/_images/build_app_03.png new file mode 100644 index 00000000..d4ceeaf2 Binary files /dev/null and b/_images/build_app_03.png differ diff --git a/_images/build_app_04.png b/_images/build_app_04.png new file mode 100644 index 00000000..ba2a9dc5 Binary files /dev/null and b/_images/build_app_04.png differ diff --git a/_images/build_app_05.png b/_images/build_app_05.png new file mode 100644 index 00000000..c6c7c2ef Binary files /dev/null and b/_images/build_app_05.png differ diff --git a/_images/build_app_06.png b/_images/build_app_06.png new file mode 100644 index 00000000..ad6facee Binary files /dev/null and b/_images/build_app_06.png differ diff --git a/_images/build_app_07.png b/_images/build_app_07.png new file mode 100644 index 00000000..45919eb3 Binary files /dev/null and b/_images/build_app_07.png differ diff --git a/_images/builder_dashboard.png b/_images/builder_dashboard.png new file mode 100644 index 00000000..8ff1be22 Binary files /dev/null and b/_images/builder_dashboard.png differ diff --git a/_images/cli_bad.png b/_images/cli_bad.png new file mode 100644 index 00000000..ad64abf0 Binary files /dev/null and b/_images/cli_bad.png differ diff --git a/_images/cli_good.png b/_images/cli_good.png new file mode 100644 index 00000000..23b4ab5e Binary files /dev/null and b/_images/cli_good.png differ diff --git a/_images/config_editor.png b/_images/config_editor.png new file mode 100644 index 00000000..8d730a6d Binary files /dev/null and b/_images/config_editor.png differ diff --git a/_images/dashboard_gallery.png b/_images/dashboard_gallery.png new file mode 100644 index 00000000..0f01baed Binary files /dev/null and b/_images/dashboard_gallery.png differ diff --git a/_images/earthquakes.png b/_images/earthquakes.png new file mode 100644 index 00000000..3096ab39 Binary files /dev/null and b/_images/earthquakes.png differ diff --git a/_images/launcher.png b/_images/launcher.png new file mode 100644 index 00000000..71ba0182 Binary files /dev/null and b/_images/launcher.png differ diff --git a/_images/layout_example.png b/_images/layout_example.png new file mode 100644 index 00000000..55916eb8 Binary files /dev/null and b/_images/layout_example.png differ diff --git a/_images/local_components_app.png b/_images/local_components_app.png new file mode 100644 index 00000000..d540c000 Binary files /dev/null and b/_images/local_components_app.png differ diff --git a/_images/lumen_dashboard.png b/_images/lumen_dashboard.png new file mode 100644 index 00000000..783dc218 Binary files /dev/null and b/_images/lumen_dashboard.png differ diff --git a/_images/nyc_taxi.png b/_images/nyc_taxi.png new file mode 100644 index 00000000..b0c97608 Binary files /dev/null and b/_images/nyc_taxi.png differ diff --git a/_images/penguins.png b/_images/penguins.png new file mode 100644 index 00000000..74c7870b Binary files /dev/null and b/_images/penguins.png differ diff --git a/_images/pipeline_diagram.png b/_images/pipeline_diagram.png new file mode 100644 index 00000000..87079e09 Binary files /dev/null and b/_images/pipeline_diagram.png differ diff --git a/_images/precip.png b/_images/precip.png new file mode 100644 index 00000000..b200d27e Binary files /dev/null and b/_images/precip.png differ diff --git a/_images/seattle.png b/_images/seattle.png new file mode 100644 index 00000000..ac13c3f4 Binary files /dev/null and b/_images/seattle.png differ diff --git a/_images/shell.png b/_images/shell.png new file mode 100644 index 00000000..c915017b Binary files /dev/null and b/_images/shell.png differ diff --git a/_images/source_editor.png b/_images/source_editor.png new file mode 100644 index 00000000..7f77a0c8 Binary files /dev/null and b/_images/source_editor.png differ diff --git a/_images/source_example.png b/_images/source_example.png new file mode 100644 index 00000000..e2dbaa8b Binary files /dev/null and b/_images/source_example.png differ diff --git a/_images/source_variable.png b/_images/source_variable.png new file mode 100644 index 00000000..df3dc5a4 Binary files /dev/null and b/_images/source_variable.png differ diff --git a/_images/variable_all.png b/_images/variable_all.png new file mode 100644 index 00000000..6b44c35b Binary files /dev/null and b/_images/variable_all.png differ diff --git a/_images/variable_editor.png b/_images/variable_editor.png new file mode 100644 index 00000000..e34c1481 Binary files /dev/null and b/_images/variable_editor.png differ diff --git a/_images/variable_selected.png b/_images/variable_selected.png new file mode 100644 index 00000000..cdee769f Binary files /dev/null and b/_images/variable_selected.png differ diff --git a/_images/view_editor.png b/_images/view_editor.png new file mode 100644 index 00000000..a39e5634 Binary files /dev/null and b/_images/view_editor.png differ diff --git a/_images/view_example.png b/_images/view_example.png new file mode 100644 index 00000000..98cf2d4c Binary files /dev/null and b/_images/view_example.png differ diff --git a/_images/windturbines.png b/_images/windturbines.png new file mode 100644 index 00000000..1f5e441b Binary files /dev/null and b/_images/windturbines.png differ diff --git a/_images/yaml_launcher.png b/_images/yaml_launcher.png new file mode 100644 index 00000000..34688093 Binary files /dev/null and b/_images/yaml_launcher.png differ diff --git a/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000..eb19f698 --- /dev/null +++ b/_sphinx_design_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/_sphinx_design_static/design-tabs.js b/_sphinx_design_static/design-tabs.js new file mode 100644 index 00000000..36b38cf0 --- /dev/null +++ b/_sphinx_design_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/_static/PyodideWebWorker.js b/_static/PyodideWebWorker.js new file mode 100644 index 00000000..e9eb1975 --- /dev/null +++ b/_static/PyodideWebWorker.js @@ -0,0 +1,218 @@ +importScripts("https://cdn.jsdelivr.net/pyodide/v0.23.1/full/pyodide.js"); + +const QUEUE = []; + +const REQUIRES = {} + +function sendPatch(patch, buffers, cell_id) { + self.postMessage({ + type: 'patch', + patch: patch, + buffers: buffers, + id: cell_id + }) +} + +function sendStdout(cell_id, stdout) { + self.postMessage({ + type: 'stdout', + content: stdout, + id: cell_id + }) +} +function sendStderr(cell_id, stderr) { + self.postMessage({ + type: 'stderr', + content: stderr, + id: cell_id + }) +} + +async function loadApplication(cell_id, path) { + console.log("Loading pyodide!"); + self.pyodide = await loadPyodide(); + self.pyodide.globals.set("sendPatch", sendPatch); + self.pyodide.globals.set("sendStdout", sendStdout); + self.pyodide.globals.set("sendStderr", sendStderr); + console.log("Loaded!"); + await self.pyodide.loadPackage("micropip"); + const packages = ['https://cdn.holoviz.org/panel/1.3.1/dist/wheels/bokeh-3.3.0-py3-none-any.whl', 'https://cdn.holoviz.org/panel/1.3.1/dist/wheels/panel-1.3.1-py3-none-any.whl', 'lumen==0.6.0', 'requests', 'pandas', 'pyodide-http', 'holoviews>=1.15.1']; + if (path != null) { + for (const key of Object.keys(REQUIRES)) { + if (path.replace('.html', '').endsWith(key.replace('.md', ''))) { + for (const req of REQUIRES[key]) { + packages.push(req) + } + } + } + } + + await self.pyodide.runPythonAsync("") + self.pyodide.runPython("import micropip") + for (const pkg of packages) { + self.postMessage({ + type: 'loading', + msg: `Loading ${pkg}`, + id: cell_id + }); + await self.pyodide.runPythonAsync(` + await micropip.install('${pkg}', keep_going=True); + `); + } + console.log("Packages loaded!"); +} + +const autodetect_deps_code = ` +import json +from panel.io.mime_render import find_imports +json.dumps(find_imports(msg.to_py()['code']))` + +const exec_code = ` +from functools import partial +from panel.io.pyodide import pyrender +from js import console + +msg = msg.to_py() +code = msg['code'] +stdout_cb = partial(sendStdout, msg['id']) +stderr_cb = partial(sendStderr, msg['id']) +target = f"output-{msg['id']}" +pyrender(code, stdout_cb, stderr_cb, target)` + +const onload_code = ` +msg = msg.to_py() +if msg['mime'] == 'application/bokeh': + from panel.io.pyodide import _link_docs_worker + from panel.io.state import state + doc = state.cache[f"output-{msg['id']}"] + _link_docs_worker(doc, sendPatch, msg['id'], 'js')` + +const patch_code = ` +import json +from panel import state + +msg = msg.to_py() +doc = state.cache[f"output-{msg['id']}"] +doc.apply_json_patch(msg['patch'], setter='js')` + +const MESSAGES = { + patch: patch_code, + execute: exec_code, + rendered: onload_code +} + +self.onmessage = async (event) => { + let resolveExecution, rejectExecution; + const executing = new Promise(function(resolve, reject){ + resolveExecution = resolve; + rejectExecution = reject; + }); + + const prev_msg = QUEUE[0] + const msg = {...event.data, executing} + QUEUE.unshift(msg) + + if (prev_msg) { + self.postMessage({ + type: 'loading', + msg: 'Awaiting previous cells', + id: msg.id + }); + await prev_msg.executing + } + + // Init pyodide + if (self.pyodide == null) { + self.postMessage({ + type: 'loading', + msg: 'Loading pyodide', + id: msg.id + }); + await loadApplication(msg.id, msg.path) + self.postMessage({ + type: 'loaded', + id: msg.id + }); + } + + // Handle message + if (!MESSAGES.hasOwnProperty(msg.type)) { + console.warn(`Service worker received unknown message type '${msg.type}'.`) + resolveExecution() + self.postMessage({ + type: 'idle', + id: msg.id + }); + return + } + + if (msg.type === 'execute') { + let deps + try { + self.pyodide.globals.set('msg', msg) + deps = self.pyodide.runPython(autodetect_deps_code) + } catch(e) { + deps = '[]' + console.warn(`Auto-detection of dependencies failed with error: ${e}`) + } + for (const pkg of JSON.parse(deps)) { + self.postMessage({ + type: 'loading', + msg: `Loading ${pkg}`, + id: msg.id + }); + try { + await self.pyodide.runPythonAsync(`await micropip.install('${pkg}', keep_going=True)`) + } catch(e) { + console.log(`Auto-detected dependency ${pkg} could not be installed.`) + } + } + } + + try { + self.pyodide.globals.set('msg', msg) + let out = await self.pyodide.runPythonAsync(MESSAGES[msg.type]) + resolveExecution() + if (out == null) { + out = new Map() + } + if (out.has('content')) { + self.postMessage({ + type: 'render', + id: msg.id, + content: out.get('content'), + mime: out.get('mime_type') + }); + } + if (out.has('stdout') && out.get('stdout').length) { + self.postMessage({ + type: 'stdout', + content: out.get('stdout'), + id: msg.id + }); + } + if (out.has('stderr') && out.get('stderr').length) { + self.postMessage({ + type: 'stderr', + content: out.get('stderr'), + id: msg.id + }); + } + self.postMessage({ + type: 'idle', + id: msg.id, + uuid: msg.uuid + }); + } catch (e) { + const traceback = `${e}` + const tblines = traceback.split('\n') + self.postMessage({ + type: 'error', + traceback: traceback, + msg: tblines[tblines.length-2], + id: msg.id + }); + resolveExecution() + throw(e) + } +} \ No newline at end of file diff --git a/_static/ServiceHandler.js b/_static/ServiceHandler.js new file mode 100644 index 00000000..6bbd526f --- /dev/null +++ b/_static/ServiceHandler.js @@ -0,0 +1,14 @@ +if ('serviceWorker' in navigator) { + navigator.serviceWorker.register(DOCUMENTATION_OPTIONS.URL_ROOT + 'PyodideServiceWorker.js').then(reg => { + reg.onupdatefound = () => { + const installingWorker = reg.installing; + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed' && + navigator.serviceWorker.controller) { + // Reload page if service worker is replaced + location.reload(); + } + } + } + }) +} \ No newline at end of file diff --git a/_static/WorkerHandler.js b/_static/WorkerHandler.js new file mode 100644 index 00000000..d10dae99 --- /dev/null +++ b/_static/WorkerHandler.js @@ -0,0 +1,95 @@ +const pyodideWorker = new Worker(DOCUMENTATION_OPTIONS.URL_ROOT + '_static/PyodideWebWorker.js'); + +pyodideWorker.documents = {} +pyodideWorker.busy = false +pyodideWorker.queues = new Map() + +function uid() { + return String( + Date.now().toString(32) + + Math.random().toString(16) + ).replace(/\./g, '') +} + +function send_change(jsdoc, doc_id, event) { + if (event.setter_id == 'py') { + return + } else if (pyodideWorker.busy && event.model && event.attr) { + let events = [] + if (pyodideWorker.queues.has(doc_id)) { + for (const old_event of pyodideWorker.queues.get(doc_id)) { + if (!(old_event.model === event.model && old_event.attr === event.attr)) { + events.push(old_event) + } + } + } + events.push(event) + pyodideWorker.queues.set(doc_id, events) + return + } + const patch = jsdoc.create_json_patch([event]) + const uuid = uid() + pyodideWorker.busy = uuid + pyodideWorker.postMessage({type: 'patch', patch: patch, id: doc_id, uuid}) +} + +pyodideWorker.onmessage = async (event) => { + const button = document.getElementById(`button-${event.data.id}`) + const output = document.getElementById(`output-${event.data.id}`) + const stdout = document.getElementById(`stdout-${event.data.id}`) + const stderr = document.getElementById(`stderr-${event.data.id}`) + const msg = event.data; + + if (msg.uuid == pyodideWorker.busy) { + if (pyodideWorker.queues.size) { + const [msg_id, events] = pyodideWorker.queues.entries().next().value + const patch = pyodideWorker.documents[msg_id].create_json_patch(events) + const uuid = uid() + pyodideWorker.busy = uuid + pyodideWorker.postMessage({type: 'patch', patch: patch, id: msg_id, uuid}) + pyodideWorker.queues.delete(msg_id) + } else { + pyodideWorker.busy = false + } + } + + if (msg.type === 'loading') { + _ChangeTooltip(button, msg.msg) + _ChangeIcon(button, iconLoading) + } else if (msg.type === 'loaded') { + _ChangeTooltip(button, 'Executing code') + } else if (msg.type === 'error') { + _ChangeTooltip(button, msg.msg) + _ChangeIcon(button, iconError) + } else if (msg.type === 'idle') { + _ChangeTooltip(button, 'Executed successfully') + _ChangeIcon(button, iconLoaded) + } else if (msg.type === 'stdout') { + const stdout = document.getElementById(`stdout-${msg.id}`) + stdout.style.display = 'block'; + stdout.innerHTML += msg.content + } else if (msg.type === 'stderr') { + const stderr = document.getElementById(`stderr-${msg.id}`) + stderr.style.display = 'block'; + stderr.innerHTML += msg.content + } else if (msg.type === 'render') { + output.style.display = 'block'; + output.setAttribute('class', 'pyodide-output live') + if (msg.mime === 'application/bokeh') { + const [view] = await Bokeh.embed.embed_item(JSON.parse(msg.content)) + + // Setup bi-directional syncing + pyodideWorker.documents[msg.id] = jsdoc = view.model.document + jsdoc.on_change(send_change.bind(null, jsdoc, msg.id), false) + } else if (msg.mime === 'text/plain') { + output.innerHTML = `
${msg.content}
`; + } else if (msg.mime === 'text/html') { + output.innerHTML = `
${msg.content}
` + } + pyodideWorker.postMessage({type: 'rendered', id: msg.id, mime: msg.mime}) + } else if (msg.type === 'patch') { + pyodideWorker.documents[msg.id].apply_json_patch(msg.patch, msg.buffers, setter_id='py') + } +}; + +window.pyodideWorker = pyodideWorker; \ No newline at end of file diff --git a/_static/_sphinx_javascript_frameworks_compat.js b/_static/_sphinx_javascript_frameworks_compat.js new file mode 100644 index 00000000..8549469d --- /dev/null +++ b/_static/_sphinx_javascript_frameworks_compat.js @@ -0,0 +1,134 @@ +/* + * _sphinx_javascript_frameworks_compat.js + * ~~~~~~~~~~ + * + * Compatability shim for jQuery and underscores.js. + * + * WILL BE REMOVED IN Sphinx 6.0 + * xref RemovedInSphinx60Warning + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + + +/** + * small helper function to urldecode strings + * + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL + */ +jQuery.urldecode = function(x) { + if (!x) { + return x + } + return decodeURIComponent(x.replace(/\+/g, ' ')); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s === 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node, addItems) { + if (node.nodeType === 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && + !jQuery(node.parentNode).hasClass(className) && + !jQuery(node.parentNode).hasClass("nohighlight")) { + var span; + var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.className = className; + } + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + if (isInSVG) { + var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect"); + var bbox = node.parentElement.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute('class', className); + addItems.push({ + "parent": node.parentNode, + "target": rect}); + } + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this, addItems); + }); + } + } + var addItems = []; + var result = this.each(function() { + highlight(this, addItems); + }); + for (var i = 0; i < addItems.length; ++i) { + jQuery(addItems[i].parent).before(addItems[i].target); + } + return result; +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 00000000..18495ea0 --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,900 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 270px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/bikes.png b/_static/bikes.png new file mode 100644 index 00000000..803908b2 Binary files /dev/null and b/_static/bikes.png differ diff --git a/_static/builder_dashboard.png b/_static/builder_dashboard.png new file mode 100644 index 00000000..8ff1be22 Binary files /dev/null and b/_static/builder_dashboard.png differ diff --git a/_static/check-solid.svg b/_static/check-solid.svg new file mode 100644 index 00000000..92fad4b5 --- /dev/null +++ b/_static/check-solid.svg @@ -0,0 +1,4 @@ + + + + diff --git a/_static/clipboard.min.js b/_static/clipboard.min.js new file mode 100644 index 00000000..54b3c463 --- /dev/null +++ b/_static/clipboard.min.js @@ -0,0 +1,7 @@ +/*! + * clipboard.js v2.0.8 + * https://clipboardjs.com/ + * + * Licensed MIT © Zeno Rocha + */ +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1 + + + + diff --git a/_static/copybutton.css b/_static/copybutton.css new file mode 100644 index 00000000..f1916ec7 --- /dev/null +++ b/_static/copybutton.css @@ -0,0 +1,94 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .3em; + width: 1.7em; + height: 1.7em; + opacity: 0; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + /* The colors that GitHub uses */ + border: #1b1f2426 1px solid; + background-color: #f6f8fa; + color: #57606a; +} + +button.copybtn.success { + border-color: #22863a; + color: #22863a; +} + +button.copybtn svg { + stroke: currentColor; + width: 1.5em; + height: 1.5em; + padding: 0.1em; +} + +div.highlight { + position: relative; +} + +/* Show the copybutton */ +.highlight:hover button.copybtn, button.copybtn.success { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/_static/copybutton.js b/_static/copybutton.js new file mode 100644 index 00000000..2ea7ff3e --- /dev/null +++ b/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = ` + ${messages[locale]['copy_success']} + + +` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = ` + ${messages[locale]['copy_to_clipboard']} + + + +` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/_static/copybutton_funcs.js b/_static/copybutton_funcs.js new file mode 100644 index 00000000..dbe1aaad --- /dev/null +++ b/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/_static/custom.css b/_static/custom.css new file mode 100644 index 00000000..ce178f2b --- /dev/null +++ b/_static/custom.css @@ -0,0 +1,130 @@ +:root[data-theme="light"] { + --pst-color-primary: rgb(47, 47, 47); + --pst-color-link: deeppink; +} + +@media (min-width: 960px) { + .bd-page-width { + max-width: 120rem; + } +} + +.bd-sidebar-primary { + max-width: 24rem; +} + +.bd-main .bd-content .bd-article-container { + max-width: 80rem; +} + +.navbar-light { + background-color: #fff !important; + box-shadow: 0 0.125rem 0.25rem 0 rgb(0 0 0 / 11%); +} + +.nav-link { + white-space: nowrap; +} + +.showcase-table { + border-spacing: 15px +} + +.showcase-table td { + border: 0px; + vertical-align: top; +} + +.pl-md-5, .px-md-5 { + padding-left: 1rem !important; +} + +.pt-md-5, .py-md-5 { + padding-top: 1rem !important; +} + +.cell_output { + padding-left: 0; +} + +@media (min-width: 1200px) { + .container, .container-lg, .container-md, .container-sm, .container-xl { + max-width: 1600px; + } +} + +#scroller-right { + max-width: 14%; +} + +@media (max-width: 1400px) { + #scroller-right { + position: relative; + right: unset; + top: unset; + max-width: 100%; + transform: unset; + } +} + +button.toggle-button { + display: none; +} + +.toggle-hidden:not(.admonition) { + height: 0; +} + +.tag_hide-input { + margin-bottom: 0 !important; +} + +.toggle-hidden + .cell_output { + margin-top: 0 !important; +} + +/* Improve styling */ + +div.cell div.cell_input { + border: none; +} + +.highlight { + border-radius: 4px; +} + +html[data-theme="light"] .highlight { + background-color: #263238; + color: #f8f8f2; +} + +pre[id^='codecell'] { + background-color: unset; + border: none; + border-radius: 0.5em; + color: #f8f8f2; + box-shadow: none; + padding: 1.5em; + white-space: pre-wrap; +} + +button.copybtn { + background-color: #263238; +} + +button.copybtn:hover { + background-color: #263238; + color: #f8f8f2; +} + +.highlight button.copybtn:hover { + background: none +} + +.o-tooltip--left:after { + background: none; +} + +ul.current.nav.bd-sidenav { + padding: 0; +} diff --git a/_static/dashboard_gallery.png b/_static/dashboard_gallery.png new file mode 100644 index 00000000..0f01baed Binary files /dev/null and b/_static/dashboard_gallery.png differ diff --git a/_static/dataframe.css b/_static/dataframe.css new file mode 100644 index 00000000..8330db60 --- /dev/null +++ b/_static/dataframe.css @@ -0,0 +1,41 @@ +table.dataframe { + margin-left: auto; + margin-right: auto; + border: none; + border-collapse: collapse; + border-spacing: 0; + color: black; + font-size: 12px; + table-layout: fixed; + width: 100%; +} + +.dataframe tr, .dataframe th, .dataframe td { + text-align: right; + vertical-align: middle; + padding: 0.5em 0.5em !important; + line-height: normal; + white-space: normal; + max-width: none; + border: none; +} + +.dataframe tbody { + display: table-row-group; + vertical-align: middle; + border-color: inherit; +} + +.dataframe tbody tr:nth-child(odd) { + background: #f5f5f5; +} + +.dataframe thead { + border-bottom: 1px solid black; + vertical-align: bottom; +} + +.dataframe tr:hover { + background: lightblue !important; + cursor: pointer; +} diff --git a/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 00000000..eb19f698 --- /dev/null +++ b/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/_static/design-tabs.js b/_static/design-tabs.js new file mode 100644 index 00000000..36b38cf0 --- /dev/null +++ b/_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/_static/diagram.png b/_static/diagram.png new file mode 100644 index 00000000..c33ba656 Binary files /dev/null and b/_static/diagram.png differ diff --git a/_static/diagram.svg b/_static/diagram.svg new file mode 100644 index 00000000..5be55d86 --- /dev/null +++ b/_static/diagram.svg @@ -0,0 +1,721 @@ + +image/svg+xmlSourceFilterViewTransformData VizData PipelinePanel diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 00000000..527b876c --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 00000000..8f50916f --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '1.3.1', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: true, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/earthquakes.png b/_static/earthquakes.png new file mode 100644 index 00000000..3096ab39 Binary files /dev/null and b/_static/earthquakes.png differ diff --git a/_static/excalidraw/lumen_dashboard.excalidraw b/_static/excalidraw/lumen_dashboard.excalidraw new file mode 100644 index 00000000..40009ddf --- /dev/null +++ b/_static/excalidraw/lumen_dashboard.excalidraw @@ -0,0 +1,617 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "type": "rectangle", + "version": 126, + "versionNonce": 508713871, + "isDeleted": false, + "id": "vhNXN9yQGXGElq3t7HS-b", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 860, + "y": 380, + "strokeColor": "#000000", + "backgroundColor": "#ced4da", + "width": 300, + "height": 460, + "seed": 867224655, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648952, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 321, + "versionNonce": 1799235809, + "isDeleted": false, + "id": "N6w_1F334hAWr69J4dq5f", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1180, + "y": 357, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 747.9999999999999, + "height": 524, + "seed": 1439839914, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648952, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 187, + "versionNonce": 230560175, + "isDeleted": false, + "id": "1CnrkrKOmBTg5LtfCCU-3", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 837, + "y": 289, + "strokeColor": "#000000", + "backgroundColor": "#00aa41", + "width": 1092, + "height": 59.00000000000001, + "seed": 1383259754, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "iHyamxAOWHEBIRPocq-d8", + "type": "arrow" + } + ], + "updated": 1664282648952, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 140, + "versionNonce": 906805825, + "isDeleted": false, + "id": "zY9bLqGtBjnW7aUZs_1sb", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 838, + "y": 356, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 334, + "height": 524, + "seed": 610194614, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282801901, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 237, + "versionNonce": 264781391, + "isDeleted": false, + "id": "oUwfntRcNOwc0g2Z2JwiT", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 880, + "y": 294.5, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 255, + "height": 44, + "seed": 1376940534, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282801901, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 3, + "text": "config.title", + "baseline": 35, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "config.title" + }, + { + "type": "text", + "version": 166, + "versionNonce": 1545610401, + "isDeleted": false, + "id": "QJdcSSMbalHzyO8x4Zya6", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1449, + "y": 362, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 203, + "height": 60, + "seed": 479196214, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648952, + "link": null, + "locked": false, + "fontSize": 49.122807017543856, + "fontFamily": 3, + "text": "targets", + "baseline": 48, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "targets" + }, + { + "type": "rectangle", + "version": 69, + "versionNonce": 1711681633, + "isDeleted": false, + "id": "jpePQQbSt1097RGAzk5Zo", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 880, + "y": 420, + "strokeColor": "#000000", + "backgroundColor": "#868e96", + "width": 260, + "height": 100, + "seed": 654936449, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "type": "text", + "id": "XkmPUqRlgBnMMifZibopR" + } + ], + "updated": 1664282648952, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 74, + "versionNonce": 1166244929, + "isDeleted": false, + "id": "XkmPUqRlgBnMMifZibopR", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 935, + "y": 448, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 150, + "height": 44, + "seed": 199800015, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648952, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 3, + "text": "filters", + "baseline": 35, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "jpePQQbSt1097RGAzk5Zo", + "originalText": "filters" + }, + { + "type": "rectangle", + "version": 130, + "versionNonce": 1672619087, + "isDeleted": false, + "id": "_mJNDTjHYKlWuISceYwcC", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 880, + "y": 560, + "strokeColor": "#000000", + "backgroundColor": "#868e96", + "width": 260, + "height": 100, + "seed": 1986076257, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "HnWYGNlRYAJUYUTm6ye3U", + "type": "text" + }, + { + "type": "text", + "id": "HnWYGNlRYAJUYUTm6ye3U" + } + ], + "updated": 1664282648952, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 137, + "versionNonce": 53234721, + "isDeleted": false, + "id": "HnWYGNlRYAJUYUTm6ye3U", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 903.5, + "y": 588, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 213, + "height": 44, + "seed": 1921987631, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648952, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 3, + "text": "transforms", + "baseline": 35, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "_mJNDTjHYKlWuISceYwcC", + "originalText": "transforms" + }, + { + "type": "rectangle", + "version": 73, + "versionNonce": 1302774383, + "isDeleted": false, + "id": "RWOs_SfyNW0_O9vY02idL", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1200, + "y": 440, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 700, + "height": 400, + "seed": 767539247, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648952, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 49, + "versionNonce": 1458577409, + "isDeleted": false, + "id": "YeUChD8tEaFFr51iWcRR2", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1220, + "y": 460, + "strokeColor": "#000000", + "backgroundColor": "#fa5252", + "width": 320, + "height": 140, + "seed": 1092027233, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "type": "text", + "id": "VIJsRV1auDBF69t0fYo3F" + } + ], + "updated": 1664282648952, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 67, + "versionNonce": 1738710159, + "isDeleted": false, + "id": "ddKbAslZRmFb4MVtqgdtT", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1580, + "y": 460, + "strokeColor": "#000000", + "backgroundColor": "#228be6", + "width": 300, + "height": 140, + "seed": 856932463, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "type": "text", + "id": "wnuTAx5fx3SpdP8cK8Exx" + } + ], + "updated": 1664282648952, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 84, + "versionNonce": 1322153953, + "isDeleted": false, + "id": "hPSOqDUuG6gGcZiVExZOo", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1220, + "y": 620, + "strokeColor": "#000000", + "backgroundColor": "#fd7e14", + "width": 660, + "height": 200, + "seed": 298563553, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "type": "text", + "id": "B3aRTA34AIVqI9fz54acp" + } + ], + "updated": 1664282648952, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 34, + "versionNonce": 215405505, + "isDeleted": false, + "id": "VIJsRV1auDBF69t0fYo3F", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1315.5, + "y": 508, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 129, + "height": 44, + "seed": 1514973729, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648952, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 3, + "text": "view 1", + "baseline": 35, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "YeUChD8tEaFFr51iWcRR2", + "originalText": "view 1" + }, + { + "type": "text", + "version": 34, + "versionNonce": 58130273, + "isDeleted": false, + "id": "wnuTAx5fx3SpdP8cK8Exx", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1665.5, + "y": 508, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 129, + "height": 44, + "seed": 702434721, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648952, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 3, + "text": "view 2", + "baseline": 35, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ddKbAslZRmFb4MVtqgdtT", + "originalText": "view 2" + }, + { + "type": "text", + "version": 56, + "versionNonce": 1392763695, + "isDeleted": false, + "id": "B3aRTA34AIVqI9fz54acp", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 1485.5, + "y": 698, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 129, + "height": 44, + "seed": 464824577, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648952, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 3, + "text": "view 3", + "baseline": 35, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "hPSOqDUuG6gGcZiVExZOo", + "originalText": "view 3" + }, + { + "type": "rectangle", + "version": 135, + "versionNonce": 2004838945, + "isDeleted": false, + "id": "q7-QpgcMJjtiNFRFQ_Alv", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 880, + "y": 700, + "strokeColor": "#000000", + "backgroundColor": "#868e96", + "width": 260, + "height": 100, + "seed": 1395514145, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [ + { + "id": "8-F7pCemOt1SpqhVK881x", + "type": "text" + }, + { + "id": "8-F7pCemOt1SpqhVK881x", + "type": "text" + }, + { + "type": "text", + "id": "8-F7pCemOt1SpqhVK881x" + } + ], + "updated": 1664282648953, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 156, + "versionNonce": 1377600623, + "isDeleted": false, + "id": "8-F7pCemOt1SpqhVK881x", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 1, + "opacity": 100, + "angle": 0, + "x": 914, + "y": 728, + "strokeColor": "#000000", + "backgroundColor": "transparent", + "width": 192, + "height": 44, + "seed": 596222831, + "groupIds": [], + "strokeSharpness": "sharp", + "boundElements": [], + "updated": 1664282648953, + "link": null, + "locked": false, + "fontSize": 36, + "fontFamily": 3, + "text": "variables", + "baseline": 35, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "q7-QpgcMJjtiNFRFQ_Alv", + "originalText": "variables" + } + ], + "appState": { + "gridSize": 20, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/_static/excalidraw/lumen_dashboard.png b/_static/excalidraw/lumen_dashboard.png new file mode 100644 index 00000000..783dc218 Binary files /dev/null and b/_static/excalidraw/lumen_dashboard.png differ diff --git a/_static/favicon.ico b/_static/favicon.ico new file mode 100644 index 00000000..67575bbb Binary files /dev/null and b/_static/favicon.ico differ diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 00000000..a858a410 Binary files /dev/null and b/_static/file.png differ diff --git a/_static/getting_started/build_app_00.png b/_static/getting_started/build_app_00.png new file mode 100644 index 00000000..bc1bf029 Binary files /dev/null and b/_static/getting_started/build_app_00.png differ diff --git a/_static/getting_started/build_app_01.png b/_static/getting_started/build_app_01.png new file mode 100644 index 00000000..a9c9b6f1 Binary files /dev/null and b/_static/getting_started/build_app_01.png differ diff --git a/_static/getting_started/build_app_02.png b/_static/getting_started/build_app_02.png new file mode 100644 index 00000000..8de25ed9 Binary files /dev/null and b/_static/getting_started/build_app_02.png differ diff --git a/_static/getting_started/build_app_03.png b/_static/getting_started/build_app_03.png new file mode 100644 index 00000000..d4ceeaf2 Binary files /dev/null and b/_static/getting_started/build_app_03.png differ diff --git a/_static/getting_started/build_app_04.png b/_static/getting_started/build_app_04.png new file mode 100644 index 00000000..ba2a9dc5 Binary files /dev/null and b/_static/getting_started/build_app_04.png differ diff --git a/_static/getting_started/build_app_05.png b/_static/getting_started/build_app_05.png new file mode 100644 index 00000000..c6c7c2ef Binary files /dev/null and b/_static/getting_started/build_app_05.png differ diff --git a/_static/getting_started/build_app_06.png b/_static/getting_started/build_app_06.png new file mode 100644 index 00000000..ad6facee Binary files /dev/null and b/_static/getting_started/build_app_06.png differ diff --git a/_static/getting_started/build_app_07.png b/_static/getting_started/build_app_07.png new file mode 100644 index 00000000..45919eb3 Binary files /dev/null and b/_static/getting_started/build_app_07.png differ diff --git a/_static/how_to/branch_yaml_00_firstTable.png b/_static/how_to/branch_yaml_00_firstTable.png new file mode 100644 index 00000000..645ef964 Binary files /dev/null and b/_static/how_to/branch_yaml_00_firstTable.png differ diff --git a/_static/how_to/branch_yaml_01_finalDashboard.png b/_static/how_to/branch_yaml_01_finalDashboard.png new file mode 100644 index 00000000..b5e6d27b Binary files /dev/null and b/_static/how_to/branch_yaml_01_finalDashboard.png differ diff --git a/_static/how_to/data_outtake/download_data/1.png b/_static/how_to/data_outtake/download_data/1.png new file mode 100644 index 00000000..8aaa4e31 Binary files /dev/null and b/_static/how_to/data_outtake/download_data/1.png differ diff --git a/_static/how_to/data_outtake/download_data/2.png b/_static/how_to/data_outtake/download_data/2.png new file mode 100644 index 00000000..fb569bb5 Binary files /dev/null and b/_static/how_to/data_outtake/download_data/2.png differ diff --git a/_static/how_to/data_outtake/download_data/3.png b/_static/how_to/data_outtake/download_data/3.png new file mode 100644 index 00000000..d9d2739a Binary files /dev/null and b/_static/how_to/data_outtake/download_data/3.png differ diff --git a/_static/how_to/local_components/local_components_app.png b/_static/how_to/local_components/local_components_app.png new file mode 100644 index 00000000..d540c000 Binary files /dev/null and b/_static/how_to/local_components/local_components_app.png differ diff --git a/_static/how_to/variables/cli_bad.png b/_static/how_to/variables/cli_bad.png new file mode 100644 index 00000000..ad64abf0 Binary files /dev/null and b/_static/how_to/variables/cli_bad.png differ diff --git a/_static/how_to/variables/cli_good.png b/_static/how_to/variables/cli_good.png new file mode 100644 index 00000000..23b4ab5e Binary files /dev/null and b/_static/how_to/variables/cli_good.png differ diff --git a/_static/how_to/variables/shell.png b/_static/how_to/variables/shell.png new file mode 100644 index 00000000..c915017b Binary files /dev/null and b/_static/how_to/variables/shell.png differ diff --git a/_static/how_to/variables/source_variable.png b/_static/how_to/variables/source_variable.png new file mode 100644 index 00000000..df3dc5a4 Binary files /dev/null and b/_static/how_to/variables/source_variable.png differ diff --git a/_static/how_to/variables/variable_all.png b/_static/how_to/variables/variable_all.png new file mode 100644 index 00000000..6b44c35b Binary files /dev/null and b/_static/how_to/variables/variable_all.png differ diff --git a/_static/how_to/variables/variable_selected.png b/_static/how_to/variables/variable_selected.png new file mode 100644 index 00000000..cdee769f Binary files /dev/null and b/_static/how_to/variables/variable_selected.png differ diff --git a/_static/icons/icon-16x16.png b/_static/icons/icon-16x16.png new file mode 100644 index 00000000..1c8c6679 Binary files /dev/null and b/_static/icons/icon-16x16.png differ diff --git a/_static/icons/icon-192x192.png b/_static/icons/icon-192x192.png new file mode 100644 index 00000000..007baa97 Binary files /dev/null and b/_static/icons/icon-192x192.png differ diff --git a/_static/icons/icon-32x32.png b/_static/icons/icon-32x32.png new file mode 100644 index 00000000..7077bfea Binary files /dev/null and b/_static/icons/icon-32x32.png differ diff --git a/_static/icons/icon-512x512.png b/_static/icons/icon-512x512.png new file mode 100644 index 00000000..eb7b10da Binary files /dev/null and b/_static/icons/icon-512x512.png differ diff --git a/_static/intake_logo.png b/_static/intake_logo.png new file mode 100644 index 00000000..ac1bb5f5 Binary files /dev/null and b/_static/intake_logo.png differ diff --git a/_static/jquery-3.6.0.js b/_static/jquery-3.6.0.js new file mode 100644 index 00000000..fc6c299b --- /dev/null +++ b/_static/jquery-3.6.0.js @@ -0,0 +1,10881 @@ +/*! + * jQuery JavaScript Library v3.6.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2021-03-02T17:08Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var flat = arr.flat ? function( array ) { + return arr.flat.call( array ); +} : function( array ) { + return arr.concat.apply( [], array ); +}; + + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + +var isFunction = function isFunction( obj ) { + + // Support: Chrome <=57, Firefox <=52 + // In some browsers, typeof returns "function" for HTML elements + // (i.e., `typeof document.createElement( "object" ) === "function"`). + // We don't want to classify *any* DOM node as a function. + // Support: QtWeb <=3.8.5, WebKit <=534.34, wkhtmltopdf tool <=0.12.5 + // Plus for old WebKit, typeof returns "function" for HTML collections + // (e.g., `typeof document.getElementsByTagName("div") === "function"`). (gh-4756) + return typeof obj === "function" && typeof obj.nodeType !== "number" && + typeof obj.item !== "function"; + }; + + +var isWindow = function isWindow( obj ) { + return obj != null && obj === obj.window; + }; + + +var document = window.document; + + + + var preservedScriptAttributes = { + type: true, + src: true, + nonce: true, + noModule: true + }; + + function DOMEval( code, node, doc ) { + doc = doc || document; + + var i, val, + script = doc.createElement( "script" ); + + script.text = code; + if ( node ) { + for ( i in preservedScriptAttributes ) { + + // Support: Firefox 64+, Edge 18+ + // Some browsers don't support the "nonce" property on scripts. + // On the other hand, just using `getAttribute` is not enough as + // the `nonce` attribute is reset to an empty string whenever it + // becomes browsing-context connected. + // See https://github.com/whatwg/html/issues/2369 + // See https://html.spec.whatwg.org/#nonce-attributes + // The `node.getAttribute` check was added for the sake of + // `jQuery.globalEval` so that it can fake a nonce-containing node + // via an object. + val = node[ i ] || node.getAttribute && node.getAttribute( i ); + if ( val ) { + script.setAttribute( i, val ); + } + } + } + doc.head.appendChild( script ).parentNode.removeChild( script ); + } + + +function toType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} +/* global Symbol */ +// Defining this global in .eslintrc.json would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.6.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + + // Return all the elements in a clean array + if ( num == null ) { + return slice.call( this ); + } + + // Return just the one element from the set + return num < 0 ? this[ num + this.length ] : this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + even: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return ( i + 1 ) % 2; + } ) ); + }, + + odd: function() { + return this.pushStack( jQuery.grep( this, function( _elem, i ) { + return i % 2; + } ) ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + copy = options[ name ]; + + // Prevent Object.prototype pollution + // Prevent never-ending loop + if ( name === "__proto__" || target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = Array.isArray( copy ) ) ) ) { + src = target[ name ]; + + // Ensure proper type for the source value + if ( copyIsArray && !Array.isArray( src ) ) { + clone = []; + } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { + clone = {}; + } else { + clone = src; + } + copyIsArray = false; + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + // Evaluates a script in a provided context; falls back to the global one + // if not specified. + globalEval: function( code, options, doc ) { + DOMEval( code, { nonce: options && options.nonce }, doc ); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return flat( ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = toType( obj ); + + if ( isFunction( obj ) || isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.6 + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://js.foundation/ + * + * Date: 2021-02-16 + */ +( function( window ) { +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + nonnativeSelectorCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ( {} ).hasOwnProperty, + arr = [], + pop = arr.pop, + pushNative = arr.push, + push = arr.push, + slice = arr.slice, + + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[ i ] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + + "ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram + identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + + // "Attribute values must be CSS identifiers [capture 5] + // or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + + whitespace + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + + "*" ), + rdescend = new RegExp( whitespace + "|>" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rhtml = /HTML$/i, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + funescape = function( escape, nonHex ) { + var high = "0x" + escape.slice( 1 ) - 0x10000; + + return nonHex ? + + // Strip the backslash prefix from a non-hex escape sequence + nonHex : + + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + inDisabledFieldset = addCombinator( + function( elem ) { + return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + ( arr = slice.call( preferredDoc.childNodes ) ), + preferredDoc.childNodes + ); + + // Support: Android<4.0 + // Detect silently failing push.apply + // eslint-disable-next-line no-unused-expressions + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + pushNative.apply( target, slice.call( els ) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + + // Can't trust NodeList.length + while ( ( target[ j++ ] = els[ i++ ] ) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + setDocument( context ); + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && ( match = rquickExpr.exec( selector ) ) ) { + + // ID selector + if ( ( m = match[ 1 ] ) ) { + + // Document context + if ( nodeType === 9 ) { + if ( ( elem = context.getElementById( m ) ) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && ( elem = newContext.getElementById( m ) ) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[ 2 ] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && + + // Support: IE 8 only + // Exclude object elements + ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + + newSelector = selector; + newContext = context; + + // qSA considers elements outside a scoping root when evaluating child or + // descendant combinators, which is not what we want. + // In such cases, we work around the behavior by prefixing every selector in the + // list with an ID selector referencing the scope context. + // The technique has to be used as well when a leading combinator is used + // as such selectors are not recognized by querySelectorAll. + // Thanks to Andrew Dupont for this technique. + if ( nodeType === 1 && + ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + + // We can use :scope instead of the ID hack if the browser + // supports it & if we're not changing the context. + if ( newContext !== context || !support.scope ) { + + // Capture the context ID, setting it first if necessary + if ( ( nid = context.getAttribute( "id" ) ) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", ( nid = expando ) ); + } + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[ i ] = ( nid ? "#" + nid : ":scope" ) + " " + + toSelector( groups[ i ] ); + } + newSelector = groups.join( "," ); + } + + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + nonnativeSelectorCache( selector, true ); + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return ( cache[ key + " " ] = value ); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement( "fieldset" ); + + try { + return !!fn( el ); + } catch ( e ) { + return false; + } finally { + + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split( "|" ), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[ i ] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( ( cur = cur.nextSibling ) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return ( name === "input" || name === "button" ) && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + + // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Only certain elements can match :enabled or :disabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled + // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled + if ( "form" in elem ) { + + // Check for inherited disabledness on relevant non-disabled elements: + // * listed form-associated elements in a disabled fieldset + // https://html.spec.whatwg.org/multipage/forms.html#category-listed + // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled + // * option elements in a disabled optgroup + // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled + // All such elements have a "form" property. + if ( elem.parentNode && elem.disabled === false ) { + + // Option elements defer to a parent optgroup if present + if ( "label" in elem ) { + if ( "label" in elem.parentNode ) { + return elem.parentNode.disabled === disabled; + } else { + return elem.disabled === disabled; + } + } + + // Support: IE 6 - 11 + // Use the isDisabled shortcut property to check for disabled fieldset ancestors + return elem.isDisabled === disabled || + + // Where there is no isDisabled, check manually + /* jshint -W018 */ + elem.isDisabled !== !disabled && + inDisabledFieldset( elem ) === disabled; + } + + return elem.disabled === disabled; + + // Try to winnow out elements that can't be disabled before trusting the disabled property. + // Some victims get caught in our net (label, legend, menu, track), but it shouldn't + // even exist on them, let alone have a boolean value. + } else if ( "label" in elem ) { + return elem.disabled === disabled; + } + + // Remaining elements are neither :enabled nor :disabled + return false; + }; +} + +/** + * Returns a function to use in pseudos for positionals + * @param {Function} fn + */ +function createPositionalPseudo( fn ) { + return markFunction( function( argument ) { + argument = +argument; + return markFunction( function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ ( j = matchIndexes[ i ] ) ] ) { + seed[ j ] = !( matches[ j ] = seed[ j ] ); + } + } + } ); + } ); +} + +/** + * Checks a node for validity as a Sizzle context + * @param {Element|Object=} context + * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value + */ +function testContext( context ) { + return context && typeof context.getElementsByTagName !== "undefined" && context; +} + +// Expose support vars for convenience +support = Sizzle.support = {}; + +/** + * Detects XML nodes + * @param {Element|Object} elem An element or a document + * @returns {Boolean} True iff elem is a non-HTML XML node + */ +isXML = Sizzle.isXML = function( elem ) { + var namespace = elem && elem.namespaceURI, + docElem = elem && ( elem.ownerDocument || elem ).documentElement; + + // Support: IE <=8 + // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes + // https://bugs.jquery.com/ticket/4833 + return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); +}; + +/** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ +setDocument = Sizzle.setDocument = function( node ) { + var hasCompare, subWindow, + doc = node ? node.ownerDocument || node : preferredDoc; + + // Return early if doc is invalid or already selected + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( doc == document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Update global variables + document = doc; + docElem = document.documentElement; + documentIsHTML = !isXML( document ); + + // Support: IE 9 - 11+, Edge 12 - 18+ + // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + + // Support: IE 11, Edge + if ( subWindow.addEventListener ) { + subWindow.addEventListener( "unload", unloadHandler, false ); + + // Support: IE 9 - 10 only + } else if ( subWindow.attachEvent ) { + subWindow.attachEvent( "onunload", unloadHandler ); + } + } + + // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, + // Safari 4 - 5 only, Opera <=11.6 - 12.x only + // IE/Edge & older browsers don't support the :scope pseudo-class. + // Support: Safari 6.0 only + // Safari 6.0 supports :scope but it's an alias of :root there. + support.scope = assert( function( el ) { + docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); + return typeof el.querySelectorAll !== "undefined" && + !el.querySelectorAll( ":scope fieldset div" ).length; + } ); + + /* Attributes + ---------------------------------------------------------------------- */ + + // Support: IE<8 + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) + support.attributes = assert( function( el ) { + el.className = "i"; + return !el.getAttribute( "className" ); + } ); + + /* getElement(s)By* + ---------------------------------------------------------------------- */ + + // Check if getElementsByTagName("*") returns only elements + support.getElementsByTagName = assert( function( el ) { + el.appendChild( document.createComment( "" ) ); + return !el.getElementsByTagName( "*" ).length; + } ); + + // Support: IE<9 + support.getElementsByClassName = rnative.test( document.getElementsByClassName ); + + // Support: IE<10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + docElem.appendChild( el ).id = expando; + return !document.getElementsByName || !document.getElementsByName( expando ).length; + } ); + + // ID filter and find + if ( support.getById ) { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute( "id" ) === attrId; + }; + }; + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var elem = context.getElementById( id ); + return elem ? [ elem ] : []; + } + }; + } else { + Expr.filter[ "ID" ] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== "undefined" && + elem.getAttributeNode( "id" ); + return node && node.value === attrId; + }; + }; + + // Support: IE 6 - 7 only + // getElementById is not reliable as a find shortcut + Expr.find[ "ID" ] = function( id, context ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { + var node, i, elems, + elem = context.getElementById( id ); + + if ( elem ) { + + // Verify the id attribute + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + + // Fall back on getElementsByName + elems = context.getElementsByName( id ); + i = 0; + while ( ( elem = elems[ i++ ] ) ) { + node = elem.getAttributeNode( "id" ); + if ( node && node.value === id ) { + return [ elem ]; + } + } + } + + return []; + } + }; + } + + // Tag + Expr.find[ "TAG" ] = support.getElementsByTagName ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); + } + } : + + function( tag, context ) { + var elem, + tmp = [], + i = 0, + + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Class + Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { + return context.getElementsByClassName( className ); + } + }; + + /* QSA/matchesSelector + ---------------------------------------------------------------------- */ + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21) + // We allow this because of a bug in IE8/9 that throws an error + // whenever `document.activeElement` is accessed on an iframe + // So, we allow :focus to pass through QSA all the time to avoid the IE error + // See https://bugs.jquery.com/ticket/13378 + rbuggyQSA = []; + + if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { + + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { + + var input; + + // Select is set to empty string on purpose + // This is to test IE's treatment of not explicitly + // setting a boolean content attribute, + // since its presence should be enough + // https://bugs.jquery.com/ticket/12359 + docElem.appendChild( el ).innerHTML = "" + + ""; + + // Support: IE8, Opera 11-12.16 + // Nothing should be selected when empty strings follow ^= or $= or *= + // The test attribute must be unknown in Opera but "safe" for WinRT + // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section + if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); + } + + // Support: IE8 + // Boolean attributes and "value" are not treated correctly + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } + + // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } + + // Support: Firefox <=3.6 - 5 only + // Old Firefox doesn't throw on a badly-escaped identifier. + el.querySelectorAll( "\\\f" ); + rbuggyQSA.push( "[\\r\\n\\f]" ); + } ); + + assert( function( el ) { + el.innerHTML = "" + + ""; + + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + var input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE8 + // Enforce case-sensitivity of name attribute + if ( el.querySelectorAll( "[name=d]" ).length ) { + rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE9-11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + docElem.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: Opera 10 - 11 only + // Opera 10-11 does not throw on post-comma invalid pseudos + el.querySelectorAll( "*,:x" ); + rbuggyQSA.push( ",.*:" ); + } ); + } + + if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || + docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector ) ) ) ) { + + assert( function( el ) { + + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( el, "*" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( el, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + } ); + } + + rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); + rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); + + /* Contains + ---------------------------------------------------------------------- */ + hasCompare = rnative.test( docElem.compareDocumentPosition ); + + // Element contains another + // Purposefully self-exclusive + // As in, an element does not contain itself + contains = hasCompare || rnative.test( docElem.contains ) ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); + } : + function( a, b ) { + if ( b ) { + while ( ( b = b.parentNode ) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + /* Sorting + ---------------------------------------------------------------------- */ + + // Document order sorting + sortOrder = hasCompare ? + function( a, b ) { + + // Flag for duplicate removal + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + // Sort on method existence if only one input has compareDocumentPosition + var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; + if ( compare ) { + return compare; + } + + // Calculate position if both inputs belong to the same document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + compare = ( a.ownerDocument || a ) == ( b.ownerDocument || b ) ? + a.compareDocumentPosition( b ) : + + // Otherwise we know they are disconnected + 1; + + // Disconnected nodes + if ( compare & 1 || + ( !support.sortDetached && b.compareDocumentPosition( a ) === compare ) ) { + + // Choose the first element that is related to our preferred document + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( a == document || a.ownerDocument == preferredDoc && + contains( preferredDoc, a ) ) { + return -1; + } + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( b == document || b.ownerDocument == preferredDoc && + contains( preferredDoc, b ) ) { + return 1; + } + + // Maintain original order + return sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + } + + return compare & 4 ? -1 : 1; + } : + function( a, b ) { + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Parentless nodes are either documents or disconnected + if ( !aup || !bup ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + return a == document ? -1 : + b == document ? 1 : + /* eslint-enable eqeqeq */ + aup ? -1 : + bup ? 1 : + sortInput ? + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( ( cur = cur.parentNode ) ) { + ap.unshift( cur ); + } + cur = b; + while ( ( cur = cur.parentNode ) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[ i ] === bp[ i ] ) { + i++; + } + + return i ? + + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[ i ], bp[ i ] ) : + + // Otherwise nodes in our document sort first + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + /* eslint-disable eqeqeq */ + ap[ i ] == preferredDoc ? -1 : + bp[ i ] == preferredDoc ? 1 : + /* eslint-enable eqeqeq */ + 0; + }; + + return document; +}; + +Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); +}; + +Sizzle.matchesSelector = function( elem, expr ) { + setDocument( elem ); + + if ( support.matchesSelector && documentIsHTML && + !nonnativeSelectorCache[ expr + " " ] && + ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch ( e ) { + nonnativeSelectorCache( expr, true ); + } + } + + return Sizzle( expr, document, null, [ elem ] ).length > 0; +}; + +Sizzle.contains = function( context, elem ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( context.ownerDocument || context ) != document ) { + setDocument( context ); + } + return contains( context, elem ); +}; + +Sizzle.attr = function( elem, name ) { + + // Set document vars if needed + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( ( elem.ownerDocument || elem ) != document ) { + setDocument( elem ); + } + + var fn = Expr.attrHandle[ name.toLowerCase() ], + + // Don't get fooled by Object.prototype properties (jQuery #13807) + val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? + fn( elem, name, !documentIsHTML ) : + undefined; + + return val !== undefined ? + val : + support.attributes || !documentIsHTML ? + elem.getAttribute( name ) : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; +}; + +Sizzle.escape = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + +Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); +}; + +/** + * Document sorting and removing duplicates + * @param {ArrayLike} results + */ +Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + j = 0, + i = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + sortInput = !support.sortStable && results.slice( 0 ); + results.sort( sortOrder ); + + if ( hasDuplicate ) { + while ( ( elem = results[ i++ ] ) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + // Clear input after sorting to release objects + // See https://github.com/jquery/sizzle/pull/225 + sortInput = null; + + return results; +}; + +/** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ +getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + + // If no nodeType, this is expected to be an array + while ( ( node = elem[ i++ ] ) ) { + + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + + // Use textContent for elements + // innerText usage removed for consistency of new lines (jQuery #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + + // Do not include comment or processing instruction nodes + + return ret; +}; + +Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + attrHandle: {}, + + find: {}, + + relative: { + ">": { dir: "parentNode", first: true }, + " ": { dir: "parentNode" }, + "+": { dir: "previousSibling", first: true }, + "~": { dir: "previousSibling" } + }, + + preFilter: { + "ATTR": function( match ) { + match[ 1 ] = match[ 1 ].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || + match[ 5 ] || "" ).replace( runescape, funescape ); + + if ( match[ 2 ] === "~=" ) { + match[ 3 ] = " " + match[ 3 ] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[ 1 ] = match[ 1 ].toLowerCase(); + + if ( match[ 1 ].slice( 0, 3 ) === "nth" ) { + + // nth-* requires argument + if ( !match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[ 4 ] = +( match[ 4 ] ? + match[ 5 ] + ( match[ 6 ] || 1 ) : + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); + + // other types prohibit arguments + } else if ( match[ 3 ] ) { + Sizzle.error( match[ 0 ] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[ 6 ] && match[ 2 ]; + + if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[ 3 ] ) { + match[ 2 ] = match[ 4 ] || match[ 5 ] || ""; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + + // Get excess from tokenize (recursively) + ( excess = tokenize( unquoted, true ) ) && + + // advance to the next closing parenthesis + ( excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length ) ) { + + // excess is a negative index + match[ 0 ] = match[ 0 ].slice( 0, excess ); + match[ 2 ] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeNameSelector ) { + var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + return nodeNameSelector === "*" ? + function() { + return true; + } : + function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + ( pattern = new RegExp( "(^|" + whitespace + + ")" + className + "(" + whitespace + "|$)" ) ) && classCache( + className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); + } ); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + /* eslint-disable max-len */ + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > -1 : + operator === "$=" ? check && result.slice( -check.length ) === check : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + /* eslint-enable max-len */ + + }; + }, + + "CHILD": function( type, what, _argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( -4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + + function( elem, _context, xml ) { + var cache, uniqueCache, outerCache, node, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType, + diff = false; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( ( node = node[ dir ] ) ) { + if ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) { + + return false; + } + } + + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + + // Seek `elem` from a previously-cached index + + // ...in a gzip-friendly way + node = parent; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex && cache[ 2 ]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( ( node = ++nodeIndex && node && node[ dir ] || + + // Fallback to seeking `elem` from the start + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + } else { + + // Use previously-cached element index if available + if ( useCache ) { + + // ...in a gzip-friendly way + node = elem; + outerCache = node[ expando ] || ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + cache = uniqueCache[ type ] || []; + nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; + diff = nodeIndex; + } + + // xml :nth-child(...) + // or :nth-last-child(...) or :nth(-last)?-of-type(...) + if ( diff === false ) { + + // Use the same loop as above to seek `elem` from the start + while ( ( node = ++nodeIndex && node && node[ dir ] || + ( diff = nodeIndex = 0 ) || start.pop() ) ) { + + if ( ( ofType ? + node.nodeName.toLowerCase() === name : + node.nodeType === 1 ) && + ++diff ) { + + // Cache the index of each encountered element + if ( useCache ) { + outerCache = node[ expando ] || + ( node[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ node.uniqueID ] || + ( outerCache[ node.uniqueID ] = {} ); + + uniqueCache[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction( function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf( seed, matched[ i ] ); + seed[ idx ] = !( matches[ idx ] = matched[ i ] ); + } + } ) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + + // Potentially complex pseudos + "not": markFunction( function( selector ) { + + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction( function( seed, matches, _context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( ( elem = unmatched[ i ] ) ) { + seed[ i ] = !( matches[ i ] = elem ); + } + } + } ) : + function( elem, _context, xml ) { + input[ 0 ] = elem; + matcher( input, null, xml, results ); + + // Don't keep the element (issue #299) + input[ 0 ] = null; + return !results.pop(); + }; + } ), + + "has": markFunction( function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + } ), + + "contains": markFunction( function( text ) { + text = text.replace( runescape, funescape ); + return function( elem ) { + return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + }; + } ), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + + // lang value must be a valid identifier + if ( !ridentifier.test( lang || "" ) ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( ( elemLang = documentIsHTML ? + elem.lang : + elem.getAttribute( "xml:lang" ) || elem.getAttribute( "lang" ) ) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } while ( ( elem = elem.parentNode ) && elem.nodeType === 1 ); + return false; + }; + } ), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && + ( !document.hasFocus || document.hasFocus() ) && + !!( elem.type || elem.href || ~elem.tabIndex ); + }, + + // Boolean properties + "enabled": createDisabledPseudo( false ), + "disabled": createDisabledPseudo( true ), + + "checked": function( elem ) { + + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return ( nodeName === "input" && !!elem.checked ) || + ( nodeName === "option" && !!elem.selected ); + }, + + "selected": function( elem ) { + + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + // eslint-disable-next-line no-unused-expressions + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), + // but not by others (comment: 8; processing instruction: 7; etc.) + // nodeType < 6 works because attributes (2) do not appear as children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeType < 6 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos[ "empty" ]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + + // Support: IE<8 + // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + ( ( attr = elem.getAttribute( "type" ) ) == null || + attr.toLowerCase() === "text" ); + }, + + // Position-in-collection + "first": createPositionalPseudo( function() { + return [ 0 ]; + } ), + + "last": createPositionalPseudo( function( _matchIndexes, length ) { + return [ length - 1 ]; + } ), + + "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + } ), + + "even": createPositionalPseudo( function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "odd": createPositionalPseudo( function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? + argument + length : + argument > length ? + length : + argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ), + + "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + } ) + } +}; + +Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; + +// Add button/input type pseudos +for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { + Expr.pseudos[ i ] = createInputPseudo( i ); +} +for ( i in { submit: true, reset: true } ) { + Expr.pseudos[ i ] = createButtonPseudo( i ); +} + +// Easy API for creating new setFilters +function setFilters() {} +setFilters.prototype = Expr.filters = Expr.pseudos; +Expr.setFilters = new setFilters(); + +tokenize = Sizzle.tokenize = function( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || ( match = rcomma.exec( soFar ) ) ) { + if ( match ) { + + // Don't consume trailing commas as valid + soFar = soFar.slice( match[ 0 ].length ) || soFar; + } + groups.push( ( tokens = [] ) ); + } + + matched = false; + + // Combinators + if ( ( match = rcombinators.exec( soFar ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + + // Cast descendant combinators to space + type: match[ 0 ].replace( rtrim, " " ) + } ); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( ( match = matchExpr[ type ].exec( soFar ) ) && ( !preFilters[ type ] || + ( match = preFilters[ type ]( match ) ) ) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + } ); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +}; + +function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[ i ].value; + } + return selector; +} + +function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + skip = combinator.next, + key = skip || dir, + checkNonElements = base && key === "parentNode", + doneName = done++; + + return combinator.first ? + + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + return false; + } : + + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var oldCache, uniqueCache, outerCache, + newCache = [ dirruns, doneName ]; + + // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching + if ( xml ) { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( ( elem = elem[ dir ] ) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + + // Support: IE <9 only + // Defend against cloned attroperties (jQuery gh-1709) + uniqueCache = outerCache[ elem.uniqueID ] || + ( outerCache[ elem.uniqueID ] = {} ); + + if ( skip && skip === elem.nodeName.toLowerCase() ) { + elem = elem[ dir ] || elem; + } else if ( ( oldCache = uniqueCache[ key ] ) && + oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { + + // Assign to newCache so results back-propagate to previous elements + return ( newCache[ 2 ] = oldCache[ 2 ] ); + } else { + + // Reuse newcache so results back-propagate to previous elements + uniqueCache[ key ] = newCache; + + // A match means we're done; a fail means we have to keep checking + if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { + return true; + } + } + } + } + } + return false; + }; +} + +function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[ i ]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[ 0 ]; +} + +function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[ i ], results ); + } + return results; +} + +function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( ( elem = unmatched[ i ] ) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; +} + +function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction( function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + + // Get initial elements from seed or context + elems = seed || multipleContexts( + selector || "*", + context.nodeType ? [ context ] : context, + [] + ), + + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + + matcherOut = matcher ? + + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + + // ...intermediate processing is necessary + [] : + + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( ( elem = temp[ i ] ) ) { + matcherOut[ postMap[ i ] ] = !( matcherIn[ postMap[ i ] ] = elem ); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) ) { + + // Restore matcherIn since elem is not yet a final match + temp.push( ( matcherIn[ i ] = elem ) ); + } + } + postFinder( null, ( matcherOut = [] ), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( ( elem = matcherOut[ i ] ) && + ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + + seed[ temp ] = !( results[ temp ] = elem ); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + } ); +} + +function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[ 0 ].type ], + implicitRelative = leadingRelative || Expr.relative[ " " ], + i = leadingRelative ? 1 : 0, + + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf( checkContext, elem ) > -1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + ( checkContext = context ).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; + } ]; + + for ( ; i < len; i++ ) { + if ( ( matcher = Expr.relative[ tokens[ i ].type ] ) ) { + matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; + } else { + matcher = Expr.filter[ tokens[ i ].type ].apply( null, tokens[ i ].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[ j ].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( + + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens + .slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); +} + +function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + var bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, outermost ) { + var elem, j, matcher, + matchedCount = 0, + i = "0", + unmatched = seed && [], + setMatched = [], + contextBackup = outermostContext, + + // We must always have either seed elements or outermost context + elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), + len = elems.length; + + if ( outermost ) { + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + outermostContext = context == document || context || outermost; + } + + // Add elements passing elementMatchers directly to results + // Support: IE<9, Safari + // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( !context && elem.ownerDocument != document ) { + setDocument( elem ); + xml = !documentIsHTML; + } + while ( ( matcher = elementMatchers[ j++ ] ) ) { + if ( matcher( elem, context || document, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + + // They will have gone through all possible matchers + if ( ( elem = !matcher && elem ) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // `i` is now the count of elements visited above, and adding it to `matchedCount` + // makes the latter nonnegative. + matchedCount += i; + + // Apply set filters to unmatched elements + // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount` + // equals `i`), unless we didn't visit _any_ elements in the above loop because we have + // no element matchers and no seed. + // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that + // case, which will result in a "00" `matchedCount` that differs from `i` but is also + // numerically zero. + if ( bySet && i !== matchedCount ) { + j = 0; + while ( ( matcher = setMatchers[ j++ ] ) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !( unmatched[ i ] || setMatched[ i ] ) ) { + setMatched[ i ] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; +} + +compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + + // Generate a function of recursive functions that can be used to check each element + if ( !match ) { + match = tokenize( selector ); + } + i = match.length; + while ( i-- ) { + cached = matcherFromTokens( match[ i ] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( + selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) + ); + + // Save selector and tokenization + cached.selector = selector; + } + return cached; +}; + +/** + * A low-level selection function that works with Sizzle's compiled + * selector functions + * @param {String|Function} selector A selector or a pre-compiled + * selector function built with Sizzle.compile + * @param {Element} context + * @param {Array} [results] + * @param {Array} [seed] A set of elements to match against + */ +select = Sizzle.select = function( selector, context, results, seed ) { + var i, tokens, token, type, find, + compiled = typeof selector === "function" && selector, + match = !seed && tokenize( ( selector = compiled.selector || selector ) ); + + results = results || []; + + // Try to minimize operations if there is only one selector in the list and no seed + // (the latter of which guarantees us context) + if ( match.length === 1 ) { + + // Reduce context if the leading compound selector is an ID + tokens = match[ 0 ] = match[ 0 ].slice( 0 ); + if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + + context = ( Expr.find[ "ID" ]( token.matches[ 0 ] + .replace( runescape, funescape ), context ) || [] )[ 0 ]; + if ( !context ) { + return results; + + // Precompiled matchers will still verify ancestry, so step up a level + } else if ( compiled ) { + context = context.parentNode; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[ i ]; + + // Abort if we hit a combinator + if ( Expr.relative[ ( type = token.type ) ] ) { + break; + } + if ( ( find = Expr.find[ type ] ) ) { + + // Search, expanding context for leading sibling combinators + if ( ( seed = find( + token.matches[ 0 ].replace( runescape, funescape ), + rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || + context + ) ) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, seed ); + return results; + } + + break; + } + } + } + } + + // Compile and execute a filtering function if one is not provided + // Provide `match` to avoid retokenization if we modified the selector above + ( compiled || compile( selector, match ) )( + seed, + context, + !documentIsHTML, + results, + !context || rsibling.test( selector ) && testContext( context.parentNode ) || context + ); + return results; +}; + +// One-time assignments + +// Sort stability +support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; + +// Support: Chrome 14-35+ +// Always assume duplicates if they aren't passed to the comparison function +support.detectDuplicates = !!hasDuplicate; + +// Initialize against the default document +setDocument(); + +// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Detached nodes confoundingly follow *each other* +support.sortDetached = assert( function( el ) { + + // Should return 1, but returns 4 (following) + return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; +} ); + +// Support: IE<8 +// Prevent attribute/property "interpolation" +// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx +if ( !assert( function( el ) { + el.innerHTML = ""; + return el.firstChild.getAttribute( "href" ) === "#"; +} ) ) { + addHandle( "type|href|height|width", function( elem, name, isXML ) { + if ( !isXML ) { + return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); + } + } ); +} + +// Support: IE<9 +// Use defaultValue in place of getAttribute("value") +if ( !support.attributes || !assert( function( el ) { + el.innerHTML = ""; + el.firstChild.setAttribute( "value", "" ); + return el.firstChild.getAttribute( "value" ) === ""; +} ) ) { + addHandle( "value", function( elem, _name, isXML ) { + if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { + return elem.defaultValue; + } + } ); +} + +// Support: IE<9 +// Use getAttributeNode to fetch booleans when getAttribute lies +if ( !assert( function( el ) { + return el.getAttribute( "disabled" ) == null; +} ) ) { + addHandle( booleans, function( elem, name, isXML ) { + var val; + if ( !isXML ) { + return elem[ name ] === true ? name.toLowerCase() : + ( val = elem.getAttributeNode( name ) ) && val.specified ? + val.value : + null; + } + } ); +} + +return Sizzle; + +} )( window ); + + + +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; + +// Deprecated +jQuery.expr[ ":" ] = jQuery.expr.pseudos; +jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; +jQuery.escapeSelector = Sizzle.escape; + + + + +var dir = function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; +}; + + +var siblings = function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; +}; + + +var rneedsContext = jQuery.expr.match.needsContext; + + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); + + + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + return !!qualifier.call( elem, i, elem ) !== not; + } ); + } + + // Single element + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + } ); + } + + // Arraylike of elements (jQuery, arguments, Array) + if ( typeof qualifier !== "string" ) { + return jQuery.grep( elements, function( elem ) { + return ( indexOf.call( qualifier, elem ) > -1 ) !== not; + } ); + } + + // Filtered directly for both simple and complex selectors + return jQuery.filter( qualifier, elements, not ); +} + +jQuery.filter = function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + if ( elems.length === 1 && elem.nodeType === 1 ) { + return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : []; + } + + return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + } ) ); +}; + +jQuery.fn.extend( { + find: function( selector ) { + var i, ret, + len = this.length, + self = this; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter( function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + } ) ); + } + + ret = this.pushStack( [] ); + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + return len > 1 ? jQuery.uniqueSort( ret ) : ret; + }, + filter: function( selector ) { + return this.pushStack( winnow( this, selector || [], false ) ); + }, + not: function( selector ) { + return this.pushStack( winnow( this, selector || [], true ) ); + }, + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + } +} ); + + +// Initialize a jQuery object + + +// A central reference to the root jQuery(document) +var rootjQuery, + + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + // Shortcut simple #id case for speed + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, + + init = jQuery.fn.init = function( selector, context, root ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Method init() accepts an alternate rootjQuery + // so migrate can support jQuery.sub (gh-2101) + root = root || rootjQuery; + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector[ 0 ] === "<" && + selector[ selector.length - 1 ] === ">" && + selector.length >= 3 ) { + + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && ( match[ 1 ] || !context ) ) { + + // HANDLE: $(html) -> $(array) + if ( match[ 1 ] ) { + context = context instanceof jQuery ? context[ 0 ] : context; + + // Option to run scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present + jQuery.merge( this, jQuery.parseHTML( + match[ 1 ], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + + // Properties of context are called as methods if possible + if ( isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[ 2 ] ); + + if ( elem ) { + + // Inject the element directly into the jQuery object + this[ 0 ] = elem; + this.length = 1; + } + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || root ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this[ 0 ] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( isFunction( selector ) ) { + return root.ready !== undefined ? + root.ready( selector ) : + + // Execute immediately if ready is not present + selector( jQuery ); + } + + return jQuery.makeArray( selector, this ); + }; + +// Give the init function the jQuery prototype for later instantiation +init.prototype = jQuery.fn; + +// Initialize central reference +rootjQuery = jQuery( document ); + + +var rparentsprev = /^(?:parents|prev(?:Until|All))/, + + // Methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend( { + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter( function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[ i ] ) ) { + return true; + } + } + } ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + targets = typeof selectors !== "string" && jQuery( selectors ); + + // Positional selectors never match, since there's no _selection_ context + if ( !rneedsContext.test( selectors ) ) { + for ( ; i < l; i++ ) { + for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) { + + // Always skip document fragments + if ( cur.nodeType < 11 && ( targets ? + targets.index( cur ) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector( cur, selectors ) ) ) { + + matched.push( cur ); + break; + } + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched ); + }, + + // Determine the position of an element within the set + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // Index in selector + if ( typeof elem === "string" ) { + return indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + return this.pushStack( + jQuery.uniqueSort( + jQuery.merge( this.get(), jQuery( selector, context ) ) + ) + ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + } +} ); + +function sibling( cur, dir ) { + while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {} + return cur; +} + +jQuery.each( { + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, _i, until ) { + return dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, _i, until ) { + return dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, _i, until ) { + return dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return siblings( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return siblings( elem.firstChild ); + }, + contents: function( elem ) { + if ( elem.contentDocument != null && + + // Support: IE 11+ + // elements with no `data` attribute has an object + // `contentDocument` with a `null` prototype. + getProto( elem.contentDocument ) ) { + + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.uniqueSort( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +} ); +var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g ); + + + +// Convert String-formatted options into Object-formatted ones +function createOptions( options ) { + var object = {}; + jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { + object[ flag ] = true; + } ); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + createOptions( options ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + + // Last fire value for non-forgettable lists + memory, + + // Flag to know if list was already fired + fired, + + // Flag to prevent firing + locked, + + // Actual callback list + list = [], + + // Queue of execution data for repeatable lists + queue = [], + + // Index of currently firing callback (modified by add/remove as needed) + firingIndex = -1, + + // Fire callbacks + fire = function() { + + // Enforce single-firing + locked = locked || options.once; + + // Execute callbacks for all pending executions, + // respecting firingIndex overrides and runtime changes + fired = firing = true; + for ( ; queue.length; firingIndex = -1 ) { + memory = queue.shift(); + while ( ++firingIndex < list.length ) { + + // Run callback and check for early termination + if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && + options.stopOnFalse ) { + + // Jump to end and forget the data so .add doesn't re-fire + firingIndex = list.length; + memory = false; + } + } + } + + // Forget the data if we're done with it + if ( !options.memory ) { + memory = false; + } + + firing = false; + + // Clean up if we're done firing for good + if ( locked ) { + + // Keep an empty list if we have data for future add calls + if ( memory ) { + list = []; + + // Otherwise, this object is spent + } else { + list = ""; + } + } + }, + + // Actual Callbacks object + self = { + + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + + // If we have memory from a past run, we should fire after adding + if ( memory && !firing ) { + firingIndex = list.length - 1; + queue.push( memory ); + } + + ( function add( args ) { + jQuery.each( args, function( _, arg ) { + if ( isFunction( arg ) ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && toType( arg ) !== "string" ) { + + // Inspect recursively + add( arg ); + } + } ); + } )( arguments ); + + if ( memory && !firing ) { + fire(); + } + } + return this; + }, + + // Remove a callback from the list + remove: function() { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + + // Handle firing indexes + if ( index <= firingIndex ) { + firingIndex--; + } + } + } ); + return this; + }, + + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? + jQuery.inArray( fn, list ) > -1 : + list.length > 0; + }, + + // Remove all callbacks from the list + empty: function() { + if ( list ) { + list = []; + } + return this; + }, + + // Disable .fire and .add + // Abort any current/pending executions + // Clear all callbacks and values + disable: function() { + locked = queue = []; + list = memory = ""; + return this; + }, + disabled: function() { + return !list; + }, + + // Disable .fire + // Also disable .add unless we have memory (since it would have no effect) + // Abort any pending executions + lock: function() { + locked = queue = []; + if ( !memory && !firing ) { + list = memory = ""; + } + return this; + }, + locked: function() { + return !!locked; + }, + + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( !locked ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + queue.push( args ); + if ( !firing ) { + fire(); + } + } + return this; + }, + + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; + + +function Identity( v ) { + return v; +} +function Thrower( ex ) { + throw ex; +} + +function adoptValue( value, resolve, reject, noValue ) { + var method; + + try { + + // Check for promise aspect first to privilege synchronous behavior + if ( value && isFunction( ( method = value.promise ) ) ) { + method.call( value ).done( resolve ).fail( reject ); + + // Other thenables + } else if ( value && isFunction( ( method = value.then ) ) ) { + method.call( value, resolve, reject ); + + // Other non-thenables + } else { + + // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer: + // * false: [ value ].slice( 0 ) => resolve( value ) + // * true: [ value ].slice( 1 ) => resolve() + resolve.apply( undefined, [ value ].slice( noValue ) ); + } + + // For Promises/A+, convert exceptions into rejections + // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in + // Deferred#then to conditionally suppress rejection. + } catch ( value ) { + + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + reject.apply( undefined, [ value ] ); + } +} + +jQuery.extend( { + + Deferred: function( func ) { + var tuples = [ + + // action, add listener, callbacks, + // ... .then handlers, argument index, [final state] + [ "notify", "progress", jQuery.Callbacks( "memory" ), + jQuery.Callbacks( "memory" ), 2 ], + [ "resolve", "done", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 0, "resolved" ], + [ "reject", "fail", jQuery.Callbacks( "once memory" ), + jQuery.Callbacks( "once memory" ), 1, "rejected" ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + "catch": function( fn ) { + return promise.then( null, fn ); + }, + + // Keep pipe for back-compat + pipe: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + + return jQuery.Deferred( function( newDefer ) { + jQuery.each( tuples, function( _i, tuple ) { + + // Map tuples (progress, done, fail) to arguments (done, fail, progress) + var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + + // deferred.progress(function() { bind to newDefer or newDefer.notify }) + // deferred.done(function() { bind to newDefer or newDefer.resolve }) + // deferred.fail(function() { bind to newDefer or newDefer.reject }) + deferred[ tuple[ 1 ] ]( function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && isFunction( returned.promise ) ) { + returned.promise() + .progress( newDefer.notify ) + .done( newDefer.resolve ) + .fail( newDefer.reject ); + } else { + newDefer[ tuple[ 0 ] + "With" ]( + this, + fn ? [ returned ] : arguments + ); + } + } ); + } ); + fns = null; + } ).promise(); + }, + then: function( onFulfilled, onRejected, onProgress ) { + var maxDepth = 0; + function resolve( depth, deferred, handler, special ) { + return function() { + var that = this, + args = arguments, + mightThrow = function() { + var returned, then; + + // Support: Promises/A+ section 2.3.3.3.3 + // https://promisesaplus.com/#point-59 + // Ignore double-resolution attempts + if ( depth < maxDepth ) { + return; + } + + returned = handler.apply( that, args ); + + // Support: Promises/A+ section 2.3.1 + // https://promisesaplus.com/#point-48 + if ( returned === deferred.promise() ) { + throw new TypeError( "Thenable self-resolution" ); + } + + // Support: Promises/A+ sections 2.3.3.1, 3.5 + // https://promisesaplus.com/#point-54 + // https://promisesaplus.com/#point-75 + // Retrieve `then` only once + then = returned && + + // Support: Promises/A+ section 2.3.4 + // https://promisesaplus.com/#point-64 + // Only check objects and functions for thenability + ( typeof returned === "object" || + typeof returned === "function" ) && + returned.then; + + // Handle a returned thenable + if ( isFunction( then ) ) { + + // Special processors (notify) just wait for resolution + if ( special ) { + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ) + ); + + // Normal processors (resolve) also hook into progress + } else { + + // ...and disregard older resolution values + maxDepth++; + + then.call( + returned, + resolve( maxDepth, deferred, Identity, special ), + resolve( maxDepth, deferred, Thrower, special ), + resolve( maxDepth, deferred, Identity, + deferred.notifyWith ) + ); + } + + // Handle all other returned values + } else { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Identity ) { + that = undefined; + args = [ returned ]; + } + + // Process the value(s) + // Default process is resolve + ( special || deferred.resolveWith )( that, args ); + } + }, + + // Only normal processors (resolve) catch and reject exceptions + process = special ? + mightThrow : + function() { + try { + mightThrow(); + } catch ( e ) { + + if ( jQuery.Deferred.exceptionHook ) { + jQuery.Deferred.exceptionHook( e, + process.stackTrace ); + } + + // Support: Promises/A+ section 2.3.3.3.4.1 + // https://promisesaplus.com/#point-61 + // Ignore post-resolution exceptions + if ( depth + 1 >= maxDepth ) { + + // Only substitute handlers pass on context + // and multiple values (non-spec behavior) + if ( handler !== Thrower ) { + that = undefined; + args = [ e ]; + } + + deferred.rejectWith( that, args ); + } + } + }; + + // Support: Promises/A+ section 2.3.3.3.1 + // https://promisesaplus.com/#point-57 + // Re-resolve promises immediately to dodge false rejection from + // subsequent errors + if ( depth ) { + process(); + } else { + + // Call an optional hook to record the stack, in case of exception + // since it's otherwise lost when execution goes async + if ( jQuery.Deferred.getStackHook ) { + process.stackTrace = jQuery.Deferred.getStackHook(); + } + window.setTimeout( process ); + } + }; + } + + return jQuery.Deferred( function( newDefer ) { + + // progress_handlers.add( ... ) + tuples[ 0 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onProgress ) ? + onProgress : + Identity, + newDefer.notifyWith + ) + ); + + // fulfilled_handlers.add( ... ) + tuples[ 1 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onFulfilled ) ? + onFulfilled : + Identity + ) + ); + + // rejected_handlers.add( ... ) + tuples[ 2 ][ 3 ].add( + resolve( + 0, + newDefer, + isFunction( onRejected ) ? + onRejected : + Thrower + ) + ); + } ).promise(); + }, + + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 5 ]; + + // promise.progress = list.add + // promise.done = list.add + // promise.fail = list.add + promise[ tuple[ 1 ] ] = list.add; + + // Handle state + if ( stateString ) { + list.add( + function() { + + // state = "resolved" (i.e., fulfilled) + // state = "rejected" + state = stateString; + }, + + // rejected_callbacks.disable + // fulfilled_callbacks.disable + tuples[ 3 - i ][ 2 ].disable, + + // rejected_handlers.disable + // fulfilled_handlers.disable + tuples[ 3 - i ][ 3 ].disable, + + // progress_callbacks.lock + tuples[ 0 ][ 2 ].lock, + + // progress_handlers.lock + tuples[ 0 ][ 3 ].lock + ); + } + + // progress_handlers.fire + // fulfilled_handlers.fire + // rejected_handlers.fire + list.add( tuple[ 3 ].fire ); + + // deferred.notify = function() { deferred.notifyWith(...) } + // deferred.resolve = function() { deferred.resolveWith(...) } + // deferred.reject = function() { deferred.rejectWith(...) } + deferred[ tuple[ 0 ] ] = function() { + deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments ); + return this; + }; + + // deferred.notifyWith = list.fireWith + // deferred.resolveWith = list.fireWith + // deferred.rejectWith = list.fireWith + deferred[ tuple[ 0 ] + "With" ] = list.fireWith; + } ); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( singleValue ) { + var + + // count of uncompleted subordinates + remaining = arguments.length, + + // count of unprocessed arguments + i = remaining, + + // subordinate fulfillment data + resolveContexts = Array( i ), + resolveValues = slice.call( arguments ), + + // the primary Deferred + primary = jQuery.Deferred(), + + // subordinate callback factory + updateFunc = function( i ) { + return function( value ) { + resolveContexts[ i ] = this; + resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; + if ( !( --remaining ) ) { + primary.resolveWith( resolveContexts, resolveValues ); + } + }; + }; + + // Single- and empty arguments are adopted like Promise.resolve + if ( remaining <= 1 ) { + adoptValue( singleValue, primary.done( updateFunc( i ) ).resolve, primary.reject, + !remaining ); + + // Use .then() to unwrap secondary thenables (cf. gh-3000) + if ( primary.state() === "pending" || + isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + + return primary.then(); + } + } + + // Multiple arguments are aggregated like Promise.all array elements + while ( i-- ) { + adoptValue( resolveValues[ i ], updateFunc( i ), primary.reject ); + } + + return primary.promise(); + } +} ); + + +// These usually indicate a programmer mistake during development, +// warn about them ASAP rather than swallowing them by default. +var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; + +jQuery.Deferred.exceptionHook = function( error, stack ) { + + // Support: IE 8 - 9 only + // Console exists when dev tools are open, which can happen at any time + if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { + window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + } +}; + + + + +jQuery.readyException = function( error ) { + window.setTimeout( function() { + throw error; + } ); +}; + + + + +// The deferred used on DOM ready +var readyList = jQuery.Deferred(); + +jQuery.fn.ready = function( fn ) { + + readyList + .then( fn ) + + // Wrap jQuery.readyException in a function so that the lookup + // happens at the time of error handling instead of callback + // registration. + .catch( function( error ) { + jQuery.readyException( error ); + } ); + + return this; +}; + +jQuery.extend( { + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + } +} ); + +jQuery.ready.then = readyList.then; + +// The ready event handler and self cleanup method +function completed() { + document.removeEventListener( "DOMContentLoaded", completed ); + window.removeEventListener( "load", completed ); + jQuery.ready(); +} + +// Catch cases where $(document).ready() is called +// after the browser event has already occurred. +// Support: IE <=9 - 10 only +// Older IE sometimes signals "interactive" too soon +if ( document.readyState === "complete" || + ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { + + // Handle it asynchronously to allow scripts the opportunity to delay ready + window.setTimeout( jQuery.ready ); + +} else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed ); +} + + + + +// Multifunctional method to get and set values of a collection +// The value/s can optionally be executed if it's a function +var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + len = elems.length, + bulk = key == null; + + // Sets many values + if ( toType( key ) === "object" ) { + chainable = true; + for ( i in key ) { + access( elems, fn, i, key[ i ], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, _key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < len; i++ ) { + fn( + elems[ i ], key, raw ? + value : + value.call( elems[ i ], i, fn( elems[ i ], key ) ) + ); + } + } + } + + if ( chainable ) { + return elems; + } + + // Gets + if ( bulk ) { + return fn.call( elems ); + } + + return len ? fn( elems[ 0 ], key ) : emptyGet; +}; + + +// Matches dashed string for camelizing +var rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g; + +// Used by camelCase as callback to replace() +function fcamelCase( _all, letter ) { + return letter.toUpperCase(); +} + +// Convert dashed to camelCase; used by the css and data modules +// Support: IE <=9 - 11, Edge 12 - 15 +// Microsoft forgot to hump their vendor prefix (#9572) +function camelCase( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); +} +var acceptData = function( owner ) { + + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); +}; + + + + +function Data() { + this.expando = jQuery.expando + Data.uid++; +} + +Data.uid = 1; + +Data.prototype = { + + cache: function( owner ) { + + // Check if the owner object already has a cache + var value = owner[ this.expando ]; + + // If not, create one + if ( !value ) { + value = {}; + + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return an empty object. + if ( acceptData( owner ) ) { + + // If it is a node unlikely to be stringify-ed or looped over + // use plain assignment + if ( owner.nodeType ) { + owner[ this.expando ] = value; + + // Otherwise secure it in a non-enumerable property + // configurable must be true to allow the property to be + // deleted when data is removed + } else { + Object.defineProperty( owner, this.expando, { + value: value, + configurable: true + } ); + } + } + } + + return value; + }, + set: function( owner, data, value ) { + var prop, + cache = this.cache( owner ); + + // Handle: [ owner, key, value ] args + // Always use camelCase key (gh-2257) + if ( typeof data === "string" ) { + cache[ camelCase( data ) ] = value; + + // Handle: [ owner, { properties } ] args + } else { + + // Copy the properties one-by-one to the cache object + for ( prop in data ) { + cache[ camelCase( prop ) ] = data[ prop ]; + } + } + return cache; + }, + get: function( owner, key ) { + return key === undefined ? + this.cache( owner ) : + + // Always use camelCase key (gh-2257) + owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ]; + }, + access: function( owner, key, value ) { + + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ( ( key && typeof key === "string" ) && value === undefined ) ) { + + return this.get( owner, key ); + } + + // When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, + cache = owner[ this.expando ]; + + if ( cache === undefined ) { + return; + } + + if ( key !== undefined ) { + + // Support array or space separated string of keys + if ( Array.isArray( key ) ) { + + // If key is an array of keys... + // We always set camelCase keys, so remove that. + key = key.map( camelCase ); + } else { + key = camelCase( key ); + + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + key = key in cache ? + [ key ] : + ( key.match( rnothtmlwhite ) || [] ); + } + + i = key.length; + + while ( i-- ) { + delete cache[ key[ i ] ]; + } + } + + // Remove the expando if there's no more data + if ( key === undefined || jQuery.isEmptyObject( cache ) ) { + + // Support: Chrome <=35 - 45 + // Webkit & Blink performance suffers when deleting properties + // from DOM nodes, so set to undefined instead + // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) + if ( owner.nodeType ) { + owner[ this.expando ] = undefined; + } else { + delete owner[ this.expando ]; + } + } + }, + hasData: function( owner ) { + var cache = owner[ this.expando ]; + return cache !== undefined && !jQuery.isEmptyObject( cache ); + } +}; +var dataPriv = new Data(); + +var dataUser = new Data(); + + + +// Implementation Summary +// +// 1. Enforce API surface and semantic compatibility with 1.9.x branch +// 2. Improve the module's maintainability by reducing the storage +// paths to a single mechanism. +// 3. Use the same single mechanism to support "private" and "user" data. +// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) +// 5. Avoid exposing implementation details on user objects (eg. expando properties) +// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 + +var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, + rmultiDash = /[A-Z]/g; + +function getData( data ) { + if ( data === "true" ) { + return true; + } + + if ( data === "false" ) { + return false; + } + + if ( data === "null" ) { + return null; + } + + // Only convert to a number if it doesn't change the string + if ( data === +data + "" ) { + return +data; + } + + if ( rbrace.test( data ) ) { + return JSON.parse( data ); + } + + return data; +} + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = getData( data ); + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + dataUser.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} + +jQuery.extend( { + hasData: function( elem ) { + return dataUser.hasData( elem ) || dataPriv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return dataUser.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + dataUser.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to dataPriv methods, these can be deprecated. + _data: function( elem, name, data ) { + return dataPriv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + dataPriv.remove( elem, name ); + } +} ); + +jQuery.fn.extend( { + data: function( key, value ) { + var i, name, data, + elem = this[ 0 ], + attrs = elem && elem.attributes; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = dataUser.get( elem ); + + if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) { + i = attrs.length; + while ( i-- ) { + + // Support: IE 11 only + // The attrs elements can be null (#14894) + if ( attrs[ i ] ) { + name = attrs[ i ].name; + if ( name.indexOf( "data-" ) === 0 ) { + name = camelCase( name.slice( 5 ) ); + dataAttr( elem, name, data[ name ] ); + } + } + } + dataPriv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each( function() { + dataUser.set( this, key ); + } ); + } + + return access( this, function( value ) { + var data; + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + + // Attempt to get data from the cache + // The key will always be camelCased in Data + data = dataUser.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, key ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each( function() { + + // We always store the camelCased key + dataUser.set( this, key, value ); + } ); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each( function() { + dataUser.remove( this, key ); + } ); + } +} ); + + +jQuery.extend( { + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = dataPriv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || Array.isArray( data ) ) { + queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // Clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // Not public - generate a queueHooks object, or return the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { + empty: jQuery.Callbacks( "once memory" ).add( function() { + dataPriv.remove( elem, [ type + "queue", key ] ); + } ) + } ); + } +} ); + +jQuery.fn.extend( { + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[ 0 ], type ); + } + + return data === undefined ? + this : + this.each( function() { + var queue = jQuery.queue( this, type, data ); + + // Ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + } ); + }, + dequeue: function( type ) { + return this.each( function() { + jQuery.dequeue( this, type ); + } ); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = dataPriv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +} ); +var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source; + +var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ); + + +var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; + +var documentElement = document.documentElement; + + + + var isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ); + }, + composed = { composed: true }; + + // Support: IE 9 - 11+, Edge 12 - 18+, iOS 10.0 - 10.2 only + // Check attachment across shadow DOM boundaries when possible (gh-3504) + // Support: iOS 10.0-10.2 only + // Early iOS 10 versions support `attachShadow` but not `getRootNode`, + // leading to errors. We need to check for `getRootNode`. + if ( documentElement.getRootNode ) { + isAttached = function( elem ) { + return jQuery.contains( elem.ownerDocument, elem ) || + elem.getRootNode( composed ) === elem.ownerDocument; + }; + } +var isHiddenWithinTree = function( elem, el ) { + + // isHiddenWithinTree might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + + // Inline style trumps all + return elem.style.display === "none" || + elem.style.display === "" && + + // Otherwise, check computed style + // Support: Firefox <=43 - 45 + // Disconnected elements can have computed display: none, so first confirm that elem is + // in the document. + isAttached( elem ) && + + jQuery.css( elem, "display" ) === "none"; + }; + + + +function adjustCSS( elem, prop, valueParts, tween ) { + var adjusted, scale, + maxIterations = 20, + currentValue = tween ? + function() { + return tween.cur(); + } : + function() { + return jQuery.css( elem, prop, "" ); + }, + initial = currentValue(), + unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + rcssNum.exec( jQuery.css( elem, prop ) ); + + if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { + + // Support: Firefox <=54 + // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) + initial = initial / 2; + + // Trust units reported by jQuery.css + unit = unit || initialInUnit[ 3 ]; + + // Iteratively approximate from a nonzero starting point + initialInUnit = +initial || 1; + + while ( maxIterations-- ) { + + // Evaluate and update our best guess (doubling guesses that zero out). + // Finish if the scale equals or crosses 1 (making the old*new product non-positive). + jQuery.style( elem, prop, initialInUnit + unit ); + if ( ( 1 - scale ) * ( 1 - ( scale = currentValue() / initial || 0.5 ) ) <= 0 ) { + maxIterations = 0; + } + initialInUnit = initialInUnit / scale; + + } + + initialInUnit = initialInUnit * 2; + jQuery.style( elem, prop, initialInUnit + unit ); + + // Make sure we update the tween properties later on + valueParts = valueParts || []; + } + + if ( valueParts ) { + initialInUnit = +initialInUnit || +initial || 0; + + // Apply relative offset (+=/-=) if specified + adjusted = valueParts[ 1 ] ? + initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] : + +valueParts[ 2 ]; + if ( tween ) { + tween.unit = unit; + tween.start = initialInUnit; + tween.end = adjusted; + } + } + return adjusted; +} + + +var defaultDisplayMap = {}; + +function getDefaultDisplay( elem ) { + var temp, + doc = elem.ownerDocument, + nodeName = elem.nodeName, + display = defaultDisplayMap[ nodeName ]; + + if ( display ) { + return display; + } + + temp = doc.body.appendChild( doc.createElement( nodeName ) ); + display = jQuery.css( temp, "display" ); + + temp.parentNode.removeChild( temp ); + + if ( display === "none" ) { + display = "block"; + } + defaultDisplayMap[ nodeName ] = display; + + return display; +} + +function showHide( elements, show ) { + var display, elem, + values = [], + index = 0, + length = elements.length; + + // Determine new display value for elements that need to change + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + display = elem.style.display; + if ( show ) { + + // Since we force visibility upon cascade-hidden elements, an immediate (and slow) + // check is required in this first loop unless we have a nonempty display value (either + // inline or about-to-be-restored) + if ( display === "none" ) { + values[ index ] = dataPriv.get( elem, "display" ) || null; + if ( !values[ index ] ) { + elem.style.display = ""; + } + } + if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) { + values[ index ] = getDefaultDisplay( elem ); + } + } else { + if ( display !== "none" ) { + values[ index ] = "none"; + + // Remember what we're overwriting + dataPriv.set( elem, "display", display ); + } + } + } + + // Set the display of the elements in a second loop to avoid constant reflow + for ( index = 0; index < length; index++ ) { + if ( values[ index ] != null ) { + elements[ index ].style.display = values[ index ]; + } + } + + return elements; +} + +jQuery.fn.extend( { + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each( function() { + if ( isHiddenWithinTree( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + } ); + } +} ); +var rcheckableType = ( /^(?:checkbox|radio)$/i ); + +var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]*)/i ); + +var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); + + + +( function() { + var fragment = document.createDocumentFragment(), + div = fragment.appendChild( document.createElement( "div" ) ), + input = document.createElement( "input" ); + + // Support: Android 4.0 - 4.3 only + // Check state lost if the name is set (#11217) + // Support: Windows Web Apps (WWA) + // `name` and `type` must use .setAttribute for WWA (#14901) + input.setAttribute( "type", "radio" ); + input.setAttribute( "checked", "checked" ); + input.setAttribute( "name", "t" ); + + div.appendChild( input ); + + // Support: Android <=4.1 only + // Older WebKit doesn't clone checked state correctly in fragments + support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE <=11 only + // Make sure textarea (and checkbox) defaultValue is properly cloned + div.innerHTML = ""; + support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; + + // Support: IE <=9 only + // IE <=9 replaces "; + support.option = !!div.lastChild; +} )(); + + +// We have to close these tags to support XHTML (#13200) +var wrapMap = { + + // XHTML parsers do not magically insert elements in the + // same way that tag soup parsers do. So we cannot shorten + // this by omitting or other required elements. + thead: [ 1, "", "
" ], + col: [ 2, "", "
" ], + tr: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + +{% endmacro %} \ No newline at end of file diff --git a/_static/windturbines.png b/_static/windturbines.png new file mode 100644 index 00000000..1f5e441b Binary files /dev/null and b/_static/windturbines.png differ diff --git a/_static/yaml_launcher.png b/_static/yaml_launcher.png new file mode 100644 index 00000000..34688093 Binary files /dev/null and b/_static/yaml_launcher.png differ diff --git a/background/index.html b/background/index.html new file mode 100644 index 00000000..88a43d2f --- /dev/null +++ b/background/index.html @@ -0,0 +1,388 @@ + + + + + + + + +Background — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Background#

+

Lumen’s Background pages discuss key topics at a high level and provide useful context for design decisions.

+ +
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/background/lumen_in_python.html b/background/lumen_in_python.html new file mode 100644 index 00000000..b1e5b747 --- /dev/null +++ b/background/lumen_in_python.html @@ -0,0 +1,387 @@ + + + + + + + + +Lumen in Python — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Lumen in Python#

+
+

What is this page about?

+

This page discusses the motivation and use-cases for Lumen’s Python APIs.

+
+

Under construction

+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/background/pipeline_branching.html b/background/pipeline_branching.html new file mode 100644 index 00000000..153a2c0b --- /dev/null +++ b/background/pipeline_branching.html @@ -0,0 +1,394 @@ + + + + + + + + +Pipeline Branching — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Pipeline Branching#

+
+

What is this page about?

+

This page discusses what a pipeline branch is and when you might need one.

+
+

A Lumen [Pipeline]lumen.pipeline.Pipeline consists of Filter and Transform components. These manipulations of the data are typically applied to a data Source to drive one or more visual outputs. However, a [Pipeline]lumen.pipeline.Pipeline can also branch off of another [Pipeline]lumen.pipeline.Pipeline allowing for further data manipulation that exists only on the branch, while retaining the shared computations up to that branching point. This allows for the creation of View components of the same underlying source data, but at different steps in data processing. For instance, you may want to display a table of filtered data alongside a view of aggregated data.

+ +
+
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/comparison.html b/comparison.html new file mode 100644 index 00000000..01ed10e9 --- /dev/null +++ b/comparison.html @@ -0,0 +1,405 @@ + + + + + + + + +Lumen compared to other dashboarding tools — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Lumen compared to other dashboarding tools#

+

Here we will first talk about the most fundamental differences that set Lumen apart from other tools, and then compare Lumen to specific competitive or complementary tools so that it is clear how Lumen fits in.

+
+

General considerations#

+

As listed at pyviz.org/tools and pyviz.org/dashboarding, there are many other Python-based open-source tools for building analytics dashboards. There are hundreds more if you consider commercial tools or ones not based on Python. How can you choose between Lumen and all these other tools?

+

What sets Lumen apart is that it lets anyone on your team make apps that build on custom Python code, without requiring that everyone learn Python. Lumen is a great choice if you have some people on a team or in an organization who can write custom Python code that does precisely what your organization needs in a particular case, whether that’s connecting to some custom data source, applying some custom transform or analysis method, viewing things in some custom chart or type of table, or literally anything else you can do in Python (which is literally anything!). Ideally those Python programmers will be using the Python ecosystem to do their daily work, using tools like those from HoloViz, and when they build custom functionality for their own work, that same functionality can be made available to non-Python users using Lumen. That way everyone in the organization can benefit from all of the innovation being developed.

+

Of course, traditional BI analytics tools like Tableau, PowerBI, or Superset also let non-technical or non-Python users with domain knowledge build visualizations and dashboards. These longer-established BI tools will generally have a more polished and friendly user interface than Lumen has, meeting more of the needs of less-technical users with no coding at all. If those tools do what’s required, use them!

+

But what do you do when you reach the limits of those tools? Many of them do include Python or other scripting tools for that purpose, but generally as an add-on that’s not fully integrated. Unlike those other tools, Lumen itself is built directly on the scientific Python stack, such as the Intake and Panel libraries, which lets Lumen (a) provide a very rich basis of functionality to non-technical users comparable to what is available to Python users, and (b) treat custom functionality as a “first class citizen”, provided exactly the same way as any of Lumen’s native functionality. That way an organization can customize anything, with new customizations requiring Python code contributed by the Python experts and then immediately usable by every Lumen user, technical or not.

+

Lumen and the rest of the HoloViz and scientific Python stack are thus designed to meet all of the needs of an organization, no matter how specialized or esoteric those needs are. By design, standard BI tools will do a great job at the typical needs common across a market segment, but won’t do as well at providing “headroom” or a “release valve” for those rarer but individually important bits that can otherwise dominate a workflow or greatly reduce its effectiveness.

+
+
+

Tableau, PowerBI, Looker, Spotfire, etc.#

+

The leading commercial dashboarding tools focus first on providing an intuitive, full-featured user interface for building apps without explicit coding, which makes them good choices for the needs of less-technical users. Unlike open-source tools like Lumen, they also include commercial support, which again can be important for the same audience. They also provide a wide swath of out-of-the-box data integrations, which can save a lot of development time for accessing supported data sources. When you reach the limits of the already-provided functionality, these tools even let you provide custom Python code that you can integrate into your applications. Finally, the tools generally include deployment platforms so that users can share deployed apps with each other in the organization, while Lumen apps need a separate deployment system.

+

So if you can afford these tools, what’s the catch? Depends on your organization’s mix of data science and analytics users. If you have an organization dominated by non-technical analytics users, plus maybe a few Python programmers to support them, then you can make good use of the commercial tools plus a little bit of customization on the side as needed, with everything organized around the commercial tool. Lumen is designed for the opposite situation: it takes the power available in the Python open-source ecosystem, and makes much of it available immediately (plus almost anything else available with small customizations) to non-technical users. So Lumen is a good choice if you have a successful Python-based data science team driving innovation in your organization, and now your problem is how you can make them have a bigger impact on your whole organization’s processes and decision making. Lumen is designed for the case where the Python data-science team (not the commercial tool vendors!) owns the process of analytics and visualization in your organization, either directly (in their Jupyter Notebooks, Panel or Voila apps, etc.) or by making functionality available to all through Lumen. The Python users can then use Python tools through Jupyter or scripts as they normally do, with full power over their machine-learning or analytic code, while then being able to publish those same components for non-technical users when they are developed. Non-technical users with domain knowledge can then apply these tools to their problems using Lumen, feeding back requirements and desired improvements to the Python team. This way domain-specific ideas can flow freely between domain experts and the data-science team, while Python-based solutions can flow freely out from the data-science team, without costly and time-consuming artificial barriers from switching from one tool or ecosystem to the other at such departmental boundaries.

+
+
+

Apache Superset#

+

Like Tableau and other commercial tools, Superset provides a very polished environment for exploring data, and like Lumen, Superset is an open-source Python+JavaScript tool that anyone can install. Compared to Lumen, however, Superset is a very heavyweight tool (despite being billed as “lightweight”), making it difficult for a Python data-science team to customize. Superset includes a database that needs installation and management, along with various user management and account features that make it difficult for a single user to install and make use of Superset locally; it’s primarily geared towards departments and companies to install with dedicated administers to maintain it. Lumen can easily be installed by an individual user, immediately giving the ability to use text-based specifications to build apps and dashboards, without necessarily requiring the central administrators to agree to support it. Lumen is also inherently extensible, accepting custom-written or existing Python-ecosystem transform, filter, and view components on the same basis as its own components, while Superset’s Python configurability is limited to specific bits of customizable behavior that a user needs to implement just for Superset. Overall, Superset focuses on providing its own world or platform to live in, while Lumen focuses narrowly on exposing the power of existing and custom Python data science code within an interface for non-technical users.

+
+
+

Datasette#

+

Like Superset and the commercial packages, Datasette provides a web-based interface for exploring data and selecting values to plot or display in tables. As a more specialized open-source tool, Datasette’s UI is not as extensive or polished as the commercial tools, but the functionality provided is nonetheless powerful because it is based around an underlying relational database.

+

In contrast, Lumen does not require that the data being processed be inserted into a database, and is thus more similar to working with a data lake than with a database (for both good and bad!). With Lumen, the data remains wherever it was originally located, without necessarily being processed before the app begins, which is a decentralized approach that can be messier but works well for querying live data sources and for large, remote datasets processed lazily. Because only the required subsets of the data are ever pulled into the Lumen app, big-data processing tools and workflows like Datashader can be used with Lumen, where the data is read as-needed from an efficient file format like Parquet. This approach makes Lumen useful for a broad range of data sizes not suitable for a standard relational database approach.

+
+
+

Perspective#

+

Like the other tools listed above, Perspective provides a GUI interface for selecting dimensions and columns for plots and tables, making it simple to explore columnar data. Like the non-Lumen HoloViz tools, Perspective is usable in Jupyter, which helps integrate configurable analytics into an otherwise custom workflow. Perspective is thus an alternative to Lumen in some cases, but we suggest using both in combination: Use Perspective to design plots, then Lumen for the full workflow consisting of data sources, arbitrary transforms, and laying out the results into a polished deployable application.

+
+
+

Panel and Bokeh#

+

Like Lumen, Panel and the underlying Bokeh library let users build dashboards that expose the power of the Python data-science ecosystem. Panel and Bokeh do so using a Python programming interface, with users writing Python code to configure each component and the overall dashboard. Like Lumen, Panel’s programming model is declarative in nature, but it also allows specification of arbitrary Python code as part of the configuration of each component, and it requires custom non-declarative Python code for specifying data sources and transformations. Lumen is a purely declarative approach that provides a text-based language for building all the components of a Panel app, keeping all Python code separate from the configuration of a particular dashboard. Lumen is thus a good choice for users who want the power of Panel and Bokeh but are not Python programmers, and is a particularly good choice for people working on a team with Panel users who can extend Lumen’s capabilities and make the custom additions available to non-Python users.

+
+
+

Dash, Streamlit, Voila+IPyWidgets#

+

Lumen’s underlying Panel library is one of a number of dashboarding technologies available in Python. Just as Lumen is built on Panel, declarative text-based user interfaces could be developed for the other availble dashboarding tools, such as Dash, Streamlit, or Voila+IPyWidgets. For data-science teams built around one of these other dashboarding tools, such a declarative interface could play a similar role to Lumen for that developer and user commnunity. In the meantime, because Panel supports nearly every common visualization tool available for Python, Lumen can already be useful as a declarative interface providing the power of the same underlying Python data-science libraries that will be used in those dashboarding tools, such as Plotly, Matplotlib, bqplot, and ipywidgets, all of which can be used in Panel apps and thus potentially with Lumen.

+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/gallery/bikes.html b/gallery/bikes.html new file mode 100644 index 00000000..846632f4 --- /dev/null +++ b/gallery/bikes.html @@ -0,0 +1,490 @@ + + + + + + + + +Transport for London: Bike Point Occupancy — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Transport for London: Bike Point Occupancy#

+ +
config:
+  title: "Transport for London: Bike Station Occupancy"
+  layout: column
+variables:
+  TFL_API_KEY:
+    type: constant
+    value: a1c692de000b4944af55f59d8e849915
+sources:
+  stations:
+    type: json
+    shared: true
+    tables:
+      stations: "https://api.tfl.gov.uk/BikePoint/"
+  occupancy:
+    type: json
+    chunk_size: 15
+    cache_dir: cache
+    tables:
+      occupancy: "https://api.tfl.gov.uk/Occupancy/BikePoints/${stations.stations.id}?app_key=${variables.TFL_API_KEY}"
+  station_occupancy:
+    type: join
+    sources: [stations, occupancy]
+    tables:
+      station_occupancy:
+        - source: stations
+          table: stations
+          index: id
+        - source: occupancy
+          table: occupancy
+          index: id
+pipelines:
+  station_occupancy:
+    source: station_occupancy
+    table: station_occupancy
+    filters:
+      - type: widget
+        field: bikesCount
+      - type: widget
+        field: totalDocks
+      - type: constant
+        field: lat
+        value: [50, 52]
+      - type: constant
+        field: lon
+        value: [-1, 1]
+    transforms:
+      - type: columns
+        columns: [commonName, bikesCount, totalDocks, lat, lon]
+      - type: project_lnglat
+        latitude: lat
+        longitude: lon
+  selected:
+    pipeline: station_occupancy
+    filters:
+      - type: param
+        parameter: locations.selection_expr
+layouts:
+  - title: "Occupancy"
+    layout: [[locations, table], [count_hist, total_hist]]
+    views:
+      locations:
+        type: hvplot
+        pipeline: station_occupancy
+        kind: points
+        x: lon
+        y: lat
+        hover_cols: [commonName]
+        tiles: EsriStreet
+        responsive: true
+        height: 500
+        color: bikesCount
+        line_color: black
+        xaxis: null
+        yaxis: null
+        framewise: false
+        selection_group: bikes
+      table:
+        type: table
+        pipeline: selected
+        height: 500
+        margin: [0, 100]
+        hidden_columns: [lat, lon]
+        show_index: false
+        sizing_mode: stretch_width
+      count_hist:
+        type: hvplot
+        pipeline: station_occupancy
+        kind: hist
+        y: bikesCount
+        responsive: true
+        height: 300
+        streaming: true
+        selection_group: bikes
+      total_hist:
+        type: hvplot
+        pipeline: station_occupancy
+        kind: hist
+        y: totalDocks
+        responsive: true
+        height: 300
+        streaming: true
+        selection_group: bikes
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/gallery/earthquakes.html b/gallery/earthquakes.html new file mode 100644 index 00000000..d20d8d0d --- /dev/null +++ b/gallery/earthquakes.html @@ -0,0 +1,459 @@ + + + + + + + + +Earthquakes — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Earthquakes#

+ +
config:
+  title: Earthquake Dashboard
+  theme: dark
+sources:
+  earthquakes:
+    type: file
+    cache_per_query: false
+    tables:
+      earthquakes: ["https://earthquake.usgs.gov/fdsnws/event/1/query?format=csv", "csv"]
+pipelines:
+  earthquakes:
+    source: earthquakes
+    table: earthquakes
+    filters:
+      - type: widget
+        field: type
+      - type: widget
+        field: mag
+      - type: widget
+        field: depth
+    transforms:
+      - type: columns
+        columns:
+          - time
+          - longitude
+          - latitude
+          - type
+          - place
+          - mag
+          - depth
+          - rms
+      - type: project_lnglat
+        longitude: longitude
+        latitude: latitude
+  selected:
+    pipeline: earthquakes
+    filters:
+      - type: param
+        parameter: map.selection_expr
+layouts:
+  - title: Earthquakes
+    views:
+      map:
+        type: hvplot
+        pipeline: earthquakes
+        kind: points
+        x: longitude
+        y: latitude
+        tiles: ESRI
+        responsive: true
+        height: 500
+        fill_color: null
+        line_color: white
+        xaxis: null
+        yaxis: null
+        selection_group: earthquakes
+        streaming: true
+        hover: false
+      table:
+        type: table
+        pipeline: selected
+        hidden_columns:
+          - longitude
+          - latitude
+        page_size: 16
+        pagination: remote
+        sizing_mode: stretch_width
+        show_index: false
+        theme: midnight
+      mag_hist:
+        type: hvplot
+        pipeline: earthquakes
+        kind: hist
+        y: mag
+        fill_color: white
+        responsive: true
+        height: 250
+        selection_group: earthquakes
+        streaming: true
+      depth_hist:
+        type: hvplot
+        pipeline: earthquakes
+        kind: hist
+        y: depth
+        fill_color: white
+        responsive: true
+        height: 250
+        selection_group: earthquakes
+        streaming: true
+      rms_hist:
+        type: hvplot
+        pipeline: earthquakes
+        kind: hist
+        y: rms
+        fill_color: white
+        responsive: true
+        height: 250
+        selection_group: earthquakes
+        streaming: true
+    refresh_rate: 60000
+    layout: [[0, 1], [2, 3, 4]]
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/gallery/index.html b/gallery/index.html new file mode 100644 index 00000000..11c7d700 --- /dev/null +++ b/gallery/index.html @@ -0,0 +1,444 @@ + + + + + + + + +Gallery — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+ +
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/gallery/nyc_taxi.html b/gallery/nyc_taxi.html new file mode 100644 index 00000000..09c53aa0 --- /dev/null +++ b/gallery/nyc_taxi.html @@ -0,0 +1,458 @@ + + + + + + + + +NYC Taxi — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

NYC Taxi#

+

+
config:
+  title: "NYC Taxi Trips"
+sources:
+  nyc_taxi:
+    type: duckdb
+    shared: true
+    uri: ":memory:"
+    tables:
+      nyc_taxi: "read_parquet('s3://datasets.holoviz.org/nyc_taxi/v2/nyc_taxi_wide.parq')"
+    initializers:
+      - "INSTALL httpfs;"
+      - "LOAD httpfs;"
+layouts:
+  - title: Trip Data
+    source: nyc_taxi
+    views:
+      - table: nyc_taxi
+        type: hvplot
+        kind: points
+        x: pickup_x
+        y: pickup_y
+        tiles: EsriStreet
+        rasterize: true
+        cnorm: eq_hist
+        responsive: true
+        height: 500
+        colorbar: false
+        selection_group: taxi
+        xaxis: null
+        yaxis: null
+      - table: nyc_taxi
+        type: hvplot
+        kind: points
+        x: dropoff_x
+        y: dropoff_y
+        tiles: EsriStreet
+        rasterize: true
+        cnorm: eq_hist
+        responsive: true
+        height: 500
+        colorbar: false
+        selection_group: taxi
+        xaxis: null
+        yaxis: null
+      - table: nyc_taxi
+        type: hvplot
+        kind: hist
+        y: trip_distance
+        bin_range: [0, 20]
+        height: 300
+        responsive: true
+        selection_group: taxi
+      - table: nyc_taxi
+        type: hvplot
+        kind: hist
+        y: tip_amount
+        bin_range: [0, 20]
+        height: 300
+        responsive: true
+        selection_group: taxi
+      - table: nyc_taxi
+        type: hvplot
+        kind: hist
+        y: fare_amount
+        bin_range: [0, 50]
+        height: 300
+        responsive: true
+        selection_group: taxi
+    sizing_mode: stretch_both
+    layout: [[0, 1], [2, 3, 4]]
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/gallery/penguins.html b/gallery/penguins.html new file mode 100644 index 00000000..1f91c428 --- /dev/null +++ b/gallery/penguins.html @@ -0,0 +1,466 @@ + + + + + + + + +Penguins — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Penguins#

+ +
config:
+  title: Palmer Penguins
+  theme: dark
+  layout: tabs
+sources:
+  penguins:
+    type: file
+    cache_per_query: false
+    cache_dir: ./cache
+    tables:
+      penguins: https://datasets.holoviz.org/penguins/v1/penguins.csv
+pipelines:
+  penguins:
+    source: penguins
+    table: penguins
+    filters:
+      species:
+        type: widget
+        field: species
+      island:
+        type: widget
+        field: island
+      sex:
+        type: widget
+        field: sex
+  selected:
+    pipeline: penguins
+    filters:
+      expr:
+        type: param
+        parameter: scatter.selection_expr
+layouts:
+  - title: Plots
+    pipeline: penguins
+    views:
+      scatter:
+        type: hvplot
+        kind: points
+        x: bill_length_mm
+        y: bill_depth_mm
+        color: species
+        responsive: true
+        height: 350
+        selection_group: penguin
+      depth_hist:
+        type: hvplot
+        kind: hist
+        y: bill_length_mm
+        responsive: true
+        height: 350
+        selection_group: penguin
+      length_hist:
+        type: hvplot
+        kind: hist
+        y: bill_depth_mm
+        responsive: true
+        height: 350
+        selection_group: penguin
+      mass_hist:
+        type: hvplot
+        kind: hist
+        y: body_mass_g
+        responsive: true
+        height: 350
+        selection_group: penguin
+    layout: [[scatter], [depth_hist, length_hist, mass_hist]]
+    sizing_mode: stretch_width
+  - title: Table
+    pipeline: selected
+    views:
+      table:
+        type: table
+        layout: fit_data_fill
+        show_index: false
+        theme: midnight
+        sizing_mode: stretch_both
+        pagination: remote
+        page_size: 50
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/gallery/precip.html b/gallery/precip.html new file mode 100644 index 00000000..7d13e691 --- /dev/null +++ b/gallery/precip.html @@ -0,0 +1,430 @@ + + + + + + + + +Precipitation — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Precipitation#

+ +
config:
+  title: "Precipitation Dashboard"
+sources:
+  rockies:
+    type: intake
+    shared: true
+    cache_dir: cache
+    catalog:
+      sources:
+        southern_rockies:
+          driver: csv
+          args:
+            urlpath: 's3://datasets.holoviz.org/precipitation/v1/SRLCC_{emissions}_Precip_{model}.csv'
+            csv_kwargs:
+              skiprows: 3
+              names: ['time', 'precip']
+              parse_dates: ['time']
+            storage_options:
+              anon: true
+pipelines:
+  rockies:
+    source: rockies
+    table: southern_rockies
+    filters:
+      - type: widget
+        field: model
+      - type: widget
+        field: model
+layouts:
+  - title: Southern Rockies
+    pipeline: rockies
+    facet:
+      by: [model]
+      layout: column
+    views:
+      - type: hvplot
+        kind: line
+        x: time
+        y: precip
+        by: [model, emissions]
+        min_height: 200
+        responsive: true
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/gallery/seattle.html b/gallery/seattle.html new file mode 100644 index 00000000..e4cc7f17 --- /dev/null +++ b/gallery/seattle.html @@ -0,0 +1,454 @@ + + + + + + + + +Seattle Weather — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Seattle Weather#

+ +
config:
+  title: Altair Seattle Weather
+  reloadable: false
+  sync_with_url: true
+sources:
+  seattle:
+    type: file
+    cache_per_query: false
+    tables:
+      weather: https://raw.githubusercontent.com/vega/vega/main/docs/data/seattle-weather.csv
+    kwargs:
+      parse_dates: [date]
+pipelines:
+  seattle:
+    source: seattle
+    table: weather
+    filters:
+      - type: widget
+        field: date
+      - type: widget
+        field: weather
+layouts:
+  - title: Seattle Weather
+    pipeline: seattle
+    views:
+      - type: altair
+        marker: rect
+        chart:
+          title: 2012-2015 Daily High Temperature (F) in Seattle, WA
+        x:
+          shorthand: date(date):O
+          title: Day
+        y:
+          shorthand: month(date):O
+          title: Month
+        encode:
+          color:
+            shorthand: max(temp_max):Q
+            scale:
+              scheme: inferno
+        properties:
+          width: container
+      - type: altair
+        x:
+          shorthand: monthdate(date):T
+          title: Date
+        y:
+          shorthand: temp_max:Q
+          title: 'Maximum Daily Temperature (C)'
+        marker: point
+        encode:
+          color: weather:N
+          size:
+            shorthand: precipitation:Q
+            scale: [5, 200]
+        properties:
+          width: container
+      - type: altair
+        x: count()
+        y: weather:N
+        encode:
+          color: weather:N
+        marker: bar
+        properties:
+          width: container
+    sizing_mode: stretch_width
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/gallery/windturbines.html b/gallery/windturbines.html new file mode 100644 index 00000000..c9b898a3 --- /dev/null +++ b/gallery/windturbines.html @@ -0,0 +1,492 @@ + + + + + + + + +Windturbines — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Windturbines#

+ +
config:
+  title: Windturbine Database Viewer
+  theme: dark
+  template: material
+sources:
+  windturbines:
+    type: duckdb
+    cache_dir: ./cache
+    uri: ":memory:"
+    tables:
+      windturbines: "read_parquet('s3://datasets.holoviz.org/windturbines/v1/windturbines.parq')"
+    initializers:
+      - "INSTALL httpfs;"
+      - "LOAD httpfs;"
+variables:
+  state:
+    type: url
+  color_by:
+    type: widget
+    kind: panel.widgets.Select
+    options:
+      - t_manu
+      - t_year
+    value: t_manu
+pipelines:
+  continental:
+    source: windturbines
+    filters:
+      - type: constant
+        field: xlong
+        value: [-125, -66]
+      - type: constant
+        field: ylat
+        value: [24, 50]
+      - type: constant
+        field: t_state
+        value: $variables.state
+  windturbines:
+    pipeline: continental
+    filters:
+      - type: widget
+        field: t_state
+      - type: widget
+        field: t_manu
+      - type: widget
+        field: p_year
+      - type: widget
+        field: t_cap
+  filtered:
+    pipeline: windturbines
+    filters:
+      - type: param
+        parameter: points.selection_expr
+  table:
+    pipeline: filtered
+    transforms:
+      - type: columns
+        columns: [t_state, t_county, p_name, t_manu, t_model, p_year, t_cap, t_hh, t_rd, t_rsa, t_ttlh]
+  count:
+    pipeline: filtered
+    transforms:
+      - type: count
+      - type: rename
+        columns:
+          case_id: Count
+  sum:
+    pipeline: filtered
+    transforms:
+      - type: columns
+        columns:
+          - t_cap
+      - type: sum
+      - type: eval
+        expr: "Capacity = table.t_cap / 10**6"
+layouts:
+  - title: Overview
+    layout: [[points, [count, capacity]], [table, [cap_hist, year_hist]]]
+    sizing_mode: stretch_width
+    views:
+      points:
+        type: hvplot
+        kind: points
+        pipeline: windturbines
+        x: easting
+        y: northing
+        c: $variables.color_by
+        tiles: ESRI
+        rasterize: true
+        dynspread: true
+        responsive: true
+        height: 500
+        xaxis: null
+        yaxis: null
+        streaming: true
+        selection_group: windturbines
+      table:
+        type: table
+        pipeline: table
+        header_filters: true
+        sizing_mode: stretch_width
+        height: 500
+        page_size: 20
+      count:
+        type: indicator
+        indicator: number
+        pipeline: count
+        field: Count
+        format: '{value:,}'
+        width: 300
+        default_color: white
+      capacity:
+        type: indicator
+        indicator: number
+        pipeline: sum
+        field: Capacity
+        format: '{value:.0f} TWh'
+        width: 300
+        default_color: white
+      cap_hist:
+        type: hvplot
+        kind: hist
+        pipeline: windturbines
+        y: t_cap
+        frame_width: 400
+        height: 250
+        selection_group: windturbines
+      year_hist:
+        type: hvplot
+        kind: hist
+        pipeline: windturbines
+        y: p_year
+        frame_width: 400
+        height: 250
+        selection_group: windturbines
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/genindex.html b/genindex.html new file mode 100644 index 00000000..e177beba --- /dev/null +++ b/genindex.html @@ -0,0 +1,1075 @@ + + + + + + + +Index — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+ +
+

Index

+
+A + | B + | C + | D + | E + | F + | G + | H + | I + | J + | L + | M + | P + | Q + | R + | S + | T + | U + | V + | W + | Y +
+

A

+ + + +
+

B

+ + +
+

C

+ + + +
+

D

+ + + +
+

E

+ + + +
+

F

+ + + +
+

G

+ + + +
+

H

+ + + +
+

I

+ + + +
+

J

+ + + +
+

L

+ + +
+

M

+ + +
+

P

+ + + +
+

Q

+ + +
+

R

+ + + +
+

S

+ + + +
+

T

+ + + +
+

U

+ + + +
+

V

+ + + +
+

W

+ + + +
+

Y

+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/getting_started/build_dashboard.html b/getting_started/build_dashboard.html new file mode 100644 index 00000000..fa404a31 --- /dev/null +++ b/getting_started/build_dashboard.html @@ -0,0 +1,759 @@ + + + + + + + + +Build a dashboard — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Build a dashboard#

+
+

What is the purpose of this page?

+

This tutorial is meant to get your hands dirty with building a Lumen dashboard. Don’t worry about understanding everything just yet - your only obligation is to complete the steps as directed.

+
+

You will build a simple Lumen dashboard and deploy it in your browser. The result will look something like this: +

+
+

1. Create a YAML file#

+

Open your favorite text editor and create an empty file called penguins.yaml.

+
+
+

2. Add a data source#

+

The first thing that is needed is a source of data. Insert and save the text below to add a remote FileSource. This will tell Lumen to fetch the Palmer Penguins dataset:

+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+
+

Once you have saved your file, open a terminal and navigate to the location of this file.

+

In the terminal, launch the file with:

+
lumen serve penguins.yaml --show --autoreload
+
+
+

By using --autoreload, the dashboard automatically updates the application whenever we make changes to the YAML file.

+

What you should see in your browser should now match what is on the Preview tab:

+
+ +
+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+
+
+ +
+

+
+
+

So far, this returns an empty dashboard because we haven’t yet specified a view - so let’s add one!

+
+
+

3. Specify a table view#

+

The simplest View to add is a table with the raw data. This gives us a good idea of what we are working with and the available fields.

+
+ +
+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+layouts:
+  - title: Penguins
+    source: penguin_source
+    views:
+      - type: table
+        table: penguin_table
+
+
+
+ +
+

+
+
+
+
+

4. Create a plot view#

+

The table gives us a primer of the data source, but to start understanding patterns in the data, we have to visualize it. There is a wide range of views to chose from but for now we will create an hvPlotView (see hvPlot for background on the library). This is as easy as replacing the table type with a hvplot type.

+
+ +
+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+layouts:
+  - title: Penguins
+    source: penguin_source
+    views:
+      - type: hvplot
+        table: penguin_table
+
+
+
+ +
+

+
+
+
+
+

5. Make a scatter plot#

+

This plot is a bit overwhelming, so instead of plotting everything in one plot, we can plot bill_length_mm on the x-axis and bill_depth_mm on the y-axis. Furthermore, we can color based on the species and change the kind of the plot to scatter.

+
+ +
+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+layouts:
+  - title: Penguins
+    source: penguin_source
+    views:
+      - type: hvplot
+        table: penguin_table
+        kind: scatter
+        x: bill_length_mm
+        y: bill_depth_mm
+        color: species
+
+
+
+ +
+

+
+
+
+
+

6. Manipulate the data#

+

Let’s now set up two filter widgets based on two fields of the data - ‘sex’ and ‘island’. Since we don’t need all of the data columns, let’s also add a transform to select only a subset of the data.

+
+ +
+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: sex
+      - type: widget
+        field: island
+    transforms:
+      - type: columns
+        columns: ['species', 'island', 'sex', 'year', 'bill_length_mm', 'bill_depth_mm']
+
+layouts:
+  - title: Penguins
+    pipeline: penguin_pipeline
+    views:
+      - type: hvplot
+        x: bill_length_mm
+        y: bill_depth_mm
+        kind: scatter
+        color: species
+
+
+
+ +
+

+
+
+
+
+

7. Expand the view types#

+

We can even expand the views with a histogram and a table.

+
+ +
+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: sex
+      - type: widget
+        field: island
+    transforms:
+      - type: columns
+        columns: ['species', 'island', 'sex', 'year', 'bill_length_mm', 'bill_depth_mm']
+
+layouts:
+  - title: Penguins
+    pipeline: penguin_pipeline
+    views:
+      - type: hvplot
+        x: bill_length_mm
+        y: bill_depth_mm
+        kind: scatter
+        color: species
+      - type: hvplot
+        kind: hist
+        y: bill_length_mm
+      - type: table
+        show_index: false
+
+
+
+ +
+

+
+
+
+
+

8. Customize the appearance and behavior#

+

The default layout we get is less than ideal for this case since it cuts off one of our plots, leaves a lot of empty space, and does not resize responsively. We can get responsive plots by adding sizing_mode to the layout and responsive to the views. By changing the layout and height, we can further customize how the dashboard looks.

+
+ +
+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: sex
+      - type: widget
+        field: island
+    transforms:
+      - type: columns
+        columns: ['species', 'island', 'sex', 'year', 'bill_length_mm', 'bill_depth_mm']
+
+layouts:
+  - title: Penguins
+    pipeline: penguin_pipeline
+    layout: [[0], [1, 2]]
+    sizing_mode: stretch_width
+    height: 800
+    views:
+      - type: hvplot
+        x: bill_length_mm
+        y: bill_depth_mm
+        kind: scatter
+        color: species
+        responsive: true
+        height: 400
+      - type: hvplot
+        kind: hist
+        y: bill_length_mm
+        responsive: true
+        height: 300
+      - type: table
+        show_index: false
+        height: 300
+
+
+
+ +
+

+
+
+
+
+

9. Add a title and theme#

+

Final step - let’s use a config section to give our dashboard a more descriptive title and change the overall theme to dark. Note that we can also set our table to dark by adding a new theme parameter at the bottom.

+
+ +
+
config:
+  title: Palmer Penguins
+  theme: dark
+
+sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: sex
+      - type: widget
+        field: island
+    transforms:
+      - type: columns
+        columns: ['species', 'island', 'sex', 'year', 'bill_length_mm', 'bill_depth_mm']
+
+layouts:
+  - title: Penguins
+    pipeline: penguin_pipeline
+    layout: [[0], [1, 2]]
+    sizing_mode: stretch_width
+    height: 800
+    views:
+      - type: hvplot
+        x: bill_length_mm
+        y: bill_depth_mm
+        kind: scatter
+        color: species
+        responsive: true
+        height: 400
+      - type: hvplot
+        kind: hist
+        y: bill_length_mm
+        responsive: true
+        height: 300
+      - type: table
+        show_index: false
+        height: 300
+        theme: midnight
+
+
+
+ +
+

+
+
+

Congratulations! You have created your first Lumen dashboard and know a bit more about penguins!

+
+

Note

+

This is just a simple example of how to build a dashboard with Lumen. The next step is to review the core concepts of what we just achieved so you can generalize these steps to create your own dashboard.

+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/getting_started/core_concepts.html b/getting_started/core_concepts.html new file mode 100644 index 00000000..8cca1ce8 --- /dev/null +++ b/getting_started/core_concepts.html @@ -0,0 +1,755 @@ + + + + + + + + +Core Concepts — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Core Concepts#

+
+

What is the purpose of this page?

+

This conceptual overview of creating a Lumen dashboard is meant to help you start generalizing what you achieved in the tutorial (Build a dashboard). After this page you should start building your own dashboard. As you build, consult the relevant How-to guides or Reference pages, as needed.

+
+
+

Overview#

+

Lumen is a framework for easily building powerful data-driven dashboards. The ease of Lumen comes from the primary interface being a simple YAML file, which reads like a cooking recipe. We call this the specification. Unlike a recipe Lumen makes it very easy to go back and forth between the specification and the final product. This makes it easy to interactively go back and forth and iteratively improve the specification. The power of Lumen comes from the ability to leverage different data intake, data processing, and data visualization libraries that are available in the Python data science ecosystem, but without having to code!

+
+
+

YAML specification#

+

The YAML file is a simple and human readable recipe for building a dashboard. Briefly, YAML uses consistent whitespace to denote structure, and most lines either create an association (with key: value), or a list (with a leading hyphen -). For more on YAML, we recommend this quick YAML guide.

+

The four primary sections of a Lumen specification file are:

+
+
+
+
+
+
+config
+

To apply settings for the whole dashboard

+
+
+
+
+
+
+
+
+
+
+
+sources
+

To list your data sources

+
+
+
+
+
+
+
+
+
+
+
+pipelines
+

To specify how you want the data to be manipulated (filtered and transformed)

+
+
+
+
+
+
+
+
+
+
+
+layouts
+

To create the views (e.g. table, plot) for your dashboard

+
+
+
+
+
+

These core sections should be not be indented in the YAML file, as they are at the top of the hierarchy:

+
config:
+  ...: ...
+sources:
+  ...:
+    ...: ...
+pipelines:
+  ...:
+    ...: ...
+layouts:
+  - ...: ...
+    ...: ...
+
+
+

In addition to these core sections, there is plenty of advanced functionality that we will preview towards the bottom of this page.

+
+
+

Config#

+

The config section provides general settings which apply to the whole dashboard to control things like the title, overall layout and theme. The structure is very simple:

+
config:
+  title: My dashboard
+  layout: tabs
+  logo: assets/my_logo.png
+  ...
+
+
+

You might remember an implementation of this from what you created in the Build a dashboard tutorial. Your config section was used to add a title and dark theme to your dashboard:

+
config:
+  title: Palmer Penguins
+  theme: dark
+
+
+

See the Config Reference for a description of all parameters.

+
+
+

Sources#

+

The sources section defines the source of your data. Depending on your source type, the specification may look a bit different, but in general it will follow this pattern:

+
sources:
+  source_name:
+    type: Type of source
+    ...: Additional source parameters
+
+
+

A common choice for a source type is FileSource, which can load CSV, Excel, JSON and Parquet files from either local (filepaths) or remote (URL) locations. In your tutorial, you use a remote CSV source:

+
sources:
+  penguin_source:
+    type: file
+    tables:
+      table_penguin: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+
+

See the Source Reference for other source types and for the relevant parameters.

+
+
+

Pipelines (data processing)#

+

The pipelines section is where you list all the ways that you want the data to be filtered or transformed. If you don’t need the data to be manipulated, you can just exclude this section.

+
+

Filters#

+

The filters of a Pipeline allows you or your dashboard’s viewers to drill down into just a subset of the data.

+
pipelines:
+  name:
+    source: ...
+    filters:
+      - type: Type of filter
+        ...: Filter Parameters
+
+
+

A very useful filter type is widget, which is used to expose filtering capability in the dashboard view. Here is the implementation from your tutorial, which specifies two widgets for dashboard viewers.

+
pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: sex
+      - type: widget
+        field: island
+
+
+

See the Filter Reference for other filter types and for the relevant parameters.

+
+
+

Transforms#

+

Within the pipeline section, you can also apply a transform to the data, such as selecting only certain columns of the data.

+
pipelines:
+  name:
+    source: ...
+    transforms:
+      - type: Type of transform
+        ...: Transform Parameters
+
+
+

Here is the complete pipelines section from your tutorial, which include both filters and a transform:

+
pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: sex
+      - type: widget
+        field: island
+    transforms:
+      - type: columns
+        columns: ['species', 'island', 'sex', 'year', 'bill_length_mm', 'bill_depth_mm']
+
+
+

See the Transform Reference for other transform types and for the relevant parameters.

+
+
+
+

Layouts (views)#

+

The layouts section declares the actual content in the rendered application. The essential structure of a layouts section is as follows:

+
layouts:
+  - title: Dashboard title
+    pipeline: The pipeline driving these views
+    ...: Dashboard parameters
+    views:
+      - type: View type
+        ...: View parameters
+
+
+
+ +Expand this dropdown for a more complex example structure of layouts
+
+
+
+
+
layouts:
+  - title: The title of the monitoring endpoint
+    download:
+      format: When specified adds a section to the sidebar allowing users to download the filtered dataset
+      kwargs: Additional keyword arguments to pass to the pandas/dask to_<format> method
+      tables: Allows declaring a subset of tables to download
+    pipeline: The pipeline driving the views of this layout. Each View can independently declare a pipeline or all use the shared pipeline defined at the layout level
+    views: A list of metrics to monitor and display on the endpoint
+      - pipeline: The [Pipeline]`lumen.pipeline.Pipeline` driving the View
+        type: The type of View to use for rendering the table
+        ...: Additional parameters for the View
+    layout: The layout inside the card(s), e.g. 'row', 'column' or 'grid'
+    facet:
+      by: List of fields to facet by
+      sort: List of fields to sort by
+      reverse: Whether to reverse the sort order
+    refresh_rate: How frequently to poll for updates in milliseconds
+    ...: Additional parameters passed to the Card layout(s), e.g. width or height
+
+
+
+

At minimum each Layout must declare a title and a set of views. Each view can be of a different type, but a good starting point is the hvPlotView. This view type allows you to produce many different types of plots available from the hvPlot library, just by specifying the kind parameter.

+

In your tutorial, the final dashboard included two kinds - scatter and histogram:

+
layouts:
+  - title: Penguins
+    pipeline: penguin_pipeline
+    layout: [[0], [1, 2]]
+    sizing_mode: stretch_width
+    height: 800
+    views:
+      - type: hvplot
+        x: bill_length_mm
+        y: bill_depth_mm
+        kind: scatter
+        color: species
+        responsive: true
+        height: 450
+      - type: hvplot
+        kind: hist
+        y: bill_length_mm
+        responsive: true
+        height: 350
+      - type: hvplot
+        kind: hist
+        y: bill_depth_mm
+        responsive: true
+        height: 350
+
+
+

See the View Reference for other view types and for the relevant parameters.

+
+
+

Advanced Functionality#

+

The following sections are meant to introduce you some of Lumen’s advanced functionality. If you want to implement some of these features, explore their associated How to guides for complete recipes.

+
+

Defaults#

+

The defaults section allows overriding parameter defaults on the Filter, Source, Transform and View objects.

+
defaults:
+  filters:
+    - type: Type to override the default on
+      ...: Parameter to override
+  sources:
+    - type: Type to override the default on
+      ...: Parameter to override
+  transforms:
+    - type: Type to override the default on
+      ...: Parameter to override
+  views:
+    - type: Type to override the default on
+      ...: Parameter to override
+
+
+

You haven’t seen an implementation of this yet, but as an example, we could have used the defaults section to override the default WidgetFilter.multi value because perhaps we wanted the widget to filter with a specific value rather than multiple values:

+
defaults:
+  filters:
+    - type: widget
+      multi: false
+
+
+

For more on defaults, check out the How to override parameter defaults guide.

+
+
+

Variables#

+

The variables sections allow you to link settings across your entire application. Once a variable has been declared in the variables section, you can reference it throughout your specification using the $variables.<variable_name> syntax.

+
variables:
+  variable_name:
+    - type: ...
+      ...: Variable parameters
+
+
+

For example, you might have a TextInput widget where a dashboard user could enter the name of a CSV file with stock data. Establishing such a widget as a Variable would allow the dashboard to dynamically update with the new data source.

+
variables:
+  ticker:
+    type: widget
+    kind: TextInput
+    default: AAPL.csv
+
+sources:
+  stock_data:
+    type: file
+    tables:
+      ticker: $variables.ticker
+
+
+

For more on variables, check out the How to use variables and references guide.

+
+
+

Sources as variables#

+

In addition to the variables section, in which you can create arbitrary types of variables, you can also refer to sources with a similar syntax. In some scenarios you might want to refer to a Source, a table on a Source or a field on a table from elsewhere in the yaml specification.

+

As an example you may have local CSV file which contains a column of URLs to monitor and feed that information to a WebsiteSource which reports whether those URLs are live. Using the $ syntax we can easily establish such references.

+
sources:
+  csv:
+    type: file
+    files: [websites.csv]
+  live:
+    type: live
+    urls: $csv.websites.url
+
+
+

The $csv.websites.url syntax will look up a Source called ‘csv’, request a table called ‘websites’ and then feed the ‘url’ column in that table to the urls parameter of the WebsiteSource.

+

For more on referring to sources, check out the How to use variables and references guide.

+
+
+

External variables (templating)#

+

In many cases you do not want to hardcode variables inside the yaml specification instead passing in variables from an environment variable, a shell command, a CLI argument, a HTTP request header or cookie, or a OAuth token variable. This can be achieved using the following templating syntax:

+
    +
  • {{env("USER")}}: look in the set environment variables for the named variable

  • +
  • {{shell("get_login thisuser -t")}}: execute the command, and use the output as the value. The output will be trimmed of any trailing whitespace.

  • +
  • {{cookie("USER")}}: look in the HTTP request cookies of the served application

  • +
  • {{header("USER")}}: look in the HTTP request headers of the served application

  • +
  • {{oauth("USER")}}: look in the OAuth user token

  • +
  • {{USER}}: Arguments passed in using --template-vars="{'USER': 'lumen_user'}" when using lumen serve on the commandline.

  • +
+

For more on templating, check out the How to use variables and references guide.

+
+
+

Authentication#

+

The auth field may provide a dictionary of any number of fields which are validated against the user information provided the the Auth provider, which is made available by Panel in the panel.state.user_info dictionary. To discover how to configure an Auth provider with Panel/Lumen see the Panel documentation.

+

As an example the GitHub OAuth provider returns the login of the user that is visiting the dashboard. If we add the following field to the yaml:

+
auth:
+  login: [philippjfr]
+
+
+

Lumen will check the current user login against all user logins listed here. For a more generic Auth mechanism many Auth providers, such as Okta, make it possible to configure a list of groups a user belongs to in which case you could list the allowed groups in the auth field.

+

For more on Authentication, check out the How to set up authentication guide.

+
+
+
+

Where to go from here?#

+

As mentioned at top of this page, you should now start building your own dashboards. As you build, consult the relevant How-to guides or Reference pages, as needed. At any point, if you want deeper discussion of Lumen to solidify your understanding, take a look at the Background section.

+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/getting_started/index.html b/getting_started/index.html new file mode 100644 index 00000000..25575c00 --- /dev/null +++ b/getting_started/index.html @@ -0,0 +1,426 @@ + + + + + + + + +Getting Started — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Getting Started#

+

This Getting Started guide will go through the installation of Lumen, how to build an app, and describe the core concepts.

+
+
+
+
+
+
+ Installation
+

Install Lumen in a few easy steps

+
+
+
+
+
+
+
+ Build a dashboard
+

How to build a Lumen dashboard

+
+
+
+
+
+
+
+ Core concepts
+

Get an overview of the core concepts of Lumen

+
+
+
+
+
+
+
+ Pipelines
+

Get an overview of the core concepts of Lumen

+
+
+
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/getting_started/installation.html b/getting_started/installation.html new file mode 100644 index 00000000..981a6eb5 --- /dev/null +++ b/getting_started/installation.html @@ -0,0 +1,453 @@ + + + + + + + + +Installation — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Installation#

+
+

Setup#

+

Lumen works with Python 3 on Linux, Windows, and Mac.

+

The recommended way to install Lumen is using the conda command that is included in the installation of Anaconda or Miniconda. To help you choose between Anaconda and Miniconda, review this page. Completing the installation for either Anaconda or Miniconda will also install Python.

+

If you are not installing Anaconda or Miniconda, you can download Python directly from Python.org. In this case, you can install Lumen using pip, which comes with Python.

+
+
+

Installing Lumen#

+
    +
  1. Open up a terminal (Powershell if you are on Windows).

  2. +
  3. Run the following command, which will install Lumen with all its dependencies.

  4. +
  5. When the command finishes, run lumen --version in the terminal and check that the version is 0.6.0.

    +
      +
    • If this is not the case, you are not running the latest version, which may cause problems.

    • +
    +
  6. +
+
+ +
+
conda install -c pyviz -c conda-forge lumen -y
+
+
+
+ +
+
pip install lumen
+
+
+
+
+
+
+

Optional dependencies#

+

Lumen is very flexible and allows you to use components from various packages. Depending on what type of dashboard components you use, you may need to install additional packages. Error messages will help you determine if you are missing a package. For instance, if you see the following:

+
Source component specification declared unknown type 'intake'.
+
+
+

install the missing package in the same way you did lumen:

+
+ +
+
conda install -c pyviz -c conda-forge intake -y
+
+
+
+ +
+
pip install intake
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/getting_started/lumen_architecture.html b/getting_started/lumen_architecture.html new file mode 100644 index 00000000..29ec27b7 --- /dev/null +++ b/getting_started/lumen_architecture.html @@ -0,0 +1,447 @@ + + + + + + + + +Lumen’s Architecture — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Lumen’s Architecture#

+

The specification file used by lumen is a YAML file. The specification can be divided into sections of data exploration and dashboard settings. As a rule of thumb, the data exploration sections are required for the dashboard, and dashboard settings are optional.

+
+

Data Exploration#

+
+
+
+
+
+
+sources
+

Where the app finds the data.

+
+
+
+
+
+
+
+pipelines
+

Manipulating the data with filters and transforms.

+
+
+
+
+
+
+
+
+
+
+
+layouts
+

The presentation of the manipulated data with views.

+
+
+
+
+
+
+
+

Dashboard Settings#

+
+
+
+
+
+
+config
+

Settings that are applied to the whole dashboard.

+
+
+
+
+
+
+
+defaults
+

Overriding default parameters.

+
+
+
+
+
+
+
+variables
+

Global variables that can be used throughout the YAML file.

+
+
+
+
+
+
+
+auth
+

Authentication for the dashboard.

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/getting_started/pipelines.html b/getting_started/pipelines.html new file mode 100644 index 00000000..d1c2792b --- /dev/null +++ b/getting_started/pipelines.html @@ -0,0 +1,842 @@ + + + + + + + + +Building a data pipeline — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Building a data pipeline#

+
import lumen
+import panel as pn
+
+pn.extension('tabulator')
+
+
+

Lumen dashboards are a powerful, declarative way to write data-driven applications and dashboards. However Lumen components also provide a powerful abstraction that can be leveraged independently of a full dashboard YAML specification. Specifically the Pipeline component offers an extremely powerful basis for building data transformations that can either be used to power analysis pipelines or to drive visual components we can render in a notebook or a custom Panel dashboard. In this section we will discover how to leverage pipelines in this way.

+

First however we need to understand how Pipelines work, specifically the order in which operations are applied. In particular we need to distinguish between operations that are applied by the Source and operations that are applied to data returned by the Source. This is because various Source types support data queries and in the case of SQL based Source may also support arbitrary SQL transforms. This means that the Pipeline will first call the Source.get method with state of the Filter and SQLTransform components allowing the Source to optimize the filter queries and transforms and return the data, once the data is returned as a DataFrame the declared Transform stages will be applied in sequence.

+

Pipeline Diagram

+
+

Declaring a pipeline#

+

Just like any other component in Lumen Pipeline components can be built using a declarative specification. Let us for example build a Pipeline that starts with a FileSource and applies a number of filters and transforms.

+
from lumen.pipeline import Pipeline
+
+data_url = 'https://datasets.holoviz.org/penguins/v1/penguins.csv'
+
+pipeline = Pipeline.from_spec({
+    'source': {
+        'type': 'file',
+        'tables': {
+            'penguins': data_url
+        }
+    },
+    'filters': [
+        {'type': 'widget', 'field': 'species'},
+        {'type': 'widget', 'field': 'island'},
+        {'type': 'widget', 'field': 'sex'},
+        {'type': 'widget', 'field': 'year'}
+    ],
+    'transforms': [
+        {'type': 'aggregate', 'method': 'mean', 'by': ['species', 'sex', 'year']}
+    ]
+})
+
+
+

Once declared we can inspect the current data easily:

+
pipeline.data
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bill_length_mmbill_depth_mmflipper_length_mmbody_mass_g
speciessexyear
Adeliefemale200737.92272718.127273185.2272733389.772727
200836.51600017.460000188.4400003386.000000
200937.40769217.350000189.3461543334.615385
male200739.95000019.509091188.1818184038.636364
200840.60400018.924000193.6400004098.000000
200940.55769218.846154194.8076923995.192308
Chinstrapfemale200746.56923117.838462188.6923083569.230769
200846.00000017.300000192.6666673472.222222
200947.00833317.533333194.3333333522.916667
male200750.87692319.130769196.1538463819.230769
200851.40000019.600000202.7777784127.777778
200951.10000019.125000201.8333333927.083333
Gentoofemale200745.06250013.993750211.0625004618.750000
200845.29545514.131818213.0000004627.272727
200946.26000014.550000213.7000004786.250000
male200749.00000015.364706218.8823535552.941176
200848.53913015.704348222.0869575410.869565
200950.88095216.019048223.0952385510.714286
+

Note that a Pipeline updates dynamically if any Source, Filter or Transform is changed or updated. In the pipeline above we declared ‘widget’ filters which we can render by accessing the control_panel property. To view the dynamically updating data can instantiate a lumen.views.Table component. In a live notebook we will now get an interactive application letting us dynamically filter the data and view the result.

+
from lumen.views import Table
+
+pn.Row(pipeline.control_panel, Table(pipeline=pipeline, pagination='remote'))
+
+
+
+ +

Note that since a Pipeline is a Parameterized object we can pass the data parameter to a Panel component e.g. here we bind the data to a DataFrame pane:

+
pn.Row(
+    pipeline.control_panel,
+    pn.pane.DataFrame(pipeline.param.data, width=800)
+)
+
+
+
+ +
+

Programmatically building pipelines#

+

A Pipeline does not have to be built using the declarative specification, instead we can programmatically build the same pipeline:

+
from lumen.sources import FileSource
+
+source = FileSource(tables={'penguins': data_url})
+pipeline = Pipeline(source=source, table='penguins')
+
+pipeline.add_filter('widget', field='species')
+pipeline.add_filter('widget', field='island')
+pipeline.add_filter('widget', field='sex')
+pipeline.add_filter('widget', field='year')
+
+pipeline
+
+
+
+ +
+
+
+

Automatic filters#

+

By setting filters='auto' we can also have Lumen automatically generate filters for all available columns:

+
Pipeline(source=source, table='penguins', filters='auto')
+
+
+
+ +
+

Chaining pipelines#

+

In some cases you will want to build branching pipelines, e.g. in an initial stage you filter the data and display it and in another stage you aggregate your data.

+
from lumen.transforms import Aggregate
+
+agg_pipeline = pipeline.chain(transforms=[Aggregate(method='mean', by=['species', 'year'])])
+
+agg_pipeline.data
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
bill_length_mmbill_depth_mmflipper_length_mmbody_mass_g
speciesyear
Adelie200738.82449018.767347186.5918373696.428571
200838.56000018.192000191.0400003742.000000
200938.98269218.098077192.0769233664.903846
Chinstrap200748.72307718.484615192.4230773694.230769
200848.70000018.450000197.7222223800.000000
200949.05416718.329167198.0833333725.000000
Gentoo200747.01470614.688235215.1176475070.588235
200846.93695714.923913217.5652175019.565217
200948.50000015.276744218.4186055140.697674
+

By chaining the Pipeline we can share computations between different stages, i.e. the filtering step still occurs in the first stage.

+
+
+
+

Building a dashboard#

+

One of the major benefits of the Pipeline architecture is that it allows Lumen components to be used outside of the context of a Lumen application. This makes it possible to build custom dashboards while still leveraging the power of all Lumen components. Let us compose a simple dashboard application driven by the pipeline we defined above.

+
from lumen.views import hvPlotUIView
+
+pn.Row(
+    pipeline.control_panel.servable(area='sidebar'),
+    pn.Tabs(
+        ('Plot', hvPlotUIView(pipeline=pipeline, kind='scatter', x='bill_length_mm', y='bill_depth_mm', by='species')),
+        ('Table', Table(pipeline=agg_pipeline))
+    ).servable()
+)
+
+
+
+ +
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/advanced/auth.html b/how_to/advanced/auth.html new file mode 100644 index 00000000..e7697407 --- /dev/null +++ b/how_to/advanced/auth.html @@ -0,0 +1,413 @@ + + + + + + + + +Configuring Authentication — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Configuring Authentication#

+

WIP

+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/advanced/callbacks.html b/how_to/advanced/callbacks.html new file mode 100644 index 00000000..0cac72be --- /dev/null +++ b/how_to/advanced/callbacks.html @@ -0,0 +1,464 @@ + + + + + + + + +How to define callbacks — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

How to define callbacks#

+

Often times you want to perform custom actions when a session launches or ends or when a user interacts with a data pipeline. Since Lumen applications are specified as a declarative specification the easiest way to to do this is to define hooks.

+

The Config object provides a number of hooks that can be defined:

+
    +
  • on_session_created: Callback that fires when a user session is created.

  • +
  • on_session_destroyed: Callback that fires when a user session is destroyed.

  • +
  • on_loaded: Callback that fires when a user frontend session is fully loaded.

  • +
  • on_error: Callback that fires if an error occurs in a dashboard callback.

  • +
  • on_update: Callback that fires when a pipeline is updated.

  • +
+
+

Reference callbacks in external module#

+

Since we have to specify callbacks as a reference to a specific module the function or method must be in an importable location. This can either be a reference to a function in an installed a package or a module shipped alongside the YAML file, e.g. if we declare a file called callbacks.py:

+
import panel as pn
+
+def created():
+   print(f'Session created for user {pn.state.user}')
+
+def updated(pipeline):
+   print(f'Pipeline {pipeline.name} was updated.')
+
+
+

We can now reference these callbacks from the YAML:

+
config:
+  on_session_created: callbacks.created
+  on_update: callbacks.updated
+
+
+
+
+

Serializing callbacks#

+

The fact that the functions have to be importable also means that when defining the callbacks programmatically they can only be serialized if they were defined in an external module.

+

As an example we cannot do something like this:

+
import lumen as lm
+
+def created():
+   print('Session created.')
+
+lm.Config(on_session_created=created).to_spec()
+
+
+

We must move the callback into a module that can be imported.

+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/advanced/index.html b/how_to/advanced/index.html new file mode 100644 index 00000000..cded71bf --- /dev/null +++ b/how_to/advanced/index.html @@ -0,0 +1,417 @@ + + + + + + + + +Advanced Topics — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+

.. raw:: html + + +

+
+

Advanced Topics#

+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/advanced/local_components.html b/how_to/advanced/local_components.html new file mode 100644 index 00000000..30057087 --- /dev/null +++ b/how_to/advanced/local_components.html @@ -0,0 +1,671 @@ + + + + + + + + +Access custom components — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Access custom components#

+
+

What does this guide solve?

+

This guide will show you how to access local files that build custom components.

+
+
+

Overview#

+

While Lumen ships with a wide range of components, users may also define custom components in files which live alongside the YAML file. There are two approaches to reference these local custom components.

+

The first approach is to save your custom components to files with specific names that Lumen will automatically import. With this approach, you can just refer to your components in the YAML specification using their simple string name (for example, texteditor).

+

The second approach is to save your custom components to your own folder and filenames. With this approach, you can refer to your components using their module path (for example, my_library.my_module.TextEditor).

+

In the custom component examples below, we will add a transform for stable sorting, and a view for a rich text editor.

+
+
+

Approach 1: Using imported files#

+

Lumen will automatically import filters.py, sources.py, transforms.py, and views.py if these files exist alongside the YAML dashboard specification.

+

For example, if you created a custom transform and a custom view, all you have to do is save the custom transform to transforms.py and the custom view to views.py, and then place them in the same directory as your YAML specification. Now you can reference these local components within your specification using their simple string name, and they will be applied when you launch your dashboard.

+

Here are our example custom component files:

+
+ +
+
import param
+from lumen import Transform
+
+class StableSort(Transform):
+    """
+    Uses a stable sorting algorithm on one or more columns.
+
+    See `pandas.DataFrame.sort_values` with kind='stable'
+
+    df.sort_values(<by>, ascending=<ascending>, kind='stable')
+    """
+
+    by = param.ListSelector(default=[], doc="""
+       Columns or indexes to sort by.""")
+
+    ascending = param.ClassSelector(default=True, class_=(bool, list), doc="""
+       Sort ascending vs. descending. Specify list for multiple sort
+       orders. If this is a list of bools, must match the length of
+       the by.""")
+
+    transform_type = 'stablesort'
+
+    _field_params = ['by']
+
+    def apply(self, table):
+        return table.sort_values(self.by, ascending=self.ascending, kind='stable')
+
+
+
+ +
+
from lumen import View
+import panel as pn
+
+class TextEditor(View):
+    """
+    Provides a rich text editor.
+
+    See https://panel.holoviz.org/reference/widgets/TextEditor.html#widgets-gallery-texteditor
+    """
+
+    view_type = 'texteditor'
+
+    _extension = 'texteditor'
+
+    def get_panel(self):
+        return pn.widgets.TextEditor(**self._get_params())
+
+    def _get_params(self):
+        return dict(**self.kwargs, sizing_mode='stretch_width', placeholder='Enter some text')
+
+
+
+
+

And here is our example YAML specification (dashboard.yaml) that references these local custom component files:

+
config:
+  title: Palmer Penguins
+
+sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: sex
+      - type: widget
+        field: island
+    transforms:
+      - type: columns
+        columns: ['species', 'island', 'sex', 'year', 'bill_length_mm', 'bill_depth_mm']
+      - type: my_module.StableSor
+        by: island
+
+layouts:
+  - title: Penguins
+    pipeline: penguin_pipeline
+    layout: [[0, 1], [2, 3]]
+    sizing_mode: stretch_width
+    height: 800
+    views:
+      - type: hvplot
+        x: bill_length_mm
+        y: bill_depth_mm
+        kind: scatter
+        color: species
+        responsive: true
+        height: 400
+      - type: hvplot
+        kind: hist
+        y: bill_length_mm
+        responsive: true
+        height: 300
+      - type: table
+        show_index: false
+        height: 300
+      - type: texteditor
+        height: 250
+
+
+

Now launch the dashboard with:

+
lumen serve dashboard.yaml --show
+
+
+

+
+
+

Approach 2: Using module paths#

+

Lumen will import custom components from your own modules (folders and files) if referenced in the YAML specification using dot notation (for example, my_library.my_module.TextEditor). If using this approach, the root of the module path (for example, my_library) needs to be in the same folder as the YAML specification.

+

Here is our example custom component file. In this case, we combined the components into one file, but they could have been in different module paths:

+

my_library/my_module.py

+
import param
+from lumen import Transform, View
+import panel as pn
+
+class StableSort(Transform):
+    """
+    Uses a stable sorting algorithm on one or more columns.
+
+    See `pandas.DataFrame.sort_values` with kind='stable'
+
+    df.sort_values(<by>, ascending=<ascending>, kind='stable')
+    """
+
+    by = param.ListSelector(default=[], doc="""
+       Columns or indexes to sort by.""")
+
+    ascending = param.ClassSelector(default=True, class_=(bool, list), doc="""
+       Sort ascending vs. descending. Specify list for multiple sort
+       orders. If this is a list of bools, must match the length of
+       the by.""")
+
+    transform_type = 'stablesort'
+
+    _field_params = ['by']
+
+    def apply(self, table):
+        return table.sort_values(self.by, ascending=self.ascending, kind='stable')
+
+
+class TextEditor(View):
+    """
+    Provides a rich text editor.
+
+    See https://panel.holoviz.org/reference/widgets/TextEditor.html#widgets-gallery-texteditor
+    """
+
+    view_type = 'texteditor'
+
+    _extension = 'texteditor'
+
+    def get_panel(self):
+        return pn.widgets.TextEditor(**self._get_params())
+
+    def _get_params(self):
+        return dict(**self.kwargs, sizing_mode='stretch_width', placeholder='Enter some text')
+
+
+

And here is our example YAML specification (dashboard.yaml) that references these local custom components:

+
config:
+  title: Palmer Penguins
+
+sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: sex
+      - type: widget
+        field: island
+    transforms:
+      - type: columns
+        columns: ['species', 'island', 'sex', 'year', 'bill_length_mm', 'bill_depth_mm']
+      - type: my_library.my_module.StableSort
+        by: island
+
+layouts:
+  - title: Penguins
+    pipeline: penguin_pipeline
+    layout: [[0, 1], [2, 3]]
+    sizing_mode: stretch_width
+    height: 800
+    views:
+      - type: hvplot
+        x: bill_length_mm
+        y: bill_depth_mm
+        kind: scatter
+        color: species
+        responsive: true
+        height: 400
+      - type: hvplot
+        kind: hist
+        y: bill_length_mm
+        responsive: true
+        height: 300
+      - type: table
+        show_index: false
+        height: 300
+      - type: my_library.my_module.TextEditor
+        height: 250
+
+
+

Now launch the dashboard with:

+
lumen serve dashboard.yaml --show
+
+
+

+
+ +
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/advanced/variables_and_references.html b/how_to/advanced/variables_and_references.html new file mode 100644 index 00000000..2871ff72 --- /dev/null +++ b/how_to/advanced/variables_and_references.html @@ -0,0 +1,645 @@ + + + + + + + + +How to use variables — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

How to use variables#

+
+

What does this guide solve?

+

This guide shows you how to use one of the advanced features of Lumen: Variables.

+
+
+

Overview#

+

Variables are one of the most powerful features of Lumen. This guide will give you an overview of three different types of variables and how to reference them in the YAML specification.

+
+
+

Variables#

+

Variables give Lumen components a lot of flexibility. Variables can be defined in multiple ways. The simplest way to define a variable is in the variables block. When a variable is defined, it can be referenced throughout the rest of the specification. This is done by using $variables.NAME, where NAME is the unique name of the variable.

+

The data source is a remote dataset containing a volume column many magnitudes greater than the rest, making it impossible to see the other time series in the data. Removing Volume from the columns variable makes the other time series visible.

+
+ +
+
variables:
+  columns:
+    type: widget
+    kind: MultiSelect
+    value: [Open,High,Low,Close,Volume,Adj Close]
+    options: [Open,High,Low,Close,Volume,Adj Close]
+    size: 7
+
+sources:
+  stock_data:
+    type: file
+    tables:
+      ticker: https://raw.githubusercontent.com/matplotlib/sample_data/master/aapl.csv
+    kwargs:
+      index_col: Date
+      parse_dates: [Date]
+
+pipelines:
+  ticker_pipe:
+    source: stock_data
+    table: ticker
+    transforms:
+      - type: columns
+        columns: $variables.columns
+
+layouts:
+- title: Plot
+  pipeline: ticker_pipe
+  views:
+    - type: hvplot
+      table: ticker
+
+
+
+ +
+

+
+ +
+

+
+
+
+
+

Sources as variables#

+

Source components can also be used like a variable. There are three main ways to pass Source information by reference:

+
    +
  1. Passing the source itself by reference $<source_name>

  2. +
  3. Passing a table on the source by reference $<source_name>.<table_name>

  4. +
  5. Passing the unique values in a field by reference $<source_name>.<table_name>.<field_name>

  6. +
+

Let us explore an example passing field values by reference. In the example below we define two sources:

+
    +
  1. The first is a CSV file with a single column containing different website URLs.

  2. +
  3. The second is a live source that checks whether the URLs from the first source are alive or dead.

  4. +
+
+ +
+
sources:
+  csv:
+    type: file
+    files: [websites.csv]
+  live:
+    type: live
+    urls: $csv.websites.url
+
+layouts:
+- title: Status of websites
+  source: live
+  views:
+    - type: table
+
+
+
+ +
+

+
+ +
+
url
+https://google.com
+https://python.org
+https://anaconda.com
+not-alive
+
+
+
+
+

The reference to the variable is built up as:

+
    +
  1. The name of the source to reference, csv in this case.

  2. +
  3. The table’s name websites, which is the filename without an extension.

  4. +
  5. Which column of the table to look at url.

  6. +
  7. Combine the last three parts, and you get the following variable $csv.websites.url.

  8. +
+
+
+

External variables (templating)#

+

The last way to reference variables is by using external variables. There are six ways to do this, all of which use Jinja2 templating with the double curly brackets notation.

+ + + + + + + + + + + + + + + + + + + + +

Method

How

Environment variable

{{ env("USER") }}

Request cookies

{{ cookie("USER") }}

Request header

{{ header("USER") }}

OAuth user token

{{ oauth("USER") }}

+

Furthermore, CLI arguments or shell commands can be used. See the sections below.

+
+

Variables with the command line#

+

To pass CLI arguments --template-vars should be used with lumen serve.

+
+ +
+
sources:
+  source:
+    type: file
+    tables:
+      table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+layouts:
+- title: Hello my dear friend {{ USER }}
+  source: source
+  views:
+    - type: table
+      table: table
+
+
+
+ +
+

Ran with lumen serve cli_example.yml --template-vars="{'USER': 'lumen_user'}" +

+
+ +
+

Ran with lumen serve cli_example.yml +

+
+
+
+
+

Variables with a shell command#

+

The shell command is done by {{ shell(COMMAND) }} and then uses the output of the command. +It is worth noting that the output will be trimmed of any trailing whitespace. +As a simple example, echo can be used as the shell command.

+
+ +
+
sources:
+  source:
+    type: file
+    tables:
+      table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+layouts:
+- title: {{ shell("echo hello from the shell") }}
+  source: source
+  views:
+    - type: table
+      table: table
+
+
+
+ +
+

+
+
+
+

Should I use $ or {{ }} for reference?

+

Internal variables are referenced with a starting dollar sign $, whereas external references use double curly brackets before and after {{ }}. External references are only resolved when the dashboard is initialized while internal variables can be resolved dynamically.

+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_intake/cache.html b/how_to/data_intake/cache.html new file mode 100644 index 00000000..7d3ed294 --- /dev/null +++ b/how_to/data_intake/cache.html @@ -0,0 +1,519 @@ + + + + + + + + +How to use cache — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

How to use cache#

+
+

What does this guide solve?

+

This guide will show you how to locally cache data to speed up reloading from a remote Source.

+
+
+

Caching file#

+

When working with large data in a non-optional file format, creating a local cache can be advantageous to save time when reloading the data. Caching a Source is done by using cache_dir followed by a directory. If the directory does not exist, it will be created. The data will be saved as parquet files in the cache directory and the schema will be stored as a JSON file.

+

Below is an example of caching a 370 MB file that consists of almost 12 million rows.

+
+

Warning

+

The initial load can take a couple of minutes as the file needs to be downloaded and cached first.

+
+
+ +
+
sources:
+  large_source:
+    type: file
+    cache_dir: cache
+    tables:
+      large_table: https://s3.amazonaws.com/datashader-data/nyc_taxi_wide.parq
+    kwargs:
+      engine: fastparquet
+
+layouts:
+  - title: Table
+    source: large_source
+    views:
+      - type: table
+        table: large_table
+
+
+
+ +
+
from lumen.pipeline import Pipeline
+
+data_url = "https://s3.amazonaws.com/datashader-data/nyc_taxi_wide.parq"
+pipeline = Pipeline.from_spec(
+    {
+        "source": {
+            "type": "file",
+            "cache_dir": "cache",
+            "tables": {"large_table": data_url},
+            "kwargs": {"engine": "fastparquet"},
+        },
+    }
+)
+pipeline.data
+
+
+
+
+

Depending on the source type data caching will cache the entire table or individual queries. Using the cache_per_query option you can toggle this behavior.

+
+

Note

+

Lumen’s cache can be added to all source types.

+
+
+
+

Precaching#

+

Sources that support caching per query can be made to pre-cache specific Filter and SQLTransform combinations. To enable pre-caching you must initialize a Pipeline and then either programmatically request to populate the pre-cache OR supply the pre-cache configuration as part of the YAML specification.

+

A pre-cache definitions can take one of two forms

+
    +
  • A dictionary containing ‘filters’ and ‘variables’ dictionaries each containing lists of values to compute a cross-product for, e.g.

  • +
+
{
+    'filters': {
+        <filter>': ['a', 'b', 'c', ...],
+        ...
+    },
+    'variables':
+        <variable>: [0, 2, 4, ...],
+        ...
+    }
+}
+
+
+
    +
  • A list containing dictionaries of explicit values for each filter and variables.

  • +
+
[
+    {
+        'filters': {<filter>: 'a'},
+        'variables': {<variable>: 0}
+    },
+    {
+        'filters': {<filter>: 'a'},
+        'variables': {<variable>: 1}
+    },
+    ...
+]
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_intake/files.html b/how_to/data_intake/files.html new file mode 100644 index 00000000..274a98ba --- /dev/null +++ b/how_to/data_intake/files.html @@ -0,0 +1,510 @@ + + + + + + + + +How to access files — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

How to access files#

+
+

What does this guide solve?

+

This guide shows you how to use a local or remote file as a source for your dashboard.

+
+
+

Overview#

+

Lumen can read from multiple data source types. +The FileSource type supports reading from either local or remote files of various formats: CSV, XLSX, XLS, Parquet, and JSON.

+
+
+

Local files#

+

One of the easiest ways to get a source is by using local files, such as a CSV file. Below is an example of how to add a local file as a source.

+
+ +
+
sources:
+  local_source:
+    type: file
+    tables:
+      local_table: local_table.csv
+
+layouts:
+  - title: Table
+    source: local_source
+    views:
+      - type: table
+        table: local_table
+
+
+
+ +
+
from lumen.pipeline import Pipeline
+
+data_path = "local_table.csv"
+pipeline = Pipeline.from_spec(
+    {
+        "source": {"type": "file", "tables": {"local_table": data_path}},
+    }
+)
+pipeline.data  # preview the data in a notebook
+
+
+
+
+
+
+

Remote files#

+

Alternatively, you can access a remote file using a URL.

+
+ +
+
sources:
+  remote_source:
+    type: file
+    tables:
+      remote_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+layouts:
+  - title: Table
+    source: remote_source
+    views:
+      - type: table
+        table: remote_table
+
+
+
+ +
+
from lumen.pipeline import Pipeline
+
+data_url = "https://datasets.holoviz.org/penguins/v1/penguins.csv"
+pipeline = Pipeline.from_spec(
+    {
+        "source": {"type": "file", "tables": {"remote_table": data_url}},
+    }
+)
+pipeline.data  # preview the data in a notebook
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_intake/index.html b/how_to/data_intake/index.html new file mode 100644 index 00000000..759b58ad --- /dev/null +++ b/how_to/data_intake/index.html @@ -0,0 +1,417 @@ + + + + + + + + +Data Intake — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+

.. raw:: html + + +

+
+

Data Intake#

+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_output/download_data.html b/how_to/data_output/download_data.html new file mode 100644 index 00000000..aa09e048 --- /dev/null +++ b/how_to/data_output/download_data.html @@ -0,0 +1,504 @@ + + + + + + + + +How to download data — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

How to download data#

+
+

What does this guide solve?

+

This guide will show you how to enable your dashboard’s viewer to download data

+
+
+

Download data#

+

There are several different ways to let a user download data. This guide will show you three ways to do it.

+
+ +
+
sources:
+  penguins:
+    type: file
+    tables:
+      penguins: https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-07-28/penguins.csv
+
+layouts:
+  - title: Table
+    source: penguins
+    download: csv
+    views:
+      - type: download
+        format: csv
+      - type: table
+        table: penguins
+        download: csv
+
+
+

+
+ +
+
sources:
+  penguins:
+    type: file
+    tables:
+      penguins: https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-07-28/penguins.csv
+
+layouts:
+  - title: Table
+    source: penguins
+    download: csv
+    views:
+      - type: download
+        format: csv
+      - type: table
+        table: penguins
+        download: csv
+
+
+

+
+ +
+
sources:
+  penguins:
+    type: file
+    tables:
+      penguins: https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2020/2020-07-28/penguins.csv
+
+layouts:
+  - title: Table
+    source: penguins
+    download: csv
+    views:
+      - type: download
+        format: csv
+      - type: table
+        table: penguins
+        download: csv
+
+
+

+
+
+
+

Note

+

The YAML specification for the example is the same, but the line used to create the specific download button is emphasized in the code and highlighted with a red box in the preview of the dashboard.

+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_output/index.html b/how_to/data_output/index.html new file mode 100644 index 00000000..2049708d --- /dev/null +++ b/how_to/data_output/index.html @@ -0,0 +1,417 @@ + + + + + + + + +Data Output — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+

.. raw:: html + + +

+
+

Data Output#

+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_processing/branch_pipeline.html b/how_to/data_processing/branch_pipeline.html new file mode 100644 index 00000000..2a80e47d --- /dev/null +++ b/how_to/data_processing/branch_pipeline.html @@ -0,0 +1,595 @@ + + + + + + + + +Branch a pipeline — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Branch a pipeline#

+
+

What does this guide solve?

+

This guide shows you how to build branching pipelines, allowing for views of the same source data at different steps in processing.

+
+
+

Overview#

+

See the Background page on Pipeline Branching.

+

Continue reading if you are working in YAML (most likely). If you are working in Python, jump to Branching in Python.

+
+
+

Branching in YAML#

+

As we will see, the essential component of branching in YAML is to use the pipeline: parameter.

+
+

Initiating a simple dashboard#

+

Let’s first create a simple dashboard without a branch and launch to ensure that things are working properly.

+
+
+
+penguins.yaml
+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: island
+
+layouts:
+  - title: Penguins
+    sizing_mode: stretch_width
+    views:
+      - type: table
+        pipeline: penguin_pipeline
+        show_index: false
+        height: 300
+
+
+
+
+
lumen serve penguins.yaml --show --autoreload
+
+
+

first table, no branch

+
+
+

Add a branch#

+

Now let’s add a new Pipeline that branches from the existing pipeline. We can accomplish this by adding a pipeline: parameter that refers back to the name of the first pipeline. In our example, our new pipeline, called branch_sort, has a pipeline: parameter that points back to penguin_pipeline.

+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: island
+  branch_sort:
+    pipeline: penguin_pipeline
+    transforms:
+      - type: columns
+        columns: ['species', 'island', 'bill_length_mm', 'bill_depth_mm']
+
+layouts:
+  - title: Penguins
+    sizing_mode: stretch_width
+    views:
+      - type: table
+        pipeline: penguin_pipeline
+        show_index: false
+        height: 300
+
+
+
+
+

Refer to the branch in a new view#

+

Finally, we can create a new View that displays the additional data manipulation steps present on our branch. Below, we simply specify a new table view with a pipeline: parameter that refers to our new branch_sort.

+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+pipelines:
+  penguin_pipeline:
+    source: penguin_source
+    table: penguin_table
+    filters:
+      - type: widget
+        field: island
+  branch_sort:
+    pipeline: penguin_pipeline
+    transforms:
+      - type: columns
+        columns: ['species', 'island', 'bill_length_mm', 'bill_depth_mm']
+
+layouts:
+  - title: Penguins
+    sizing_mode: stretch_width
+    views:
+      - type: table
+        pipeline: penguin_pipeline
+        show_index: false
+        height: 300
+      - type: table
+        pipeline: branch_sort
+        show_index: false
+        height: 300
+
+
+

final dashboard

+
+
+
+

Branching in Python#

+

As we will see below, the primary tool to create a branch of a Pipeline in Python is to use the pipeline.chain method.

+
+

Initiating the pipeline#

+

Let’s start by creating a pipeline up to a branching point. See the How to guide - Build a dashboard in Python - for a walk-through of these initial steps.

+
from lumen.pipeline import Pipeline
+from lumen.sources import FileSource
+
+data_url = 'https://datasets.holoviz.org/penguins/v1/penguins.csv'
+
+pipeline = Pipeline(source=FileSource(tables={'penguins': data_url}), table='penguins')
+
+pipeline.add_filter('widget', field='species')
+pipeline.add_filter('widget', field='island')
+pipeline.add_filter('widget', field='sex')
+pipeline.add_filter('widget', field='year')
+
+pipeline.data
+
+
+
+
+

Branching the pipeline#

+

At this point, we will create a branch of our pipeline by using the pipeline.chain method, and apply a new transform that aggregates the data, only on this branch. We assign the result to a new Pipeline variable so that we can refer to it separately from the original pipeline.

+
from lumen.transforms import Aggregate
+
+agg_pipeline = pipeline.chain(transforms=[Aggregate(method='mean', by=['species', 'year'])])
+
+agg_pipeline.data
+
+
+
+
+ +
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_processing/index.html b/how_to/data_processing/index.html new file mode 100644 index 00000000..597f899b --- /dev/null +++ b/how_to/data_processing/index.html @@ -0,0 +1,417 @@ + + + + + + + + +Data Processing — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+

.. raw:: html + + +

+
+

Data Processing#

+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_processing/pipeline_python.html b/how_to/data_processing/pipeline_python.html new file mode 100644 index 00000000..bb9406a2 --- /dev/null +++ b/how_to/data_processing/pipeline_python.html @@ -0,0 +1,704 @@ + + + + + + + + +Build a Pipeline in Python — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Build a Pipeline in Python#

+
+

What does this guide solve?

+

Although the primary interface for building a Lumen dashboard is the YAML specification file, this guide shows you an alternate approaches for building with Python. To learn more, visit the Lumen in Python Conceptual Guide.

+
+
+

Overview#

+

When building with Lumen in Python, the main object that defines a dashboard is the Pipeline. With this Pipeline object, you can specify the data source, filters, and transforms. There are two approaches to add these specifications to a Pipeline object, declaratively or programmatically. While the declarative approach is more compact, the programmatic approach allows you to seperate the pipeline creation steps.

+

Pipeline Diagram

+
+
+

Declaratively specifying a pipeline#

+

The declarative specification approach looks similar to a YAML file hierarchy, but consists of nested Python dictionary and list objects.

+
import lumen as lm
+
+data_url = 'https://datasets.holoviz.org/penguins/v1/penguins.csv'
+
+pipeline = lm.Pipeline.from_spec({
+    'source': {
+        'type': 'file',
+        'tables': {
+            'penguins': data_url
+        }
+    },
+    'filters': [
+        {'type': 'widget', 'field': 'species'},
+        {'type': 'widget', 'field': 'island'},
+        {'type': 'widget', 'field': 'sex'},
+        {'type': 'widget', 'field': 'year'}
+    ],
+    'transforms': [
+        {'type': 'aggregate', 'method': 'mean', 'by': ['species', 'sex', 'year']}
+    ]
+})
+
+
+
+
+

Programmatically specifying a pipeline#

+

The programmatic specification approach uses Lumen objects to build the pipeline step by step.

+
+

Add source#

+

First, add a valid Source to your Pipeline. A common choice is FileSource, which can load CSV, Excel, JSON and Parquet files, but see the Source Reference for all options.

+
from lumen.sources import FileSource
+
+data_url = 'https://datasets.holoviz.org/penguins/v1/penguins.csv'
+
+pipeline = lm.Pipeline(source=FileSource(tables={'penguins': data_url}), table='penguins')
+
+
+
+

Preview the data

+

At any point after defining the source in your pipeline, you can inspect the data in a notebook with pipeline.data

+
+
pipeline.data.head()
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
speciesislandbill_length_mmbill_depth_mmflipper_length_mmbody_mass_gsexyear
0AdelieTorgersen39.118.7181.03750.0male2007
1AdelieTorgersen39.517.4186.03800.0female2007
2AdelieTorgersen40.318.0195.03250.0female2007
3AdelieTorgersenNaNNaNNaNNaNNaN2007
4AdelieTorgersen36.719.3193.03450.0female2007
+
+
+

Add filter#

+

Next, you can add widgets for certain columns of your source. When displaying the dashboard, these widgets will allows your dashboard users to filter the data. See the Filter Reference for all options.

+
pipeline.add_filter('widget', field='species')
+pipeline.add_filter('widget', field='island')
+pipeline.add_filter('widget', field='sex')
+pipeline.add_filter('widget', field='year')
+
+
+
+
+

Add transform#

+

Now you can apply a transform to the data, such as computing the mean or selecting certain columns. See the Transform Reference for more.

+
columns = ['species', 'island', 'sex', 'year', 'bill_length_mm', 'bill_depth_mm']
+
+pipeline.add_transform('columns', columns=columns)
+
+pipeline.data.head()
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
speciesislandsexyearbill_length_mmbill_depth_mm
0AdelieTorgersenmale200739.118.7
1AdelieTorgersenfemale200739.517.4
2AdelieTorgersenfemale200740.318.0
3AdelieTorgersenNaN2007NaNNaN
4AdelieTorgersenfemale200736.719.3
+
+

Manually update dashboard

+

By default, every interaction will update the dashboard. If this behavior is unwanted, for instance, if you want to select multiple filter widgets and not have the dashboard update after every individual selection, set auto_update=False on the Pipeline. This will require you to manually trigger an update by clicking a button.

+
+
+
+
+

Display the pipeline#

+

Once you have built your pipeline it is extremely easy to view it interactively. As long as you have loaded the Panel extension with pn.extension('tabulator') simply displaying a pipeline in a notebook cell will render it:

+
import panel as pn
+
+pn.extension('tabulator')
+
+pipeline
+
+
+
+ +

If you are working in a local REPL or from a script you can also use pipeline.show() to preview it.

+

You can also easily render the control panel containing the filter widgets and variables separately:

+
pipeline.control_panel
+
+
+
+ +
+ +
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_visualization/dashboard_python.html b/how_to/data_visualization/dashboard_python.html new file mode 100644 index 00000000..6786bab7 --- /dev/null +++ b/how_to/data_visualization/dashboard_python.html @@ -0,0 +1,597 @@ + + + + + + + + +Building a dashboard in Python — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Building a dashboard in Python#

+

In a previous guide we discovered how we could build data pipelines in Python, here we will pick up where we left of and build an entire dashboard in Python.

+

To start with let us declare the Pipeline we will be working with again and initialize the Panel extension so we can render output and tables.

+
import lumen as lm
+import panel as pn
+
+pn.extension('tabulator', design='material')
+
+pipeline = lm.Pipeline.from_spec({
+    'source': {
+        'type': 'file',
+        'tables': {
+            'penguins': 'https://datasets.holoviz.org/penguins/v1/penguins.csv'
+        }
+    },
+    'filters': [
+        {'type': 'widget', 'field': 'island'},
+        {'type': 'widget', 'field': 'sex'},
+        {'type': 'widget', 'field': 'year'}
+    ],
+    'auto_update': False
+})
+
+pipeline
+
+
+
+ +
+

Attaching Views#

+

Attaching a View to a Pipeline only requires passing the pipeline as an argument to the View constructor. The View will now be linked to the pipeline and update when we change it:

+
scatter = lm.views.hvPlotView(
+    pipeline=pipeline, kind='scatter', x='bill_length_mm', y='bill_depth_mm', by='species',
+    height=300, responsive=True
+)
+
+scatter
+
+
+
+ +

Now let us create one more view, a Table:

+
table = lm.views.Table(pipeline=pipeline, page_size=10, sizing_mode='stretch_width')
+
+table
+
+
+
+ +
+
+

Laying out views#

+

Now we could lay these components out using Panel and publish a Panel dashboard but for now we will stick entirely with Lumen components. The Lumen Layout component will let us arrange one or more views. Here we will take our two views and put the in layout:

+
layout = lm.Layout(views={'scatter': scatter, 'table': table}, title='Palmer Penguins')
+
+layout
+
+
+
+ +
+
+

Building the dashboard#

+

Finally we can add our Layout to a Dashboard instance and give the dashboard a title via the config option.

+
lm.Dashboard(config={'title': 'Palmer Penguins'}, layouts=[layout])
+
+
+
+ +
+

Note

+

A Dashboard (like most other components) can be previewed by displaying itself in notebook environments or by using .show() in a REPL. To serve it as a standalone application use the .servable() method and launch the notebook or script with panel serve app.py.

+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_visualization/deploy.html b/how_to/data_visualization/deploy.html new file mode 100644 index 00000000..8641f6e2 --- /dev/null +++ b/how_to/data_visualization/deploy.html @@ -0,0 +1,440 @@ + + + + + + + + +Deploy a dashboard — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Deploy a dashboard#

+
+

What does this guide solve?

+

Whether you are still developing or have already completed your specification file, deployment creates a visual instantiation of your dashboard.

+
+

Run the code below to start a Lumen server that displays your dashboard in a browser window. Change <dashboard.yaml> to the path of your YAML specification file.

+
lumen serve <dashboard.yaml> --show
+
+
+

If you are developing a dashboard using a Python script (see Lumen in Python guide) instead of a YAML file, you can use the same deployment approach by supplying the path to the Python script.

+
lumen serve <dashboard.py> --show
+
+
+
+

Deploy during development#

+

While developing with Lumen, it is a great idea to visualize the progress of your dashboard. The code below uses --autoreload to refresh the view every time you save your YAML specification file.

+
lumen serve <dashboard.yaml> --show --autoreload
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_visualization/index.html b/how_to/data_visualization/index.html new file mode 100644 index 00000000..aaa066c9 --- /dev/null +++ b/how_to/data_visualization/index.html @@ -0,0 +1,417 @@ + + + + + + + + +Visualize and Deploy — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+

.. raw:: html + + +

+
+

Visualize and Deploy#

+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/data_visualization/views.html b/how_to/data_visualization/views.html new file mode 100644 index 00000000..a8574fa3 --- /dev/null +++ b/how_to/data_visualization/views.html @@ -0,0 +1,480 @@ + + + + + + + + +How to define views — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

How to define views#

+
+

What does this guide solve?

+

This guide will show you how to define views on your dashboard

+
+
+

Overview#

+

A view is the final output of a dashboard, but to be able to create a view, at least one data Source is needed. +The following example source is a table containing data about individual penguins with various measurements. +This source could have been filtered or transformed but is omitted to keep the example simple.

+

The views are located in the layouts area and can take the form of various visual components. +Lumen includes many View types and is built so that you can easily use components from the Holoviz ecosystem, such as a scatter plot from hvPlot or an indicator from Panel.

+

+

Below is an example of two views of the same data - a scatter plot and a table.

+
+ +
+
sources:
+  penguin_source:
+    type: file
+    tables:
+      penguin_table: https://datasets.holoviz.org/penguins/v1/penguins.csv
+
+layouts:
+  - title: Table
+    source: penguin_source
+    views:
+      - type: hvplot
+        table: penguin_table
+        kind: scatter
+        color: species
+      - type: table
+        table: penguin_table
+
+
+
+ +
+
import panel as pn
+from lumen.pipeline import Pipeline
+from lumen.views import Table, hvPlotView
+
+pn.extension("tabulator")
+
+data_url = "https://datasets.holoviz.org/penguins/v1/penguins.csv"
+pipeline = Pipeline.from_spec(
+    {
+        "source": {"type": "file", "tables": {"penguin_table": data_url}},
+    }
+)
+
+pn.Column(hvPlotView(pipeline=pipeline), Table(pipeline=pipeline))
+
+
+

To arrange the Lumen dashboard views in Python, use Panel, as shown here.

+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/index.html b/how_to/index.html new file mode 100644 index 00000000..c061d8d0 --- /dev/null +++ b/how_to/index.html @@ -0,0 +1,586 @@ + + + + + + + + +How to Guides — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

How to Guides#

+

Lumen’s How to Guides provide step by step recipes for solving essential problems and tasks. They are more advanced than the Getting Started material and assume some knowledge of how Lumen works.

+
+

Data Intake#

+
+
+
+
+
+
+ Access Files
+

Learn how to use a local or remote file as a source for your dashboard.

+
+
+
+
+
+
+
+ Cache Data
+

Learn how to locally cache data to speed up reloading from a remote Source.

+
+
+
+
+
+
+
+

Data Processing#

+
+
+
+
+
+
+ Build Pipelines with Python
+

Learn the basics of how to build a Lumen Pipeline programmatically with Python.

+
+
+
+
+
+
+
+ Branch a Pipeline
+

Learn how to build branching pipelines, allowing for views of the same source data at different steps in processing.

+
+
+
+
+
+
+
+

Visualize and Deploy#

+
+
+
+
+
+
+ Define Views
+

Learn how to define views on your dashboard.

+
+
+
+
+
+
+
+ Visualize Dashboards with Python
+

Learn how to build a Lumen Dashboard programmatically with Python.

+
+
+
+
+
+
+
+ Deploy
+

Learn how to deploy a visual instantiation of your dashboard.

+
+
+
+
+
+
+
+

Validation#

+
+
+
+
+
+
+ Validate Specification
+

Learn how to validate the YAML file that specifies a Lumen dashboard.

+
+
+
+
+
+
+
+

Data Output#

+
+
+
+
+
+
+ Enable Data Download
+

Learn how to enable your dashboard’s viewer to download data.

+
+
+
+
+
+
+
+

Advanced Topics#

+
+
+
+
+
+
+ Reference Variables
+

How to use variables and references to link objects across the YAML file.

+
+
+
+
+
+
+
+ Access Custom Components
+

Learn how to access local files that build custom components.

+
+
+
+
+
+
+
+ Configure Authentication
+

Learn how to configure authentication for your dashboard.

+
+
+
+
+
+
+
+ Define Callbacks
+

Learn how to perform custom actions with callbacks.

+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/validation/index.html b/how_to/validation/index.html new file mode 100644 index 00000000..068e62eb --- /dev/null +++ b/how_to/validation/index.html @@ -0,0 +1,417 @@ + + + + + + + + +Validation — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+

.. raw:: html + + +

+
+

Validation#

+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/how_to/validation/validate.html b/how_to/validation/validate.html new file mode 100644 index 00000000..47951064 --- /dev/null +++ b/how_to/validation/validate.html @@ -0,0 +1,488 @@ + + + + + + + + +Validate the specification — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Validate the specification#

+
+

What does this guide solve?

+

This guide shows you how to validate the YAML file that specifies a Lumen dashboard.

+
+
+

Run the specification routine#

+

Use the lumen validate command line tool to run the validation. Insert the path to your specification file in place of <dashboard.yml> below.

+
lumen validate <dashboard.yaml>
+
+
+
+
+

Debug an invalid specification file#

+

When the validation fails, it will provide an error message indicating the type and location of the issue.

+
+

Indentation errors#

+

Indentation errors often show up as “expected… but found…”

+
expected <block end>, but found '?'
+  in "<unicode string>", line 28, column 3:
+      facet:
+      ^
+
+
+

They may also appear as messages about certain values not being allowed in this hierarchy level:

+
ERROR: mapping values are not allowed here
+  in "<unicode string>", line 6, column 11:
+        shared: true
+              ^
+
+
+
+
+

Invalid keys or values#

+

For constrained key and value fields, invalid entries will get caught, and a recommendation may be provided:

+
View component specification declared unknown type 'hvplotqedq'. Did you mean 'hvplot or 'hvplot_ui'?
+
+    table: southern_rockies
+    type: hvplotqedq
+    kind: line
+    x: time
+    y: precip
+    by:
+    - model
+    - emissions
+    min_height: 200
+    responsive: true
+
+
+
+
+

Package not installed#

+

The validation will also catch the declaration of packages not installed. For example:

+
ERROR: In order to use the source component 'intake', the 'intake' package must be installed.
+
+
+

In this case, simply install the package into your environment, such as with:

+
conda install intake
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 00000000..9d87c76b --- /dev/null +++ b/index.html @@ -0,0 +1,463 @@ + + + + + + + + +Welcome to Lumen! — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+ +
+
+

Welcome to Lumen!#

+ +
+
+
+
+
+
+Bike Sharing
+_images/bikes.png +
+
+
+
+
+
+
+NYC Taxi
+_images/nyc_taxi.png +
+
+
+
+
+
+
+Penguins
+_images/penguins.png +
+
+
+
+
+
+
+Windturbines
+_images/windturbines.png +
+
+
+
+
+
+
+Seattle Weather
+_images/seattle.png +
+
+
+
+
+
+
+Earthquakes
+_images/earthquakes.png +
+
+
+
+
+

The Lumen project provides a framework for visual analytics, which allows users to build data-driven dashboards using a simple, yet highly expressive, declarative specification.

+

If you’ve used commerical BI tools you will know the pain of ensuring that the data is in the format required by the visualization components. When data is managed by different teams this means coordinating between teams and pushing the transformation into your database or data lake. Lumen aims to provide an highly extensible system around data intake, data processing and visualization that allows you to quickly iterate to gain insights in your data.

+

The power of Lumen comes from the ability to leverage the powerful data intake, data processing and data visualization libraries available in the PyData ecosystem.

+
    +
  • Data Intake: A flexible system for declaring data sources with strong integration with Intake, allows Lumen to query data from a wide range of sources including many file formats such as CSV or Parquet but also SQL and many others.

  • +
  • Data Processing: Internally Lumen stores data as DataFrame objects, allowing users to leverage familiar APIs for filtering and transforming data using Pandas while also providing the ability to scale these transformations out to a cluster thanks to Dask but also allows you to dynamically generate SQL queries to push the computation into your database.

  • +
  • Data Visualization: Since Lumen is built on Panel all the most popular plotting libraries and many other components such as powerful datagrids and BI indicators are supported.

  • +
+

The core strengths of Lumen include:

+
    +
  • Flexibility: The design of Lumen allows flexibly combining data intake, data processing and data visualization into a simple declarative pipeline.

  • +
  • Extensibility: Every part of Lumen is designed to be extended letting you define custom Source, Filter, Transform and View components.

  • +
  • Scalability: Lumen is designed with performance in mind and supports scalable Dask DataFrames out of the box, letting you scale to datasets larger than memory or even scale out to a cluster.

  • +
  • Security: Lumen ships with a wide range of OAuth providers out of the box, making it a breeze to add authentication to your applications.

  • +
+

Build reusable components to drive your visual analytics that can be reused even by team members who are not Python experts.

+
+
+
+
+
+
+ Installation
+

Install Lumen in a few easy steps

+
+
+
+
+
+
+
+ Build a dashboard
+

How to build a Lumen dashboard

+
+
+
+
+
+
+
+ Core concepts
+

Get an overview of the core concepts of Lumen

+
+
+
+
+
+
+
+ Data Pipelines
+

Discover how to build powerful data pipelines with with Lumen.

+
+
+
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/objects.inv b/objects.inv new file mode 100644 index 00000000..fc4fb421 Binary files /dev/null and b/objects.inv differ diff --git a/reference/Config.html b/reference/Config.html new file mode 100644 index 00000000..877e8ab2 --- /dev/null +++ b/reference/Config.html @@ -0,0 +1,586 @@ + + + + + + + + +Config — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Config#

+
+
+class lumen.dashboard.Config(*, auto_update, background_load, editable, layout, loading_color, loading_spinner, logo, ncols, on_error, on_loaded, on_session_created, on_session_destroyed, on_update, reloadable, show_traceback, sync_with_url, template, theme, title, name)#
+

Config provides high-level configuration options for the +lumen.dashboard.Dashboard.

+
+
+
+

Parameters#

+
+
+
+
+
+
+auto_update
+

type: bool
default: None
Whether changes in filters, transforms and references automaticallytrigger updates in the data or whether an update has to be triggeredmanually using the update event or the update button in the UI.

+
+
+
+
+
+
+
+background_load
+

type: bool
default: False
Whether to load any layouts in the background.

+
+
+
+
+
+
+
+editable
+

type: bool
default: False
Whether the dashboard specification is editable from withinthe deployed dashboard.

+
+
+
+
+
+
+
+layout
+

type: Any
default: panel.FlexBox
Possible values: panel.Accordion | panel.Column | panel.GridBox | panel.Row | panel.Tabs | panel.FlexBox
Overall layout of the dashboard.

+
+
+
+
+
+
+
+loading_color
+

type: Any
default: '#0072B5'
Color of the loading indicator.

+
+
+
+
+
+
+
+loading_spinner
+

type: Any
default: 'arc'
Possible values: 'arc' | 'arcs' | 'bar' | 'dots' | 'petal'
Loading indicator to use when component loading parameter is set.

+
+
+
+
+
+
+
+logo
+

type: str
default: None
A logo to add to the theme.

+
+
+
+
+
+
+
+name
+

type: str
default: 'Config'
String identifier for this object.

+
+
+
+
+
+
+
+ncols
+

type: int
default: 3
bounds: (1, None)
Number of columns to lay out layouts in.

+
+
+
+
+
+
+
+on_error
+

type: Any
default: None
Callback that fires if an error occurs in a dashboard callback.The exception is passed as the first argument.

+
+
+
+
+
+
+
+on_loaded
+

type: Any
default: None
Callback that fires when a user frontend session is fully loaded.

+
+
+
+
+
+
+
+on_session_created
+

type: Any
default: None
Callback that fires when a user session is created.

+
+
+
+
+
+
+
+on_session_destroyed
+

type: Any
default: None
Callback that fires when a user session is destroyed.

+
+
+
+
+
+
+
+on_update
+

type: Any
default: None
Callback that fires when a pipeline is updated. The updatedpipeline is passed as the first argument.

+
+
+
+
+
+
+
+reloadable
+

type: bool
default: True
Whether to allow reloading data from source(s) using a button.

+
+
+
+
+
+
+
+show_traceback
+

type: bool
default: True
Whether to show the traceback if an error happens.

+
+
+
+
+
+
+
+sync_with_url
+

type: bool
default: False
Whether to sync current state of the application.

+
+
+
+
+
+
+
+template
+

type: Any
default: panel.template.MaterialTemplate
Possible values: panel.template.BootstrapTemplate | panel.template.ReactTemplate | panel.template.GoldenTemplate | panel.template.MaterialTemplate | panel.template.VanillaTemplate | panel.template.FastListTemplate | panel.template.SlidesTemplate | panel.template.FastGridTemplate
The Panel template to render the dashboard into.

+
+
+
+
+
+
+
+theme
+

type: Any
default: panel.theme.DefaultTheme
Possible values: panel.theme.DefaultTheme | panel.theme.DarkTheme
The Panel template theme to style the dashboard with.

+
+
+
+
+
+
+
+title
+

type: str
default: 'Lumen Dashboard'
The title of the dashboard.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Config.construct_template()#
+
+
+
+Config.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/Defaults.html b/reference/Defaults.html new file mode 100644 index 00000000..9c5fe5ac --- /dev/null +++ b/reference/Defaults.html @@ -0,0 +1,459 @@ + + + + + + + + +Defaults — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Defaults#

+
+
+class lumen.dashboard.Defaults(*, download, filters, sources, transforms, views, name)#
+

Defaults to apply to the component classes.

+
+
+
+

Parameters#

+
+
+
+
+
+
+download
+

type: dict
default: {}
Defaults for the Download object

+
+
+
+
+
+
+
+filters
+

type: list[dict]
default: []
Defaults for Filter objects.

+
+
+
+
+
+
+
+name
+

type: str
default: 'Defaults'
String identifier for this object.

+
+
+
+
+
+
+
+sources
+

type: list[dict]
default: []
Defaults for Source objects.

+
+
+
+
+
+
+
+transforms
+

type: list[dict]
default: []
Defaults for Transform objects.

+
+
+
+
+
+
+
+views
+

type: list[dict]
default: []
Defaults for View objects.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Defaults.apply()#
+
+
+
+Defaults.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/Layout.html b/reference/Layout.html new file mode 100644 index 00000000..034d0244 --- /dev/null +++ b/reference/Layout.html @@ -0,0 +1,612 @@ + + + + + + + + +Layout — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Layout#

+
+
+class lumen.layout.Layout(*, auto_update, description, download, facet, layout, refresh_rate, reloadable, rerender, show_title, source, title, tsformat, views, name)#
+

Layout renders one or more lumen.views.base.View components +into a layout.

+

Additionally it provides functionality for facetting the +lumen.views.base.View objects by grouping the data along +some dimension.

+
+
+
+

Parameters#

+
+
+
+
+
+
+auto_update
+

type: bool
default: True
Whether changes in filters, transforms and references automaticallytrigger updates in the data or whether an update has to be triggeredmanually using the update event or the update button in the UI.

+
+
+
+
+
+
+
+description
+

type: str
default: None
A description about the app will be added to the top of the sidebar

+
+
+
+
+
+
+
+download
+

type: lumen.layout.Download
default: Download()
The download objects determines whether and how the source tablescan be downloaded.

+
+
+
+
+
+
+
+facet
+

type: lumen.layout.Facet
default: None
The facet object determines whether and how to facet the cardson the layout.

+
+
+
+
+
+
+
+layout
+

type: str | list | dict
default: 'column'
Defines the layout of the views in the monitor layout. Can be’column’, ‘row’, ‘grid’, ‘row’ or a nested list of indexescorresponding to the views, e.g. [[0, 1], [2]] will createa Column of one row containing views 0 and 1 and a second Rowcontaining view 2.

+
+
+
+
+
+
+
+name
+

type: str
default: 'Layout'
String identifier for this object.

+
+
+
+
+
+
+
+refresh_rate
+

type: int
default: None
bounds: None
How frequently to refresh the monitor by querying the adaptor.

+
+
+
+
+
+
+
+reloadable
+

type: bool
default: True
Whether to allow reloading data layout’s source using a button.

+
+
+
+
+
+
+
+rerender
+

type: bool
default: False
An event that is triggered whenever the View requests a re-render.

+
+
+
+
+
+
+
+show_title
+

type: bool
default: True
Whether to show the title in Card headers.

+
+
+
+
+
+
+
+source
+

type: lumen.Source
default: None
The Source queries the data from some data source.

+
+
+
+
+
+
+
+title   required
+

type: str
default: ''
A title for this Layout.

+
+
+
+
+
+
+
+tsformat
+

type: str
default: '%m/%d/%Y %H:%M:%S'

+
+
+
+
+
+
+
+views   required
+

type: list | dict
default: None
List or dictionary of View specifications.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Layout.get_cards() List[Card]#
+
+
+
+Layout.get_filter_panel(skip=None, apply_button: bool = True) Column#
+
+
+
+Layout.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+Layout.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+Layout.start(event: param.parameterized.Event | None = None)#
+

Starts any periodic callback instantiated on this object.

+
+
+
+Layout.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+Layout.update(*events: Event, clear_cache: bool = True)#
+

Updates the views on this layout by clearing any caches and +rerendering the views on this Layout.

+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/Pipeline.html b/reference/Pipeline.html new file mode 100644 index 00000000..1217e65f --- /dev/null +++ b/reference/Pipeline.html @@ -0,0 +1,679 @@ + + + + + + + + +Pipeline — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Pipeline#

+
+
+class lumen.pipeline.Pipeline(*, source, table, schema=None, filters=None, **params)#
+

Pipeline encapsulates filters and transformations applied to a +lumen.sources.base.Source table.

+

A Pipeline ingests data from a +lumen.sources.base.Source table or another Pipeline +applying the declared lumen.filters.base.Filter, +lumen.transforms.base.Transform and +lumen.transforms.sql.SQLTransform definitions. It can be +used to drive one or more visual outputs or leveraged as a +standalone component to encapsulate multiple data processing +steps.

+
+
+
+

Parameters#

+
+
+
+
+
+
+auto_update
+

type: bool
default: True
Whether changes in filters, transforms and references automaticallytrigger updates in the data or whether an update has to be triggeredmanually using the update event or the update button in the UI.

+
+
+
+
+
+
+
+data
+

type: pandas.DataFrame
default: None
The current data on this source.

+
+
+
+
+
+
+
+filters
+

type: list[lumen.Filter]
default: []
A list of Filters to apply to the source data.

+
+
+
+
+
+
+
+name
+

type: str
default: 'Pipeline'
String identifier for this object.

+
+
+
+
+
+
+
+pipeline
+

type: lumen.Pipeline
default: None
Optionally a pipeline may be chained to another pipeline.

+
+
+
+
+
+
+
+schema
+

type: dict
default: None
The schema of the input data.

+
+
+
+
+
+
+
+source
+

type: lumen.Source
default: None
The Source this pipeline is fed by.

+
+
+
+
+
+
+
+sql_transforms
+

type: list[lumen.transforms.SQLTransform]
default: []
A list of SQLTransforms to apply to the source data.

+
+
+
+
+
+
+
+table
+

type: str
default: ''
The name of the table driving this pipeline.

+
+
+
+
+
+
+
+transforms
+

type: list[lumen.Transform]
default: []
A list of Transforms to apply to the source data.

+
+
+
+
+
+
+
+update
+

type: bool
default: False
Update event trigger (if manual update is set).

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Pipeline.add_filter(filt: Union[Filter, Type[Filter], Widget], field: Optional[str] = None, **kwargs)#
+

Add a filter to the pipeline.

+
+
Parameters:
+
    +
  • filt (Filter | Type[Filter]) – The filter instance or filter type to add.

  • +
  • field (str | None) – The field to filter on (required to instantiate Filter type).

  • +
+
+
+
+
+
+Pipeline.add_transform(transform: Transform, **kwargs)#
+

Add a (SQL)Transform to the pipeline.

+
+
Parameters:
+

filt (Transform) – The Transform instance to add.

+
+
+
+
+
+Pipeline.chain(filters: Optional[List[Filter]] = None, transforms: Optional[List[Transform]] = None, sql_transforms: Optional[List[Transform]] = None, **kwargs)#
+

Chains additional filtering, transform and sql_transform operations +on an existing pipeline. Note that if one or more sql_transforms +are provided the pipeline is cloned rather than applying the +operations on top of the existing pipeline.

+
+
Parameters:
+
    +
  • filters (List[Filter] | None) – Additional filters to apply on top of existing pipeline.

  • +
  • transforms (List[Transform] | None) – Additional transforms to apply on top of existing pipeline.

  • +
  • sql_transforms (List[SQLTransform] | None) – Additional filters to apply on top of existing pipeline.

  • +
+
+
Return type:
+

Pipeline

+
+
+
+
+
+Pipeline.clone(**params) Pipeline#
+

Create a new instance of the pipeline with optionally overridden parameter values.

+
+
+
+Pipeline.precache(queries: Union[Dict[str, Dict[str, List[Any]]], List[Dict[str, Dict[str, Any]]]]) None#
+

Populates the cache of the lumen.sources.base.Source with the provided queries.

+

Queries can be provided in two formats:

+
+
    +
  • A dictionary containing ‘filters’ and ‘variables’ +dictionaries each containing lists of values to compute +a cross-product for, e.g.

    +
    +
    +
    {
    +
    ‘filters’: {

    <filter>’: [‘a’, ‘b’, ‘c’, …], +…

    +
    +
    +

    }, +‘variables’: {

    +
    +

    <variable>: [0, 2, 4, …], +…

    +
    +

    }

    +
    +
    +

    }

    +
    +
  • +
  • A list containing dictionaries of explicit values +for each filter and variables.

    +
    +
    +
    [{
    +

    ‘filters’: {<filter>: ‘a’}, +‘variables’: {<variable>: 0}

    +
    +

    }, +{

    +
    +

    ‘filters’: {<filter>: ‘a’}, +‘variables’: {<variable>: 1}

    +
    +
    +
    +

    ]

    +
    +
  • +
+
+
+
+
+Pipeline.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+Pipeline.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+Pipeline.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously +serialized components, e.g. to allow resolving of +references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+Pipeline.traverse(type) Union[List[Transform], List[Filter]]#
+

Returns all Filter or Transform objects in a potentially chained +pipeline.

+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/auth/Auth.html b/reference/auth/Auth.html new file mode 100644 index 00000000..23ca35fa --- /dev/null +++ b/reference/auth/Auth.html @@ -0,0 +1,411 @@ + + + + + + + + +Auth — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Auth#

+
+
+class lumen.auth.Auth(*, name)#
+

An AuthPlugin is given the auth specfication and can apply arbitrary +transforms to it.

+
+
+
+

Parameters#

+
+
+
+
+
+
+name
+

type: str
default: 'Auth'
String identifier for this object.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Auth.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+Auth.transform(spec: Dict[str, Any]) Dict[str, Any]#
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/auth/YamlAuthMapperPlugin.html b/reference/auth/YamlAuthMapperPlugin.html new file mode 100644 index 00000000..a4925de2 --- /dev/null +++ b/reference/auth/YamlAuthMapperPlugin.html @@ -0,0 +1,462 @@ + + + + + + + + +YamlAuthMapperPlugin type: yaml — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

YamlAuthMapperPlugin  type: yaml#

+
+
+class lumen.auth.YamlAuthMapperPlugin(*, yaml_file, name)#
+

The YamlAuthMapperPlugin uses a Yaml file to map auth keys +allowing more concise declarations for individual dashboards, e.g. +the following yaml specification:

+
+
+
group:
+
admins:
+
email:
+
+
+
+
users:
+
email:
+
+
+
+
+
+
+
+

will expand this auth spec:

+
+
+
auth:
+
group:
    +
  • admins

  • +
+
+
+
+
+
+

to this expanded spec:

+
+
+
+
+
+

Parameters#

+
+
+
+
+
+
+yaml_file
+

type: str | pathlib.Path
default: None

+
+
+
+
+
+
+
+
+

Methods#

+
+
+YamlAuthMapperPlugin.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+YamlAuthMapperPlugin.transform(spec: Dict[str, Any]) Dict[str, Any]#
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/auth/index.html b/reference/auth/index.html new file mode 100644 index 00000000..0b5e311e --- /dev/null +++ b/reference/auth/index.html @@ -0,0 +1,437 @@ + + + + + + + + +Auth — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Auth#

+
+
+class lumen.auth.Auth(*, name)#
+

An AuthPlugin is given the auth specfication and can apply arbitrary +transforms to it.

+
+
+
+

Parameters#

+
+
+
+
+
+
+name
+

type: str
default: 'Auth'
String identifier for this object.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Auth.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+Auth.transform(spec: Dict[str, Any]) Dict[str, Any]#
+
+
+
+

Types#

+
+
+
+
+
+
+Auth type: None
+

An AuthPlugin is given the auth specfication and can apply arbitrary

+
+
+
+
+
+
+
+YamlAuthMapperPlugin type: yaml
+

The YamlAuthMapperPlugin uses a Yaml file to map auth keys

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/filter/BinFilter.html b/reference/filter/BinFilter.html new file mode 100644 index 00000000..b7e9763c --- /dev/null +++ b/reference/filter/BinFilter.html @@ -0,0 +1,471 @@ + + + + + + + + +BinFilter type: bins — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

BinFilter  type: bins#

+
+
+class lumen.filters.base.BinFilter(*, bins, empty_select, labels, multi, default, disabled, throttled, visible, field, label, schema, shared, sync_with_url, table, value, name)#
+

BinFilter is a special WidgetFilter that allows selecting from a set of bins.

+

The bins must be declared from a list of tuples declaring the +lower- and upper-bound of each bin and an optional set of labels +of the same length.

+
+
+
+

Parameters#

+
+
+
+
+
+
+bins
+

type: list[Any]
default: []
A list of bins expressed as length two tuples.

+
+
+
+
+
+
+
+default
+

type: Any
default: None
The default value to use on the widget.

+
+
+
+
+
+
+
+disabled
+

type: bool
default: False
Whether the filter should be disabled.

+
+
+
+
+
+
+
+empty_select
+

type: bool
default: True
Add an option to Select widgets to indicate no filtering.

+
+
+
+
+
+
+
+labels
+

type: list[Any]
default: None
A list of labels for each bin (optional).

+
+
+
+
+
+
+
+multi
+

type: bool
default: True
Whether to use a single-value or multi-value selection widget.

+
+
+
+
+
+
+
+throttled
+

type: bool
default: True
If the widget has a value_throttled parameter use that instead,ensuring that no intermediate events are generated, e.g. whendragging a slider.

+
+
+
+
+
+
+
+visible
+

type: bool
default: True
Whether the filter should be visible.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+BinFilter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/filter/ConstantFilter.html b/reference/filter/ConstantFilter.html new file mode 100644 index 00000000..808b37e1 --- /dev/null +++ b/reference/filter/ConstantFilter.html @@ -0,0 +1,388 @@ + + + + + + + + +ConstantFilter type: constant — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

ConstantFilter  type: constant#

+
+
+class lumen.filters.base.ConstantFilter(*, field, label, schema, shared, sync_with_url, table, value, name)#
+

The ConstantFilter allows requesting a constant value from the +Source.

+
+
+
+

Methods#

+
+
+ConstantFilter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/filter/DateFilter.html b/reference/filter/DateFilter.html new file mode 100644 index 00000000..0f41c7b2 --- /dev/null +++ b/reference/filter/DateFilter.html @@ -0,0 +1,453 @@ + + + + + + + + +DateFilter type: date — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

DateFilter  type: date#

+
+
+class lumen.filters.base.DateFilter(*, mode, multi, default, disabled, throttled, visible, field, label, schema, shared, sync_with_url, table, value, name)#
+

DateFilter is a WidgetFilter specialized to select calendar dates.

+

Depending on whether multi selection is enabled a single date or +range of dates can be selected with a DatePicker or +DateRangeSlider respectively.

+
+
+
+

Parameters#

+
+
+
+
+
+
+default
+

type: Any
default: None
The default value to use on the widget.

+
+
+
+
+
+
+
+disabled
+

type: bool
default: False
Whether the filter should be disabled.

+
+
+
+
+
+
+
+mode
+

type: Any
default: 'slider'
Possible values: 'slider' | 'picker'
Whether to use a slider or a picker.

+
+
+
+
+
+
+
+multi
+

type: bool
default: True
Whether to use a single-value or multi-value/range selection widget.

+
+
+
+
+
+
+
+throttled
+

type: bool
default: True
Whether to throttle slider value changes.

+
+
+
+
+
+
+
+visible
+

type: bool
default: True
Whether the filter should be visible.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+DateFilter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/filter/DatetimeFilter.html b/reference/filter/DatetimeFilter.html new file mode 100644 index 00000000..40ad0b55 --- /dev/null +++ b/reference/filter/DatetimeFilter.html @@ -0,0 +1,453 @@ + + + + + + + + +DatetimeFilter type: datetime — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

DatetimeFilter  type: datetime#

+
+
+class lumen.filters.base.DatetimeFilter(*, mode, multi, default, disabled, throttled, visible, field, label, schema, shared, sync_with_url, table, value, name)#
+

DatetimeFilter is a WidgetFilter specialized to filter by datetimes.

+

Depending on whether multi selection is enabled a single date or +range of dates can be selected with a DatetimePicker or +DatetimeRangeSlider respectively.

+
+
+
+

Parameters#

+
+
+
+
+
+
+default
+

type: Any
default: None
The default value to use on the widget.

+
+
+
+
+
+
+
+disabled
+

type: bool
default: False
Whether the filter should be disabled.

+
+
+
+
+
+
+
+mode
+

type: Any
default: 'slider'
Possible values: 'slider' | 'picker'
Whether to use a slider or a picker.

+
+
+
+
+
+
+
+multi
+

type: bool
default: True
Whether to use a single-value or multi-value/range selection widget.

+
+
+
+
+
+
+
+throttled
+

type: bool
default: True
Whether to throttle slider value changes.

+
+
+
+
+
+
+
+visible
+

type: bool
default: True
Whether the filter should be visible.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+DatetimeFilter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/filter/FacetFilter.html b/reference/filter/FacetFilter.html new file mode 100644 index 00000000..811fb5e9 --- /dev/null +++ b/reference/filter/FacetFilter.html @@ -0,0 +1,389 @@ + + + + + + + + +FacetFilter type: facet — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

FacetFilter  type: facet#

+
+
+class lumen.filters.base.FacetFilter(*, field, label, schema, shared, sync_with_url, table, value, name)#
+

The FacetFilter allows faceting the data along some dimension to +allow a single View to be exploded into multiple by grouping over +one of the indexes.

+
+
+
+

Methods#

+
+
+FacetFilter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/filter/ParamFilter.html b/reference/filter/ParamFilter.html new file mode 100644 index 00000000..cd81cdd0 --- /dev/null +++ b/reference/filter/ParamFilter.html @@ -0,0 +1,407 @@ + + + + + + + + +ParamFilter type: param — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

ParamFilter  type: param#

+
+
+class lumen.filters.base.ParamFilter(*, parameter, field, label, schema, shared, sync_with_url, table, value, name)#
+

ParamFilter reflects the value of a parameter declared on a View.

+

The ParamFilter can be used to implement cross-filtering between +different views.

+
+
+
+

Parameters#

+
+
+
+
+
+
+parameter
+

type: param.Parameter | str
default: None
Reference to a Parameter on an existing View.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+ParamFilter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/filter/WidgetFilter.html b/reference/filter/WidgetFilter.html new file mode 100644 index 00000000..c350a984 --- /dev/null +++ b/reference/filter/WidgetFilter.html @@ -0,0 +1,470 @@ + + + + + + + + +WidgetFilter type: widget — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

WidgetFilter  type: widget#

+
+
+class lumen.filters.base.WidgetFilter(*, empty_select, max_options, multi, widget, default, disabled, throttled, visible, field, label, schema, shared, sync_with_url, table, value, name)#
+

WidgetFilter generates a Widget from the table schema provided by a Source.

+

By default the widget type will be inferred from the data and +depending on whether multi value selection is enabled.

+
+
+
+

Parameters#

+
+
+
+
+
+
+default
+

type: Any
default: None
The default value to use on the widget.

+
+
+
+
+
+
+
+disabled
+

type: bool
default: False
Whether the filter should be disabled.

+
+
+
+
+
+
+
+empty_select
+

type: bool
default: True
Add an option to Select widgets to indicate no filtering.

+
+
+
+
+
+
+
+max_options
+

type: int
default: 500
bounds: None
Maximum number of options to render.

+
+
+
+
+
+
+
+multi
+

type: bool
default: True
Whether to use a single-value or multi-value selection widget,e.g. for a numeric value this could be a regular slider or arange slider.

+
+
+
+
+
+
+
+throttled
+

type: bool
default: True
If the widget has a value_throttled parameter use that instead,ensuring that no intermediate events are generated, e.g. whendragging a slider.

+
+
+
+
+
+
+
+visible
+

type: bool
default: True
Whether the filter should be visible.

+
+
+
+
+
+
+
+widget
+

type: panel.widgets.Widget
default: None
The widget instance. When declared in a specification a fullmodule path to a Panel widget class can be provided to overridethe default inferred widget.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+WidgetFilter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/filter/index.html b/reference/filter/index.html new file mode 100644 index 00000000..b516e818 --- /dev/null +++ b/reference/filter/index.html @@ -0,0 +1,539 @@ + + + + + + + + +Filter — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Filter#

+
+
+class lumen.filters.base.Filter(*, field, label, schema, shared, sync_with_url, table, value, name)#
+

Filter components supply the filter values used by Source components to query data. .

+
+
+
+

Parameters#

+
+
+
+
+
+
+field   required
+

type: str
default: ''
The field being filtered.

+
+
+
+
+
+
+
+label
+

type: str
default: ''
A label for the Filter.

+
+
+
+
+
+
+
+name
+

type: str
default: 'Filter'
String identifier for this object.

+
+
+
+
+
+
+
+schema
+

type: dict
default: None
The JSON schema provided by the Source declaring informationabout the data to be filtered.

+
+
+
+
+
+
+
+shared
+

type: bool
default: False
Whether the filter is shared across all layouts.

+
+
+
+
+
+
+
+sync_with_url
+

type: bool
default: True
Whether to sync the filter state with the URL parameters.

+
+
+
+
+
+
+
+table
+

type: str
default: None
The table being filtered. If None applies to all tables.

+
+
+
+
+
+
+
+value
+

type: Any
default: None
The current filter value.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Filter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+

Types#

+
+
+
+
+
+
+ConstantFilter type: constant
+

The ConstantFilter allows requesting a constant value from the

+
+
+
+
+
+
+
+FacetFilter type: facet
+

The FacetFilter allows faceting the data along some dimension to

+
+
+
+
+
+
+
+ParamFilter type: param
+

ParamFilter reflects the value of a parameter declared on a View.

+
+
+
+
+
+
+
+WidgetFilter type: widget
+

WidgetFilter generates a Widget from the table schema provided by a Source.

+
+
+
+
+
+
+
+BinFilter type: bins
+

BinFilter is a special WidgetFilter that allows selecting from a set of bins.

+
+
+
+
+
+
+
+DateFilter type: date
+

DateFilter is a WidgetFilter specialized to select calendar dates.

+
+
+
+
+
+
+
+DatetimeFilter type: datetime
+

DatetimeFilter is a WidgetFilter specialized to filter by datetimes.

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/index.html b/reference/index.html new file mode 100644 index 00000000..a54568c2 --- /dev/null +++ b/reference/index.html @@ -0,0 +1,1020 @@ + + + + + + + + +Reference — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Reference#

+
+

Config#

+

Config provides high-level configuration options for the

+
+
+

Variable#

+

Variable components declare values that can be referenced from other components.

+
+
+
+
+
+
+Constant type: constant
+

Constant declares a constant value that can be referenced.

+
+
+
+
+
+
+
+EnvVariable type: env
+

EnvVariable fetches an environment variable that can be referenced.

+
+
+
+
+
+
+
+Widget type: widget
+

Widget variables dynamically reflect the current widget value.

+
+
+
+
+
+
+
+Parameter type: param
+

Parameter variables reflect the current value of a parameter.

+
+
+
+
+
+
+
+URLQuery type: url
+

URLQuery variables reflect the value of a URL query parameter.

+
+
+
+
+
+
+
+Cookie type: cookie
+

Cookie variables reflect the value of a cookie in the request.

+
+
+
+
+
+
+
+UserInfo type: user
+

UserInfo variables reflect a value in the user info returned by an OAuth provider.

+
+
+
+
+
+
+
+Header type: header
+

Header variables reflect the value of a request header.

+
+
+
+
+
+
+
+

Pipeline#

+

Pipeline encapsulates filters and transformations applied to a

+
+
+

Source#

+

Source components provide allow querying all kinds of data.

+
+
+
+
+
+
+RESTSource type: rest
+

RESTSource allows querying REST endpoints conforming to the Lumen REST specification.

+
+
+
+
+
+
+
+FileSource type: file
+

FileSource loads CSV, Excel and Parquet files using pandas and dask read_* functions.

+
+
+
+
+
+
+
+WebsiteSource type: live
+

WebsiteSource queries whether a website responds with a 400 status code.

+
+
+
+
+
+
+
+PanelSessionSource type: session_info
+

PanelSessionSource queries the session_info endpoint of a Panel application.

+
+
+
+
+
+
+
+JoinedSource type: join
+

JoinedSource performs a join on tables from one or more sources.

+
+
+
+
+
+
+
+DerivedSource type: derived
+

DerivedSource applies filtering and transforms to tables from other sources.

+
+
+
+
+
+
+
+JSONSource type: json
+

The JSONSource is very similar to the FileSource but loads json files.

+
+
+
+
+
+
+
+IntakeSource type: intake
+

An IntakeSource loads data from an Intake catalog.

+
+
+
+
+
+
+
+IntakeSQLSource type: intake_sql
+

IntakeSQLSource extends the IntakeSource with support for SQL data.

+
+
+
+
+
+
+
+

Filter#

+

Filter components supply the filter values used by Source components to query data. .

+
+
+
+
+
+
+ConstantFilter type: constant
+

The ConstantFilter allows requesting a constant value from the

+
+
+
+
+
+
+
+FacetFilter type: facet
+

The FacetFilter allows faceting the data along some dimension to

+
+
+
+
+
+
+
+ParamFilter type: param
+

ParamFilter reflects the value of a parameter declared on a View.

+
+
+
+
+
+
+
+WidgetFilter type: widget
+

WidgetFilter generates a Widget from the table schema provided by a Source.

+
+
+
+
+
+
+
+BinFilter type: bins
+

BinFilter is a special WidgetFilter that allows selecting from a set of bins.

+
+
+
+
+
+
+
+DateFilter type: date
+

DateFilter is a WidgetFilter specialized to select calendar dates.

+
+
+
+
+
+
+
+DatetimeFilter type: datetime
+

DatetimeFilter is a WidgetFilter specialized to filter by datetimes.

+
+
+
+
+
+
+
+

Transform#

+

Transform components implement transforms of DataFrame objects.

+
+
+
+
+
+
+Filter type: None
+

Filter transform implement the filtering behavior of Filter components.

+
+
+
+
+
+
+
+HistoryTransform type: history
+

HistoryTransform accumulates a history of the queried data.

+
+
+
+
+
+
+
+Aggregate type: aggregate
+

Aggregate one or more columns or indexes, see pandas.DataFrame.groupby.

+
+
+
+
+
+
+
+Sort type: sort
+

Sort on one or more columns, see pandas.DataFrame.sort_values.

+
+
+
+
+
+
+
+Query type: query
+

Query applies the pandas.DataFrame.query method.

+
+
+
+
+
+
+
+Columns type: columns
+

Columns selects a subset of columns.

+
+
+
+
+
+
+
+Astype type: as_type
+

Astype transforms the type of one or more columns.

+
+
+
+
+
+
+
+Stack type: stack
+

Stack applies pandas.DataFrame.stack to the declared level.

+
+
+
+
+
+
+
+Unstack type: unstack
+

Unstack applies pandas.DataFrame.unstack to the declared level.

+
+
+
+
+
+
+
+Iloc type: iloc
+

Iloc applies integer slicing to the data, see pandas.DataFrame.iloc.

+
+
+
+
+
+
+
+Sample type: sample
+

Sample returns a random sample of items.

+
+
+
+
+
+
+
+Compute type: compute
+

Compute turns a dask.dataframe.DataFrame into a pandas.DataFrame.

+
+
+
+
+
+
+
+Pivot type: pivot
+

Pivot applies pandas.DataFrame.pivot given an index, columns, and values.

+
+
+
+
+
+
+
+Melt type: melt
+

Melt applies the pandas.melt operation given the id_vars and value_vars.

+
+
+
+
+
+
+
+SetIndex type: set_index
+

SetIndex promotes DataFrame columns to indexes, see pandas.DataFrame.set_index.

+
+
+
+
+
+
+
+ResetIndex type: reset_index
+

ResetIndex resets DataFrame indexes to columns or drops them, see pandas.DataFrame.reset_index

+
+
+
+
+
+
+
+Rename type: rename
+

Rename renames columns or indexes, see pandas.DataFrame.rename.

+
+
+
+
+
+
+
+RenameAxis type: rename_axis
+

Set the name of the axis for the index or columns,

+
+
+
+
+
+
+
+Count type: count
+

Counts non-nan values in each column of the DataFrame and returns

+
+
+
+
+
+
+
+Sum type: sum
+

Sums numeric values in each column of the DataFrame and returns a

+
+
+
+
+
+
+
+Eval type: eval
+

Applies an eval assignment expression to a DataFrame. The

+
+
+
+
+
+
+
+project_lnglat type: project_lnglat
+

project_lnglat projects the given longitude/latitude columns to Web Mercator.

+
+
+
+
+
+
+
+SQLGroupBy type: sql_group_by
+

Performs a Group-By and aggregation

+
+
+
+
+
+
+
+SQLLimit type: sql_limit
+

Performs a LIMIT SQL operation on the query

+
+
+
+
+
+
+
+SQLDistinct type: sql_distinct
+

SQLDistinct Transform

+
+
+
+
+
+
+
+SQLMinMax type: sql_minmax
+

SQLMinMax Transform

+
+
+
+
+
+
+
+SQLColumns type: sql_columns
+

SQLColumns Transform

+
+
+
+
+
+
+
+SQLFilter type: sql_filter
+

Translates Lumen Filter query into a SQL WHERE statement.

+
+
+
+
+
+
+
+

View#

+

View components provide a visual representation for the data returned

+
+
+
+
+
+
+Panel type: panel
+

Panel views provide a way to declaratively wrap a Panel component.

+
+
+
+
+
+
+
+StringView type: string
+

StringView renders the latest value of the field as a HTML string.

+
+
+
+
+
+
+
+IndicatorView type: indicator
+

IndicatorView renders the latest field value as a Panel Indicator.

+
+
+
+
+
+
+
+Table type: table
+

Table renders data using the powerful Panel Tabulator component.

+
+
+
+
+
+
+
+DownloadView type: download
+

DownloadView renders a button that allows downloading data as CSV, Excel, and parquet files.

+
+
+
+
+
+
+
+PerspectiveView type: perspective
+

PerspectiveView renders data into a Perspective widget.

+
+
+
+
+
+
+
+AltairView type: altair
+

AltairView provides a declarative way to render Altair charts.

+
+
+
+
+
+
+
+hvPlotUIView type: hvplot_ui
+

hvPlotUIView displays provides a component for exploring datasets interactively.

+
+
+
+
+
+
+
+hvPlotView type: hvplot
+

hvPlotView renders the queried data as a bokeh plot generated with hvPlot.

+
+
+
+
+
+
+
+

Layout#

+

Layout renders one or more :class:lumen.views.base.View components

+
+
+

Auth#

+

An AuthPlugin is given the auth specfication and can apply arbitrary

+
+
+
+
+
+
+Auth type: None
+

An AuthPlugin is given the auth specfication and can apply arbitrary

+
+
+
+
+
+
+
+YamlAuthMapperPlugin type: yaml
+

The YamlAuthMapperPlugin uses a Yaml file to map auth keys

+
+
+
+
+
+
+
+

Defaults#

+

Defaults to apply to the component classes.

+
+
+
+ +
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/DerivedSource.html b/reference/source/DerivedSource.html new file mode 100644 index 00000000..8a6b2d01 --- /dev/null +++ b/reference/source/DerivedSource.html @@ -0,0 +1,531 @@ + + + + + + + + +DerivedSource type: derived — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

DerivedSource  type: derived#

+
+
+class lumen.sources.base.DerivedSource(*, filters, source, tables, transforms, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

DerivedSource applies filtering and transforms to tables from other sources.

+

A DerivedSource references tables on other sources and optionally +allows applying filters and transforms to the returned data which +is then made available as a new (derived) table.

+

The DerivedSource has two modes:

+

Table Mode

+

When an explicit tables specification is provided full control +over the exact tables to filter and transform is available. This +is referred to as the ‘table’ mode.

+

In ‘table’ mode the tables can reference any table on any source +using the reference syntax and declare filters and transforms to +apply to that specific table, e.g. a table specification might +look like this:

+
{
+  'derived_table': {
+    'source': 'original_source',
+    'table': 'original_table'
+    'filters': [
+      ...
+    ],
+    'transforms': [
+      ...
+    ]
+  }
+}
+
+
+

Mirror mode

+

When a source is declared all tables on that Source are mirrored +and filtered and transformed according to the supplied filters +and transforms. This is referred to as ‘mirror’ mode.

+

In mirror mode the DerivedSource may reference an existing source +directly, e.g.:

+
{
+    'type': 'derived',
+    'source': 'original_source',
+    'filters': [...],
+    'transforms': [...],
+}
+
+
+
+
+
+

Parameters#

+
+
+
+
+
+
+filters
+

type: list[Any]
default: []
A list of filters to apply to all tables of this source.

+
+
+
+
+
+
+
+source
+

type: lumen.Source
default: None
A source to mirror the tables on.

+
+
+
+
+
+
+
+tables
+

type: dict
default: {}
The dictionary of tables and associated filters and transforms.

+
+
+
+
+
+
+
+transforms
+

type: list[Any]
default: []
A list of transforms to apply to all tables of this source.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+DerivedSource.clear_cache()#
+

Clears any cached data.

+
+
+
+DerivedSource.get(table: str, **query) DataFrame#
+

Return a table; optionally filtered by the given query.

+
+
Parameters:
+
    +
  • table (str) – The name of the table to query

  • +
  • query (dict) – A dictionary containing all the query parameters

  • +
+
+
Returns:
+

A DataFrame containing the queried table.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+DerivedSource.get_schema(table: Optional[str] = None) Union[Dict[str, Dict[str, Any]], Dict[str, Any]]#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+DerivedSource.get_tables() List[str]#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+DerivedSource.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/FileSource.html b/reference/source/FileSource.html new file mode 100644 index 00000000..6ebdb4eb --- /dev/null +++ b/reference/source/FileSource.html @@ -0,0 +1,495 @@ + + + + + + + + +FileSource type: file — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

FileSource  type: file#

+
+
+class lumen.sources.base.FileSource(*, dask, kwargs, tables, use_dask, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

FileSource loads CSV, Excel and Parquet files using pandas and dask read_* functions.

+

The FileSource can declare a list or dictionary of local or +remote files which are then loaded using either pandas.read_* or +dask.dataframe.read_* functions depending on whether use_dask +is enabled.

+
+
+
+

Parameters#

+
+
+
+
+
+
+dask
+

type: bool
default: False
Whether to return a Dask dataframe.

+
+
+
+
+
+
+
+kwargs
+

type: dict
default: None
Keyword arguments to the pandas/dask loading function.

+
+
+
+
+
+
+
+tables
+

type: list | dict
default: None
List or dictionary of tables to load. If a list is supplied thenames are computed from the filenames, otherwise the keys arethe names. The values must filepaths or URLs to the data:{    'local' : '/home/user/local_file.csv',    'remote': 'https://test.com/test.csv'}if the filepath does not have a declared extension an extensionmay be provided in a list or tuple, e.g.:{'table': ['http://test.com/api', 'json']}

+
+
+
+
+
+
+
+use_dask
+

type: bool
default: True
Whether to use dask to load files.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+FileSource.clear_cache(*events: Event)#
+

Clears any cached data.

+
+
+
+FileSource.get(table: str, **query) DataFrame#
+

Return a table; optionally filtered by the given query.

+
+
Parameters:
+
    +
  • table (str) – The name of the table to query

  • +
  • query (dict) – A dictionary containing all the query parameters

  • +
+
+
Returns:
+

A DataFrame containing the queried table.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+FileSource.get_schema(table: Optional[str] = None) Union[Dict[str, Dict[str, Any]], Dict[str, Any]]#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+FileSource.get_tables() List[str]#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+FileSource.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/IntakeSQLSource.html b/reference/source/IntakeSQLSource.html new file mode 100644 index 00000000..570a9cd6 --- /dev/null +++ b/reference/source/IntakeSQLSource.html @@ -0,0 +1,491 @@ + + + + + + + + +IntakeSQLSource type: intake_sql — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

IntakeSQLSource  type: intake_sql#

+
+
+class lumen.sources.intake_sql.IntakeSQLSource(*, filter_in_sql, catalog, dask, uri, load_schema, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

IntakeSQLSource extends the IntakeSource with support for SQL data.

+

In addition to the standard intake support for reading catalogs +the IntakeSQLSource computes the schema by querying the database +instead of loading all the data into memory and allows for +SQLTransform to be applied when querying the SQL database.

+
+
+
+

Parameters#

+
+
+
+
+
+
+catalog
+

type: dict
default: None
An inlined Catalog specification.

+
+
+
+
+
+
+
+dask
+

type: bool
default: False
Whether to return a dask DataFrame.

+
+
+
+
+
+
+
+filter_in_sql
+

type: bool
default: True

+
+
+
+
+
+
+
+load_schema
+

type: bool
default: True
Whether to load the schema

+
+
+
+
+
+
+
+uri
+

type: str
default: ''
URI of the catalog file.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+IntakeSQLSource.clear_cache(*events: Event)#
+

Clears any cached data.

+
+
+
+IntakeSQLSource.get(table, **query)#
+

Applies SQL Transforms, creating new temp catalog on the fly +and querying the database.

+
+
+
+IntakeSQLSource.get_schema(table=None)#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+IntakeSQLSource.get_tables()#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+IntakeSQLSource.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/IntakeSource.html b/reference/source/IntakeSource.html new file mode 100644 index 00000000..344cfd5c --- /dev/null +++ b/reference/source/IntakeSource.html @@ -0,0 +1,495 @@ + + + + + + + + +IntakeSource type: intake — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

IntakeSource  type: intake#

+
+
+class lumen.sources.intake.IntakeSource(*, catalog, dask, uri, load_schema, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

An IntakeSource loads data from an Intake catalog.

+

Intake is a lightweight set of tools for loading and sharing data +in data science projects using convenient catalog specifications.

+

The IntakeSource can be given a dictionary catalog specification +OR a URI pointing to a catalog.yaml file on disk.

+
+
+
+

Parameters#

+
+
+
+
+
+
+catalog
+

type: dict
default: None
An inlined Catalog specification.

+
+
+
+
+
+
+
+dask
+

type: bool
default: False
Whether to return a dask DataFrame.

+
+
+
+
+
+
+
+load_schema
+

type: bool
default: True
Whether to load the schema

+
+
+
+
+
+
+
+uri
+

type: str
default: ''
URI of the catalog file.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+IntakeSource.clear_cache(*events: Event)#
+

Clears any cached data.

+
+
+
+IntakeSource.get(table, **query)#
+

Return a table; optionally filtered by the given query.

+
+
Parameters:
+
    +
  • table (str) – The name of the table to query

  • +
  • query (dict) – A dictionary containing all the query parameters

  • +
+
+
Returns:
+

A DataFrame containing the queried table.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+IntakeSource.get_schema(table=None)#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+IntakeSource.get_tables()#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+IntakeSource.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/JSONSource.html b/reference/source/JSONSource.html new file mode 100644 index 00000000..d2d60d75 --- /dev/null +++ b/reference/source/JSONSource.html @@ -0,0 +1,502 @@ + + + + + + + + +JSONSource type: json — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

JSONSource  type: json#

+
+
+class lumen.sources.base.JSONSource(*, chunk_size, dask, kwargs, tables, use_dask, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

The JSONSource is very similar to the FileSource but loads json files.

+

Both local and remote JSON files can be fetched by declaring them +as a list or dictionaries of tables.

+
+
+
+

Parameters#

+
+
+
+
+
+
+chunk_size
+

type: int
default: 0
bounds: None
Number of items to load per chunk if a template variableis provided.

+
+
+
+
+
+
+
+dask
+

type: bool
default: False
Whether to return a Dask dataframe.

+
+
+
+
+
+
+
+kwargs
+

type: dict
default: None
Keyword arguments to the pandas/dask loading function.

+
+
+
+
+
+
+
+tables
+

type: list | dict
default: None
List or dictionary of tables to load. If a list is supplied thenames are computed from the filenames, otherwise the keys arethe names. The values must filepaths or URLs to the data:{    'local' : '/home/user/local_file.csv',    'remote': 'https://test.com/test.csv'}

+
+
+
+
+
+
+
+use_dask
+

type: bool
default: True
Whether to use dask to load files.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+JSONSource.clear_cache(*events: Event)#
+

Clears any cached data.

+
+
+
+JSONSource.get(table: str, **query) DataFrame#
+

Return a table; optionally filtered by the given query.

+
+
Parameters:
+
    +
  • table (str) – The name of the table to query

  • +
  • query (dict) – A dictionary containing all the query parameters

  • +
+
+
Returns:
+

A DataFrame containing the queried table.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+JSONSource.get_schema(table: Optional[str] = None) Union[Dict[str, Dict[str, Any]], Dict[str, Any]]#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+JSONSource.get_tables() List[str]#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+JSONSource.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/JoinedSource.html b/reference/source/JoinedSource.html new file mode 100644 index 00000000..a46731b7 --- /dev/null +++ b/reference/source/JoinedSource.html @@ -0,0 +1,494 @@ + + + + + + + + +JoinedSource type: join — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

JoinedSource  type: join#

+
+
+class lumen.sources.base.JoinedSource(*, sources, tables, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

JoinedSource performs a join on tables from one or more sources.

+

A JoinedSource applies a join on two or more sources returning +new table(s) with data from all sources. It iterates over the +tables specification and merges the specified tables from the +declared sources on the supplied index.

+

In this way multiple tables from multiple sources can be merged. +Individual tables from sources that should not be joined may also +be surfaced by declaring a single source and table in the +specification.

+

As a simple example we may have sources A and B, which contain +tables ‘foo’ and ‘bar’ respectively. We now want to merge these +tables on column ‘a’ in Table A with column ‘b’ in Table B:

+
{'new_table': [
+  {'source': 'A', 'table': 'foo', 'index': 'a'},
+  {'source': 'B', 'table': 'bar', 'index': 'b'}
+]}
+
+
+

The joined source will now publish the “new_table” with all +columns from tables “foo” and “bar” except for the index column +from table “bar”, which was merged with the index column “a” from +table “foo”.

+
+
+
+

Parameters#

+
+
+
+
+
+
+sources
+

type: list | dict
default: None
A dictionary of sources indexed by their assigned name.

+
+
+
+
+
+
+
+tables
+

type: dict
default: {}
A dictionary with the names of the joined sources as keysand a specification of the source, table and index to mergeon.{"new_table": [    {'source': <source_name>,     'table': <table_name>,     'index': <index_name>    },    {'source': <source_name>,     'table': <table_name>,     'index': <index_name>    },    ...]}

+
+
+
+
+
+
+
+
+

Methods#

+
+
+JoinedSource.clear_cache()#
+

Clears any cached data.

+
+
+
+JoinedSource.get(table: str, **query) DataFrame#
+

Return a table; optionally filtered by the given query.

+
+
Parameters:
+
    +
  • table (str) – The name of the table to query

  • +
  • query (dict) – A dictionary containing all the query parameters

  • +
+
+
Returns:
+

A DataFrame containing the queried table.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+JoinedSource.get_schema(table: Optional[str] = None) Union[Dict[str, Dict[str, Any]], Dict[str, Any]]#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+JoinedSource.get_tables() List[str]#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+JoinedSource.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/PanelSessionSource.html b/reference/source/PanelSessionSource.html new file mode 100644 index 00000000..894a588a --- /dev/null +++ b/reference/source/PanelSessionSource.html @@ -0,0 +1,486 @@ + + + + + + + + +PanelSessionSource type: session_info — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

PanelSessionSource  type: session_info#

+
+
+class lumen.sources.base.PanelSessionSource(*, endpoint, timeout, urls, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

” +PanelSessionSource queries the session_info endpoint of a Panel application.

+

Panel applications with –rest-session-info enabled can be queried +about session statistics. This source makes this data available to +Lumen for monitoring.

+
+
+
+

Parameters#

+
+
+
+
+
+
+endpoint
+

type: str
default: 'rest/session_info'

+
+
+
+
+
+
+
+timeout
+

type: Any
default: 5

+
+
+
+
+
+
+
+urls
+

type: list[Any]
default: []
URL of the websites to monitor.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+PanelSessionSource.clear_cache(*events: Event)#
+

Clears any cached data.

+
+
+
+PanelSessionSource.get(table: str, **query) DataFrame#
+

Return a table; optionally filtered by the given query.

+
+
Parameters:
+
    +
  • table (str) – The name of the table to query

  • +
  • query (dict) – A dictionary containing all the query parameters

  • +
+
+
Returns:
+

A DataFrame containing the queried table.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+PanelSessionSource.get_schema(table: Optional[str] = None) Union[Dict[str, Dict[str, Any]], Dict[str, Any]]#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+PanelSessionSource.get_tables() List[str]#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+PanelSessionSource.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/RESTSource.html b/reference/source/RESTSource.html new file mode 100644 index 00000000..88d6bba8 --- /dev/null +++ b/reference/source/RESTSource.html @@ -0,0 +1,467 @@ + + + + + + + + +RESTSource type: rest — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

RESTSource  type: rest#

+
+
+class lumen.sources.base.RESTSource(*, url, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

RESTSource allows querying REST endpoints conforming to the Lumen REST specification.

+

The url must offer two endpoints, the /data endpoint must +return data in a records format while the /schema endpoint must +return a valid Lumen JSON schema.

+
+
+
+

Parameters#

+
+
+
+
+
+
+url
+

type: str
default: ''
URL of the REST endpoint to monitor.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+RESTSource.clear_cache(*events: Event)#
+

Clears any cached data.

+
+
+
+RESTSource.get(table: str, **query) DataFrame#
+

Return a table; optionally filtered by the given query.

+
+
Parameters:
+
    +
  • table (str) – The name of the table to query

  • +
  • query (dict) – A dictionary containing all the query parameters

  • +
+
+
Returns:
+

A DataFrame containing the queried table.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+RESTSource.get_schema(table: Optional[str] = None) Union[Dict[str, Dict[str, Any]], Dict[str, Any]]#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+RESTSource.get_tables() List[str]#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+RESTSource.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/WebsiteSource.html b/reference/source/WebsiteSource.html new file mode 100644 index 00000000..f3b69ac9 --- /dev/null +++ b/reference/source/WebsiteSource.html @@ -0,0 +1,464 @@ + + + + + + + + +WebsiteSource type: live — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

WebsiteSource  type: live#

+
+
+class lumen.sources.base.WebsiteSource(*, urls, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

WebsiteSource queries whether a website responds with a 400 status code.

+
+
+
+

Parameters#

+
+
+
+
+
+
+urls
+

type: list[Any]
default: []
URLs of the websites to monitor.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+WebsiteSource.clear_cache(*events: Event)#
+

Clears any cached data.

+
+
+
+WebsiteSource.get(table: str, **query) DataFrame#
+

Return a table; optionally filtered by the given query.

+
+
Parameters:
+
    +
  • table (str) – The name of the table to query

  • +
  • query (dict) – A dictionary containing all the query parameters

  • +
+
+
Returns:
+

A DataFrame containing the queried table.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+WebsiteSource.get_schema(table: Optional[str] = None) Union[Dict[str, Dict[str, Any]], Dict[str, Any]]#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+WebsiteSource.get_tables() List[str]#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+WebsiteSource.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/source/index.html b/reference/source/index.html new file mode 100644 index 00000000..af77a84c --- /dev/null +++ b/reference/source/index.html @@ -0,0 +1,605 @@ + + + + + + + + +Source — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Source#

+
+
+class lumen.sources.base.Source(*, cache_dir, cache_per_query, cache_with_dask, root, shared, name)#
+

Source components provide allow querying all kinds of data.

+

A Source can return one or more tables queried using the +.get_tables method, a description of the data returned by each +table in the form of a JSON schema accessible via the .get_schema +method and lastly a .get method that allows filtering the data.

+

The Source base class also implements both in-memory and disk +caching which can be enabled if a cache_dir is provided. Data +cached to disk is stored as parquet files.

+
+
+
+

Parameters#

+
+
+
+
+
+
+cache_dir
+

type: str
default: None
Whether to enable local cache and write file to disk.

+
+
+
+
+
+
+
+cache_per_query
+

type: bool
default: True
Whether to query the whole dataset or individual queries.

+
+
+
+
+
+
+
+cache_with_dask
+

type: bool
default: True
Whether to read and write cache files with dask if available.

+
+
+
+
+
+
+
+name
+

type: str
default: 'Source'
String identifier for this object.

+
+
+
+
+
+
+
+root
+

type: pathlib.Path
default: None
Root folder of the cache_dir, default is config.root

+
+
+
+
+
+
+
+shared
+

type: bool
default: False
Whether the Source can be shared across all instances of thedashboard. If set to True the Source will be loaded oninitial server load.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Source.clear_cache(*events: Event)#
+

Clears any cached data.

+
+
+
+Source.get(table: str, **query) DataFrame#
+

Return a table; optionally filtered by the given query.

+
+
Parameters:
+
    +
  • table (str) – The name of the table to query

  • +
  • query (dict) – A dictionary containing all the query parameters

  • +
+
+
Returns:
+

A DataFrame containing the queried table.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Source.get_schema(table: Optional[str] = None) Union[Dict[str, Dict[str, Any]], Dict[str, Any]]#
+

Returns JSON schema describing the tables returned by the +Source.

+
+
Parameters:
+

table (str or None) – The name of the table to return the schema for. If None +returns schema for all available tables.

+
+
Returns:
+

JSON schema(s) for one or all the tables.

+
+
Return type:
+

dict

+
+
+
+
+
+Source.get_tables() List[str]#
+

Returns the list of tables available on this source.

+
+
Returns:
+

The list of available tables on this source.

+
+
Return type:
+

list

+
+
+
+
+
+Source.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+

Types#

+
+
+
+
+
+
+RESTSource type: rest
+

RESTSource allows querying REST endpoints conforming to the Lumen REST specification.

+
+
+
+
+
+
+
+FileSource type: file
+

FileSource loads CSV, Excel and Parquet files using pandas and dask read_* functions.

+
+
+
+
+
+
+
+WebsiteSource type: live
+

WebsiteSource queries whether a website responds with a 400 status code.

+
+
+
+
+
+
+
+PanelSessionSource type: session_info
+

PanelSessionSource queries the session_info endpoint of a Panel application.

+
+
+
+
+
+
+
+JoinedSource type: join
+

JoinedSource performs a join on tables from one or more sources.

+
+
+
+
+
+
+
+DerivedSource type: derived
+

DerivedSource applies filtering and transforms to tables from other sources.

+
+
+
+
+
+
+
+JSONSource type: json
+

The JSONSource is very similar to the FileSource but loads json files.

+
+
+
+
+
+
+
+IntakeSource type: intake
+

An IntakeSource loads data from an Intake catalog.

+
+
+
+
+
+
+
+IntakeSQLSource type: intake_sql
+

IntakeSQLSource extends the IntakeSource with support for SQL data.

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Aggregate.html b/reference/transform/Aggregate.html new file mode 100644 index 00000000..cf0ca4af --- /dev/null +++ b/reference/transform/Aggregate.html @@ -0,0 +1,459 @@ + + + + + + + + +Aggregate type: aggregate — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Aggregate  type: aggregate#

+
+
+class lumen.transforms.base.Aggregate(*, by, columns, kwargs, method, with_index, controls, name)#
+

Aggregate one or more columns or indexes, see pandas.DataFrame.groupby.

+

df.groupby(<by>)[<columns>].<method>()[.reset_index()]

+
+
+
+

Parameters#

+
+
+
+
+
+
+by
+

type: Any
default: None
Possible values: ``
Columns or indexes to group by.

+
+
+
+
+
+
+
+columns
+

type: Any
default: None
Possible values: ``
Columns to aggregate.

+
+
+
+
+
+
+
+kwargs
+

type: dict
default: {}
Keyword arguments to the aggregation method.

+
+
+
+
+
+
+
+method
+

type: str
default: None
Name of aggregation method.

+
+
+
+
+
+
+
+with_index
+

type: bool
default: True
Whether to make the groupby columns indexes.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Aggregate.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Aggregate.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Astype.html b/reference/transform/Astype.html new file mode 100644 index 00000000..39f7b252 --- /dev/null +++ b/reference/transform/Astype.html @@ -0,0 +1,422 @@ + + + + + + + + +Astype type: as_type — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Astype  type: as_type#

+
+
+class lumen.transforms.base.Astype(*, dtypes, controls, name)#
+

Astype transforms the type of one or more columns.

+
+
+
+

Parameters#

+
+
+
+
+
+
+dtypes
+

type: dict
default: None
Mapping from column name to new type.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Astype.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Astype.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Columns.html b/reference/transform/Columns.html new file mode 100644 index 00000000..5456ed67 --- /dev/null +++ b/reference/transform/Columns.html @@ -0,0 +1,423 @@ + + + + + + + + +Columns type: columns — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Columns  type: columns#

+
+
+class lumen.transforms.base.Columns(*, columns, controls, name)#
+

Columns selects a subset of columns.

+

df[<columns>]

+
+
+
+

Parameters#

+
+
+
+
+
+
+columns
+

type: Any
default: None
Possible values: ``
The subset of columns to select.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Columns.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Columns.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Compute.html b/reference/transform/Compute.html new file mode 100644 index 00000000..587bb337 --- /dev/null +++ b/reference/transform/Compute.html @@ -0,0 +1,404 @@ + + + + + + + + +Compute type: compute — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Compute  type: compute#

+
+
+class lumen.transforms.base.Compute(*, controls, name)#
+

Compute turns a dask.dataframe.DataFrame into a pandas.DataFrame.

+
+
+
+

Methods#

+
+
+Compute.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Compute.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Count.html b/reference/transform/Count.html new file mode 100644 index 00000000..df129dbe --- /dev/null +++ b/reference/transform/Count.html @@ -0,0 +1,443 @@ + + + + + + + + +Count type: count — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Count  type: count#

+
+
+class lumen.transforms.base.Count(*, axis, level, numeric_only, controls, name)#
+

Counts non-nan values in each column of the DataFrame and returns +a new DataFrame with a single row with a count for each original +column, see pandas.DataFrame.count.

+

df.count(axis=<axis>, level=<level>, numeric_only=<numeric_only>).to_frame().T

+
+
+
+

Parameters#

+
+
+
+
+
+
+axis
+

type: int | str
default: 0
The axis to rename. 0 or ‘index’, 1 or ‘columns’

+
+
+
+
+
+
+
+level
+

type: int | list | str
default: None
The indexes to stack.

+
+
+
+
+
+
+
+numeric_only
+

type: bool
default: False
Include only float, int or boolean data.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Count.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Count.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Eval.html b/reference/transform/Eval.html new file mode 100644 index 00000000..add3f52e --- /dev/null +++ b/reference/transform/Eval.html @@ -0,0 +1,431 @@ + + + + + + + + +Eval type: eval — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Eval  type: eval#

+
+
+class lumen.transforms.base.Eval(*, expr, controls, name)#
+

Applies an eval assignment expression to a DataFrame. The +expression can reference columns on the original table by +referencing table.<column> and must assign to a variable that +will become a new column in the DataFrame, e.g. to divide a +value column by one thousand and assign the result to a new column +called kilo_value you can write an expr like:

+
+

kilo_value = table.value / 1000

+
+

See pandas.eval for more information.

+
+
+
+

Parameters#

+
+
+
+
+
+
+expr
+

type: str
default: ''
The expression to apply to the table.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Eval.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Eval.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Filter.html b/reference/transform/Filter.html new file mode 100644 index 00000000..2d864673 --- /dev/null +++ b/reference/transform/Filter.html @@ -0,0 +1,432 @@ + + + + + + + + +Filter type: None — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Filter  type: None#

+
+
+class lumen.transforms.base.Filter(*, conditions, controls, name)#
+

Filter transform implement the filtering behavior of Filter components.

+

The filter conditions must be declared as a list of tuple containing +the name of the column to be filtered and one of the following:

+
+
    +
  • scalar: A scalar value will be matched using equality operators

  • +
  • tuple: A tuple value specifies a numeric or date range.

  • +
  • list: A list value specifies a set of categories to match against.

  • +
  • list(tuple): A list of tuples specifies a list of ranges.

  • +
+
+
+
+
+

Parameters#

+
+
+
+
+
+
+conditions
+

type: list[Any]
default: []
List of filter conditions expressed as tuples of the columnname and the filter value.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Filter.apply(df: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Filter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/HistoryTransform.html b/reference/transform/HistoryTransform.html new file mode 100644 index 00000000..f99bd904 --- /dev/null +++ b/reference/transform/HistoryTransform.html @@ -0,0 +1,435 @@ + + + + + + + + +HistoryTransform type: history — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

HistoryTransform  type: history#

+
+
+class lumen.transforms.base.HistoryTransform(*, date_column, length, controls, name)#
+

HistoryTransform accumulates a history of the queried data.

+

The internal buffer accumulates data up to the supplied length +and (optionally) adds a date_column to the data.

+
+
+
+

Parameters#

+
+
+
+
+
+
+date_column
+

type: Any
default: None
Possible values: ``
If defined adds a date column with the supplied name.

+
+
+
+
+
+
+
+length
+

type: int
default: 10
bounds: (1, None)
Accumulates a history of data.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+HistoryTransform.apply(table: DataFrame) DataFrame#
+

Accumulates a history of the data in a buffer up to the +declared length and optionally adds the current datetime to +the declared date_column.

+
+
Parameters:
+

data (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the buffered history of the data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+HistoryTransform.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Iloc.html b/reference/transform/Iloc.html new file mode 100644 index 00000000..6450e427 --- /dev/null +++ b/reference/transform/Iloc.html @@ -0,0 +1,432 @@ + + + + + + + + +Iloc type: iloc — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Iloc  type: iloc#

+
+
+class lumen.transforms.base.Iloc(*, end, start, controls, name)#
+

Iloc applies integer slicing to the data, see pandas.DataFrame.iloc.

+

df.iloc[<start>:<end>]

+
+
+
+

Parameters#

+
+
+
+
+
+
+end
+

type: int
default: None
bounds: None

+
+
+
+
+
+
+
+start
+

type: int
default: None
bounds: None

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Iloc.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Iloc.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Melt.html b/reference/transform/Melt.html new file mode 100644 index 00000000..b61775f6 --- /dev/null +++ b/reference/transform/Melt.html @@ -0,0 +1,458 @@ + + + + + + + + +Melt type: melt — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Melt  type: melt#

+
+
+class lumen.transforms.base.Melt(*, id_vars, ignore_index, value_name, value_vars, var_name, controls, name)#
+

Melt applies the pandas.melt operation given the id_vars and value_vars.

+
+
+
+

Parameters#

+
+
+
+
+
+
+id_vars
+

type: Any
default: []
Possible values: ``
Column(s) to use as identifier variables.

+
+
+
+
+
+
+
+ignore_index
+

type: bool
default: True
If True, original index is ignored. If False, the originalindex is retained. Index labels will be repeated asnecessary.

+
+
+
+
+
+
+
+value_name
+

type: str
default: 'value'
Name to use for the ‘value’ column.

+
+
+
+
+
+
+
+value_vars
+

type: Any
default: None
Possible values: ``
Column(s) to unpivot. If not specified, uses all columns thatare not set as id_vars.

+
+
+
+
+
+
+
+var_name
+

type: str
default: None
Name to use for the ‘variable’ column. If None it usesframe.columns.name or ‘variable’.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Melt.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Melt.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Pivot.html b/reference/transform/Pivot.html new file mode 100644 index 00000000..4034dff8 --- /dev/null +++ b/reference/transform/Pivot.html @@ -0,0 +1,440 @@ + + + + + + + + +Pivot type: pivot — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Pivot  type: pivot#

+
+
+class lumen.transforms.base.Pivot(*, columns, index, values, controls, name)#
+

Pivot applies pandas.DataFrame.pivot given an index, columns, and values.

+
+
+
+

Parameters#

+
+
+
+
+
+
+columns
+

type: str
default: None
Column to use to make new frame’s columns.

+
+
+
+
+
+
+
+index
+

type: str
default: None
Column to use to make new frame’s index.If None, uses existing index.

+
+
+
+
+
+
+
+values
+

type: Any
default: None
Possible values: ``
Column(s) to use for populating new frame’s values.If not specified, all remaining columns will be usedand the result will have hierarchically indexed columns.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Pivot.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Pivot.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Query.html b/reference/transform/Query.html new file mode 100644 index 00000000..d967f6d9 --- /dev/null +++ b/reference/transform/Query.html @@ -0,0 +1,423 @@ + + + + + + + + +Query type: query — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Query  type: query#

+
+
+class lumen.transforms.base.Query(*, query, controls, name)#
+

Query applies the pandas.DataFrame.query method.

+

df.query(<query>)

+
+
+
+

Parameters#

+
+
+
+
+
+
+query
+

type: str
default: ''
The query to apply to the table.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Query.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Query.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Rename.html b/reference/transform/Rename.html new file mode 100644 index 00000000..f4fecfca --- /dev/null +++ b/reference/transform/Rename.html @@ -0,0 +1,471 @@ + + + + + + + + +Rename type: rename — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Rename  type: rename#

+
+
+class lumen.transforms.base.Rename(*, axis, columns, copy, index, level, mapper, controls, name)#
+

Rename renames columns or indexes, see pandas.DataFrame.rename.

+
+
df.rename(mapper=<mapper>, columns=<columns>, index=<index>,

level=<level>, axis=<axis>, copy=<copy>)

+
+
+
+
+
+

Parameters#

+
+
+
+
+
+
+axis
+

type: int | str
default: None
The axis to rename. 0 or ‘index’, 1 or ‘columns’

+
+
+
+
+
+
+
+columns
+

type: dict
default: None
Alternative to specifying axis (mapper, axis=1 is equivalent tocolumns=mapper).

+
+
+
+
+
+
+
+copy
+

type: bool
default: False
Also copy underlying data.

+
+
+
+
+
+
+
+index
+

type: dict
default: None
Alternative to specifying axis (mapper, axis=0 is equivalent toindex=mapper).

+
+
+
+
+
+
+
+level
+

type: int | str
default: None
In case of a MultiIndex, only rename labels in the specified level.

+
+
+
+
+
+
+
+mapper
+

type: dict
default: None
Dict to apply to that axis’ values. Use either mapper and axis tospecify the axis to target with mapper, or index and columns.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Rename.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Rename.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/RenameAxis.html b/reference/transform/RenameAxis.html new file mode 100644 index 00000000..42e963ad --- /dev/null +++ b/reference/transform/RenameAxis.html @@ -0,0 +1,463 @@ + + + + + + + + +RenameAxis type: rename_axis — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

RenameAxis  type: rename_axis#

+
+
+class lumen.transforms.base.RenameAxis(*, axis, columns, copy, index, mapper, controls, name)#
+

Set the name of the axis for the index or columns, +see pandas.DataFrame.rename_axis.

+
+
df.rename_axis(mapper=<mapper>, columns=<columns>, index=<index>,

axis=<axis>, copy=<copy>)

+
+
+
+
+
+

Parameters#

+
+
+
+
+
+
+axis
+

type: int | str
default: 0
The axis to rename. 0 or ‘index’, 1 or ‘columns’

+
+
+
+
+
+
+
+columns
+

type: str | list | dict
default: None
A scalar, list-like, dict-like to apply to that axis’ values.Note that the columns parameter is not allowed if the objectis a Series. This parameter only apply for DataFrame type objects.Use either mapper and axis to specify the axis to target withmapper, or index and/or columns.

+
+
+
+
+
+
+
+copy
+

type: bool
default: True
Also copy underlying data.

+
+
+
+
+
+
+
+index
+

type: str | list | dict
default: None
A scalar, list-like, dict-like to apply to that axis’ values.Note that the columns parameter is not allowed if the objectis a Series. This parameter only apply for DataFrame type objects.Use either mapper and axis to specify the axis to target withmapper, or index and/or columns.

+
+
+
+
+
+
+
+mapper
+

type: str | list
default: None
Value to set the axis name attribute.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+RenameAxis.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+RenameAxis.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/ResetIndex.html b/reference/transform/ResetIndex.html new file mode 100644 index 00000000..c408e3db --- /dev/null +++ b/reference/transform/ResetIndex.html @@ -0,0 +1,450 @@ + + + + + + + + +ResetIndex type: reset_index — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

ResetIndex  type: reset_index#

+
+
+class lumen.transforms.base.ResetIndex(*, col_fill, col_level, drop, level, controls, name)#
+

ResetIndex resets DataFrame indexes to columns or drops them, see pandas.DataFrame.reset_index

+

df.reset_index(drop=<drop>, col_fill=<col_fill>, col_level=<col_level>, level=<level>)

+
+
+
+

Parameters#

+
+
+
+
+
+
+col_fill
+

type: str
default: ''
If the columns have multiple levels, determines how the otherlevels are named. If None then the index name is repeated.

+
+
+
+
+
+
+
+col_level
+

type: int | str
default: 0
If the columns have multiple levels, determines which level thelabels are inserted into. By default it is inserted into thefirst level.

+
+
+
+
+
+
+
+drop
+

type: bool
default: False
Do not try to insert index into dataframe columns. This resetsthe index to the default integer index.

+
+
+
+
+
+
+
+level
+

type: int | str | list
default: None
Only remove the given levels from the index. Removes all levelsby default.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+ResetIndex.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+ResetIndex.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/SQLColumns.html b/reference/transform/SQLColumns.html new file mode 100644 index 00000000..e1db2b26 --- /dev/null +++ b/reference/transform/SQLColumns.html @@ -0,0 +1,421 @@ + + + + + + + + +SQLColumns type: sql_columns — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

SQLColumns  type: sql_columns#

+
+
+class lumen.transforms.sql.SQLColumns(*, columns, controls, name)#
+
+
+
+

Parameters#

+
+
+
+
+
+
+columns
+

type: list[Any]
default: []
Columns to return.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+SQLColumns.apply(sql_in)#
+

Given an SQL statement, manipulate it, and return a new SQL statement.

+
+
Parameters:
+

sql_in (string) – The initial SQL query to be manipulated.

+
+
Returns:
+

New SQL query derived from the above query.

+
+
Return type:
+

string

+
+
+
+
+
+SQLColumns.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/SQLDistinct.html b/reference/transform/SQLDistinct.html new file mode 100644 index 00000000..1b362fe8 --- /dev/null +++ b/reference/transform/SQLDistinct.html @@ -0,0 +1,421 @@ + + + + + + + + +SQLDistinct type: sql_distinct — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

SQLDistinct  type: sql_distinct#

+
+
+class lumen.transforms.sql.SQLDistinct(*, columns, controls, name)#
+
+
+
+

Parameters#

+
+
+
+
+
+
+columns
+

type: list[Any]
default: []
Columns to return distinct values for.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+SQLDistinct.apply(sql_in)#
+

Given an SQL statement, manipulate it, and return a new SQL statement.

+
+
Parameters:
+

sql_in (string) – The initial SQL query to be manipulated.

+
+
Returns:
+

New SQL query derived from the above query.

+
+
Return type:
+

string

+
+
+
+
+
+SQLDistinct.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/SQLFilter.html b/reference/transform/SQLFilter.html new file mode 100644 index 00000000..e34fcb0e --- /dev/null +++ b/reference/transform/SQLFilter.html @@ -0,0 +1,422 @@ + + + + + + + + +SQLFilter type: sql_filter — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

SQLFilter  type: sql_filter#

+
+
+class lumen.transforms.sql.SQLFilter(*, conditions, controls, name)#
+

Translates Lumen Filter query into a SQL WHERE statement.

+
+
+
+

Parameters#

+
+
+
+
+
+
+conditions
+

type: list[Any]
default: []
List of filter conditions expressed as tuples of the columnname and the filter value.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+SQLFilter.apply(sql_in)#
+

Given an SQL statement, manipulate it, and return a new SQL statement.

+
+
Parameters:
+

sql_in (string) – The initial SQL query to be manipulated.

+
+
Returns:
+

New SQL query derived from the above query.

+
+
Return type:
+

string

+
+
+
+
+
+SQLFilter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/SQLGroupBy.html b/reference/transform/SQLGroupBy.html new file mode 100644 index 00000000..a96072e1 --- /dev/null +++ b/reference/transform/SQLGroupBy.html @@ -0,0 +1,431 @@ + + + + + + + + +SQLGroupBy type: sql_group_by — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

SQLGroupBy  type: sql_group_by#

+
+
+class lumen.transforms.sql.SQLGroupBy(*, aggregates, by, controls, name)#
+

Performs a Group-By and aggregation

+
+
+
+

Parameters#

+
+
+
+
+
+
+aggregates
+

type: dict
default: None
mapping of Aggregate Functions to use to which column to use them on

+
+
+
+
+
+
+
+by
+

type: list[Any]
default: []
Columns to Group by

+
+
+
+
+
+
+
+
+

Methods#

+
+
+SQLGroupBy.apply(sql_in)#
+

Given an SQL statement, manipulate it, and return a new SQL statement.

+
+
Parameters:
+

sql_in (string) – The initial SQL query to be manipulated.

+
+
Returns:
+

New SQL query derived from the above query.

+
+
Return type:
+

string

+
+
+
+
+
+SQLGroupBy.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/SQLLimit.html b/reference/transform/SQLLimit.html new file mode 100644 index 00000000..d6bdf97e --- /dev/null +++ b/reference/transform/SQLLimit.html @@ -0,0 +1,422 @@ + + + + + + + + +SQLLimit type: sql_limit — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

SQLLimit  type: sql_limit#

+
+
+class lumen.transforms.sql.SQLLimit(*, limit, controls, name)#
+

Performs a LIMIT SQL operation on the query

+
+
+
+

Parameters#

+
+
+
+
+
+
+limit
+

type: int
default: 1000
bounds: None
Limit on the number of rows to return

+
+
+
+
+
+
+
+
+

Methods#

+
+
+SQLLimit.apply(sql_in)#
+

Given an SQL statement, manipulate it, and return a new SQL statement.

+
+
Parameters:
+

sql_in (string) – The initial SQL query to be manipulated.

+
+
Returns:
+

New SQL query derived from the above query.

+
+
Return type:
+

string

+
+
+
+
+
+SQLLimit.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/SQLMinMax.html b/reference/transform/SQLMinMax.html new file mode 100644 index 00000000..1ec6b303 --- /dev/null +++ b/reference/transform/SQLMinMax.html @@ -0,0 +1,421 @@ + + + + + + + + +SQLMinMax type: sql_minmax — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

SQLMinMax  type: sql_minmax#

+
+
+class lumen.transforms.sql.SQLMinMax(*, columns, controls, name)#
+
+
+
+

Parameters#

+
+
+
+
+
+
+columns
+

type: list[Any]
default: []
Columns to return min/max values for.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+SQLMinMax.apply(sql_in)#
+

Given an SQL statement, manipulate it, and return a new SQL statement.

+
+
Parameters:
+

sql_in (string) – The initial SQL query to be manipulated.

+
+
Returns:
+

New SQL query derived from the above query.

+
+
Return type:
+

string

+
+
+
+
+
+SQLMinMax.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Sample.html b/reference/transform/Sample.html new file mode 100644 index 00000000..84697bdf --- /dev/null +++ b/reference/transform/Sample.html @@ -0,0 +1,441 @@ + + + + + + + + +Sample type: sample — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Sample  type: sample#

+
+
+class lumen.transforms.base.Sample(*, frac, n, replace, controls, name)#
+

Sample returns a random sample of items.

+

df.sample(n=<n>, frac=<frac>, replace=<replace>)

+
+
+
+

Parameters#

+
+
+
+
+
+
+frac
+

type: Number
default: None
bounds: (0, 1)
Fraction of axis items to return.

+
+
+
+
+
+
+
+n
+

type: int
default: None
bounds: None
Number of items to return.

+
+
+
+
+
+
+
+replace
+

type: bool
default: False
Sample with or without replacement.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Sample.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Sample.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/SetIndex.html b/reference/transform/SetIndex.html new file mode 100644 index 00000000..d5686886 --- /dev/null +++ b/reference/transform/SetIndex.html @@ -0,0 +1,450 @@ + + + + + + + + +SetIndex type: set_index — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

SetIndex  type: set_index#

+
+
+class lumen.transforms.base.SetIndex(*, append, drop, keys, verify_integrity, controls, name)#
+

SetIndex promotes DataFrame columns to indexes, see pandas.DataFrame.set_index.

+

df.set_index(<keys>, drop=<drop>, append=<append>, verify_integrity=<verify_integrity>)

+
+
+
+

Parameters#

+
+
+
+
+
+
+append
+

type: bool
default: False
Whether to append columns to existing index.

+
+
+
+
+
+
+
+drop
+

type: bool
default: True
Delete columns to be used as the new index.

+
+
+
+
+
+
+
+keys
+

type: str | list
default: None
This parameter can be either a single column key or a listcontaining column keys.

+
+
+
+
+
+
+
+verify_integrity
+

type: bool
default: False
Check the new index for duplicates. Otherwise defer the checkuntil necessary. Setting to False will improve the performanceof this method.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+SetIndex.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+SetIndex.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Sort.html b/reference/transform/Sort.html new file mode 100644 index 00000000..59ba0224 --- /dev/null +++ b/reference/transform/Sort.html @@ -0,0 +1,432 @@ + + + + + + + + +Sort type: sort — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Sort  type: sort#

+
+
+class lumen.transforms.base.Sort(*, ascending, by, controls, name)#
+

Sort on one or more columns, see pandas.DataFrame.sort_values.

+

df.sort_values(<by>, ascending=<ascending>)

+
+
+
+

Parameters#

+
+
+
+
+
+
+ascending
+

type: bool | list
default: True
Sort ascending vs. descending. Specify list for multiple sortorders. If this is a list of bools, must match the length ofthe by.

+
+
+
+
+
+
+
+by
+

type: Any
default: []
Possible values: ``
Columns or indexes to sort by.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Sort.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Sort.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Stack.html b/reference/transform/Stack.html new file mode 100644 index 00000000..d86d3f6f --- /dev/null +++ b/reference/transform/Stack.html @@ -0,0 +1,432 @@ + + + + + + + + +Stack type: stack — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Stack  type: stack#

+
+
+class lumen.transforms.base.Stack(*, dropna, level, controls, name)#
+

Stack applies pandas.DataFrame.stack to the declared level.

+

df.stack(<level>)

+
+
+
+

Parameters#

+
+
+
+
+
+
+dropna
+

type: bool
default: True
Whether to drop rows in the resulting Frame/Series with missing values.Stacking a column level onto the index axis can create combinations ofindex and column values that are missing from the originaldataframe.

+
+
+
+
+
+
+
+level
+

type: int | list | str
default: -1
The indexes to stack.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Stack.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Stack.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Sum.html b/reference/transform/Sum.html new file mode 100644 index 00000000..7cc2248d --- /dev/null +++ b/reference/transform/Sum.html @@ -0,0 +1,434 @@ + + + + + + + + +Sum type: sum — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Sum  type: sum#

+
+
+class lumen.transforms.base.Sum(*, axis, level, controls, name)#
+

Sums numeric values in each column of the DataFrame and returns a +new DataFrame with a single row containing the sum for each +original column, see pandas.DataFrame.sum.

+

df.count(axis=<axis>, level=<level>).to_frame().T

+
+
+
+

Parameters#

+
+
+
+
+
+
+axis
+

type: int | str
default: 0
The axis to rename. 0 or ‘index’, 1 or ‘columns’

+
+
+
+
+
+
+
+level
+

type: int | list | str
default: None
The indexes to stack.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Sum.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Sum.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/Unstack.html b/reference/transform/Unstack.html new file mode 100644 index 00000000..10c26982 --- /dev/null +++ b/reference/transform/Unstack.html @@ -0,0 +1,432 @@ + + + + + + + + +Unstack type: unstack — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Unstack  type: unstack#

+
+
+class lumen.transforms.base.Unstack(*, fill_value, level, controls, name)#
+

Unstack applies pandas.DataFrame.unstack to the declared level.

+

df.unstack(<level>)

+
+
+
+

Parameters#

+
+
+
+
+
+
+fill_value
+

type: int | str | dict
default: None
Replace NaN with this value if the unstack produces missing values.

+
+
+
+
+
+
+
+level
+

type: int | list | str
default: -1
The indexes to unstack.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Unstack.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Unstack.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/index.html b/reference/transform/index.html new file mode 100644 index 00000000..064be268 --- /dev/null +++ b/reference/transform/index.html @@ -0,0 +1,691 @@ + + + + + + + + +Transform — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Transform#

+
+
+class lumen.transforms.base.Transform(*, controls, name)#
+

Transform components implement transforms of DataFrame objects.

+
+
+
+

Parameters#

+
+
+
+
+
+
+controls
+

type: list[Any]
default: []
Parameters that should be exposed as widgets in the UI.

+
+
+
+
+
+
+
+name
+

type: str
default: 'Transform'
String identifier for this object.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Transform.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Transform.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+

Types#

+
+
+
+
+
+
+Filter type: None
+

Filter transform implement the filtering behavior of Filter components.

+
+
+
+
+
+
+
+HistoryTransform type: history
+

HistoryTransform accumulates a history of the queried data.

+
+
+
+
+
+
+
+Aggregate type: aggregate
+

Aggregate one or more columns or indexes, see pandas.DataFrame.groupby.

+
+
+
+
+
+
+
+Sort type: sort
+

Sort on one or more columns, see pandas.DataFrame.sort_values.

+
+
+
+
+
+
+
+Query type: query
+

Query applies the pandas.DataFrame.query method.

+
+
+
+
+
+
+
+Columns type: columns
+

Columns selects a subset of columns.

+
+
+
+
+
+
+
+Astype type: as_type
+

Astype transforms the type of one or more columns.

+
+
+
+
+
+
+
+Stack type: stack
+

Stack applies pandas.DataFrame.stack to the declared level.

+
+
+
+
+
+
+
+Unstack type: unstack
+

Unstack applies pandas.DataFrame.unstack to the declared level.

+
+
+
+
+
+
+
+Iloc type: iloc
+

Iloc applies integer slicing to the data, see pandas.DataFrame.iloc.

+
+
+
+
+
+
+
+Sample type: sample
+

Sample returns a random sample of items.

+
+
+
+
+
+
+
+Compute type: compute
+

Compute turns a dask.dataframe.DataFrame into a pandas.DataFrame.

+
+
+
+
+
+
+
+Pivot type: pivot
+

Pivot applies pandas.DataFrame.pivot given an index, columns, and values.

+
+
+
+
+
+
+
+Melt type: melt
+

Melt applies the pandas.melt operation given the id_vars and value_vars.

+
+
+
+
+
+
+
+SetIndex type: set_index
+

SetIndex promotes DataFrame columns to indexes, see pandas.DataFrame.set_index.

+
+
+
+
+
+
+
+ResetIndex type: reset_index
+

ResetIndex resets DataFrame indexes to columns or drops them, see pandas.DataFrame.reset_index

+
+
+
+
+
+
+
+Rename type: rename
+

Rename renames columns or indexes, see pandas.DataFrame.rename.

+
+
+
+
+
+
+
+RenameAxis type: rename_axis
+

Set the name of the axis for the index or columns,

+
+
+
+
+
+
+
+Count type: count
+

Counts non-nan values in each column of the DataFrame and returns

+
+
+
+
+
+
+
+Sum type: sum
+

Sums numeric values in each column of the DataFrame and returns a

+
+
+
+
+
+
+
+Eval type: eval
+

Applies an eval assignment expression to a DataFrame. The

+
+
+
+
+
+
+
+project_lnglat type: project_lnglat
+

project_lnglat projects the given longitude/latitude columns to Web Mercator.

+
+
+
+
+
+
+
+SQLGroupBy type: sql_group_by
+

Performs a Group-By and aggregation

+
+
+
+
+
+
+
+SQLLimit type: sql_limit
+

Performs a LIMIT SQL operation on the query

+
+
+
+
+
+
+
+SQLDistinct type: sql_distinct
+

SQLDistinct Transform

+
+
+
+
+
+
+
+SQLMinMax type: sql_minmax
+

SQLMinMax Transform

+
+
+
+
+
+
+
+SQLColumns type: sql_columns
+

SQLColumns Transform

+
+
+
+
+
+
+
+SQLFilter type: sql_filter
+

Translates Lumen Filter query into a SQL WHERE statement.

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/transform/project_lnglat.html b/reference/transform/project_lnglat.html new file mode 100644 index 00000000..3136fdfc --- /dev/null +++ b/reference/transform/project_lnglat.html @@ -0,0 +1,434 @@ + + + + + + + + +project_lnglat type: project_lnglat — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

project_lnglat  type: project_lnglat#

+
+
+class lumen.transforms.base.project_lnglat(*, latitude, longitude, controls, name)#
+

project_lnglat projects the given longitude/latitude columns to Web Mercator.

+

Converts latitude and longitude values into WGS84 (Web Mercator) +coordinates (meters East of Greenwich and meters North of the +Equator).

+
+
+
+

Parameters#

+
+
+
+
+
+
+latitude
+

type: str
default: 'longitude'
Latitude column

+
+
+
+
+
+
+
+longitude
+

type: str
default: 'longitude'
Longitude column

+
+
+
+
+
+
+
+
+

Methods#

+
+
+project_lnglat.apply(table: DataFrame) DataFrame#
+

Given a table transform it in some way and return it.

+
+
Parameters:
+

table (DataFrame) – The queried table as a DataFrame.

+
+
Returns:
+

A DataFrame containing the transformed data.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+project_lnglat.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/variable/Constant.html b/reference/variable/Constant.html new file mode 100644 index 00000000..a7730f12 --- /dev/null +++ b/reference/variable/Constant.html @@ -0,0 +1,395 @@ + + + + + + + + +Constant type: constant — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Constant  type: constant#

+
+
+class lumen.variables.base.Constant(*, default, label, materialize, required, secure, value, name)#
+

Constant declares a constant value that can be referenced.

+
+
+
+

Methods#

+
+
+Constant.as_materialized() Constant#
+

If the variable is to be materialized by the builder this +implements the conversion from a variable that references +some external value to a materialized value.

+
+
+
+Constant.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/variable/Cookie.html b/reference/variable/Cookie.html new file mode 100644 index 00000000..8248512d --- /dev/null +++ b/reference/variable/Cookie.html @@ -0,0 +1,413 @@ + + + + + + + + +Cookie type: cookie — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/variable/EnvVariable.html b/reference/variable/EnvVariable.html new file mode 100644 index 00000000..a6148033 --- /dev/null +++ b/reference/variable/EnvVariable.html @@ -0,0 +1,413 @@ + + + + + + + + +EnvVariable type: env — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

EnvVariable  type: env#

+
+
+class lumen.variables.base.EnvVariable(*, key, default, label, materialize, required, secure, value, name)#
+

EnvVariable fetches an environment variable that can be referenced.

+
+
+
+

Parameters#

+
+
+
+
+
+
+key
+

type: str
default: None
The name of the environment variable to observe.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+EnvVariable.as_materialized() Constant#
+

If the variable is to be materialized by the builder this +implements the conversion from a variable that references +some external value to a materialized value.

+
+
+
+EnvVariable.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/variable/Header.html b/reference/variable/Header.html new file mode 100644 index 00000000..2d7e1290 --- /dev/null +++ b/reference/variable/Header.html @@ -0,0 +1,413 @@ + + + + + + + + +Header type: header — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Header  type: header#

+
+
+class lumen.variables.base.Header(*, key, default, label, materialize, required, secure, value, name)#
+

Header variables reflect the value of a request header.

+
+
+
+

Parameters#

+
+
+
+
+
+
+key
+

type: str
default: None
The request header to observe.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Header.as_materialized() Constant#
+

If the variable is to be materialized by the builder this +implements the conversion from a variable that references +some external value to a materialized value.

+
+
+
+Header.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/variable/Parameter.html b/reference/variable/Parameter.html new file mode 100644 index 00000000..f6fd6332 --- /dev/null +++ b/reference/variable/Parameter.html @@ -0,0 +1,413 @@ + + + + + + + + +Parameter type: param — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Parameter  type: param#

+
+
+class lumen.variables.base.Parameter(*, parameter, default, label, materialize, required, secure, value, name)#
+

Parameter variables reflect the current value of a parameter.

+
+
+
+

Parameters#

+
+
+
+
+
+
+parameter
+

type: param.Parameter
default: None
A parameter instance whose current value will be reflectedon this variable.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Parameter.as_materialized() Constant#
+

If the variable is to be materialized by the builder this +implements the conversion from a variable that references +some external value to a materialized value.

+
+
+
+Parameter.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/variable/URLQuery.html b/reference/variable/URLQuery.html new file mode 100644 index 00000000..8d996935 --- /dev/null +++ b/reference/variable/URLQuery.html @@ -0,0 +1,413 @@ + + + + + + + + +URLQuery type: url — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

URLQuery  type: url#

+
+
+class lumen.variables.base.URLQuery(*, key, default, label, materialize, required, secure, value, name)#
+

URLQuery variables reflect the value of a URL query parameter.

+
+
+
+

Parameters#

+
+
+
+
+
+
+key
+

type: str
default: None
The URL query parameter to observe.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+URLQuery.as_materialized() Constant#
+

If the variable is to be materialized by the builder this +implements the conversion from a variable that references +some external value to a materialized value.

+
+
+
+URLQuery.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/variable/UserInfo.html b/reference/variable/UserInfo.html new file mode 100644 index 00000000..352d28d2 --- /dev/null +++ b/reference/variable/UserInfo.html @@ -0,0 +1,413 @@ + + + + + + + + +UserInfo type: user — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

UserInfo  type: user#

+
+
+class lumen.variables.base.UserInfo(*, key, default, label, materialize, required, secure, value, name)#
+

UserInfo variables reflect a value in the user info returned by an OAuth provider.

+
+
+
+

Parameters#

+
+
+
+
+
+
+key
+

type: str
default: None
The key in the OAuth pn.state.user_info dictionary to observe.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+UserInfo.as_materialized() Constant#
+

If the variable is to be materialized by the builder this +implements the conversion from a variable that references +some external value to a materialized value.

+
+
+
+UserInfo.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/variable/Widget.html b/reference/variable/Widget.html new file mode 100644 index 00000000..96ee8ad1 --- /dev/null +++ b/reference/variable/Widget.html @@ -0,0 +1,422 @@ + + + + + + + + +Widget type: widget — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Widget  type: widget#

+
+
+class lumen.variables.base.Widget(*, kind, throttled, default, label, materialize, required, secure, value, name)#
+

Widget variables dynamically reflect the current widget value.

+
+
+
+

Parameters#

+
+
+
+
+
+
+kind   required
+

type: str
default: None
The type of widget to instantiate.

+
+
+
+
+
+
+
+throttled
+

type: bool
default: True
If the widget has a value_throttled parameter use that instead,ensuring that no intermediate events are generated, e.g. whendragging a slider.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Widget.as_materialized() Constant#
+

If the variable is to be materialized by the builder this +implements the conversion from a variable that references +some external value to a materialized value.

+
+
+
+Widget.to_spec(context=None)#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/variable/index.html b/reference/variable/index.html new file mode 100644 index 00000000..91fc1ea2 --- /dev/null +++ b/reference/variable/index.html @@ -0,0 +1,552 @@ + + + + + + + + +Variable — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Variable#

+
+
+class lumen.variables.base.Variable(*, default, label, materialize, required, secure, value, name)#
+

Variable components declare values that can be referenced from other components.

+

The source of the Variable value can be anything from an +environment variable to a widget or URL parameter. Variable +components allow a concise way to configure other components and +make it possible to orchestrate actions across multiple +components.

+
+
+
+

Parameters#

+
+
+
+
+
+
+default
+

type: Any
default: None
Default value to use if no other value is defined

+
+
+
+
+
+
+
+label
+

type: str
default: None
Optional label override for variable. Used wherever the variableshows up in the UI.

+
+
+
+
+
+
+
+materialize
+

type: bool
default: False
Whether the variable should be inlined as a constant variable(in the Lumen Builder).

+
+
+
+
+
+
+
+name
+

type: str
default: 'Variable'
String identifier for this object.

+
+
+
+
+
+
+
+required
+

type: bool
default: False
Whether the variable should be treated as required.

+
+
+
+
+
+
+
+secure
+

type: bool
default: False
Whether the variable should be treated as secure.

+
+
+
+
+
+
+
+value
+

type: Any
default: None
The materialized value of the variable.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Variable.as_materialized() Constant#
+

If the variable is to be materialized by the builder this +implements the conversion from a variable that references +some external value to a materialized value.

+
+
+
+Variable.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Return type:
+

Resolved and instantiated Component object

+
+
+
+
+
+

Types#

+
+
+
+
+
+
+Constant type: constant
+

Constant declares a constant value that can be referenced.

+
+
+
+
+
+
+
+EnvVariable type: env
+

EnvVariable fetches an environment variable that can be referenced.

+
+
+
+
+
+
+
+Widget type: widget
+

Widget variables dynamically reflect the current widget value.

+
+
+
+
+
+
+
+Parameter type: param
+

Parameter variables reflect the current value of a parameter.

+
+
+
+
+
+
+
+URLQuery type: url
+

URLQuery variables reflect the value of a URL query parameter.

+
+
+
+
+
+
+
+Cookie type: cookie
+

Cookie variables reflect the value of a cookie in the request.

+
+
+
+
+
+
+
+UserInfo type: user
+

UserInfo variables reflect a value in the user info returned by an OAuth provider.

+
+
+
+
+
+
+
+Header type: header
+

Header variables reflect the value of a request header.

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/AltairView.html b/reference/view/AltairView.html new file mode 100644 index 00000000..2d307842 --- /dev/null +++ b/reference/view/AltairView.html @@ -0,0 +1,611 @@ + + + + + + + + +AltairView type: altair — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

AltairView  type: altair#

+
+
+class lumen.views.base.AltairView(*, chart, encode, mark, marker, project, properties, transform, x, y, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

AltairView provides a declarative way to render Altair charts.

+
+
+
+

Parameters#

+
+
+
+
+
+
+chart
+

type: dict
default: {}
Keyword argument for Chart.

+
+
+
+
+
+
+
+encode
+

type: dict
default: {}
Keyword arguments for encode.

+
+
+
+
+
+
+
+mark
+

type: dict
default: {}
Keyword arguments for mark.

+
+
+
+
+
+
+
+marker
+

type: Any
default: 'line'
Possible values: 'area' | 'bar' | 'boxplot' | 'circle' | 'errorband' | 'errorbar' | 'geoshape' | 'image' | 'line' | 'point' | 'rect' | 'rule' | 'square' | 'text' | 'tick' | 'trail'

+
+
+
+
+
+
+
+project
+

type: dict
default: None
Keyword arguments for project.

+
+
+
+
+
+
+
+properties
+

type: dict
default: None
Keyword arguments for properties.

+
+
+
+
+
+
+
+transform
+

type: dict
default: None
Keyword arguments for transforms, nested by the type oftransform, e.g. {‘bin’: {‘as_’: ‘binned’, ‘field’: ‘x’}}.

+
+
+
+
+
+
+
+x
+

type: Any
default: None
Possible values: ``
The column to render on the x-axis.

+
+
+
+
+
+
+
+y
+

type: Any
default: None
Possible values: ``
The column to render on the y-axis.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+AltairView.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+AltairView.get_panel() Vega#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+AltairView.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+AltairView.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+AltairView.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+AltairView.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+AltairView.update(*events: Event, invalidate_cache: bool = True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/DownloadView.html b/reference/view/DownloadView.html new file mode 100644 index 00000000..5c9499f2 --- /dev/null +++ b/reference/view/DownloadView.html @@ -0,0 +1,557 @@ + + + + + + + + +DownloadView type: download — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

DownloadView  type: download#

+
+
+class lumen.views.base.DownloadView(*, filename, format, kwargs, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

DownloadView renders a button that allows downloading data as CSV, Excel, and parquet files.

+
+
+
+

Parameters#

+
+
+
+
+
+
+filename
+

type: str
default: 'data'
Filename of the downloaded file.

+
+
+
+
+
+
+
+format   required
+

type: Any
default: None
Possible values: 'csv' | 'xlsx' | 'json' | 'parquet'
The format to download the data in.

+
+
+
+
+
+
+
+kwargs
+

type: dict
default: {}
Keyword arguments passed to the serialization function, e.g.data.to_csv(file_obj, **kwargs).

+
+
+
+
+
+
+
+
+

Methods#

+
+
+DownloadView.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+DownloadView.get_panel() FileDownload#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+DownloadView.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+DownloadView.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+DownloadView.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+DownloadView.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+DownloadView.update(*events: Event, invalidate_cache: bool = True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/IndicatorView.html b/reference/view/IndicatorView.html new file mode 100644 index 00000000..d8a592b3 --- /dev/null +++ b/reference/view/IndicatorView.html @@ -0,0 +1,548 @@ + + + + + + + + +IndicatorView type: indicator — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

IndicatorView  type: indicator#

+
+
+class lumen.views.base.IndicatorView(*, indicator, label, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

IndicatorView renders the latest field value as a Panel Indicator.

+
+
+
+

Parameters#

+
+
+
+
+
+
+indicator
+

type: Any
default: panel.widgets.Trend
Possible values: panel.widgets.Trend | panel.widgets.Tqdm | panel.widgets.BooleanStatus | panel.widgets.LoadingSpinner | panel.widgets.Progress | panel.widgets.Number | panel.widgets.indicators.String | panel.widgets.Gauge | panel.widgets.Dial | panel.widgets.LinearGauge
The name of the panel Indicator type.

+
+
+
+
+
+
+
+label
+

type: str
default: ''
A custom label to use for the Indicator.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+IndicatorView.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+IndicatorView.get_panel()#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+IndicatorView.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+IndicatorView.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+IndicatorView.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+IndicatorView.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+IndicatorView.update(*events: Event, invalidate_cache: bool = True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/Panel.html b/reference/view/Panel.html new file mode 100644 index 00000000..f35d1e51 --- /dev/null +++ b/reference/view/Panel.html @@ -0,0 +1,564 @@ + + + + + + + + +Panel type: panel — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Panel  type: panel#

+
+
+class lumen.views.base.Panel(*, spec, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

Panel views provide a way to declaratively wrap a Panel component.

+

The Panel View is a very general purpose view that allows +expressing arbitrary Panel objects as a specification. The Panel +specification may be arbitrarily nested making it possible to +specify entire layouts. Additionally the Panel specification also +supports references, including standard source and variable +references and a custom $data reference that inserts the current +data of the View.

+

``` +type: panel

+
+
+
spec:

type: panel.layout.Column +objects:

+
+
    +
  • type: pn.pane.Markdown +object: ‘# My custom title’

  • +
  • type: pn.pane.DataFrame +object: $data

  • +
+
+
+
+
+

```

+
+
+
+

Parameters#

+
+
+
+
+
+
+spec
+

type: dict
default: None

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Panel.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Panel.get_panel()#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+Panel.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+Panel.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+Panel.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+Panel.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+Panel.update(*events: Event, invalidate_cache: bool = True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/PerspectiveView.html b/reference/view/PerspectiveView.html new file mode 100644 index 00000000..6c32a6a5 --- /dev/null +++ b/reference/view/PerspectiveView.html @@ -0,0 +1,621 @@ + + + + + + + + +PerspectiveView type: perspective — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

PerspectiveView  type: perspective#

+
+
+class lumen.views.base.PerspectiveView(*, aggregates, column_pivots, columns, computed_columns, filters, plugin, row_pivots, selectable, sort, theme, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

PerspectiveView renders data into a Perspective widget.

+

See https://panel.holoviz.org/reference/panes/Perspective.html for more details.

+
+
+
+

Parameters#

+
+
+
+
+
+
+aggregates
+

type: dict
default: None
How to aggregate. For example {x: “distinct count”}

+
+
+
+
+
+
+
+column_pivots
+

type: Any
default: None
Possible values: ``
A list of source columns to pivot by. For example [“x”, “y”]

+
+
+
+
+
+
+
+columns
+

type: Any
default: None
Possible values: ``
A list of source columns to show as columns. For example [“x”, “y”]

+
+
+
+
+
+
+
+computed_columns
+

type: Any
default: None
Possible values: ``
A list of computed columns. For example [“”x”+”index””]

+
+
+
+
+
+
+
+filters
+

type: list[Any]
default: None
How to filter. For example [[“x”, “<”, 3],[“y”, “contains”, “abc”]]

+
+
+
+
+
+
+
+plugin
+

type: Any
default: 'datagrid'
Possible values: 'hypergrid' | 'datagrid' | 'd3_y_bar' | 'd3_x_bar' | 'd3_xy_line' | 'd3_y_line' | 'd3_y_area' | 'd3_y_scatter' | 'd3_xy_scatter' | 'd3_treemap' | 'd3_sunburst' | 'd3_heatmap' | 'd3_candlestick' | 'd3_ohlc'
The name of a plugin to display the data. For example hypergrid or d3_xy_scatter.

+
+
+
+
+
+
+
+row_pivots
+

type: Any
default: None
Possible values: ``
A list of source columns to group by. For example [“x”, “y”]

+
+
+
+
+
+
+
+selectable
+

type: bool
default: True
Whether items are selectable.

+
+
+
+
+
+
+
+sort
+

type: list[Any]
default: None
How to sort. For example[[“x”,”desc”]]

+
+
+
+
+
+
+
+theme
+

type: Any
default: 'material'
Possible values: 'material' | 'material-dark' | 'monokai' | 'solarized' | 'solarized-dark' | 'vaporwave'
The style of the PerspectiveViewer. For example material-dark

+
+
+
+
+
+
+
+
+

Methods#

+
+
+PerspectiveView.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+PerspectiveView.get_panel() Perspective#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+PerspectiveView.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+PerspectiveView.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+PerspectiveView.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+PerspectiveView.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+PerspectiveView.update(*events: Event, invalidate_cache: bool = True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/StringView.html b/reference/view/StringView.html new file mode 100644 index 00000000..cb44f274 --- /dev/null +++ b/reference/view/StringView.html @@ -0,0 +1,539 @@ + + + + + + + + +StringView type: string — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

StringView  type: string#

+
+
+class lumen.views.base.StringView(*, font_size, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

StringView renders the latest value of the field as a HTML string.

+
+
+
+

Parameters#

+
+
+
+
+
+
+font_size
+

type: str
default: '24pt'
The font size of the rendered field value.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+StringView.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+StringView.get_panel() HTML#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+StringView.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+StringView.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+StringView.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+StringView.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+StringView.update(*events: Event, invalidate_cache: bool = True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/Table.html b/reference/view/Table.html new file mode 100644 index 00000000..07d84ef1 --- /dev/null +++ b/reference/view/Table.html @@ -0,0 +1,540 @@ + + + + + + + + +Table type: table — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Table  type: table#

+
+
+class lumen.views.base.Table(*, page_size, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

Table renders data using the powerful Panel Tabulator component.

+

See https://panel.holoviz.org/reference/widgets/Tabulator.html

+
+
+
+

Parameters#

+
+
+
+
+
+
+page_size
+

type: int
default: 20
bounds: (1, None)
Number of rows to render per page, if pagination is enabled.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+Table.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+Table.get_panel()#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+Table.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+Table.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+Table.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+Table.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+Table.update(*events: Event, invalidate_cache: bool = True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/hvPlotUIView.html b/reference/view/hvPlotUIView.html new file mode 100644 index 00000000..db58a843 --- /dev/null +++ b/reference/view/hvPlotUIView.html @@ -0,0 +1,575 @@ + + + + + + + + +hvPlotUIView type: hvplot_ui — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

hvPlotUIView  type: hvplot_ui#

+
+
+class lumen.views.base.hvPlotUIView(*, by, groupby, kind, x, y, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

hvPlotUIView displays provides a component for exploring datasets interactively.

+
+
+
+

Parameters#

+
+
+
+
+
+
+by
+

type: Any
default: None
Possible values: ``
The column(s) to facet the plot by.

+
+
+
+
+
+
+
+groupby
+

type: Any
default: None
Possible values: ``
The column(s) to group by.

+
+
+
+
+
+
+
+kind
+

type: str
default: None
The kind of plot, e.g. ‘scatter’ or ‘line’.

+
+
+
+
+
+
+
+x
+

type: Any
default: None
Possible values: ``
The column to render on the x-axis.

+
+
+
+
+
+
+
+y
+

type: Any
default: None
Possible values: ``
The column to render on the y-axis.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+hvPlotUIView.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+hvPlotUIView.get_panel()#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+hvPlotUIView.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+hvPlotUIView.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+hvPlotUIView.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+hvPlotUIView.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+hvPlotUIView.update(*events: Event, invalidate_cache: bool = True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/hvPlotView.html b/reference/view/hvPlotView.html new file mode 100644 index 00000000..70081d43 --- /dev/null +++ b/reference/view/hvPlotView.html @@ -0,0 +1,609 @@ + + + + + + + + +hvPlotView type: hvplot — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

hvPlotView  type: hvplot#

+
+
+class lumen.views.base.hvPlotView(*, opts, selection_expr, streaming, by, groupby, kind, x, y, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

hvPlotView renders the queried data as a bokeh plot generated with hvPlot.

+

hvPlot allows for a concise but powerful declaration of a plot via +its simple API.

+
+
+
+

Parameters#

+
+
+
+
+
+
+by
+

type: Any
default: None
Possible values: ``
The column(s) to facet the plot by.

+
+
+
+
+
+
+
+groupby
+

type: Any
default: None
Possible values: ``
The column(s) to group by.

+
+
+
+
+
+
+
+kind
+

type: str
default: None
The kind of plot, e.g. ‘scatter’ or ‘line’.

+
+
+
+
+
+
+
+opts
+

type: dict
default: {}
HoloViews options to apply on the plot.

+
+
+
+
+
+
+
+selection_expr
+

type: Any
default: None
A selection expression caputirng the current selection appliedon the plot.

+
+
+
+
+
+
+
+streaming
+

type: bool
default: False
Whether to stream new data to the plot or rerender the plot.

+
+
+
+
+
+
+
+x
+

type: Any
default: None
Possible values: ``
The column to render on the x-axis.

+
+
+
+
+
+
+
+y
+

type: Any
default: None
Possible values: ``
The column to render on the y-axis.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+hvPlotView.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+hvPlotView.get_panel()#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+hvPlotView.get_plot(df)#
+
+
+
+hvPlotView.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+hvPlotView.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+hvPlotView.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+hvPlotView.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+hvPlotView.update(*events, invalidate_cache=True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/reference/view/index.html b/reference/view/index.html new file mode 100644 index 00000000..6076f803 --- /dev/null +++ b/reference/view/index.html @@ -0,0 +1,715 @@ + + + + + + + + +View — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

View#

+
+
+class lumen.views.base.View(*, controls, download, field, limit, loading_indicator, pipeline, rerender, selection_group, title, name)#
+

View components provide a visual representation for the data returned +by a lumen.source.base.Source or lumen.pipeline.Pipeline.

+

The View must return a Panel object or an object that can be +rendered by Panel. The base class provides methods which query the +the provided lumen.pipeline.Pipeline.

+

Subclasses should use these methods to query the data and return +a Viewable Panel object in the get_panel method.

+
+
+
+

Parameters#

+
+
+
+
+
+
+controls
+

type: list[Any]
default: []
Parameters that should be exposed as widgets in the UI.

+
+
+
+
+
+
+
+download
+

type: lumen.downloads.Download
default: Download()
The download objects determines whether and how the source tablescan be downloaded.

+
+
+
+
+
+
+
+field
+

type: Any
default: None
Possible values: ``
The field being visualized.

+
+
+
+
+
+
+
+limit
+

type: int
default: None
bounds: (0, None)
Limits the number of rows that are rendered.

+
+
+
+
+
+
+
+loading_indicator
+

type: bool
default: True
Whether to display a loading indicator on the View when thePipeline is refreshing the data.

+
+
+
+
+
+
+
+name
+

type: str
default: 'View'
String identifier for this object.

+
+
+
+
+
+
+
+pipeline
+

type: lumen.Pipeline
default: None
The data pipeline that drives the View.

+
+
+
+
+
+
+
+rerender
+

type: bool
default: False
An event that is triggered whenever the View requests a re-render.

+
+
+
+
+
+
+
+selection_group
+

type: str
default: None
Declares a selection group the plot is part of. This featurerequires the separate HoloViews library.

+
+
+
+
+
+
+
+title
+

type: str
default: None
The title of the view.

+
+
+
+
+
+
+
+
+

Methods#

+
+
+View.get_data()#
+

Queries the Source for the specified table applying any +filters and transformations specified on the View. Unlike +get_value this should be used when multiple return values +are expected.

+
+
Returns:
+

The queried table after filtering and transformations are +applied.

+
+
Return type:
+

DataFrame

+
+
+
+
+
+View.get_panel() Viewable#
+

Constructs and returns a Panel object which will represent a +view of the queried table.

+
+
Returns:
+

A Panel Viewable object representing a current +representation of the queried table.

+
+
Return type:
+

panel.Viewable

+
+
+
+
+
+View.get_value(field: Optional[str] = None)#
+

Queries the Source for the data associated with a particular +field applying any filters and transformations specified on +the View. Unlike get_data this method returns a single +scalar value associated with the field and should therefore +only be used if only a single.

+
+
Parameters:
+

field (str (optional)) – The field from the table to return; if None uses +field defined on the View.

+
+
Returns:
+

A single scalar value representing the current value of +the queried field.

+
+
Return type:
+

object

+
+
+
+
+
+View.servable(title: Optional[str] = None, location: bool | 'Location' = True, area: str = 'main', target: Optional[str] = None) Viewable#
+

Serves the object or adds it to the configured +pn.state.template if in a panel serve context, writes to the +DOM if in a pyodide context and returns the Panel object to +allow it to display itself in a notebook context.

+
+
Parameters:
+
    +
  • title (str) – A string title to give the Document (if served as an app)

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
  • area (str (deprecated)) – The area of a template to add the component too. Only has an +effect if pn.config.template has been set.

  • +
  • target (str) – Target area to write to. If a template has been configured +on pn.config.template this refers to the target area in the +template while in pyodide this refers to the ID of the DOM +node to write to.

  • +
+
+
Return type:
+

The Panel object itself

+
+
+
+
+
+View.show(title: Optional[str] = None, port: int = 0, address: Optional[str] = None, websocket_origin: Optional[str] = None, threaded: bool = False, verbose: bool = True, open: bool = True, location: bool | 'Location' = True, **kwargs) threading.Thread | 'Server'#
+

Starts a Bokeh server and displays the Viewable in a new tab.

+
+
Parameters:
+
    +
  • title (str | None) – A string title to give the Document (if served as an app)

  • +
  • port (int (optional, default=0)) – Allows specifying a specific port

  • +
  • address (str) – The address the server should listen on for HTTP requests.

  • +
  • websocket_origin (str or list(str) (optional)) – A list of hosts that can connect to the websocket. +This is typically required when embedding a server app in +an external web site. +If None, “localhost” is used.

  • +
  • threaded (boolean (optional, default=False)) – Whether to launch the Server on a separate thread, allowing +interactive use.

  • +
  • verbose (boolean (optional, default=True)) – Whether to print the address and port

  • +
  • open (boolean (optional, default=True)) – Whether to open the server in a new browser tab

  • +
  • location (boolean or panel.io.location.Location) – Whether to create a Location component to observe and +set the URL location.

  • +
+
+
Returns:
+

server – Returns the Bokeh server instance or the thread the server +was launched on (if threaded=True)

+
+
Return type:
+

bokeh.server.Server or panel.io.server.StoppableThread

+
+
+
+
+
+View.to_spec(context: Optional[Dict[str, Any]] = None) Dict[str, Any]#
+

Exports the full specification to reconstruct this component.

+
+
Parameters:
+

context (Dict[str, Any]) – Context contains the specification of all previously serialized components, +e.g. to allow resolving of references.

+
+
Return type:
+

Declarative specification of this component.

+
+
+
+
+
+View.update(*events: Event, invalidate_cache: bool = True)#
+

Triggers an update in the View.

+
+
Parameters:
+
    +
  • events (tuple) – param events that may trigger an update.

  • +
  • invalidate_cache (bool) – Whether to clear the View’s cache.

  • +
+
+
+
+
+
+

Types#

+
+
+
+
+
+
+Panel type: panel
+

Panel views provide a way to declaratively wrap a Panel component.

+
+
+
+
+
+
+
+StringView type: string
+

StringView renders the latest value of the field as a HTML string.

+
+
+
+
+
+
+
+IndicatorView type: indicator
+

IndicatorView renders the latest field value as a Panel Indicator.

+
+
+
+
+
+
+
+Table type: table
+

Table renders data using the powerful Panel Tabulator component.

+
+
+
+
+
+
+
+DownloadView type: download
+

DownloadView renders a button that allows downloading data as CSV, Excel, and parquet files.

+
+
+
+
+
+
+
+PerspectiveView type: perspective
+

PerspectiveView renders data into a Perspective widget.

+
+
+
+
+
+
+
+AltairView type: altair
+

AltairView provides a declarative way to render Altair charts.

+
+
+
+
+
+
+
+hvPlotUIView type: hvplot_ui
+

hvPlotUIView displays provides a component for exploring datasets interactively.

+
+
+
+
+
+
+
+hvPlotView type: hvplot
+

hvPlotView renders the queried data as a bokeh plot generated with hvPlot.

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/search.html b/search.html new file mode 100644 index 00000000..a6912cc8 --- /dev/null +++ b/search.html @@ -0,0 +1,320 @@ + + + + + + +Search - Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+

Search

+ + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/searchindex.js b/searchindex.js new file mode 100644 index 00000000..18751edd --- /dev/null +++ b/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["background/index", "background/lumen_in_python", "background/pipeline_branching", "comparison", "gallery/bikes", "gallery/earthquakes", "gallery/index", "gallery/nyc_taxi", "gallery/penguins", "gallery/precip", "gallery/seattle", "gallery/windturbines", "getting_started/build_dashboard", "getting_started/core_concepts", "getting_started/index", "getting_started/installation", "getting_started/lumen_architecture", "getting_started/pipelines", "how_to/advanced/auth", "how_to/advanced/callbacks", "how_to/advanced/index", "how_to/advanced/local_components", "how_to/advanced/variables_and_references", "how_to/data_intake/cache", "how_to/data_intake/files", "how_to/data_intake/index", "how_to/data_output/download_data", "how_to/data_output/index", "how_to/data_processing/branch_pipeline", "how_to/data_processing/index", "how_to/data_processing/pipeline_python", "how_to/data_visualization/dashboard_python", "how_to/data_visualization/deploy", "how_to/data_visualization/index", "how_to/data_visualization/views", "how_to/index", "how_to/validation/index", "how_to/validation/validate", "index", "reference/Config", "reference/Defaults", "reference/Layout", "reference/Pipeline", "reference/auth/Auth", "reference/auth/YamlAuthMapperPlugin", "reference/auth/index", "reference/filter/BinFilter", "reference/filter/ConstantFilter", "reference/filter/DateFilter", "reference/filter/DatetimeFilter", "reference/filter/FacetFilter", "reference/filter/ParamFilter", "reference/filter/WidgetFilter", "reference/filter/index", "reference/index", "reference/source/DerivedSource", "reference/source/FileSource", "reference/source/IntakeSQLSource", "reference/source/IntakeSource", "reference/source/JSONSource", "reference/source/JoinedSource", "reference/source/PanelSessionSource", "reference/source/RESTSource", "reference/source/WebsiteSource", "reference/source/index", "reference/transform/Aggregate", "reference/transform/Astype", "reference/transform/Columns", "reference/transform/Compute", "reference/transform/Count", "reference/transform/Eval", "reference/transform/Filter", "reference/transform/HistoryTransform", "reference/transform/Iloc", "reference/transform/Melt", "reference/transform/Pivot", "reference/transform/Query", "reference/transform/Rename", "reference/transform/RenameAxis", "reference/transform/ResetIndex", "reference/transform/SQLColumns", "reference/transform/SQLDistinct", "reference/transform/SQLFilter", "reference/transform/SQLGroupBy", "reference/transform/SQLLimit", "reference/transform/SQLMinMax", "reference/transform/Sample", "reference/transform/SetIndex", "reference/transform/Sort", "reference/transform/Stack", "reference/transform/Sum", "reference/transform/Unstack", "reference/transform/index", "reference/transform/project_lnglat", "reference/variable/Constant", "reference/variable/Cookie", "reference/variable/EnvVariable", "reference/variable/Header", "reference/variable/Parameter", "reference/variable/URLQuery", "reference/variable/UserInfo", "reference/variable/Widget", "reference/variable/index", "reference/view/AltairView", "reference/view/DownloadView", "reference/view/IndicatorView", "reference/view/Panel", "reference/view/PerspectiveView", "reference/view/StringView", "reference/view/Table", "reference/view/hvPlotUIView", "reference/view/hvPlotView", "reference/view/index", "ui/configuration", "ui/index"], "filenames": ["background/index.md", "background/lumen_in_python.md", "background/pipeline_branching.md", "comparison.md", "gallery/bikes.md", "gallery/earthquakes.md", "gallery/index.md", "gallery/nyc_taxi.md", "gallery/penguins.md", "gallery/precip.md", "gallery/seattle.md", "gallery/windturbines.md", "getting_started/build_dashboard.md", "getting_started/core_concepts.md", "getting_started/index.md", "getting_started/installation.md", "getting_started/lumen_architecture.md", "getting_started/pipelines.md", "how_to/advanced/auth.md", "how_to/advanced/callbacks.md", "how_to/advanced/index.md", "how_to/advanced/local_components.md", "how_to/advanced/variables_and_references.md", "how_to/data_intake/cache.md", "how_to/data_intake/files.md", "how_to/data_intake/index.md", "how_to/data_output/download_data.md", "how_to/data_output/index.md", "how_to/data_processing/branch_pipeline.md", "how_to/data_processing/index.md", "how_to/data_processing/pipeline_python.md", "how_to/data_visualization/dashboard_python.md", "how_to/data_visualization/deploy.md", "how_to/data_visualization/index.md", "how_to/data_visualization/views.md", "how_to/index.md", "how_to/validation/index.md", "how_to/validation/validate.md", "index.md", "reference/Config.md", "reference/Defaults.md", "reference/Layout.md", "reference/Pipeline.md", "reference/auth/Auth.md", "reference/auth/YamlAuthMapperPlugin.md", "reference/auth/index.md", "reference/filter/BinFilter.md", "reference/filter/ConstantFilter.md", "reference/filter/DateFilter.md", "reference/filter/DatetimeFilter.md", "reference/filter/FacetFilter.md", "reference/filter/ParamFilter.md", "reference/filter/WidgetFilter.md", "reference/filter/index.md", "reference/index.md", "reference/source/DerivedSource.md", "reference/source/FileSource.md", "reference/source/IntakeSQLSource.md", "reference/source/IntakeSource.md", "reference/source/JSONSource.md", "reference/source/JoinedSource.md", "reference/source/PanelSessionSource.md", "reference/source/RESTSource.md", "reference/source/WebsiteSource.md", "reference/source/index.md", "reference/transform/Aggregate.md", "reference/transform/Astype.md", "reference/transform/Columns.md", "reference/transform/Compute.md", "reference/transform/Count.md", "reference/transform/Eval.md", "reference/transform/Filter.md", "reference/transform/HistoryTransform.md", "reference/transform/Iloc.md", "reference/transform/Melt.md", "reference/transform/Pivot.md", "reference/transform/Query.md", "reference/transform/Rename.md", "reference/transform/RenameAxis.md", "reference/transform/ResetIndex.md", "reference/transform/SQLColumns.md", "reference/transform/SQLDistinct.md", "reference/transform/SQLFilter.md", "reference/transform/SQLGroupBy.md", "reference/transform/SQLLimit.md", "reference/transform/SQLMinMax.md", "reference/transform/Sample.md", "reference/transform/SetIndex.md", "reference/transform/Sort.md", "reference/transform/Stack.md", "reference/transform/Sum.md", "reference/transform/Unstack.md", "reference/transform/index.md", "reference/transform/project_lnglat.md", "reference/variable/Constant.md", "reference/variable/Cookie.md", "reference/variable/EnvVariable.md", "reference/variable/Header.md", "reference/variable/Parameter.md", "reference/variable/URLQuery.md", "reference/variable/UserInfo.md", "reference/variable/Widget.md", "reference/variable/index.md", "reference/view/AltairView.md", "reference/view/DownloadView.md", "reference/view/IndicatorView.md", "reference/view/Panel.md", "reference/view/PerspectiveView.md", "reference/view/StringView.md", "reference/view/Table.md", "reference/view/hvPlotUIView.md", "reference/view/hvPlotView.md", "reference/view/index.md", "ui/configuration.md", "ui/index.md"], "titles": ["Background", "Lumen in Python", "Pipeline Branching", "Lumen compared to other dashboarding tools", "Transport for London: Bike Point Occupancy", "Earthquakes", "Gallery", "NYC Taxi", "Penguins", "Precipitation", "Seattle Weather", "Windturbines", " Build a dashboard", " Core Concepts", "Getting Started", " Installation", "Lumen\u2019s Architecture", " Building a data pipeline", "Configuring Authentication", "How to define callbacks", "Advanced Topics", "Access custom components", "How to use variables", "How to use cache", "How to access files", "Data Intake", "How to download data", "Data Output", "Branch a pipeline", "Data Processing", "Build a Pipeline in Python", "Building a dashboard in Python", "Deploy a dashboard", "Visualize and Deploy", "How to define views", "How to Guides", "Validation", "Validate the specification", "Welcome to Lumen!", "Config", "Defaults", "Layout", "Pipeline", "Auth", "YamlAuthMapperPlugin\u00a0\u00a0type: yaml", "Auth", "BinFilter\u00a0\u00a0type: bins", "ConstantFilter\u00a0\u00a0type: constant", "DateFilter\u00a0\u00a0type: date", "DatetimeFilter\u00a0\u00a0type: datetime", "FacetFilter\u00a0\u00a0type: facet", "ParamFilter\u00a0\u00a0type: param", "WidgetFilter\u00a0\u00a0type: widget", "Filter", "Reference", "DerivedSource\u00a0\u00a0type: derived", "FileSource\u00a0\u00a0type: file", "IntakeSQLSource\u00a0\u00a0type: intake_sql", "IntakeSource\u00a0\u00a0type: intake", "JSONSource\u00a0\u00a0type: json", "JoinedSource\u00a0\u00a0type: join", "PanelSessionSource\u00a0\u00a0type: session_info", "RESTSource\u00a0\u00a0type: rest", "WebsiteSource\u00a0\u00a0type: live", "Source", "Aggregate\u00a0\u00a0type: aggregate", "Astype\u00a0\u00a0type: as_type", "Columns\u00a0\u00a0type: columns", "Compute\u00a0\u00a0type: compute", "Count\u00a0\u00a0type: count", "Eval\u00a0\u00a0type: eval", "Filter\u00a0\u00a0type: None", "HistoryTransform\u00a0\u00a0type: history", "Iloc\u00a0\u00a0type: iloc", "Melt\u00a0\u00a0type: melt", "Pivot\u00a0\u00a0type: pivot", "Query\u00a0\u00a0type: query", "Rename\u00a0\u00a0type: rename", "RenameAxis\u00a0\u00a0type: rename_axis", "ResetIndex\u00a0\u00a0type: reset_index", "SQLColumns\u00a0\u00a0type: sql_columns", "SQLDistinct\u00a0\u00a0type: sql_distinct", "SQLFilter\u00a0\u00a0type: sql_filter", "SQLGroupBy\u00a0\u00a0type: sql_group_by", "SQLLimit\u00a0\u00a0type: sql_limit", "SQLMinMax\u00a0\u00a0type: sql_minmax", "Sample\u00a0\u00a0type: sample", "SetIndex\u00a0\u00a0type: set_index", "Sort\u00a0\u00a0type: sort", "Stack\u00a0\u00a0type: stack", "Sum\u00a0\u00a0type: sum", "Unstack\u00a0\u00a0type: unstack", "Transform", "project_lnglat\u00a0\u00a0type: project_lnglat", "Constant\u00a0\u00a0type: constant", "Cookie\u00a0\u00a0type: cookie", "EnvVariable\u00a0\u00a0type: env", "Header\u00a0\u00a0type: header", "Parameter\u00a0\u00a0type: param", "URLQuery\u00a0\u00a0type: url", "UserInfo\u00a0\u00a0type: user", "Widget\u00a0\u00a0type: widget", "Variable", "AltairView\u00a0\u00a0type: altair", "DownloadView\u00a0\u00a0type: download", "IndicatorView\u00a0\u00a0type: indicator", "Panel\u00a0\u00a0type: panel", "PerspectiveView\u00a0\u00a0type: perspective", "StringView\u00a0\u00a0type: string", "Table\u00a0\u00a0type: table", "hvPlotUIView\u00a0\u00a0type: hvplot_ui", "hvPlotView\u00a0\u00a0type: hvplot", "View", "Configuration", "UI"], "terms": {"lumen": [0, 2, 12, 13, 14, 17, 19, 21, 22, 23, 24, 28, 30, 31, 32, 34, 35, 37, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114], "": [0, 1, 3, 12, 13, 22, 23, 26, 28, 35, 39, 41, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 74, 75, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "page": [0, 15, 28, 109, 114], "discuss": [0, 1, 2, 13], "kei": [0, 13, 44, 45, 54, 56, 59, 87, 95, 96, 97, 99, 100], "topic": 0, "high": [0, 10, 22, 39, 54, 114], "level": [0, 13, 37, 39, 54, 69, 77, 79, 89, 90, 91, 92, 114], "provid": [0, 3, 13, 17, 19, 21, 35, 37, 38, 39, 41, 42, 52, 53, 54, 55, 56, 59, 64, 100, 102, 103, 106, 110, 112, 114], "us": [0, 1, 3, 12, 13, 15, 16, 17, 24, 26, 28, 30, 31, 32, 34, 35, 37, 38, 39, 41, 42, 44, 45, 46, 48, 49, 51, 52, 53, 54, 55, 56, 58, 59, 64, 71, 74, 75, 77, 78, 83, 87, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "context": [0, 17, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "design": [0, 3, 31, 38], "decis": [0, 3], "python": [0, 3, 13, 15, 22, 23, 24, 32, 34, 35, 38], "pipelin": [0, 4, 5, 8, 9, 10, 11, 12, 14, 16, 19, 21, 22, 23, 24, 31, 34, 35, 38, 39, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "branch": [0, 17, 30, 35], "motiv": 1, "case": [1, 3, 12, 13, 15, 17, 21, 22, 37, 77], "api": [1, 4, 38, 56, 111], "under": 1, "construct": [1, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "when": [2, 3, 13, 15, 19, 21, 22, 23, 30, 31, 37, 38, 39, 41, 42, 52, 55, 57, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "you": [2, 3, 12, 13, 15, 17, 19, 21, 22, 23, 24, 26, 28, 30, 32, 34, 37, 38, 70, 113, 114], "might": [2, 13, 55], "need": [2, 3, 12, 13, 15, 17, 21, 23, 34], "one": [2, 3, 12, 21, 22, 23, 31, 34, 41, 42, 50, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 70, 71, 88, 92, 114], "A": [2, 13, 17, 23, 30, 31, 34, 38, 39, 41, 42, 46, 53, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 86, 87, 88, 89, 90, 91, 92, 93, 98, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "consist": [2, 3, 13, 23, 30], "filter": [2, 3, 4, 5, 8, 9, 10, 11, 12, 16, 21, 23, 28, 31, 34, 38, 39, 40, 41, 42, 46, 47, 48, 49, 50, 51, 52, 55, 56, 58, 59, 60, 61, 62, 63, 64, 82, 92, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "transform": [2, 3, 4, 5, 11, 12, 16, 17, 21, 22, 28, 34, 38, 39, 40, 41, 42, 43, 44, 45, 55, 57, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 93, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "compon": [2, 3, 15, 17, 22, 28, 31, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114], "These": [2, 3, 13], "manipul": [2, 13, 16, 28, 80, 81, 82, 83, 84, 85], "data": [2, 3, 7, 10, 19, 22, 23, 24, 28, 31, 34, 38, 39, 41, 42, 50, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 86, 87, 88, 89, 90, 91, 92, 93, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "ar": [2, 3, 12, 13, 15, 16, 17, 19, 21, 22, 26, 28, 30, 32, 34, 35, 37, 38, 42, 46, 52, 55, 56, 59, 79, 89, 101, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "typic": [2, 3, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "appli": [2, 3, 13, 16, 17, 21, 28, 30, 40, 42, 43, 45, 53, 54, 55, 57, 60, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "sourc": [2, 3, 4, 5, 7, 8, 9, 10, 11, 15, 16, 17, 21, 23, 24, 26, 28, 31, 34, 35, 37, 38, 39, 40, 41, 42, 47, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113], "drive": [2, 3, 13, 17, 38, 42, 112], "more": [2, 3, 12, 13, 21, 30, 31, 35, 41, 42, 44, 54, 60, 64, 65, 66, 70, 88, 92, 107, 114], "visual": [2, 3, 12, 13, 17, 32, 34, 38, 42, 54, 112, 114], "output": [2, 13, 22, 31, 34, 42], "howev": [2, 3, 17], "can": [2, 3, 12, 13, 15, 16, 17, 19, 21, 22, 23, 24, 28, 30, 31, 32, 34, 38, 41, 42, 43, 45, 48, 49, 51, 52, 54, 55, 56, 58, 59, 60, 61, 64, 70, 87, 89, 94, 96, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "also": [2, 3, 12, 13, 15, 17, 19, 21, 22, 30, 37, 38, 60, 64, 77, 78, 106], "off": [2, 12], "anoth": [2, 17, 42], "allow": [2, 3, 13, 15, 17, 28, 30, 35, 37, 38, 39, 40, 41, 42, 44, 46, 47, 50, 53, 54, 55, 57, 62, 64, 78, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "further": [2, 12], "exist": [2, 3, 21, 23, 28, 42, 51, 55, 75, 87, 114], "onli": [2, 3, 12, 13, 19, 22, 28, 31, 41, 42, 69, 77, 78, 79, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "while": [2, 3, 17, 21, 22, 30, 32, 38, 41, 42, 62, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "retain": [2, 74], "share": [2, 3, 4, 7, 9, 13, 17, 37, 38, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "comput": [2, 17, 23, 30, 38, 42, 54, 56, 57, 59, 92, 107], "up": [2, 12, 13, 15, 22, 23, 28, 31, 35, 37, 72, 102, 113, 114], "point": [2, 5, 6, 7, 8, 10, 11, 13, 28, 30, 58, 103, 114], "creation": [2, 30], "view": [2, 3, 4, 5, 7, 8, 9, 10, 11, 16, 17, 21, 22, 23, 24, 26, 30, 32, 35, 37, 38, 40, 41, 50, 51, 53, 103, 104, 105, 106, 107, 108, 109, 110, 111, 113], "same": [2, 3, 15, 17, 21, 26, 28, 32, 34, 35, 46, 114], "underli": [2, 3, 77, 78], "differ": [2, 3, 13, 17, 21, 22, 26, 28, 35, 38, 51], "step": [2, 12, 14, 17, 28, 30, 35, 38, 42], "process": [2, 3, 28, 38, 42, 114], "For": [2, 3, 13, 15, 21, 37, 107], "instanc": [2, 15, 30, 31, 41, 42, 52, 64, 98, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "mai": [2, 13, 15, 17, 21, 37, 42, 55, 60, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "want": [2, 3, 13, 17, 19, 30, 60, 114], "displai": [2, 3, 13, 17, 28, 31, 32, 41, 42, 54, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "tabl": [2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 17, 21, 22, 23, 24, 26, 28, 30, 31, 34, 37, 42, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 86, 87, 88, 89, 90, 91, 92, 93, 103, 104, 105, 106, 107, 108, 110, 111, 112, 114], "alongsid": [2, 19, 21], "aggreg": [2, 17, 28, 30, 54, 83, 92, 107], "how": [2, 3, 12, 13, 14, 17, 21, 28, 31, 37, 38, 41, 79, 107, 112, 114], "here": [3, 17, 21, 31, 34, 37, 114], "we": [3, 12, 13, 17, 19, 21, 22, 28, 31, 60, 114], "first": [3, 12, 17, 21, 22, 23, 28, 30, 39, 113, 114], "talk": 3, "about": [3, 12, 34, 37, 41, 61, 114], "most": [3, 13, 22, 28, 31, 38], "fundament": 3, "set": [3, 12, 13, 17, 30, 39, 41, 42, 46, 53, 54, 58, 64, 71, 74, 78, 87, 92, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114], "apart": 3, "from": [3, 12, 15, 17, 19, 21, 22, 23, 24, 28, 30, 34, 35, 38, 39, 41, 42, 46, 47, 52, 53, 54, 55, 56, 58, 59, 60, 64, 66, 79, 80, 81, 82, 83, 84, 85, 89, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114], "specif": [3, 15, 16, 17, 19, 21, 22, 23, 26, 30, 32, 35, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "competit": 3, "complementari": 3, "so": [3, 12, 28, 31, 34], "i": [3, 15, 16, 17, 19, 21, 23, 24, 26, 28, 30, 32, 34, 38, 39, 41, 42, 43, 45, 46, 48, 49, 52, 53, 54, 55, 56, 58, 59, 64, 74, 77, 78, 79, 88, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114], "clear": [3, 41, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "fit": 3, "As": [3, 13, 16, 19, 22, 28, 30, 60, 114], "list": [3, 13, 21, 23, 30, 40, 41, 42, 46, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 69, 71, 78, 79, 80, 81, 82, 83, 85, 87, 88, 89, 90, 91, 92, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "pyviz": [3, 15], "org": [3, 7, 8, 9, 11, 12, 13, 15, 17, 21, 22, 24, 28, 30, 31, 34, 44, 107, 109], "mani": [3, 13, 22, 34, 38], "base": [3, 12, 17, 41, 42, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "open": [3, 12, 15, 22, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "build": [3, 13, 14, 21, 28, 35, 38, 114], "analyt": [3, 38], "There": [3, 12, 21, 22, 26, 30], "hundr": 3, "consid": 3, "commerci": 3, "ones": 3, "choos": [3, 15], "between": [3, 13, 15, 17, 38, 51, 114], "all": [3, 12, 13, 15, 17, 21, 22, 23, 30, 38, 39, 40, 41, 42, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 74, 75, 79, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "what": [3, 15, 114], "let": [3, 12, 17, 22, 26, 28, 31, 38, 114], "anyon": 3, "your": [3, 12, 13, 17, 21, 24, 26, 30, 32, 34, 35, 37, 38, 114], "team": [3, 38], "make": [3, 13, 17, 22, 38, 61, 65, 75, 102, 106, 114], "app": [3, 14, 16, 31, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "custom": [3, 17, 19, 35, 38, 105, 106], "code": [3, 13, 26, 32, 54, 63, 64], "without": [3, 13, 22, 28, 86], "requir": [3, 16, 30, 31, 38, 41, 42, 53, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "everyon": 3, "learn": [3, 30, 35], "great": [3, 32], "choic": [3, 13, 30, 114], "have": [3, 12, 13, 17, 19, 21, 30, 32, 34, 56, 60, 75, 79, 114], "some": [3, 13, 17, 21, 35, 41, 50, 53, 54, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 114], "peopl": 3, "an": [3, 12, 13, 14, 17, 19, 22, 23, 24, 30, 31, 34, 38, 39, 41, 42, 43, 45, 46, 51, 52, 54, 55, 56, 57, 58, 64, 70, 75, 80, 81, 82, 83, 84, 85, 92, 96, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "organ": 3, "who": [3, 38], "write": [3, 17, 41, 42, 64, 70, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "doe": [3, 12, 17, 56, 114], "precis": 3, "particular": [3, 17, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "whether": [3, 13, 22, 32, 39, 41, 42, 46, 48, 49, 52, 53, 54, 56, 57, 58, 59, 63, 64, 65, 87, 89, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "connect": [3, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "analysi": [3, 17], "method": [3, 13, 17, 19, 22, 28, 30, 31, 54], "thing": [3, 12, 13, 28, 114], "chart": [3, 10, 54, 103, 112], "type": [3, 4, 5, 7, 8, 9, 10, 11, 13, 15, 17, 21, 22, 23, 24, 26, 28, 30, 31, 34, 37, 39, 40, 41, 42, 43, 54, 114], "liter": 3, "anyth": [3, 102], "els": 3, "do": [3, 13, 19, 21, 22, 26, 79], "which": [3, 13, 15, 17, 21, 22, 30, 38, 55, 56, 60, 64, 79, 83, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "ideal": [3, 12], "those": [3, 13], "programm": 3, "ecosystem": [3, 13, 34, 38], "daili": [3, 10], "work": [3, 12, 15, 17, 23, 28, 30, 31, 35], "like": [3, 12, 13, 17, 19, 22, 28, 31, 55, 70, 78, 114], "holoviz": [3, 7, 8, 9, 11, 12, 13, 17, 21, 22, 24, 28, 30, 31, 34, 44, 107, 109], "thei": [3, 13, 19, 21, 35, 37, 114], "function": [3, 19, 41, 54, 56, 59, 64, 83, 104], "own": [3, 12, 13, 21, 114], "made": [3, 13, 23, 55], "avail": [3, 12, 13, 17, 38, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "non": [3, 23, 54, 69, 92], "user": [3, 13, 19, 21, 22, 26, 30, 38, 39, 44, 54, 56, 59, 102], "That": 3, "wai": [3, 13, 15, 17, 19, 22, 24, 26, 54, 60, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 86, 87, 88, 89, 90, 91, 92, 93, 102, 103, 106, 112], "benefit": [3, 17], "innov": 3, "being": [3, 13, 37, 53, 112], "develop": 3, "Of": 3, "cours": 3, "tradit": 3, "bi": [3, 38], "technic": 3, "domain": 3, "knowledg": [3, 35], "longer": 3, "establish": [3, 13], "polish": 3, "friendli": 3, "interfac": [3, 13, 30], "than": [3, 12, 13, 22, 35, 38, 42], "ha": [3, 13, 28, 39, 41, 42, 46, 52, 55, 101, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "meet": 3, "less": [3, 12], "If": [3, 13, 15, 21, 23, 28, 30, 32, 38, 41, 42, 46, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 72, 74, 75, 79, 88, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "them": [3, 21, 22, 54, 59, 79, 83, 92], "But": 3, "reach": 3, "limit": [3, 54, 84, 92, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "includ": [3, 13, 15, 34, 38, 69, 106, 114], "script": [3, 30, 31, 32], "purpos": [3, 106], "add": [3, 13, 21, 24, 31, 38, 39, 41, 42, 46, 52, 72, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "fulli": [3, 19, 39], "integr": [3, 38], "unlik": [3, 13, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "itself": [3, 22, 31, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "built": [3, 17, 22, 30, 34, 38, 114], "directli": [3, 15, 55], "scientif": 3, "stack": [3, 54, 69, 90, 92], "intak": [3, 9, 13, 15, 37, 38, 54, 57, 64], "librari": [3, 12, 13, 38, 112], "veri": [3, 13, 15, 54, 59, 64, 106], "rich": [3, 21], "basi": [3, 17], "b": [3, 23, 42, 60], "treat": [3, 102], "class": [3, 21, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "citizen": 3, "exactli": 3, "ani": [3, 13, 17, 22, 30, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "nativ": 3, "new": [3, 12, 13, 41, 42, 55, 57, 60, 66, 69, 70, 75, 80, 81, 82, 83, 84, 85, 87, 90, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "contribut": 3, "expert": [3, 38], "immedi": 3, "usabl": 3, "everi": [3, 30, 32, 38], "rest": [3, 22, 54, 61, 64], "thu": 3, "matter": 3, "special": [3, 46, 48, 49, 53, 54], "esoter": 3, "By": [3, 12, 17, 30, 52, 54, 79, 83, 92], "standard": [3, 57, 106], "job": 3, "common": [3, 13, 30], "across": [3, 13, 35, 53, 64, 102], "market": 3, "segment": 3, "won": 3, "t": [3, 10, 12, 13, 69, 90], "well": 3, "headroom": 3, "releas": 3, "valv": 3, "rarer": 3, "individu": [3, 23, 30, 34, 44, 60, 64, 114], "import": [3, 17, 19, 23, 24, 28, 30, 31, 34, 114], "bit": [3, 12, 13], "otherwis": [3, 56, 59, 87], "domin": 3, "workflow": 3, "greatli": 3, "reduc": 3, "its": [3, 15, 111], "effect": [3, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "The": [3, 12, 13, 15, 16, 19, 21, 22, 23, 24, 26, 30, 31, 32, 34, 37, 38, 39, 41, 42, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 96, 97, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114], "lead": [3, 13], "focu": 3, "intuit": 3, "full": [3, 17, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "featur": [3, 13, 22], "explicit": [3, 23, 42, 55], "good": [3, 12, 13], "support": [3, 17, 23, 24, 38, 54, 57, 64, 106], "again": [3, 31], "audienc": 3, "wide": [3, 12, 21, 38], "swath": 3, "out": [3, 13, 38, 39], "box": [3, 26, 38], "save": [3, 12, 21, 23, 32], "lot": [3, 12, 22], "time": [3, 5, 9, 19, 22, 23, 32, 37, 113, 114], "access": [3, 17, 35, 64], "alreadi": [3, 32, 114], "even": [3, 12, 38], "applic": [3, 12, 13, 17, 19, 31, 38, 39, 54, 61, 64, 114], "final": [3, 12, 13, 28, 31, 34, 114], "deploy": [3, 32, 114], "platform": 3, "deploi": [3, 12, 39, 114], "each": [3, 13, 23, 42, 46, 54, 64, 69, 90, 92, 114], "separ": [3, 28, 30, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "system": [3, 38], "afford": 3, "catch": [3, 37], "depend": [3, 13, 23, 48, 49, 52, 56, 114], "mix": 3, "scienc": [3, 13, 58], "plu": 3, "mayb": 3, "few": [3, 14, 38], "littl": 3, "side": 3, "everyth": [3, 12], "around": [3, 38], "opposit": 3, "situat": 3, "take": [3, 13, 23, 31, 34, 114], "power": [3, 13, 17, 22, 38, 54, 109, 111, 112], "much": [3, 114], "almost": [3, 23], "small": 3, "success": 3, "now": [3, 12, 13, 17, 19, 21, 28, 30, 31, 60], "problem": [3, 15, 35], "bigger": 3, "impact": 3, "whole": [3, 13, 16, 64], "where": [3, 16, 22, 31, 54, 82, 92, 113, 114], "vendor": 3, "either": [3, 13, 15, 17, 19, 23, 24, 56, 77, 78, 87, 114], "jupyt": 3, "notebook": [3, 17, 24, 30, 31, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "through": [3, 14, 28, 114], "normal": 3, "over": [3, 50, 55, 60, 114], "machin": 3, "abl": [3, 34], "publish": [3, 31, 60], "feed": [3, 13], "back": [3, 13, 28], "desir": 3, "improv": [3, 13, 87], "thi": [3, 14, 15, 17, 19, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114], "idea": [3, 12, 32], "flow": 3, "freeli": 3, "solut": 3, "costli": 3, "consum": 3, "artifici": 3, "barrier": 3, "switch": 3, "department": 3, "boundari": 3, "environ": [3, 13, 22, 31, 37, 54, 96, 102, 114], "explor": [3, 13, 22, 54, 110, 112, 114], "javascript": 3, "instal": [3, 7, 11, 14, 19, 38], "heavyweight": 3, "despit": 3, "bill": 3, "lightweight": [3, 58], "difficult": 3, "databas": [3, 11, 38, 57], "manag": [3, 38], "along": [3, 41, 50, 53, 54], "variou": [3, 15, 17, 24, 34, 114], "account": 3, "singl": [3, 22, 46, 48, 49, 50, 52, 60, 69, 87, 90, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "local": [3, 13, 21, 23, 30, 35, 56, 59, 64, 114], "primarili": 3, "gear": 3, "toward": [3, 13, 114], "depart": 3, "compani": 3, "dedic": 3, "administ": 3, "maintain": 3, "easili": [3, 13, 17, 30, 34, 114], "give": [3, 12, 22, 31, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "abil": [3, 13, 38, 114], "text": [3, 12, 21, 103], "necessarili": 3, "central": 3, "administr": 3, "agre": 3, "inher": 3, "extens": [3, 17, 22, 30, 31, 34, 38, 56], "accept": 3, "written": 3, "configur": [3, 13, 23, 35, 39, 41, 42, 54, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "customiz": 3, "behavior": [3, 23, 30, 54, 71, 92, 114], "implement": [3, 13, 51, 54, 64, 71, 92, 94, 95, 96, 97, 98, 99, 100, 101, 102], "just": [3, 12, 13, 17, 21, 114], "overal": [3, 12, 13, 39], "focus": 3, "world": 3, "live": [3, 13, 17, 21, 22, 54, 64], "narrowli": 3, "expos": [3, 13, 92, 112], "within": [3, 13, 21], "packag": [3, 15, 19], "web": [3, 41, 42, 54, 92, 93, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "select": [3, 4, 5, 8, 11, 12, 13, 22, 30, 46, 48, 49, 52, 53, 54, 67, 92, 107, 111, 112, 114], "valu": [3, 4, 11, 13, 22, 23, 39, 42, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 59, 65, 67, 69, 70, 71, 72, 74, 75, 77, 78, 81, 82, 85, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "plot": [3, 8, 13, 17, 22, 34, 38, 54, 110, 111, 112, 114], "ui": [3, 39, 41, 42, 92, 102, 112, 113], "nonetheless": 3, "becaus": [3, 12, 13, 17], "relat": 3, "In": [3, 12, 13, 15, 17, 21, 22, 28, 31, 37, 55, 57, 60, 77, 113, 114], "contrast": 3, "insert": [3, 12, 37, 79, 106], "similar": [3, 13, 30, 54, 59, 64], "lake": [3, 38], "both": [3, 13, 59, 64], "bad": 3, "With": [3, 21, 30], "remain": [3, 75], "wherev": [3, 102], "wa": [3, 10, 13, 19, 41, 42, 60, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "origin": [3, 28, 69, 70, 74, 90], "locat": [3, 4, 12, 13, 19, 34, 37, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "befor": [3, 22, 114], "begin": 3, "decentr": 3, "approach": [3, 30, 32], "messier": 3, "queri": [3, 5, 17, 23, 38, 41, 42, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 99, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "larg": [3, 23], "remot": [3, 5, 8, 12, 13, 17, 22, 23, 35, 56, 59], "dataset": [3, 7, 8, 9, 11, 12, 13, 17, 21, 22, 24, 28, 30, 31, 34, 38, 54, 64, 110, 112, 114], "lazili": 3, "subset": [3, 12, 13, 54, 67, 92], "ever": 3, "pull": 3, "big": 3, "datashad": [3, 23], "read": [3, 13, 24, 28, 57, 64], "effici": 3, "file": [3, 5, 8, 10, 13, 16, 17, 19, 22, 26, 28, 30, 31, 32, 34, 35, 38, 44, 45, 54, 57, 58, 59, 64, 104, 112, 114], "format": [3, 5, 11, 13, 23, 24, 26, 38, 42, 62, 104], "parquet": [3, 13, 23, 24, 30, 38, 54, 56, 64, 104, 112], "broad": 3, "rang": [3, 12, 21, 38, 48, 49, 71], "size": [3, 10, 22, 108], "suitabl": 3, "abov": [3, 17, 80, 81, 82, 83, 84, 85], "gui": 3, "dimens": [3, 41, 50, 53, 54], "column": [3, 4, 5, 9, 11, 12, 13, 17, 21, 22, 28, 30, 34, 37, 39, 41, 54, 60, 65, 66, 69, 70, 71, 72, 74, 75, 77, 78, 79, 80, 81, 83, 85, 87, 88, 89, 90, 92, 93, 103, 106, 107, 110, 111], "simpl": [3, 12, 13, 17, 21, 22, 34, 38, 60, 111], "columnar": 3, "help": [3, 13, 15], "altern": [3, 24, 30, 77], "suggest": 3, "combin": [3, 21, 22, 23, 38, 89], "arbitrari": [3, 13, 17, 43, 45, 54, 106], "lai": [3, 39], "result": [3, 12, 17, 28, 70, 75, 89], "program": 3, "model": [3, 9, 37], "declar": [3, 13, 15, 19, 31, 37, 38, 39, 40, 41, 42, 44, 46, 51, 52, 53, 54, 55, 56, 59, 60, 71, 72, 89, 91, 92, 94, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "natur": 3, "part": [3, 22, 23, 38, 112], "specifi": [3, 13, 19, 21, 28, 35, 37, 41, 42, 60, 71, 74, 75, 77, 78, 88, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "pure": 3, "languag": 3, "keep": [3, 34], "particularli": 3, "extend": [3, 38, 54, 57, 64], "capabl": [3, 13], "addit": [3, 13, 15, 28, 42, 57, 114], "number": [3, 11, 13, 17, 19, 39, 52, 59, 84, 86, 105, 109, 112, 114], "technologi": 3, "could": [3, 13, 21, 31, 34, 52], "availbl": 3, "plai": 3, "role": 3, "commnun": 3, "meantim": 3, "nearli": 3, "plotli": 3, "matplotlib": [3, 22], "bqplot": 3, "potenti": [3, 42], "config": [4, 5, 7, 8, 9, 10, 11, 12, 16, 19, 21, 31, 41, 42, 64, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113], "titl": [4, 5, 7, 8, 9, 10, 11, 13, 21, 22, 23, 24, 26, 28, 31, 34, 39, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "station": 4, "layout": [4, 5, 7, 8, 9, 10, 11, 12, 16, 21, 22, 23, 24, 26, 28, 31, 34, 39, 53, 106], "variabl": [4, 11, 16, 23, 28, 30, 35, 42, 70, 74, 94, 95, 96, 97, 98, 99, 100, 101, 106, 113], "tfl_api_kei": 4, "constant": [4, 11, 53, 54, 95, 96, 97, 98, 99, 100, 101, 102], "a1c692de000b4944af55f59d8e849915": 4, "json": [4, 13, 23, 24, 30, 53, 54, 55, 56, 57, 58, 60, 61, 62, 63, 64, 104], "true": [4, 5, 7, 8, 9, 10, 11, 21, 31, 37, 39, 41, 42, 46, 48, 49, 52, 53, 56, 57, 58, 59, 64, 65, 74, 78, 87, 88, 89, 101, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "http": [4, 5, 8, 10, 12, 13, 17, 21, 22, 23, 24, 26, 28, 30, 31, 34, 41, 42, 56, 59, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "tfl": 4, "gov": [4, 5], "uk": 4, "bikepoint": 4, "chunk_siz": [4, 59], "15": [4, 17], "cache_dir": [4, 8, 9, 11, 23, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "cach": [4, 8, 9, 11, 35, 41, 42, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "id": [4, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "app_kei": 4, "station_occup": 4, "join": [4, 54, 64], "index": [4, 21, 50, 54, 60, 65, 69, 74, 75, 77, 78, 79, 87, 88, 89, 90, 91, 92, 107], "widget": [4, 5, 8, 9, 10, 11, 12, 13, 17, 21, 22, 28, 30, 31, 42, 46, 48, 49, 53, 54, 92, 102, 105, 107, 109, 112, 114], "field": [4, 5, 8, 9, 10, 11, 12, 13, 17, 21, 22, 28, 30, 31, 37, 42, 46, 47, 48, 49, 50, 51, 52, 53, 54, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "bikescount": 4, "totaldock": 4, "lat": 4, "50": [4, 7, 8, 11, 17], "52": 4, "lon": 4, "1": [4, 5, 7, 23, 30, 39, 41, 42, 69, 72, 77, 78, 86, 89, 90, 91, 109], "commonnam": 4, "project_lnglat": [4, 5, 54, 92], "latitud": [4, 5, 54, 92, 93], "longitud": [4, 5, 54, 92, 93], "param": [4, 5, 8, 11, 17, 21, 41, 42, 44, 53, 54, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "paramet": [4, 5, 8, 11, 12, 13, 16, 17, 28, 54, 68, 114], "selection_expr": [4, 5, 8, 11, 111], "count_hist": 4, "total_hist": 4, "hvplot": [4, 5, 7, 8, 9, 11, 12, 13, 21, 22, 34, 37, 54, 112, 114], "kind": [4, 5, 7, 8, 9, 11, 12, 13, 17, 21, 22, 31, 34, 37, 54, 64, 101, 110, 111, 114], "x": [4, 5, 7, 8, 9, 10, 11, 12, 13, 17, 21, 31, 37, 103, 107, 110, 111], "y": [4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 17, 21, 31, 37, 41, 103, 107, 110, 111], "hover_col": 4, "tile": [4, 5, 7, 11], "esristreet": [4, 7], "respons": [4, 5, 7, 8, 9, 11, 12, 13, 21, 31, 37], "height": [4, 5, 7, 8, 11, 21, 28, 31], "500": [4, 5, 7, 11, 52], "color": [4, 8, 10, 12, 13, 21, 34, 39], "line_color": [4, 5], "black": 4, "xaxi": [4, 5, 7, 11], "null": [4, 5, 7, 11], "yaxi": [4, 5, 7, 11], "framewis": 4, "fals": [4, 5, 7, 8, 10, 12, 13, 21, 28, 30, 31, 39, 41, 42, 46, 48, 49, 52, 53, 56, 57, 58, 59, 64, 69, 74, 77, 79, 86, 87, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "selection_group": [4, 5, 7, 8, 11, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "margin": 4, "0": [4, 5, 7, 21, 23, 30, 41, 42, 59, 69, 77, 78, 79, 86, 90, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "100": 4, "hidden_column": [4, 5], "show_index": [4, 5, 8, 12, 21, 28], "sizing_mod": [4, 5, 7, 8, 10, 11, 12, 13, 21, 28, 31], "stretch_width": [4, 5, 8, 10, 11, 12, 13, 21, 28, 31], "hist": [4, 5, 7, 8, 11, 12, 13, 21], "300": [4, 7, 11, 12, 21, 28, 31], "stream": [4, 5, 11, 111], "dashboard": [5, 9, 13, 14, 15, 19, 21, 22, 24, 26, 34, 35, 37, 38, 39, 40, 44, 113], "theme": [5, 8, 11, 13, 39, 107, 114], "dark": [5, 8, 11, 12, 13, 107], "cache_per_queri": [5, 8, 10, 23, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "usg": 5, "fdsnw": 5, "event": [5, 39, 41, 42, 46, 52, 56, 57, 58, 59, 61, 62, 63, 64, 101, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "csv": [5, 8, 9, 10, 12, 13, 17, 21, 22, 24, 26, 28, 30, 31, 34, 38, 54, 56, 59, 64, 104, 112, 114], "mag": 5, "depth": 5, "place": [5, 21, 37, 114], "rm": 5, "map": [5, 37, 44, 45, 54, 66, 83], "esri": [5, 11], "fill_color": 5, "white": [5, 11], "hover": [5, 114], "page_s": [5, 8, 11, 31, 109], "16": [5, 17], "pagin": [5, 8, 17, 109], "midnight": [5, 8, 12], "mag_hist": 5, "250": [5, 11, 21], "depth_hist": [5, 8], "rms_hist": 5, "refresh_r": [5, 13, 41], "60000": 5, "2": [5, 7, 23, 30, 41, 42], "3": [5, 7, 9, 21, 30, 37, 39, 107], "4": [5, 7, 23, 30, 42], "london": 6, "bike": [6, 38], "nyc": [6, 38], "taxi": [6, 38], "penguin": [6, 12, 13, 17, 21, 22, 24, 26, 28, 30, 31, 34, 38, 114], "precipit": [6, 10], "seattl": [6, 38], "weather": [6, 38], "earthquak": [6, 38], "trip": 7, "nyc_taxi": 7, "duckdb": [7, 11], "uri": [7, 11, 57, 58], "memori": [7, 11, 38, 57, 64], "read_parquet": [7, 11], "s3": [7, 9, 11, 23], "v2": 7, "nyc_taxi_wid": [7, 23], "parq": [7, 11, 23], "initi": [7, 11, 17, 22, 23, 31, 80, 81, 82, 83, 84, 85], "httpf": [7, 11], "load": [7, 11, 13, 19, 23, 30, 39, 54, 56, 57, 58, 59, 64, 112], "pickup_x": 7, "pickup_i": 7, "raster": [7, 11], "cnorm": 7, "eq_hist": 7, "colorbar": 7, "dropoff_x": 7, "dropoff_i": 7, "trip_dist": 7, "bin_rang": 7, "20": [7, 11, 109], "tip_amount": 7, "fare_amount": 7, "stretch_both": [7, 8], "palmer": [8, 12, 13, 21, 31, 114], "tab": [8, 12, 13, 17, 39, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "v1": [8, 9, 11, 12, 13, 17, 21, 22, 24, 28, 30, 31, 34], "speci": [8, 12, 13, 17, 21, 28, 30, 31, 34], "island": [8, 12, 13, 17, 21, 28, 30, 31], "sex": [8, 12, 13, 17, 21, 28, 30, 31], "expr": [8, 11, 70], "scatter": [8, 13, 17, 21, 31, 34, 110, 111], "bill_length_mm": [8, 12, 13, 17, 21, 28, 30, 31], "bill_depth_mm": [8, 12, 13, 17, 21, 28, 30, 31], "350": [8, 13], "length_hist": 8, "mass_hist": 8, "body_mass_g": [8, 17, 30], "fit_data_fil": 8, "rocki": 9, "catalog": [9, 54, 57, 58, 64], "southern_rocki": [9, 37], "driver": 9, "arg": 9, "urlpath": 9, "srlcc_": 9, "emiss": [9, 37], "_precip_": 9, "csv_kwarg": 9, "skiprow": 9, "name": [9, 13, 19, 21, 22, 28, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "precip": [9, 37], "parse_d": [9, 10, 22], "storage_opt": 9, "anon": 9, "southern": 9, "facet": [9, 13, 37, 41, 53, 54, 110, 111], "line": [9, 13, 26, 37, 103, 110, 111], "min_height": [9, 37], "200": [9, 10, 37], "altair": [10, 54, 112], "reload": [10, 23, 35, 39, 41], "sync_with_url": [10, 39, 46, 47, 48, 49, 50, 51, 52, 53], "raw": [10, 12, 20, 22, 25, 26, 27, 29, 33, 36], "githubusercont": [10, 22, 26], "com": [10, 22, 23, 26, 56, 59], "vega": [10, 103], "main": [10, 22, 30, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "doc": [10, 21], "kwarg": [10, 13, 21, 22, 23, 41, 42, 56, 59, 65, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "date": [10, 22, 49, 53, 54, 71, 72], "marker": [10, 103], "rect": [10, 103], "2012": 10, "2015": 10, "temperatur": 10, "f": [10, 19], "shorthand": 10, "o": 10, "dai": 10, "month": 10, "encod": [10, 103], "max": [10, 85], "temp_max": 10, "q": 10, "scale": [10, 38], "scheme": 10, "inferno": 10, "properti": [10, 17, 103], "width": [10, 11], "contain": [10, 13, 22, 23, 30, 34, 39, 40, 41, 42, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 86, 87, 88, 89, 90, 91, 92, 93, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "monthdat": 10, "maximum": [10, 52], "c": [10, 11, 15, 23, 42], "n": [10, 86], "5": [10, 30, 61], "count": [10, 11, 54, 90, 92, 107], "bar": [10, 39, 60, 103], "viewer": [11, 13, 26, 35], "templat": [11, 39, 41, 42, 59, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "materi": [11, 31, 35, 94, 95, 96, 97, 98, 99, 100, 101, 102, 107], "state": [11, 13, 17, 19, 39, 41, 42, 53, 100, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "url": [11, 13, 22, 24, 41, 42, 53, 54, 56, 59, 61, 62, 63, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "color_bi": 11, "panel": [11, 13, 17, 19, 21, 30, 31, 34, 38, 39, 41, 42, 44, 52, 54, 61, 64, 103, 104, 105, 107, 108, 109, 110, 111, 112], "option": [11, 16, 22, 23, 30, 31, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "t_manu": 11, "t_year": 11, "continent": 11, "xlong": 11, "125": 11, "66": 11, "ylat": 11, "24": 11, "t_state": 11, "p_year": 11, "t_cap": 11, "t_counti": 11, "p_name": 11, "t_model": 11, "t_hh": 11, "t_rd": 11, "t_rsa": 11, "t_ttlh": 11, "renam": [11, 54, 69, 78, 90, 92], "case_id": 11, "sum": [11, 54, 92], "eval": [11, 54, 92], "capac": 11, "10": [11, 31, 72], "6": [11, 15, 37], "overview": [11, 14, 38, 114], "cap_hist": 11, "year_hist": 11, "east": [11, 93], "north": [11, 93], "dynspread": 11, "header_filt": 11, "indic": [11, 34, 37, 38, 39, 46, 52, 54, 112], "default_color": 11, "0f": 11, "twh": 11, "frame_width": 11, "400": [11, 12, 21, 54, 63, 64], "tutori": [12, 13], "meant": [12, 13], "get": [12, 17, 22, 24, 35, 37, 38, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "hand": 12, "dirti": 12, "don": [12, 13], "worri": 12, "understand": [12, 13, 17], "yet": [12, 13, 38], "oblig": 12, "complet": [12, 13, 15, 32, 114], "direct": 12, "browser": [12, 32, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "look": [12, 13, 22, 30, 55], "someth": [12, 19], "favorit": 12, "editor": [12, 21], "empti": 12, "call": [12, 13, 17, 19, 28, 70], "below": [12, 21, 22, 23, 24, 28, 32, 34, 37, 114], "filesourc": [12, 13, 17, 24, 28, 30, 54, 59, 64, 114], "tell": 12, "fetch": [12, 54, 59, 96, 102, 114], "penguin_sourc": [12, 13, 21, 28, 34], "penguin_t": [12, 13, 21, 28, 34], "onc": [12, 13, 17, 30, 114], "termin": [12, 15], "navig": 12, "launch": [12, 19, 21, 28, 31, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113], "serv": [12, 13, 21, 22, 28, 31, 32, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "show": [12, 21, 22, 23, 24, 26, 28, 30, 31, 32, 34, 37, 39, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "autoreload": [12, 28, 32], "automat": [12, 21], "updat": [12, 13, 17, 19, 31, 39, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "whenev": [12, 41, 112], "chang": [12, 17, 31, 32, 39, 41, 42, 48, 49], "should": [12, 13, 41, 42, 46, 48, 49, 52, 60, 92, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "see": [12, 13, 15, 21, 22, 28, 30, 32, 54, 65, 69, 70, 73, 77, 78, 79, 87, 88, 90, 92, 107, 109, 114], "match": [12, 21, 71, 88], "preview": [12, 13, 22, 24, 26, 31, 114], "far": 12, "return": [12, 13, 17, 21, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "haven": [12, 13], "simplest": [12, 22], "u": [12, 17, 22, 31, 114], "primer": 12, "start": [12, 13, 17, 22, 28, 31, 32, 35, 41, 42, 73, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "pattern": [12, 13], "chose": 12, "hvplotview": [12, 13, 31, 34, 54, 112, 114], "background": [12, 13, 28, 39], "easi": [12, 13, 14, 30, 38, 114], "replac": [12, 86, 91], "overwhelm": 12, "instead": [12, 13, 17, 32, 46, 52, 57, 101, 114], "axi": [12, 54, 69, 77, 78, 86, 89, 90, 92, 103, 110, 111], "furthermor": [12, 22], "two": [12, 13, 21, 22, 23, 30, 31, 34, 42, 46, 55, 60, 62, 114], "sinc": [12, 17, 19, 38], "penguin_pipelin": [12, 13, 21, 28], "year": [12, 13, 17, 21, 28, 30, 31], "histogram": [12, 13], "default": [12, 16, 21, 30, 39, 41, 42, 43, 44, 45, 46, 48, 49, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "cut": 12, "our": [12, 21, 28, 31], "leav": 12, "space": 12, "resiz": 12, "ad": [12, 23, 28, 41, 114], "800": [12, 13, 17, 21], "section": [12, 13, 16, 17, 22], "descript": [12, 13, 41, 64], "note": [12, 17, 22, 42, 78], "bottom": [12, 13], "congratul": 12, "know": [12, 38], "exampl": [12, 13, 17, 19, 21, 22, 23, 24, 26, 28, 34, 37, 60, 107, 113, 114], "next": [12, 30], "review": [12, 15], "core": [12, 14, 38], "concept": [12, 14, 38], "achiev": [12, 13], "gener": [12, 13, 17, 38, 46, 52, 53, 54, 101, 106, 111, 112], "conceptu": [13, 30], "creat": [13, 19, 21, 23, 26, 28, 31, 32, 34, 39, 41, 42, 57, 89, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114], "after": [13, 22, 30, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "consult": 13, "relev": 13, "guid": [13, 14, 31, 114], "refer": [13, 21, 30, 35, 39, 40, 41, 42, 51, 55, 70, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "framework": [13, 38], "driven": [13, 17, 38], "eas": 13, "come": [13, 15, 38], "primari": [13, 28, 30], "cook": 13, "recip": [13, 35], "forth": 13, "product": [13, 23, 42], "interact": [13, 17, 19, 30, 41, 42, 54, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "iter": [13, 38, 60], "leverag": [13, 17, 38, 42], "human": 13, "readabl": 13, "briefli": 13, "whitespac": [13, 22], "denot": 13, "structur": [13, 113], "associ": [13, 55, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "hyphen": 13, "recommend": [13, 15, 37], "quick": 13, "four": 13, "To": [13, 15, 17, 22, 23, 30, 31, 34, 114], "e": [13, 17, 19, 23, 39, 40, 41, 42, 44, 46, 52, 55, 56, 70, 101, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "g": [13, 17, 19, 23, 39, 40, 41, 42, 44, 46, 52, 55, 56, 70, 101, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "indent": 13, "top": [13, 41, 42, 114], "hierarchi": [13, 30, 37], "plenti": 13, "control": [13, 30, 55, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "my": [13, 22, 106], "logo": [13, 39, 114], "asset": 13, "my_logo": 13, "png": [13, 113], "rememb": 13, "defin": [13, 17, 21, 22, 30, 35, 38, 41, 72, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "follow": [13, 15, 22, 23, 34, 44, 71, 113, 114], "source_nam": [13, 22, 60], "excel": [13, 30, 54, 56, 64, 104, 112], "filepath": [13, 56, 59], "table_penguin": 13, "other": [13, 17, 22, 31, 38, 54, 55, 64, 102, 114], "exclud": 13, "drill": 13, "down": [13, 114], "certain": [13, 30, 37], "actual": [13, 114], "content": 13, "render": [13, 17, 30, 31, 39, 41, 52, 54, 103, 104, 105, 107, 108, 109, 110, 111, 112], "essenti": [13, 28, 35], "expand": [13, 44], "dropdown": 13, "complex": 13, "monitor": [13, 41, 61, 62, 63], "endpoint": [13, 54, 61, 62, 64], "download": [13, 23, 35, 40, 41, 54, 103, 105, 106, 107, 108, 109, 110, 111, 112, 114], "sidebar": [13, 17, 26, 41], "keyword": [13, 56, 59, 65, 103, 104], "argument": [13, 22, 31, 39, 56, 59, 65, 103, 104], "pass": [13, 17, 22, 31, 39, 104], "panda": [13, 21, 38, 42, 54, 56, 59, 64, 65, 68, 69, 70, 73, 74, 75, 76, 77, 78, 79, 87, 88, 89, 90, 91, 92], "dask": [13, 38, 54, 56, 57, 58, 59, 64, 68, 92], "to_": 13, "independ": [13, 17], "metric": 13, "insid": 13, "card": [13, 41], "row": [13, 17, 23, 39, 41, 69, 84, 89, 90, 109, 112], "grid": [13, 41], "sort": [13, 21, 54, 92, 107], "revers": 13, "order": [13, 17, 21, 37], "frequent": [13, 41], "poll": 13, "millisecond": 13, "At": [13, 28, 30], "minimum": 13, "must": [13, 19, 21, 23, 37, 46, 56, 59, 62, 70, 71, 88, 112], "produc": [13, 91], "450": 13, "introduc": 13, "overrid": [13, 16, 102], "object": [13, 17, 19, 30, 35, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "seen": 13, "widgetfilt": [13, 46, 48, 49, 53, 54], "multi": [13, 46, 48, 49, 52], "perhap": 13, "rather": [13, 42], "multipl": [13, 21, 22, 24, 30, 42, 50, 60, 79, 88, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "check": [13, 15, 22, 87], "link": [13, 31, 35], "entir": [13, 23, 31, 106, 114], "been": [13, 21, 34, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 114], "throughout": [13, 16, 22, 114], "variable_nam": 13, "syntax": [13, 55], "textinput": 13, "enter": [13, 21], "stock": 13, "would": 13, "dynam": [13, 17, 22, 38, 54, 101, 102, 114], "ticker": [13, 22], "aapl": [13, 22], "stock_data": [13, 22], "scenario": 13, "elsewher": 13, "inform": [13, 22, 70, 114], "websitesourc": [13, 54, 64], "report": 13, "websit": [13, 22, 54, 61, 63, 64], "request": [13, 22, 23, 41, 42, 47, 53, 54, 95, 97, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "hardcod": 13, "shell": 13, "command": [13, 15, 37], "cli": [13, 22], "header": [13, 22, 41, 54, 102], "cooki": [13, 22, 54, 102], "oauth": [13, 22, 38, 54, 100, 102], "token": [13, 22], "env": [13, 22, 54, 102], "get_login": 13, "thisus": 13, "execut": 13, "trim": [13, 22], "trail": [13, 22, 103], "var": [13, 22, 113], "lumen_us": [13, 22], "commandlin": 13, "auth": [13, 16, 44], "dictionari": [13, 23, 30, 41, 42, 55, 56, 58, 59, 60, 61, 62, 63, 64, 100], "valid": [13, 30, 62], "against": [13, 71], "user_info": [13, 100], "discov": [13, 17, 31, 38], "document": [13, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "github": 13, "login": 13, "visit": [13, 30], "philippjfr": 13, "current": [13, 17, 39, 42, 53, 54, 72, 98, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "mechan": 13, "okta": 13, "possibl": [13, 17, 39, 48, 49, 65, 67, 72, 74, 75, 88, 102, 103, 104, 105, 106, 107, 110, 111, 112, 114], "group": [13, 41, 44, 50, 54, 65, 83, 92, 107, 110, 111, 112, 114], "belong": 13, "mention": 13, "deeper": 13, "solidifi": 13, "go": 14, "describ": [14, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "linux": 15, "window": [15, 32], "mac": 15, "conda": [15, 37], "anaconda": [15, 22], "miniconda": 15, "pip": 15, "powershel": 15, "run": [15, 32, 114], "finish": 15, "latest": [15, 54, 105, 108, 112], "caus": 15, "forg": 15, "flexibl": [15, 22, 38], "error": [15, 19, 39], "messag": [15, 37], "determin": [15, 41, 79, 112], "miss": [15, 89, 91], "unknown": [15, 37], "did": [15, 37], "yaml": [16, 17, 19, 21, 22, 23, 24, 26, 30, 32, 34, 35, 37, 45, 54, 58, 114], "divid": [16, 70], "rule": [16, 103], "thumb": 16, "find": 16, "present": [16, 28], "global": 16, "authent": [16, 35, 38], "pn": [17, 19, 21, 30, 31, 34, 41, 42, 100, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "tabul": [17, 30, 31, 34, 54, 109, 112], "abstract": 17, "offer": [17, 62, 114], "extrem": [17, 30], "oper": [17, 42, 54, 71, 74, 84, 92], "distinguish": 17, "sql": [17, 38, 42, 54, 57, 64, 80, 81, 82, 83, 84, 85, 92], "mean": [17, 19, 28, 30, 37, 38], "sqltransform": [17, 23, 42, 57], "optim": 17, "datafram": [17, 21, 38, 42, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 86, 87, 88, 89, 90, 91, 92, 93, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "stage": 17, "sequenc": 17, "data_url": [17, 23, 24, 28, 30, 34], "from_spec": [17, 23, 24, 30, 31, 34], "inspect": [17, 30], "flipper_length_mm": [17, 30], "adeli": [17, 30], "femal": [17, 30], "2007": [17, 30], "37": 17, "922727": 17, "18": [17, 30], "127273": 17, "185": 17, "227273": 17, "3389": 17, "772727": 17, "2008": 17, "36": [17, 30], "516000": 17, "17": [17, 30], "460000": 17, "188": 17, "440000": 17, "3386": 17, "000000": 17, "2009": 17, "407692": 17, "350000": 17, "189": 17, "346154": 17, "3334": 17, "615385": 17, "male": [17, 30], "39": [17, 30], "950000": 17, "19": [17, 30], "509091": 17, "181818": 17, "4038": 17, "636364": 17, "40": [17, 30], "604000": 17, "924000": 17, "193": [17, 30], "640000": 17, "4098": 17, "557692": 17, "846154": 17, "194": 17, "807692": 17, "3995": 17, "192308": 17, "chinstrap": 17, "46": 17, "569231": 17, "838462": 17, "692308": 17, "3569": 17, "230769": 17, "300000": 17, "192": 17, "666667": 17, "3472": 17, "222222": 17, "47": 17, "008333": 17, "533333": 17, "333333": 17, "3522": 17, "916667": 17, "876923": 17, "130769": 17, "196": 17, "153846": 17, "3819": 17, "51": 17, "400000": 17, "600000": 17, "202": 17, "777778": 17, "4127": 17, "100000": 17, "125000": 17, "201": 17, "833333": 17, "3927": 17, "083333": 17, "gentoo": 17, "45": 17, "062500": 17, "13": 17, "993750": 17, "211": 17, "4618": 17, "750000": 17, "295455": 17, "14": 17, "131818": 17, "213": 17, "4627": 17, "272727": 17, "260000": 17, "550000": 17, "700000": 17, "4786": 17, "250000": 17, "49": 17, "364706": 17, "218": 17, "882353": 17, "5552": 17, "941176": 17, "48": 17, "539130": 17, "704348": 17, "222": 17, "086957": 17, "5410": 17, "869565": 17, "880952": 17, "019048": 17, "223": 17, "095238": 17, "5510": 17, "714286": 17, "control_panel": [17, 30], "instanti": [17, 32, 35, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102], "parameter": [17, 41], "bind": 17, "pane": [17, 106, 107], "add_filt": [17, 28, 30, 42], "auto": 17, "agg_pipelin": [17, 28], "38": 17, "824490": 17, "767347": 17, "186": [17, 30], "591837": 17, "3696": 17, "428571": 17, "560000": 17, "192000": 17, "191": 17, "040000": 17, "3742": 17, "982692": 17, "098077": 17, "076923": 17, "3664": 17, "903846": 17, "723077": 17, "484615": 17, "423077": 17, "3694": 17, "450000": 17, "197": 17, "722222": 17, "3800": [17, 30], "054167": 17, "329167": 17, "198": 17, "3725": 17, "014706": 17, "688235": 17, "215": 17, "117647": 17, "5070": 17, "588235": 17, "936957": 17, "923913": 17, "217": 17, "565217": 17, "5019": 17, "500000": 17, "276744": 17, "418605": 17, "5140": 17, "697674": 17, "still": [17, 32], "occur": [17, 19, 39], "One": [17, 24, 114], "major": 17, "architectur": 17, "outsid": 17, "compos": 17, "hvplotuiview": [17, 54, 112], "servabl": [17, 31, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "area": [17, 34, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "wip": 18, "often": [19, 37], "perform": [19, 35, 38, 54, 60, 64, 83, 84, 92], "action": [19, 35, 102], "session": [19, 39, 61], "end": [19, 37, 73], "easiest": [19, 24], "hook": 19, "on_session_cr": [19, 39], "fire": [19, 39], "on_session_destroi": [19, 39], "destroi": [19, 39], "on_load": [19, 39], "frontend": [19, 39], "on_error": [19, 39], "on_upd": [19, 39], "ship": [19, 21, 38], "py": [19, 21, 31, 32], "def": [19, 21], "print": [19, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "fact": 19, "programmat": [19, 23, 35], "were": 19, "cannot": 19, "lm": [19, 30, 31], "to_spec": [19, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "move": 19, "html": [20, 21, 25, 27, 29, 33, 36, 54, 107, 108, 109, 112], "string": [21, 37, 39, 40, 41, 42, 43, 45, 53, 54, 64, 80, 81, 82, 83, 84, 85, 92, 102, 103, 104, 105, 106, 107, 109, 110, 111, 112], "texteditor": 21, "second": [21, 22, 41], "folder": [21, 64], "filenam": [21, 22, 56, 59, 104], "my_librari": 21, "my_modul": 21, "stabl": 21, "directori": [21, 23, 113, 114], "stablesort": 21, "algorithm": 21, "sort_valu": [21, 54, 88, 92], "df": [21, 65, 67, 69, 71, 73, 76, 77, 78, 79, 86, 87, 88, 89, 90, 91, 111], "ascend": [21, 88], "listselector": 21, "classselector": 21, "class_": 21, "bool": [21, 39, 41, 42, 46, 48, 49, 52, 53, 56, 57, 58, 59, 64, 65, 69, 74, 77, 78, 79, 86, 87, 88, 89, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "v": [21, 88], "descend": [21, 88], "length": [21, 46, 72, 88], "transform_typ": 21, "_field_param": 21, "self": 21, "galleri": 21, "view_typ": 21, "_extens": 21, "get_panel": [21, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "_get_param": 21, "dict": [21, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "placehold": 21, "And": 21, "stablesor": 21, "referenc": [21, 22, 54, 70, 94, 96, 102], "dot": [21, 39], "notat": [21, 22], "root": [21, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "advanc": 22, "three": [22, 26], "block": [22, 37], "done": [22, 23], "uniqu": 22, "volum": 22, "magnitud": 22, "greater": 22, "imposs": 22, "seri": [22, 78, 89], "remov": [22, 79, 114], "visibl": [22, 46, 48, 49, 52], "multiselect": 22, "low": 22, "close": 22, "adj": 22, "7": [22, 30], "sample_data": 22, "master": [22, 26], "index_col": 22, "ticker_pip": 22, "table_nam": [22, 60], "field_nam": 22, "aliv": 22, "dead": 22, "statu": [22, 54, 63, 64], "googl": 22, "last": 22, "six": 22, "jinja2": 22, "doubl": 22, "curli": 22, "bracket": 22, "hello": 22, "dear": 22, "friend": 22, "correct": 22, "ran": 22, "cli_exampl": 22, "yml": [22, 37, 113], "faulti": 22, "It": [22, 42, 60], "worth": 22, "echo": 22, "intern": [22, 38, 72], "dollar": 22, "sign": 22, "wherea": 22, "resolv": [22, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "speed": [23, 35], "advantag": 23, "schema": [23, 42, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "store": [23, 38, 64], "370": 23, "mb": 23, "12": 23, "million": 23, "coupl": 23, "minut": 23, "large_sourc": 23, "large_t": 23, "amazonaw": 23, "engin": 23, "fastparquet": 23, "toggl": [23, 114], "per": [23, 59, 109], "pre": [23, 114], "enabl": [23, 26, 35, 48, 49, 52, 56, 61, 64, 109, 114], "popul": [23, 42, 75, 114], "OR": [23, 58, 114], "suppli": [23, 32, 53, 54, 55, 56, 59, 60, 72], "definit": [23, 42, 114], "form": [23, 34, 64, 114], "cross": [23, 42, 51], "xlsx": [24, 104], "xl": 24, "local_sourc": 24, "local_t": 24, "data_path": 24, "remote_sourc": 24, "remote_t": 24, "sever": 26, "rfordatasci": 26, "tidytuesdai": 26, "2020": 26, "07": 26, "28": [26, 37], "button": [26, 30, 39, 41, 42, 54, 104, 112, 114], "emphas": 26, "highlight": 26, "red": 26, "continu": 28, "jump": 28, "ensur": [28, 38, 46, 52, 101], "properli": 28, "accomplish": 28, "branch_sort": 28, "simpli": [28, 30, 37, 114], "tool": [28, 37, 38, 58], "chain": [28, 42], "walk": 28, "assign": [28, 54, 60, 70, 92], "although": 30, "compact": 30, "seper": 30, "nest": [30, 41, 103, 106], "head": 30, "torgersen": 30, "181": 30, "3750": 30, "195": 30, "3250": 30, "nan": [30, 54, 69, 91, 92], "3450": 30, "add_transform": [30, 42], "unwant": 30, "auto_upd": [30, 31, 39, 41, 42], "trigger": [30, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "click": 30, "long": 30, "cell": 30, "repl": [30, 31], "previou": 31, "pick": [31, 114], "left": 31, "constructor": 31, "stick": 31, "arrang": [31, 34, 114], "put": 31, "via": [31, 64, 111], "standalon": [31, 42], "server": [32, 41, 42, 64, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "path": [32, 37, 44, 52, 64], "progress": [32, 105], "refresh": [32, 41, 112], "least": 34, "measur": 34, "omit": 34, "shown": 34, "solv": 35, "task": 35, "assum": 35, "basic": 35, "callback": [35, 39, 41], "fail": 37, "issu": 37, "expect": [37, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "found": 37, "unicod": 37, "appear": 37, "11": 37, "constrain": 37, "entri": 37, "caught": 37, "hvplotqedq": 37, "hvplot_ui": [37, 54, 112], "windturbin": 38, "project": [38, 54, 58, 92, 93, 103], "highli": [38, 114], "express": [38, 46, 54, 70, 71, 82, 92, 106, 111], "ve": 38, "commer": 38, "pain": 38, "coordin": [38, 93], "push": 38, "aim": 38, "quickli": 38, "gain": 38, "insight": 38, "pydata": 38, "strong": 38, "familiar": [38, 114], "cluster": 38, "thank": 38, "popular": 38, "datagrid": [38, 107], "strength": 38, "flexibli": 38, "scalabl": 38, "mind": 38, "larger": 38, "secur": [38, 94, 95, 96, 97, 98, 99, 100, 101, 102], "breez": 38, "reusabl": 38, "reus": 38, "member": 38, "background_load": 39, "edit": [39, 114], "loading_color": 39, "loading_spinn": 39, "ncol": 39, "show_traceback": 39, "none": [39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "automaticallytrigg": [39, 41, 42], "triggeredmanu": [39, 41, 42], "withinth": 39, "flexbox": 39, "accordion": 39, "gridbox": 39, "0072b5": 39, "arc": 39, "petal": 39, "str": [39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "identifi": [39, 40, 41, 42, 43, 45, 53, 64, 74, 92, 102, 112], "int": [39, 41, 42, 52, 59, 69, 72, 73, 77, 78, 79, 84, 86, 89, 90, 91, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "bound": [39, 41, 46, 52, 59, 72, 73, 84, 86, 109, 112], "except": [39, 60], "updatedpipelin": 39, "traceback": 39, "happen": 39, "sync": [39, 53], "materialtempl": 39, "bootstraptempl": 39, "reacttempl": 39, "goldentempl": 39, "vanillatempl": 39, "fastlisttempl": 39, "slidestempl": 39, "fastgridtempl": 39, "defaultthem": 39, "darkthem": 39, "style": [39, 107], "construct_templ": 39, "export": [39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "reconstruct": [39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "previous": [39, 40, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "serial": [39, 40, 41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "rerend": [41, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "show_titl": 41, "tsformat": 41, "addition": [41, 106], "tablescan": [41, 112], "cardson": 41, "indexescorrespond": 41, "createa": 41, "rowcontain": 41, "adaptor": 41, "re": [41, 112], "m": 41, "d": 41, "h": 41, "get_card": 41, "get_filter_panel": 41, "skip": 41, "apply_button": 41, "target": [41, 42, 77, 78, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "viewabl": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "dom": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "pyodid": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "boolean": [41, 42, 69, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "io": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "observ": [41, 42, 95, 96, 97, 99, 100, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "deprec": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "too": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "node": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "port": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "address": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "websocket_origin": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "thread": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "verbos": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "bokeh": [41, 42, 54, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "listen": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "host": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "websocket": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "embed": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "extern": [41, 42, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "site": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "localhost": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "stoppablethread": [41, 42, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "period": 41, "clear_cach": [41, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "encapsul": [42, 54], "ingest": 42, "input": 42, "fed": 42, "sql_transform": 42, "manual": 42, "filt": 42, "union": [42, 55, 56, 59, 60, 61, 62, 63, 64], "clone": 42, "overridden": 42, "precach": 42, "travers": 42, "authplugin": [43, 45, 54], "given": [43, 45, 54, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93], "specfic": [43, 45, 54], "spec": [43, 44, 45, 106], "yaml_fil": 44, "concis": [44, 102, 111], "admin": 44, "email": 44, "philipp": 44, "pathlib": [44, 64], "yamlauthmapperplugin": [45, 54], "empty_select": [46, 52], "label": [46, 47, 48, 49, 50, 51, 52, 53, 74, 77, 94, 95, 96, 97, 98, 99, 100, 101, 102, 105], "disabl": [46, 48, 49, 52], "throttl": [46, 48, 49, 52, 101], "tupl": [46, 56, 71, 82, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "lower": 46, "upper": 46, "value_throttl": [46, 52, 101], "intermedi": [46, 52, 101], "whendrag": [46, 52, 101], "slider": [46, 48, 49, 52, 101], "mode": [48, 49, 55], "calendar": [48, 53, 54], "datepick": 48, "daterangeslid": 48, "respect": [48, 49, 60], "picker": [48, 49], "datetimepick": 49, "datetimerangeslid": 49, "explod": 50, "reflect": [51, 53, 54, 95, 97, 98, 99, 100, 101, 102], "max_opt": 52, "infer": 52, "numer": [52, 54, 71, 90, 92], "regular": 52, "arang": 52, "fullmodul": 52, "overrideth": 52, "informationabout": 53, "constantfilt": [53, 54], "facetfilt": [53, 54], "paramfilt": [53, 54], "binfilt": [53, 54], "bin": [53, 54, 103], "datefilt": [53, 54], "datetimefilt": [53, 54], "datetim": [53, 54, 72], "envvari": [54, 102], "urlqueri": [54, 102], "userinfo": [54, 102], "info": [54, 61, 100, 102], "restsourc": [54, 64], "conform": [54, 62, 64], "read_": [54, 56, 64], "respond": [54, 63, 64], "panelsessionsourc": [54, 64], "session_info": [54, 64], "joinedsourc": [54, 64], "derivedsourc": [54, 64], "deriv": [54, 64, 80, 81, 82, 83, 84, 85], "jsonsourc": [54, 64], "intakesourc": [54, 57, 64], "intakesqlsourc": [54, 64], "intake_sql": [54, 64], "historytransform": [54, 92], "histori": [54, 92], "accumul": [54, 72, 92], "groupbi": [54, 65, 92, 110, 111], "astyp": [54, 92], "as_typ": [54, 92], "unstack": [54, 92], "iloc": [54, 92], "integ": [54, 73, 79, 92], "slice": [54, 73, 92], "sampl": [54, 92], "random": [54, 86, 92], "item": [54, 59, 86, 92, 107, 114], "turn": [54, 68, 92], "pivot": [54, 92, 107], "melt": [54, 92], "id_var": [54, 74, 92], "value_var": [54, 74, 92], "setindex": [54, 92], "set_index": [54, 92], "promot": [54, 87, 92], "resetindex": [54, 92], "reset_index": [54, 65, 92], "reset": [54, 79, 92], "drop": [54, 79, 87, 89, 92], "renameaxi": [54, 92], "rename_axi": [54, 92], "mercat": [54, 92, 93], "sqlgroupbi": [54, 92], "sql_group_bi": [54, 92], "sqllimit": [54, 92], "sql_limit": [54, 92], "sqldistinct": [54, 92], "sql_distinct": [54, 92], "sqlminmax": [54, 92], "sql_minmax": [54, 92], "sqlcolumn": [54, 92], "sql_column": [54, 92], "sqlfilter": [54, 92], "sql_filter": [54, 92], "translat": [54, 82, 92], "statement": [54, 80, 81, 82, 83, 84, 85, 92], "represent": [54, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "wrap": [54, 106, 112], "stringview": [54, 112], "indicatorview": [54, 112], "downloadview": [54, 112], "perspectiveview": [54, 112], "perspect": [54, 112], "altairview": [54, 112], "cache_with_dask": [55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "exact": 55, "derived_t": 55, "original_sourc": 55, "original_t": 55, "mirror": 55, "accord": 55, "get_schema": [55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "get_tabl": [55, 56, 57, 58, 59, 60, 61, 62, 63, 64], "use_dask": [56, 59], "thenam": [56, 59], "areth": [56, 59], "home": [56, 59], "local_fil": [56, 59], "test": [56, 59], "extensionmai": 56, "filter_in_sql": 57, "load_schema": [57, 58], "inlin": [57, 58, 102], "temp": 57, "fly": 57, "conveni": 58, "disk": [58, 64], "chunk": 59, "variablei": 59, "merg": 60, "surfac": 60, "foo": 60, "new_tabl": 60, "keysand": 60, "mergeon": 60, "index_nam": 60, "timeout": 61, "statist": 61, "record": 62, "lastli": 64, "thedashboard": 64, "oniniti": 64, "with_index": 65, "dtype": 66, "numeric_onli": 69, "to_fram": [69, 90], "float": 69, "becom": 70, "thousand": 70, "kilo_valu": 70, "1000": [70, 84], "condit": [71, 82], "scalar": [71, 78, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "equal": 71, "categori": 71, "columnnam": [71, 82], "date_column": 72, "buffer": 72, "ignore_index": 74, "value_nam": 74, "var_nam": 74, "ignor": 74, "originalindex": 74, "repeat": [74, 79], "asnecessari": 74, "unpivot": 74, "thatar": 74, "frame": [74, 75, 89], "usedand": 75, "hierarch": 75, "copi": [77, 78], "mapper": [77, 78], "equival": 77, "multiindex": 77, "tospecifi": 77, "objecti": 78, "withmapp": 78, "attribut": 78, "col_fil": 79, "col_level": 79, "otherlevel": 79, "thelabel": 79, "thefirst": 79, "try": [79, 114], "resetsth": 79, "levelsbi": 79, "sql_in": [80, 81, 82, 83, 84, 85], "distinct": [81, 107], "min": 85, "frac": 86, "fraction": 86, "append": 87, "verify_integr": 87, "delet": 87, "listcontain": 87, "duplic": 87, "defer": 87, "checkuntil": 87, "necessari": 87, "performanceof": 87, "sortord": 88, "ofth": 88, "dropna": 89, "onto": 89, "ofindex": 89, "originaldatafram": 89, "fill_valu": 91, "convert": 93, "wgs84": 93, "meter": 93, "greenwich": 93, "equat": 93, "as_materi": [94, 95, 96, 97, 98, 99, 100, 101, 102], "builder": [94, 95, 96, 97, 98, 99, 100, 101, 102, 113], "convers": [94, 95, 96, 97, 98, 99, 100, 101, 102], "whose": 98, "reflectedon": 98, "orchestr": 102, "variableshow": 102, "mark": 103, "loading_ind": [103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "boxplot": 103, "circl": 103, "errorband": 103, "errorbar": 103, "geoshap": 103, "imag": 103, "squar": 103, "tick": 103, "oftransform": 103, "as_": 103, "get_data": [103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "get_valu": [103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "repres": [103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "therefor": [103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "invalidate_cach": [103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "to_csv": 104, "file_obj": 104, "filedownload": 104, "trend": 105, "tqdm": 105, "booleanstatu": 105, "loadingspinn": 105, "gaug": 105, "dial": 105, "lineargaug": 105, "arbitrarili": 106, "markdown": 106, "column_pivot": 107, "computed_column": 107, "plugin": 107, "row_pivot": 107, "detail": 107, "abc": 107, "hypergrid": 107, "d3_y_bar": 107, "d3_x_bar": 107, "d3_xy_lin": 107, "d3_y_lin": 107, "d3_y_area": 107, "d3_y_scatt": 107, "d3_xy_scatt": 107, "d3_treemap": 107, "d3_sunburst": 107, "d3_heatmap": 107, "d3_candlestick": 107, "d3_ohlc": 107, "desc": 107, "monokai": 107, "solar": 107, "vaporwav": 107, "font_siz": 108, "24pt": 108, "font": 108, "opt": 111, "holoview": [111, 112], "caputirng": 111, "appliedon": 111, "get_plot": 111, "subclass": 112, "thepipelin": 112, "featurerequir": 112, "quit": 113, "straightforward": 113, "launcher": 113, "assembl": 114, "greet": 114, "modifi": 114, "decid": 114, "scratch": 114, "unsur": 114, "explan": 114, "usual": 114, "credenti": 114, "right": 114, "modal": 114, "pop": 114, "collect": 114, "et": 114, "al": 114, "journei": 114}, "objects": {"lumen.auth": [[45, 0, 1, "", "Auth"], [44, 0, 1, "", "YamlAuthMapperPlugin"]], "lumen.auth.Auth": [[45, 1, 1, "", "to_spec"], [45, 1, 1, "", "transform"]], "lumen.auth.YamlAuthMapperPlugin": [[44, 1, 1, "", "to_spec"], [44, 1, 1, "", "transform"]], "lumen.dashboard": [[39, 0, 1, "", "Config"], [40, 0, 1, "", "Defaults"]], "lumen.dashboard.Config": [[39, 1, 1, "", "construct_template"], [39, 1, 1, "", "to_spec"]], "lumen.dashboard.Defaults": [[40, 1, 1, "", "apply"], [40, 1, 1, "", "to_spec"]], "lumen.filters.base": [[46, 0, 1, "", "BinFilter"], [47, 0, 1, "", "ConstantFilter"], [48, 0, 1, "", "DateFilter"], [49, 0, 1, "", "DatetimeFilter"], [50, 0, 1, "", "FacetFilter"], [53, 0, 1, "", "Filter"], [51, 0, 1, "", "ParamFilter"], [52, 0, 1, "", "WidgetFilter"]], "lumen.filters.base.BinFilter": [[46, 1, 1, "", "to_spec"]], "lumen.filters.base.ConstantFilter": [[47, 1, 1, "", "to_spec"]], "lumen.filters.base.DateFilter": [[48, 1, 1, "", "to_spec"]], "lumen.filters.base.DatetimeFilter": [[49, 1, 1, "", "to_spec"]], "lumen.filters.base.FacetFilter": [[50, 1, 1, "", "to_spec"]], "lumen.filters.base.Filter": [[53, 1, 1, "", "to_spec"]], "lumen.filters.base.ParamFilter": [[51, 1, 1, "", "to_spec"]], "lumen.filters.base.WidgetFilter": [[52, 1, 1, "", "to_spec"]], "lumen.layout": [[41, 0, 1, "", "Layout"]], "lumen.layout.Layout": [[41, 1, 1, "", "get_cards"], [41, 1, 1, "", "get_filter_panel"], [41, 1, 1, "", "servable"], [41, 1, 1, "", "show"], [41, 1, 1, "", "start"], [41, 1, 1, "", "to_spec"], [41, 1, 1, "", "update"]], "lumen.pipeline": [[42, 0, 1, "", "Pipeline"]], "lumen.pipeline.Pipeline": [[42, 1, 1, "", "add_filter"], [42, 1, 1, "", "add_transform"], [42, 1, 1, "", "chain"], [42, 1, 1, "", "clone"], [42, 1, 1, "", "precache"], [42, 1, 1, "", "servable"], [42, 1, 1, "", "show"], [42, 1, 1, "", "to_spec"], [42, 1, 1, "", "traverse"]], "lumen.sources.base": [[55, 0, 1, "", "DerivedSource"], [56, 0, 1, "", "FileSource"], [59, 0, 1, "", "JSONSource"], [60, 0, 1, "", "JoinedSource"], [61, 0, 1, "", "PanelSessionSource"], [62, 0, 1, "", "RESTSource"], [64, 0, 1, "", "Source"], [63, 0, 1, "", "WebsiteSource"]], "lumen.sources.base.DerivedSource": [[55, 1, 1, "", "clear_cache"], [55, 1, 1, "", "get"], [55, 1, 1, "", "get_schema"], [55, 1, 1, "", "get_tables"], [55, 1, 1, "", "to_spec"]], "lumen.sources.base.FileSource": [[56, 1, 1, "", "clear_cache"], [56, 1, 1, "", "get"], [56, 1, 1, "", "get_schema"], [56, 1, 1, "", "get_tables"], [56, 1, 1, "", "to_spec"]], "lumen.sources.base.JSONSource": [[59, 1, 1, "", "clear_cache"], [59, 1, 1, "", "get"], [59, 1, 1, "", "get_schema"], [59, 1, 1, "", "get_tables"], [59, 1, 1, "", "to_spec"]], "lumen.sources.base.JoinedSource": [[60, 1, 1, "", "clear_cache"], [60, 1, 1, "", "get"], [60, 1, 1, "", "get_schema"], [60, 1, 1, "", "get_tables"], [60, 1, 1, "", "to_spec"]], "lumen.sources.base.PanelSessionSource": [[61, 1, 1, "", "clear_cache"], [61, 1, 1, "", "get"], [61, 1, 1, "", "get_schema"], [61, 1, 1, "", "get_tables"], [61, 1, 1, "", "to_spec"]], "lumen.sources.base.RESTSource": [[62, 1, 1, "", "clear_cache"], [62, 1, 1, "", "get"], [62, 1, 1, "", "get_schema"], [62, 1, 1, "", "get_tables"], [62, 1, 1, "", "to_spec"]], "lumen.sources.base.Source": [[64, 1, 1, "", "clear_cache"], [64, 1, 1, "", "get"], [64, 1, 1, "", "get_schema"], [64, 1, 1, "", "get_tables"], [64, 1, 1, "", "to_spec"]], "lumen.sources.base.WebsiteSource": [[63, 1, 1, "", "clear_cache"], [63, 1, 1, "", "get"], [63, 1, 1, "", "get_schema"], [63, 1, 1, "", "get_tables"], [63, 1, 1, "", "to_spec"]], "lumen.sources.intake": [[58, 0, 1, "", "IntakeSource"]], "lumen.sources.intake.IntakeSource": [[58, 1, 1, "", "clear_cache"], [58, 1, 1, "", "get"], [58, 1, 1, "", "get_schema"], [58, 1, 1, "", "get_tables"], [58, 1, 1, "", "to_spec"]], "lumen.sources.intake_sql": [[57, 0, 1, "", "IntakeSQLSource"]], "lumen.sources.intake_sql.IntakeSQLSource": [[57, 1, 1, "", "clear_cache"], [57, 1, 1, "", "get"], [57, 1, 1, "", "get_schema"], [57, 1, 1, "", "get_tables"], [57, 1, 1, "", "to_spec"]], "lumen.transforms.base": [[65, 0, 1, "", "Aggregate"], [66, 0, 1, "", "Astype"], [67, 0, 1, "", "Columns"], [68, 0, 1, "", "Compute"], [69, 0, 1, "", "Count"], [70, 0, 1, "", "Eval"], [71, 0, 1, "", "Filter"], [72, 0, 1, "", "HistoryTransform"], [73, 0, 1, "", "Iloc"], [74, 0, 1, "", "Melt"], [75, 0, 1, "", "Pivot"], [76, 0, 1, "", "Query"], [77, 0, 1, "", "Rename"], [78, 0, 1, "", "RenameAxis"], [79, 0, 1, "", "ResetIndex"], [86, 0, 1, "", "Sample"], [87, 0, 1, "", "SetIndex"], [88, 0, 1, "", "Sort"], [89, 0, 1, "", "Stack"], [90, 0, 1, "", "Sum"], [92, 0, 1, "", "Transform"], [91, 0, 1, "", "Unstack"], [93, 0, 1, "", "project_lnglat"]], "lumen.transforms.base.Aggregate": [[65, 1, 1, "", "apply"], [65, 1, 1, "", "to_spec"]], "lumen.transforms.base.Astype": [[66, 1, 1, "", "apply"], [66, 1, 1, "", "to_spec"]], "lumen.transforms.base.Columns": [[67, 1, 1, "", "apply"], [67, 1, 1, "", "to_spec"]], "lumen.transforms.base.Compute": [[68, 1, 1, "", "apply"], [68, 1, 1, "", "to_spec"]], "lumen.transforms.base.Count": [[69, 1, 1, "", "apply"], [69, 1, 1, "", "to_spec"]], "lumen.transforms.base.Eval": [[70, 1, 1, "", "apply"], [70, 1, 1, "", "to_spec"]], "lumen.transforms.base.Filter": [[71, 1, 1, "", "apply"], [71, 1, 1, "", "to_spec"]], "lumen.transforms.base.HistoryTransform": [[72, 1, 1, "", "apply"], [72, 1, 1, "", "to_spec"]], "lumen.transforms.base.Iloc": [[73, 1, 1, "", "apply"], [73, 1, 1, "", "to_spec"]], "lumen.transforms.base.Melt": [[74, 1, 1, "", "apply"], [74, 1, 1, "", "to_spec"]], "lumen.transforms.base.Pivot": [[75, 1, 1, "", "apply"], [75, 1, 1, "", "to_spec"]], "lumen.transforms.base.Query": [[76, 1, 1, "", "apply"], [76, 1, 1, "", "to_spec"]], "lumen.transforms.base.Rename": [[77, 1, 1, "", "apply"], [77, 1, 1, "", "to_spec"]], "lumen.transforms.base.RenameAxis": [[78, 1, 1, "", "apply"], [78, 1, 1, "", "to_spec"]], "lumen.transforms.base.ResetIndex": [[79, 1, 1, "", "apply"], [79, 1, 1, "", "to_spec"]], "lumen.transforms.base.Sample": [[86, 1, 1, "", "apply"], [86, 1, 1, "", "to_spec"]], "lumen.transforms.base.SetIndex": [[87, 1, 1, "", "apply"], [87, 1, 1, "", "to_spec"]], "lumen.transforms.base.Sort": [[88, 1, 1, "", "apply"], [88, 1, 1, "", "to_spec"]], "lumen.transforms.base.Stack": [[89, 1, 1, "", "apply"], [89, 1, 1, "", "to_spec"]], "lumen.transforms.base.Sum": [[90, 1, 1, "", "apply"], [90, 1, 1, "", "to_spec"]], "lumen.transforms.base.Transform": [[92, 1, 1, "", "apply"], [92, 1, 1, "", "to_spec"]], "lumen.transforms.base.Unstack": [[91, 1, 1, "", "apply"], [91, 1, 1, "", "to_spec"]], "lumen.transforms.base.project_lnglat": [[93, 1, 1, "", "apply"], [93, 1, 1, "", "to_spec"]], "lumen.transforms.sql": [[80, 0, 1, "", "SQLColumns"], [81, 0, 1, "", "SQLDistinct"], [82, 0, 1, "", "SQLFilter"], [83, 0, 1, "", "SQLGroupBy"], [84, 0, 1, "", "SQLLimit"], [85, 0, 1, "", "SQLMinMax"]], "lumen.transforms.sql.SQLColumns": [[80, 1, 1, "", "apply"], [80, 1, 1, "", "to_spec"]], "lumen.transforms.sql.SQLDistinct": [[81, 1, 1, "", "apply"], [81, 1, 1, "", "to_spec"]], "lumen.transforms.sql.SQLFilter": [[82, 1, 1, "", "apply"], [82, 1, 1, "", "to_spec"]], "lumen.transforms.sql.SQLGroupBy": [[83, 1, 1, "", "apply"], [83, 1, 1, "", "to_spec"]], "lumen.transforms.sql.SQLLimit": [[84, 1, 1, "", "apply"], [84, 1, 1, "", "to_spec"]], "lumen.transforms.sql.SQLMinMax": [[85, 1, 1, "", "apply"], [85, 1, 1, "", "to_spec"]], "lumen.variables.base": [[94, 0, 1, "", "Constant"], [95, 0, 1, "", "Cookie"], [96, 0, 1, "", "EnvVariable"], [97, 0, 1, "", "Header"], [98, 0, 1, "", "Parameter"], [99, 0, 1, "", "URLQuery"], [100, 0, 1, "", "UserInfo"], [102, 0, 1, "", "Variable"], [101, 0, 1, "", "Widget"]], "lumen.variables.base.Constant": [[94, 1, 1, "", "as_materialized"], [94, 1, 1, "", "to_spec"]], "lumen.variables.base.Cookie": [[95, 1, 1, "", "as_materialized"], [95, 1, 1, "", "to_spec"]], "lumen.variables.base.EnvVariable": [[96, 1, 1, "", "as_materialized"], [96, 1, 1, "", "to_spec"]], "lumen.variables.base.Header": [[97, 1, 1, "", "as_materialized"], [97, 1, 1, "", "to_spec"]], "lumen.variables.base.Parameter": [[98, 1, 1, "", "as_materialized"], [98, 1, 1, "", "to_spec"]], "lumen.variables.base.URLQuery": [[99, 1, 1, "", "as_materialized"], [99, 1, 1, "", "to_spec"]], "lumen.variables.base.UserInfo": [[100, 1, 1, "", "as_materialized"], [100, 1, 1, "", "to_spec"]], "lumen.variables.base.Variable": [[102, 1, 1, "", "as_materialized"], [102, 1, 1, "", "to_spec"]], "lumen.variables.base.Widget": [[101, 1, 1, "", "as_materialized"], [101, 1, 1, "", "to_spec"]], "lumen.views.base": [[103, 0, 1, "", "AltairView"], [104, 0, 1, "", "DownloadView"], [105, 0, 1, "", "IndicatorView"], [106, 0, 1, "", "Panel"], [107, 0, 1, "", "PerspectiveView"], [108, 0, 1, "", "StringView"], [109, 0, 1, "", "Table"], [112, 0, 1, "", "View"], [110, 0, 1, "", "hvPlotUIView"], [111, 0, 1, "", "hvPlotView"]], "lumen.views.base.AltairView": [[103, 1, 1, "", "get_data"], [103, 1, 1, "", "get_panel"], [103, 1, 1, "", "get_value"], [103, 1, 1, "", "servable"], [103, 1, 1, "", "show"], [103, 1, 1, "", "to_spec"], [103, 1, 1, "", "update"]], "lumen.views.base.DownloadView": [[104, 1, 1, "", "get_data"], [104, 1, 1, "", "get_panel"], [104, 1, 1, "", "get_value"], [104, 1, 1, "", "servable"], [104, 1, 1, "", "show"], [104, 1, 1, "", "to_spec"], [104, 1, 1, "", "update"]], "lumen.views.base.IndicatorView": [[105, 1, 1, "", "get_data"], [105, 1, 1, "", "get_panel"], [105, 1, 1, "", "get_value"], [105, 1, 1, "", "servable"], [105, 1, 1, "", "show"], [105, 1, 1, "", "to_spec"], [105, 1, 1, "", "update"]], "lumen.views.base.Panel": [[106, 1, 1, "", "get_data"], [106, 1, 1, "", "get_panel"], [106, 1, 1, "", "get_value"], [106, 1, 1, "", "servable"], [106, 1, 1, "", "show"], [106, 1, 1, "", "to_spec"], [106, 1, 1, "", "update"]], "lumen.views.base.PerspectiveView": [[107, 1, 1, "", "get_data"], [107, 1, 1, "", "get_panel"], [107, 1, 1, "", "get_value"], [107, 1, 1, "", "servable"], [107, 1, 1, "", "show"], [107, 1, 1, "", "to_spec"], [107, 1, 1, "", "update"]], "lumen.views.base.StringView": [[108, 1, 1, "", "get_data"], [108, 1, 1, "", "get_panel"], [108, 1, 1, "", "get_value"], [108, 1, 1, "", "servable"], [108, 1, 1, "", "show"], [108, 1, 1, "", "to_spec"], [108, 1, 1, "", "update"]], "lumen.views.base.Table": [[109, 1, 1, "", "get_data"], [109, 1, 1, "", "get_panel"], [109, 1, 1, "", "get_value"], [109, 1, 1, "", "servable"], [109, 1, 1, "", "show"], [109, 1, 1, "", "to_spec"], [109, 1, 1, "", "update"]], "lumen.views.base.View": [[112, 1, 1, "", "get_data"], [112, 1, 1, "", "get_panel"], [112, 1, 1, "", "get_value"], [112, 1, 1, "", "servable"], [112, 1, 1, "", "show"], [112, 1, 1, "", "to_spec"], [112, 1, 1, "", "update"]], "lumen.views.base.hvPlotUIView": [[110, 1, 1, "", "get_data"], [110, 1, 1, "", "get_panel"], [110, 1, 1, "", "get_value"], [110, 1, 1, "", "servable"], [110, 1, 1, "", "show"], [110, 1, 1, "", "to_spec"], [110, 1, 1, "", "update"]], "lumen.views.base.hvPlotView": [[111, 1, 1, "", "get_data"], [111, 1, 1, "", "get_panel"], [111, 1, 1, "", "get_plot"], [111, 1, 1, "", "get_value"], [111, 1, 1, "", "servable"], [111, 1, 1, "", "show"], [111, 1, 1, "", "to_spec"], [111, 1, 1, "", "update"]]}, "objtypes": {"0": "py:class", "1": "py:method"}, "objnames": {"0": ["py", "class", "Python class"], "1": ["py", "method", "Python method"]}, "titleterms": {"background": 0, "lumen": [1, 3, 15, 16, 38], "python": [1, 28, 30, 31], "what": [1, 2, 12, 13, 21, 22, 23, 24, 26, 28, 30, 32, 34, 37], "i": [1, 2, 12, 13, 22], "thi": [1, 2, 12, 13, 21, 22, 23, 24, 26, 28, 30, 32, 34, 37], "page": [1, 2, 12, 13], "about": [1, 2], "pipelin": [2, 13, 17, 28, 30, 42, 54], "branch": [2, 28], "relat": [2, 21, 28, 30], "resourc": [2, 21, 28, 30], "compar": 3, "other": 3, "dashboard": [3, 12, 16, 17, 28, 30, 31, 32, 114], "tool": [3, 12], "gener": 3, "consider": 3, "tableau": 3, "powerbi": 3, "looker": 3, "spotfir": 3, "etc": 3, "apach": 3, "superset": 3, "datasett": 3, "perspect": [3, 107], "panel": [3, 106], "bokeh": 3, "dash": 3, "streamlit": 3, "voila": 3, "ipywidget": 3, "transport": 4, "london": 4, "bike": 4, "point": 4, "occup": 4, "earthquak": 5, "galleri": [6, 114], "nyc": 7, "taxi": 7, "penguin": 8, "precipit": 9, "seattl": 10, "weather": 10, "windturbin": 11, "svg": [12, 13, 15, 17], "version": [12, 13, 15, 17], "1": [12, 13, 15, 17, 21], "width": [12, 13, 15, 17], "2": [12, 13, 15, 17, 21], "0em": [12, 13, 15, 17], "height": [12, 13, 15, 17], "class": [12, 13, 15, 17], "sd": [12, 13, 15, 17], "octicon": [12, 13, 15, 17], "mr": [12, 13, 15, 17], "viewbox": [12, 13, 15, 17], "0": [12, 13, 15, 17], "24": [12, 13, 15, 17], "aria": [12, 13, 15, 17], "hidden": [12, 13, 15, 17], "true": [12, 13, 15, 17], "path": [12, 13, 15, 17, 21], "fill": [12, 13, 15, 17], "rule": [12, 13, 15, 17], "evenodd": [12, 13, 15, 17], "d": [12, 13, 15, 17], "m7": 12, "875": 12, "292a": 12, "125": 12, "00": [12, 13, 15, 17], "032": 12, "018a7": 12, "7": [12, 13, 15, 17], "004": 12, "75": [12, 13, 15, 17], "8": [12, 15], "25a7": 12, "247": 12, "003": 12, "654": [12, 13], "6": [12, 13], "297c": 12, "57": 12, "327": [12, 13], "982": 12, "955": 12, "941": 12, "682v": 12, "002l": 12, "317": 12, "058a": 12, "11": [12, 13, 17], "498": 12, "078l": 12, "062v": 12, "004c": 12, "006": 12, "09": [12, 13], "047": 12, "215": 12, "188": 12, "296a8": 12, "747": 12, "013": 12, "25": [12, 13, 15], "25a8": 12, "74": 12, "732": 12, "169": 12, "547": 12, "011": [12, 15], "709": 12, "064c": 12, "484": 12, "292": [12, 13], "809": 12, "835": 12, "46v4": 12, "714a": 12, "119": [12, 15], "213l2": 12, "385c": 12, "08": 12, "05": 12, "182": 12, "262": 12, "0l2": 12, "385a": 12, "213v2": 12, "478c0": 12, "626": 12, "325": 12, "81": 12, "461a1": 12, "708": 12, "064": 12, "17": 12, "01": [12, 13, 15], "4": [12, 13, 17], "41": [12, 13], "598c": 12, "14": [12, 13], "081": 12, "193": 12, "206": 12, "296v": 12, "004l": 12, "318": 12, "062a": 12, "058v": 12, "002c": 12, "041": 12, "727": 12, "37": 12, "355": 12, "94": 12, "682a7": 12, "0019": [12, 13], "3": [12, 13, 15, 17], "093": 12, "5": [12, 13, 15, 17], "018l": 12, "001c": 12, "014": 12, "031": 12, "036": 12, "022": 12, "084": 12, "079": [12, 13], "177v7": 12, "19a1": 12, "833": 12, "49l": 12, "385a1": 12, "834": 12, "0l": [12, 13, 15], "384a1": 12, "018": [12, 13], "192v2": 12, "477c0": 12, "098": [12, 15], "048": 12, "155": 12, "176a": 12, "062": [12, 13], "011l": 12, "001z": 12, "build": [12, 17, 30, 31], "purpos": [12, 13], "creat": 12, "yaml": [12, 13, 28, 44], "file": [12, 21, 23, 24, 37, 56], "add": [12, 28, 30], "data": [12, 13, 16, 17, 25, 26, 27, 29, 30, 35], "sourc": [12, 13, 22, 30, 54, 64, 114], "specifi": [12, 30], "tabl": [12, 109], "view": [12, 13, 28, 31, 34, 54, 112, 114], "plot": 12, "make": 12, "scatter": 12, "manipul": 12, "expand": 12, "type": [12, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "custom": [12, 21], "appear": 12, "behavior": 12, "9": [12, 13, 15, 17], "titl": 12, "theme": 12, "mortar": 13, "board": 13, "m12": 13, "06a": 13, "584": 13, "458": 13, "81a": 13, "000": [13, 15], "38l4": 13, "793v3": 13, "803a2": 13, "901": 13, "757c": 13, "579": 13, "58": 13, "923": 13, "43v4": 13, "5c0": [13, 15], "248": 13, "128": 13, "486": 13, "335": 13, "624": 13, "06": 13, "04": 13, "117": 13, "073": 13, "22": 13, "124": 13, "297": 13, "138": 13, "52": 13, "213": 13, "448": 13, "149": 13, "288": 13, "925": 13, "288s1": 13, "477": 13, "288c": 13, "223": [13, 15], "075": 13, "396": 13, "15": [13, 15], "213a2": 13, "21": 13, "117a": 13, "762": 13, "008": 13, "28v": 13, "344": 13, "85": 13, "428a2": 13, "758v": 13, "17l5": 13, "958": 13, "516a": 13, "0l5": 13, "208": 13, "2v4": 13, "003a2": 13, "552": 13, "085": 13, "057": 13, "849": 13, "65c": 13, "826": 13, "488": 13, "255": 13, "021": 13, "572": 13, "612": 13, "162": 13, "037": 13, "1a": 13, "192": 13, "487c": 13, "56": 13, "072": 13, "173": 13, "113": 13, "846": 13, "558": 13, "254": 13, "592": 13, "334": 13, "23": 13, "538": 13, "316": 13, "914": 13, "64": 13, "163": 13, "896a2": 13, "84": 13, "392": 13, "482h": 13, "001a": 13, "15v": 13, "892l4": 13, "542": 13, "917a": 13, "382l": 13, "75zm5": 13, "15c": 13, "377": 13, "745": 13, "141": 13, "017": [13, 17], "413": 13, "265": 13, "483": 13, "368v4": 13, "022c": 13, "299": 13, "105": [13, 15], "797": 13, "228": 13, "228s1": 13, "201": 13, "123": 13, "228v16": 13, "78c0": 13, "669": 13, "218": 13, "103": 13, "368a1": 13, "431": 13, "005": 13, "15zm7": 13, "564l2": 13, "678": 13, "12": 13, "564": [13, 15], "322": 13, "436z": 13, "core": 13, "concept": 13, "overview": [13, 21, 22, 24, 28, 30, 34], "specif": [13, 37], "config": [13, 39, 54, 114], "process": [13, 29, 35], "filter": [13, 17, 30, 53, 54, 71], "transform": [13, 30, 54, 92], "layout": [13, 41, 54, 114], "advanc": [13, 20, 35], "function": 13, "default": [13, 40, 54], "variabl": [13, 22, 54, 102, 114], "extern": [13, 19, 22], "templat": [13, 22], "authent": [13, 18], "where": 13, "go": 13, "from": 13, "here": 13, "get": 14, "start": 14, "desktop": 15, "download": [15, 26, 104], "m11": 15, "331v": 15, "75a": [15, 17], "0v8": 15, "58l1": 15, "949": 15, "11a": 15, "1115": 15, "237l": 15, "52a": 15, "102": 15, "22l1": 15, "111z": 15, "m2": 15, "25h5": 15, "5a": 15, "100": [15, 17], "5h": [15, 17], "5a1": 15, "001": [15, 17], "75v11": 15, "966": 15, "784": 15, "75h6": 15, "204c": 15, "171": 15, "375": 15, "805": 15, "652": 15, "77": 15, "757a": 15, "007": 15, "22h8": 15, "565": 15, "243c": 15, "964": 15, "598": 15, "382": 15, "769": 15, "757h6": 15, "204a1": 15, "0023": 15, "25v3": 15, "75a1": 15, "0021": 15, "2h": 15, "5h5": 15, "25v11": 15, "25h2": 15, "75zm10": 15, "463": 15, "17c": 15, "126": 15, "266": 15, "445": 15, "52c": 15, "66": 15, "055": 15, "234": 15, "074z": 15, "instal": [15, 37], "setup": 15, "option": 15, "depend": 15, "": 16, "architectur": 16, "explor": 16, "set": 16, "git": 17, "commit": 17, "m15": 17, "75a3": 17, "0zm1": 17, "444": 17, "75a5": 17, "888": 17, "0h2": 17, "5h4": 17, "306a5": 17, "009": 17, "0h4": 17, "306a": 17, "306z": 17, "declar": [17, 30], "programmat": [17, 30], "automat": 17, "chain": 17, "configur": [18, 113], "how": [19, 22, 23, 24, 26, 34, 35], "defin": [19, 34], "callback": 19, "refer": [19, 22, 28, 54], "modul": [19, 21], "serial": 19, "topic": [20, 35], "access": [21, 24], "compon": 21, "doe": [21, 22, 23, 24, 26, 28, 30, 32, 34, 37], "guid": [21, 22, 23, 24, 26, 28, 30, 32, 34, 35, 37], "solv": [21, 22, 23, 24, 26, 28, 30, 32, 34, 37], "approach": 21, "us": [21, 22, 23], "import": 21, "command": 22, "line": 22, "shell": 22, "should": 22, "cach": 23, "precach": 23, "local": 24, "remot": 24, "intak": [25, 35, 58], "output": [27, 35], "initi": 28, "simpl": 28, "new": 28, "preview": 30, "manual": 30, "updat": 30, "displai": 30, "attach": 31, "lai": 31, "out": 31, "note": [31, 113], "deploi": [32, 33, 35], "dure": 32, "develop": 32, "visual": [33, 35], "valid": [35, 36, 37], "run": 37, "routin": 37, "debug": 37, "an": 37, "invalid": 37, "indent": 37, "error": 37, "kei": 37, "valu": 37, "packag": 37, "welcom": 38, "paramet": [39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "method": [39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112], "auth": [43, 45, 54], "yamlauthmapperplugin": 44, "binfilt": 46, "bin": 46, "constantfilt": 47, "constant": [47, 94], "datefilt": 48, "date": 48, "datetimefilt": 49, "datetim": 49, "facetfilt": 50, "facet": 50, "paramfilt": 51, "param": [51, 98], "widgetfilt": 52, "widget": [52, 101], "derivedsourc": 55, "deriv": 55, "filesourc": 56, "intakesqlsourc": 57, "intake_sql": 57, "intakesourc": 58, "jsonsourc": 59, "json": 59, "joinedsourc": 60, "join": 60, "panelsessionsourc": 61, "session_info": 61, "restsourc": 62, "rest": 62, "websitesourc": 63, "live": 63, "aggreg": 65, "astyp": 66, "as_typ": 66, "column": 67, "comput": 68, "count": 69, "eval": 70, "none": 71, "historytransform": 72, "histori": 72, "iloc": 73, "melt": 74, "pivot": 75, "queri": 76, "renam": 77, "renameaxi": 78, "rename_axi": 78, "resetindex": 79, "reset_index": 79, "sqlcolumn": 80, "sql_column": 80, "sqldistinct": 81, "sql_distinct": 81, "sqlfilter": 82, "sql_filter": 82, "sqlgroupbi": 83, "sql_group_bi": 83, "sqllimit": 84, "sql_limit": 84, "sqlminmax": 85, "sql_minmax": 85, "sampl": 86, "setindex": 87, "set_index": 87, "sort": 88, "stack": 89, "sum": 90, "unstack": 91, "project_lnglat": 93, "cooki": 95, "envvari": 96, "env": 96, "header": 97, "urlqueri": 99, "url": 99, "userinfo": 100, "user": 100, "altairview": 103, "altair": 103, "downloadview": 104, "indicatorview": 105, "indic": 105, "perspectiveview": 107, "stringview": 108, "string": 108, "hvplotuiview": 110, "hvplot_ui": 110, "hvplotview": 111, "hvplot": 111, "ui": 114, "launch": 114, "builder": 114, "step": 114, "editor": 114, "tip": 114, "launcher": 114}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 57}, "alltitles": {"Background": [[0, "background"]], "Lumen in Python": [[1, "lumen-in-python"]], "What is this page about?": [[1, null], [2, null]], "Pipeline Branching": [[2, "pipeline-branching"]], "Related resources:": [[2, "related-resources"]], "Lumen compared to other dashboarding tools": [[3, "lumen-compared-to-other-dashboarding-tools"]], "General considerations": [[3, "general-considerations"]], "Tableau, PowerBI, Looker, Spotfire, etc.": [[3, "tableau-powerbi-looker-spotfire-etc"]], "Apache Superset": [[3, "apache-superset"]], "Datasette": [[3, "datasette"]], "Perspective": [[3, "perspective"]], "Panel and Bokeh": [[3, "panel-and-bokeh"]], "Dash, Streamlit, Voila+IPyWidgets": [[3, "dash-streamlit-voila-ipywidgets"]], "Transport for London: Bike Point Occupancy": [[4, "transport-for-london-bike-point-occupancy"]], "Earthquakes": [[5, "earthquakes"]], "Gallery": [[6, "gallery"]], "NYC Taxi": [[7, "nyc-taxi"]], "Penguins": [[8, "penguins"]], "Precipitation": [[9, "precipitation"]], "Seattle Weather": [[10, "seattle-weather"]], "Windturbines": [[11, "windturbines"]], " Build a dashboard": [[12, "svg-version-1-1-width-2-0em-height-2-0em-class-sd-octicon-sd-octicon-tools-sd-mr-1-viewbox-0-0-24-24-aria-hidden-true-path-fill-rule-evenodd-d-m7-875-2-292a-125-125-0-00-032-018a7-24-7-24-0-004-75-8-25a7-247-7-247-0-003-654-6-297c-57-327-982-955-941-1-682v-002l-317-6-058a-75-75-0-11-1-498-078l-317-6-062v-004c-006-09-047-215-188-296a8-747-8-747-0-013-25-8-25a8-74-8-74-0-013-732-7-169-1-547-1-547-0-011-709-064c-484-292-809-835-809-1-46v4-714a-25-25-0-00-119-213l2-25-1-385c-08-05-182-05-262-0l2-25-1-385a-25-25-0-00-119-213v2-478c0-626-325-1-169-81-1-461a1-547-1-547-0-011-708-064-8-74-8-74-0-013-732-7-17-8-747-8-747-0-01-4-41-7-598c-14-081-193-206-188-296v-004l-318-6-062a-75-75-0-11-1-498-078l-317-6-058v-002c-041-727-37-1-355-94-1-682a7-247-7-247-0-0019-25-8-25a7-24-7-24-0-00-3-093-5-94-125-125-0-00-032-018l-01-001c-003-0-014-0-031-01-036-022-084-079-084-177v7-19a1-75-1-75-0-01-833-1-49l-2-25-1-385a1-75-1-75-0-01-1-834-0l-2-25-1-384a1-75-1-75-0-018-7-192v2-477c0-098-048-155-084-176a-062-062-0-00-031-011l-01-001z-path-svg-build-a-dashboard"]], "What is the purpose of this page?": [[12, null], [13, null]], "1. Create a YAML file": [[12, "create-a-yaml-file"]], "2. Add a data source": [[12, "add-a-data-source"]], "3. Specify a table view": [[12, "specify-a-table-view"]], "4. Create a plot view": [[12, "create-a-plot-view"]], "5. Make a scatter plot": [[12, "make-a-scatter-plot"]], "6. Manipulate the data": [[12, "manipulate-the-data"]], "7. Expand the view types": [[12, "expand-the-view-types"]], "8. Customize the appearance and behavior": [[12, "customize-the-appearance-and-behavior"]], "9. Add a title and theme": [[12, "add-a-title-and-theme"]], " Core Concepts": [[13, "svg-version-1-1-width-2-0em-height-2-0em-class-sd-octicon-sd-octicon-mortar-board-sd-mr-1-viewbox-0-0-24-24-aria-hidden-true-path-fill-rule-evenodd-d-m12-292-2-06a-75-75-0-00-584-0l-458-6-81a-75-75-0-000-1-38l4-25-9-793v3-803a2-901-2-901-0-00-1-327-757c-579-58-923-1-41-923-2-43v4-5c0-248-128-486-335-624-06-04-117-073-22-124-124-062-297-138-52-213-448-149-1-09-288-1-925-288s1-477-14-1-925-288c-223-075-396-15-52-213a2-11-2-11-0-00-21-117a-762-762-0-008-21-28v-4-5c0-1-018-344-1-85-923-2-428a2-9-2-9-0-00-1-327-758v-3-17l5-958-2-516a-75-75-0-00-584-0l5-208-2-2v4-003a2-552-2-552-0-01-079-085-4-057-4-057-0-01-849-65c-826-488-2-255-1-021-4-572-1-021-612-0-1-162-037-1-654-1a-75-75-0-00-192-1-487c-56-072-1-173-113-1-846-113-2-558-0-4-254-592-5-334-1-23-538-316-914-64-1-163-896a2-84-2-84-0-00-392-482h-001a-75-75-0-0019-15v-4-892l4-542-1-917a-75-75-0-000-1-382l-11-25-4-75zm5-15c-377-0-745-141-1-017-413-265-265-483-7-483-1-368v4-022c-299-105-797-228-1-5-228s1-201-123-1-5-228v16-78c0-669-218-1-103-483-1-368a1-431-1-431-0-005-15zm7-3-564l2-678-7-5-12-3-564-21-322-7-5-12-11-436z-path-svg-core-concepts"]], "Overview": [[13, "overview"], [21, "overview"], [22, "overview"], [24, "overview"], [28, "overview"], [30, "overview"], [34, "overview"]], "YAML specification": [[13, "yaml-specification"]], "Config": [[13, "config"], [39, "config"], [54, "config"]], "Sources": [[13, "sources"]], "Pipelines (data processing)": [[13, "pipelines-data-processing"]], "Filters": [[13, "filters"]], "Transforms": [[13, "transforms"]], "Layouts (views)": [[13, "layouts-views"]], "Advanced Functionality": [[13, "advanced-functionality"]], "Defaults": [[13, "defaults"], [40, "defaults"], [54, "defaults"]], "Variables": [[13, "variables"], [22, "variables"]], "Sources as variables": [[13, "sources-as-variables"], [22, "sources-as-variables"]], "External variables (templating)": [[13, "external-variables-templating"], [22, "external-variables-templating"]], "Authentication": [[13, "authentication"]], "Where to go from here?": [[13, "where-to-go-from-here"]], "Getting Started": [[14, "getting-started"]], " Installation": [[15, "svg-version-1-1-width-2-0em-height-2-0em-class-sd-octicon-sd-octicon-desktop-download-sd-mr-1-viewbox-0-0-24-24-aria-hidden-true-path-d-m11-25-9-331v-75a-75-75-0-011-5-0v8-58l1-949-2-11a-75-75-0-1115-8-8-237l-3-25-3-52a-75-75-0-01-1-102-0l-3-25-3-52a-75-75-0-119-3-7-22l1-949-2-111z-path-path-fill-rule-evenodd-d-m2-5-3-75a-25-25-0-01-25-25h5-5a-75-75-0-100-1-5h-5-5a1-75-1-75-0-001-3-75v11-5c0-966-784-1-75-1-75-1-75h6-204c-171-1-375-805-2-652-1-77-3-757a-75-75-0-007-75-22h8-5a-75-75-0-00-565-1-243c-964-1-105-1-598-2-382-1-769-3-757h6-204a1-75-1-75-0-0023-15-25v3-75a1-75-1-75-0-0021-25-2h-5-5a-75-75-0-000-1-5h5-5a-25-25-0-01-25-25v11-5a-25-25-0-01-25-25h2-75a-25-25-0-01-25-25v3-75zm10-463-17c-126-1-266-564-2-445-1-223-3-5h5-52c-66-1-055-1-098-2-234-1-223-3-5h-3-074z-path-svg-installation"]], "Setup": [[15, "setup"]], "Installing Lumen": [[15, "installing-lumen"]], "Optional dependencies": [[15, "optional-dependencies"]], "Lumen\u2019s Architecture": [[16, "lumen-s-architecture"]], "Data Exploration": [[16, "data-exploration"]], "Dashboard Settings": [[16, "dashboard-settings"]], " Building a data pipeline": [[17, "svg-version-1-1-width-2-0em-height-2-0em-class-sd-octicon-sd-octicon-git-commit-sd-mr-1-viewbox-0-0-24-24-aria-hidden-true-path-fill-rule-evenodd-d-m15-5-11-75a3-5-3-5-0-11-7-0-3-5-3-5-0-017-0zm1-444-75a5-001-5-001-0-00-9-888-0h2-75a-75-75-0-100-1-5h4-306a5-001-5-001-0-009-888-0h4-306a-75-75-0-100-1-5h-4-306z-path-svg-building-a-data-pipeline"]], "Declaring a pipeline": [[17, "declaring-a-pipeline"]], "Programmatically building pipelines": [[17, "programmatically-building-pipelines"]], "Automatic filters": [[17, "automatic-filters"]], "Chaining pipelines": [[17, "chaining-pipelines"]], "Building a dashboard": [[17, "building-a-dashboard"]], "Configuring Authentication": [[18, "configuring-authentication"]], "How to define callbacks": [[19, "how-to-define-callbacks"]], "Reference callbacks in external module": [[19, "reference-callbacks-in-external-module"]], "Serializing callbacks": [[19, "serializing-callbacks"]], "Advanced Topics": [[20, "advanced-topics"], [35, "advanced-topics"]], "Access custom components": [[21, "access-custom-components"]], "What does this guide solve?": [[21, null], [22, null], [23, null], [24, null], [26, null], [28, null], [30, null], [32, null], [34, null], [37, null]], "Approach 1: Using imported files": [[21, "approach-1-using-imported-files"]], "Approach 2: Using module paths": [[21, "approach-2-using-module-paths"]], "Related Resources": [[21, "related-resources"], [28, "related-resources"], [30, "related-resources"]], "How to use variables": [[22, "how-to-use-variables"]], "Variables with the command line": [[22, "variables-with-the-command-line"]], "Variables with a shell command": [[22, "variables-with-a-shell-command"]], "Should I use $ or {{ }} for reference?": [[22, null]], "How to use cache": [[23, "how-to-use-cache"]], "Caching file": [[23, "caching-file"]], "Precaching": [[23, "precaching"]], "How to access files": [[24, "how-to-access-files"]], "Local files": [[24, "local-files"]], "Remote files": [[24, "remote-files"]], "Data Intake": [[25, "data-intake"], [35, "data-intake"]], "How to download data": [[26, "how-to-download-data"]], "Download data": [[26, "download-data"]], "Data Output": [[27, "data-output"], [35, "data-output"]], "Branch a pipeline": [[28, "branch-a-pipeline"]], "Branching in YAML": [[28, "branching-in-yaml"]], "Initiating a simple dashboard": [[28, "initiating-a-simple-dashboard"]], "Add a branch": [[28, "add-a-branch"]], "Refer to the branch in a new view": [[28, "refer-to-the-branch-in-a-new-view"]], "Branching in Python": [[28, "branching-in-python"]], "Initiating the pipeline": [[28, "initiating-the-pipeline"]], "Branching the pipeline": [[28, "branching-the-pipeline"]], "Data Processing": [[29, "data-processing"], [35, "data-processing"]], "Build a Pipeline in Python": [[30, "build-a-pipeline-in-python"]], "Declaratively specifying a pipeline": [[30, "declaratively-specifying-a-pipeline"]], "Programmatically specifying a pipeline": [[30, "programmatically-specifying-a-pipeline"]], "Add source": [[30, "add-source"]], "Preview the data": [[30, null]], "Add filter": [[30, "add-filter"]], "Add transform": [[30, "add-transform"]], "Manually update dashboard": [[30, null]], "Display the pipeline": [[30, "display-the-pipeline"]], "Building a dashboard in Python": [[31, "building-a-dashboard-in-python"]], "Attaching Views": [[31, "attaching-views"]], "Laying out views": [[31, "laying-out-views"]], "Building the dashboard": [[31, "building-the-dashboard"]], "Note": [[31, null], [113, null]], "Deploy a dashboard": [[32, "deploy-a-dashboard"]], "Deploy during development": [[32, "deploy-during-development"]], "Visualize and Deploy": [[33, "visualize-and-deploy"], [35, "visualize-and-deploy"]], "How to define views": [[34, "how-to-define-views"]], "How to Guides": [[35, "how-to-guides"]], "Validation": [[35, "validation"], [36, "validation"]], "Validate the specification": [[37, "validate-the-specification"]], "Run the specification routine": [[37, "run-the-specification-routine"]], "Debug an invalid specification file": [[37, "debug-an-invalid-specification-file"]], "Indentation errors": [[37, "indentation-errors"]], "Invalid keys or values": [[37, "invalid-keys-or-values"]], "Package not installed": [[37, "package-not-installed"]], "Welcome to Lumen!": [[38, "welcome-to-lumen"]], "Parameters": [[39, "parameters"], [40, "parameters"], [41, "parameters"], [42, "parameters"], [43, "parameters"], [44, "parameters"], [45, "parameters"], [46, "parameters"], [48, "parameters"], [49, "parameters"], [51, "parameters"], [52, "parameters"], [53, "parameters"], [55, "parameters"], [56, "parameters"], [57, "parameters"], [58, "parameters"], [59, "parameters"], [60, "parameters"], [61, "parameters"], [62, "parameters"], [63, "parameters"], [64, "parameters"], [65, "parameters"], [66, "parameters"], [67, "parameters"], [69, "parameters"], [70, "parameters"], [71, "parameters"], [72, "parameters"], [73, "parameters"], [74, "parameters"], [75, "parameters"], [76, "parameters"], [77, "parameters"], [78, "parameters"], [79, "parameters"], [80, "parameters"], [81, "parameters"], [82, "parameters"], [83, "parameters"], [84, "parameters"], [85, "parameters"], [86, "parameters"], [87, "parameters"], [88, "parameters"], [89, "parameters"], [90, "parameters"], [91, "parameters"], [92, "parameters"], [93, "parameters"], [95, "parameters"], [96, "parameters"], [97, "parameters"], [98, "parameters"], [99, "parameters"], [100, "parameters"], [101, "parameters"], [102, "parameters"], [103, "parameters"], [104, "parameters"], [105, "parameters"], [106, "parameters"], [107, "parameters"], [108, "parameters"], [109, "parameters"], [110, "parameters"], [111, "parameters"], [112, "parameters"]], "Methods": [[39, "methods"], [40, "methods"], [41, "methods"], [42, "methods"], [43, "methods"], [44, "methods"], [45, "methods"], [46, "methods"], [47, "methods"], [48, "methods"], [49, "methods"], [50, "methods"], [51, "methods"], [52, "methods"], [53, "methods"], [55, "methods"], [56, "methods"], [57, "methods"], [58, "methods"], [59, "methods"], [60, "methods"], [61, "methods"], [62, "methods"], [63, "methods"], [64, "methods"], [65, "methods"], [66, "methods"], [67, "methods"], [68, "methods"], [69, "methods"], [70, "methods"], [71, "methods"], [72, "methods"], [73, "methods"], [74, "methods"], [75, "methods"], [76, "methods"], [77, "methods"], [78, "methods"], [79, "methods"], [80, "methods"], [81, "methods"], [82, "methods"], [83, "methods"], [84, "methods"], [85, "methods"], [86, "methods"], [87, "methods"], [88, "methods"], [89, "methods"], [90, "methods"], [91, "methods"], [92, "methods"], [93, "methods"], [94, "methods"], [95, "methods"], [96, "methods"], [97, "methods"], [98, "methods"], [99, "methods"], [100, "methods"], [101, "methods"], [102, "methods"], [103, "methods"], [104, "methods"], [105, "methods"], [106, "methods"], [107, "methods"], [108, "methods"], [109, "methods"], [110, "methods"], [111, "methods"], [112, "methods"]], "Layout": [[41, "layout"], [54, "layout"]], "Pipeline": [[42, "pipeline"], [54, "pipeline"]], "Auth": [[43, "auth"], [45, "auth"], [54, "auth"]], "YamlAuthMapperPlugin\u00a0\u00a0type: yaml": [[44, "yamlauthmapperplugin-type-yaml"]], "Types": [[45, "types"], [53, "types"], [64, "types"], [92, "types"], [102, "types"], [112, "types"]], "BinFilter\u00a0\u00a0type: bins": [[46, "binfilter-type-bins"]], "ConstantFilter\u00a0\u00a0type: constant": [[47, "constantfilter-type-constant"]], "DateFilter\u00a0\u00a0type: date": [[48, "datefilter-type-date"]], "DatetimeFilter\u00a0\u00a0type: datetime": [[49, "datetimefilter-type-datetime"]], "FacetFilter\u00a0\u00a0type: facet": [[50, "facetfilter-type-facet"]], "ParamFilter\u00a0\u00a0type: param": [[51, "paramfilter-type-param"]], "WidgetFilter\u00a0\u00a0type: widget": [[52, "widgetfilter-type-widget"]], "Filter": [[53, "filter"], [54, "filter"]], "Reference": [[54, "reference"]], "Variable": [[54, "variable"], [102, "variable"]], "Source": [[54, "source"], [64, "source"]], "Transform": [[54, "transform"], [92, "transform"]], "View": [[54, "view"], [112, "view"]], "DerivedSource\u00a0\u00a0type: derived": [[55, "derivedsource-type-derived"]], "FileSource\u00a0\u00a0type: file": [[56, "filesource-type-file"]], "IntakeSQLSource\u00a0\u00a0type: intake_sql": [[57, "intakesqlsource-type-intake-sql"]], "IntakeSource\u00a0\u00a0type: intake": [[58, "intakesource-type-intake"]], "JSONSource\u00a0\u00a0type: json": [[59, "jsonsource-type-json"]], "JoinedSource\u00a0\u00a0type: join": [[60, "joinedsource-type-join"]], "PanelSessionSource\u00a0\u00a0type: session_info": [[61, "panelsessionsource-type-session-info"]], "RESTSource\u00a0\u00a0type: rest": [[62, "restsource-type-rest"]], "WebsiteSource\u00a0\u00a0type: live": [[63, "websitesource-type-live"]], "Aggregate\u00a0\u00a0type: aggregate": [[65, "aggregate-type-aggregate"]], "Astype\u00a0\u00a0type: as_type": [[66, "astype-type-as-type"]], "Columns\u00a0\u00a0type: columns": [[67, "columns-type-columns"]], "Compute\u00a0\u00a0type: compute": [[68, "compute-type-compute"]], "Count\u00a0\u00a0type: count": [[69, "count-type-count"]], "Eval\u00a0\u00a0type: eval": [[70, "eval-type-eval"]], "Filter\u00a0\u00a0type: None": [[71, "filter-type-none"]], "HistoryTransform\u00a0\u00a0type: history": [[72, "historytransform-type-history"]], "Iloc\u00a0\u00a0type: iloc": [[73, "iloc-type-iloc"]], "Melt\u00a0\u00a0type: melt": [[74, "melt-type-melt"]], "Pivot\u00a0\u00a0type: pivot": [[75, "pivot-type-pivot"]], "Query\u00a0\u00a0type: query": [[76, "query-type-query"]], "Rename\u00a0\u00a0type: rename": [[77, "rename-type-rename"]], "RenameAxis\u00a0\u00a0type: rename_axis": [[78, "renameaxis-type-rename-axis"]], "ResetIndex\u00a0\u00a0type: reset_index": [[79, "resetindex-type-reset-index"]], "SQLColumns\u00a0\u00a0type: sql_columns": [[80, "sqlcolumns-type-sql-columns"]], "SQLDistinct\u00a0\u00a0type: sql_distinct": [[81, "sqldistinct-type-sql-distinct"]], "SQLFilter\u00a0\u00a0type: sql_filter": [[82, "sqlfilter-type-sql-filter"]], "SQLGroupBy\u00a0\u00a0type: sql_group_by": [[83, "sqlgroupby-type-sql-group-by"]], "SQLLimit\u00a0\u00a0type: sql_limit": [[84, "sqllimit-type-sql-limit"]], "SQLMinMax\u00a0\u00a0type: sql_minmax": [[85, "sqlminmax-type-sql-minmax"]], "Sample\u00a0\u00a0type: sample": [[86, "sample-type-sample"]], "SetIndex\u00a0\u00a0type: set_index": [[87, "setindex-type-set-index"]], "Sort\u00a0\u00a0type: sort": [[88, "sort-type-sort"]], "Stack\u00a0\u00a0type: stack": [[89, "stack-type-stack"]], "Sum\u00a0\u00a0type: sum": [[90, "sum-type-sum"]], "Unstack\u00a0\u00a0type: unstack": [[91, "unstack-type-unstack"]], "project_lnglat\u00a0\u00a0type: project_lnglat": [[93, "project-lnglat-type-project-lnglat"]], "Constant\u00a0\u00a0type: constant": [[94, "constant-type-constant"]], "Cookie\u00a0\u00a0type: cookie": [[95, "cookie-type-cookie"]], "EnvVariable\u00a0\u00a0type: env": [[96, "envvariable-type-env"]], "Header\u00a0\u00a0type: header": [[97, "header-type-header"]], "Parameter\u00a0\u00a0type: param": [[98, "parameter-type-param"]], "URLQuery\u00a0\u00a0type: url": [[99, "urlquery-type-url"]], "UserInfo\u00a0\u00a0type: user": [[100, "userinfo-type-user"]], "Widget\u00a0\u00a0type: widget": [[101, "widget-type-widget"]], "AltairView\u00a0\u00a0type: altair": [[103, "altairview-type-altair"]], "DownloadView\u00a0\u00a0type: download": [[104, "downloadview-type-download"]], "IndicatorView\u00a0\u00a0type: indicator": [[105, "indicatorview-type-indicator"]], "Panel\u00a0\u00a0type: panel": [[106, "panel-type-panel"]], "PerspectiveView\u00a0\u00a0type: perspective": [[107, "perspectiveview-type-perspective"]], "StringView\u00a0\u00a0type: string": [[108, "stringview-type-string"]], "Table\u00a0\u00a0type: table": [[109, "table-type-table"]], "hvPlotUIView\u00a0\u00a0type: hvplot_ui": [[110, "hvplotuiview-type-hvplot-ui"]], "hvPlotView\u00a0\u00a0type: hvplot": [[111, "hvplotview-type-hvplot"]], "Configuration": [[113, "configuration"]], "UI": [[114, "ui"]], "Launching the Builder UI": [[114, "launching-the-builder-ui"]], "Step-by-step": [[114, "step-by-step"]], "Dashboard Gallery": [[114, "dashboard-gallery"]], "Config Editor": [[114, "config-editor"]], "Tip": [[114, null], [114, null]], "Variable Editor": [[114, "variable-editor"]], "Source Editor": [[114, "source-editor"]], "View Editor": [[114, "view-editor"]], "Layout Editor": [[114, "layout-editor"]], "Launcher": [[114, "launcher"]]}, "indexentries": {"config (class in lumen.dashboard)": [[39, "lumen.dashboard.Config"]], "construct_template() (lumen.dashboard.config method)": [[39, "lumen.dashboard.Config.construct_template"]], "to_spec() (lumen.dashboard.config method)": [[39, "lumen.dashboard.Config.to_spec"]], "defaults (class in lumen.dashboard)": [[40, "lumen.dashboard.Defaults"]], "apply() (lumen.dashboard.defaults method)": [[40, "lumen.dashboard.Defaults.apply"]], "to_spec() (lumen.dashboard.defaults method)": [[40, "lumen.dashboard.Defaults.to_spec"]], "layout (class in lumen.layout)": [[41, "lumen.layout.Layout"]], "get_cards() (lumen.layout.layout method)": [[41, "lumen.layout.Layout.get_cards"]], "get_filter_panel() (lumen.layout.layout method)": [[41, "lumen.layout.Layout.get_filter_panel"]], "servable() (lumen.layout.layout method)": [[41, "lumen.layout.Layout.servable"]], "show() (lumen.layout.layout method)": [[41, "lumen.layout.Layout.show"]], "start() (lumen.layout.layout method)": [[41, "lumen.layout.Layout.start"]], "to_spec() (lumen.layout.layout method)": [[41, "lumen.layout.Layout.to_spec"]], "update() (lumen.layout.layout method)": [[41, "lumen.layout.Layout.update"]], "pipeline (class in lumen.pipeline)": [[42, "lumen.pipeline.Pipeline"]], "add_filter() (lumen.pipeline.pipeline method)": [[42, "lumen.pipeline.Pipeline.add_filter"]], "add_transform() (lumen.pipeline.pipeline method)": [[42, "lumen.pipeline.Pipeline.add_transform"]], "chain() (lumen.pipeline.pipeline method)": [[42, "lumen.pipeline.Pipeline.chain"]], "clone() (lumen.pipeline.pipeline method)": [[42, "lumen.pipeline.Pipeline.clone"]], "precache() (lumen.pipeline.pipeline method)": [[42, "lumen.pipeline.Pipeline.precache"]], "servable() (lumen.pipeline.pipeline method)": [[42, "lumen.pipeline.Pipeline.servable"]], "show() (lumen.pipeline.pipeline method)": [[42, "lumen.pipeline.Pipeline.show"]], "to_spec() (lumen.pipeline.pipeline method)": [[42, "lumen.pipeline.Pipeline.to_spec"]], "traverse() (lumen.pipeline.pipeline method)": [[42, "lumen.pipeline.Pipeline.traverse"]], "auth (class in lumen.auth)": [[43, "lumen.auth.Auth"], [45, "lumen.auth.Auth"]], "to_spec() (lumen.auth.auth method)": [[43, "lumen.auth.Auth.to_spec"], [45, "lumen.auth.Auth.to_spec"]], "transform() (lumen.auth.auth method)": [[43, "lumen.auth.Auth.transform"], [45, "lumen.auth.Auth.transform"]], "yamlauthmapperplugin (class in lumen.auth)": [[44, "lumen.auth.YamlAuthMapperPlugin"]], "to_spec() (lumen.auth.yamlauthmapperplugin method)": [[44, "lumen.auth.YamlAuthMapperPlugin.to_spec"]], "transform() (lumen.auth.yamlauthmapperplugin method)": [[44, "lumen.auth.YamlAuthMapperPlugin.transform"]], "binfilter (class in lumen.filters.base)": [[46, "lumen.filters.base.BinFilter"]], "to_spec() (lumen.filters.base.binfilter method)": [[46, "lumen.filters.base.BinFilter.to_spec"]], "constantfilter (class in lumen.filters.base)": [[47, "lumen.filters.base.ConstantFilter"]], "to_spec() (lumen.filters.base.constantfilter method)": [[47, "lumen.filters.base.ConstantFilter.to_spec"]], "datefilter (class in lumen.filters.base)": [[48, "lumen.filters.base.DateFilter"]], "to_spec() (lumen.filters.base.datefilter method)": [[48, "lumen.filters.base.DateFilter.to_spec"]], "datetimefilter (class in lumen.filters.base)": [[49, "lumen.filters.base.DatetimeFilter"]], "to_spec() (lumen.filters.base.datetimefilter method)": [[49, "lumen.filters.base.DatetimeFilter.to_spec"]], "facetfilter (class in lumen.filters.base)": [[50, "lumen.filters.base.FacetFilter"]], "to_spec() (lumen.filters.base.facetfilter method)": [[50, "lumen.filters.base.FacetFilter.to_spec"]], "paramfilter (class in lumen.filters.base)": [[51, "lumen.filters.base.ParamFilter"]], "to_spec() (lumen.filters.base.paramfilter method)": [[51, "lumen.filters.base.ParamFilter.to_spec"]], "widgetfilter (class in lumen.filters.base)": [[52, "lumen.filters.base.WidgetFilter"]], "to_spec() (lumen.filters.base.widgetfilter method)": [[52, "lumen.filters.base.WidgetFilter.to_spec"]], "filter (class in lumen.filters.base)": [[53, "lumen.filters.base.Filter"]], "to_spec() (lumen.filters.base.filter method)": [[53, "lumen.filters.base.Filter.to_spec"]], "derivedsource (class in lumen.sources.base)": [[55, "lumen.sources.base.DerivedSource"]], "clear_cache() (lumen.sources.base.derivedsource method)": [[55, "lumen.sources.base.DerivedSource.clear_cache"]], "get() (lumen.sources.base.derivedsource method)": [[55, "lumen.sources.base.DerivedSource.get"]], "get_schema() (lumen.sources.base.derivedsource method)": [[55, "lumen.sources.base.DerivedSource.get_schema"]], "get_tables() (lumen.sources.base.derivedsource method)": [[55, "lumen.sources.base.DerivedSource.get_tables"]], "to_spec() (lumen.sources.base.derivedsource method)": [[55, "lumen.sources.base.DerivedSource.to_spec"]], "filesource (class in lumen.sources.base)": [[56, "lumen.sources.base.FileSource"]], "clear_cache() (lumen.sources.base.filesource method)": [[56, "lumen.sources.base.FileSource.clear_cache"]], "get() (lumen.sources.base.filesource method)": [[56, "lumen.sources.base.FileSource.get"]], "get_schema() (lumen.sources.base.filesource method)": [[56, "lumen.sources.base.FileSource.get_schema"]], "get_tables() (lumen.sources.base.filesource method)": [[56, "lumen.sources.base.FileSource.get_tables"]], "to_spec() (lumen.sources.base.filesource method)": [[56, "lumen.sources.base.FileSource.to_spec"]], "intakesqlsource (class in lumen.sources.intake_sql)": [[57, "lumen.sources.intake_sql.IntakeSQLSource"]], "clear_cache() (lumen.sources.intake_sql.intakesqlsource method)": [[57, "lumen.sources.intake_sql.IntakeSQLSource.clear_cache"]], "get() (lumen.sources.intake_sql.intakesqlsource method)": [[57, "lumen.sources.intake_sql.IntakeSQLSource.get"]], "get_schema() (lumen.sources.intake_sql.intakesqlsource method)": [[57, "lumen.sources.intake_sql.IntakeSQLSource.get_schema"]], "get_tables() (lumen.sources.intake_sql.intakesqlsource method)": [[57, "lumen.sources.intake_sql.IntakeSQLSource.get_tables"]], "to_spec() (lumen.sources.intake_sql.intakesqlsource method)": [[57, "lumen.sources.intake_sql.IntakeSQLSource.to_spec"]], "intakesource (class in lumen.sources.intake)": [[58, "lumen.sources.intake.IntakeSource"]], "clear_cache() (lumen.sources.intake.intakesource method)": [[58, "lumen.sources.intake.IntakeSource.clear_cache"]], "get() (lumen.sources.intake.intakesource method)": [[58, "lumen.sources.intake.IntakeSource.get"]], "get_schema() (lumen.sources.intake.intakesource method)": [[58, "lumen.sources.intake.IntakeSource.get_schema"]], "get_tables() (lumen.sources.intake.intakesource method)": [[58, "lumen.sources.intake.IntakeSource.get_tables"]], "to_spec() (lumen.sources.intake.intakesource method)": [[58, "lumen.sources.intake.IntakeSource.to_spec"]], "jsonsource (class in lumen.sources.base)": [[59, "lumen.sources.base.JSONSource"]], "clear_cache() (lumen.sources.base.jsonsource method)": [[59, "lumen.sources.base.JSONSource.clear_cache"]], "get() (lumen.sources.base.jsonsource method)": [[59, "lumen.sources.base.JSONSource.get"]], "get_schema() (lumen.sources.base.jsonsource method)": [[59, "lumen.sources.base.JSONSource.get_schema"]], "get_tables() (lumen.sources.base.jsonsource method)": [[59, "lumen.sources.base.JSONSource.get_tables"]], "to_spec() (lumen.sources.base.jsonsource method)": [[59, "lumen.sources.base.JSONSource.to_spec"]], "joinedsource (class in lumen.sources.base)": [[60, "lumen.sources.base.JoinedSource"]], "clear_cache() (lumen.sources.base.joinedsource method)": [[60, "lumen.sources.base.JoinedSource.clear_cache"]], "get() (lumen.sources.base.joinedsource method)": [[60, "lumen.sources.base.JoinedSource.get"]], "get_schema() (lumen.sources.base.joinedsource method)": [[60, "lumen.sources.base.JoinedSource.get_schema"]], "get_tables() (lumen.sources.base.joinedsource method)": [[60, "lumen.sources.base.JoinedSource.get_tables"]], "to_spec() (lumen.sources.base.joinedsource method)": [[60, "lumen.sources.base.JoinedSource.to_spec"]], "panelsessionsource (class in lumen.sources.base)": [[61, "lumen.sources.base.PanelSessionSource"]], "clear_cache() (lumen.sources.base.panelsessionsource method)": [[61, "lumen.sources.base.PanelSessionSource.clear_cache"]], "get() (lumen.sources.base.panelsessionsource method)": [[61, "lumen.sources.base.PanelSessionSource.get"]], "get_schema() (lumen.sources.base.panelsessionsource method)": [[61, "lumen.sources.base.PanelSessionSource.get_schema"]], "get_tables() (lumen.sources.base.panelsessionsource method)": [[61, "lumen.sources.base.PanelSessionSource.get_tables"]], "to_spec() (lumen.sources.base.panelsessionsource method)": [[61, "lumen.sources.base.PanelSessionSource.to_spec"]], "restsource (class in lumen.sources.base)": [[62, "lumen.sources.base.RESTSource"]], "clear_cache() (lumen.sources.base.restsource method)": [[62, "lumen.sources.base.RESTSource.clear_cache"]], "get() (lumen.sources.base.restsource method)": [[62, "lumen.sources.base.RESTSource.get"]], "get_schema() (lumen.sources.base.restsource method)": [[62, "lumen.sources.base.RESTSource.get_schema"]], "get_tables() (lumen.sources.base.restsource method)": [[62, "lumen.sources.base.RESTSource.get_tables"]], "to_spec() (lumen.sources.base.restsource method)": [[62, "lumen.sources.base.RESTSource.to_spec"]], "websitesource (class in lumen.sources.base)": [[63, "lumen.sources.base.WebsiteSource"]], "clear_cache() (lumen.sources.base.websitesource method)": [[63, "lumen.sources.base.WebsiteSource.clear_cache"]], "get() (lumen.sources.base.websitesource method)": [[63, "lumen.sources.base.WebsiteSource.get"]], "get_schema() (lumen.sources.base.websitesource method)": [[63, "lumen.sources.base.WebsiteSource.get_schema"]], "get_tables() (lumen.sources.base.websitesource method)": [[63, "lumen.sources.base.WebsiteSource.get_tables"]], "to_spec() (lumen.sources.base.websitesource method)": [[63, "lumen.sources.base.WebsiteSource.to_spec"]], "source (class in lumen.sources.base)": [[64, "lumen.sources.base.Source"]], "clear_cache() (lumen.sources.base.source method)": [[64, "lumen.sources.base.Source.clear_cache"]], "get() (lumen.sources.base.source method)": [[64, "lumen.sources.base.Source.get"]], "get_schema() (lumen.sources.base.source method)": [[64, "lumen.sources.base.Source.get_schema"]], "get_tables() (lumen.sources.base.source method)": [[64, "lumen.sources.base.Source.get_tables"]], "to_spec() (lumen.sources.base.source method)": [[64, "lumen.sources.base.Source.to_spec"]], "aggregate (class in lumen.transforms.base)": [[65, "lumen.transforms.base.Aggregate"]], "apply() (lumen.transforms.base.aggregate method)": [[65, "lumen.transforms.base.Aggregate.apply"]], "to_spec() (lumen.transforms.base.aggregate method)": [[65, "lumen.transforms.base.Aggregate.to_spec"]], "astype (class in lumen.transforms.base)": [[66, "lumen.transforms.base.Astype"]], "apply() (lumen.transforms.base.astype method)": [[66, "lumen.transforms.base.Astype.apply"]], "to_spec() (lumen.transforms.base.astype method)": [[66, "lumen.transforms.base.Astype.to_spec"]], "columns (class in lumen.transforms.base)": [[67, "lumen.transforms.base.Columns"]], "apply() (lumen.transforms.base.columns method)": [[67, "lumen.transforms.base.Columns.apply"]], "to_spec() (lumen.transforms.base.columns method)": [[67, "lumen.transforms.base.Columns.to_spec"]], "compute (class in lumen.transforms.base)": [[68, "lumen.transforms.base.Compute"]], "apply() (lumen.transforms.base.compute method)": [[68, "lumen.transforms.base.Compute.apply"]], "to_spec() (lumen.transforms.base.compute method)": [[68, "lumen.transforms.base.Compute.to_spec"]], "count (class in lumen.transforms.base)": [[69, "lumen.transforms.base.Count"]], "apply() (lumen.transforms.base.count method)": [[69, "lumen.transforms.base.Count.apply"]], "to_spec() (lumen.transforms.base.count method)": [[69, "lumen.transforms.base.Count.to_spec"]], "eval (class in lumen.transforms.base)": [[70, "lumen.transforms.base.Eval"]], "apply() (lumen.transforms.base.eval method)": [[70, "lumen.transforms.base.Eval.apply"]], "to_spec() (lumen.transforms.base.eval method)": [[70, "lumen.transforms.base.Eval.to_spec"]], "filter (class in lumen.transforms.base)": [[71, "lumen.transforms.base.Filter"]], "apply() (lumen.transforms.base.filter method)": [[71, "lumen.transforms.base.Filter.apply"]], "to_spec() (lumen.transforms.base.filter method)": [[71, "lumen.transforms.base.Filter.to_spec"]], "historytransform (class in lumen.transforms.base)": [[72, "lumen.transforms.base.HistoryTransform"]], "apply() (lumen.transforms.base.historytransform method)": [[72, "lumen.transforms.base.HistoryTransform.apply"]], "to_spec() (lumen.transforms.base.historytransform method)": [[72, "lumen.transforms.base.HistoryTransform.to_spec"]], "iloc (class in lumen.transforms.base)": [[73, "lumen.transforms.base.Iloc"]], "apply() (lumen.transforms.base.iloc method)": [[73, "lumen.transforms.base.Iloc.apply"]], "to_spec() (lumen.transforms.base.iloc method)": [[73, "lumen.transforms.base.Iloc.to_spec"]], "melt (class in lumen.transforms.base)": [[74, "lumen.transforms.base.Melt"]], "apply() (lumen.transforms.base.melt method)": [[74, "lumen.transforms.base.Melt.apply"]], "to_spec() (lumen.transforms.base.melt method)": [[74, "lumen.transforms.base.Melt.to_spec"]], "pivot (class in lumen.transforms.base)": [[75, "lumen.transforms.base.Pivot"]], "apply() (lumen.transforms.base.pivot method)": [[75, "lumen.transforms.base.Pivot.apply"]], "to_spec() (lumen.transforms.base.pivot method)": [[75, "lumen.transforms.base.Pivot.to_spec"]], "query (class in lumen.transforms.base)": [[76, "lumen.transforms.base.Query"]], "apply() (lumen.transforms.base.query method)": [[76, "lumen.transforms.base.Query.apply"]], "to_spec() (lumen.transforms.base.query method)": [[76, "lumen.transforms.base.Query.to_spec"]], "rename (class in lumen.transforms.base)": [[77, "lumen.transforms.base.Rename"]], "apply() (lumen.transforms.base.rename method)": [[77, "lumen.transforms.base.Rename.apply"]], "to_spec() (lumen.transforms.base.rename method)": [[77, "lumen.transforms.base.Rename.to_spec"]], "renameaxis (class in lumen.transforms.base)": [[78, "lumen.transforms.base.RenameAxis"]], "apply() (lumen.transforms.base.renameaxis method)": [[78, "lumen.transforms.base.RenameAxis.apply"]], "to_spec() (lumen.transforms.base.renameaxis method)": [[78, "lumen.transforms.base.RenameAxis.to_spec"]], "resetindex (class in lumen.transforms.base)": [[79, "lumen.transforms.base.ResetIndex"]], "apply() (lumen.transforms.base.resetindex method)": [[79, "lumen.transforms.base.ResetIndex.apply"]], "to_spec() (lumen.transforms.base.resetindex method)": [[79, "lumen.transforms.base.ResetIndex.to_spec"]], "sqlcolumns (class in lumen.transforms.sql)": [[80, "lumen.transforms.sql.SQLColumns"]], "apply() (lumen.transforms.sql.sqlcolumns method)": [[80, "lumen.transforms.sql.SQLColumns.apply"]], "to_spec() (lumen.transforms.sql.sqlcolumns method)": [[80, "lumen.transforms.sql.SQLColumns.to_spec"]], "sqldistinct (class in lumen.transforms.sql)": [[81, "lumen.transforms.sql.SQLDistinct"]], "apply() (lumen.transforms.sql.sqldistinct method)": [[81, "lumen.transforms.sql.SQLDistinct.apply"]], "to_spec() (lumen.transforms.sql.sqldistinct method)": [[81, "lumen.transforms.sql.SQLDistinct.to_spec"]], "sqlfilter (class in lumen.transforms.sql)": [[82, "lumen.transforms.sql.SQLFilter"]], "apply() (lumen.transforms.sql.sqlfilter method)": [[82, "lumen.transforms.sql.SQLFilter.apply"]], "to_spec() (lumen.transforms.sql.sqlfilter method)": [[82, "lumen.transforms.sql.SQLFilter.to_spec"]], "sqlgroupby (class in lumen.transforms.sql)": [[83, "lumen.transforms.sql.SQLGroupBy"]], "apply() (lumen.transforms.sql.sqlgroupby method)": [[83, "lumen.transforms.sql.SQLGroupBy.apply"]], "to_spec() (lumen.transforms.sql.sqlgroupby method)": [[83, "lumen.transforms.sql.SQLGroupBy.to_spec"]], "sqllimit (class in lumen.transforms.sql)": [[84, "lumen.transforms.sql.SQLLimit"]], "apply() (lumen.transforms.sql.sqllimit method)": [[84, "lumen.transforms.sql.SQLLimit.apply"]], "to_spec() (lumen.transforms.sql.sqllimit method)": [[84, "lumen.transforms.sql.SQLLimit.to_spec"]], "sqlminmax (class in lumen.transforms.sql)": [[85, "lumen.transforms.sql.SQLMinMax"]], "apply() (lumen.transforms.sql.sqlminmax method)": [[85, "lumen.transforms.sql.SQLMinMax.apply"]], "to_spec() (lumen.transforms.sql.sqlminmax method)": [[85, "lumen.transforms.sql.SQLMinMax.to_spec"]], "sample (class in lumen.transforms.base)": [[86, "lumen.transforms.base.Sample"]], "apply() (lumen.transforms.base.sample method)": [[86, "lumen.transforms.base.Sample.apply"]], "to_spec() (lumen.transforms.base.sample method)": [[86, "lumen.transforms.base.Sample.to_spec"]], "setindex (class in lumen.transforms.base)": [[87, "lumen.transforms.base.SetIndex"]], "apply() (lumen.transforms.base.setindex method)": [[87, "lumen.transforms.base.SetIndex.apply"]], "to_spec() (lumen.transforms.base.setindex method)": [[87, "lumen.transforms.base.SetIndex.to_spec"]], "sort (class in lumen.transforms.base)": [[88, "lumen.transforms.base.Sort"]], "apply() (lumen.transforms.base.sort method)": [[88, "lumen.transforms.base.Sort.apply"]], "to_spec() (lumen.transforms.base.sort method)": [[88, "lumen.transforms.base.Sort.to_spec"]], "stack (class in lumen.transforms.base)": [[89, "lumen.transforms.base.Stack"]], "apply() (lumen.transforms.base.stack method)": [[89, "lumen.transforms.base.Stack.apply"]], "to_spec() (lumen.transforms.base.stack method)": [[89, "lumen.transforms.base.Stack.to_spec"]], "sum (class in lumen.transforms.base)": [[90, "lumen.transforms.base.Sum"]], "apply() (lumen.transforms.base.sum method)": [[90, "lumen.transforms.base.Sum.apply"]], "to_spec() (lumen.transforms.base.sum method)": [[90, "lumen.transforms.base.Sum.to_spec"]], "unstack (class in lumen.transforms.base)": [[91, "lumen.transforms.base.Unstack"]], "apply() (lumen.transforms.base.unstack method)": [[91, "lumen.transforms.base.Unstack.apply"]], "to_spec() (lumen.transforms.base.unstack method)": [[91, "lumen.transforms.base.Unstack.to_spec"]], "transform (class in lumen.transforms.base)": [[92, "lumen.transforms.base.Transform"]], "apply() (lumen.transforms.base.transform method)": [[92, "lumen.transforms.base.Transform.apply"]], "to_spec() (lumen.transforms.base.transform method)": [[92, "lumen.transforms.base.Transform.to_spec"]], "apply() (lumen.transforms.base.project_lnglat method)": [[93, "lumen.transforms.base.project_lnglat.apply"]], "project_lnglat (class in lumen.transforms.base)": [[93, "lumen.transforms.base.project_lnglat"]], "to_spec() (lumen.transforms.base.project_lnglat method)": [[93, "lumen.transforms.base.project_lnglat.to_spec"]], "constant (class in lumen.variables.base)": [[94, "lumen.variables.base.Constant"]], "as_materialized() (lumen.variables.base.constant method)": [[94, "lumen.variables.base.Constant.as_materialized"]], "to_spec() (lumen.variables.base.constant method)": [[94, "lumen.variables.base.Constant.to_spec"]], "cookie (class in lumen.variables.base)": [[95, "lumen.variables.base.Cookie"]], "as_materialized() (lumen.variables.base.cookie method)": [[95, "lumen.variables.base.Cookie.as_materialized"]], "to_spec() (lumen.variables.base.cookie method)": [[95, "lumen.variables.base.Cookie.to_spec"]], "envvariable (class in lumen.variables.base)": [[96, "lumen.variables.base.EnvVariable"]], "as_materialized() (lumen.variables.base.envvariable method)": [[96, "lumen.variables.base.EnvVariable.as_materialized"]], "to_spec() (lumen.variables.base.envvariable method)": [[96, "lumen.variables.base.EnvVariable.to_spec"]], "header (class in lumen.variables.base)": [[97, "lumen.variables.base.Header"]], "as_materialized() (lumen.variables.base.header method)": [[97, "lumen.variables.base.Header.as_materialized"]], "to_spec() (lumen.variables.base.header method)": [[97, "lumen.variables.base.Header.to_spec"]], "parameter (class in lumen.variables.base)": [[98, "lumen.variables.base.Parameter"]], "as_materialized() (lumen.variables.base.parameter method)": [[98, "lumen.variables.base.Parameter.as_materialized"]], "to_spec() (lumen.variables.base.parameter method)": [[98, "lumen.variables.base.Parameter.to_spec"]], "urlquery (class in lumen.variables.base)": [[99, "lumen.variables.base.URLQuery"]], "as_materialized() (lumen.variables.base.urlquery method)": [[99, "lumen.variables.base.URLQuery.as_materialized"]], "to_spec() (lumen.variables.base.urlquery method)": [[99, "lumen.variables.base.URLQuery.to_spec"]], "userinfo (class in lumen.variables.base)": [[100, "lumen.variables.base.UserInfo"]], "as_materialized() (lumen.variables.base.userinfo method)": [[100, "lumen.variables.base.UserInfo.as_materialized"]], "to_spec() (lumen.variables.base.userinfo method)": [[100, "lumen.variables.base.UserInfo.to_spec"]], "widget (class in lumen.variables.base)": [[101, "lumen.variables.base.Widget"]], "as_materialized() (lumen.variables.base.widget method)": [[101, "lumen.variables.base.Widget.as_materialized"]], "to_spec() (lumen.variables.base.widget method)": [[101, "lumen.variables.base.Widget.to_spec"]], "variable (class in lumen.variables.base)": [[102, "lumen.variables.base.Variable"]], "as_materialized() (lumen.variables.base.variable method)": [[102, "lumen.variables.base.Variable.as_materialized"]], "to_spec() (lumen.variables.base.variable method)": [[102, "lumen.variables.base.Variable.to_spec"]], "altairview (class in lumen.views.base)": [[103, "lumen.views.base.AltairView"]], "get_data() (lumen.views.base.altairview method)": [[103, "lumen.views.base.AltairView.get_data"]], "get_panel() (lumen.views.base.altairview method)": [[103, "lumen.views.base.AltairView.get_panel"]], "get_value() (lumen.views.base.altairview method)": [[103, "lumen.views.base.AltairView.get_value"]], "servable() (lumen.views.base.altairview method)": [[103, "lumen.views.base.AltairView.servable"]], "show() (lumen.views.base.altairview method)": [[103, "lumen.views.base.AltairView.show"]], "to_spec() (lumen.views.base.altairview method)": [[103, "lumen.views.base.AltairView.to_spec"]], "update() (lumen.views.base.altairview method)": [[103, "lumen.views.base.AltairView.update"]], "downloadview (class in lumen.views.base)": [[104, "lumen.views.base.DownloadView"]], "get_data() (lumen.views.base.downloadview method)": [[104, "lumen.views.base.DownloadView.get_data"]], "get_panel() (lumen.views.base.downloadview method)": [[104, "lumen.views.base.DownloadView.get_panel"]], "get_value() (lumen.views.base.downloadview method)": [[104, "lumen.views.base.DownloadView.get_value"]], "servable() (lumen.views.base.downloadview method)": [[104, "lumen.views.base.DownloadView.servable"]], "show() (lumen.views.base.downloadview method)": [[104, "lumen.views.base.DownloadView.show"]], "to_spec() (lumen.views.base.downloadview method)": [[104, "lumen.views.base.DownloadView.to_spec"]], "update() (lumen.views.base.downloadview method)": [[104, "lumen.views.base.DownloadView.update"]], "indicatorview (class in lumen.views.base)": [[105, "lumen.views.base.IndicatorView"]], "get_data() (lumen.views.base.indicatorview method)": [[105, "lumen.views.base.IndicatorView.get_data"]], "get_panel() (lumen.views.base.indicatorview method)": [[105, "lumen.views.base.IndicatorView.get_panel"]], "get_value() (lumen.views.base.indicatorview method)": [[105, "lumen.views.base.IndicatorView.get_value"]], "servable() (lumen.views.base.indicatorview method)": [[105, "lumen.views.base.IndicatorView.servable"]], "show() (lumen.views.base.indicatorview method)": [[105, "lumen.views.base.IndicatorView.show"]], "to_spec() (lumen.views.base.indicatorview method)": [[105, "lumen.views.base.IndicatorView.to_spec"]], "update() (lumen.views.base.indicatorview method)": [[105, "lumen.views.base.IndicatorView.update"]], "panel (class in lumen.views.base)": [[106, "lumen.views.base.Panel"]], "get_data() (lumen.views.base.panel method)": [[106, "lumen.views.base.Panel.get_data"]], "get_panel() (lumen.views.base.panel method)": [[106, "lumen.views.base.Panel.get_panel"]], "get_value() (lumen.views.base.panel method)": [[106, "lumen.views.base.Panel.get_value"]], "servable() (lumen.views.base.panel method)": [[106, "lumen.views.base.Panel.servable"]], "show() (lumen.views.base.panel method)": [[106, "lumen.views.base.Panel.show"]], "to_spec() (lumen.views.base.panel method)": [[106, "lumen.views.base.Panel.to_spec"]], "update() (lumen.views.base.panel method)": [[106, "lumen.views.base.Panel.update"]], "perspectiveview (class in lumen.views.base)": [[107, "lumen.views.base.PerspectiveView"]], "get_data() (lumen.views.base.perspectiveview method)": [[107, "lumen.views.base.PerspectiveView.get_data"]], "get_panel() (lumen.views.base.perspectiveview method)": [[107, "lumen.views.base.PerspectiveView.get_panel"]], "get_value() (lumen.views.base.perspectiveview method)": [[107, "lumen.views.base.PerspectiveView.get_value"]], "servable() (lumen.views.base.perspectiveview method)": [[107, "lumen.views.base.PerspectiveView.servable"]], "show() (lumen.views.base.perspectiveview method)": [[107, "lumen.views.base.PerspectiveView.show"]], "to_spec() (lumen.views.base.perspectiveview method)": [[107, "lumen.views.base.PerspectiveView.to_spec"]], "update() (lumen.views.base.perspectiveview method)": [[107, "lumen.views.base.PerspectiveView.update"]], "stringview (class in lumen.views.base)": [[108, "lumen.views.base.StringView"]], "get_data() (lumen.views.base.stringview method)": [[108, "lumen.views.base.StringView.get_data"]], "get_panel() (lumen.views.base.stringview method)": [[108, "lumen.views.base.StringView.get_panel"]], "get_value() (lumen.views.base.stringview method)": [[108, "lumen.views.base.StringView.get_value"]], "servable() (lumen.views.base.stringview method)": [[108, "lumen.views.base.StringView.servable"]], "show() (lumen.views.base.stringview method)": [[108, "lumen.views.base.StringView.show"]], "to_spec() (lumen.views.base.stringview method)": [[108, "lumen.views.base.StringView.to_spec"]], "update() (lumen.views.base.stringview method)": [[108, "lumen.views.base.StringView.update"]], "table (class in lumen.views.base)": [[109, "lumen.views.base.Table"]], "get_data() (lumen.views.base.table method)": [[109, "lumen.views.base.Table.get_data"]], "get_panel() (lumen.views.base.table method)": [[109, "lumen.views.base.Table.get_panel"]], "get_value() (lumen.views.base.table method)": [[109, "lumen.views.base.Table.get_value"]], "servable() (lumen.views.base.table method)": [[109, "lumen.views.base.Table.servable"]], "show() (lumen.views.base.table method)": [[109, "lumen.views.base.Table.show"]], "to_spec() (lumen.views.base.table method)": [[109, "lumen.views.base.Table.to_spec"]], "update() (lumen.views.base.table method)": [[109, "lumen.views.base.Table.update"]], "get_data() (lumen.views.base.hvplotuiview method)": [[110, "lumen.views.base.hvPlotUIView.get_data"]], "get_panel() (lumen.views.base.hvplotuiview method)": [[110, "lumen.views.base.hvPlotUIView.get_panel"]], "get_value() (lumen.views.base.hvplotuiview method)": [[110, "lumen.views.base.hvPlotUIView.get_value"]], "hvplotuiview (class in lumen.views.base)": [[110, "lumen.views.base.hvPlotUIView"]], "servable() (lumen.views.base.hvplotuiview method)": [[110, "lumen.views.base.hvPlotUIView.servable"]], "show() (lumen.views.base.hvplotuiview method)": [[110, "lumen.views.base.hvPlotUIView.show"]], "to_spec() (lumen.views.base.hvplotuiview method)": [[110, "lumen.views.base.hvPlotUIView.to_spec"]], "update() (lumen.views.base.hvplotuiview method)": [[110, "lumen.views.base.hvPlotUIView.update"]], "get_data() (lumen.views.base.hvplotview method)": [[111, "lumen.views.base.hvPlotView.get_data"]], "get_panel() (lumen.views.base.hvplotview method)": [[111, "lumen.views.base.hvPlotView.get_panel"]], "get_plot() (lumen.views.base.hvplotview method)": [[111, "lumen.views.base.hvPlotView.get_plot"]], "get_value() (lumen.views.base.hvplotview method)": [[111, "lumen.views.base.hvPlotView.get_value"]], "hvplotview (class in lumen.views.base)": [[111, "lumen.views.base.hvPlotView"]], "servable() (lumen.views.base.hvplotview method)": [[111, "lumen.views.base.hvPlotView.servable"]], "show() (lumen.views.base.hvplotview method)": [[111, "lumen.views.base.hvPlotView.show"]], "to_spec() (lumen.views.base.hvplotview method)": [[111, "lumen.views.base.hvPlotView.to_spec"]], "update() (lumen.views.base.hvplotview method)": [[111, "lumen.views.base.hvPlotView.update"]], "view (class in lumen.views.base)": [[112, "lumen.views.base.View"]], "get_data() (lumen.views.base.view method)": [[112, "lumen.views.base.View.get_data"]], "get_panel() (lumen.views.base.view method)": [[112, "lumen.views.base.View.get_panel"]], "get_value() (lumen.views.base.view method)": [[112, "lumen.views.base.View.get_value"]], "servable() (lumen.views.base.view method)": [[112, "lumen.views.base.View.servable"]], "show() (lumen.views.base.view method)": [[112, "lumen.views.base.View.show"]], "to_spec() (lumen.views.base.view method)": [[112, "lumen.views.base.View.to_spec"]], "update() (lumen.views.base.view method)": [[112, "lumen.views.base.View.update"]]}}) \ No newline at end of file diff --git a/site.webmanifest b/site.webmanifest new file mode 100644 index 00000000..4af06141 --- /dev/null +++ b/site.webmanifest @@ -0,0 +1,27 @@ +{ + "name": "Lumen 1.3.1 documentation", + "short_name": "Lumen 1.3.1 documentation", + "start_url": "index.html", + "icons": [ + { + "src": "_static/icons/icon-32x32.png", + "type": "image/png", + "sizes": "32x32" + }, + { + "src": "_static/icons/icon-192x192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "_static/icons/icon-512x512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "display": "standalone", + "scope": "/", + "background_color": "#fdfdfd", + "theme_color": "#0072B5", + "orientation": "any" +} \ No newline at end of file diff --git a/ui/configuration.html b/ui/configuration.html new file mode 100644 index 00000000..a53c3c61 --- /dev/null +++ b/ui/configuration.html @@ -0,0 +1,383 @@ + + + + + + + + +Configuration — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

Configuration#

+

Configuring the Lumen Builder UI is quite straightforward. In the directory where you will be launching the lumen builder from create a components directory with the following structure.

+
.
+│   config.yml
+│───components
+│  │───dashboards
+│  │      example.yml
+│  │      example.png
+│  │      ...
+│  │───launchers
+│  │      launcher.yml
+│  │      ...
+│  │───sources
+│  │      source.yml
+│  │      source.png
+│  │      ...
+│  │───variables
+│  │      vars.yml
+│  │      ...
+│  │───views
+│  │      view.yml
+│  │      view.png
+│  │      ...
+
+
+
+

Note

+

The first time you launch lumen builder in a directory it will set up this directory for you.

+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + +
+ +
+ + \ No newline at end of file diff --git a/ui/index.html b/ui/index.html new file mode 100644 index 00000000..00a5f0c8 --- /dev/null +++ b/ui/index.html @@ -0,0 +1,503 @@ + + + + + + + + +UI — Lumen 1.3.1 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ +
+
+
+ + + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+

UI#

+

The Builder UI for Lumen makes it possible to build entire dashboards using a visual UI. The Builder is highly configurable and can be pre-populated with existing dashboards and pre-defined components, making it easy to edit or assemble a new dashboard using data sources, views, filters and variables that have already been set up.

+
+

Launching the Builder UI#

+

To launch into the builder UI you simply run:

+
lumen builder
+
+
+

in the directory where you have placed your configuration.

+
+
+

Step-by-step#

+

This step-by-step guide will take you through the process of building a dashboard with the Builder UI.

+ +
+

Config Editor#

+

The Config editor lets you control high-level configuration options for your new dashboard such as the title, logo, template and theme.

+
+ +
+

The Config editor includes a number of fields such as the title, logo, template and theme for your new dashboard.#

+
+
+
+

Tip

+

If you are unsure what a particular configuration option or parameter does try hovering over the widget to see additional explanation.

+
+
+
+

Variable Editor#

+

The Variable editor is the first step that lets you declare actual components for your dashboard. Declaring components for your dashboard usually follows the same steps, either select pre-configured components or declare the type and name of a new component and then use the widget forms that are created to configure the new component. Variable definitions are useful to set up all kinds of dynamic behaviors in your dashboards, whether it is simply to fetch credentials of your data sources from an environment variable or to declare widgets that will let you dynamically control updates to various other components.

+
+The Variable editor allows selecting, adding and removing +
+

The Variable editor allows selecting, adding and removing variables definitions from your dashboard.#

+
+
+
+

Tip

+

Throughout the Builder UI pre-configured sources can easily be added to your dashboard simply by enabling the toggle at the top-right of each gallery item.

+
+
+
+

Source Editor#

+

The Source editor is an important step towards building your dashboard as it will declare all the data sources for your dashboard. You will have the choice to pick between pre-configured sources that have been defined on your Builder deployment or define your own source.

+
+The Source Editor display a gallery to add pre-configured sources or define a new source to be added to the dashboard. +
+

The Source Editor display a gallery to add pre-configured sources or define a new source to be added to the dashboard.#

+
+
+

When editing a Source or defining a new one a modal will pop up that lets you define the parameters of the Source and preview the various tables returned by the source.

+
+A preview of a `FileSource` that points to a CSV file of penguins.csv containing information about individual penguins collected by Palmer et al. +
+

A preview of a FileSource that points to a CSV file of penguins.csv containing information about individual penguins collected by Palmer et al.#

+
+
+
+
+

View Editor#

+

Once you have defined your data sources it is time to declare some views to add to your dashboard. The View editor (much like the Source and Variable` editors before it) will let you either select existing pre-configured views or declare entirely new views.

+
+The View Editor display a gallery to add pre-configured views or define a new view to be added to the dashboard. +
+

The View Editor display a gallery to add pre-configured views or define a new views to be added to the dashboard.#

+
+
+

When adding a new View or editing an existing one the familiar modal will pop up. One you have selected the Source and table that you want to create a View from, select the type of view you want to create, give it a name and then use the editor that opens to configure the parameters of your view. As an example, below we have created an hvPlotView using the hvPlot Explorer UI:

+
+An example of declaring a new `hvPlotView` built using the hvPlot Explorer UI. +
+

An example of declaring a new hvPlotView built using the hvPlot Explorer UI.#

+
+
+
+
+

Layout Editor#

+

The Layout editor allows configured one or more layout groups to be added to your dashboard.

+
+An example of declaring a new `hvPlotView` built using the hvPlot Explorer UI. +
+

In the layout editor you can add new layout groups or toggle existing layout groups to be included or not.#

+
+
+

When adding a new layout group a modal will pop up that will allow you to define a name for you new layout group and then select which views to include and how they should be arranged.

+
+Configuring a layout group containing two plots. +
+

Configuring a layout group containing two plots visualizing the penguins dataset.#

+
+
+
+
+

Launcher#

+

The launcher page is the final step in your journey towards declaring a dashboard. Depending on how your Lumen Builder deployment has been configured this will offer a number of options for either downloading the dashboard YAML specification, previewing it locally or deploying it.

+ +

If we select the YAML launcher it will take us to a page that previews the YAML specification and offers a button to download it.

+
+The YAML launcher component display a preview of the dashboard specification and allows you to download it. +
+

The YAML launcher component display a preview of the dashboard specification and allows you to download it.#

+
+
+

If we instead decide to preview it (and the Lumen Builder is running locally) it will pop up a new browser tab with a preview of the application we just built:

+
+A preview of the dashboard that we built in this step-by-step guide. +
+

A preview of the dashboard that we built in this step-by-step guide.#

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+ + + + + + \ No newline at end of file