PageSourceSearch

https://fewslab.netlify.app/

html fewslab.netlify.app collected 2026-10-03 10:43:48 UTC 23,444 bytes, 595 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<!-- 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 &amp; 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      &nbsp;
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> &nbsp;
578<a href="https://www.linkedin.com/in/caitlinagrady/" target="_blank"><i class="bi bi-linkedin"></i> Caitlin Grady</a> &nbsp;
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      &nbsp;
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.