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 Team â 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>
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-15634bcf2e68342d4ad2dfa704d543f6.css" rel="stylesheet" id="quarto-text-highlighting-styles">
47<script src="site_libs/bootstrap/bootstrap.min.js"></script>
47 48<link href="site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet"> 49<link href="site_libs/bootstrap/bootstrap-22f1789df73c9a524649167e87525b34.min.css" rel="stylesheet" append-hash="true" id="quarto-bootstrap" data-mode="light">
50<script id="quarto-search-options" type="application/json">{ 51 "location": "navbar", 52 "copy-button": false, 53 "collapse-after": 3, 54 "panel-placement": "end", 55 "type": "overlay", 56 "limit": 50, 57 "keyboard-shortcut": [ 58 "f", 59 "/", 60 "s" 61 ], 62 "language": { 63 "search-no-results-text": "No results", 64 "search-matching-documents-text": "matching documents", 65 "search-copy-link-title": "Copy link to search", 66 "search-hide-matches-text": "Hide additional matches", 67 "search-more-match-text": "more match in this document", 68 "search-more-matches-text": "more matches in this document", 69 "search-clear-button-title": "Clear", 70 "search-text-placeholder": "", 71 "search-detached-cancel-button-title": "Cancel", 72 "search-submit-button-title": "Submit", 73 "search-label": "Search" 74 } 75}</script>
75 76<style>html{ scroll-behavior: smooth; }</style> 77<!-- academic icons --> 78 79<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/jpswalsh/academicons@1/css/academicons.min.css"> 80 81<!-- altmetric icons -->
82<script type="text/javascript" src="https://d1bxh8uas1mnw7.cloudfront.net/assets/embed.js"></script>
82 83 84<!-- fontawesome icons -->
85<script src="https://kit.fontawesome.com/1392a7030f.js" crossorigin="anonymous"></script>
85 86 87 88 89 90</head> 91 92<body class="floating nav-fixed quarto-light"> 93 94<div id="quarto-search-results"></div> 95 <header id="quarto-header" class="headroom fixed-top"> 96 <nav class="navbar navbar-expand-lg " data-bs-theme="dark"> 97 <div class="navbar-container container-fluid"> 98 <div class="navbar-brand-container mx-auto"> 99 <a class='navbar-brand' href='/'> 100 <span class="navbar-title">FEWsLab</span> 101 </a> 102 </div> 103 <div id="quarto-search" class="" title="Search"></div> 104 <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(); }"> 105 <span class="navbar-toggler-icon"></span> 106</button> 107 <div class="collapse navbar-collapse" id="navbarCollapse"> 108 <ul class="navbar-nav navbar-nav-scroll ms-auto"> 109 <li class="nav-item"> 110 <a class='nav-link' href='/about'> 111<span class="menu-text">About</span></a> 112 </li> 113 <li class="nav-item"> 114 <a aria-current='page' class='nav-link active' href='/lab'> 115<span class="menu-text">Team</span></a> 116 </li> 117 <li class="nav-item"> 118 <a class='nav-link' href='/research'> 119<span class="menu-text">News & Publications</span></a> 120 </li> 121 <li class="nav-item"> 122 <a class='nav-link' href='/teaching'> 123<span class="menu-text">Teaching</span></a> 124 </li> 125 <li class="nav-item"> 126 <a class='nav-link' href='/projects'> 127<span class="menu-text">Projects</span></a> 128 </li> 129</ul> 130 </div> <!-- /navcollapse --> 131 <div class="quarto-navbar-tools"> 132</div> 133 </div> <!-- /container-fluid --> 134 </nav> 135</header> 136<!-- content --> 137<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-full page-navbar"> 138<!-- sidebar --> 139 <nav id="quarto-sidebar" class="sidebar collapse collapse-horizontal quarto-sidebar-collapse-item sidebar-navigation floating overflow-auto"> 140 <nav id="TOC" role="doc-toc" class="toc-active"> 141 <h2 id="toc-title">On this page</h2> 142 143 <ul> 144 <li><a href="#graduate-students" id="toc-graduate-students" class="nav-link active" data-scroll-target="#graduate-students">Graduate Students</a></li> 145 <li><a href="#undergraduate-students" id="toc-undergraduate-students" class="nav-link" data-scroll-target="#undergraduate-students">Undergraduate Students</a></li> 146 </ul> 147</nav> 148</nav> 149<div id="quarto-sidebar-glass" class="quarto-sidebar-collapse-item" data-bs-toggle="collapse" data-bs-target=".quarto-sidebar-collapse-item"></div> 150<!-- margin-sidebar --> 151 <div id="quarto-margin-sidebar" class="sidebar margin-sidebar zindex-bottom"> 152 </div> 153<!-- main --> 154<main class="content column-page-right" id="quarto-document-content"> 155 156<header id="title-block-header" class="quarto-title-block default"> 157<div class="quarto-title"> 158<h1 class="title">FEWsLab Team</h1> 159</div> 160 161 162 163<div class="quarto-title-meta column-page-right"> 164 165 166 167 168 </div> 169 170 171 172</header> 173 174 175<section id="graduate-students" class="level2"> 176<h2 class="anchored" data-anchor-id="graduate-students">Graduate Students</h2> 177<div class="float-left"> 178<p><img src="images/lab/dhanya.jpg" width="150px"></p> 179<section id="dhanyasri-bolla" class="level3"> 180<h3 class="anchored" data-anchor-id="dhanyasri-bolla"><strong>Dhanyasri Bolla</strong></h3> 181<p>Dhanyasri is a masterâs student in the Engineering Management program at George Washington University (GWU). She received her Bachelor of Technology in Electronics and Communication Engineering from the Sardar Vallabhbhai National Institute of Technology in 2023. Currently pursuing her masterâs degree, Dhanya is interested in shifting into the finance field and is taking relevant courses to achieve this goal. Her undergraduate research focused on analyzing the performance of 5G waveforms over a 3D channel model. Professionally, she is skilled in Python, data visualization using Tableau and front-end web development. Her extracurricular interests include event management at university events and photography.</p> 182<p><br></p> 183<p><img src="images/lab/abbey.jpg" width="150px"></p> 184</section> 185<section id="abbey-kollar" class="level3"> 186<h3 class="anchored" data-anchor-id="abbey-kollar"><strong>Abbey Kollar</strong></h3> 187<p>Abbey is a doctoral student in the Systems Engineering Ph.D. program at GWU. She received her B.S. in Chemical Engineering with honors and a minor in Applied Economics from The Pennsylvania State University in 2023. Abbeyâs undergraduate research focused on the conversion of plastics and biomass to oil and reducing nitrous oxide production from fertilizer use. Her research interests include renewable energy systems, climate change, economics, and policy. As a <a href="https://dtais.engineering.gwu.edu/">DTAIS fellow</a>, Abbey will integrate trustworthy AI into her research as well.</p> 188<p><br></p> 189<p><img src="images/lab/tarun.jpeg" width="150px"></p> 190</section> 191<section id="tarun-kumanduri" class="level3"> 192<h3 class="anchored" data-anchor-id="tarun-kumanduri"><strong>Tarun Kumanduri</strong></h3> 193<p>Tarun is a Masterâs student in the Data Analytics Program at George Washington University. He holds a Bachelorâs Degree in Computer Science and Engineering from JNTU Hyderabad. His expertise in Data Analysis, Visualization, and Modeling is enhanced by his interest in Project Management. He served as an Operations Intern in the UNICEF-Government of Telangana âSchool Innovation Challenge.â He is also a certified Yoga Teacher and the Events Director for the George Washington Desis Student Organization.</p> 194<p><br></p> 195<p><img src="images/lab/bryce.jpeg" width="150px"></p> 196</section> 197<section id="bryce-huffman" class="level3"> 198<h3 class="anchored" data-anchor-id="bryce-huffman"><strong>Bryce Huffman</strong></h3> 199<p>Bryce is a doctoral student in the Systems Engineering Ph.D. program at GWU. He received his B.S. in Systems Engineering and Economics from the University of Virginia in 2022. His research interests are at the intersection of artificial intelligence and human systems, specifically focused on methods to embed advanced AI models into human workflows to support decision-making, eff
199iciency, and efficacy. He is also interested in how human-AI interactions shape user trust and intuition development across expertise levels, as well as how these dynamics play out in real-world systems. In support of these interests, Bryce is a fellow in GWâs âCo-Design of Trustworthy AI Systemsâ (DTAIS) program.</p> 200<p><br></p> 201</section> 202</div> 203</section> 204<section id="undergraduate-students" class="level2"> 205<h2 class="anchored" data-anchor-id="undergraduate-students">Undergraduate Students</h2> 206<div class="float-left"> 207<p><img src="images/lab/maddy.jpg" width="150px"></p> 208<section id="madelyn-mccarthy" class="level3"> 209<h3 class="anchored" data-anchor-id="madelyn-mccarthy"><strong>Madelyn McCarthy</strong></h3> 210<p>Madelyn is an undergraduate student studying Environmental and Sustainability Science, with minors in Geography and Business. Her research interests focus on the global green energy transition and on exploring how science, business, and policy can collaborate to create meaningful environmental change. As a senior, she is applying to Masterâs programs in Environmental Management to continue her academic and professional development. Outside of the lab, Madelyn enjoys traveling, practicing Pilates, and discovering new matcha spots.</p> 211</section> 212</div> 213<div class="float-left"> 214<p><img src="images/lab/dia.jpg" width="150px"></p> 215<section id="dia-makhecha" class="level3"> 216<h3 class="anchored" data-anchor-id="dia-makhecha"><strong>Dia Makhecha</strong></h3> 217<p>Dia Makhecha is an undergraduate student studying Political Science and International Business, with a minor in Sustainability. Her academic and professional interests lie at the intersection of energy policy and consulting, and international development, with a particular focus on advancing equitable and sustainable energy transitions in the Global South. Diaâs experience spans corporate sustainability research at TATA Power, legal and policy internships, and leadership roles in student, executive, and advocacy organizations including the Director of International Students at the George Washington University Student Government Association, and Licensee at TedxFoggyBottom. As she continues to explore the nexus between policy, business, and the environment, Dia is eager to contribute to interdisciplinary research that support sustainable governance and international affairs.</p> 218<p><br></p> 219</section> 220<section id="lab-manager" class="level2"> 221<h2 class="anchored" data-anchor-id="lab-manager">Lab Manager</h2> 222<div class="float-left"> 223<p><img src="images/lab/sachi.jpg" width="150px"></p> 224<section id="sachi-nandurkar" class="level3"> 225<h3 class="anchored" data-anchor-id="sachi-nandurkar"><strong>Sachi Nandurkar</strong></h3> 226<p>Sachi completed her masterâs in the Engineering Management program at GWU (May 2025). Her research at the FEWâs Lab focuses on the life cycle assessment and circularity of electric vehicles. She also serves as the Lab Manager for the FEWsLab where she supports organization and project management for the team and PI Grady. Previously she served as a Graduate Teaching Assistant, where she taught labs on advanced Excel, SQL, and ERDs. She has experience in global program management and data analytics. Outside the lab, Sachi loves Formula One.</p> 227</section> 228</div> 229<p><br></p> 230</section> 231<section id="principal-investigator" class="level2"> 232<h2 class="anchored" data-anchor-id="principal-investigator">Principal Investigator</h2> 233<section id="dr.-caitlin-grady" class="level3 float-left"> 234<h3 class="anchored" data-anchor-id="dr.-caitlin-grady"><strong>Dr. Caitlin Grady</strong></h3> 235<p><img src="images/lab/caitlin_grady.jpg" class="img-fluid" style="margin-right: 20px; margin-bottom: 50px;" data-float="left" width="150" alt="Dr. Caitlin Grady"> Dr. Caitlin Grady is an Associate Professor in the Department of <a href="https://emse.engineering.gwu.edu/">Engineering Management and Systems Engineering</a> and the Director of Research at the <a href="https://globalfoodinstitute.gwu.edu/">Global Food Institute</a>. Her academic background and research expertise spans a variety of engineering and policy domains across food, energy, and water systems. This includes both qualitative and quantitative approaches to studying systems such as agricultural trade, the electricity grid, natural hazards, and adaptation to climate change. Prior to her academic roles, she held several federal government roles including with the House of Representatives, the Department of Energy, and the Department of State. In these roles, she worked on a myriad of issues including agriculture, water & energy, air quality, budget & appropriations, international development, and diplomatic engagement.</p> 236<p><strong>Education:</strong><br> 237Ph.D., Civil and Environmental Engineering, Purdue University<br> 238M.S., Agricultural and Biological Engineering, Purdue University<br> 239B.S., Science and Technology Studies, Virginia Tech (Humanities, Science, and the Environment Major; Environmental Policy and Planning Minor)</p> 240</section> 241<p><br></p> 242</section> 243<section id="alumni" class="level1"> 244<h1>Alumni</h1> 245<ul> 246<li>Jose Fernandez (2017â2018): M.Eng., Penn State Civil Engineering, Water Resources. Now Project Engineer in Ecuador.</li> 247<li>Andrew Pannone (2017â2018): Undergraduate, Penn State Engineering. Now PhD student in Dr. Saptarshi Das Lab, Penn State.</li> 248<li>Jack Iffert (2018â2019): B.S. Civil Engineering. Now Transportation Analyst at Kimley Horn.</li> 249<li>
249Jared Lawrence (2018â2019): MIA, PSU School of International Affairs.</li> 250<li>Maya Zambrano-Lee (Summer 2019): Visiting undergrad, Univ. of Maryland. Now Sustainability Intern, City of Brunswick.</li> 251<li>Abby Cowser (2019â2020): B.S. Civil Engineering. Now Staff Engineer, WDP & Associates.</li> 252<li>Tasnuva Mahjabin (2017â2020): Ph.D. Civil Engineering. Now Water Resources Engineer II at Atkins.</li> 253<li>Autumn Deitrick (2019â2021): B.S. Civil Engineering. Now Ph.D. student in Engineering Education at Penn State.</li> 254<li>Tori Lenze (2020â2022): B.S. Mechanical Engineering. Now graduate student at Penn State.</li> 255<li>Yuchen Fu (2021â2022): B.S. Civil Engineering. Now graduate student at Stanford University.</li> 256<li>Xinran Zhang (2021â2022): B.S. Civil Engineering. Now graduate student at University of Michigan.</li> 257<li>Luis Delgado (2020â2022): M.S. Civil Engineering. Now PhD student in Engineering Education at Penn State.</li> 258<li>Sarah Torhan (2020â2022): M.S. Civil Engineering. Now PhD student at Penn State.</li> 259<li>
259Lauren Dennis (2019â2023): Ph.D. Civil Engineering, Climate Science. Now Presidential Management Fellow.</li> 260<li>Paniz Mohammadpour (2018â2023): Ph.D. Civil Engineering. Now Water Resources Engineer II at Atkins.</li> 261<li>Selena Hinojos (2021-2025) : Ph.D. in Engineering Management. Now Post Doc at University of Lousiana.</li> 262<li>Rebecca Germaine (2023-2025) : B.S. in Public Health. Now a masters student at GW.</li> 263<li>Sachi Nandurkar (2023-2025) : M.S. in Engineering Management. Now the FEWsLab Lab manager!</li> 264</ul> 265<hr> 266</section> 267<section id="student-awards" class="level1"> 268<h1>Student Awards</h1> 269<ul> 270<li>Bryce Huffman - NSF Graduate Research Fellowship Honorable Mention (2025)</li> 271<li>Abbey Kollar â NSF Graduate Research Fellowship (2024)<br> 272</li> 273<li>Lauren Dennis â Presidential Management Fellow (2023)<br> 274</li> 275<li>Sarah Torhan â NDSEG Fellow, Fulbright Fellow, Boren Fellow (2022)<br> 276</li> 277<li>Autumn Deitrick â NSF Fellow (2021), Goldwater Scholar (2020), Mission Award (2021)<br> 278</li> 279<li>Selena Hinojos â Bunton-Waller Fellowship (2020â2021)<br> 280</li> 281<li>Luis Delgado â GEM Fellow, Bunton-Waller Fellowship (2020â2021)<br> 282</li> 283<li>Abby Cowser â ASCE New Faces of Civil Engineering, Oswald Award (2020)<br> 284</li> 285<li>
285Lauren Dennis â PSU Graduate Fellowship (2019â2020), NSF NRT Fellow (2020â2021)<br> 286</li> 287<li>Paniz Mohammadpour â CUAHSI Travel Scholarship (2019)<br> 288</li> 289<li>Jack Iffert â Ralph Dorn Hetzel Award (2019), Engineering Technology and Ethics Fellowship (2018)<br> 290</li> 291<li>Tasnuva Mahjabin â Travel Grant (AGU Fall Conference), SESYNC Workshop Award (2018)<br> 292</li> 293<li>Andrew Pannone â CERI Scholarship (2018), REU Fellowship (2018)</li> 294</ul> 295<hr> 296<p><em>Current and prospective students are encouraged to contact Dr. Grady for opportunities.</em></p> 297 298 299</section> 300</div> 301</section> 302 303</main> <!-- /main -->
304<script id="quarto-html-after-body" type="application/javascript"> 305 window.document.addEventListener("DOMContentLoaded", function (event) { 306 const icon = "î§"; 307 const anchorJS = new window.AnchorJS(); 308 anchorJS.options = { 309 placement: 'right', 310 icon: icon 311 }; 312 anchorJS.add('.anchored'); 313 const isCodeAnnotation = (el) => { 314 for (const clz of el.classList) { 315 if (clz.startsWith('code-annotation-')) { 316 return true; 317 } 318 } 319 return false; 320 } 321 const onCopySuccess = function(e) { 322 // button target 323 const button = e.trigger; 324 // don't keep focus 325 button.blur(); 326 // flash "checked" 327 button.classList.add('code-copy-button-checked'); 328 var currentTitle = button.getAttribute("title"); 329 button.setAttribute("title", "Copied!"); 330 let tooltip; 331 if (window.bootstrap) { 332 button.setAttribute("data-bs-toggle", "tooltip"); 333 button.setAttribute("data-bs-placement", "left"); 334 button.setAttribute("data-bs-title", "Copied!"); 335 tooltip = new bootstrap.Tooltip(button, 336 { trigger: "manual", 337 customClass: "code-copy-button-tooltip", 338 offset: [0, -8]}); 339 tooltip.show(); 340 } 341 setTimeout(function() { 342 if (tooltip) { 343 tooltip.hide(); 344 button.removeAttribute("data-bs-title"); 345 button.removeAttribute("data-bs-toggle"); 346 button.removeAttribute("data-bs-placement"); 347 } 348 button.setAttribute("title", currentTitle); 349 button.classList.remove('code-copy-button-checked'); 350 }, 1000); 351 // clear code selection 352 e.clearSelection(); 353 } 354 const getTextToCopy = function(trigger) { 355 const outerScaffold = trigger.parentElement.cloneNode(true); 356 const codeEl = outerScaffold.querySelector('code'); 357 for (const childEl of codeEl.children) { 358 if (isCodeAnnotation(childEl)) { 359 childEl.remove(); 360 } 361 } 362 return codeEl.innerText; 363 } 364 const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', { 365 text: getTextToCopy 366 }); 367 clipboard.on('success', onCopySuccess); 368 if (window.document.getElementById('quarto-embedded-source-code-modal')) { 369 const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', { 370 text: getTextToCopy, 371 container: window.document.getElementById('quarto-embedded-source-code-modal') 372 }); 373 clipboardModal.on('success', onCopySuccess); 374 } 375 var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//); 376 var mailtoRegex = new RegExp(/^mailto:/); 377 var filterRegex = new RegExp("https:\/\/fewslab\.netlify\.app"); 378 var isInternal = (href) => { 379 return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href); 380 } 381 // Inspect non-navigation links and adorn them if external 382 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)'); 383 for (var i=0; i<links.length; i++) { 384 const link = links[i]; 385 if (!isInternal(link.href)) { 386 // undo the damage that might have been done by quarto-nav.js in the case of 387 // links that we want to consider external 388 if (link.dataset.originalHref !== undefined) { 389 link.href = link.dataset.originalHref; 390 } 391 // target, if specified 392 link.setAttribute("target", "_blank"); 393 if (link.getAttribute("rel") === null) { 394 link.setAttribute("rel", "noopener"); 395 } 396 } 397 } 398 function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) { 399 const config = { 400 allowHTML: true, 401 maxWidth: 500, 402 delay: 100, 403 arrow: false, 404 appendTo: function(el) { 405 return el.parentElement; 406 }, 407 interactive: true, 408 interactiveBorder: 10, 409 theme: 'quarto', 410 placement: 'bottom-start', 411 }; 412 if (contentFn) { 413 config.content = contentFn; 414 } 415 if (onTriggerFn) { 416 config.onTrigger = onTriggerFn; 417 } 418 if (onUntriggerFn) { 419 config.onUntrigger = onUntriggerFn; 420 } 421 window.tippy(el, config); 422 } 423 const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]'); 424 for (var i=0; i<noterefs.length; i++) { 425 const ref = noterefs[i]; 426 tippyHover(ref, function() { 427 // use id or data attribute instead here 428 let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href'); 429 try { href = new URL(href).hash; } catch {} 430 const id = href.replace(/^#\/?/, ""); 431 const note = window.document.getElementById(id); 432 if (note) { 433 return note.innerHTML; 434 } else { 435 return ""; 436 } 437 }); 438 } 439 const xrefs = window.document.querySelectorAll('a.quarto-xref'); 440 const processXRef = (id, note) => { 441 // Strip column container classes 442 const stripColumnClz = (el) => { 443 el.classList.remove("page-full", "page-columns"); 444 if (el.children) { 445 for (const child of el.children) {
446 stripColumnClz(child); 447 } 448 } 449 } 450 stripColumnClz(note) 451 if (id === null || id.startsWith('sec-')) { 452 // Special case sections, only their first couple elements 453 const container = document.createElement("div"); 454 if (note.children && note.children.length > 2) { 455 container.appendChild(note.children[0].cloneNode(true)); 456 for (let i = 1; i < note.children.length; i++) { 457 const child = note.children[i]; 458 if (child.tagName === "P" && child.innerText === "") { 459 continue; 460 } else { 461 container.appendChild(child.cloneNode(true)); 462 break; 463 } 464 } 465 if (window.Quarto?.typesetMath) { 466 window.Quarto.typesetMath(container); 467 } 468 return container.innerHTML 469 } else { 470 if (window.Quarto?.typesetMath) { 471 window.Quarto.typesetMath(note); 472 } 473 return note.innerHTML; 474 } 475 } else { 476 // Remove any anchor links if they are present 477 const anchorLink = note.querySelector('a.anchorjs-link'); 478 if (anchorLink) { 479 anchorLink.remove(); 480 } 481 if (window.Quarto?.typesetMath) { 482 window.Quarto.typesetMath(note); 483 } 484 if (note.classList.contains("callout")) { 485 return note.outerHTML; 486 } else { 487 return note.innerHTML; 488 } 489 } 490 } 491 for (var i=0; i<xrefs.length; i++) { 492 const xref = xrefs[i]; 493 tippyHover(xref, undefined, function(instance) { 494 instance.disable(); 495 let url = xref.getAttribute('href'); 496 let hash = undefined; 497 if (url.startsWith('#')) { 498 hash = url; 499 } else { 500 try { hash = new URL(url).hash; } catch {} 501 } 502 if (hash) { 503 const id = hash.replace(/^#\/?/, ""); 504 const note = window.document.getElementById(id); 505 if (note !== null) { 506 try { 507 const html = processXRef(id, note.cloneNode(true)); 508 instance.setContent(html); 509 } finally { 510 instance.enable(); 511 instance.show(); 512 } 513 } else { 514 // See if we can fetch this 515 fetch(url.split('#')[0]) 516 .then(res => res.text()) 517 .then(html => { 518 const parser = new DOMParser(); 519 const htmlDoc = parser.parseFromString(html, "text/html"); 520 const note = htmlDoc.getElementById(id); 521 if (note !== null) { 522 const html = processXRef(id, note); 523 instance.setContent(html); 524 } 525 }).finally(() => { 526 instance.enable(); 527 instance.show(); 528 }); 529 } 530 } else { 531 // See if we can fetch a full url (with no hash to target) 532 // This is a special case and we should probably do some content thinning / targeting 533 fetch(url) 534 .then(res => res.text()) 535 .then(html => { 536 const parser = new DOMParser(); 537 const htmlDoc = parser.parseFromString(html, "text/html"); 538 const note = htmlDoc.querySelector('main.content'); 539 if (note !== null) { 540 // This should only happen for chapter cross references 541 // (since there is no id in the URL) 542 // remove the first header 543 if (note.children.length > 0 && note.children[0].tagName === "HEADER") { 544 note.children[0].remove(); 545 } 546 const html = processXRef(null, note); 547 instance.setContent(html); 548 } 549 }).finally(() => { 550 instance.enable(); 551 instance.show(); 552 }); 553 } 554 }, function(instance) { 555 }); 556 } 557 let selectedAnnoteEl; 558 const selectorForAnnotation = ( cell, annotation) => { 559 let cellAttr = 'data-code-cell="' + cell + '"'; 560 let lineAttr = 'data-code-annotation="' + annotation + '"'; 561 const selector = 'span[' + cellAttr + '][' + lineAttr + ']'; 562 return selector; 563 } 564 const selectCodeLines = (annoteEl) => { 565 const doc = window.document; 566 const targetCell = annoteEl.getAttribute("data-target-cell"); 567 const targetAnnotation = annoteEl.getAttribute("data-target-annotation"); 568 const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation)); 569 const lines = annoteSpan.getAttribute("data-code-lines").split(","); 570 const lineIds = lines.map((line) => { 571 return targetCell + "-" + line; 572 }) 573 let top = null; 574 let height = null; 575 let parent = null; 576 if (lineIds.length > 0) { 577 //compute the position of the single el (top and bottom and make a div) 578 const el = window.document.getElementById(lineIds[0]); 579 top = el.offsetTop; 580 height = el.offsetHeight; 581 parent = el.parentElement.parentElement; 582 if (lineIds.length > 1) { 583 const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]); 584 const bottom = lastEl.offsetTop + lastEl.offsetHeight; 585 height = bottom - top; 586 } 587 if (top !== null && height !== null && parent !== null) { 588 // cook up a div (if necessary) and position it 589 let div = window.document.getElementById("code-annotation-line-highlight"); 590 if (div === null) { 591 div = window.document.createElement("div"); 592 div.setAttribute("id", "code-annotation-line-highlight"); 593 div.style.position = 'absolute'; 594 parent.appendChild(div); 595 } 596 div.style.top = top - 2 + "px"; 597 div.style.height = height + 4 + "px"; 598 div.style.left = 0; 599 let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter"); 600 if (gutterDiv === null) { 601 gutterDiv = window.document.createElement("div"); 602 gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter"); 603 gutterDiv.style.position = 'absolute'; 604 const codeCell = window.document.getElementById(targetCell); 605 const gutter = codeCell.querySelector('.code-annotation-gutter'); 606 gutter.appendChild(gutterDiv); 607 } 608 gutterDiv.style.top = top - 2 + "px"; 609 gutterDiv.style.height = height + 4 + "px"; 610 } 611 selectedAnnoteEl = annoteEl; 612 } 613 }; 614 const unselectCodeLines = () => { 615 const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"]; 616 elementsIds.forEach((elId) => { 617 const div = window.document.getElementById(elId); 618 if (div) { 619 div.remove(); 620 } 621 }); 622 selectedAnnoteEl = undefined; 623 }; 624 // Handle positioning of the toggle 625 window.addEventListener( 626 "resize", 627 throttle(() => { 628 elRect = undefined; 629 if (selectedAnnoteEl) { 630 selectCodeLines(selectedAnnoteEl); 631 } 632 }, 10) 633 ); 634 function throttle(fn, ms) { 635 let throttle = false;
636 let timer; 637 return (...args) => { 638 if(!throttle) { // first call gets through 639 fn.apply(this, args); 640 throttle = true; 641 } else { // all the others get throttled 642 if(timer) clearTimeout(timer); // cancel #2 643 timer = setTimeout(() => { 644 fn.apply(this, args); 645 timer = throttle = false; 646 }, ms); 647 } 648 }; 649 } 650 // Attach click handler to the DT 651 const annoteDls = window.document.querySelectorAll('dt[data-target-cell]'); 652 for (const annoteDlNode of annoteDls) { 653 annoteDlNode.addEventListener('click', (event) => { 654 const clickedEl = event.target; 655 if (clickedEl !== selectedAnnoteEl) { 656 unselectCodeLines(); 657 const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active'); 658 if (activeEl) { 659 activeEl.classList.remove('code-annotation-active'); 660 } 661 selectCodeLines(clickedEl); 662 clickedEl.classList.add('code-annotation-active'); 663 } else { 664 // Unselect the line 665 unselectCodeLines(); 666 clickedEl.classList.remove('code-annotation-active'); 667 } 668 }); 669 } 670 const findCites = (el) => { 671 const parentEl = el.parentElement; 672 if (parentEl) { 673 const cites = parentEl.dataset.cites; 674 if (cites) { 675 return { 676 el, 677 cites: cites.split(' ') 678 }; 679 } else { 680 return findCites(el.parentElement) 681 } 682 } else { 683 return undefined; 684 } 685 }; 686 var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]'); 687 for (var i=0; i<bibliorefs.length; i++) { 688 const ref = bibliorefs[i]; 689 const citeInfo = findCites(ref); 690 if (citeInfo) { 691 tippyHover(citeInfo.el, function() { 692 var popup = window.document.createElement('div'); 693 citeInfo.cites.forEach(function(cite) { 694 var citeDiv = window.document.createElement('div'); 695 citeDiv.classList.add('hanging-indent'); 696 citeDiv.classList.add('csl-entry'); 697 var biblioDiv = window.document.getElementById('ref-' + cite); 698 if (biblioDiv) { 699 citeDiv.innerHTML = biblioDiv.innerHTML; 700 } 701 popup.appendChild(citeDiv); 702 }); 703 return popup.innerHTML; 704 }); 705 } 706 } 707 }); 708 </script>
708 709</div> <!-- /content --> 710<footer class="footer"> 711 <div class="nav-footer"> 712 <div class="nav-footer-left"> 713 714 </div> 715 <div class="nav-footer-center"> 716 <ul class="footer-items list-unstyled"> 717 <li class="nav-item"> 718 Contact: <a href="mailto:[email protected]">[email protected]</a><br> 719<a href="https://www.linkedin.com/company/fews-lab" target="_blank"><i class="bi bi-linkedin"></i> FEWsLab</a> 720<a href="https://www.linkedin.com/in/caitlinagrady/" target="_blank"><i class="bi bi-linkedin"></i> Caitlin Grady</a> 721<a href="https://bsky.app/profile/caitlinagrady.bsky.social" target="_blank"><i class="fa fa-brands fa-bluesky"></i> Bluesky</a><br> 722Site made with <a href="https://quarto.org/" target="_blank"><img src="https://quarto.org/favicon.png" width="12"> Quarto</a><br> 723© 2025 FEWsLab 724 </li> 725</ul> 726 </div> 727 <div class="nav-footer-right"> 728 729 </div> 730 </div> 731</footer> 732 733 734 735
736<script src="site_libs/quarto-html/zenscroll-min.js"></script>
736 737</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.