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<!-- This site is hosted on Netlify. Anyone can build and deploy a site 6 like this one for free: https://netlify.new/?utm_campaign=loops&utm_source=ai-legible&utm_medium=owned&utm_content=comment&utm_id=af4360b4-4a70-4cbe-87f6-43fa708bbace 7 Netlify hosting facts for this site: static/SSR served via Netlify Edge. --> 8<meta name="generator" content="quarto-1.9.38"> 9 10<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> 11 12 13<title>FEWsLab</title> 14<style> 15/* Default styles provided by pandoc. 16** See https://pandoc.org/MANUAL.html#variables-for-html for config info. 17*/ 18code{white-space: pre-wrap;} 19span.smallcaps{font-variant: small-caps;} 20div.columns{display: flex; gap: min(4vw, 1.5em);} 21div.column{flex: auto; overflow-x: auto;} 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="./images/favicon/favicon.ico" rel="icon">
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>
43 44<link href="site_libs/quarto-html/tippy.css" rel="stylesheet"> 45<link href="site_libs/quarto-html/quarto-syntax-highlighting-15634bcf2e68342d4ad2dfa704d543f6.css" rel="stylesheet" id="quarto-text-highlighting-styles">
46<script src="site_libs/bootstrap/bootstrap.min.js"></script>
46 47<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet"> 48<link href="site_libs/bootstrap/bootstrap-22f1789df73c9a524649167e87525b34.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
49<script id="quarto-search-options" type="application/json">{ 50 "location": "navbar", 51 "copy-button": false, 52 "collapse-after": 3, 53 "panel-placement": "end", 54 "type": "overlay", 55 "limit": 50, 56 "keyboard-shortcut": [ 57 "f", 58 "/", 59 "s" 60 ], 61 "language": { 62 "search-no-results-text": "No results", 63 "search-matching-documents-text": "matching documents", 64 "search-copy-link-title": "Copy link to search", 65 "search-hide-matches-text": "Hide additional matches", 66 "search-more-match-text": "more match in this document", 67 "search-more-matches-text": "more matches in this document", 68 "search-clear-button-title": "Clear", 69 "search-text-placeholder": "", 70 "search-detached-cancel-button-title": "Cancel", 71 "search-submit-button-title": "Submit", 72 "search-label": "Search" 73 } 74}</script>
74 75<style>html{ scroll-behavior: smooth; }</style> 76<!-- academic icons --> 77 78<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jpswalsh/academicons@1/css/academicons.min.css"> 79 80<!-- altmetric icons -->
81<script type="text/javascript" src="https://d1bxh8uas1mnw7.cloudfront.net/assets/embed.js"></script>
81 82 83<!-- fontawesome icons -->
84<script src="https://kit.fontawesome.com/1392a7030f.js" crossorigin="anonymous"></script>
84 85 86 87 88 89</head> 90 91<body class="nav-fixed fullcontent quarto-light"> 92 93<div id="quarto-search-results"></div> 94 <header id="quarto-header" class="headroom fixed-top"> 95 <nav class="navbar navbar-expand-lg " data-bs-theme="dark"> 96 <div class="navbar-container container-fluid"> 97 <div class="navbar-brand-container mx-auto"> 98 <a class='navbar-brand' href='/'> 99 <span class="navbar-title">FEWsLab</span> 100 </a> 101 </div> 102 <div id="quarto-search" class="" title="Search"></div> 103 <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(); }"> 104 <span class="navbar-toggler-icon"></span> 105</button> 106 <div class="collapse navbar-collapse" id="navbarCollapse"> 107 <ul class="navbar-nav navbar-nav-scroll ms-auto"> 108 <li class="nav-item"> 109 <a class='nav-link' href='/about'> 110<span class="menu-text">About</span></a> 111 </li> 112 <li class="nav-item"> 113 <a class='nav-link' href='/lab'> 114<span class="menu-text">Team</span></a> 115 </li> 116 <li class="nav-item"> 117 <a class='nav-link' href='/research'> 118<span class="menu-text">News & Publications</span></a> 119 </li> 120 <li class="nav-item"> 121 <a class='nav-link' href='/teaching'> 122<span class="menu-text">Teaching</span></a> 123 </li> 124 <li class="nav-item"> 125 <a class='nav-link' href='/projects'> 126<span class="menu-text">Projects</span></a> 127 </li> 128</ul> 129 </div> <!-- /navcollapse --> 130 <div class="quarto-navbar-tools"> 131</div> 132 </div> <!-- /container-fluid --> 133 </nav> 134</header> 135<!-- content --> 136<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar"> 137<!-- sidebar --> 138<!-- margin-sidebar --> 139 140<!-- main --> 141<div class="quarto-about-trestles"> 142 <div class="about-entity"> 143 <img src="images/lab/logo/logo.png" class="about-image 144 rounded " style="width: 20em;"> 145<header id="title-block-header" class="quarto-title-block"></header> 146 <div class="about-links"> 147 <a href="https://www.linkedin.com/company/fews-lab" class="about-link" rel="" target=""> 148 <i class="bi bi-linkedin"></i> 149 <span class="about-link-text"></span> 150 </a> 151</div> 152 </div> 153 <div class="about-contents"><main class="content" id="quarto-document-content"> 154<section id="welcome-to-the-fewslab-website" class="level3"> 155<h3 data-anchor-id="welcome-to-the-fewslab-website">Welcome to the FEWsLab Website</h3> 156<p>At <strong>FEWsLab</strong>, we investigate interconnections across <strong>food</strong>, <strong>energy</strong>, and <strong>water</strong> systems.</p> 157<p>Our lab combines <strong>Systems modeling</strong>, <strong>Socio-technical data</strong>, <strong>Ethical and policy analyses</strong>.</p> 158<p>We aim to foster a more <strong>economic</strong>, <strong>sustainable</strong>, and <strong>secure</strong> environment, balancing <strong>fundamental research</strong> with <strong>practical policy insights</strong>.</p> 159<hr> 160<blockquote class="blockquote"> 161<p><em>âThe future of resource security lies in mapping the invisible threads that bind our food, energy, and water systems togetherâ</em></p> 162</blockquote> 163 164 165</section> 166</main></div> 167</div> 168 <!-- /main -->
169<script id="quarto-html-after-body" type="application/javascript"> 170 window.document.addEventListener("DOMContentLoaded", function (event) { 171 const isCodeAnnotation = (el) => { 172 for (const clz of el.classList) { 173 if (clz.startsWith('code-annotation-')) { 174 return true; 175 } 176 } 177 return false; 178 } 179 const onCopySuccess = function(e) { 180 // button target 181 const button = e.trigger; 182 // don't keep focus 183 button.blur(); 184 // flash "checked" 185 button.classList.add('code-copy-button-checked'); 186 var currentTitle = button.getAttribute("title"); 187 button.setAttribute("title", "Copied!"); 188 let tooltip; 189 if (window.bootstrap) { 190 button.setAttribute("data-bs-toggle", "tooltip"); 191 button.setAttribute("data-bs-placement", "left"); 192 button.setAttribute("data-bs-title", "Copied!"); 193 tooltip = new bootstrap.Tooltip(button, 194 { trigger: "manual", 195 customClass: "code-copy-button-tooltip", 196 offset: [0, -8]}); 197 tooltip.show(); 198 } 199 setTimeout(function() { 200 if (tooltip) { 201 tooltip.hide(); 202 button.removeAttribute("data-bs-title"); 203 button.removeAttribute("data-bs-toggle"); 204 button.removeAttribute("data-bs-placement"); 205 } 206 button.setAttribute("title", currentTitle); 207 button.classList.remove('code-copy-button-checked'); 208 }, 1000); 209 // clear code selection 210 e.clearSelection(); 211 } 212 const getTextToCopy = function(trigger) { 213 const outerScaffold = trigger.parentElement.cloneNode(true); 214 const codeEl = outerScaffold.querySelector('code'); 215 for (const childEl of codeEl.children) { 216 if (isCodeAnnotation(childEl)) { 217 childEl.remove(); 218 } 219 } 220 return codeEl.innerText; 221 } 222 const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', { 223 text: getTextToCopy 224 }); 225 clipboard.on('success', onCopySuccess); 226 if (window.document.getElementById('quarto-embedded-source-code-modal')) { 227 const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', { 228 text: getTextToCopy, 229 container: window.document.getElementById('quarto-embedded-source-code-modal') 230 }); 231 clipboardModal.on('success', onCopySuccess); 232 } 233 var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//); 234 var mailtoRegex = new RegExp(/^mailto:/); 235 var filterRegex = new RegExp("https:\/\/fewslab\.netlify\.app"); 236 var isInternal = (href) => { 237 return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href); 238 } 239 // Inspect non-navigation links and adorn them if external 240 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)'); 241 for (var i=0; i<links.length; i++) { 242 const link = links[i]; 243 if (!isInternal(link.href)) { 244 // undo the damage that might have been done by quarto-nav.js in the case of 245 // links that we want to consider external 246 if (link.dataset.originalHref !== undefined) { 247 link.href = link.dataset.originalHref; 248 } 249 // target, if specified 250 link.setAttribute("target", "_blank"); 251 if (link.getAttribute("rel") === null) { 252 link.setAttribute("rel", "noopener"); 253 } 254 } 255 } 256 function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) { 257 const config = { 258 allowHTML: true, 259 maxWidth: 500, 260 delay: 100, 261 arrow: false, 262 appendTo: function(el) { 263 return el.parentElement; 264 }, 265 interactive: true, 266 interactiveBorder: 10, 267 theme: 'quarto', 268 placement: 'bottom-start', 269 }; 270 if (contentFn) { 271 config.content = contentFn; 272 } 273 if (onTriggerFn) { 274 config.onTrigger = onTriggerFn; 275 } 276 if (onUntriggerFn) { 277 config.onUntrigger = onUntriggerFn; 278 } 279 window.tippy(el, config); 280 } 281 const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]'); 282 for (var i=0; i<noterefs.length; i++) { 283 const ref = noterefs[i]; 284 tippyHover(ref, function() { 285 // use id or data attribute instead here 286 let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href'); 287 try { href = new URL(href).hash; } catch {} 288 const id = href.replace(/^#\/?/, ""); 289 const note = window.document.getElementById(id); 290 if (note) { 291 return note.innerHTML; 292 } else { 293 return ""; 294 } 295 }); 296 } 297 const xrefs = window.document.querySelectorAll('a.quarto-xref'); 298 const processXRef = (id, note) => { 299 // Strip column container classes 300 const stripColumnClz = (el) => { 301 el.classList.remove("page-full", "page-columns"); 302 if (el.children) { 303 for (const child of el.children) {
304 stripColumnClz(child); 305 } 306 } 307 } 308 stripColumnClz(note) 309 if (id === null || id.startsWith('sec-')) { 310 // Special case sections, only their first couple elements 311 const container = document.createElement("div"); 312 if (note.children && note.children.length > 2) { 313 container.appendChild(note.children[0].cloneNode(true)); 314 for (let i = 1; i < note.children.length; i++) { 315 const child = note.children[i]; 316 if (child.tagName === "P" && child.innerText === "") { 317 continue; 318 } else { 319 container.appendChild(child.cloneNode(true)); 320 break; 321 } 322 } 323 if (window.Quarto?.typesetMath) { 324 window.Quarto.typesetMath(container); 325 } 326 return container.innerHTML 327 } else { 328 if (window.Quarto?.typesetMath) { 329 window.Quarto.typesetMath(note); 330 } 331 return note.innerHTML; 332 } 333 } else { 334 // Remove any anchor links if they are present 335 const anchorLink = note.querySelector('a.anchorjs-link'); 336 if (anchorLink) { 337 anchorLink.remove(); 338 } 339 if (window.Quarto?.typesetMath) { 340 window.Quarto.typesetMath(note); 341 } 342 if (note.classList.contains("callout")) { 343 return note.outerHTML; 344 } else { 345 return note.innerHTML; 346 } 347 } 348 } 349 for (var i=0; i<xrefs.length; i++) { 350 const xref = xrefs[i]; 351 tippyHover(xref, undefined, function(instance) { 352 instance.disable(); 353 let url = xref.getAttribute('href'); 354 let hash = undefined; 355 if (url.startsWith('#')) { 356 hash = url; 357 } else { 358 try { hash = new URL(url).hash; } catch {} 359 } 360 if (hash) { 361 const id = hash.replace(/^#\/?/, ""); 362 const note = window.document.getElementById(id); 363 if (note !== null) { 364 try { 365 const html = processXRef(id, note.cloneNode(true)); 366 instance.setContent(html); 367 } finally { 368 instance.enable(); 369 instance.show(); 370 } 371 } else { 372 // See if we can fetch this 373 fetch(url.split('#')[0]) 374 .then(res => res.text()) 375 .then(html => { 376 const parser = new DOMParser(); 377 const htmlDoc = parser.parseFromString(html, "text/html"); 378 const note = htmlDoc.getElementById(id); 379 if (note !== null) { 380 const html = processXRef(id, note); 381 instance.setContent(html); 382 } 383 }).finally(() => { 384 instance.enable(); 385 instance.show(); 386 }); 387 } 388 } else { 389 // See if we can fetch a full url (with no hash to target) 390 // This is a special case and we should probably do some content thinning / targeting 391 fetch(url) 392 .then(res => res.text()) 393 .then(html => { 394 const parser = new DOMParser(); 395 const htmlDoc = parser.parseFromString(html, "text/html"); 396 const note = htmlDoc.querySelector('main.content'); 397 if (note !== null) { 398 // This should only happen for chapter cross references 399 // (since there is no id in the URL) 400 // remove the first header 401 if (note.children.length > 0 && note.children[0].tagName === "HEADER") { 402 note.children[0].remove(); 403 } 404 const html = processXRef(null, note); 405 instance.setContent(html); 406 } 407 }).finally(() => { 408 instance.enable(); 409 instance.show(); 410 }); 411 } 412 }, function(instance) { 413 }); 414 } 415 let selectedAnnoteEl; 416 const selectorForAnnotation = ( cell, annotation) => { 417 let cellAttr = 'data-code-cell="' + cell + '"'; 418 let lineAttr = 'data-code-annotation="' + annotation + '"'; 419 const selector = 'span[' + cellAttr + '][' + lineAttr + ']'; 420 return selector; 421 } 422 const selectCodeLines = (annoteEl) => { 423 const doc = window.document; 424 const targetCell = annoteEl.getAttribute("data-target-cell"); 425 const targetAnnotation = annoteEl.getAttribute("data-target-annotation"); 426 const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation)); 427 const lines = annoteSpan.getAttribute("data-code-lines").split(","); 428 const lineIds = lines.map((line) => { 429 return targetCell + "-" + line; 430 }) 431 let top = null; 432 let height = null; 433 let parent = null; 434 if (lineIds.length > 0) { 435 //compute the position of the single el (top and bottom and make a div) 436 const el = window.document.getElementById(lineIds[0]); 437 top = el.offsetTop; 438 height = el.offsetHeight; 439 parent = el.parentElement.parentElement; 440 if (lineIds.length > 1) { 441 const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]); 442 const bottom = lastEl.offsetTop + lastEl.offsetHeight; 443 height = bottom - top; 444 } 445 if (top !== null && height !== null && parent !== null) { 446 // cook up a div (if necessary) and position it 447 let div = window.document.getElementById("code-annotation-line-highlight"); 448 if (div === null) { 449 div = window.document.createElement("div"); 450 div.setAttribute("id", "code-annotation-line-highlight"); 451 div.style.position = 'absolute'; 452 parent.appendChild(div); 453 } 454 div.style.top = top - 2 + "px"; 455 div.style.height = height + 4 + "px"; 456 div.style.left = 0; 457 let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter"); 458 if (gutterDiv === null) { 459 gutterDiv = window.document.createElement("div"); 460 gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter"); 461 gutterDiv.style.position = 'absolute'; 462 const codeCell = window.document.getElementById(targetCell); 463 const gutter = codeCell.querySelector('.code-annotation-gutter'); 464 gutter.appendChild(gutterDiv); 465 } 466 gutterDiv.style.top = top - 2 + "px"; 467 gutterDiv.style.height = height + 4 + "px"; 468 } 469 selectedAnnoteEl = annoteEl; 470 } 471 }; 472 const unselectCodeLines = () => { 473 const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"]; 474 elementsIds.forEach((elId) => { 475 const div = window.document.getElementById(elId); 476 if (div) { 477 div.remove(); 478 } 479 }); 480 selectedAnnoteEl = undefined; 481 }; 482 // Handle positioning of the toggle 483 window.addEventListener( 484 "resize", 485 throttle(() => { 486 elRect = undefined; 487 if (selectedAnnoteEl) { 488 selectCodeLines(selectedAnnoteEl); 489 } 490 }, 10) 491 ); 492 function throttle(fn, ms) { 493 let throttle = false;
494 let timer; 495 return (...args) => { 496 if(!throttle) { // first call gets through 497 fn.apply(this, args); 498 throttle = true; 499 } else { // all the others get throttled 500 if(timer) clearTimeout(timer); // cancel #2 501 timer = setTimeout(() => { 502 fn.apply(this, args); 503 timer = throttle = false; 504 }, ms); 505 } 506 }; 507 } 508 // Attach click handler to the DT 509 const annoteDls = window.document.querySelectorAll('dt[data-target-cell]'); 510 for (const annoteDlNode of annoteDls) { 511 annoteDlNode.addEventListener('click', (event) => { 512 const clickedEl = event.target; 513 if (clickedEl !== selectedAnnoteEl) { 514 unselectCodeLines(); 515 const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active'); 516 if (activeEl) { 517 activeEl.classList.remove('code-annotation-active'); 518 } 519 selectCodeLines(clickedEl); 520 clickedEl.classList.add('code-annotation-active'); 521 } else { 522 // Unselect the line 523 unselectCodeLines(); 524 clickedEl.classList.remove('code-annotation-active'); 525 } 526 }); 527 } 528 const findCites = (el) => { 529 const parentEl = el.parentElement; 530 if (parentEl) { 531 const cites = parentEl.dataset.cites; 532 if (cites) { 533 return { 534 el, 535 cites: cites.split(' ') 536 }; 537 } else { 538 return findCites(el.parentElement) 539 } 540 } else { 541 return undefined; 542 } 543 }; 544 var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]'); 545 for (var i=0; i<bibliorefs.length; i++) { 546 const ref = bibliorefs[i]; 547 const citeInfo = findCites(ref); 548 if (citeInfo) { 549 tippyHover(citeInfo.el, function() { 550 var popup = window.document.createElement('div'); 551 citeInfo.cites.forEach(function(cite) { 552 var citeDiv = window.document.createElement('div'); 553 citeDiv.classList.add('hanging-indent'); 554 citeDiv.classList.add('csl-entry'); 555 var biblioDiv = window.document.getElementById('ref-' + cite); 556 if (biblioDiv) { 557 citeDiv.innerHTML = biblioDiv.innerHTML; 558 } 559 popup.appendChild(citeDiv); 560 }); 561 return popup.innerHTML; 562 }); 563 } 564 } 565 }); 566 </script>
566 567</div> <!-- /content --> 568<footer class="footer"> 569 <div class="nav-footer"> 570 <div class="nav-footer-left"> 571 572 </div> 573 <div class="nav-footer-center"> 574 <ul class="footer-items list-unstyled"> 575 <li class="nav-item"> 576 Contact: <a href="mailto:[email protected]">[email protected]</a><br> 577<a href="https://www.linkedin.com/company/fews-lab" target="_blank"><i class="bi bi-linkedin"></i> FEWsLab</a> 578<a href="https://www.linkedin.com/in/caitlinagrady/" target="_blank"><i class="bi bi-linkedin"></i> Caitlin Grady</a> 579<a href="https://bsky.app/profile/caitlinagrady.bsky.social" target="_blank"><i class="fa fa-brands fa-bluesky"></i> Bluesky</a><br> 580Site made with <a href="https://quarto.org/" target="_blank"><img src="https://quarto.org/favicon.png" width="12"> Quarto</a><br> 581© 2025 FEWsLab 582 </li> 583</ul> 584 </div> 585 <div class="nav-footer-right"> 586 587 </div> 588 </div> 589</footer> 590 591 592 593
594<script src="site_libs/quarto-html/zenscroll-min.js"></script>
594 595</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.