CINXE.COM

Hail | Index

<!DOCTYPE html> <html lang="en"> <head> <title>Hail | Index </title> <meta charset="utf-8"/> <meta name="description" content=""/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700" rel="stylesheet"/> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/> <link rel="shortcut icon" href="/static/hail_logo_sq-sm-opt.ico" type="image/x-icon"/> <link rel="stylesheet" href="/static/css/style.css"/> <link rel="stylesheet" href="/static/css/navbar.css"/> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism.min.css"/> <script> (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) })(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); ga('create', 'UA-86050742-1', 'auto'); ga('send', 'pageview'); </script> </head> <body> <nav class="navbar align-content-start justify-content-start sticky" id="hail-navbar"> <div class="container-fluid align-content-start justify-content-start d-flex" id="hail-container-fluid"> <div class="navbar-header" id="hail-navbar-header"> <a class="navbar-left" id="hail-navbar-brand" href="/"> <img alt="Hail" height="30" id="logo" src="/static/hail-logo-cropped-sm-opt.png" /> </a> <button type="button" id='navbar-toggler' class="navbar-toggler" data-toggle="collapse" data-target="#hail-navbar-collapse" aria-expanded="false"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> </div> <div class="collapse navbar-collapse" id="hail-navbar-collapse"> <input id='search' type='search' placeholder='Search Hail Docs'/> <a id="survey" href="https://forms.gle/ucgu9h35UEkB68FB7"> Fill out the Community Feedback Survey! </a> <ul class="nav navbar-nav navbar-right" id="hail-menu"> <li class="nav-item"> <a href="/docs/0.2/index.html">Query Docs</a> </li> <li class="nav-item"> <a href="/docs/batch/index.html">Batch Docs</a> </li> <li class="nav-item"> <a href="https://discuss.hail.is">Forum</a> </li> <li class="nav-item"> <a href="/references.html">Science</a> </li> <li class="nav-item"> <a href="https://blog.hail.is">Blog</a> </li> <li class="nav-item" style='margin-top:-2px'> <a href="https://github.com/hail-is/hail" class='img-link' target='_blank'> <svg height="32" aria-hidden="true" viewBox="0 0 16 16" version="1.1" width="32" data-view-component="true" class="octicon octicon-mark-github v-align-middle"> <path d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"></path> </svg> </a> </li> </ul> </div> </div> </nav> <div id="main"> <span id='home'> <div id="hero"> <div id="hero-background"></div> <div id="all-hero-content"> <div id="hero-content"> <h1 id="logo-title">Powering genomic analysis, at every scale</h1> <div class="logo-subtitle">Cloud-native genomic dataframes and batch computing</div> <div id="hero-button-container"> <a class="button" href="#install">Install</a> <a class="button" href="#hail-query">Hail Query</a> <a class="button" href="#hail-batch">Hail Batch</a> <a rel="noopener" class="button" href="/gethelp.html">Get Help</a> </div> </div> <div id="hero-content-right"> <pre class="right language-python" style="display:flex;min-width: 500px;"> <img id="reveal-img" src="/static/hail-tutorial-gwas-plot-cropped-opt.png" style="cursor: pointer;width:600px;height:360px;" onclick="reveal(this);" /> <code id="reveal-code" class="language-python" style="display:none;width:600px;height:360px; cursor: pointer;" onclick="hide(this);">import hail as hl mt = hl.read_matrix_table('resources/post_qc.mt') mt = mt.filter_rows(hl.agg.call_stats(mt.GT, mt.alleles).AF[1] > 0.01) pca_scores = hl.hwe_normalized_pca(mt.GT, k = 5, True)[1] mt = mt.annotate_cols(pca = pca_scores[mt.s]) gwas = hl.linear_regression_rows( y=mt.pheno.caffeine_consumption, x=mt.GT.n_alt_alleles(), covariates=[1.0, mt.pheno.is_female, mt.pca.scores[0], mt.pca.scores[1], mt.pca.scores[2]]) p = hl.plot.manhattan(gwas.p_value) show(p) </code> </pre> <div class="logo-subtitle small">GWAS with Hail (click to <span id='reveal-text'>show code</span>)</div> </div> </div> </div> <div id="install" class="about dark" style="z-index:1"> <div class="header-wrap" style="justify-content: center;"> <h1>Install</h1> </div> <div class="about-content columns" style="align-self: center;"> <section style="flex-direction:column;margin:auto;"> <div style="background:white;padding:20px; color:black;text-align:center;margin:20px 0px;display:block;font-family:'Courier New', Courier, monospace"> pip install hail</div> <p> Hail requires Python 3 and the <a rel="noopener" href="https://adoptopenjdk.net/index.html" target="_blank">Java 11 JRE</a>. </p> <p>GNU/Linux will also need the C and C++ standard libraries if not already installed.</p> <p> <a rel="noopener" href="/docs/0.2/getting_started.html">Detailed instructions</a> </p> </section> </div> </div> <div id="hail-query" class="about"> <div class="content"> <div class="header-wrap" styel="justify-content: space-between"> <h1>Hail Query</h1> </div> <div class="about-content columns"> <section> <h4>Simplified Analysis</h4> <p> Hail Query provides powerful, easy-to-use data science tools. Interrogate data at every scale: small datasets on a laptop through to biobank-scale datasets (e.g. UK Biobank, <a rel="noopener" href="https://www.nature.com/immersive/d42859-020-00002-x/index.html">gnomAD</a>, TopMed, FinnGen, and Biobank Japan) in the cloud. </p> </section> <section> <h4>Genomic Dataframes</h4> <p> Modern data science is driven by numeric matrices (see <a rel="noopener" href="https://numpy.org/">Numpy</a>) and tables (see <a rel="noopener" href="https://www.r-project.org/about.html">R</a> dataframes and <a rel="noopener" href="https://pandas.pydata.org">Pandas</a>). While sufficient for many tasks, none of these tools adequately capture the structure of genetic data. Genetic data combines the multiple axes of a matrix (e.g. variants and samples) with the structured data of tables (e.g. genotypes). To support genomic analysis, Hail introduces a powerful and distributed data structure combining features of matrices and dataframes called <a rel="noopener" href="/docs/0.2/overview/matrix_table.html?highlight=matrix%20table" target="_blank">MatrixTable</a>. </p> </section> <section> <h4>Input Unification</h4> <p> The <a rel="noopener" href="/docs/0.2/overview/matrix_table.html?highlight=matrix%20table" target="_blank">Hail MatrixTable</a> unifies a wide range of input formats (e.g. vcf, bgen, plink, tsv, gtf, bed files), and supports scalable queries, even on petabyte-size datasets. Hail's MatrixTable abstraction provides an integrated and scalable analysis platform for science. </p> </section> </div> <a rel="noopener" class="button" href="/tutorial.html" style='align-self:flex-end; margin-top:1rem;'>Learn More</a> </div> </div> <div id="hail-batch" class="about dark"> <div class="content"> <div class="header-wrap" styel="justify-content: space-between"> <h1>Hail Batch</h1> </div> <div class="about-content columns"> <section> <h4>Arbitrary Tools</h4> <p> Hail Batch enables massively parallel execution and composition of arbitrary GNU/Linux tools like PLINK, SAIGE, sed, and even Python scripts that use Hail Query! </p> </section> <section> <h4>Cost-efficiency and Ease-of-use</h4> <p> Hail Batch is cost-efficient and easy-to-use because it automatically and cooperatively manages cloud resources for all users. As an end-user you need only describe which programs to run, with what arguments, and the dependencies between programs. </p> </section> <section> <h4>Scalability and Cost Control</h4> <p> Hail Batch automatically scales to fit the needs of your job. Instead of queueing for limited resources on a fixed-size cluster, your jobs only queue while the service requests more cores from the cloud. Hail Batch also optionally enforces spending limits which protect users from cost overruns. </p> </section> </div> <a rel="noopener" class="button" href="/docs/batch/index.html" style='align-self:flex-end; margin-top:1rem;'>Learn More</a> </div> </div> <div class="about"> <div class="content"> <div class="header-wrap"> <h1>Acknowledgments</h1> </div> <div class="about-content"> <p>The Hail team has several sources of funding at the Broad Institute:</p> <ul> <li> The Stanley Center for Psychiatric Research, which together with Neale Lab has provided an incredibly supportive and stimulating home. </li> <li> Principal Investigator Benjamin Neale, whose scientific leadership has been essential for solving the right problems. </li> <li> Principal Investigator Daniel MacArthur and the other members of the gnomAD council. </li> <li> Jeremy Wertheimer, whose strategic advice and generous philanthropy have been essential for growing the impact of Hail. </li> </ul> <p>We are grateful for generous support from:</p> <ul> <li> The National Institute of Diabetes and Digestive and Kidney Diseases </li> <li>The National Institute of Mental Health</li> <li>The National Human Genome Research Institute</li> </ul> <p>We are grateful for generous past support from:</p> <ul> <li>The Chan Zuckerburg Initiative</li> </ul> <p> We would like to thank <a rel="noopener" href="https://zulipchat.com/" target="_blank">Zulip</a> for supporting open-source by providing free hosting, and YourKit, LLC for generously providing free licenses for <a rel="noopener" href="https://www.yourkit.com/java/profiler/">YourKit Java Profiler</a> for open-source development. </p> </div> </div> </div> <script> const cachedImg = document.getElementById("reveal-img"); const cachedCode = document.getElementById("reveal-code"); const cachedText = document.getElementById("reveal-text"); const defText = cachedText.textContent; function reveal(e) { cachedCode.style.display = "block"; cachedImg.style.display = "none"; cachedText.textContent = "show plot"; } function hide(e) { cachedCode.style.display = "none"; cachedImg.style.display = "initial"; cachedText.textContent = defText; } </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" integrity="sha512-7Tmwzq3E6Wz5Ue1YikHkMXpyno2Qt4xIz9RMdKXHKyRIsmadkS5yUL0v3YM+H2VQLtFy0zw+RvxqOhevZbxWaA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script> requirejs(["https://cdnjs.cloudflare.com/ajax/libs/three.js/r121/three.min.js"], function(THREE) { /*Created by Hail Team copyright 2020. Based on VantaJS, original license follows:*/ /*Copyright 2020 Teng Bao Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* from helpers.js*/ function ri(start, end) { if (start == null) start = 0; if (end == null) end = 1; return Math.floor(start + (Math.random() * ((end - start) + 1))); } function getBrightness(threeColor) { return (0.299 * threeColor.r) + (0.587 * threeColor.g) + (0.114 * threeColor.b); } function getPixelRatio() { return (!window.devicePixelRatio || window.devicePixelRatio < 2) ? 2 : window.devicePixelRatio } /*pruned/extended _base.js + vanta.net.js, focused on performance improvement, drops cpu usage by 75%, reduces memory usage, and introduces hover effects*/ class Viz { constructor(userOptions = {}) { if (!THREE.WebGLRenderer) { console.error("ThreeJS has not been loaded, or WebGL is unsupported"); return; } this.options = Object.assign({ color: 0xff3f81, backgroundColor: 0xfffffff, points: 10, maxDistance: 20, spacing: 15, showDots: true }, userOptions); this.el = document.querySelector(this.options.el); if (!this.el) { console.error(`Cannot find ${this.options.el}`); return; } if (!this.el.style.position == 'absolute') { this.el.style.position = 'absolute'; } this.el.style.opacity = 0; this.hidden = true; this.mouse = { "x": 0, "y": 0, "rawY": 0, "updated": false, "updatedCount": -1, "ran": false }; this.highlightColor = new THREE.Color('purple'); this.cachedColor = new THREE.Color(0x000000); this.options.color = new THREE.Color(this.options.color); this.options.backgroundColor = new THREE.Color(this.options.backgroundColor); this.diffColor = this.options.color.clone().sub(this.options.backgroundColor); this.colorB = getBrightness(new THREE.Color(this.options.color)); this.bgB = getBrightness(new THREE.Color(this.options.backgroundColor)); this.elOffset = this.el.offsetTop; this.elOnscreen = false; this.isScrolling = false; this.resizeTimeout = null; this.postInit = false; this.points = []; this.animationTimeout = null; this.animationLoop = this.animationLoop.bind(this); window.requestAnimationFrame(() => { let canvas = document.createElement('canvas'); let context = canvas.getContext('webgl', { alpha: true, antialias: true }); this.renderer = new THREE.WebGLRenderer({ canvas: canvas, context: context }); this.el.appendChild(this.renderer.domElement); }); const intersectionThreshold = 0.6; const intersectionCallback = (entries) => { if (entries.length > 1) { console.warn("should be observing a single element, ignoring all but first"); } // entries[0].isIntersecting incorrect in firefox this.elOnscreen = entries[0].intersectionRatio > intersectionThreshold; this.interval = 1000 / 12; if (this.elOnscreen) { if (!this.postInit) { try { window.requestAnimationFrame(() => { this.init(); this.listen(); this.then = Date.now(); this.animationLoop(); this.postInit = true; }); } catch (e) { if (this.renderer && this.renderer.domElement) { this.el.removeChild(this.renderer.domElement) } log.error(e); return } return; } this.animationLoop(); return; } }; let observer = new IntersectionObserver(intersectionCallback, { threshold: intersectionThreshold }); window.requestAnimationFrame(() => observer.observe(this.renderer.domElement)); } listen() { this.elOffset = this.el.offsetTop; this.isScrolling = false; this.resizeTimeout = null; window.addEventListener('resize', (e) => this.resize(e)); window.addEventListener('scroll', () => { if (this.isScrolling != null) { window.clearTimeout(this.isScrolling); } this.isScrolling = setTimeout(() => this.isScrolling = null, 100); }); let timeout = null; this.mouse.dontshow = false; window.addEventListener('mousemove', (e) => { if (timeout != null) { clearTimeout(timeout); } timeout = setTimeout(() => { this.onMouseMove2(e) timeout = null; }, this.mouse.dontshow ? 32 : 4); }, false); const d = document.getElementById('hero-content'); const n = document.getElementById('hail-navbar'); d.onmouseover = () => { if (timeout != null) { clearTimeout(timeout); } this.mouse.updated = false; this.mouse.updatedCount = 0; this.mouse.dontshow = true; } d.onmouseout = () => { if (timeout != null) { clearTimeout(timeout); } this.mouse.updated = true; this.mouse.updatedCount = 0; this.mouse.dontshow = false; } n.onmouseover = () => { if (timeout != null) { clearTimeout(timeout); } this.mouse.updated = false; this.mouse.updatedCount = 0; this.mouse.dontshow = true; } n.onmouseout = () => { if (timeout != null) { clearTimeout(timeout); } this.mouse.updated = true; this.mouse.updatedCount = 0; this.mouse.dontshow = false; } } resize(e) { if (this.resizeTimeout != null) { clearTimeout(this.resizeTimeout); } this.resizeTimeout = setTimeout(() => { this.hidden = true; if (this.camera) { this.camera.aspect = this.el.offsetWidth / this.el.offsetHeight; if (typeof this.camera.updateProjectionMatrix === "function") { this.camera.updateProjectionMatrix() } } if (this.renderer) { this.renderer.setSize(this.el.offsetWidth, this.el.offsetHeight) this.renderer.setPixelRatio(getPixelRatio()) } this.animationLoop(); this.resizeTimeout = null; }, 128); } animationLoop(tInterval = 33) { if (!this.hidden && !this.mouse.updated) { if (this.animationTimeout != null) { clearTimeout(this.animationTimeout) this.animationTimeout = null; } return; } if (this.startedAnimation || !this.elOnscreen) { if (this.animationTimeout != null) { clearTimeout(this.animationTimeout) this.animationTimeout = null; } return; } if (this.animationTimeout != null) { clearTimeout(this.animationTimeout); } const now = Date.now(); const delta = now - this.then; if (!this.isScrolling) { if (this.hidden || delta > this.interval) { this.onUpdate() if (this.scene && this.camera) { this.renderer.render(this.scene, this.camera) } this.mouse.updated = false; } } if (this.hidden) { this.startedAnimation = true; window.requestAnimationFrame(() => { this.el.style.opacity = .5; this.hidden = false; this.startedAnimation = false; this.then = now - 1000 - (delta % this.interval); this.animationTimeout = window.setTimeout(() => { this.animationLoop(tInterval); this.animationTimeout = null; }, tInterval); }); return; } this.then = now - (delta % this.interval); } onMouseMove2(e) { if (!this.elOnscreen || this.mouse.dontshow) { return; } if (!this.mouse.ran) { this.mouse.ran = true; return; } if (!this.rayCaster) { this.rayCaster = new THREE.Raycaster() } const ox = e.pageX; const oy = e.pageY - this.elOffset; const x = (ox / this.el.offsetWidth) * 2 - 1; const y = - (oy / this.el.offsetHeight) * 2 + 1; if (x !== this.mouse.x || y !== this.mouse.y) { this.mouse.x = x; this.mouse.y = y; this.mouse.updated = true; this.mouse.updatedCount = 0; this.rayCaster.setFromCamera(new THREE.Vector2(this.mouse.x, this.mouse.y), this.camera); this.animationLoop(); } } genPoint(x, y, z) { const geometry = new THREE.SphereGeometry(0.2, 12, 12); const material = new THREE.MeshLambertMaterial({ color: this.options.color, transparent: true, opacity: .35 }); const sphere = new THREE.Mesh(geometry, material); sphere.position.set(x, y, z); sphere.r = 0.00025 * ((Math.random() * 4) - 2); // rotation rate, larger is faster return sphere; } init() { const group = new THREE.Group(); group.position.set(0, 0, 0); let { points, spacing } = this.options; const numPoints = points * points * 2; this.linePositions = new Float32Array(numPoints * numPoints * 3); this.lineColors = new Float32Array(numPoints * numPoints * 3); const geometry = new THREE.BufferGeometry(); geometry.setAttribute('position', new THREE.BufferAttribute(this.linePositions, 3)); geometry.setAttribute('color', new THREE.BufferAttribute(this.lineColors, 3)); geometry.computeBoundingSphere(); geometry.setDrawRange(0, 0); const material = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors }); material.linewidth = 0.25; this.linesMesh = new THREE.LineSegments(geometry, material); this.linesMesh.renderOrder = 2; group.add(this.linesMesh); for (let i = 0; i <= points; i++) { for (let j = 0; j <= points; j++) { const y = ri(-3, 3) const x = ((i - (points / 2)) * spacing) + ri(-5, 5); let z = ((j - (points / 2)) * spacing) + ri(-5, 5); if (i % 2) { z += spacing * 0.5 }; const p1 = this.genPoint(x, y - ri(5, 15), z); const p2 = this.genPoint(x + ri(-5, 5), y + ri(5, 15), z + ri(-5, 5)); group.add(p1, p2); this.points.push(p1, p2); } } this.renderer.setSize(this.el.offsetWidth, this.el.offsetHeight) this.renderer.setPixelRatio(getPixelRatio()) this.camera = new THREE.PerspectiveCamera(25, this.el.offsetWidth / (this.el.offsetHeight), .01, 10000); this.camera.position.set(50, 100, 150); this.camera.lookAt(0, 0, 0); this.scene = new THREE.Scene(); this.scene.add(this.camera) this.scene.add(new THREE.AmbientLight(0xffffff, 0.75)); this.scene.add(group); } onUpdate() { let vertexpos = 0; let colorpos = 0; let numConnected = 0; let dist, distToMouse, lineColor, p, p2, ang; let affected1 = 0; for (let i = 0; i < this.points.length; i++) { p = this.points[i]; if (this.rayCaster) { if (this.mouse.updated) { distToMouse = (12 - this.rayCaster.ray.distanceToPoint(p.position)) * 0.25; if (distToMouse > 1) { affected1 = 1; p.material.color = this.highlightColor; } else { affected1 = 0; p.material.color = this.options.color; } } else if (p.material.color !== this.options.color) { p.material.color = this.options.color; } } if (p.r !== 0) { ang = Math.atan2(p.position.z, p.position.x) + p.r; dist = Math.sqrt((p.position.z ** 2) + (p.position.x ** 2)); p.position.x = dist * Math.cos(ang); p.position.z = dist * Math.sin(ang); } for (let j = i; j < this.points.length; j++) { p2 = this.points[j] dist = Math.sqrt(((p.position.x - p2.position.x) ** 2) + ((p.position.y - p2.position.y) ** 2) + ((p.position.z - p2.position.z) ** 2)) if (dist >= this.options.maxDistance) { continue; } if (affected1) { lineColor = this.highlightColor; } else { let alpha = ((1.0 - (dist / this.options.maxDistance))); if (alpha < 0) { alpha = 0; } else if (alpha > 1) { alpha = 1; } lineColor = this.options.backgroundColor.clone().lerp(this.options.color, alpha); } this.linePositions[vertexpos++] = p.position.x; this.linePositions[vertexpos++] = p.position.y; this.linePositions[vertexpos++] = p.position.z; this.linePositions[vertexpos++] = p2.position.x; this.linePositions[vertexpos++] = p2.position.y; this.linePositions[vertexpos++] = p2.position.z; this.lineColors[colorpos++] = lineColor.r; this.lineColors[colorpos++] = lineColor.g; this.lineColors[colorpos++] = lineColor.b; this.lineColors[colorpos++] = lineColor.r; this.lineColors[colorpos++] = lineColor.g; this.lineColors[colorpos++] = lineColor.b; numConnected++; } } this.linesMesh.geometry.setDrawRange(0, numConnected * 2); this.linesMesh.geometry.attributes.position.needsUpdate = true; this.linesMesh.geometry.attributes.color.needsUpdate = true; } } new Viz({ el: "#hero-background", points: 10, maxDistance: 23, spacing: 20, backgroundColor: "#fff", color: "#283870", }); }) </script> </span> </div> <script> const cached = document.getElementById("hail-navbar-collapse"); const initialStyle = cached.style.display; document.getElementById("navbar-toggler").addEventListener("click", () => { const computed = getComputedStyle(cached); if (computed.display == 'none') { cached.style.display = 'block'; } else { cached.style.display = initialStyle; } }); (function () { var cpage = location.pathname; var menuItems = document.querySelectorAll('#hail-menu a'); for (var i = 0; i < menuItems.length; i++) { if (menuItems[i].pathname === cpage && menuItems[i].host == location.host) { menuItems[i].className = "active"; return; } } if (cpage === "/" || cpage === "/index.html") { document.getElementById('hail-navbar-brand').className = "active"; }; })(); </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" integrity="sha512-7Tmwzq3E6Wz5Ue1YikHkMXpyno2Qt4xIz9RMdKXHKyRIsmadkS5yUL0v3YM+H2VQLtFy0zw+RvxqOhevZbxWaA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script type="text/javascript"> requirejs(["https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.js"], function(docsearch) { let isHighlighted = false; const cachedSearchInput = document.getElementById("search"); const cachedNavbar = document.getElementById("hail-navbar") cachedSearchInput.addEventListener("keyup", (ev) => { handleSearchKeyUp(cachedSearchInput.value, ev) }); function handleSearchKeyUp(query, ev) { if(ev.keyCode == 13 && !isHighlighted) { location.href = `/search.html?query=${encodeURIComponent(query)}`; } } window.addEventListener("keyup", (ev) => { if(ev.keyCode != 191) { return; } cachedSearchInput.focus(); }) const algoliaOptions = { hitsPerPage: 10, exactOnSingleWordQuery: "word", queryType: "prefixAll", advancedSyntax: true, }; docsearch({ appId: 'SWB3TKBY4S', apiKey: '313905b758e55f2aed5d9fe2fd9d0807', indexName: 'hail_is', inputSelector: '#search', debug: false, // hide on blur handleSelected: function(input, event, suggestion, datasetNumber, context) { isHighlighted = !!suggestion; location.href = suggestion.url; }, queryHook: function(query) { // algolia seems to split on period, but not split queries on period, affects methods search return query.replace(/\./g, " "); }, autocompleteOptions: { autoselect: false }, algoliaOptions: algoliaOptions, }); const cachedAlgolia = document.querySelector("#algolia-autocomplete-listbox-0 > .ds-dataset-1"); cachedAlgolia.style.overflow = 'scroll'; cachedAlgolia.style.maxHeight = `${window.innerHeight - cachedNavbar.offsetHeight}px`; let evTimeout = null; const ev = window.addEventListener("resize", () => { if (evTimeout) { clearTimeout(evTimeout); } evTimeout = setTimeout(() => { cachedAlgolia.style.maxHeight = `${window.innerHeight - cachedNavbar.offsetHeight}px`; evTimeout = null; }, 100); }) }); </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/components/prism-core.min.js" integrity="sha512-wstmAnvcHpCrEIjaT/G9dgWhJUgtf4mlp+RUBds/CxgjKAy67VkD9qbY3IGUk7Ri/syWJ3H18rYuyGei2cGQrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/components/prism-python.min.js" integrity="sha512-MkilXdEDuAGfyVcMLmLt0qIJuF/k0Tt3gQ417QkVKn0O7SqQ3ugRkLY21o1ze2LHo2mhmeef8C/Wu7W4r0Gw6w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10