PageSourceSearch

https://hubverse.io/tools/dashboards.html

html hubverse.io collected 2026-10-03 21:38:37 UTC 36,560 bytes, 881 lines download raw bytes

1<!DOCTYPE html>
2<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head>
3
4<meta charset="utf-8">
5<meta name="generator" content="quarto-1.10.18">
6
7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
8
9
10<title>Dashboards – hubverse</title>
11<style>
12/* Default styles provided by pandoc.
13** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
14*/
15span.smallcaps{font-variant: small-caps;}
16div.columns{display: flex; gap: 1.5em;}
17div.column{flex: auto;}
18@media screen {
19div.columns{gap: min(4vw, 1.5em);}
20div.column{overflow-x: auto;}
21}
22div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
23ul.task-list{list-style: none;}
24ul.task-list li input[type="checkbox"] {
25  width: 0.8em;
26  margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 
27  vertical-align: middle;
28}
29</style>
30
31
32<script src="../site_libs/quarto-nav/quarto-nav.js"></script>
vendor: 1 bytes, line 32
32
33<script src="../site_libs/quarto-nav/headroom.min.js"></script>
vendor: 1 bytes, line 33
33
34<script src="../site_libs/clipboard/clipboard.min.js"></script>
vendor: 1 bytes, line 34
34
35<script src="../site_libs/quarto-search/autocomplete.umd.js"></script>
vendor: 1 bytes, line 35
35
36<script src="../site_libs/quarto-search/fuse.min.js"></script>
vendor: 1 bytes, line 36
36
37<script src="../site_libs/quarto-search/quarto-search.js"></script>
37
38<meta name="quarto:offset" content="../">
39<link href="..//brand/logo/logo.png" rel="icon" type="image/png">
40<script src="../site_libs/quarto-html/quarto.js" type="module"></script>
vendor: 1 bytes, line 40
40
41<script src="../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script>
vendor: 1 bytes, line 41
41
42<script src="../site_libs/quarto-html/popper.min.js"></script>
vendor: 1 bytes, line 42
42
43<script src="../site_libs/quarto-html/tippy.umd.min.js"></script>
vendor: 1 bytes, line 43
43
44<script src="../site_libs/quarto-html/anchor.min.js"></script>
44
45<link href="../site_libs/quarto-html/tippy.css" rel="stylesheet">
46<link href="../site_libs/quarto-html/quarto-syntax-highlighting-64a204ab8560d761af7679ceaba22944.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles">
47<link href="../site_libs/quarto-html/quarto-syntax-highlighting-dark-b85bc7c33db8c58e0ec93c3465666fed.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles">
48<link href="../site_libs/quarto-html/quarto-syntax-highlighting-64a204ab8560d761af7679ceaba22944.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles">
49<script src="../site_libs/bootstrap/bootstrap.min.js"></script>
49
50<link href="../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet">
51<link href="../site_libs/bootstrap/bootstrap-faa19e120cee703ce4399906c6e9bee7.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light">
52<link href="../site_libs/bootstrap/bootstrap-dark-faa19e120cee703ce4399906c6e9bee7.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="light">
53<link href="../site_libs/bootstrap/bootstrap-faa19e120cee703ce4399906c6e9bee7.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light">
54<link href="../site_libs/quarto-contrib/fontawesome6-6.7.2/all.min.css" rel="stylesheet">
55<link href="../site_libs/quarto-contrib/fontawesome6-6.7.2/latex-fontsize.css" rel="stylesheet">
56<script id="quarto-search-options" type="application/json">{
57  "location": "navbar",
58  "copy-button": false,
59  "collapse-after": 3,
60  "panel-placement": "end",
61  "type": "overlay",
62  "limit": 50,
63  "keyboard-shortcut": [
64    "f",
65    "/",
66    "s"
67  ],
68  "show-item-context": false,
69  "language": {
70    "search-no-results-text": "No results",
71    "search-matching-documents-text": "matching documents",
72    "search-copy-link-title": "Copy link to search",
73    "search-hide-matches-text": "Hide additional matches",
74    "search-more-match-text": "more match in this document",
75    "search-more-matches-text": "more matches in this document",
76    "search-clear-button-title": "Clear",
77    "search-text-placeholder": "",
78    "search-detached-cancel-button-title": "Cancel",
79    "search-submit-button-title": "Submit",
80    "search-label": "Search"
81  }
82}</script>
82
83<!-- Privacy-friendly analytics by Plausible -->
84<script async="" src="https://plausible.io/js/pa-Qtr0-pdxejuvymNBgYMIj.js"></script>
vendor: 1 bytes, line 84
84
85<script>
86  window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
87  plausible.init()
88</script>
88
89
90
91<link rel="stylesheet" href="../styles.css">
92</head>
93
94<body class="nav-fixed quarto-light">
95
96<div id="quarto-search-results"></div>
97  <header id="quarto-header" class="headroom fixed-top">
98    <div id="quarto-announcement" data-announcement-id="8501bbe9620e8dff98c7b235d38034d7" class="alert alert-info hidden"><i class="bi bi-baloon quarto-announcement-icon"></i><div class="quarto-announcement-content">
99<p>Welcome to the hubverse. Discover <a href="../community/index.html">our community</a>, get involved, or reach out to share your feedback.</p>
100</div><i class="bi bi-x-lg quarto-announcement-action"></i></div>
101    <nav class="navbar navbar-expand-lg " data-bs-theme="dark">
102      <div class="navbar-container container-fluid">
103      <div class="navbar-brand-container mx-auto">
104    <a href="../index.html" class="navbar-brand navbar-brand-logo">
105    <img src="../brand/logo/logo.png" alt="" class="navbar-logo light-content">
106    <img src="../brand/logo/logo.png" alt="" class="navbar-logo dark-content">
107    </a>
108    <a class="navbar-brand" href="../index.html">
109    <span class="navbar-title">hubverse</span>
110    </a>
111  </div>
112            <div id="quarto-search" class="" title="Search"></div>
113          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" role="menu" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }">
114  <span class="navbar-toggler-icon"></span>
115</button>
116          <div class="collapse navbar-collapse" id="navbarCollapse">
117            <ul class="navbar-nav navbar-nav-scroll ms-auto">
118  <li class="nav-item">
119    <a class="nav-link" href="../index.html"> 
120<span class="menu-text">Home</span></a>
121  </li>  
122  <li class="nav-item dropdown ">
123    <a class="nav-link dropdown-toggle" href="#" id="nav-menu-get-started" role="link" data-bs-toggle="dropdown" aria-expanded="false">
124 <span class="menu-text"><strong>Get started</strong></span>
125    </a>
126    <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="nav-menu-get-started">    
127        <li>
128    <a class="dropdown-item" href="../quickstart/index.html"><i class="bi bi-question-circle" role="img">
129</i> 
130 <span class="dropdown-text">What is a modeling hub?</span></a>
131  </li>  
132        <li>
133    <a class="dropdown-item" href="../quickstart/create.html"><i class="bi bi-diagram-3" role="img">
134</i> 
135 <span class="dropdown-text">Create a hub</span></a>
136  </li>  
137        <li>
138    <a class="dropdown-item" href="../quickstart/submit.html"><i class="bi bi-file-earmark-arrow-up" role="img">
139</i> 
140 <span class="dropdown-text">Submit model output</span></a>
141  </li>  
142        <li>
143    <a class="dropdown-item" href="../quickstart/analyze.html"><i class="bi bi-graph-up" role="img">
144</i> 
145 <span class="dropdown-text">Analyze data</span></a>
146  </li>  
147        <li>
148    <a class="dropdown-item" href="../quickstart/develop.html"><i class="bi bi-braces" role="img">
149</i> 
150 <span class="dropdown-text">Develop software</span></a>
151  </li>  
152        <li><hr class="dropdown-divider"></li>
153        <li>
154    <a class="dropdown-item" href="../quickstart/support-consulting.html"><i class="bi bi-headset" role="img">
155</i> 
156 <span class="dropdown-text">Consulting support</span></a>
157  </li>  
158    </ul>
159  </li>
160  <li class="nav-item dropdown ">
161    <a class="nav-link dropdown-toggle" href="#" id="nav-menu-tools" role="link" data-bs-toggle="dropdown" aria-expanded="false">
162 <span class="menu-text">Tools</span>
163    </a>
164    <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="nav-menu-tools">    
165        <li>
166    <a class="dropdown-item" href="../tools/data.html"><i class="bi bi-compass" role="img">
167</i> 
168 <span class="dropdown-text">Data standards</span></a>
169  </li>  
170        <li>
171    <a class="dropdown-item" href="../tools/software.html"><i class="bi bi-tools" role="img">
172</i> 
173 <span class="dropdown-text">Software</span></a>
174  </li>  
175        <li>
176    <a class="dropdown-item" href="../tools/dashboards.html"><i class="bi bi-speedometer" role="img">
177</i> 
178 <span class="dropdown-text">Dashboards</span></a>
179  </li>  
180    </ul>
181  </li>
182  <li class="nav-item dropdown ">
183    <a class="nav-link dropdown-toggle" href="#" id="nav-menu-community" role="link" data-bs-toggle="dropdown" aria-expanded="false">
184 <span class="menu-text">Community</span>
185    </a>
186    <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="nav-menu-community">    
187        <li>
188    <a class="dropdown-item" href="../community/index.html">
189 <span class="dropdown-text"><i class="fa-solid fa-people-line" aria-label="people-line"></i> &nbsp;Community</span></a>
190  </li>  
191        <li>
192    <a class="dropdown-item" href="../community/hubs.html">
193 <span class="dropdown-text"><i class="fa-solid fa-list" aria-label="list"></i> &nbsp;&nbsp;List of hubs</span></a>
194  </li>  
195        <li>
196    <a class="dropdown-item" href="../community/contributors.html">
197 <span class="dropdown-text"><i class="fa-solid fa-pencil" aria-label="pencil"></i> &nbsp;&nbsp;Contributors</span></a>
198  </li>  
199        <li>
200    <a class="dropdown-item" href="../contact.html">
201 <span class="dropdown-text"><i class="fa-solid fa-address-card" aria-label="address-card"></i> &nbsp;&nbsp;Contact</span></a>
202  </li>  
203        <li><hr class="dropdown-divider"></li>
204        <li>
205    <a class="dropdown-item" href="../about.html"><i class="bi bi-info-circle-fill" role="img">
206</i> 
207 <span class="dropdown-text">
207About the hubverse</span></a>
208  </li>  
209    </ul>
210  </li>
211  <li class="nav-item dropdown ">
212    <a class="nav-link dropdown-toggle" href="#" id="nav-menu-resources" role="link" data-bs-toggle="dropdown" aria-expanded="false">
213 <span class="menu-text">Resources</span>
214    </a>
215    <ul class="dropdown-menu dropdown-menu-end" aria-labelledby="nav-menu-resources">    
216        <li>
217    <a class="dropdown-item" href="../terminology.html"><i class="bi bi-book" role="img">
218</i> 
219 <span class="dropdown-text">Terminology</span></a>
220  </li>  
221        <li>
222    <a class="dropdown-item" href="https://docs.hubverse.io/">
223 <span class="dropdown-text"><i class="fa-solid fa-book" aria-label="book"></i> &nbsp;&nbsp;Documentation <i class="fa-solid fa-arrow-up-right-from-square" aria-label="arrow-up-right-from-square"></i></span></a>
224  </li>  
225        <li>
226    <a class="dropdown-item" href="../funding.html">
227 <span class="dropdown-text"><i class="fa-solid fa-coins" aria-label="coins"></i> &nbsp;&nbsp;Funding</span></a>
228  </li>  
229        <li>
230    <a class="dropdown-item" href="../researchtalks.html">
231 <span class="dropdown-text"><i class="fa-solid fa-user-graduate" aria-label="user-graduate"></i> &nbsp;Research &amp; talks</span></a>
232  </li>  
233        <li>
234    <a class="dropdown-item" href="../trainings.html">
235 <span class="dropdown-text"><i class="fa-solid fa-laptop-code" aria-label="laptop-code"></i> &nbsp;Trainings</span></a>
236  </li>  
237        <li>
238    <a class="dropdown-item" href="../cite.html">
239 <span class="dropdown-text"><i class="fa-solid fa-quote-left" aria-label="quote-left"></i> &nbsp;&nbsp;How to cite</span></a>
240  </li>  
241        <li>
242    <a class="dropdown-item" href="../CONTRIBUTING.html"><i class="bi bi-github" role="img">
243</i> 
244 <span class="dropdown-text">Contributing to the site</span></a>
245  </li>  
246        <li><hr class="dropdown-divider"></li>
247        <li>
248    <a class="dropdown-item" href="../quickstart/support-consulting.html"><i class="bi bi-headset" role="img">
249</i> 
250 <span class="dropdown-text">Consulting support</span></a>
251  </li>  
252    </ul>
253  </li>
254  <li class="nav-item compact">
255    <a class="nav-link" href="https://github.com/hubverse-org"> <i class="bi bi-github" role="img" aria-label="hubverse GitHub organization">
256</i> 
257<span class="menu-text"></span></a>
258  </li>  
259</ul>
260          </div> <!-- /navcollapse -->
261            <div class="quarto-navbar-tools">
262</div>
263      </div> <!-- /container-fluid -->
264    </nav>
265</header>
266<!-- content -->
267<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar">
268<!-- sidebar -->
269<!-- margin-sidebar -->
270    <div id="quarto-margin-sidebar" class="sidebar margin-sidebar">
271        <nav id="TOC" role="doc-toc" class="toc-active">
272    <h2 id="toc-title">On this page</h2>
273   
274  <ul>
275  <li><a href="#introduction" id="toc-introduction" class="nav-link active" data-scroll-target="#introduction">Introduction</a></li>
276  <li><a href="#examples" id="toc-examples" class="nav-link" data-scroll-target="#examples">Examples</a></li>
277  </ul>
278<div class="toc-actions"><ul><li><a href="https://github.com/hubverse-org/hubverse-site/edit/main/tools/dashboards.qmd" class="toc-action"><i class="bi bi-github"></i>Edit this page</a></li><li><a href="https://github.com/hubverse-org/hubverse-site/blob/main/tools/dashboards.qmd" class="toc-action"><i class="bi empty"></i>View source</a></li><li><a href="https://github.com/hubverse-org/hubverse-site/issues/new" class="toc-action"><i class="bi empty"></i>Report an issue</a></li></ul></div></nav>
279    </div>
280<!-- main -->
281<main class="content" id="quarto-document-content">
282<script>
283  const path = window.location.pathname;
284  const isDev = window.location.hostname === "localhost";
285
286  // Use console.log for debugging:
287  // console.log("🔍 docs-redirect script loaded");
288  // console.log("🚧 Current path:", path);
289
290  const redirects = {
291    "overview/history.html": "https://hubverse.io/about.html#history",
292    "overview/contributors.html": "https://hubverse.io/community/contributors.html",
293    "overview/contribute.html": "https://hubverse.io/community/",
294    "overview/who-we-are.html": "https://hubverse.io/about.html",
295    "overview/scope.html": "https://hubverse.io/about.html#scope",
296    "overview/support-consulting.html": "https://hubverse.io/quickstart/support-consulting.html",
297    "overview/data-storage.html": "https://docs.hubverse.io/en/latest/user-guide/data-storage.html",
298    "user-guide/presentations.html": "https://hubverse.io/researchtalks.html"
299  };
300
301  const versionedPathRegex = /^\/en\/(\d+\.\d+\.\d+|latest|stable)\//;
302  const isVersionedPath = versionedPathRegex.test(path);
303  const isLatestOrStable = path.startsWith("/en/latest") || path.startsWith("/en/stable");
304
305  let redirected = false;
306
307  if (isDev || isVersionedPath) {
308    if (isLatestOrStable) {
309      for (const [key, url] of Object.entries(redirects)) {
310        if (path.includes(key)) {
311          // console.log("🔀 Redirecting to:", url);
312          window.location.href = url;
313          redirected = true;
314          break;
315        }
316      }
317    }
318  }
319
320  if (!redirected && isVersionedPath) {
321    const fallback = "https://docs.hubverse.io" + path;
322    // console.log("🔀 Redirecting to fallback docs:", fallback);
323    window.location.href = fallback;
324  }
325</script>
325
326
327
328<header id="title-block-header" class="quarto-title-block default">
329<div class="quarto-title">
330<h1 class="title"><i class="bi bi-speedometer"></i> Dashboards</h1>
331</div>
332
333
334
335<div class="quarto-title-meta">
336
337    
338  
339    
340  </div>
341  
342
343
344</header>
345
346
347<section id="introduction" class="level2">
348<h2 class="anchored" data-anchor-id="introduction">Introduction</h2>
349<div class="callout callout-style-default callout-note callout-titled">
350<div class="callout-header d-flex align-content-center">
351<div class="callout-icon-container">
352<i class="callout-icon"></i>
353</div>
354<div class="callout-title-container flex-fill">
355Note
356</div>
357</div>
358<div class="callout-body-container callout-body">
359<p>The current iteration of the dashboard is intended for modelers and hub administrators, who are more likely to be familiar with modeling exercise and evaluation methods.</p>
360<p>This is not yet intended for use by decision-makers as there is more information here than they may want or need.</p>
361</div>
362</div>
363<p>The hubverse dashboard is an experimental landing page and plug-and-play visualization for hub data. Each dashboard is an independent repository for any given hub.</p>
364<div id="fig-dashboards" class="quarto-layout-panel">
365<figure class="quarto-float quarto-float-fig figure">
366<div aria-describedby="fig-dashboards-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
367<div class="quarto-layout-row">
368<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: flex-start;">
369<div class="quarto-figure quarto-figure-center">
370<figure class="figure">
371<p><img src="../includes/img/dashboard-forecast.png" class="img-fluid figure-img"></p>
372<figcaption>forecasts</figcaption>
373</figure>
374</div>
375</div>
376<div class="quarto-layout-cell" style="flex-basis: 50.0%;justify-content: flex-start;">
377<div class="quarto-figure quarto-figure-center">
378<figure class="figure">
379<p><img src="../includes/img/dashboard-eval-heat.png" class="img-fluid figure-img"></p>
380<figcaption>evaluations</figcaption>
381</figure>
382</div>
383</div>
384</div>
385</div>
386<figcaption class="quarto-float-caption-bottom quarto-float-caption quarto-float-fig" id="fig-dashboards-caption-0ceaefa1-69ba-4598-a22c-09a6ac19f8ca">
387Figure&nbsp;1: Forecast and Evaluation dashboards for the FluSight forecast hub.
388</figcaption>
389</figure>
390</div>
391<p><a href="https://docs.hubverse.io/en/latest/user-guide/dashboards.html" class="btn btn-outline-dark ms-auto"><i class="fa-solid fa-book" aria-label="book"></i> Get started with dashboards</a></p>
392</section>
393<section id="examples" class="level2">
394<h2 class="anchored" data-anchor-id="examples">Examples</h2>
395<p>Some examples of dashboards are:</p>
396<table class="caption-top table">
397<thead>
398<tr class="header">
399<th>Hub</th>
400<th>Dashboard</th>
401</tr>
402</thead>
403<tbody>
404<tr class="odd">
405<td><a href="https://github.com/reichlab/flu-metrocast">flu-metrocast</a></td>
406<td><a href="https://reichlab.io/metrocast-dashboard" class="uri">https://reichlab.io/metrocast-dashboard</a></td>
407</tr>
408<tr class="even">
409<td><a href="https://github.com/cdcepi/FluSight-Forecast-hub">FluSight-forecast-hub</a></td>
410<td><a href="https://reichlab.io/flusight-dashboard" class="uri">https://reichlab.io/flusight-dashboard</a></td>
411</tr>
412<tr class="odd">
413<td><a href="https://github.com/CDCgov/covid19-forecast-hub">COVID-19 Forecast Hub</a></td>
414<td><a href="https://reichlab.io/covidhub-dashboard" class="uri">https://reichlab.io/covidhub-dashboard</a></td>
415</tr>
416<tr class="even">
417<td><a href="https://github.com/reichlab/variant-nowcast-hub">variant-nowcast-hub</a></td>
418<td><a href="https://reichlab.io/variant-nowcast-hub-dashboard" class="uri">https://reichlab.io/variant-nowcast-hub-dashboard</a></td>
419</tr>
420</tbody>
421</table>
422<div class="page-nav">
423<div class="prev-page">
424<p><a href="../tools/software.html" class="prev-arrow">‹</a></p>
425<p><a href="../tools/software.html" class="prev-label">Previous</a></p>
426<p><a href="../tools/software.html" class="prev-title"><strong>Software</strong></a></p>
427</div>
428<div class="next-page">
429<p><a href="../community/index.html" class="next-label">Next</a></p>
430<p><a href="../community/index.html" class="next-arrow">›</a></p>
431<p><a href="../community/index.html" class="next-title"><strong>Community</strong></a></p>
432</div>
433</div>
434
435
436</section>
437
438</main> <!-- /main -->
439<script id="quarto-html-after-body" type="application/javascript">
440  window.document.addEventListener("DOMContentLoaded", function (event) {
441    const icon = "";
442    const anchorJS = new window.AnchorJS();
443    anchorJS.options = {
444      placement: 'right',
445      icon: icon
446    };
447    anchorJS.add('.anchored');
448    const isCodeAnnotation = (el) => {
449      for (const clz of el.classList) {
450        if (clz.startsWith('code-annotation-')) {                     
451          return true;
452        }
453      }
454      return false;
455    }
456    const onCopySuccess = function(e) {
457      // button target
458      const button = e.trigger;
459      // don't keep focus
460      button.blur();
461      // flash "checked"
462      button.classList.add('code-copy-button-checked');
463      var currentTitle = button.getAttribute("title");
464      button.setAttribute("title", "Copied!");
465      let tooltip;
466      if (window.bootstrap) {
467        button.setAttribute("data-bs-toggle", "tooltip");
468        button.setAttribute("data-bs-placement", "left");
469        button.setAttribute("data-bs-title", "Copied!");
470        tooltip = new bootstrap.Tooltip(button, 
471          { trigger: "manual", 
472            customClass: "code-copy-button-tooltip",
473            offset: [0, -8]});
474        tooltip.show();    
475      }
476      setTimeout(function() {
477        if (tooltip) {
478          tooltip.hide();
479          button.removeAttribute("data-bs-title");
480          button.removeAttribute("data-bs-toggle");
481          button.removeAttribute("data-bs-placement");
482        }
483        button.setAttribute("title", currentTitle);
484        button.classList.remove('code-copy-button-checked');
485      }, 1000);
486      // clear code selection
487      e.clearSelection();
488    }
489    const getTextToCopy = function(trigger) {
490      const outerScaffold = trigger.parentElement.cloneNode(true);
491      const codeEl = outerScaffold.querySelector('code');
492      for (const childEl of codeEl.children) {
493        if (isCodeAnnotation(childEl)) {
494          childEl.remove();
495        }
496      }
497      return codeEl.innerText;
498    }
499    const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', {
500      text: getTextToCopy
501    });
502    clipboard.on('success', onCopySuccess);
503    if (window.document.getElementById('quarto-embedded-source-code-modal')) {
504      const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', {
505        text: getTextToCopy,
506        container: window.document.getElementById('quarto-embedded-source-code-modal')
507      });
508      clipboardModal.on('success', onCopySuccess);
509    }
510      var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//);
511      var mailtoRegex = new RegExp(/^mailto:/);
512        var filterRegex = new RegExp("https:\/\/hubverse\.io");
513      var isInternal = (href) => {
514          return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href);
515      }
516      // Inspect non-navigation links and adorn them if external
517     var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)');
518      for (var i=0; i<links.length; i++) {
519        const link = links[i];
520        if (!isInternal(link.href)) {
521          // undo the damage that might have been done by quarto-nav.js in the case of
522          // links that we want to consider external
523          if (link.dataset.originalHref !== undefined) {
524            link.href = link.dataset.originalHref;
525          }
526            // default icon
527            link.classList.add("external");
528        }
529      }
530    function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) {
531      const config = {
532        allowHTML: true,
533        maxWidth: 500,
534        delay: 100,
535        arrow: false,
536        appendTo: function(el) {
537            return el.parentElement;
538        },
539        interactive: true,
540        interactiveBorder: 10,
541        theme: 'quarto',
542        placement: 'bottom-start',
543      };
544      if (contentFn) {
545        config.content = contentFn;
546      }
547      if (onTriggerFn) {
548        config.onTrigger = onTriggerFn;
549      }
550      if (onUntriggerFn) {
551        config.onUntrigger = onUntriggerFn;
552      }
553      window.tippy(el, config); 
554    }
555    const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]');
556    for (var i=0; i<noterefs.length; i++) {
557      const ref = noterefs[i];
558      tippyHover(ref, function() {
559        // use id or data attribute instead here
560        let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href');
561        try { href = new URL(href).hash; } catch {}
562        const id = href.replace(/^#\/?/, "");
563        const note = window.document.getElementById(id);
564        if (note) {
565          return note.innerHTML;
566        } else {
567          return "";
568        }
569      });
570    }
571    const xrefs = window.document.querySelectorAll('a.quarto-xref');
572    const processXRef = (id, note) => {
573      // Strip column container classes
574      const stripColumnClz = (el) => {
575        el.classList.remove("page-full", "page-columns");
576        if (el.children) {
577          for (const child of el.children) {
578            stripColumnClz(child);
579          }
580        }
581      }
582      stripColumnClz(note)
583      if (id === null || id.startsWith('sec-')) {
584        // Special case sections, only their first couple elements
585        const container = document.createElement("div");
586        if (note.children && note.children.length > 2) {
587          container.appendChild(note.children[0].cloneNode(true));
588          for (let i = 1; i < note.children.length; i++) {
589            const child = note.children[i];
590            if (child.tagName === "P" && child.innerText === "") {
591              continue;
592            } else {
593              container.appendChild(child.cloneNode(true));
594              break;
595            }
596          }
597          if (window.Quarto?.typesetMath) {
598            window.Quarto.typesetMath(container);
599          }
600          return container.innerHTML
601        } else {
602          if (window.Quarto?.typesetMath) {
603            window.Quarto.typesetMath(note);
604          }
605          return note.innerHTML;
606        }
607      } else {
608        // Remove any anchor links if they are present
609        const anchorLink = note.querySelector('a.anchorjs-link');
610        if (anchorLink) {
611          anchorLink.remove();
612        }
613        if (window.Quarto?.typesetMath) {
614          window.Quarto.typesetMath(note);
615        }
616        if (note.classList.contains("callout")) {
617          return note.outerHTML;
618        } else {
619          return note.innerHTML;
620        }
621      }
622    }
623    for (var i=0; i<xrefs.length; i++) {
624      const xref = xrefs[i];
625      tippyHover(xref, undefined, function(instance) {
626        instance.disable();
627        let url = xref.getAttribute('href');
628        let hash = undefined; 
629        if (url.startsWith('#')) {
630          hash = url;
631        } else {
632          try { hash = new URL(url).hash; } catch {}
633        }
634        if (hash) {
635          const id = hash.replace(/^#\/?/, "");
636          const note = window.document.getElementById(id);
637          if (note !== null) {
638            try {
639              const html = processXRef(id, note.cloneNode(true));
640              instance.setContent(html);
641            } finally {
642              instance.enable();
643              instance.show();
644            }
645          } else {
646            // See if we can fetch this
647            fetch(url.split('#')[0])
648            .then(res => res.text())
649            .then(html => {
650              const parser = new DOMParser();
651              const htmlDoc = parser.parseFromString(html, "text/html");
652              const note = htmlDoc.getElementById(id);
653              if (note !== null) {
654                const html = processXRef(id, note);
655                instance.setContent(html);
656              } 
657            }).finally(() => {
658              instance.enable();
659              instance.show();
660            });
661          }
662        } else {
663          // See if we can fetch a full url (with no hash to target)
664          // This is a special case and we should probably do some content thinning / targeting
665          fetch(url)
666          .then(res => res.text())
667          .then(html => {
668            const parser = new DOMParser();
669            const htmlDoc = parser.parseFromString(html, "text/html");
670            const note = htmlDoc.querySelector('main.content');
671            if (note !== null) {
672              // This should only happen for chapter cross references
673              // (since there is no id in the URL)
674              // remove the first header
675              if (note.children.length > 0 && note.children[0].tagName === "HEADER") {
676                note.children[0].remove();
677              }
678              const html = processXRef(null, note);
679              instance.setContent(html);
680            } 
681          }).finally(() => {
682            instance.enable();
683            instance.show();
684          });
685        }
686      }, function(instance) {
687      });
688    }
689        let selectedAnnoteEl;
690        const selectorForAnnotation = ( cell, annotation) => {
691          let cellAttr = 'data-code-cell="' + cell + '"';
692          let lineAttr = 'data-code-annotation="' +  annotation + '"';
693          const selector = 'span[' + cellAttr + '][' + lineAttr + ']';
694          return selector;
695        }
696        const selectCodeLines = (annoteEl) => {
697          const doc = window.document;
698          const targetCell = annoteEl.getAttribute("data-target-cell");
699          const targetAnnotation = annoteEl.getAttribute("data-target-annotation");
700          const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation));
701          const lines = annoteSpan.getAttribute("data-code-lines").split(",");
702          const lineIds = lines.map((line) => {
703            return targetCell + "-" + line;
704          })
705          let top = null;
706          let height = null;
707          let parent = null;
708          if (lineIds.length > 0) {
709              //compute the position of the single el (top and bottom and make a div)
710              const el = window.document.getElementById(lineIds[0]);
711              top = el.offsetTop;
712              height = el.offsetHeight;
713              parent = el.parentElement.parentElement;
714            if (lineIds.length > 1) {
715              const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]);
716              const bottom = lastEl.offsetTop + lastEl.offsetHeight;
717              height = bottom - top;
718            }
719            if (top !== null && height !== null && parent !== null) {
720              // cook up a div (if necessary) and position it 
721              let div = window.document.getElementById("code-annotation-line-highlight");
722              if (div === null) {
723                div = window.document.createElement("div");
724                div.setAttribute("id", "code-annotation-line-highlight");
725                div.style.position = 'absolute';
726                parent.appendChild(div);
727              }
728              div.style.top = top - 2 + "px";
729              div.style.height = height + 4 + "px";
730              div.style.left = 0;
731              let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter");
732              if (gutterDiv === null) {
733                gutterDiv = window.document.createElement("div");
734                gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter");
735                gutterDiv.style.position = 'absolute';
736                const codeCell = window.document.getElementById(targetCell);
737                const gutter = codeCell.querySelector('.code-annotation-gutter');
738                gutter.appendChild(gutterDiv);
739              }
740              gutterDiv.style.top = top - 2 + "px";
741              gutterDiv.style.height = height + 4 + "px";
742            }
743            selectedAnnoteEl = annoteEl;
744          }
745        };
746        const unselectCodeLines = () => {
747          const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"];
748          elementsIds.forEach((elId) => {
749            const div = window.document.getElementById(elId);
750            if (div) {
751              div.remove();
752            }
753          });
754          selectedAnnoteEl = undefined;
755        };
756          // Handle positioning of the toggle
757      window.addEventListener(
758        "resize",
759        throttle(() => {
760          elRect = undefined;
761          if (selectedAnnoteEl) {
762            selectCodeLines(selectedAnnoteEl);
763          }
764        }, 10)
765      );
766      function throttle(fn, ms) {
767      let throttle = false;
768      let timer;
769        return (...args) => {
770          if(!throttle) { // first call gets through
771              fn.apply(this, args);
772              throttle = true;
773          } else { // all the others get throttled
774              if(timer) clearTimeout(timer); // cancel #2
775              timer = setTimeout(() => {
776                fn.apply(this, args);
777                timer = throttle = false;
778              }, ms);
779          }
780        };
781      }
782        // Attach click handler to the DT
783        const annoteDls = window.document.querySelectorAll('dt[data-target-cell]');
784        for (const annoteDlNode of annoteDls) {
785          annoteDlNode.addEventListener('click', (event) => {
786            const clickedEl = event.target;
787            if (clickedEl !== selectedAnnoteEl) {
788              unselectCodeLines();
789              const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active');
790              if (activeEl) {
791                activeEl.classList.remove('code-annotation-active');
792              }
793              selectCodeLines(clickedEl);
794              clickedEl.classList.add('code-annotation-active');
795            } else {
796              // Unselect the line
797              unselectCodeLines();
798              clickedEl.classList.remove('code-annotation-active');
799            }
800          });
801        }
802    const findCites = (el) => {
803      const parentEl = el.parentElement;
804      if (parentEl) {
805        const cites = parentEl.dataset.cites;
806        if (cites) {
807          return {
808            el,
809            cites: cites.split(' ')
810          };
811        } else {
812          return findCites(el.parentElement)
813        }
814      } else {
815        return undefined;
816      }
817    };
818    var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]');
819    for (var i=0; i<bibliorefs.length; i++) {
820      const ref = bibliorefs[i];
821      const citeInfo = findCites(ref);
822      if (citeInfo) {
823        tippyHover(citeInfo.el, function() {
824          var popup = window.document.createElement('div');
825          citeInfo.cites.forEach(function(cite) {
826            var citeDiv = window.document.createElement('div');
827            citeDiv.classList.add('hanging-indent');
828            citeDiv.classList.add('csl-entry');
829            var biblioDiv = window.document.getElementById('ref-' + cite);
830            if (biblioDiv) {
831              citeDiv.innerHTML = biblioDiv.innerHTML;
832            }
833            popup.appendChild(citeDiv);
834          });
835          return popup.innerHTML;
836        });
837      }
838    }
839  });
840  </script>
840
841</div> <!-- /content -->
842<footer class="footer">
843  <div class="nav-footer">
844    <div class="nav-footer-left">
845      <ul class="footer-items list-unstyled">
846    <li class="nav-item">
847      <i class="bi bi-c-circle" role="img">
848</i> 
849 Copyright 2025, Collaborative Modelling Consortium
850  </li>  
851</ul>
852    </div>   
853    <div class="nav-footer-center">
854      &nbsp;
855    <div class="toc-actions d-sm-block d-md-none"><ul><li><a href="https://github.com/hubverse-org/hubverse-site/edit/main/tools/dashboards.qmd" class="toc-action"><i class="bi bi-github"></i>Edit this page</a></li><li><a href="https://github.com/hubverse-org/hubverse-site/blob/main/tools/dashboards.qmd" class="toc-action"><i class="bi empty"></i>View source</a></li><li><a href="https://github.com/hubverse-org/hubverse-site/issues/new" class="toc-action"><i class="bi empty"></i>Report an issue</a></li></ul></div></div>
856    <div class="nav-footer-right">
857      <ul class="footer-items list-unstyled">
858    <li class="nav-item">
859    <a class="nav-link" href="../funding.html">
860<p><i class="fa-solid fa-coins" aria-label="coins"></i> Funding supporting the hubverse</p>
861</a>
862  </li>  
863    <li class="nav-item">
864    <a class="nav-link" href="../contact.html">
865<p><i class="fa-solid fa-address-card" aria-label="address-card"></i> Contact</p>
866</a>
867  </li>  
868    <li class="nav-item">
869    <a class="nav-link" href="../about.html">
870<p><i class="bi bi-info-circle-fill"></i> About the hubverse</p>
871</a>
872  </li>  
873</ul>
874    </div>
875  </div>
876</footer>
877
878
879
880
881</body></html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.