diff --git a/.buildinfo b/.buildinfo new file mode 100644 index 0000000..9f0acc7 --- /dev/null +++ b/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: fd8ea45cda0bf6a8165e8a72a61a1875 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/.github/scripts/yamlheader.html b/.github/scripts/yamlheader.html new file mode 100644 index 0000000..55e553b --- /dev/null +++ b/.github/scripts/yamlheader.html @@ -0,0 +1,121 @@ + + +
+ + + +As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
+We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
+Examples of unacceptable behaviour by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
+Instances of abusive, harassing, or otherwise unacceptable behaviour may be reported by opening an issue or contacting one or more of the project maintainers.
+This Code of Conduct is adapted from the Contributor Covenant, version 1.0.0, available at https://contributor-covenant.org/version/1/0/0/.
+Key4hep is an open source project, and we welcome contributions of all kinds:
+New lessons
Fixes to existing material
Bug reports
Reviews of proposed changes
By contributing, you are agreeing that we may redistribute your work under +these licenses. You also agree to abide by our contributor code of +conduct.
+We use the fork and pull model to manage changes. +More information about forking a repository and making a Pull Request.
You should branch from and submit pull requests against the main
branch
+(in some repositories it may still be master
but this will change in the
+future to main
).
If you’re looking for things to work on, feel free to get in touch with the +Key4hep team at key4hep dash sw @ cern dot ch. You can also have a look at +the the list of issues for this repository. Comments on issues and +reviews of pull requests are equally welcome.
Except where otherwise noted, the example programs and other software provided +by Software Carpentry are made available under the OSI-approved Apache +2.0.
+Short
+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 0; + visibility: hidden; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} + +/* By default the copy button shouldn't show up when printing a page */ +@media print { + button.copybtn { + display: none; + } +} diff --git a/_static/copybutton.js b/_static/copybutton.js new file mode 100644 index 0000000..2ea7ff3 --- /dev/null +++ b/_static/copybutton.js @@ -0,0 +1,248 @@ +// Localization support +const messages = { + 'en': { + 'copy': 'Copy', + 'copy_to_clipboard': 'Copy to clipboard', + 'copy_success': 'Copied!', + 'copy_failure': 'Failed to copy', + }, + 'es' : { + 'copy': 'Copiar', + 'copy_to_clipboard': 'Copiar al portapapeles', + 'copy_success': '¡Copiado!', + 'copy_failure': 'Error al copiar', + }, + 'de' : { + 'copy': 'Kopieren', + 'copy_to_clipboard': 'In die Zwischenablage kopieren', + 'copy_success': 'Kopiert!', + 'copy_failure': 'Fehler beim Kopieren', + }, + 'fr' : { + 'copy': 'Copier', + 'copy_to_clipboard': 'Copier dans le presse-papier', + 'copy_success': 'Copié !', + 'copy_failure': 'Échec de la copie', + }, + 'ru': { + 'copy': 'Скопировать', + 'copy_to_clipboard': 'Скопировать в буфер', + 'copy_success': 'Скопировано!', + 'copy_failure': 'Не удалось скопировать', + }, + 'zh-CN': { + 'copy': '复制', + 'copy_to_clipboard': '复制到剪贴板', + 'copy_success': '复制成功!', + 'copy_failure': '复制失败', + }, + 'it' : { + 'copy': 'Copiare', + 'copy_to_clipboard': 'Copiato negli appunti', + 'copy_success': 'Copiato!', + 'copy_failure': 'Errore durante la copia', + } +} + +let locale = 'en' +if( document.documentElement.lang !== undefined + && messages[document.documentElement.lang] !== undefined ) { + locale = document.documentElement.lang +} + +let doc_url_root = DOCUMENTATION_OPTIONS.URL_ROOT; +if (doc_url_root == '#') { + doc_url_root = ''; +} + +/** + * SVG files for our copy buttons + */ +let iconCheck = `` + +// If the user specified their own SVG use that, otherwise use the default +let iconCopy = ``; +if (!iconCopy) { + iconCopy = `` +} + +/** + * Set up copy/paste for code blocks + */ + +const runWhenDOMLoaded = cb => { + if (document.readyState != 'loading') { + cb() + } else if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', cb) + } else { + document.attachEvent('onreadystatechange', function() { + if (document.readyState == 'complete') cb() + }) + } +} + +const codeCellId = index => `codecell${index}` + +// Clears selected text since ClipboardJS will select the text when copying +const clearSelection = () => { + if (window.getSelection) { + window.getSelection().removeAllRanges() + } else if (document.selection) { + document.selection.empty() + } +} + +// Changes tooltip text for a moment, then changes it back +// We want the timeout of our `success` class to be a bit shorter than the +// tooltip and icon change, so that we can hide the icon before changing back. +var timeoutIcon = 2000; +var timeoutSuccessClass = 1500; + +const temporarilyChangeTooltip = (el, oldText, newText) => { + el.setAttribute('data-tooltip', newText) + el.classList.add('success') + // Remove success a little bit sooner than we change the tooltip + // So that we can use CSS to hide the copybutton first + setTimeout(() => el.classList.remove('success'), timeoutSuccessClass) + setTimeout(() => el.setAttribute('data-tooltip', oldText), timeoutIcon) +} + +// Changes the copy button icon for two seconds, then changes it back +const temporarilyChangeIcon = (el) => { + el.innerHTML = iconCheck; + setTimeout(() => {el.innerHTML = iconCopy}, timeoutIcon) +} + +const addCopyButtonToCodeCells = () => { + // If ClipboardJS hasn't loaded, wait a bit and try again. This + // happens because we load ClipboardJS asynchronously. + if (window.ClipboardJS === undefined) { + setTimeout(addCopyButtonToCodeCells, 250) + return + } + + // Add copybuttons to all of our code cells + const COPYBUTTON_SELECTOR = 'div.highlight pre'; + const codeCells = document.querySelectorAll(COPYBUTTON_SELECTOR) + codeCells.forEach((codeCell, index) => { + const id = codeCellId(index) + codeCell.setAttribute('id', id) + + const clipboardButton = id => + `` + codeCell.insertAdjacentHTML('afterend', clipboardButton(id)) + }) + +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} + + +var copyTargetText = (trigger) => { + var target = document.querySelector(trigger.attributes['data-clipboard-target'].value); + + // get filtered text + let exclude = '.linenos'; + + let text = filterText(target, exclude); + return formatCopyText(text, '', false, true, true, true, '', '') +} + + // Initialize with a callback so we can modify the text before copy + const clipboard = new ClipboardJS('.copybtn', {text: copyTargetText}) + + // Update UI with error/success messages + clipboard.on('success', event => { + clearSelection() + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_success']) + temporarilyChangeIcon(event.trigger) + }) + + clipboard.on('error', event => { + temporarilyChangeTooltip(event.trigger, messages[locale]['copy'], messages[locale]['copy_failure']) + }) +} + +runWhenDOMLoaded(addCopyButtonToCodeCells) \ No newline at end of file diff --git a/_static/copybutton_funcs.js b/_static/copybutton_funcs.js new file mode 100644 index 0000000..dbe1aaa --- /dev/null +++ b/_static/copybutton_funcs.js @@ -0,0 +1,73 @@ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Removes excluded text from a Node. + * + * @param {Node} target Node to filter. + * @param {string} exclude CSS selector of nodes to exclude. + * @returns {DOMString} Text from `target` with text removed. + */ +export function filterText(target, exclude) { + const clone = target.cloneNode(true); // clone as to not modify the live DOM + if (exclude) { + // remove excluded nodes + clone.querySelectorAll(exclude).forEach(node => node.remove()); + } + return clone.innerText; +} + +// Callback when a copy button is clicked. Will be passed the node that was clicked +// should then grab the text and replace pieces of text that shouldn't be used in output +export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") { + var regexp; + var match; + + // Do we check for line continuation characters and "HERE-documents"? + var useLineCont = !!lineContinuationChar + var useHereDoc = !!hereDocDelim + + // create regexp to capture prompt and remaining line + if (isRegexp) { + regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)') + } else { + regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)') + } + + const outputLines = []; + var promptFound = false; + var gotLineCont = false; + var gotHereDoc = false; + const lineGotPrompt = []; + for (const line of textContent.split('\n')) { + match = line.match(regexp) + if (match || gotLineCont || gotHereDoc) { + promptFound = regexp.test(line) + lineGotPrompt.push(promptFound) + if (removePrompts && promptFound) { + outputLines.push(match[2]) + } else { + outputLines.push(line) + } + gotLineCont = line.endsWith(lineContinuationChar) & useLineCont + if (line.includes(hereDocDelim) & useHereDoc) + gotHereDoc = !gotHereDoc + } else if (!onlyCopyPromptLines) { + outputLines.push(line) + } else if (copyEmptyLines && line.trim() === '') { + outputLines.push(line) + } + } + + // If no lines with the prompt were found then just use original lines + if (lineGotPrompt.some(v => v === true)) { + textContent = outputLines.join('\n'); + } + + // Remove a trailing newline to avoid auto-running when pasting + if (textContent.endsWith("\n")) { + textContent = textContent.slice(0, -1) + } + return textContent +} diff --git a/_static/css/badge_only.css b/_static/css/badge_only.css new file mode 100644 index 0000000..c718cee --- /dev/null +++ b/_static/css/badge_only.css @@ -0,0 +1 @@ +.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}@font-face{font-family:FontAwesome;font-style:normal;font-weight:400;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#FontAwesome) format("svg")}.fa:before{font-family:FontAwesome;font-style:normal;font-weight:400;line-height:1}.fa:before,a .fa{text-decoration:inherit}.fa:before,a .fa,li .fa{display:inline-block}li .fa-large:before{width:1.875em}ul.fas{list-style-type:none;margin-left:2em;text-indent:-.8em}ul.fas li .fa{width:.8em}ul.fas li .fa-large:before{vertical-align:baseline}.fa-book:before,.icon-book:before{content:"\f02d"}.fa-caret-down:before,.icon-caret-down:before{content:"\f0d7"}.fa-caret-up:before,.icon-caret-up:before{content:"\f0d8"}.fa-caret-left:before,.icon-caret-left:before{content:"\f0d9"}.fa-caret-right:before,.icon-caret-right:before{content:"\f0da"}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60}.rst-versions .rst-current-version:after{clear:both;content:"";display:block}.rst-versions .rst-current-version .fa{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}} \ No newline at end of file diff --git a/_static/css/fonts/Roboto-Slab-Bold.woff b/_static/css/fonts/Roboto-Slab-Bold.woff new file mode 100644 index 0000000..6cb6000 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Bold.woff differ diff --git a/_static/css/fonts/Roboto-Slab-Bold.woff2 b/_static/css/fonts/Roboto-Slab-Bold.woff2 new file mode 100644 index 0000000..7059e23 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Bold.woff2 differ diff --git a/_static/css/fonts/Roboto-Slab-Regular.woff b/_static/css/fonts/Roboto-Slab-Regular.woff new file mode 100644 index 0000000..f815f63 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Regular.woff differ diff --git a/_static/css/fonts/Roboto-Slab-Regular.woff2 b/_static/css/fonts/Roboto-Slab-Regular.woff2 new file mode 100644 index 0000000..f2c76e5 Binary files /dev/null and b/_static/css/fonts/Roboto-Slab-Regular.woff2 differ diff --git a/_static/css/fonts/fontawesome-webfont.eot b/_static/css/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000..e9f60ca Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.eot differ diff --git a/_static/css/fonts/fontawesome-webfont.svg b/_static/css/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000..855c845 --- /dev/null +++ b/_static/css/fonts/fontawesome-webfont.svg @@ -0,0 +1,2671 @@ + + + diff --git a/_static/css/fonts/fontawesome-webfont.ttf b/_static/css/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000..35acda2 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.ttf differ diff --git a/_static/css/fonts/fontawesome-webfont.woff b/_static/css/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000..400014a Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.woff differ diff --git a/_static/css/fonts/fontawesome-webfont.woff2 b/_static/css/fonts/fontawesome-webfont.woff2 new file mode 100644 index 0000000..4d13fc6 Binary files /dev/null and b/_static/css/fonts/fontawesome-webfont.woff2 differ diff --git a/_static/css/fonts/lato-bold-italic.woff b/_static/css/fonts/lato-bold-italic.woff new file mode 100644 index 0000000..88ad05b Binary files /dev/null and b/_static/css/fonts/lato-bold-italic.woff differ diff --git a/_static/css/fonts/lato-bold-italic.woff2 b/_static/css/fonts/lato-bold-italic.woff2 new file mode 100644 index 0000000..c4e3d80 Binary files /dev/null and b/_static/css/fonts/lato-bold-italic.woff2 differ diff --git a/_static/css/fonts/lato-bold.woff b/_static/css/fonts/lato-bold.woff new file mode 100644 index 0000000..c6dff51 Binary files /dev/null and b/_static/css/fonts/lato-bold.woff differ diff --git a/_static/css/fonts/lato-bold.woff2 b/_static/css/fonts/lato-bold.woff2 new file mode 100644 index 0000000..bb19504 Binary files /dev/null and b/_static/css/fonts/lato-bold.woff2 differ diff --git a/_static/css/fonts/lato-normal-italic.woff b/_static/css/fonts/lato-normal-italic.woff new file mode 100644 index 0000000..76114bc Binary files /dev/null and b/_static/css/fonts/lato-normal-italic.woff differ diff --git a/_static/css/fonts/lato-normal-italic.woff2 b/_static/css/fonts/lato-normal-italic.woff2 new file mode 100644 index 0000000..3404f37 Binary files /dev/null and b/_static/css/fonts/lato-normal-italic.woff2 differ diff --git a/_static/css/fonts/lato-normal.woff b/_static/css/fonts/lato-normal.woff new file mode 100644 index 0000000..ae1307f Binary files /dev/null and b/_static/css/fonts/lato-normal.woff differ diff --git a/_static/css/fonts/lato-normal.woff2 b/_static/css/fonts/lato-normal.woff2 new file mode 100644 index 0000000..3bf9843 Binary files /dev/null and b/_static/css/fonts/lato-normal.woff2 differ diff --git a/_static/css/theme.css b/_static/css/theme.css new file mode 100644 index 0000000..19a446a --- /dev/null +++ b/_static/css/theme.css @@ -0,0 +1,4 @@ +html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}[hidden],audio:not([controls]){display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}body{margin:0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}blockquote{margin:0}dfn{font-style:italic}ins{background:#ff9;text-decoration:none}ins,mark{color:#000}mark{background:#ff0;font-style:italic;font-weight:700}.rst-content code,.rst-content tt,code,kbd,pre,samp{font-family:monospace,serif;_font-family:courier new,monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:after,q:before{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}dl,ol,ul{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure,form{margin:0}label{cursor:pointer}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type=button],input[type=reset],input[type=submit]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}textarea{resize:vertical}table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none!important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{body,html,section{background:none!important}*{box-shadow:none!important;text-shadow:none!important;filter:none!important;-ms-filter:none!important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}.rst-content .toctree-wrapper>p.caption,h2,h3,p{orphans:3;widows:3}.rst-content .toctree-wrapper>p.caption,h2,h3{page-break-after:avoid}}.btn,.fa:before,.icon:before,.rst-content .admonition,.rst-content .admonition-title:before,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .code-block-caption .headerlink:before,.rst-content .danger,.rst-content .eqno .headerlink:before,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-alert,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before,input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week],select,textarea{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(fonts/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713?#iefix&v=4.7.0) format("embedded-opentype"),url(fonts/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(fonts/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(fonts/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(fonts/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14286em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14286em;width:2.14286em;top:.14286em;text-align:center}.fa-li.fa-lg{left:-1.85714em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa-pull-left.icon,.fa.fa-pull-left,.rst-content .code-block-caption .fa-pull-left.headerlink,.rst-content .eqno .fa-pull-left.headerlink,.rst-content .fa-pull-left.admonition-title,.rst-content code.download span.fa-pull-left:first-child,.rst-content dl dt .fa-pull-left.headerlink,.rst-content h1 .fa-pull-left.headerlink,.rst-content h2 .fa-pull-left.headerlink,.rst-content h3 .fa-pull-left.headerlink,.rst-content h4 .fa-pull-left.headerlink,.rst-content h5 .fa-pull-left.headerlink,.rst-content h6 .fa-pull-left.headerlink,.rst-content p .fa-pull-left.headerlink,.rst-content table>caption .fa-pull-left.headerlink,.rst-content tt.download span.fa-pull-left:first-child,.wy-menu-vertical li.current>a button.fa-pull-left.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-left.toctree-expand,.wy-menu-vertical li button.fa-pull-left.toctree-expand{margin-right:.3em}.fa-pull-right.icon,.fa.fa-pull-right,.rst-content .code-block-caption .fa-pull-right.headerlink,.rst-content .eqno .fa-pull-right.headerlink,.rst-content .fa-pull-right.admonition-title,.rst-content code.download span.fa-pull-right:first-child,.rst-content dl dt .fa-pull-right.headerlink,.rst-content h1 .fa-pull-right.headerlink,.rst-content h2 .fa-pull-right.headerlink,.rst-content h3 .fa-pull-right.headerlink,.rst-content h4 .fa-pull-right.headerlink,.rst-content h5 .fa-pull-right.headerlink,.rst-content h6 .fa-pull-right.headerlink,.rst-content p .fa-pull-right.headerlink,.rst-content table>caption .fa-pull-right.headerlink,.rst-content tt.download span.fa-pull-right:first-child,.wy-menu-vertical li.current>a button.fa-pull-right.toctree-expand,.wy-menu-vertical li.on a button.fa-pull-right.toctree-expand,.wy-menu-vertical li button.fa-pull-right.toctree-expand{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left,.pull-left.icon,.rst-content .code-block-caption .pull-left.headerlink,.rst-content .eqno .pull-left.headerlink,.rst-content .pull-left.admonition-title,.rst-content code.download span.pull-left:first-child,.rst-content dl dt .pull-left.headerlink,.rst-content h1 .pull-left.headerlink,.rst-content h2 .pull-left.headerlink,.rst-content h3 .pull-left.headerlink,.rst-content h4 .pull-left.headerlink,.rst-content h5 .pull-left.headerlink,.rst-content h6 .pull-left.headerlink,.rst-content p .pull-left.headerlink,.rst-content table>caption .pull-left.headerlink,.rst-content tt.download span.pull-left:first-child,.wy-menu-vertical li.current>a button.pull-left.toctree-expand,.wy-menu-vertical li.on a button.pull-left.toctree-expand,.wy-menu-vertical li button.pull-left.toctree-expand{margin-right:.3em}.fa.pull-right,.pull-right.icon,.rst-content .code-block-caption .pull-right.headerlink,.rst-content .eqno .pull-right.headerlink,.rst-content .pull-right.admonition-title,.rst-content code.download span.pull-right:first-child,.rst-content dl dt .pull-right.headerlink,.rst-content h1 .pull-right.headerlink,.rst-content h2 .pull-right.headerlink,.rst-content h3 .pull-right.headerlink,.rst-content h4 .pull-right.headerlink,.rst-content h5 .pull-right.headerlink,.rst-content h6 .pull-right.headerlink,.rst-content p .pull-right.headerlink,.rst-content table>caption .pull-right.headerlink,.rst-content tt.download span.pull-right:first-child,.wy-menu-vertical li.current>a button.pull-right.toctree-expand,.wy-menu-vertical li.on a button.pull-right.toctree-expand,.wy-menu-vertical li button.pull-right.toctree-expand{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s linear infinite;animation:fa-spin 2s linear infinite}.fa-pulse{-webkit-animation:fa-spin 1s steps(8) infinite;animation:fa-spin 1s steps(8) infinite}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:""}.fa-music:before{content:""}.fa-search:before,.icon-search:before{content:""}.fa-envelope-o:before{content:""}.fa-heart:before{content:""}.fa-star:before{content:""}.fa-star-o:before{content:""}.fa-user:before{content:""}.fa-film:before{content:""}.fa-th-large:before{content:""}.fa-th:before{content:""}.fa-th-list:before{content:""}.fa-check:before{content:""}.fa-close:before,.fa-remove:before,.fa-times:before{content:""}.fa-search-plus:before{content:""}.fa-search-minus:before{content:""}.fa-power-off:before{content:""}.fa-signal:before{content:""}.fa-cog:before,.fa-gear:before{content:""}.fa-trash-o:before{content:""}.fa-home:before,.icon-home:before{content:""}.fa-file-o:before{content:""}.fa-clock-o:before{content:""}.fa-road:before{content:""}.fa-download:before,.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{content:""}.fa-arrow-circle-o-down:before{content:""}.fa-arrow-circle-o-up:before{content:""}.fa-inbox:before{content:""}.fa-play-circle-o:before{content:""}.fa-repeat:before,.fa-rotate-right:before{content:""}.fa-refresh:before{content:""}.fa-list-alt:before{content:""}.fa-lock:before{content:""}.fa-flag:before{content:""}.fa-headphones:before{content:""}.fa-volume-off:before{content:""}.fa-volume-down:before{content:""}.fa-volume-up:before{content:""}.fa-qrcode:before{content:""}.fa-barcode:before{content:""}.fa-tag:before{content:""}.fa-tags:before{content:""}.fa-book:before,.icon-book:before{content:""}.fa-bookmark:before{content:""}.fa-print:before{content:""}.fa-camera:before{content:""}.fa-font:before{content:""}.fa-bold:before{content:""}.fa-italic:before{content:""}.fa-text-height:before{content:""}.fa-text-width:before{content:""}.fa-align-left:before{content:""}.fa-align-center:before{content:""}.fa-align-right:before{content:""}.fa-align-justify:before{content:""}.fa-list:before{content:""}.fa-dedent:before,.fa-outdent:before{content:""}.fa-indent:before{content:""}.fa-video-camera:before{content:""}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:""}.fa-pencil:before{content:""}.fa-map-marker:before{content:""}.fa-adjust:before{content:""}.fa-tint:before{content:""}.fa-edit:before,.fa-pencil-square-o:before{content:""}.fa-share-square-o:before{content:""}.fa-check-square-o:before{content:""}.fa-arrows:before{content:""}.fa-step-backward:before{content:""}.fa-fast-backward:before{content:""}.fa-backward:before{content:""}.fa-play:before{content:""}.fa-pause:before{content:""}.fa-stop:before{content:""}.fa-forward:before{content:""}.fa-fast-forward:before{content:""}.fa-step-forward:before{content:""}.fa-eject:before{content:""}.fa-chevron-left:before{content:""}.fa-chevron-right:before{content:""}.fa-plus-circle:before{content:""}.fa-minus-circle:before{content:""}.fa-times-circle:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before{content:""}.fa-check-circle:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before{content:""}.fa-question-circle:before{content:""}.fa-info-circle:before{content:""}.fa-crosshairs:before{content:""}.fa-times-circle-o:before{content:""}.fa-check-circle-o:before{content:""}.fa-ban:before{content:""}.fa-arrow-left:before{content:""}.fa-arrow-right:before{content:""}.fa-arrow-up:before{content:""}.fa-arrow-down:before{content:""}.fa-mail-forward:before,.fa-share:before{content:""}.fa-expand:before{content:""}.fa-compress:before{content:""}.fa-plus:before{content:""}.fa-minus:before{content:""}.fa-asterisk:before{content:""}.fa-exclamation-circle:before,.rst-content .admonition-title:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before{content:""}.fa-gift:before{content:""}.fa-leaf:before{content:""}.fa-fire:before,.icon-fire:before{content:""}.fa-eye:before{content:""}.fa-eye-slash:before{content:""}.fa-exclamation-triangle:before,.fa-warning:before{content:""}.fa-plane:before{content:""}.fa-calendar:before{content:""}.fa-random:before{content:""}.fa-comment:before{content:""}.fa-magnet:before{content:""}.fa-chevron-up:before{content:""}.fa-chevron-down:before{content:""}.fa-retweet:before{content:""}.fa-shopping-cart:before{content:""}.fa-folder:before{content:""}.fa-folder-open:before{content:""}.fa-arrows-v:before{content:""}.fa-arrows-h:before{content:""}.fa-bar-chart-o:before,.fa-bar-chart:before{content:""}.fa-twitter-square:before{content:""}.fa-facebook-square:before{content:""}.fa-camera-retro:before{content:""}.fa-key:before{content:""}.fa-cogs:before,.fa-gears:before{content:""}.fa-comments:before{content:""}.fa-thumbs-o-up:before{content:""}.fa-thumbs-o-down:before{content:""}.fa-star-half:before{content:""}.fa-heart-o:before{content:""}.fa-sign-out:before{content:""}.fa-linkedin-square:before{content:""}.fa-thumb-tack:before{content:""}.fa-external-link:before{content:""}.fa-sign-in:before{content:""}.fa-trophy:before{content:""}.fa-github-square:before{content:""}.fa-upload:before{content:""}.fa-lemon-o:before{content:""}.fa-phone:before{content:""}.fa-square-o:before{content:""}.fa-bookmark-o:before{content:""}.fa-phone-square:before{content:""}.fa-twitter:before{content:""}.fa-facebook-f:before,.fa-facebook:before{content:""}.fa-github:before,.icon-github:before{content:""}.fa-unlock:before{content:""}.fa-credit-card:before{content:""}.fa-feed:before,.fa-rss:before{content:""}.fa-hdd-o:before{content:""}.fa-bullhorn:before{content:""}.fa-bell:before{content:""}.fa-certificate:before{content:""}.fa-hand-o-right:before{content:""}.fa-hand-o-left:before{content:""}.fa-hand-o-up:before{content:""}.fa-hand-o-down:before{content:""}.fa-arrow-circle-left:before,.icon-circle-arrow-left:before{content:""}.fa-arrow-circle-right:before,.icon-circle-arrow-right:before{content:""}.fa-arrow-circle-up:before{content:""}.fa-arrow-circle-down:before{content:""}.fa-globe:before{content:""}.fa-wrench:before{content:""}.fa-tasks:before{content:""}.fa-filter:before{content:""}.fa-briefcase:before{content:""}.fa-arrows-alt:before{content:""}.fa-group:before,.fa-users:before{content:""}.fa-chain:before,.fa-link:before,.icon-link:before{content:""}.fa-cloud:before{content:""}.fa-flask:before{content:""}.fa-cut:before,.fa-scissors:before{content:""}.fa-copy:before,.fa-files-o:before{content:""}.fa-paperclip:before{content:""}.fa-floppy-o:before,.fa-save:before{content:""}.fa-square:before{content:""}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:""}.fa-list-ul:before{content:""}.fa-list-ol:before{content:""}.fa-strikethrough:before{content:""}.fa-underline:before{content:""}.fa-table:before{content:""}.fa-magic:before{content:""}.fa-truck:before{content:""}.fa-pinterest:before{content:""}.fa-pinterest-square:before{content:""}.fa-google-plus-square:before{content:""}.fa-google-plus:before{content:""}.fa-money:before{content:""}.fa-caret-down:before,.icon-caret-down:before,.wy-dropdown .caret:before{content:""}.fa-caret-up:before{content:""}.fa-caret-left:before{content:""}.fa-caret-right:before{content:""}.fa-columns:before{content:""}.fa-sort:before,.fa-unsorted:before{content:""}.fa-sort-desc:before,.fa-sort-down:before{content:""}.fa-sort-asc:before,.fa-sort-up:before{content:""}.fa-envelope:before{content:""}.fa-linkedin:before{content:""}.fa-rotate-left:before,.fa-undo:before{content:""}.fa-gavel:before,.fa-legal:before{content:""}.fa-dashboard:before,.fa-tachometer:before{content:""}.fa-comment-o:before{content:""}.fa-comments-o:before{content:""}.fa-bolt:before,.fa-flash:before{content:""}.fa-sitemap:before{content:""}.fa-umbrella:before{content:""}.fa-clipboard:before,.fa-paste:before{content:""}.fa-lightbulb-o:before{content:""}.fa-exchange:before{content:""}.fa-cloud-download:before{content:""}.fa-cloud-upload:before{content:""}.fa-user-md:before{content:""}.fa-stethoscope:before{content:""}.fa-suitcase:before{content:""}.fa-bell-o:before{content:""}.fa-coffee:before{content:""}.fa-cutlery:before{content:""}.fa-file-text-o:before{content:""}.fa-building-o:before{content:""}.fa-hospital-o:before{content:""}.fa-ambulance:before{content:""}.fa-medkit:before{content:""}.fa-fighter-jet:before{content:""}.fa-beer:before{content:""}.fa-h-square:before{content:""}.fa-plus-square:before{content:""}.fa-angle-double-left:before{content:""}.fa-angle-double-right:before{content:""}.fa-angle-double-up:before{content:""}.fa-angle-double-down:before{content:""}.fa-angle-left:before{content:""}.fa-angle-right:before{content:""}.fa-angle-up:before{content:""}.fa-angle-down:before{content:""}.fa-desktop:before{content:""}.fa-laptop:before{content:""}.fa-tablet:before{content:""}.fa-mobile-phone:before,.fa-mobile:before{content:""}.fa-circle-o:before{content:""}.fa-quote-left:before{content:""}.fa-quote-right:before{content:""}.fa-spinner:before{content:""}.fa-circle:before{content:""}.fa-mail-reply:before,.fa-reply:before{content:""}.fa-github-alt:before{content:""}.fa-folder-o:before{content:""}.fa-folder-open-o:before{content:""}.fa-smile-o:before{content:""}.fa-frown-o:before{content:""}.fa-meh-o:before{content:""}.fa-gamepad:before{content:""}.fa-keyboard-o:before{content:""}.fa-flag-o:before{content:""}.fa-flag-checkered:before{content:""}.fa-terminal:before{content:""}.fa-code:before{content:""}.fa-mail-reply-all:before,.fa-reply-all:before{content:""}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:""}.fa-location-arrow:before{content:""}.fa-crop:before{content:""}.fa-code-fork:before{content:""}.fa-chain-broken:before,.fa-unlink:before{content:""}.fa-question:before{content:""}.fa-info:before{content:""}.fa-exclamation:before{content:""}.fa-superscript:before{content:""}.fa-subscript:before{content:""}.fa-eraser:before{content:""}.fa-puzzle-piece:before{content:""}.fa-microphone:before{content:""}.fa-microphone-slash:before{content:""}.fa-shield:before{content:""}.fa-calendar-o:before{content:""}.fa-fire-extinguisher:before{content:""}.fa-rocket:before{content:""}.fa-maxcdn:before{content:""}.fa-chevron-circle-left:before{content:""}.fa-chevron-circle-right:before{content:""}.fa-chevron-circle-up:before{content:""}.fa-chevron-circle-down:before{content:""}.fa-html5:before{content:""}.fa-css3:before{content:""}.fa-anchor:before{content:""}.fa-unlock-alt:before{content:""}.fa-bullseye:before{content:""}.fa-ellipsis-h:before{content:""}.fa-ellipsis-v:before{content:""}.fa-rss-square:before{content:""}.fa-play-circle:before{content:""}.fa-ticket:before{content:""}.fa-minus-square:before{content:""}.fa-minus-square-o:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before{content:""}.fa-level-up:before{content:""}.fa-level-down:before{content:""}.fa-check-square:before{content:""}.fa-pencil-square:before{content:""}.fa-external-link-square:before{content:""}.fa-share-square:before{content:""}.fa-compass:before{content:""}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:""}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:""}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:""}.fa-eur:before,.fa-euro:before{content:""}.fa-gbp:before{content:""}.fa-dollar:before,.fa-usd:before{content:""}.fa-inr:before,.fa-rupee:before{content:""}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:""}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:""}.fa-krw:before,.fa-won:before{content:""}.fa-bitcoin:before,.fa-btc:before{content:""}.fa-file:before{content:""}.fa-file-text:before{content:""}.fa-sort-alpha-asc:before{content:""}.fa-sort-alpha-desc:before{content:""}.fa-sort-amount-asc:before{content:""}.fa-sort-amount-desc:before{content:""}.fa-sort-numeric-asc:before{content:""}.fa-sort-numeric-desc:before{content:""}.fa-thumbs-up:before{content:""}.fa-thumbs-down:before{content:""}.fa-youtube-square:before{content:""}.fa-youtube:before{content:""}.fa-xing:before{content:""}.fa-xing-square:before{content:""}.fa-youtube-play:before{content:""}.fa-dropbox:before{content:""}.fa-stack-overflow:before{content:""}.fa-instagram:before{content:""}.fa-flickr:before{content:""}.fa-adn:before{content:""}.fa-bitbucket:before,.icon-bitbucket:before{content:""}.fa-bitbucket-square:before{content:""}.fa-tumblr:before{content:""}.fa-tumblr-square:before{content:""}.fa-long-arrow-down:before{content:""}.fa-long-arrow-up:before{content:""}.fa-long-arrow-left:before{content:""}.fa-long-arrow-right:before{content:""}.fa-apple:before{content:""}.fa-windows:before{content:""}.fa-android:before{content:""}.fa-linux:before{content:""}.fa-dribbble:before{content:""}.fa-skype:before{content:""}.fa-foursquare:before{content:""}.fa-trello:before{content:""}.fa-female:before{content:""}.fa-male:before{content:""}.fa-gittip:before,.fa-gratipay:before{content:""}.fa-sun-o:before{content:""}.fa-moon-o:before{content:""}.fa-archive:before{content:""}.fa-bug:before{content:""}.fa-vk:before{content:""}.fa-weibo:before{content:""}.fa-renren:before{content:""}.fa-pagelines:before{content:""}.fa-stack-exchange:before{content:""}.fa-arrow-circle-o-right:before{content:""}.fa-arrow-circle-o-left:before{content:""}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:""}.fa-dot-circle-o:before{content:""}.fa-wheelchair:before{content:""}.fa-vimeo-square:before{content:""}.fa-try:before,.fa-turkish-lira:before{content:""}.fa-plus-square-o:before,.wy-menu-vertical li button.toctree-expand:before{content:""}.fa-space-shuttle:before{content:""}.fa-slack:before{content:""}.fa-envelope-square:before{content:""}.fa-wordpress:before{content:""}.fa-openid:before{content:""}.fa-bank:before,.fa-institution:before,.fa-university:before{content:""}.fa-graduation-cap:before,.fa-mortar-board:before{content:""}.fa-yahoo:before{content:""}.fa-google:before{content:""}.fa-reddit:before{content:""}.fa-reddit-square:before{content:""}.fa-stumbleupon-circle:before{content:""}.fa-stumbleupon:before{content:""}.fa-delicious:before{content:""}.fa-digg:before{content:""}.fa-pied-piper-pp:before{content:""}.fa-pied-piper-alt:before{content:""}.fa-drupal:before{content:""}.fa-joomla:before{content:""}.fa-language:before{content:""}.fa-fax:before{content:""}.fa-building:before{content:""}.fa-child:before{content:""}.fa-paw:before{content:""}.fa-spoon:before{content:""}.fa-cube:before{content:""}.fa-cubes:before{content:""}.fa-behance:before{content:""}.fa-behance-square:before{content:""}.fa-steam:before{content:""}.fa-steam-square:before{content:""}.fa-recycle:before{content:""}.fa-automobile:before,.fa-car:before{content:""}.fa-cab:before,.fa-taxi:before{content:""}.fa-tree:before{content:""}.fa-spotify:before{content:""}.fa-deviantart:before{content:""}.fa-soundcloud:before{content:""}.fa-database:before{content:""}.fa-file-pdf-o:before{content:""}.fa-file-word-o:before{content:""}.fa-file-excel-o:before{content:""}.fa-file-powerpoint-o:before{content:""}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:""}.fa-file-archive-o:before,.fa-file-zip-o:before{content:""}.fa-file-audio-o:before,.fa-file-sound-o:before{content:""}.fa-file-movie-o:before,.fa-file-video-o:before{content:""}.fa-file-code-o:before{content:""}.fa-vine:before{content:""}.fa-codepen:before{content:""}.fa-jsfiddle:before{content:""}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:""}.fa-circle-o-notch:before{content:""}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:""}.fa-empire:before,.fa-ge:before{content:""}.fa-git-square:before{content:""}.fa-git:before{content:""}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:""}.fa-tencent-weibo:before{content:""}.fa-qq:before{content:""}.fa-wechat:before,.fa-weixin:before{content:""}.fa-paper-plane:before,.fa-send:before{content:""}.fa-paper-plane-o:before,.fa-send-o:before{content:""}.fa-history:before{content:""}.fa-circle-thin:before{content:""}.fa-header:before{content:""}.fa-paragraph:before{content:""}.fa-sliders:before{content:""}.fa-share-alt:before{content:""}.fa-share-alt-square:before{content:""}.fa-bomb:before{content:""}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:""}.fa-tty:before{content:""}.fa-binoculars:before{content:""}.fa-plug:before{content:""}.fa-slideshare:before{content:""}.fa-twitch:before{content:""}.fa-yelp:before{content:""}.fa-newspaper-o:before{content:""}.fa-wifi:before{content:""}.fa-calculator:before{content:""}.fa-paypal:before{content:""}.fa-google-wallet:before{content:""}.fa-cc-visa:before{content:""}.fa-cc-mastercard:before{content:""}.fa-cc-discover:before{content:""}.fa-cc-amex:before{content:""}.fa-cc-paypal:before{content:""}.fa-cc-stripe:before{content:""}.fa-bell-slash:before{content:""}.fa-bell-slash-o:before{content:""}.fa-trash:before{content:""}.fa-copyright:before{content:""}.fa-at:before{content:""}.fa-eyedropper:before{content:""}.fa-paint-brush:before{content:""}.fa-birthday-cake:before{content:""}.fa-area-chart:before{content:""}.fa-pie-chart:before{content:""}.fa-line-chart:before{content:""}.fa-lastfm:before{content:""}.fa-lastfm-square:before{content:""}.fa-toggle-off:before{content:""}.fa-toggle-on:before{content:""}.fa-bicycle:before{content:""}.fa-bus:before{content:""}.fa-ioxhost:before{content:""}.fa-angellist:before{content:""}.fa-cc:before{content:""}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:""}.fa-meanpath:before{content:""}.fa-buysellads:before{content:""}.fa-connectdevelop:before{content:""}.fa-dashcube:before{content:""}.fa-forumbee:before{content:""}.fa-leanpub:before{content:""}.fa-sellsy:before{content:""}.fa-shirtsinbulk:before{content:""}.fa-simplybuilt:before{content:""}.fa-skyatlas:before{content:""}.fa-cart-plus:before{content:""}.fa-cart-arrow-down:before{content:""}.fa-diamond:before{content:""}.fa-ship:before{content:""}.fa-user-secret:before{content:""}.fa-motorcycle:before{content:""}.fa-street-view:before{content:""}.fa-heartbeat:before{content:""}.fa-venus:before{content:""}.fa-mars:before{content:""}.fa-mercury:before{content:""}.fa-intersex:before,.fa-transgender:before{content:""}.fa-transgender-alt:before{content:""}.fa-venus-double:before{content:""}.fa-mars-double:before{content:""}.fa-venus-mars:before{content:""}.fa-mars-stroke:before{content:""}.fa-mars-stroke-v:before{content:""}.fa-mars-stroke-h:before{content:""}.fa-neuter:before{content:""}.fa-genderless:before{content:""}.fa-facebook-official:before{content:""}.fa-pinterest-p:before{content:""}.fa-whatsapp:before{content:""}.fa-server:before{content:""}.fa-user-plus:before{content:""}.fa-user-times:before{content:""}.fa-bed:before,.fa-hotel:before{content:""}.fa-viacoin:before{content:""}.fa-train:before{content:""}.fa-subway:before{content:""}.fa-medium:before{content:""}.fa-y-combinator:before,.fa-yc:before{content:""}.fa-optin-monster:before{content:""}.fa-opencart:before{content:""}.fa-expeditedssl:before{content:""}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:""}.fa-battery-3:before,.fa-battery-three-quarters:before{content:""}.fa-battery-2:before,.fa-battery-half:before{content:""}.fa-battery-1:before,.fa-battery-quarter:before{content:""}.fa-battery-0:before,.fa-battery-empty:before{content:""}.fa-mouse-pointer:before{content:""}.fa-i-cursor:before{content:""}.fa-object-group:before{content:""}.fa-object-ungroup:before{content:""}.fa-sticky-note:before{content:""}.fa-sticky-note-o:before{content:""}.fa-cc-jcb:before{content:""}.fa-cc-diners-club:before{content:""}.fa-clone:before{content:""}.fa-balance-scale:before{content:""}.fa-hourglass-o:before{content:""}.fa-hourglass-1:before,.fa-hourglass-start:before{content:""}.fa-hourglass-2:before,.fa-hourglass-half:before{content:""}.fa-hourglass-3:before,.fa-hourglass-end:before{content:""}.fa-hourglass:before{content:""}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:""}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:""}.fa-hand-scissors-o:before{content:""}.fa-hand-lizard-o:before{content:""}.fa-hand-spock-o:before{content:""}.fa-hand-pointer-o:before{content:""}.fa-hand-peace-o:before{content:""}.fa-trademark:before{content:""}.fa-registered:before{content:""}.fa-creative-commons:before{content:""}.fa-gg:before{content:""}.fa-gg-circle:before{content:""}.fa-tripadvisor:before{content:""}.fa-odnoklassniki:before{content:""}.fa-odnoklassniki-square:before{content:""}.fa-get-pocket:before{content:""}.fa-wikipedia-w:before{content:""}.fa-safari:before{content:""}.fa-chrome:before{content:""}.fa-firefox:before{content:""}.fa-opera:before{content:""}.fa-internet-explorer:before{content:""}.fa-television:before,.fa-tv:before{content:""}.fa-contao:before{content:""}.fa-500px:before{content:""}.fa-amazon:before{content:""}.fa-calendar-plus-o:before{content:""}.fa-calendar-minus-o:before{content:""}.fa-calendar-times-o:before{content:""}.fa-calendar-check-o:before{content:""}.fa-industry:before{content:""}.fa-map-pin:before{content:""}.fa-map-signs:before{content:""}.fa-map-o:before{content:""}.fa-map:before{content:""}.fa-commenting:before{content:""}.fa-commenting-o:before{content:""}.fa-houzz:before{content:""}.fa-vimeo:before{content:""}.fa-black-tie:before{content:""}.fa-fonticons:before{content:""}.fa-reddit-alien:before{content:""}.fa-edge:before{content:""}.fa-credit-card-alt:before{content:""}.fa-codiepie:before{content:""}.fa-modx:before{content:""}.fa-fort-awesome:before{content:""}.fa-usb:before{content:""}.fa-product-hunt:before{content:""}.fa-mixcloud:before{content:""}.fa-scribd:before{content:""}.fa-pause-circle:before{content:""}.fa-pause-circle-o:before{content:""}.fa-stop-circle:before{content:""}.fa-stop-circle-o:before{content:""}.fa-shopping-bag:before{content:""}.fa-shopping-basket:before{content:""}.fa-hashtag:before{content:""}.fa-bluetooth:before{content:""}.fa-bluetooth-b:before{content:""}.fa-percent:before{content:""}.fa-gitlab:before,.icon-gitlab:before{content:""}.fa-wpbeginner:before{content:""}.fa-wpforms:before{content:""}.fa-envira:before{content:""}.fa-universal-access:before{content:""}.fa-wheelchair-alt:before{content:""}.fa-question-circle-o:before{content:""}.fa-blind:before{content:""}.fa-audio-description:before{content:""}.fa-volume-control-phone:before{content:""}.fa-braille:before{content:""}.fa-assistive-listening-systems:before{content:""}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:""}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:""}.fa-glide:before{content:""}.fa-glide-g:before{content:""}.fa-sign-language:before,.fa-signing:before{content:""}.fa-low-vision:before{content:""}.fa-viadeo:before{content:""}.fa-viadeo-square:before{content:""}.fa-snapchat:before{content:""}.fa-snapchat-ghost:before{content:""}.fa-snapchat-square:before{content:""}.fa-pied-piper:before{content:""}.fa-first-order:before{content:""}.fa-yoast:before{content:""}.fa-themeisle:before{content:""}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:""}.fa-fa:before,.fa-font-awesome:before{content:""}.fa-handshake-o:before{content:""}.fa-envelope-open:before{content:""}.fa-envelope-open-o:before{content:""}.fa-linode:before{content:""}.fa-address-book:before{content:""}.fa-address-book-o:before{content:""}.fa-address-card:before,.fa-vcard:before{content:""}.fa-address-card-o:before,.fa-vcard-o:before{content:""}.fa-user-circle:before{content:""}.fa-user-circle-o:before{content:""}.fa-user-o:before{content:""}.fa-id-badge:before{content:""}.fa-drivers-license:before,.fa-id-card:before{content:""}.fa-drivers-license-o:before,.fa-id-card-o:before{content:""}.fa-quora:before{content:""}.fa-free-code-camp:before{content:""}.fa-telegram:before{content:""}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:""}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:""}.fa-thermometer-2:before,.fa-thermometer-half:before{content:""}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:""}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:""}.fa-shower:before{content:""}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:""}.fa-podcast:before{content:""}.fa-window-maximize:before{content:""}.fa-window-minimize:before{content:""}.fa-window-restore:before{content:""}.fa-times-rectangle:before,.fa-window-close:before{content:""}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:""}.fa-bandcamp:before{content:""}.fa-grav:before{content:""}.fa-etsy:before{content:""}.fa-imdb:before{content:""}.fa-ravelry:before{content:""}.fa-eercast:before{content:""}.fa-microchip:before{content:""}.fa-snowflake-o:before{content:""}.fa-superpowers:before{content:""}.fa-wpexplorer:before{content:""}.fa-meetup:before{content:""}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}.fa,.icon,.rst-content .admonition-title,.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content code.download span:first-child,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink,.rst-content tt.download span:first-child,.wy-dropdown .caret,.wy-inline-validate.wy-inline-validate-danger .wy-input-context,.wy-inline-validate.wy-inline-validate-info .wy-input-context,.wy-inline-validate.wy-inline-validate-success .wy-input-context,.wy-inline-validate.wy-inline-validate-warning .wy-input-context,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li button.toctree-expand{font-family:inherit}.fa:before,.icon:before,.rst-content .admonition-title:before,.rst-content .code-block-caption .headerlink:before,.rst-content .eqno .headerlink:before,.rst-content code.download span:first-child:before,.rst-content dl dt .headerlink:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content p.caption .headerlink:before,.rst-content p .headerlink:before,.rst-content table>caption .headerlink:before,.rst-content tt.download span:first-child:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-menu-vertical li.current>a button.toctree-expand:before,.wy-menu-vertical li.on a button.toctree-expand:before,.wy-menu-vertical li button.toctree-expand:before{font-family:FontAwesome;display:inline-block;font-style:normal;font-weight:400;line-height:1;text-decoration:inherit}.rst-content .code-block-caption a .headerlink,.rst-content .eqno a .headerlink,.rst-content a .admonition-title,.rst-content code.download a span:first-child,.rst-content dl dt a .headerlink,.rst-content h1 a .headerlink,.rst-content h2 a .headerlink,.rst-content h3 a .headerlink,.rst-content h4 a .headerlink,.rst-content h5 a .headerlink,.rst-content h6 a .headerlink,.rst-content p.caption a .headerlink,.rst-content p a .headerlink,.rst-content table>caption a .headerlink,.rst-content tt.download a span:first-child,.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand,.wy-menu-vertical li a button.toctree-expand,a .fa,a .icon,a .rst-content .admonition-title,a .rst-content .code-block-caption .headerlink,a .rst-content .eqno .headerlink,a .rst-content code.download span:first-child,a .rst-content dl dt .headerlink,a .rst-content h1 .headerlink,a .rst-content h2 .headerlink,a .rst-content h3 .headerlink,a .rst-content h4 .headerlink,a .rst-content h5 .headerlink,a .rst-content h6 .headerlink,a .rst-content p.caption .headerlink,a .rst-content p .headerlink,a .rst-content table>caption .headerlink,a .rst-content tt.download span:first-child,a .wy-menu-vertical li button.toctree-expand{display:inline-block;text-decoration:inherit}.btn .fa,.btn .icon,.btn .rst-content .admonition-title,.btn .rst-content .code-block-caption .headerlink,.btn .rst-content .eqno .headerlink,.btn .rst-content code.download span:first-child,.btn .rst-content dl dt .headerlink,.btn .rst-content h1 .headerlink,.btn .rst-content h2 .headerlink,.btn .rst-content h3 .headerlink,.btn .rst-content h4 .headerlink,.btn .rst-content h5 .headerlink,.btn .rst-content h6 .headerlink,.btn .rst-content p .headerlink,.btn .rst-content table>caption .headerlink,.btn .rst-content tt.download span:first-child,.btn .wy-menu-vertical li.current>a button.toctree-expand,.btn .wy-menu-vertical li.on a button.toctree-expand,.btn .wy-menu-vertical li button.toctree-expand,.nav .fa,.nav .icon,.nav .rst-content .admonition-title,.nav .rst-content .code-block-caption .headerlink,.nav .rst-content .eqno .headerlink,.nav .rst-content code.download span:first-child,.nav .rst-content dl dt .headerlink,.nav .rst-content h1 .headerlink,.nav .rst-content h2 .headerlink,.nav .rst-content h3 .headerlink,.nav .rst-content h4 .headerlink,.nav .rst-content h5 .headerlink,.nav .rst-content h6 .headerlink,.nav .rst-content p .headerlink,.nav .rst-content table>caption .headerlink,.nav .rst-content tt.download span:first-child,.nav .wy-menu-vertical li.current>a button.toctree-expand,.nav .wy-menu-vertical li.on a button.toctree-expand,.nav .wy-menu-vertical li button.toctree-expand,.rst-content .btn .admonition-title,.rst-content .code-block-caption .btn .headerlink,.rst-content .code-block-caption .nav .headerlink,.rst-content .eqno .btn .headerlink,.rst-content .eqno .nav .headerlink,.rst-content .nav .admonition-title,.rst-content code.download .btn span:first-child,.rst-content code.download .nav span:first-child,.rst-content dl dt .btn .headerlink,.rst-content dl dt .nav .headerlink,.rst-content h1 .btn .headerlink,.rst-content h1 .nav .headerlink,.rst-content h2 .btn .headerlink,.rst-content h2 .nav .headerlink,.rst-content h3 .btn .headerlink,.rst-content h3 .nav .headerlink,.rst-content h4 .btn .headerlink,.rst-content h4 .nav .headerlink,.rst-content h5 .btn .headerlink,.rst-content h5 .nav .headerlink,.rst-content h6 .btn .headerlink,.rst-content h6 .nav .headerlink,.rst-content p .btn .headerlink,.rst-content p .nav .headerlink,.rst-content table>caption .btn .headerlink,.rst-content table>caption .nav .headerlink,.rst-content tt.download .btn span:first-child,.rst-content tt.download .nav span:first-child,.wy-menu-vertical li .btn button.toctree-expand,.wy-menu-vertical li.current>a .btn button.toctree-expand,.wy-menu-vertical li.current>a .nav button.toctree-expand,.wy-menu-vertical li .nav button.toctree-expand,.wy-menu-vertical li.on a .btn button.toctree-expand,.wy-menu-vertical li.on a .nav button.toctree-expand{display:inline}.btn .fa-large.icon,.btn .fa.fa-large,.btn .rst-content .code-block-caption .fa-large.headerlink,.btn .rst-content .eqno .fa-large.headerlink,.btn .rst-content .fa-large.admonition-title,.btn .rst-content code.download span.fa-large:first-child,.btn .rst-content dl dt .fa-large.headerlink,.btn .rst-content h1 .fa-large.headerlink,.btn .rst-content h2 .fa-large.headerlink,.btn .rst-content h3 .fa-large.headerlink,.btn .rst-content h4 .fa-large.headerlink,.btn .rst-content h5 .fa-large.headerlink,.btn .rst-content h6 .fa-large.headerlink,.btn .rst-content p .fa-large.headerlink,.btn .rst-content table>caption .fa-large.headerlink,.btn .rst-content tt.download span.fa-large:first-child,.btn .wy-menu-vertical li button.fa-large.toctree-expand,.nav .fa-large.icon,.nav .fa.fa-large,.nav .rst-content .code-block-caption .fa-large.headerlink,.nav .rst-content .eqno .fa-large.headerlink,.nav .rst-content .fa-large.admonition-title,.nav .rst-content code.download span.fa-large:first-child,.nav .rst-content dl dt .fa-large.headerlink,.nav .rst-content h1 .fa-large.headerlink,.nav .rst-content h2 .fa-large.headerlink,.nav .rst-content h3 .fa-large.headerlink,.nav .rst-content h4 .fa-large.headerlink,.nav .rst-content h5 .fa-large.headerlink,.nav .rst-content h6 .fa-large.headerlink,.nav .rst-content p .fa-large.headerlink,.nav .rst-content table>caption .fa-large.headerlink,.nav .rst-content tt.download span.fa-large:first-child,.nav .wy-menu-vertical li button.fa-large.toctree-expand,.rst-content .btn .fa-large.admonition-title,.rst-content .code-block-caption .btn .fa-large.headerlink,.rst-content .code-block-caption .nav .fa-large.headerlink,.rst-content .eqno .btn .fa-large.headerlink,.rst-content .eqno .nav .fa-large.headerlink,.rst-content .nav .fa-large.admonition-title,.rst-content code.download .btn span.fa-large:first-child,.rst-content code.download .nav span.fa-large:first-child,.rst-content dl dt .btn .fa-large.headerlink,.rst-content dl dt .nav .fa-large.headerlink,.rst-content h1 .btn .fa-large.headerlink,.rst-content h1 .nav .fa-large.headerlink,.rst-content h2 .btn .fa-large.headerlink,.rst-content h2 .nav .fa-large.headerlink,.rst-content h3 .btn .fa-large.headerlink,.rst-content h3 .nav .fa-large.headerlink,.rst-content h4 .btn .fa-large.headerlink,.rst-content h4 .nav .fa-large.headerlink,.rst-content h5 .btn .fa-large.headerlink,.rst-content h5 .nav .fa-large.headerlink,.rst-content h6 .btn .fa-large.headerlink,.rst-content h6 .nav .fa-large.headerlink,.rst-content p .btn .fa-large.headerlink,.rst-content p .nav .fa-large.headerlink,.rst-content table>caption .btn .fa-large.headerlink,.rst-content table>caption .nav .fa-large.headerlink,.rst-content tt.download .btn span.fa-large:first-child,.rst-content tt.download .nav span.fa-large:first-child,.wy-menu-vertical li .btn button.fa-large.toctree-expand,.wy-menu-vertical li .nav button.fa-large.toctree-expand{line-height:.9em}.btn .fa-spin.icon,.btn .fa.fa-spin,.btn .rst-content .code-block-caption .fa-spin.headerlink,.btn .rst-content .eqno .fa-spin.headerlink,.btn .rst-content .fa-spin.admonition-title,.btn .rst-content code.download span.fa-spin:first-child,.btn .rst-content dl dt .fa-spin.headerlink,.btn .rst-content h1 .fa-spin.headerlink,.btn .rst-content h2 .fa-spin.headerlink,.btn .rst-content h3 .fa-spin.headerlink,.btn .rst-content h4 .fa-spin.headerlink,.btn .rst-content h5 .fa-spin.headerlink,.btn .rst-content h6 .fa-spin.headerlink,.btn .rst-content p .fa-spin.headerlink,.btn .rst-content table>caption .fa-spin.headerlink,.btn .rst-content tt.download span.fa-spin:first-child,.btn .wy-menu-vertical li button.fa-spin.toctree-expand,.nav .fa-spin.icon,.nav .fa.fa-spin,.nav .rst-content .code-block-caption .fa-spin.headerlink,.nav .rst-content .eqno .fa-spin.headerlink,.nav .rst-content .fa-spin.admonition-title,.nav .rst-content code.download span.fa-spin:first-child,.nav .rst-content dl dt .fa-spin.headerlink,.nav .rst-content h1 .fa-spin.headerlink,.nav .rst-content h2 .fa-spin.headerlink,.nav .rst-content h3 .fa-spin.headerlink,.nav .rst-content h4 .fa-spin.headerlink,.nav .rst-content h5 .fa-spin.headerlink,.nav .rst-content h6 .fa-spin.headerlink,.nav .rst-content p .fa-spin.headerlink,.nav .rst-content table>caption .fa-spin.headerlink,.nav .rst-content tt.download span.fa-spin:first-child,.nav .wy-menu-vertical li button.fa-spin.toctree-expand,.rst-content .btn .fa-spin.admonition-title,.rst-content .code-block-caption .btn .fa-spin.headerlink,.rst-content .code-block-caption .nav .fa-spin.headerlink,.rst-content .eqno .btn .fa-spin.headerlink,.rst-content .eqno .nav .fa-spin.headerlink,.rst-content .nav .fa-spin.admonition-title,.rst-content code.download .btn span.fa-spin:first-child,.rst-content code.download .nav span.fa-spin:first-child,.rst-content dl dt .btn .fa-spin.headerlink,.rst-content dl dt .nav .fa-spin.headerlink,.rst-content h1 .btn .fa-spin.headerlink,.rst-content h1 .nav .fa-spin.headerlink,.rst-content h2 .btn .fa-spin.headerlink,.rst-content h2 .nav .fa-spin.headerlink,.rst-content h3 .btn .fa-spin.headerlink,.rst-content h3 .nav .fa-spin.headerlink,.rst-content h4 .btn .fa-spin.headerlink,.rst-content h4 .nav .fa-spin.headerlink,.rst-content h5 .btn .fa-spin.headerlink,.rst-content h5 .nav .fa-spin.headerlink,.rst-content h6 .btn .fa-spin.headerlink,.rst-content h6 .nav .fa-spin.headerlink,.rst-content p .btn .fa-spin.headerlink,.rst-content p .nav .fa-spin.headerlink,.rst-content table>caption .btn .fa-spin.headerlink,.rst-content table>caption .nav .fa-spin.headerlink,.rst-content tt.download .btn span.fa-spin:first-child,.rst-content tt.download .nav span.fa-spin:first-child,.wy-menu-vertical li .btn button.fa-spin.toctree-expand,.wy-menu-vertical li .nav button.fa-spin.toctree-expand{display:inline-block}.btn.fa:before,.btn.icon:before,.rst-content .btn.admonition-title:before,.rst-content .code-block-caption .btn.headerlink:before,.rst-content .eqno .btn.headerlink:before,.rst-content code.download span.btn:first-child:before,.rst-content dl dt .btn.headerlink:before,.rst-content h1 .btn.headerlink:before,.rst-content h2 .btn.headerlink:before,.rst-content h3 .btn.headerlink:before,.rst-content h4 .btn.headerlink:before,.rst-content h5 .btn.headerlink:before,.rst-content h6 .btn.headerlink:before,.rst-content p .btn.headerlink:before,.rst-content table>caption .btn.headerlink:before,.rst-content tt.download span.btn:first-child:before,.wy-menu-vertical li button.btn.toctree-expand:before{opacity:.5;-webkit-transition:opacity .05s ease-in;-moz-transition:opacity .05s ease-in;transition:opacity .05s ease-in}.btn.fa:hover:before,.btn.icon:hover:before,.rst-content .btn.admonition-title:hover:before,.rst-content .code-block-caption .btn.headerlink:hover:before,.rst-content .eqno .btn.headerlink:hover:before,.rst-content code.download span.btn:first-child:hover:before,.rst-content dl dt .btn.headerlink:hover:before,.rst-content h1 .btn.headerlink:hover:before,.rst-content h2 .btn.headerlink:hover:before,.rst-content h3 .btn.headerlink:hover:before,.rst-content h4 .btn.headerlink:hover:before,.rst-content h5 .btn.headerlink:hover:before,.rst-content h6 .btn.headerlink:hover:before,.rst-content p .btn.headerlink:hover:before,.rst-content table>caption .btn.headerlink:hover:before,.rst-content tt.download span.btn:first-child:hover:before,.wy-menu-vertical li button.btn.toctree-expand:hover:before{opacity:1}.btn-mini .fa:before,.btn-mini .icon:before,.btn-mini .rst-content .admonition-title:before,.btn-mini .rst-content .code-block-caption .headerlink:before,.btn-mini .rst-content .eqno .headerlink:before,.btn-mini .rst-content code.download span:first-child:before,.btn-mini .rst-content dl dt .headerlink:before,.btn-mini .rst-content h1 .headerlink:before,.btn-mini .rst-content h2 .headerlink:before,.btn-mini .rst-content h3 .headerlink:before,.btn-mini .rst-content h4 .headerlink:before,.btn-mini .rst-content h5 .headerlink:before,.btn-mini .rst-content h6 .headerlink:before,.btn-mini .rst-content p .headerlink:before,.btn-mini .rst-content table>caption .headerlink:before,.btn-mini .rst-content tt.download span:first-child:before,.btn-mini .wy-menu-vertical li button.toctree-expand:before,.rst-content .btn-mini .admonition-title:before,.rst-content .code-block-caption .btn-mini .headerlink:before,.rst-content .eqno .btn-mini .headerlink:before,.rst-content code.download .btn-mini span:first-child:before,.rst-content dl dt .btn-mini .headerlink:before,.rst-content h1 .btn-mini .headerlink:before,.rst-content h2 .btn-mini .headerlink:before,.rst-content h3 .btn-mini .headerlink:before,.rst-content h4 .btn-mini .headerlink:before,.rst-content h5 .btn-mini .headerlink:before,.rst-content h6 .btn-mini .headerlink:before,.rst-content p .btn-mini .headerlink:before,.rst-content table>caption .btn-mini .headerlink:before,.rst-content tt.download .btn-mini span:first-child:before,.wy-menu-vertical li .btn-mini button.toctree-expand:before{font-size:14px;vertical-align:-15%}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning,.wy-alert{padding:12px;line-height:24px;margin-bottom:24px;background:#e7f2fa}.rst-content .admonition-title,.wy-alert-title{font-weight:700;display:block;color:#fff;background:#6ab0de;padding:6px 12px;margin:-12px -12px 12px}.rst-content .danger,.rst-content .error,.rst-content .wy-alert-danger.admonition,.rst-content .wy-alert-danger.admonition-todo,.rst-content .wy-alert-danger.attention,.rst-content .wy-alert-danger.caution,.rst-content .wy-alert-danger.hint,.rst-content .wy-alert-danger.important,.rst-content .wy-alert-danger.note,.rst-content .wy-alert-danger.seealso,.rst-content .wy-alert-danger.tip,.rst-content .wy-alert-danger.warning,.wy-alert.wy-alert-danger{background:#fdf3f2}.rst-content .danger .admonition-title,.rst-content .danger .wy-alert-title,.rst-content .error .admonition-title,.rst-content .error .wy-alert-title,.rst-content .wy-alert-danger.admonition-todo .admonition-title,.rst-content .wy-alert-danger.admonition-todo .wy-alert-title,.rst-content .wy-alert-danger.admonition .admonition-title,.rst-content .wy-alert-danger.admonition .wy-alert-title,.rst-content .wy-alert-danger.attention .admonition-title,.rst-content .wy-alert-danger.attention .wy-alert-title,.rst-content .wy-alert-danger.caution .admonition-title,.rst-content .wy-alert-danger.caution .wy-alert-title,.rst-content .wy-alert-danger.hint .admonition-title,.rst-content .wy-alert-danger.hint .wy-alert-title,.rst-content .wy-alert-danger.important .admonition-title,.rst-content .wy-alert-danger.important .wy-alert-title,.rst-content .wy-alert-danger.note .admonition-title,.rst-content .wy-alert-danger.note .wy-alert-title,.rst-content .wy-alert-danger.seealso .admonition-title,.rst-content .wy-alert-danger.seealso .wy-alert-title,.rst-content .wy-alert-danger.tip .admonition-title,.rst-content .wy-alert-danger.tip .wy-alert-title,.rst-content .wy-alert-danger.warning .admonition-title,.rst-content .wy-alert-danger.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-danger .admonition-title,.wy-alert.wy-alert-danger .rst-content .admonition-title,.wy-alert.wy-alert-danger .wy-alert-title{background:#f29f97}.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .warning,.rst-content .wy-alert-warning.admonition,.rst-content .wy-alert-warning.danger,.rst-content .wy-alert-warning.error,.rst-content .wy-alert-warning.hint,.rst-content .wy-alert-warning.important,.rst-content .wy-alert-warning.note,.rst-content .wy-alert-warning.seealso,.rst-content .wy-alert-warning.tip,.wy-alert.wy-alert-warning{background:#ffedcc}.rst-content .admonition-todo .admonition-title,.rst-content .admonition-todo .wy-alert-title,.rst-content .attention .admonition-title,.rst-content .attention .wy-alert-title,.rst-content .caution .admonition-title,.rst-content .caution .wy-alert-title,.rst-content .warning .admonition-title,.rst-content .warning .wy-alert-title,.rst-content .wy-alert-warning.admonition .admonition-title,.rst-content .wy-alert-warning.admonition .wy-alert-title,.rst-content .wy-alert-warning.danger .admonition-title,.rst-content .wy-alert-warning.danger .wy-alert-title,.rst-content .wy-alert-warning.error .admonition-title,.rst-content .wy-alert-warning.error .wy-alert-title,.rst-content .wy-alert-warning.hint .admonition-title,.rst-content .wy-alert-warning.hint .wy-alert-title,.rst-content .wy-alert-warning.important .admonition-title,.rst-content .wy-alert-warning.important .wy-alert-title,.rst-content .wy-alert-warning.note .admonition-title,.rst-content .wy-alert-warning.note .wy-alert-title,.rst-content .wy-alert-warning.seealso .admonition-title,.rst-content .wy-alert-warning.seealso .wy-alert-title,.rst-content .wy-alert-warning.tip .admonition-title,.rst-content .wy-alert-warning.tip .wy-alert-title,.rst-content .wy-alert.wy-alert-warning .admonition-title,.wy-alert.wy-alert-warning .rst-content .admonition-title,.wy-alert.wy-alert-warning .wy-alert-title{background:#f0b37e}.rst-content .note,.rst-content .seealso,.rst-content .wy-alert-info.admonition,.rst-content .wy-alert-info.admonition-todo,.rst-content .wy-alert-info.attention,.rst-content .wy-alert-info.caution,.rst-content .wy-alert-info.danger,.rst-content .wy-alert-info.error,.rst-content .wy-alert-info.hint,.rst-content .wy-alert-info.important,.rst-content .wy-alert-info.tip,.rst-content .wy-alert-info.warning,.wy-alert.wy-alert-info{background:#e7f2fa}.rst-content .note .admonition-title,.rst-content .note .wy-alert-title,.rst-content .seealso .admonition-title,.rst-content .seealso .wy-alert-title,.rst-content .wy-alert-info.admonition-todo .admonition-title,.rst-content .wy-alert-info.admonition-todo .wy-alert-title,.rst-content .wy-alert-info.admonition .admonition-title,.rst-content .wy-alert-info.admonition .wy-alert-title,.rst-content .wy-alert-info.attention .admonition-title,.rst-content .wy-alert-info.attention .wy-alert-title,.rst-content .wy-alert-info.caution .admonition-title,.rst-content .wy-alert-info.caution .wy-alert-title,.rst-content .wy-alert-info.danger .admonition-title,.rst-content .wy-alert-info.danger .wy-alert-title,.rst-content .wy-alert-info.error .admonition-title,.rst-content .wy-alert-info.error .wy-alert-title,.rst-content .wy-alert-info.hint .admonition-title,.rst-content .wy-alert-info.hint .wy-alert-title,.rst-content .wy-alert-info.important .admonition-title,.rst-content .wy-alert-info.important .wy-alert-title,.rst-content .wy-alert-info.tip .admonition-title,.rst-content .wy-alert-info.tip .wy-alert-title,.rst-content .wy-alert-info.warning .admonition-title,.rst-content .wy-alert-info.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-info .admonition-title,.wy-alert.wy-alert-info .rst-content .admonition-title,.wy-alert.wy-alert-info .wy-alert-title{background:#6ab0de}.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .wy-alert-success.admonition,.rst-content .wy-alert-success.admonition-todo,.rst-content .wy-alert-success.attention,.rst-content .wy-alert-success.caution,.rst-content .wy-alert-success.danger,.rst-content .wy-alert-success.error,.rst-content .wy-alert-success.note,.rst-content .wy-alert-success.seealso,.rst-content .wy-alert-success.warning,.wy-alert.wy-alert-success{background:#dbfaf4}.rst-content .hint .admonition-title,.rst-content .hint .wy-alert-title,.rst-content .important .admonition-title,.rst-content .important .wy-alert-title,.rst-content .tip .admonition-title,.rst-content .tip .wy-alert-title,.rst-content .wy-alert-success.admonition-todo .admonition-title,.rst-content .wy-alert-success.admonition-todo .wy-alert-title,.rst-content .wy-alert-success.admonition .admonition-title,.rst-content .wy-alert-success.admonition .wy-alert-title,.rst-content .wy-alert-success.attention .admonition-title,.rst-content .wy-alert-success.attention .wy-alert-title,.rst-content .wy-alert-success.caution .admonition-title,.rst-content .wy-alert-success.caution .wy-alert-title,.rst-content .wy-alert-success.danger .admonition-title,.rst-content .wy-alert-success.danger .wy-alert-title,.rst-content .wy-alert-success.error .admonition-title,.rst-content .wy-alert-success.error .wy-alert-title,.rst-content .wy-alert-success.note .admonition-title,.rst-content .wy-alert-success.note .wy-alert-title,.rst-content .wy-alert-success.seealso .admonition-title,.rst-content .wy-alert-success.seealso .wy-alert-title,.rst-content .wy-alert-success.warning .admonition-title,.rst-content .wy-alert-success.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-success .admonition-title,.wy-alert.wy-alert-success .rst-content .admonition-title,.wy-alert.wy-alert-success .wy-alert-title{background:#1abc9c}.rst-content .wy-alert-neutral.admonition,.rst-content .wy-alert-neutral.admonition-todo,.rst-content .wy-alert-neutral.attention,.rst-content .wy-alert-neutral.caution,.rst-content .wy-alert-neutral.danger,.rst-content .wy-alert-neutral.error,.rst-content .wy-alert-neutral.hint,.rst-content .wy-alert-neutral.important,.rst-content .wy-alert-neutral.note,.rst-content .wy-alert-neutral.seealso,.rst-content .wy-alert-neutral.tip,.rst-content .wy-alert-neutral.warning,.wy-alert.wy-alert-neutral{background:#f3f6f6}.rst-content .wy-alert-neutral.admonition-todo .admonition-title,.rst-content .wy-alert-neutral.admonition-todo .wy-alert-title,.rst-content .wy-alert-neutral.admonition .admonition-title,.rst-content .wy-alert-neutral.admonition .wy-alert-title,.rst-content .wy-alert-neutral.attention .admonition-title,.rst-content .wy-alert-neutral.attention .wy-alert-title,.rst-content .wy-alert-neutral.caution .admonition-title,.rst-content .wy-alert-neutral.caution .wy-alert-title,.rst-content .wy-alert-neutral.danger .admonition-title,.rst-content .wy-alert-neutral.danger .wy-alert-title,.rst-content .wy-alert-neutral.error .admonition-title,.rst-content .wy-alert-neutral.error .wy-alert-title,.rst-content .wy-alert-neutral.hint .admonition-title,.rst-content .wy-alert-neutral.hint .wy-alert-title,.rst-content .wy-alert-neutral.important .admonition-title,.rst-content .wy-alert-neutral.important .wy-alert-title,.rst-content .wy-alert-neutral.note .admonition-title,.rst-content .wy-alert-neutral.note .wy-alert-title,.rst-content .wy-alert-neutral.seealso .admonition-title,.rst-content .wy-alert-neutral.seealso .wy-alert-title,.rst-content .wy-alert-neutral.tip .admonition-title,.rst-content .wy-alert-neutral.tip .wy-alert-title,.rst-content .wy-alert-neutral.warning .admonition-title,.rst-content .wy-alert-neutral.warning .wy-alert-title,.rst-content .wy-alert.wy-alert-neutral .admonition-title,.wy-alert.wy-alert-neutral .rst-content .admonition-title,.wy-alert.wy-alert-neutral .wy-alert-title{color:#404040;background:#e1e4e5}.rst-content .wy-alert-neutral.admonition-todo a,.rst-content .wy-alert-neutral.admonition a,.rst-content .wy-alert-neutral.attention a,.rst-content .wy-alert-neutral.caution a,.rst-content .wy-alert-neutral.danger a,.rst-content .wy-alert-neutral.error a,.rst-content .wy-alert-neutral.hint a,.rst-content .wy-alert-neutral.important a,.rst-content .wy-alert-neutral.note a,.rst-content .wy-alert-neutral.seealso a,.rst-content .wy-alert-neutral.tip a,.rst-content .wy-alert-neutral.warning a,.wy-alert.wy-alert-neutral a{color:#2980b9}.rst-content .admonition-todo p:last-child,.rst-content .admonition p:last-child,.rst-content .attention p:last-child,.rst-content .caution p:last-child,.rst-content .danger p:last-child,.rst-content .error p:last-child,.rst-content .hint p:last-child,.rst-content .important p:last-child,.rst-content .note p:last-child,.rst-content .seealso p:last-child,.rst-content .tip p:last-child,.rst-content .warning p:last-child,.wy-alert p:last-child{margin-bottom:0}.wy-tray-container{position:fixed;bottom:0;left:0;z-index:600}.wy-tray-container li{display:block;width:300px;background:transparent;color:#fff;text-align:center;box-shadow:0 5px 5px 0 rgba(0,0,0,.1);padding:0 24px;min-width:20%;opacity:0;height:0;line-height:56px;overflow:hidden;-webkit-transition:all .3s ease-in;-moz-transition:all .3s ease-in;transition:all .3s ease-in}.wy-tray-container li.wy-tray-item-success{background:#27ae60}.wy-tray-container li.wy-tray-item-info{background:#2980b9}.wy-tray-container li.wy-tray-item-warning{background:#e67e22}.wy-tray-container li.wy-tray-item-danger{background:#e74c3c}.wy-tray-container li.on{opacity:1;height:56px}@media screen and (max-width:768px){.wy-tray-container{bottom:auto;top:0;width:100%}.wy-tray-container li{width:100%}}button{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle;cursor:pointer;line-height:normal;-webkit-appearance:button;*overflow:visible}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}button[disabled]{cursor:default}.btn{display:inline-block;border-radius:2px;line-height:normal;white-space:nowrap;text-align:center;cursor:pointer;font-size:100%;padding:6px 12px 8px;color:#fff;border:1px solid rgba(0,0,0,.1);background-color:#27ae60;text-decoration:none;font-weight:400;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 2px -1px hsla(0,0%,100%,.5),inset 0 -2px 0 0 rgba(0,0,0,.1);outline-none:false;vertical-align:middle;*display:inline;zoom:1;-webkit-user-drag:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transition:all .1s linear;-moz-transition:all .1s linear;transition:all .1s linear}.btn-hover{background:#2e8ece;color:#fff}.btn:hover{background:#2cc36b;color:#fff}.btn:focus{background:#2cc36b;outline:0}.btn:active{box-shadow:inset 0 -1px 0 0 rgba(0,0,0,.05),inset 0 2px 0 0 rgba(0,0,0,.1);padding:8px 12px 6px}.btn:visited{color:#fff}.btn-disabled,.btn-disabled:active,.btn-disabled:focus,.btn-disabled:hover,.btn:disabled{background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=40);opacity:.4;cursor:not-allowed;box-shadow:none}.btn::-moz-focus-inner{padding:0;border:0}.btn-small{font-size:80%}.btn-info{background-color:#2980b9!important}.btn-info:hover{background-color:#2e8ece!important}.btn-neutral{background-color:#f3f6f6!important;color:#404040!important}.btn-neutral:hover{background-color:#e5ebeb!important;color:#404040}.btn-neutral:visited{color:#404040!important}.btn-success{background-color:#27ae60!important}.btn-success:hover{background-color:#295!important}.btn-danger{background-color:#e74c3c!important}.btn-danger:hover{background-color:#ea6153!important}.btn-warning{background-color:#e67e22!important}.btn-warning:hover{background-color:#e98b39!important}.btn-invert{background-color:#222}.btn-invert:hover{background-color:#2f2f2f!important}.btn-link{background-color:transparent!important;color:#2980b9;box-shadow:none;border-color:transparent!important}.btn-link:active,.btn-link:hover{background-color:transparent!important;color:#409ad5!important;box-shadow:none}.btn-link:visited{color:#9b59b6}.wy-btn-group .btn,.wy-control .btn{vertical-align:middle}.wy-btn-group{margin-bottom:24px;*zoom:1}.wy-btn-group:after,.wy-btn-group:before{display:table;content:""}.wy-btn-group:after{clear:both}.wy-dropdown{position:relative;display:inline-block}.wy-dropdown-active .wy-dropdown-menu{display:block}.wy-dropdown-menu{position:absolute;left:0;display:none;float:left;top:100%;min-width:100%;background:#fcfcfc;z-index:100;border:1px solid #cfd7dd;box-shadow:0 2px 2px 0 rgba(0,0,0,.1);padding:12px}.wy-dropdown-menu>dd>a{display:block;clear:both;color:#404040;white-space:nowrap;font-size:90%;padding:0 12px;cursor:pointer}.wy-dropdown-menu>dd>a:hover{background:#2980b9;color:#fff}.wy-dropdown-menu>dd.divider{border-top:1px solid #cfd7dd;margin:6px 0}.wy-dropdown-menu>dd.search{padding-bottom:12px}.wy-dropdown-menu>dd.search input[type=search]{width:100%}.wy-dropdown-menu>dd.call-to-action{background:#e3e3e3;text-transform:uppercase;font-weight:500;font-size:80%}.wy-dropdown-menu>dd.call-to-action:hover{background:#e3e3e3}.wy-dropdown-menu>dd.call-to-action .btn{color:#fff}.wy-dropdown.wy-dropdown-up .wy-dropdown-menu{bottom:100%;top:auto;left:auto;right:0}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu{background:#fcfcfc;margin-top:2px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a{padding:6px 12px}.wy-dropdown.wy-dropdown-bubble .wy-dropdown-menu a:hover{background:#2980b9;color:#fff}.wy-dropdown.wy-dropdown-left .wy-dropdown-menu{right:0;left:auto;text-align:right}.wy-dropdown-arrow:before{content:" ";border-bottom:5px solid #f5f5f5;border-left:5px solid transparent;border-right:5px solid transparent;position:absolute;display:block;top:-4px;left:50%;margin-left:-3px}.wy-dropdown-arrow.wy-dropdown-arrow-left:before{left:11px}.wy-form-stacked select{display:block}.wy-form-aligned .wy-help-inline,.wy-form-aligned input,.wy-form-aligned label,.wy-form-aligned select,.wy-form-aligned textarea{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-form-aligned .wy-control-group>label{display:inline-block;vertical-align:middle;width:10em;margin:6px 12px 0 0;float:left}.wy-form-aligned .wy-control{float:left}.wy-form-aligned .wy-control label{display:block}.wy-form-aligned .wy-control select{margin-top:6px}fieldset{margin:0}fieldset,legend{border:0;padding:0}legend{width:100%;white-space:normal;margin-bottom:24px;font-size:150%;*margin-left:-7px}label,legend{display:block}label{margin:0 0 .3125em;color:#333;font-size:90%}input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}.wy-control-group{margin-bottom:24px;max-width:1200px;margin-left:auto;margin-right:auto;*zoom:1}.wy-control-group:after,.wy-control-group:before{display:table;content:""}.wy-control-group:after{clear:both}.wy-control-group.wy-control-group-required>label:after{content:" *";color:#e74c3c}.wy-control-group .wy-form-full,.wy-control-group .wy-form-halves,.wy-control-group .wy-form-thirds{padding-bottom:12px}.wy-control-group .wy-form-full input[type=color],.wy-control-group .wy-form-full input[type=date],.wy-control-group .wy-form-full input[type=datetime-local],.wy-control-group .wy-form-full input[type=datetime],.wy-control-group .wy-form-full input[type=email],.wy-control-group .wy-form-full input[type=month],.wy-control-group .wy-form-full input[type=number],.wy-control-group .wy-form-full input[type=password],.wy-control-group .wy-form-full input[type=search],.wy-control-group .wy-form-full input[type=tel],.wy-control-group .wy-form-full input[type=text],.wy-control-group .wy-form-full input[type=time],.wy-control-group .wy-form-full input[type=url],.wy-control-group .wy-form-full input[type=week],.wy-control-group .wy-form-full select,.wy-control-group .wy-form-halves input[type=color],.wy-control-group .wy-form-halves input[type=date],.wy-control-group .wy-form-halves input[type=datetime-local],.wy-control-group .wy-form-halves input[type=datetime],.wy-control-group .wy-form-halves input[type=email],.wy-control-group .wy-form-halves input[type=month],.wy-control-group .wy-form-halves input[type=number],.wy-control-group .wy-form-halves input[type=password],.wy-control-group .wy-form-halves input[type=search],.wy-control-group .wy-form-halves input[type=tel],.wy-control-group .wy-form-halves input[type=text],.wy-control-group .wy-form-halves input[type=time],.wy-control-group .wy-form-halves input[type=url],.wy-control-group .wy-form-halves input[type=week],.wy-control-group .wy-form-halves select,.wy-control-group .wy-form-thirds input[type=color],.wy-control-group .wy-form-thirds input[type=date],.wy-control-group .wy-form-thirds input[type=datetime-local],.wy-control-group .wy-form-thirds input[type=datetime],.wy-control-group .wy-form-thirds input[type=email],.wy-control-group .wy-form-thirds input[type=month],.wy-control-group .wy-form-thirds input[type=number],.wy-control-group .wy-form-thirds input[type=password],.wy-control-group .wy-form-thirds input[type=search],.wy-control-group .wy-form-thirds input[type=tel],.wy-control-group .wy-form-thirds input[type=text],.wy-control-group .wy-form-thirds input[type=time],.wy-control-group .wy-form-thirds input[type=url],.wy-control-group .wy-form-thirds input[type=week],.wy-control-group .wy-form-thirds select{width:100%}.wy-control-group .wy-form-full{float:left;display:block;width:100%;margin-right:0}.wy-control-group .wy-form-full:last-child{margin-right:0}.wy-control-group .wy-form-halves{float:left;display:block;margin-right:2.35765%;width:48.82117%}.wy-control-group .wy-form-halves:last-child,.wy-control-group .wy-form-halves:nth-of-type(2n){margin-right:0}.wy-control-group .wy-form-halves:nth-of-type(odd){clear:left}.wy-control-group .wy-form-thirds{float:left;display:block;margin-right:2.35765%;width:31.76157%}.wy-control-group .wy-form-thirds:last-child,.wy-control-group .wy-form-thirds:nth-of-type(3n){margin-right:0}.wy-control-group .wy-form-thirds:nth-of-type(3n+1){clear:left}.wy-control-group.wy-control-group-no-input .wy-control,.wy-control-no-input{margin:6px 0 0;font-size:90%}.wy-control-no-input{display:inline-block}.wy-control-group.fluid-input input[type=color],.wy-control-group.fluid-input input[type=date],.wy-control-group.fluid-input input[type=datetime-local],.wy-control-group.fluid-input input[type=datetime],.wy-control-group.fluid-input input[type=email],.wy-control-group.fluid-input input[type=month],.wy-control-group.fluid-input input[type=number],.wy-control-group.fluid-input input[type=password],.wy-control-group.fluid-input input[type=search],.wy-control-group.fluid-input input[type=tel],.wy-control-group.fluid-input input[type=text],.wy-control-group.fluid-input input[type=time],.wy-control-group.fluid-input input[type=url],.wy-control-group.fluid-input input[type=week]{width:100%}.wy-form-message-inline{padding-left:.3em;color:#666;font-size:90%}.wy-form-message{display:block;color:#999;font-size:70%;margin-top:.3125em;font-style:italic}.wy-form-message p{font-size:inherit;font-style:italic;margin-bottom:6px}.wy-form-message p:last-child{margin-bottom:0}input{line-height:normal}input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;*overflow:visible}input[type=color],input[type=date],input[type=datetime-local],input[type=datetime],input[type=email],input[type=month],input[type=number],input[type=password],input[type=search],input[type=tel],input[type=text],input[type=time],input[type=url],input[type=week]{-webkit-appearance:none;padding:6px;display:inline-block;border:1px solid #ccc;font-size:80%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;box-shadow:inset 0 1px 3px #ddd;border-radius:0;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}input[type=datetime-local]{padding:.34375em .625em}input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{padding:0;margin-right:.3125em;*height:13px;*width:13px}input[type=checkbox],input[type=radio],input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}input[type=color]:focus,input[type=date]:focus,input[type=datetime-local]:focus,input[type=datetime]:focus,input[type=email]:focus,input[type=month]:focus,input[type=number]:focus,input[type=password]:focus,input[type=search]:focus,input[type=tel]:focus,input[type=text]:focus,input[type=time]:focus,input[type=url]:focus,input[type=week]:focus{outline:0;outline:thin dotted\9;border-color:#333}input.no-focus:focus{border-color:#ccc!important}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:thin dotted #333;outline:1px auto #129fea}input[type=color][disabled],input[type=date][disabled],input[type=datetime-local][disabled],input[type=datetime][disabled],input[type=email][disabled],input[type=month][disabled],input[type=number][disabled],input[type=password][disabled],input[type=search][disabled],input[type=tel][disabled],input[type=text][disabled],input[type=time][disabled],input[type=url][disabled],input[type=week][disabled]{cursor:not-allowed;background-color:#fafafa}input:focus:invalid,select:focus:invalid,textarea:focus:invalid{color:#e74c3c;border:1px solid #e74c3c}input:focus:invalid:focus,select:focus:invalid:focus,textarea:focus:invalid:focus{border-color:#e74c3c}input[type=checkbox]:focus:invalid:focus,input[type=file]:focus:invalid:focus,input[type=radio]:focus:invalid:focus{outline-color:#e74c3c}input.wy-input-large{padding:12px;font-size:100%}textarea{overflow:auto;vertical-align:top;width:100%;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif}select,textarea{padding:.5em .625em;display:inline-block;border:1px solid #ccc;font-size:80%;box-shadow:inset 0 1px 3px #ddd;-webkit-transition:border .3s linear;-moz-transition:border .3s linear;transition:border .3s linear}select{border:1px solid #ccc;background-color:#fff}select[multiple]{height:auto}select:focus,textarea:focus{outline:0}input[readonly],select[disabled],select[readonly],textarea[disabled],textarea[readonly]{cursor:not-allowed;background-color:#fafafa}input[type=checkbox][disabled],input[type=radio][disabled]{cursor:not-allowed}.wy-checkbox,.wy-radio{margin:6px 0;color:#404040;display:block}.wy-checkbox input,.wy-radio input{vertical-align:baseline}.wy-form-message-inline{display:inline-block;*display:inline;*zoom:1;vertical-align:middle}.wy-input-prefix,.wy-input-suffix{white-space:nowrap;padding:6px}.wy-input-prefix .wy-input-context,.wy-input-suffix .wy-input-context{line-height:27px;padding:0 8px;display:inline-block;font-size:80%;background-color:#f3f6f6;border:1px solid #ccc;color:#999}.wy-input-suffix .wy-input-context{border-left:0}.wy-input-prefix .wy-input-context{border-right:0}.wy-switch{position:relative;display:block;height:24px;margin-top:12px;cursor:pointer}.wy-switch:before{left:0;top:0;width:36px;height:12px;background:#ccc}.wy-switch:after,.wy-switch:before{position:absolute;content:"";display:block;border-radius:4px;-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.wy-switch:after{width:18px;height:18px;background:#999;left:-3px;top:-3px}.wy-switch span{position:absolute;left:48px;display:block;font-size:12px;color:#ccc;line-height:1}.wy-switch.active:before{background:#1e8449}.wy-switch.active:after{left:24px;background:#27ae60}.wy-switch.disabled{cursor:not-allowed;opacity:.8}.wy-control-group.wy-control-group-error .wy-form-message,.wy-control-group.wy-control-group-error>label{color:#e74c3c}.wy-control-group.wy-control-group-error input[type=color],.wy-control-group.wy-control-group-error input[type=date],.wy-control-group.wy-control-group-error input[type=datetime-local],.wy-control-group.wy-control-group-error input[type=datetime],.wy-control-group.wy-control-group-error input[type=email],.wy-control-group.wy-control-group-error input[type=month],.wy-control-group.wy-control-group-error input[type=number],.wy-control-group.wy-control-group-error input[type=password],.wy-control-group.wy-control-group-error input[type=search],.wy-control-group.wy-control-group-error input[type=tel],.wy-control-group.wy-control-group-error input[type=text],.wy-control-group.wy-control-group-error input[type=time],.wy-control-group.wy-control-group-error input[type=url],.wy-control-group.wy-control-group-error input[type=week],.wy-control-group.wy-control-group-error textarea{border:1px solid #e74c3c}.wy-inline-validate{white-space:nowrap}.wy-inline-validate .wy-input-context{padding:.5em .625em;display:inline-block;font-size:80%}.wy-inline-validate.wy-inline-validate-success .wy-input-context{color:#27ae60}.wy-inline-validate.wy-inline-validate-danger .wy-input-context{color:#e74c3c}.wy-inline-validate.wy-inline-validate-warning .wy-input-context{color:#e67e22}.wy-inline-validate.wy-inline-validate-info .wy-input-context{color:#2980b9}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.rotate-180{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.rotate-270{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.mirror{-webkit-transform:scaleX(-1);-moz-transform:scaleX(-1);-ms-transform:scaleX(-1);-o-transform:scaleX(-1);transform:scaleX(-1)}.mirror.rotate-90{-webkit-transform:scaleX(-1) rotate(90deg);-moz-transform:scaleX(-1) rotate(90deg);-ms-transform:scaleX(-1) rotate(90deg);-o-transform:scaleX(-1) rotate(90deg);transform:scaleX(-1) rotate(90deg)}.mirror.rotate-180{-webkit-transform:scaleX(-1) rotate(180deg);-moz-transform:scaleX(-1) rotate(180deg);-ms-transform:scaleX(-1) rotate(180deg);-o-transform:scaleX(-1) rotate(180deg);transform:scaleX(-1) rotate(180deg)}.mirror.rotate-270{-webkit-transform:scaleX(-1) rotate(270deg);-moz-transform:scaleX(-1) rotate(270deg);-ms-transform:scaleX(-1) rotate(270deg);-o-transform:scaleX(-1) rotate(270deg);transform:scaleX(-1) rotate(270deg)}@media only screen and (max-width:480px){.wy-form button[type=submit]{margin:.7em 0 0}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=text],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week],.wy-form label{margin-bottom:.3em;display:block}.wy-form input[type=color],.wy-form input[type=date],.wy-form input[type=datetime-local],.wy-form input[type=datetime],.wy-form input[type=email],.wy-form input[type=month],.wy-form input[type=number],.wy-form input[type=password],.wy-form input[type=search],.wy-form input[type=tel],.wy-form input[type=time],.wy-form input[type=url],.wy-form input[type=week]{margin-bottom:0}.wy-form-aligned .wy-control-group label{margin-bottom:.3em;text-align:left;display:block;width:100%}.wy-form-aligned .wy-control{margin:1.5em 0 0}.wy-form-message,.wy-form-message-inline,.wy-form .wy-help-inline{display:block;font-size:80%;padding:6px 0}}@media screen and (max-width:768px){.tablet-hide{display:none}}@media screen and (max-width:480px){.mobile-hide{display:none}}.float-left{float:left}.float-right{float:right}.full-width{width:100%}.rst-content table.docutils,.rst-content table.field-list,.wy-table{border-collapse:collapse;border-spacing:0;empty-cells:show;margin-bottom:24px}.rst-content table.docutils caption,.rst-content table.field-list caption,.wy-table caption{color:#000;font:italic 85%/1 arial,sans-serif;padding:1em 0;text-align:center}.rst-content table.docutils td,.rst-content table.docutils th,.rst-content table.field-list td,.rst-content table.field-list th,.wy-table td,.wy-table th{font-size:90%;margin:0;overflow:visible;padding:8px 16px}.rst-content table.docutils td:first-child,.rst-content table.docutils th:first-child,.rst-content table.field-list td:first-child,.rst-content table.field-list th:first-child,.wy-table td:first-child,.wy-table th:first-child{border-left-width:0}.rst-content table.docutils thead,.rst-content table.field-list thead,.wy-table thead{color:#000;text-align:left;vertical-align:bottom;white-space:nowrap}.rst-content table.docutils thead th,.rst-content table.field-list thead th,.wy-table thead th{font-weight:700;border-bottom:2px solid #e1e4e5}.rst-content table.docutils td,.rst-content table.field-list td,.wy-table td{background-color:transparent;vertical-align:middle}.rst-content table.docutils td p,.rst-content table.field-list td p,.wy-table td p{line-height:18px}.rst-content table.docutils td p:last-child,.rst-content table.field-list td p:last-child,.wy-table td p:last-child{margin-bottom:0}.rst-content table.docutils .wy-table-cell-min,.rst-content table.field-list .wy-table-cell-min,.wy-table .wy-table-cell-min{width:1%;padding-right:0}.rst-content table.docutils .wy-table-cell-min input[type=checkbox],.rst-content table.field-list .wy-table-cell-min input[type=checkbox],.wy-table .wy-table-cell-min input[type=checkbox]{margin:0}.wy-table-secondary{color:grey;font-size:90%}.wy-table-tertiary{color:grey;font-size:80%}.rst-content table.docutils:not(.field-list) tr:nth-child(2n-1) td,.wy-table-backed,.wy-table-odd td,.wy-table-striped tr:nth-child(2n-1) td{background-color:#f3f6f6}.rst-content table.docutils,.wy-table-bordered-all{border:1px solid #e1e4e5}.rst-content table.docutils td,.wy-table-bordered-all td{border-bottom:1px solid #e1e4e5;border-left:1px solid #e1e4e5}.rst-content table.docutils tbody>tr:last-child td,.wy-table-bordered-all tbody>tr:last-child td{border-bottom-width:0}.wy-table-bordered{border:1px solid #e1e4e5}.wy-table-bordered-rows td{border-bottom:1px solid #e1e4e5}.wy-table-bordered-rows tbody>tr:last-child td{border-bottom-width:0}.wy-table-horizontal td,.wy-table-horizontal th{border-width:0 0 1px;border-bottom:1px solid #e1e4e5}.wy-table-horizontal tbody>tr:last-child td{border-bottom-width:0}.wy-table-responsive{margin-bottom:24px;max-width:100%;overflow:auto}.wy-table-responsive table{margin-bottom:0!important}.wy-table-responsive table td,.wy-table-responsive table th{white-space:nowrap}a{color:#2980b9;text-decoration:none;cursor:pointer}a:hover{color:#3091d1}a:visited{color:#9b59b6}html{height:100%}body,html{overflow-x:hidden}body{font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;font-weight:400;color:#404040;min-height:100%;background:#edf0f2}.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22!important}a.wy-text-warning:hover{color:#eb9950!important}.wy-text-info{color:#2980b9!important}a.wy-text-info:hover{color:#409ad5!important}.wy-text-success{color:#27ae60!important}a.wy-text-success:hover{color:#36d278!important}.wy-text-danger{color:#e74c3c!important}a.wy-text-danger:hover{color:#ed7669!important}.wy-text-neutral{color:#404040!important}a.wy-text-neutral:hover{color:#595959!important}.rst-content .toctree-wrapper>p.caption,h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif}p{line-height:24px;font-size:16px;margin:0 0 24px}h1{font-size:175%}.rst-content .toctree-wrapper>p.caption,h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}hr{display:block;height:1px;border:0;border-top:1px solid #e1e4e5;margin:24px 0;padding:0}.rst-content code,.rst-content tt,code{white-space:nowrap;max-width:100%;background:#fff;border:1px solid #e1e4e5;font-size:75%;padding:0 5px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#e74c3c;overflow-x:auto}.rst-content tt.code-large,code.code-large{font-size:90%}.rst-content .section ul,.rst-content .toctree-wrapper ul,.rst-content section ul,.wy-plain-list-disc,article ul{list-style:disc;line-height:24px;margin-bottom:24px}.rst-content .section ul li,.rst-content .toctree-wrapper ul li,.rst-content section ul li,.wy-plain-list-disc li,article ul li{list-style:disc;margin-left:24px}.rst-content .section ul li p:last-child,.rst-content .section ul li ul,.rst-content .toctree-wrapper ul li p:last-child,.rst-content .toctree-wrapper ul li ul,.rst-content section ul li p:last-child,.rst-content section ul li ul,.wy-plain-list-disc li p:last-child,.wy-plain-list-disc li ul,article ul li p:last-child,article ul li ul{margin-bottom:0}.rst-content .section ul li li,.rst-content .toctree-wrapper ul li li,.rst-content section ul li li,.wy-plain-list-disc li li,article ul li li{list-style:circle}.rst-content .section ul li li li,.rst-content .toctree-wrapper ul li li li,.rst-content section ul li li li,.wy-plain-list-disc li li li,article ul li li li{list-style:square}.rst-content .section ul li ol li,.rst-content .toctree-wrapper ul li ol li,.rst-content section ul li ol li,.wy-plain-list-disc li ol li,article ul li ol li{list-style:decimal}.rst-content .section ol,.rst-content .section ol.arabic,.rst-content .toctree-wrapper ol,.rst-content .toctree-wrapper ol.arabic,.rst-content section ol,.rst-content section ol.arabic,.wy-plain-list-decimal,article ol{list-style:decimal;line-height:24px;margin-bottom:24px}.rst-content .section ol.arabic li,.rst-content .section ol li,.rst-content .toctree-wrapper ol.arabic li,.rst-content .toctree-wrapper ol li,.rst-content section ol.arabic li,.rst-content section ol li,.wy-plain-list-decimal li,article ol li{list-style:decimal;margin-left:24px}.rst-content .section ol.arabic li ul,.rst-content .section ol li p:last-child,.rst-content .section ol li ul,.rst-content .toctree-wrapper ol.arabic li ul,.rst-content .toctree-wrapper ol li p:last-child,.rst-content .toctree-wrapper ol li ul,.rst-content section ol.arabic li ul,.rst-content section ol li p:last-child,.rst-content section ol li ul,.wy-plain-list-decimal li p:last-child,.wy-plain-list-decimal li ul,article ol li p:last-child,article ol li ul{margin-bottom:0}.rst-content .section ol.arabic li ul li,.rst-content .section ol li ul li,.rst-content .toctree-wrapper ol.arabic li ul li,.rst-content .toctree-wrapper ol li ul li,.rst-content section ol.arabic li ul li,.rst-content section ol li ul li,.wy-plain-list-decimal li ul li,article ol li ul li{list-style:disc}.wy-breadcrumbs{*zoom:1}.wy-breadcrumbs:after,.wy-breadcrumbs:before{display:table;content:""}.wy-breadcrumbs:after{clear:both}.wy-breadcrumbs>li{display:inline-block;padding-top:5px}.wy-breadcrumbs>li.wy-breadcrumbs-aside{float:right}.rst-content .wy-breadcrumbs>li code,.rst-content .wy-breadcrumbs>li tt,.wy-breadcrumbs>li .rst-content tt,.wy-breadcrumbs>li code{all:inherit;color:inherit}.breadcrumb-item:before{content:"/";color:#bbb;font-size:13px;padding:0 6px 0 3px}.wy-breadcrumbs-extra{margin-bottom:0;color:#b3b3b3;font-size:80%;display:inline-block}@media screen and (max-width:480px){.wy-breadcrumbs-extra,.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}@media print{.wy-breadcrumbs li.wy-breadcrumbs-aside{display:none}}html{font-size:16px}.wy-affix{position:fixed;top:1.618em}.wy-menu a:hover{text-decoration:none}.wy-menu-horiz{*zoom:1}.wy-menu-horiz:after,.wy-menu-horiz:before{display:table;content:""}.wy-menu-horiz:after{clear:both}.wy-menu-horiz li,.wy-menu-horiz ul{display:inline-block}.wy-menu-horiz li:hover{background:hsla(0,0%,100%,.1)}.wy-menu-horiz li.divide-left{border-left:1px solid #404040}.wy-menu-horiz li.divide-right{border-right:1px solid #404040}.wy-menu-horiz a{height:32px;display:inline-block;line-height:32px;padding:0 16px}.wy-menu-vertical{width:300px}.wy-menu-vertical header,.wy-menu-vertical p.caption{color:#55a5d9;height:32px;line-height:32px;padding:0 1.618em;margin:12px 0 0;display:block;font-weight:700;text-transform:uppercase;font-size:85%;white-space:nowrap}.wy-menu-vertical ul{margin-bottom:0}.wy-menu-vertical li.divide-top{border-top:1px solid #404040}.wy-menu-vertical li.divide-bottom{border-bottom:1px solid #404040}.wy-menu-vertical li.current{background:#e3e3e3}.wy-menu-vertical li.current a{color:grey;border-right:1px solid #c9c9c9;padding:.4045em 2.427em}.wy-menu-vertical li.current a:hover{background:#d6d6d6}.rst-content .wy-menu-vertical li tt,.wy-menu-vertical li .rst-content tt,.wy-menu-vertical li code{border:none;background:inherit;color:inherit;padding-left:0;padding-right:0}.wy-menu-vertical li button.toctree-expand{display:block;float:left;margin-left:-1.2em;line-height:18px;color:#4d4d4d;border:none;background:none;padding:0}.wy-menu-vertical li.current>a,.wy-menu-vertical li.on a{color:#404040;font-weight:700;position:relative;background:#fcfcfc;border:none;padding:.4045em 1.618em}.wy-menu-vertical li.current>a:hover,.wy-menu-vertical li.on a:hover{background:#fcfcfc}.wy-menu-vertical li.current>a:hover button.toctree-expand,.wy-menu-vertical li.on a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.current>a button.toctree-expand,.wy-menu-vertical li.on a button.toctree-expand{display:block;line-height:18px;color:#333}.wy-menu-vertical li.toctree-l1.current>a{border-bottom:1px solid #c9c9c9;border-top:1px solid #c9c9c9}.wy-menu-vertical .toctree-l1.current .toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .toctree-l11>ul{display:none}.wy-menu-vertical .toctree-l1.current .current.toctree-l2>ul,.wy-menu-vertical .toctree-l2.current .current.toctree-l3>ul,.wy-menu-vertical .toctree-l3.current .current.toctree-l4>ul,.wy-menu-vertical .toctree-l4.current .current.toctree-l5>ul,.wy-menu-vertical .toctree-l5.current .current.toctree-l6>ul,.wy-menu-vertical .toctree-l6.current .current.toctree-l7>ul,.wy-menu-vertical .toctree-l7.current .current.toctree-l8>ul,.wy-menu-vertical .toctree-l8.current .current.toctree-l9>ul,.wy-menu-vertical .toctree-l9.current .current.toctree-l10>ul,.wy-menu-vertical .toctree-l10.current .current.toctree-l11>ul{display:block}.wy-menu-vertical li.toctree-l3,.wy-menu-vertical li.toctree-l4{font-size:.9em}.wy-menu-vertical li.toctree-l2 a,.wy-menu-vertical li.toctree-l3 a,.wy-menu-vertical li.toctree-l4 a,.wy-menu-vertical li.toctree-l5 a,.wy-menu-vertical li.toctree-l6 a,.wy-menu-vertical li.toctree-l7 a,.wy-menu-vertical li.toctree-l8 a,.wy-menu-vertical li.toctree-l9 a,.wy-menu-vertical li.toctree-l10 a{color:#404040}.wy-menu-vertical li.toctree-l2 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l3 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l4 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l5 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l6 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l7 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l8 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l9 a:hover button.toctree-expand,.wy-menu-vertical li.toctree-l10 a:hover button.toctree-expand{color:grey}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a,.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a,.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a,.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a,.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a,.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a,.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a,.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{display:block}.wy-menu-vertical li.toctree-l2.current>a{padding:.4045em 2.427em}.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{padding:.4045em 1.618em .4045em 4.045em}.wy-menu-vertical li.toctree-l3.current>a{padding:.4045em 4.045em}.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{padding:.4045em 1.618em .4045em 5.663em}.wy-menu-vertical li.toctree-l4.current>a{padding:.4045em 5.663em}.wy-menu-vertical li.toctree-l4.current li.toctree-l5>a{padding:.4045em 1.618em .4045em 7.281em}.wy-menu-vertical li.toctree-l5.current>a{padding:.4045em 7.281em}.wy-menu-vertical li.toctree-l5.current li.toctree-l6>a{padding:.4045em 1.618em .4045em 8.899em}.wy-menu-vertical li.toctree-l6.current>a{padding:.4045em 8.899em}.wy-menu-vertical li.toctree-l6.current li.toctree-l7>a{padding:.4045em 1.618em .4045em 10.517em}.wy-menu-vertical li.toctree-l7.current>a{padding:.4045em 10.517em}.wy-menu-vertical li.toctree-l7.current li.toctree-l8>a{padding:.4045em 1.618em .4045em 12.135em}.wy-menu-vertical li.toctree-l8.current>a{padding:.4045em 12.135em}.wy-menu-vertical li.toctree-l8.current li.toctree-l9>a{padding:.4045em 1.618em .4045em 13.753em}.wy-menu-vertical li.toctree-l9.current>a{padding:.4045em 13.753em}.wy-menu-vertical li.toctree-l9.current li.toctree-l10>a{padding:.4045em 1.618em .4045em 15.371em}.wy-menu-vertical li.toctree-l10.current>a{padding:.4045em 15.371em}.wy-menu-vertical li.toctree-l10.current li.toctree-l11>a{padding:.4045em 1.618em .4045em 16.989em}.wy-menu-vertical li.toctree-l2.current>a,.wy-menu-vertical li.toctree-l2.current li.toctree-l3>a{background:#c9c9c9}.wy-menu-vertical li.toctree-l2 button.toctree-expand{color:#a3a3a3}.wy-menu-vertical li.toctree-l3.current>a,.wy-menu-vertical li.toctree-l3.current li.toctree-l4>a{background:#bdbdbd}.wy-menu-vertical li.toctree-l3 button.toctree-expand{color:#969696}.wy-menu-vertical li.current ul{display:block}.wy-menu-vertical li ul{margin-bottom:0;display:none}.wy-menu-vertical li ul li a{margin-bottom:0;color:#d9d9d9;font-weight:400}.wy-menu-vertical a{line-height:18px;padding:.4045em 1.618em;display:block;position:relative;font-size:90%;color:#d9d9d9}.wy-menu-vertical a:hover{background-color:#4e4a4a;cursor:pointer}.wy-menu-vertical a:hover button.toctree-expand{color:#d9d9d9}.wy-menu-vertical a:active{background-color:#2980b9;cursor:pointer;color:#fff}.wy-menu-vertical a:active button.toctree-expand{color:#fff}.wy-side-nav-search{display:block;width:300px;padding:.809em;margin-bottom:.809em;z-index:200;background-color:#2980b9;text-align:center;color:#fcfcfc}.wy-side-nav-search input[type=text]{width:100%;border-radius:50px;padding:6px 12px;border-color:#2472a4}.wy-side-nav-search img{display:block;margin:auto auto .809em;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-side-nav-search .wy-dropdown>a,.wy-side-nav-search>a{color:#fcfcfc;font-size:100%;font-weight:700;display:inline-block;padding:4px 6px;margin-bottom:.809em;max-width:100%}.wy-side-nav-search .wy-dropdown>a:hover,.wy-side-nav-search>a:hover{background:hsla(0,0%,100%,.1)}.wy-side-nav-search .wy-dropdown>a img.logo,.wy-side-nav-search>a img.logo{display:block;margin:0 auto;height:auto;width:auto;border-radius:0;max-width:100%;background:transparent}.wy-side-nav-search .wy-dropdown>a.icon img.logo,.wy-side-nav-search>a.icon img.logo{margin-top:.85em}.wy-side-nav-search>div.version{margin-top:-.4045em;margin-bottom:.809em;font-weight:400;color:hsla(0,0%,100%,.3)}.wy-nav .wy-menu-vertical header{color:#2980b9}.wy-nav .wy-menu-vertical a{color:#b3b3b3}.wy-nav .wy-menu-vertical a:hover{background-color:#2980b9;color:#fff}[data-menu-wrap]{-webkit-transition:all .2s ease-in;-moz-transition:all .2s ease-in;transition:all .2s ease-in;position:absolute;opacity:1;width:100%;opacity:0}[data-menu-wrap].move-center{left:0;right:auto;opacity:1}[data-menu-wrap].move-left{right:auto;left:-100%;opacity:0}[data-menu-wrap].move-right{right:-100%;left:auto;opacity:0}.wy-body-for-nav{background:#fcfcfc}.wy-grid-for-nav{position:absolute;width:100%;height:100%}.wy-nav-side{position:fixed;top:0;bottom:0;left:0;padding-bottom:2em;width:300px;overflow-x:hidden;overflow-y:hidden;min-height:100%;color:#9b9b9b;background:#343131;z-index:200}.wy-side-scroll{width:320px;position:relative;overflow-x:hidden;overflow-y:scroll;height:100%}.wy-nav-top{display:none;background:#2980b9;color:#fff;padding:.4045em .809em;position:relative;line-height:50px;text-align:center;font-size:100%;*zoom:1}.wy-nav-top:after,.wy-nav-top:before{display:table;content:""}.wy-nav-top:after{clear:both}.wy-nav-top a{color:#fff;font-weight:700}.wy-nav-top img{margin-right:12px;height:45px;width:45px;background-color:#2980b9;padding:5px;border-radius:100%}.wy-nav-top i{font-size:30px;float:left;cursor:pointer;padding-top:inherit}.wy-nav-content-wrap{margin-left:300px;background:#fcfcfc;min-height:100%}.wy-nav-content{padding:1.618em 3.236em;height:100%;max-width:800px;margin:auto}.wy-body-mask{position:fixed;width:100%;height:100%;background:rgba(0,0,0,.2);display:none;z-index:499}.wy-body-mask.on{display:block}footer{color:grey}footer p{margin-bottom:12px}.rst-content footer span.commit tt,footer span.commit .rst-content tt,footer span.commit code{padding:0;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:1em;background:none;border:none;color:grey}.rst-footer-buttons{*zoom:1}.rst-footer-buttons:after,.rst-footer-buttons:before{width:100%;display:table;content:""}.rst-footer-buttons:after{clear:both}.rst-breadcrumbs-buttons{margin-top:12px;*zoom:1}.rst-breadcrumbs-buttons:after,.rst-breadcrumbs-buttons:before{display:table;content:""}.rst-breadcrumbs-buttons:after{clear:both}#search-results .search li{margin-bottom:24px;border-bottom:1px solid #e1e4e5;padding-bottom:24px}#search-results .search li:first-child{border-top:1px solid #e1e4e5;padding-top:24px}#search-results .search li a{font-size:120%;margin-bottom:12px;display:inline-block}#search-results .context{color:grey;font-size:90%}.genindextable li>ul{margin-left:24px}@media screen and (max-width:768px){.wy-body-for-nav{background:#fcfcfc}.wy-nav-top{display:block}.wy-nav-side{left:-300px}.wy-nav-side.shift{width:85%;left:0}.wy-menu.wy-menu-vertical,.wy-side-nav-search,.wy-side-scroll{width:auto}.wy-nav-content-wrap{margin-left:0}.wy-nav-content-wrap .wy-nav-content{padding:1.618em}.wy-nav-content-wrap.shift{position:fixed;min-width:100%;left:85%;top:0;height:100%;overflow:hidden}}@media screen and (min-width:1100px){.wy-nav-content-wrap{background:rgba(0,0,0,.05)}.wy-nav-content{margin:0;background:#fcfcfc}}@media print{.rst-versions,.wy-nav-side,footer{display:none}.wy-nav-content-wrap{margin-left:0}}.rst-versions{position:fixed;bottom:0;left:0;width:300px;color:#fcfcfc;background:#1f1d1d;font-family:Lato,proxima-nova,Helvetica Neue,Arial,sans-serif;z-index:400}.rst-versions a{color:#2980b9;text-decoration:none}.rst-versions .rst-badge-small{display:none}.rst-versions .rst-current-version{padding:12px;background-color:#272525;display:block;text-align:right;font-size:90%;cursor:pointer;color:#27ae60;*zoom:1}.rst-versions .rst-current-version:after,.rst-versions .rst-current-version:before{display:table;content:""}.rst-versions .rst-current-version:after{clear:both}.rst-content .code-block-caption .rst-versions .rst-current-version .headerlink,.rst-content .eqno .rst-versions .rst-current-version .headerlink,.rst-content .rst-versions .rst-current-version .admonition-title,.rst-content code.download .rst-versions .rst-current-version span:first-child,.rst-content dl dt .rst-versions .rst-current-version .headerlink,.rst-content h1 .rst-versions .rst-current-version .headerlink,.rst-content h2 .rst-versions .rst-current-version .headerlink,.rst-content h3 .rst-versions .rst-current-version .headerlink,.rst-content h4 .rst-versions .rst-current-version .headerlink,.rst-content h5 .rst-versions .rst-current-version .headerlink,.rst-content h6 .rst-versions .rst-current-version .headerlink,.rst-content p .rst-versions .rst-current-version .headerlink,.rst-content table>caption .rst-versions .rst-current-version .headerlink,.rst-content tt.download .rst-versions .rst-current-version span:first-child,.rst-versions .rst-current-version .fa,.rst-versions .rst-current-version .icon,.rst-versions .rst-current-version .rst-content .admonition-title,.rst-versions .rst-current-version .rst-content .code-block-caption .headerlink,.rst-versions .rst-current-version .rst-content .eqno .headerlink,.rst-versions .rst-current-version .rst-content code.download span:first-child,.rst-versions .rst-current-version .rst-content dl dt .headerlink,.rst-versions .rst-current-version .rst-content h1 .headerlink,.rst-versions .rst-current-version .rst-content h2 .headerlink,.rst-versions .rst-current-version .rst-content h3 .headerlink,.rst-versions .rst-current-version .rst-content h4 .headerlink,.rst-versions .rst-current-version .rst-content h5 .headerlink,.rst-versions .rst-current-version .rst-content h6 .headerlink,.rst-versions .rst-current-version .rst-content p .headerlink,.rst-versions .rst-current-version .rst-content table>caption .headerlink,.rst-versions .rst-current-version .rst-content tt.download span:first-child,.rst-versions .rst-current-version .wy-menu-vertical li button.toctree-expand,.wy-menu-vertical li .rst-versions .rst-current-version button.toctree-expand{color:#fcfcfc}.rst-versions .rst-current-version .fa-book,.rst-versions .rst-current-version .icon-book{float:left}.rst-versions .rst-current-version.rst-out-of-date{background-color:#e74c3c;color:#fff}.rst-versions .rst-current-version.rst-active-old-version{background-color:#f1c40f;color:#000}.rst-versions.shift-up{height:auto;max-height:100%;overflow-y:scroll}.rst-versions.shift-up .rst-other-versions{display:block}.rst-versions .rst-other-versions{font-size:90%;padding:12px;color:grey;display:none}.rst-versions .rst-other-versions hr{display:block;height:1px;border:0;margin:20px 0;padding:0;border-top:1px solid #413d3d}.rst-versions .rst-other-versions dd{display:inline-block;margin:0}.rst-versions .rst-other-versions dd a{display:inline-block;padding:6px;color:#fcfcfc}.rst-versions.rst-badge{width:auto;bottom:20px;right:20px;left:auto;border:none;max-width:300px;max-height:90%}.rst-versions.rst-badge .fa-book,.rst-versions.rst-badge .icon-book{float:none;line-height:30px}.rst-versions.rst-badge.shift-up .rst-current-version{text-align:right}.rst-versions.rst-badge.shift-up .rst-current-version .fa-book,.rst-versions.rst-badge.shift-up .rst-current-version .icon-book{float:left}.rst-versions.rst-badge>.rst-current-version{width:auto;height:30px;line-height:30px;padding:0 6px;display:block;text-align:center}@media screen and (max-width:768px){.rst-versions{width:85%;display:none}.rst-versions.shift{display:block}}.rst-content .toctree-wrapper>p.caption,.rst-content h1,.rst-content h2,.rst-content h3,.rst-content h4,.rst-content h5,.rst-content h6{margin-bottom:24px}.rst-content img{max-width:100%;height:auto}.rst-content div.figure,.rst-content figure{margin-bottom:24px}.rst-content div.figure .caption-text,.rst-content figure .caption-text{font-style:italic}.rst-content div.figure p:last-child.caption,.rst-content figure p:last-child.caption{margin-bottom:0}.rst-content div.figure.align-center,.rst-content figure.align-center{text-align:center}.rst-content .section>a>img,.rst-content .section>img,.rst-content section>a>img,.rst-content section>img{margin-bottom:24px}.rst-content abbr[title]{text-decoration:none}.rst-content.style-external-links a.reference.external:after{font-family:FontAwesome;content:"\f08e";color:#b3b3b3;vertical-align:super;font-size:60%;margin:0 .2em}.rst-content blockquote{margin-left:24px;line-height:24px;margin-bottom:24px}.rst-content pre.literal-block{white-space:pre;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;display:block;overflow:auto}.rst-content div[class^=highlight],.rst-content pre.literal-block{border:1px solid #e1e4e5;overflow-x:auto;margin:1px 0 24px}.rst-content div[class^=highlight] div[class^=highlight],.rst-content pre.literal-block div[class^=highlight]{padding:0;border:none;margin:0}.rst-content div[class^=highlight] td.code{width:100%}.rst-content .linenodiv pre{border-right:1px solid #e6e9ea;margin:0;padding:12px;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;user-select:none;pointer-events:none}.rst-content div[class^=highlight] pre{white-space:pre;margin:0;padding:12px;display:block;overflow:auto}.rst-content div[class^=highlight] pre .hll{display:block;margin:0 -12px;padding:0 12px}.rst-content .linenodiv pre,.rst-content div[class^=highlight] pre,.rst-content pre.literal-block{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;font-size:12px;line-height:1.4}.rst-content div.highlight .gp,.rst-content div.highlight span.linenos{user-select:none;pointer-events:none}.rst-content div.highlight span.linenos{display:inline-block;padding-left:0;padding-right:12px;margin-right:12px;border-right:1px solid #e6e9ea}.rst-content .code-block-caption{font-style:italic;font-size:85%;line-height:1;padding:1em 0;text-align:center}@media print{.rst-content .codeblock,.rst-content div[class^=highlight],.rst-content div[class^=highlight] pre{white-space:pre-wrap}}.rst-content .admonition,.rst-content .admonition-todo,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .note,.rst-content .seealso,.rst-content .tip,.rst-content .warning{clear:both}.rst-content .admonition-todo .last,.rst-content .admonition-todo>:last-child,.rst-content .admonition .last,.rst-content .admonition>:last-child,.rst-content .attention .last,.rst-content .attention>:last-child,.rst-content .caution .last,.rst-content .caution>:last-child,.rst-content .danger .last,.rst-content .danger>:last-child,.rst-content .error .last,.rst-content .error>:last-child,.rst-content .hint .last,.rst-content .hint>:last-child,.rst-content .important .last,.rst-content .important>:last-child,.rst-content .note .last,.rst-content .note>:last-child,.rst-content .seealso .last,.rst-content .seealso>:last-child,.rst-content .tip .last,.rst-content .tip>:last-child,.rst-content .warning .last,.rst-content .warning>:last-child{margin-bottom:0}.rst-content .admonition-title:before{margin-right:4px}.rst-content .admonition table{border-color:rgba(0,0,0,.1)}.rst-content .admonition table td,.rst-content .admonition table th{background:transparent!important;border-color:rgba(0,0,0,.1)!important}.rst-content .section ol.loweralpha,.rst-content .section ol.loweralpha>li,.rst-content .toctree-wrapper ol.loweralpha,.rst-content .toctree-wrapper ol.loweralpha>li,.rst-content section ol.loweralpha,.rst-content section ol.loweralpha>li{list-style:lower-alpha}.rst-content .section ol.upperalpha,.rst-content .section ol.upperalpha>li,.rst-content .toctree-wrapper ol.upperalpha,.rst-content .toctree-wrapper ol.upperalpha>li,.rst-content section ol.upperalpha,.rst-content section ol.upperalpha>li{list-style:upper-alpha}.rst-content .section ol li>*,.rst-content .section ul li>*,.rst-content .toctree-wrapper ol li>*,.rst-content .toctree-wrapper ul li>*,.rst-content section ol li>*,.rst-content section ul li>*{margin-top:12px;margin-bottom:12px}.rst-content .section ol li>:first-child,.rst-content .section ul li>:first-child,.rst-content .toctree-wrapper ol li>:first-child,.rst-content .toctree-wrapper ul li>:first-child,.rst-content section ol li>:first-child,.rst-content section ul li>:first-child{margin-top:0}.rst-content .section ol li>p,.rst-content .section ol li>p:last-child,.rst-content .section ul li>p,.rst-content .section ul li>p:last-child,.rst-content .toctree-wrapper ol li>p,.rst-content .toctree-wrapper ol li>p:last-child,.rst-content .toctree-wrapper ul li>p,.rst-content .toctree-wrapper ul li>p:last-child,.rst-content section ol li>p,.rst-content section ol li>p:last-child,.rst-content section ul li>p,.rst-content section ul li>p:last-child{margin-bottom:12px}.rst-content .section ol li>p:only-child,.rst-content .section ol li>p:only-child:last-child,.rst-content .section ul li>p:only-child,.rst-content .section ul li>p:only-child:last-child,.rst-content .toctree-wrapper ol li>p:only-child,.rst-content .toctree-wrapper ol li>p:only-child:last-child,.rst-content .toctree-wrapper ul li>p:only-child,.rst-content .toctree-wrapper ul li>p:only-child:last-child,.rst-content section ol li>p:only-child,.rst-content section ol li>p:only-child:last-child,.rst-content section ul li>p:only-child,.rst-content section ul li>p:only-child:last-child{margin-bottom:0}.rst-content .section ol li>ol,.rst-content .section ol li>ul,.rst-content .section ul li>ol,.rst-content .section ul li>ul,.rst-content .toctree-wrapper ol li>ol,.rst-content .toctree-wrapper ol li>ul,.rst-content .toctree-wrapper ul li>ol,.rst-content .toctree-wrapper ul li>ul,.rst-content section ol li>ol,.rst-content section ol li>ul,.rst-content section ul li>ol,.rst-content section ul li>ul{margin-bottom:12px}.rst-content .section ol.simple li>*,.rst-content .section ol.simple li ol,.rst-content .section ol.simple li ul,.rst-content .section ul.simple li>*,.rst-content .section ul.simple li ol,.rst-content .section ul.simple li ul,.rst-content .toctree-wrapper ol.simple li>*,.rst-content .toctree-wrapper ol.simple li ol,.rst-content .toctree-wrapper ol.simple li ul,.rst-content .toctree-wrapper ul.simple li>*,.rst-content .toctree-wrapper ul.simple li ol,.rst-content .toctree-wrapper ul.simple li ul,.rst-content section ol.simple li>*,.rst-content section ol.simple li ol,.rst-content section ol.simple li ul,.rst-content section ul.simple li>*,.rst-content section ul.simple li ol,.rst-content section ul.simple li ul{margin-top:0;margin-bottom:0}.rst-content .line-block{margin-left:0;margin-bottom:24px;line-height:24px}.rst-content .line-block .line-block{margin-left:24px;margin-bottom:0}.rst-content .topic-title{font-weight:700;margin-bottom:12px}.rst-content .toc-backref{color:#404040}.rst-content .align-right{float:right;margin:0 0 24px 24px}.rst-content .align-left{float:left;margin:0 24px 24px 0}.rst-content .align-center{margin:auto}.rst-content .align-center:not(table){display:block}.rst-content .code-block-caption .headerlink,.rst-content .eqno .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink,.rst-content dl dt .headerlink,.rst-content h1 .headerlink,.rst-content h2 .headerlink,.rst-content h3 .headerlink,.rst-content h4 .headerlink,.rst-content h5 .headerlink,.rst-content h6 .headerlink,.rst-content p.caption .headerlink,.rst-content p .headerlink,.rst-content table>caption .headerlink{opacity:0;font-size:14px;font-family:FontAwesome;margin-left:.5em}.rst-content .code-block-caption .headerlink:focus,.rst-content .code-block-caption:hover .headerlink,.rst-content .eqno .headerlink:focus,.rst-content .eqno:hover .headerlink,.rst-content .toctree-wrapper>p.caption .headerlink:focus,.rst-content .toctree-wrapper>p.caption:hover .headerlink,.rst-content dl dt .headerlink:focus,.rst-content dl dt:hover .headerlink,.rst-content h1 .headerlink:focus,.rst-content h1:hover .headerlink,.rst-content h2 .headerlink:focus,.rst-content h2:hover .headerlink,.rst-content h3 .headerlink:focus,.rst-content h3:hover .headerlink,.rst-content h4 .headerlink:focus,.rst-content h4:hover .headerlink,.rst-content h5 .headerlink:focus,.rst-content h5:hover .headerlink,.rst-content h6 .headerlink:focus,.rst-content h6:hover .headerlink,.rst-content p.caption .headerlink:focus,.rst-content p.caption:hover .headerlink,.rst-content p .headerlink:focus,.rst-content p:hover .headerlink,.rst-content table>caption .headerlink:focus,.rst-content table>caption:hover .headerlink{opacity:1}.rst-content p a{overflow-wrap:anywhere}.rst-content .wy-table td p,.rst-content .wy-table td ul,.rst-content .wy-table th p,.rst-content .wy-table th ul,.rst-content table.docutils td p,.rst-content table.docutils td ul,.rst-content table.docutils th p,.rst-content table.docutils th ul,.rst-content table.field-list td p,.rst-content table.field-list td ul,.rst-content table.field-list th p,.rst-content table.field-list th ul{font-size:inherit}.rst-content .btn:focus{outline:2px solid}.rst-content table>caption .headerlink:after{font-size:12px}.rst-content .centered{text-align:center}.rst-content .sidebar{float:right;width:40%;display:block;margin:0 0 24px 24px;padding:24px;background:#f3f6f6;border:1px solid #e1e4e5}.rst-content .sidebar dl,.rst-content .sidebar p,.rst-content .sidebar ul{font-size:90%}.rst-content .sidebar .last,.rst-content .sidebar>:last-child{margin-bottom:0}.rst-content .sidebar .sidebar-title{display:block;font-family:Roboto Slab,ff-tisa-web-pro,Georgia,Arial,sans-serif;font-weight:700;background:#e1e4e5;padding:6px 12px;margin:-24px -24px 24px;font-size:100%}.rst-content .highlighted{background:#f1c40f;box-shadow:0 0 0 2px #f1c40f;display:inline;font-weight:700}.rst-content .citation-reference,.rst-content .footnote-reference{vertical-align:baseline;position:relative;top:-.4em;line-height:0;font-size:90%}.rst-content .citation-reference>span.fn-bracket,.rst-content .footnote-reference>span.fn-bracket{display:none}.rst-content .hlist{width:100%}.rst-content dl dt span.classifier:before{content:" : "}.rst-content dl dt span.classifier-delimiter{display:none!important}html.writer-html4 .rst-content table.docutils.citation,html.writer-html4 .rst-content table.docutils.footnote{background:none;border:none}html.writer-html4 .rst-content table.docutils.citation td,html.writer-html4 .rst-content table.docutils.citation tr,html.writer-html4 .rst-content table.docutils.footnote td,html.writer-html4 .rst-content table.docutils.footnote tr{border:none;background-color:transparent!important;white-space:normal}html.writer-html4 .rst-content table.docutils.citation td.label,html.writer-html4 .rst-content table.docutils.footnote td.label{padding-left:0;padding-right:0;vertical-align:top}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{display:grid;grid-template-columns:auto minmax(80%,95%)}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{display:inline-grid;grid-template-columns:max-content auto}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{display:grid;grid-template-columns:auto auto minmax(.65rem,auto) minmax(40%,95%)}html.writer-html5 .rst-content aside.citation>span.label,html.writer-html5 .rst-content aside.footnote>span.label,html.writer-html5 .rst-content div.citation>span.label{grid-column-start:1;grid-column-end:2}html.writer-html5 .rst-content aside.citation>span.backrefs,html.writer-html5 .rst-content aside.footnote>span.backrefs,html.writer-html5 .rst-content div.citation>span.backrefs{grid-column-start:2;grid-column-end:3;grid-row-start:1;grid-row-end:3}html.writer-html5 .rst-content aside.citation>p,html.writer-html5 .rst-content aside.footnote>p,html.writer-html5 .rst-content div.citation>p{grid-column-start:4;grid-column-end:5}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.field-list,html.writer-html5 .rst-content dl.footnote{margin-bottom:24px}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dt{padding-left:1rem}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.field-list>dd,html.writer-html5 .rst-content dl.field-list>dt,html.writer-html5 .rst-content dl.footnote>dd,html.writer-html5 .rst-content dl.footnote>dt{margin-bottom:0}html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{font-size:.9rem}html.writer-html5 .rst-content dl.citation>dt,html.writer-html5 .rst-content dl.footnote>dt{margin:0 .5rem .5rem 0;line-height:1.2rem;word-break:break-all;font-weight:400}html.writer-html5 .rst-content dl.citation>dt>span.brackets:before,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:before{content:"["}html.writer-html5 .rst-content dl.citation>dt>span.brackets:after,html.writer-html5 .rst-content dl.footnote>dt>span.brackets:after{content:"]"}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a{word-break:keep-all}html.writer-html5 .rst-content dl.citation>dt>span.fn-backref>a:not(:first-child):before,html.writer-html5 .rst-content dl.footnote>dt>span.fn-backref>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content dl.citation>dd,html.writer-html5 .rst-content dl.footnote>dd{margin:0 0 .5rem;line-height:1.2rem}html.writer-html5 .rst-content dl.citation>dd p,html.writer-html5 .rst-content dl.footnote>dd p{font-size:.9rem}html.writer-html5 .rst-content aside.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content div.citation{padding-left:1rem;padding-right:1rem;font-size:.9rem;line-height:1.2rem}html.writer-html5 .rst-content aside.citation p,html.writer-html5 .rst-content aside.footnote p,html.writer-html5 .rst-content div.citation p{font-size:.9rem;line-height:1.2rem;margin-bottom:12px}html.writer-html5 .rst-content aside.citation span.backrefs,html.writer-html5 .rst-content aside.footnote span.backrefs,html.writer-html5 .rst-content div.citation span.backrefs{text-align:left;font-style:italic;margin-left:.65rem;word-break:break-word;word-spacing:-.1rem;max-width:5rem}html.writer-html5 .rst-content aside.citation span.backrefs>a,html.writer-html5 .rst-content aside.footnote span.backrefs>a,html.writer-html5 .rst-content div.citation span.backrefs>a{word-break:keep-all}html.writer-html5 .rst-content aside.citation span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content aside.footnote span.backrefs>a:not(:first-child):before,html.writer-html5 .rst-content div.citation span.backrefs>a:not(:first-child):before{content:" "}html.writer-html5 .rst-content aside.citation span.label,html.writer-html5 .rst-content aside.footnote span.label,html.writer-html5 .rst-content div.citation span.label{line-height:1.2rem}html.writer-html5 .rst-content aside.citation-list,html.writer-html5 .rst-content aside.footnote-list,html.writer-html5 .rst-content div.citation-list{margin-bottom:24px}html.writer-html5 .rst-content dl.option-list kbd{font-size:.9rem}.rst-content table.docutils.footnote,html.writer-html4 .rst-content table.docutils.citation,html.writer-html5 .rst-content aside.footnote,html.writer-html5 .rst-content aside.footnote-list aside.footnote,html.writer-html5 .rst-content div.citation-list>div.citation,html.writer-html5 .rst-content dl.citation,html.writer-html5 .rst-content dl.footnote{color:grey}.rst-content table.docutils.footnote code,.rst-content table.docutils.footnote tt,html.writer-html4 .rst-content table.docutils.citation code,html.writer-html4 .rst-content table.docutils.citation tt,html.writer-html5 .rst-content aside.footnote-list aside.footnote code,html.writer-html5 .rst-content aside.footnote-list aside.footnote tt,html.writer-html5 .rst-content aside.footnote code,html.writer-html5 .rst-content aside.footnote tt,html.writer-html5 .rst-content div.citation-list>div.citation code,html.writer-html5 .rst-content div.citation-list>div.citation tt,html.writer-html5 .rst-content dl.citation code,html.writer-html5 .rst-content dl.citation tt,html.writer-html5 .rst-content dl.footnote code,html.writer-html5 .rst-content dl.footnote tt{color:#555}.rst-content .wy-table-responsive.citation,.rst-content .wy-table-responsive.footnote{margin-bottom:0}.rst-content .wy-table-responsive.citation+:not(.citation),.rst-content .wy-table-responsive.footnote+:not(.footnote){margin-top:24px}.rst-content .wy-table-responsive.citation:last-child,.rst-content .wy-table-responsive.footnote:last-child{margin-bottom:24px}.rst-content table.docutils th{border-color:#e1e4e5}html.writer-html5 .rst-content table.docutils th{border:1px solid #e1e4e5}html.writer-html5 .rst-content table.docutils td>p,html.writer-html5 .rst-content table.docutils th>p{line-height:1rem;margin-bottom:0;font-size:.9rem}.rst-content table.docutils td .last,.rst-content table.docutils td .last>:last-child{margin-bottom:0}.rst-content table.field-list,.rst-content table.field-list td{border:none}.rst-content table.field-list td p{line-height:inherit}.rst-content table.field-list td>strong{display:inline-block}.rst-content table.field-list .field-name{padding-right:10px;text-align:left;white-space:nowrap}.rst-content table.field-list .field-body{text-align:left}.rst-content code,.rst-content tt{color:#000;font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;padding:2px 5px}.rst-content code big,.rst-content code em,.rst-content tt big,.rst-content tt em{font-size:100%!important;line-height:normal}.rst-content code.literal,.rst-content tt.literal{color:#e74c3c;white-space:normal}.rst-content code.xref,.rst-content tt.xref,a .rst-content code,a .rst-content tt{font-weight:700;color:#404040;overflow-wrap:normal}.rst-content kbd,.rst-content pre,.rst-content samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace}.rst-content a code,.rst-content a tt{color:#2980b9}.rst-content dl{margin-bottom:24px}.rst-content dl dt{font-weight:700;margin-bottom:12px}.rst-content dl ol,.rst-content dl p,.rst-content dl table,.rst-content dl ul{margin-bottom:12px}.rst-content dl dd{margin:0 0 12px 24px;line-height:24px}.rst-content dl dd>ol:last-child,.rst-content dl dd>p:last-child,.rst-content dl dd>table:last-child,.rst-content dl dd>ul:last-child{margin-bottom:0}html.writer-html4 .rst-content dl:not(.docutils),html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple){margin-bottom:24px}html.writer-html4 .rst-content dl:not(.docutils)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{display:table;margin:6px 0;font-size:90%;line-height:normal;background:#e7f2fa;color:#2980b9;border-top:3px solid #6ab0de;padding:6px;position:relative}html.writer-html4 .rst-content dl:not(.docutils)>dt:before,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:before{color:#6ab0de}html.writer-html4 .rst-content dl:not(.docutils)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt{margin-bottom:6px;border:none;border-left:3px solid #ccc;background:#f0f0f0;color:#555}html.writer-html4 .rst-content dl:not(.docutils) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) dl:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt .headerlink{color:#404040;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils)>dt:first-child,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple)>dt:first-child{margin-top:0}html.writer-html4 .rst-content dl:not(.docutils) code.descclassname,html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descclassname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{background-color:transparent;border:none;padding:0;font-size:100%!important}html.writer-html4 .rst-content dl:not(.docutils) code.descname,html.writer-html4 .rst-content dl:not(.docutils) tt.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) code.descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) tt.descname{font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .optional,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .optional{display:inline-block;padding:0 4px;color:#000;font-weight:700}html.writer-html4 .rst-content dl:not(.docutils) .property,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property{display:inline-block;padding-right:8px;max-width:100%}html.writer-html4 .rst-content dl:not(.docutils) .k,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .k{font-style:italic}html.writer-html4 .rst-content dl:not(.docutils) .descclassname,html.writer-html4 .rst-content dl:not(.docutils) .descname,html.writer-html4 .rst-content dl:not(.docutils) .sig-name,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descclassname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .descname,html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .sig-name{font-family:SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,Courier,monospace;color:#000}.rst-content .viewcode-back,.rst-content .viewcode-link{display:inline-block;color:#27ae60;font-size:80%;padding-left:24px}.rst-content .viewcode-back{display:block;float:right}.rst-content p.rubric{margin-bottom:12px;font-weight:700}.rst-content code.download,.rst-content tt.download{background:inherit;padding:inherit;font-weight:400;font-family:inherit;font-size:inherit;color:inherit;border:inherit;white-space:inherit}.rst-content code.download span:first-child,.rst-content tt.download span:first-child{-webkit-font-smoothing:subpixel-antialiased}.rst-content code.download span:first-child:before,.rst-content tt.download span:first-child:before{margin-right:4px}.rst-content .guilabel,.rst-content .menuselection{font-size:80%;font-weight:700;border-radius:4px;padding:2.4px 6px;margin:auto 2px}.rst-content .guilabel,.rst-content .menuselection{border:1px solid #7fbbe3;background:#e7f2fa}.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>.kbd,.rst-content :not(dl.option-list)>:not(dt):not(kbd):not(.kbd)>kbd{color:inherit;font-size:80%;background-color:#fff;border:1px solid #a6a6a6;border-radius:4px;box-shadow:0 2px grey;padding:2.4px 6px;margin:auto 0}.rst-content .versionmodified{font-style:italic}@media screen and (max-width:480px){.rst-content .sidebar{width:100%}}span[id*=MathJax-Span]{color:#404040}.math{text-align:center}@font-face{font-family:Lato;src:url(fonts/lato-normal.woff2?bd03a2cc277bbbc338d464e679fe9942) format("woff2"),url(fonts/lato-normal.woff?27bd77b9162d388cb8d4c4217c7c5e2a) format("woff");font-weight:400;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold.woff2?cccb897485813c7c256901dbca54ecf2) format("woff2"),url(fonts/lato-bold.woff?d878b6c29b10beca227e9eef4246111b) format("woff");font-weight:700;font-style:normal;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-bold-italic.woff2?0b6bb6725576b072c5d0b02ecdd1900d) format("woff2"),url(fonts/lato-bold-italic.woff?9c7e4e9eb485b4a121c760e61bc3707c) format("woff");font-weight:700;font-style:italic;font-display:block}@font-face{font-family:Lato;src:url(fonts/lato-normal-italic.woff2?4eb103b4d12be57cb1d040ed5e162e9d) format("woff2"),url(fonts/lato-normal-italic.woff?f28f2d6482446544ef1ea1ccc6dd5892) format("woff");font-weight:400;font-style:italic;font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:400;src:url(fonts/Roboto-Slab-Regular.woff2?7abf5b8d04d26a2cafea937019bca958) format("woff2"),url(fonts/Roboto-Slab-Regular.woff?c1be9284088d487c5e3ff0a10a92e58c) format("woff");font-display:block}@font-face{font-family:Roboto Slab;font-style:normal;font-weight:700;src:url(fonts/Roboto-Slab-Bold.woff2?9984f4a9bda09be08e83f2506954adbe) format("woff2"),url(fonts/Roboto-Slab-Bold.woff?bed5564a116b05148e3b3bea6fb1162a) format("woff");font-display:block} \ No newline at end of file diff --git a/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css b/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css new file mode 100644 index 0000000..eb19f69 --- /dev/null +++ b/_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css @@ -0,0 +1 @@ +.sd-bg-primary{background-color:var(--sd-color-primary) !important}.sd-bg-text-primary{color:var(--sd-color-primary-text) !important}button.sd-bg-primary:focus,button.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}a.sd-bg-primary:focus,a.sd-bg-primary:hover{background-color:var(--sd-color-primary-highlight) !important}.sd-bg-secondary{background-color:var(--sd-color-secondary) !important}.sd-bg-text-secondary{color:var(--sd-color-secondary-text) !important}button.sd-bg-secondary:focus,button.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}a.sd-bg-secondary:focus,a.sd-bg-secondary:hover{background-color:var(--sd-color-secondary-highlight) !important}.sd-bg-success{background-color:var(--sd-color-success) !important}.sd-bg-text-success{color:var(--sd-color-success-text) !important}button.sd-bg-success:focus,button.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}a.sd-bg-success:focus,a.sd-bg-success:hover{background-color:var(--sd-color-success-highlight) !important}.sd-bg-info{background-color:var(--sd-color-info) !important}.sd-bg-text-info{color:var(--sd-color-info-text) !important}button.sd-bg-info:focus,button.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}a.sd-bg-info:focus,a.sd-bg-info:hover{background-color:var(--sd-color-info-highlight) !important}.sd-bg-warning{background-color:var(--sd-color-warning) !important}.sd-bg-text-warning{color:var(--sd-color-warning-text) !important}button.sd-bg-warning:focus,button.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}a.sd-bg-warning:focus,a.sd-bg-warning:hover{background-color:var(--sd-color-warning-highlight) !important}.sd-bg-danger{background-color:var(--sd-color-danger) !important}.sd-bg-text-danger{color:var(--sd-color-danger-text) !important}button.sd-bg-danger:focus,button.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}a.sd-bg-danger:focus,a.sd-bg-danger:hover{background-color:var(--sd-color-danger-highlight) !important}.sd-bg-light{background-color:var(--sd-color-light) !important}.sd-bg-text-light{color:var(--sd-color-light-text) !important}button.sd-bg-light:focus,button.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}a.sd-bg-light:focus,a.sd-bg-light:hover{background-color:var(--sd-color-light-highlight) !important}.sd-bg-muted{background-color:var(--sd-color-muted) !important}.sd-bg-text-muted{color:var(--sd-color-muted-text) !important}button.sd-bg-muted:focus,button.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}a.sd-bg-muted:focus,a.sd-bg-muted:hover{background-color:var(--sd-color-muted-highlight) !important}.sd-bg-dark{background-color:var(--sd-color-dark) !important}.sd-bg-text-dark{color:var(--sd-color-dark-text) !important}button.sd-bg-dark:focus,button.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}a.sd-bg-dark:focus,a.sd-bg-dark:hover{background-color:var(--sd-color-dark-highlight) !important}.sd-bg-black{background-color:var(--sd-color-black) !important}.sd-bg-text-black{color:var(--sd-color-black-text) !important}button.sd-bg-black:focus,button.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}a.sd-bg-black:focus,a.sd-bg-black:hover{background-color:var(--sd-color-black-highlight) !important}.sd-bg-white{background-color:var(--sd-color-white) !important}.sd-bg-text-white{color:var(--sd-color-white-text) !important}button.sd-bg-white:focus,button.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}a.sd-bg-white:focus,a.sd-bg-white:hover{background-color:var(--sd-color-white-highlight) !important}.sd-text-primary,.sd-text-primary>p{color:var(--sd-color-primary) !important}a.sd-text-primary:focus,a.sd-text-primary:hover{color:var(--sd-color-primary-highlight) !important}.sd-text-secondary,.sd-text-secondary>p{color:var(--sd-color-secondary) !important}a.sd-text-secondary:focus,a.sd-text-secondary:hover{color:var(--sd-color-secondary-highlight) !important}.sd-text-success,.sd-text-success>p{color:var(--sd-color-success) !important}a.sd-text-success:focus,a.sd-text-success:hover{color:var(--sd-color-success-highlight) !important}.sd-text-info,.sd-text-info>p{color:var(--sd-color-info) !important}a.sd-text-info:focus,a.sd-text-info:hover{color:var(--sd-color-info-highlight) !important}.sd-text-warning,.sd-text-warning>p{color:var(--sd-color-warning) !important}a.sd-text-warning:focus,a.sd-text-warning:hover{color:var(--sd-color-warning-highlight) !important}.sd-text-danger,.sd-text-danger>p{color:var(--sd-color-danger) !important}a.sd-text-danger:focus,a.sd-text-danger:hover{color:var(--sd-color-danger-highlight) !important}.sd-text-light,.sd-text-light>p{color:var(--sd-color-light) !important}a.sd-text-light:focus,a.sd-text-light:hover{color:var(--sd-color-light-highlight) !important}.sd-text-muted,.sd-text-muted>p{color:var(--sd-color-muted) !important}a.sd-text-muted:focus,a.sd-text-muted:hover{color:var(--sd-color-muted-highlight) !important}.sd-text-dark,.sd-text-dark>p{color:var(--sd-color-dark) !important}a.sd-text-dark:focus,a.sd-text-dark:hover{color:var(--sd-color-dark-highlight) !important}.sd-text-black,.sd-text-black>p{color:var(--sd-color-black) !important}a.sd-text-black:focus,a.sd-text-black:hover{color:var(--sd-color-black-highlight) !important}.sd-text-white,.sd-text-white>p{color:var(--sd-color-white) !important}a.sd-text-white:focus,a.sd-text-white:hover{color:var(--sd-color-white-highlight) !important}.sd-outline-primary{border-color:var(--sd-color-primary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-primary:focus,a.sd-outline-primary:hover{border-color:var(--sd-color-primary-highlight) !important}.sd-outline-secondary{border-color:var(--sd-color-secondary) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-secondary:focus,a.sd-outline-secondary:hover{border-color:var(--sd-color-secondary-highlight) !important}.sd-outline-success{border-color:var(--sd-color-success) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-success:focus,a.sd-outline-success:hover{border-color:var(--sd-color-success-highlight) !important}.sd-outline-info{border-color:var(--sd-color-info) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-info:focus,a.sd-outline-info:hover{border-color:var(--sd-color-info-highlight) !important}.sd-outline-warning{border-color:var(--sd-color-warning) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-warning:focus,a.sd-outline-warning:hover{border-color:var(--sd-color-warning-highlight) !important}.sd-outline-danger{border-color:var(--sd-color-danger) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-danger:focus,a.sd-outline-danger:hover{border-color:var(--sd-color-danger-highlight) !important}.sd-outline-light{border-color:var(--sd-color-light) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-light:focus,a.sd-outline-light:hover{border-color:var(--sd-color-light-highlight) !important}.sd-outline-muted{border-color:var(--sd-color-muted) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-muted:focus,a.sd-outline-muted:hover{border-color:var(--sd-color-muted-highlight) !important}.sd-outline-dark{border-color:var(--sd-color-dark) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-dark:focus,a.sd-outline-dark:hover{border-color:var(--sd-color-dark-highlight) !important}.sd-outline-black{border-color:var(--sd-color-black) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-black:focus,a.sd-outline-black:hover{border-color:var(--sd-color-black-highlight) !important}.sd-outline-white{border-color:var(--sd-color-white) !important;border-style:solid !important;border-width:1px !important}a.sd-outline-white:focus,a.sd-outline-white:hover{border-color:var(--sd-color-white-highlight) !important}.sd-bg-transparent{background-color:transparent !important}.sd-outline-transparent{border-color:transparent !important}.sd-text-transparent{color:transparent !important}.sd-p-0{padding:0 !important}.sd-pt-0,.sd-py-0{padding-top:0 !important}.sd-pr-0,.sd-px-0{padding-right:0 !important}.sd-pb-0,.sd-py-0{padding-bottom:0 !important}.sd-pl-0,.sd-px-0{padding-left:0 !important}.sd-p-1{padding:.25rem !important}.sd-pt-1,.sd-py-1{padding-top:.25rem !important}.sd-pr-1,.sd-px-1{padding-right:.25rem !important}.sd-pb-1,.sd-py-1{padding-bottom:.25rem !important}.sd-pl-1,.sd-px-1{padding-left:.25rem !important}.sd-p-2{padding:.5rem !important}.sd-pt-2,.sd-py-2{padding-top:.5rem !important}.sd-pr-2,.sd-px-2{padding-right:.5rem !important}.sd-pb-2,.sd-py-2{padding-bottom:.5rem !important}.sd-pl-2,.sd-px-2{padding-left:.5rem !important}.sd-p-3{padding:1rem !important}.sd-pt-3,.sd-py-3{padding-top:1rem !important}.sd-pr-3,.sd-px-3{padding-right:1rem !important}.sd-pb-3,.sd-py-3{padding-bottom:1rem !important}.sd-pl-3,.sd-px-3{padding-left:1rem !important}.sd-p-4{padding:1.5rem !important}.sd-pt-4,.sd-py-4{padding-top:1.5rem !important}.sd-pr-4,.sd-px-4{padding-right:1.5rem !important}.sd-pb-4,.sd-py-4{padding-bottom:1.5rem !important}.sd-pl-4,.sd-px-4{padding-left:1.5rem !important}.sd-p-5{padding:3rem !important}.sd-pt-5,.sd-py-5{padding-top:3rem !important}.sd-pr-5,.sd-px-5{padding-right:3rem !important}.sd-pb-5,.sd-py-5{padding-bottom:3rem !important}.sd-pl-5,.sd-px-5{padding-left:3rem !important}.sd-m-auto{margin:auto !important}.sd-mt-auto,.sd-my-auto{margin-top:auto !important}.sd-mr-auto,.sd-mx-auto{margin-right:auto !important}.sd-mb-auto,.sd-my-auto{margin-bottom:auto !important}.sd-ml-auto,.sd-mx-auto{margin-left:auto !important}.sd-m-0{margin:0 !important}.sd-mt-0,.sd-my-0{margin-top:0 !important}.sd-mr-0,.sd-mx-0{margin-right:0 !important}.sd-mb-0,.sd-my-0{margin-bottom:0 !important}.sd-ml-0,.sd-mx-0{margin-left:0 !important}.sd-m-1{margin:.25rem !important}.sd-mt-1,.sd-my-1{margin-top:.25rem !important}.sd-mr-1,.sd-mx-1{margin-right:.25rem !important}.sd-mb-1,.sd-my-1{margin-bottom:.25rem !important}.sd-ml-1,.sd-mx-1{margin-left:.25rem !important}.sd-m-2{margin:.5rem !important}.sd-mt-2,.sd-my-2{margin-top:.5rem !important}.sd-mr-2,.sd-mx-2{margin-right:.5rem !important}.sd-mb-2,.sd-my-2{margin-bottom:.5rem !important}.sd-ml-2,.sd-mx-2{margin-left:.5rem !important}.sd-m-3{margin:1rem !important}.sd-mt-3,.sd-my-3{margin-top:1rem !important}.sd-mr-3,.sd-mx-3{margin-right:1rem !important}.sd-mb-3,.sd-my-3{margin-bottom:1rem !important}.sd-ml-3,.sd-mx-3{margin-left:1rem !important}.sd-m-4{margin:1.5rem !important}.sd-mt-4,.sd-my-4{margin-top:1.5rem !important}.sd-mr-4,.sd-mx-4{margin-right:1.5rem !important}.sd-mb-4,.sd-my-4{margin-bottom:1.5rem !important}.sd-ml-4,.sd-mx-4{margin-left:1.5rem !important}.sd-m-5{margin:3rem !important}.sd-mt-5,.sd-my-5{margin-top:3rem !important}.sd-mr-5,.sd-mx-5{margin-right:3rem !important}.sd-mb-5,.sd-my-5{margin-bottom:3rem !important}.sd-ml-5,.sd-mx-5{margin-left:3rem !important}.sd-w-25{width:25% !important}.sd-w-50{width:50% !important}.sd-w-75{width:75% !important}.sd-w-100{width:100% !important}.sd-w-auto{width:auto !important}.sd-h-25{height:25% !important}.sd-h-50{height:50% !important}.sd-h-75{height:75% !important}.sd-h-100{height:100% !important}.sd-h-auto{height:auto !important}.sd-d-none{display:none !important}.sd-d-inline{display:inline !important}.sd-d-inline-block{display:inline-block !important}.sd-d-block{display:block !important}.sd-d-grid{display:grid !important}.sd-d-flex-row{display:-ms-flexbox !important;display:flex !important;flex-direction:row !important}.sd-d-flex-column{display:-ms-flexbox !important;display:flex !important;flex-direction:column !important}.sd-d-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}@media(min-width: 576px){.sd-d-sm-none{display:none !important}.sd-d-sm-inline{display:inline !important}.sd-d-sm-inline-block{display:inline-block !important}.sd-d-sm-block{display:block !important}.sd-d-sm-grid{display:grid !important}.sd-d-sm-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-sm-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 768px){.sd-d-md-none{display:none !important}.sd-d-md-inline{display:inline !important}.sd-d-md-inline-block{display:inline-block !important}.sd-d-md-block{display:block !important}.sd-d-md-grid{display:grid !important}.sd-d-md-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-md-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 992px){.sd-d-lg-none{display:none !important}.sd-d-lg-inline{display:inline !important}.sd-d-lg-inline-block{display:inline-block !important}.sd-d-lg-block{display:block !important}.sd-d-lg-grid{display:grid !important}.sd-d-lg-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-lg-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}@media(min-width: 1200px){.sd-d-xl-none{display:none !important}.sd-d-xl-inline{display:inline !important}.sd-d-xl-inline-block{display:inline-block !important}.sd-d-xl-block{display:block !important}.sd-d-xl-grid{display:grid !important}.sd-d-xl-flex{display:-ms-flexbox !important;display:flex !important}.sd-d-xl-inline-flex{display:-ms-inline-flexbox !important;display:inline-flex !important}}.sd-align-major-start{justify-content:flex-start !important}.sd-align-major-end{justify-content:flex-end !important}.sd-align-major-center{justify-content:center !important}.sd-align-major-justify{justify-content:space-between !important}.sd-align-major-spaced{justify-content:space-evenly !important}.sd-align-minor-start{align-items:flex-start !important}.sd-align-minor-end{align-items:flex-end !important}.sd-align-minor-center{align-items:center !important}.sd-align-minor-stretch{align-items:stretch !important}.sd-text-justify{text-align:justify !important}.sd-text-left{text-align:left !important}.sd-text-right{text-align:right !important}.sd-text-center{text-align:center !important}.sd-font-weight-light{font-weight:300 !important}.sd-font-weight-lighter{font-weight:lighter !important}.sd-font-weight-normal{font-weight:400 !important}.sd-font-weight-bold{font-weight:700 !important}.sd-font-weight-bolder{font-weight:bolder !important}.sd-font-italic{font-style:italic !important}.sd-text-decoration-none{text-decoration:none !important}.sd-text-lowercase{text-transform:lowercase !important}.sd-text-uppercase{text-transform:uppercase !important}.sd-text-capitalize{text-transform:capitalize !important}.sd-text-wrap{white-space:normal !important}.sd-text-nowrap{white-space:nowrap !important}.sd-text-truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sd-fs-1,.sd-fs-1>p{font-size:calc(1.375rem + 1.5vw) !important;line-height:unset !important}.sd-fs-2,.sd-fs-2>p{font-size:calc(1.325rem + 0.9vw) !important;line-height:unset !important}.sd-fs-3,.sd-fs-3>p{font-size:calc(1.3rem + 0.6vw) !important;line-height:unset !important}.sd-fs-4,.sd-fs-4>p{font-size:calc(1.275rem + 0.3vw) !important;line-height:unset !important}.sd-fs-5,.sd-fs-5>p{font-size:1.25rem !important;line-height:unset !important}.sd-fs-6,.sd-fs-6>p{font-size:1rem !important;line-height:unset !important}.sd-border-0{border:0 solid !important}.sd-border-top-0{border-top:0 solid !important}.sd-border-bottom-0{border-bottom:0 solid !important}.sd-border-right-0{border-right:0 solid !important}.sd-border-left-0{border-left:0 solid !important}.sd-border-1{border:1px solid !important}.sd-border-top-1{border-top:1px solid !important}.sd-border-bottom-1{border-bottom:1px solid !important}.sd-border-right-1{border-right:1px solid !important}.sd-border-left-1{border-left:1px solid !important}.sd-border-2{border:2px solid !important}.sd-border-top-2{border-top:2px solid !important}.sd-border-bottom-2{border-bottom:2px solid !important}.sd-border-right-2{border-right:2px solid !important}.sd-border-left-2{border-left:2px solid !important}.sd-border-3{border:3px solid !important}.sd-border-top-3{border-top:3px solid !important}.sd-border-bottom-3{border-bottom:3px solid !important}.sd-border-right-3{border-right:3px solid !important}.sd-border-left-3{border-left:3px solid !important}.sd-border-4{border:4px solid !important}.sd-border-top-4{border-top:4px solid !important}.sd-border-bottom-4{border-bottom:4px solid !important}.sd-border-right-4{border-right:4px solid !important}.sd-border-left-4{border-left:4px solid !important}.sd-border-5{border:5px solid !important}.sd-border-top-5{border-top:5px solid !important}.sd-border-bottom-5{border-bottom:5px solid !important}.sd-border-right-5{border-right:5px solid !important}.sd-border-left-5{border-left:5px solid !important}.sd-rounded-0{border-radius:0 !important}.sd-rounded-1{border-radius:.2rem !important}.sd-rounded-2{border-radius:.3rem !important}.sd-rounded-3{border-radius:.5rem !important}.sd-rounded-pill{border-radius:50rem !important}.sd-rounded-circle{border-radius:50% !important}.shadow-none{box-shadow:none !important}.sd-shadow-sm{box-shadow:0 .125rem .25rem var(--sd-color-shadow) !important}.sd-shadow-md{box-shadow:0 .5rem 1rem var(--sd-color-shadow) !important}.sd-shadow-lg{box-shadow:0 1rem 3rem var(--sd-color-shadow) !important}@keyframes sd-slide-from-left{0%{transform:translateX(-100%)}100%{transform:translateX(0)}}@keyframes sd-slide-from-right{0%{transform:translateX(200%)}100%{transform:translateX(0)}}@keyframes sd-grow100{0%{transform:scale(0);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50{0%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:1}}@keyframes sd-grow50-rot20{0%{transform:scale(0.5) rotateZ(-20deg);opacity:.5}75%{transform:scale(1) rotateZ(5deg);opacity:1}95%{transform:scale(1) rotateZ(-1deg);opacity:1}100%{transform:scale(1) rotateZ(0);opacity:1}}.sd-animate-slide-from-left{animation:1s ease-out 0s 1 normal none running sd-slide-from-left}.sd-animate-slide-from-right{animation:1s ease-out 0s 1 normal none running sd-slide-from-right}.sd-animate-grow100{animation:1s ease-out 0s 1 normal none running sd-grow100}.sd-animate-grow50{animation:1s ease-out 0s 1 normal none running sd-grow50}.sd-animate-grow50-rot20{animation:1s ease-out 0s 1 normal none running sd-grow50-rot20}.sd-badge{display:inline-block;padding:.35em .65em;font-size:.75em;font-weight:700;line-height:1;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25rem}.sd-badge:empty{display:none}a.sd-badge{text-decoration:none}.sd-btn .sd-badge{position:relative;top:-1px}.sd-btn{background-color:transparent;border:1px solid transparent;border-radius:.25rem;cursor:pointer;display:inline-block;font-weight:400;font-size:1rem;line-height:1.5;padding:.375rem .75rem;text-align:center;text-decoration:none;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;vertical-align:middle;user-select:none;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none}.sd-btn:hover{text-decoration:none}@media(prefers-reduced-motion: reduce){.sd-btn{transition:none}}.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-primary:hover,.sd-btn-primary:focus{color:var(--sd-color-primary-text) !important;background-color:var(--sd-color-primary-highlight) !important;border-color:var(--sd-color-primary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-primary{color:var(--sd-color-primary) !important;border-color:var(--sd-color-primary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-secondary:hover,.sd-btn-secondary:focus{color:var(--sd-color-secondary-text) !important;background-color:var(--sd-color-secondary-highlight) !important;border-color:var(--sd-color-secondary-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-secondary{color:var(--sd-color-secondary) !important;border-color:var(--sd-color-secondary) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-success:hover,.sd-btn-success:focus{color:var(--sd-color-success-text) !important;background-color:var(--sd-color-success-highlight) !important;border-color:var(--sd-color-success-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-success{color:var(--sd-color-success) !important;border-color:var(--sd-color-success) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-info:hover,.sd-btn-info:focus{color:var(--sd-color-info-text) !important;background-color:var(--sd-color-info-highlight) !important;border-color:var(--sd-color-info-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-info{color:var(--sd-color-info) !important;border-color:var(--sd-color-info) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-warning:hover,.sd-btn-warning:focus{color:var(--sd-color-warning-text) !important;background-color:var(--sd-color-warning-highlight) !important;border-color:var(--sd-color-warning-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-warning{color:var(--sd-color-warning) !important;border-color:var(--sd-color-warning) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-danger:hover,.sd-btn-danger:focus{color:var(--sd-color-danger-text) !important;background-color:var(--sd-color-danger-highlight) !important;border-color:var(--sd-color-danger-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-danger{color:var(--sd-color-danger) !important;border-color:var(--sd-color-danger) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-light:hover,.sd-btn-light:focus{color:var(--sd-color-light-text) !important;background-color:var(--sd-color-light-highlight) !important;border-color:var(--sd-color-light-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-light{color:var(--sd-color-light) !important;border-color:var(--sd-color-light) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-muted:hover,.sd-btn-muted:focus{color:var(--sd-color-muted-text) !important;background-color:var(--sd-color-muted-highlight) !important;border-color:var(--sd-color-muted-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-muted{color:var(--sd-color-muted) !important;border-color:var(--sd-color-muted) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-dark:hover,.sd-btn-dark:focus{color:var(--sd-color-dark-text) !important;background-color:var(--sd-color-dark-highlight) !important;border-color:var(--sd-color-dark-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-dark{color:var(--sd-color-dark) !important;border-color:var(--sd-color-dark) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-black:hover,.sd-btn-black:focus{color:var(--sd-color-black-text) !important;background-color:var(--sd-color-black-highlight) !important;border-color:var(--sd-color-black-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-black{color:var(--sd-color-black) !important;border-color:var(--sd-color-black) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-btn-white:hover,.sd-btn-white:focus{color:var(--sd-color-white-text) !important;background-color:var(--sd-color-white-highlight) !important;border-color:var(--sd-color-white-highlight) !important;border-width:1px !important;border-style:solid !important}.sd-btn-outline-white{color:var(--sd-color-white) !important;border-color:var(--sd-color-white) !important;border-width:1px !important;border-style:solid !important}.sd-stretched-link::after{position:absolute;top:0;right:0;bottom:0;left:0;z-index:1;content:""}.sd-hide-link-text{font-size:0}.sd-octicon,.sd-material-icon{display:inline-block;fill:currentColor;vertical-align:middle}.sd-avatar-xs{border-radius:50%;object-fit:cover;object-position:center;width:1rem;height:1rem}.sd-avatar-sm{border-radius:50%;object-fit:cover;object-position:center;width:3rem;height:3rem}.sd-avatar-md{border-radius:50%;object-fit:cover;object-position:center;width:5rem;height:5rem}.sd-avatar-lg{border-radius:50%;object-fit:cover;object-position:center;width:7rem;height:7rem}.sd-avatar-xl{border-radius:50%;object-fit:cover;object-position:center;width:10rem;height:10rem}.sd-avatar-inherit{border-radius:50%;object-fit:cover;object-position:center;width:inherit;height:inherit}.sd-avatar-initial{border-radius:50%;object-fit:cover;object-position:center;width:initial;height:initial}.sd-card{background-clip:border-box;background-color:var(--sd-color-card-background);border:1px solid var(--sd-color-card-border);border-radius:.25rem;color:var(--sd-color-card-text);display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;min-width:0;position:relative;word-wrap:break-word}.sd-card>hr{margin-left:0;margin-right:0}.sd-card-hover:hover{border-color:var(--sd-color-card-border-hover);transform:scale(1.01)}.sd-card-body{-ms-flex:1 1 auto;flex:1 1 auto;padding:1rem 1rem}.sd-card-title{margin-bottom:.5rem}.sd-card-subtitle{margin-top:-0.25rem;margin-bottom:0}.sd-card-text:last-child{margin-bottom:0}.sd-card-link:hover{text-decoration:none}.sd-card-link+.card-link{margin-left:1rem}.sd-card-header{padding:.5rem 1rem;margin-bottom:0;background-color:var(--sd-color-card-header);border-bottom:1px solid var(--sd-color-card-border)}.sd-card-header:first-child{border-radius:calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0}.sd-card-footer{padding:.5rem 1rem;background-color:var(--sd-color-card-footer);border-top:1px solid var(--sd-color-card-border)}.sd-card-footer:last-child{border-radius:0 0 calc(0.25rem - 1px) calc(0.25rem - 1px)}.sd-card-header-tabs{margin-right:-0.5rem;margin-bottom:-0.5rem;margin-left:-0.5rem;border-bottom:0}.sd-card-header-pills{margin-right:-0.5rem;margin-left:-0.5rem}.sd-card-img-overlay{position:absolute;top:0;right:0;bottom:0;left:0;padding:1rem;border-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom,.sd-card-img-top{width:100%}.sd-card-img,.sd-card-img-top{border-top-left-radius:calc(0.25rem - 1px);border-top-right-radius:calc(0.25rem - 1px)}.sd-card-img,.sd-card-img-bottom{border-bottom-left-radius:calc(0.25rem - 1px);border-bottom-right-radius:calc(0.25rem - 1px)}.sd-cards-carousel{width:100%;display:flex;flex-wrap:nowrap;-ms-flex-direction:row;flex-direction:row;overflow-x:hidden;scroll-snap-type:x mandatory}.sd-cards-carousel.sd-show-scrollbar{overflow-x:auto}.sd-cards-carousel:hover,.sd-cards-carousel:focus{overflow-x:auto}.sd-cards-carousel>.sd-card{flex-shrink:0;scroll-snap-align:start}.sd-cards-carousel>.sd-card:not(:last-child){margin-right:3px}.sd-card-cols-1>.sd-card{width:90%}.sd-card-cols-2>.sd-card{width:45%}.sd-card-cols-3>.sd-card{width:30%}.sd-card-cols-4>.sd-card{width:22.5%}.sd-card-cols-5>.sd-card{width:18%}.sd-card-cols-6>.sd-card{width:15%}.sd-card-cols-7>.sd-card{width:12.8571428571%}.sd-card-cols-8>.sd-card{width:11.25%}.sd-card-cols-9>.sd-card{width:10%}.sd-card-cols-10>.sd-card{width:9%}.sd-card-cols-11>.sd-card{width:8.1818181818%}.sd-card-cols-12>.sd-card{width:7.5%}.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl{margin-left:auto;margin-right:auto;padding-left:var(--sd-gutter-x, 0.75rem);padding-right:var(--sd-gutter-x, 0.75rem);width:100%}@media(min-width: 576px){.sd-container-sm,.sd-container{max-width:540px}}@media(min-width: 768px){.sd-container-md,.sd-container-sm,.sd-container{max-width:720px}}@media(min-width: 992px){.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:960px}}@media(min-width: 1200px){.sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container{max-width:1140px}}.sd-row{--sd-gutter-x: 1.5rem;--sd-gutter-y: 0;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-top:calc(var(--sd-gutter-y) * -1);margin-right:calc(var(--sd-gutter-x) * -0.5);margin-left:calc(var(--sd-gutter-x) * -0.5)}.sd-row>*{box-sizing:border-box;flex-shrink:0;width:100%;max-width:100%;padding-right:calc(var(--sd-gutter-x) * 0.5);padding-left:calc(var(--sd-gutter-x) * 0.5);margin-top:var(--sd-gutter-y)}.sd-col{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-auto>*{flex:0 0 auto;width:auto}.sd-row-cols-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}@media(min-width: 576px){.sd-col-sm{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-sm-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-sm-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-sm-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-sm-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-sm-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-sm-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-sm-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-sm-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-sm-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-sm-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-sm-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-sm-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-sm-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 768px){.sd-col-md{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-md-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-md-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-md-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-md-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-md-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-md-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-md-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-md-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-md-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-md-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-md-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-md-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-md-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 992px){.sd-col-lg{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-lg-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-lg-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-lg-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-lg-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-lg-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-lg-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-lg-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-lg-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-lg-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-lg-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-lg-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-lg-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-lg-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}@media(min-width: 1200px){.sd-col-xl{flex:1 0 0%;-ms-flex:1 0 0%}.sd-row-cols-xl-auto{flex:1 0 auto;-ms-flex:1 0 auto;width:100%}.sd-row-cols-xl-1>*{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-row-cols-xl-2>*{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-row-cols-xl-3>*{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-row-cols-xl-4>*{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-row-cols-xl-5>*{flex:0 0 auto;-ms-flex:0 0 auto;width:20%}.sd-row-cols-xl-6>*{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-row-cols-xl-7>*{flex:0 0 auto;-ms-flex:0 0 auto;width:14.2857142857%}.sd-row-cols-xl-8>*{flex:0 0 auto;-ms-flex:0 0 auto;width:12.5%}.sd-row-cols-xl-9>*{flex:0 0 auto;-ms-flex:0 0 auto;width:11.1111111111%}.sd-row-cols-xl-10>*{flex:0 0 auto;-ms-flex:0 0 auto;width:10%}.sd-row-cols-xl-11>*{flex:0 0 auto;-ms-flex:0 0 auto;width:9.0909090909%}.sd-row-cols-xl-12>*{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}}.sd-col-auto{flex:0 0 auto;-ms-flex:0 0 auto;width:auto}.sd-col-1{flex:0 0 auto;-ms-flex:0 0 auto;width:8.3333333333%}.sd-col-2{flex:0 0 auto;-ms-flex:0 0 auto;width:16.6666666667%}.sd-col-3{flex:0 0 auto;-ms-flex:0 0 auto;width:25%}.sd-col-4{flex:0 0 auto;-ms-flex:0 0 auto;width:33.3333333333%}.sd-col-5{flex:0 0 auto;-ms-flex:0 0 auto;width:41.6666666667%}.sd-col-6{flex:0 0 auto;-ms-flex:0 0 auto;width:50%}.sd-col-7{flex:0 0 auto;-ms-flex:0 0 auto;width:58.3333333333%}.sd-col-8{flex:0 0 auto;-ms-flex:0 0 auto;width:66.6666666667%}.sd-col-9{flex:0 0 auto;-ms-flex:0 0 auto;width:75%}.sd-col-10{flex:0 0 auto;-ms-flex:0 0 auto;width:83.3333333333%}.sd-col-11{flex:0 0 auto;-ms-flex:0 0 auto;width:91.6666666667%}.sd-col-12{flex:0 0 auto;-ms-flex:0 0 auto;width:100%}.sd-g-0,.sd-gy-0{--sd-gutter-y: 0}.sd-g-0,.sd-gx-0{--sd-gutter-x: 0}.sd-g-1,.sd-gy-1{--sd-gutter-y: 0.25rem}.sd-g-1,.sd-gx-1{--sd-gutter-x: 0.25rem}.sd-g-2,.sd-gy-2{--sd-gutter-y: 0.5rem}.sd-g-2,.sd-gx-2{--sd-gutter-x: 0.5rem}.sd-g-3,.sd-gy-3{--sd-gutter-y: 1rem}.sd-g-3,.sd-gx-3{--sd-gutter-x: 1rem}.sd-g-4,.sd-gy-4{--sd-gutter-y: 1.5rem}.sd-g-4,.sd-gx-4{--sd-gutter-x: 1.5rem}.sd-g-5,.sd-gy-5{--sd-gutter-y: 3rem}.sd-g-5,.sd-gx-5{--sd-gutter-x: 3rem}@media(min-width: 576px){.sd-col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-sm-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-sm-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-sm-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-sm-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-sm-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-sm-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-sm-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-sm-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-sm-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-sm-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-sm-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-sm-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-sm-0,.sd-gy-sm-0{--sd-gutter-y: 0}.sd-g-sm-0,.sd-gx-sm-0{--sd-gutter-x: 0}.sd-g-sm-1,.sd-gy-sm-1{--sd-gutter-y: 0.25rem}.sd-g-sm-1,.sd-gx-sm-1{--sd-gutter-x: 0.25rem}.sd-g-sm-2,.sd-gy-sm-2{--sd-gutter-y: 0.5rem}.sd-g-sm-2,.sd-gx-sm-2{--sd-gutter-x: 0.5rem}.sd-g-sm-3,.sd-gy-sm-3{--sd-gutter-y: 1rem}.sd-g-sm-3,.sd-gx-sm-3{--sd-gutter-x: 1rem}.sd-g-sm-4,.sd-gy-sm-4{--sd-gutter-y: 1.5rem}.sd-g-sm-4,.sd-gx-sm-4{--sd-gutter-x: 1.5rem}.sd-g-sm-5,.sd-gy-sm-5{--sd-gutter-y: 3rem}.sd-g-sm-5,.sd-gx-sm-5{--sd-gutter-x: 3rem}}@media(min-width: 768px){.sd-col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-md-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-md-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-md-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-md-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-md-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-md-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-md-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-md-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-md-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-md-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-md-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-md-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-md-0,.sd-gy-md-0{--sd-gutter-y: 0}.sd-g-md-0,.sd-gx-md-0{--sd-gutter-x: 0}.sd-g-md-1,.sd-gy-md-1{--sd-gutter-y: 0.25rem}.sd-g-md-1,.sd-gx-md-1{--sd-gutter-x: 0.25rem}.sd-g-md-2,.sd-gy-md-2{--sd-gutter-y: 0.5rem}.sd-g-md-2,.sd-gx-md-2{--sd-gutter-x: 0.5rem}.sd-g-md-3,.sd-gy-md-3{--sd-gutter-y: 1rem}.sd-g-md-3,.sd-gx-md-3{--sd-gutter-x: 1rem}.sd-g-md-4,.sd-gy-md-4{--sd-gutter-y: 1.5rem}.sd-g-md-4,.sd-gx-md-4{--sd-gutter-x: 1.5rem}.sd-g-md-5,.sd-gy-md-5{--sd-gutter-y: 3rem}.sd-g-md-5,.sd-gx-md-5{--sd-gutter-x: 3rem}}@media(min-width: 992px){.sd-col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-lg-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-lg-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-lg-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-lg-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-lg-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-lg-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-lg-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-lg-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-lg-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-lg-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-lg-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-lg-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-lg-0,.sd-gy-lg-0{--sd-gutter-y: 0}.sd-g-lg-0,.sd-gx-lg-0{--sd-gutter-x: 0}.sd-g-lg-1,.sd-gy-lg-1{--sd-gutter-y: 0.25rem}.sd-g-lg-1,.sd-gx-lg-1{--sd-gutter-x: 0.25rem}.sd-g-lg-2,.sd-gy-lg-2{--sd-gutter-y: 0.5rem}.sd-g-lg-2,.sd-gx-lg-2{--sd-gutter-x: 0.5rem}.sd-g-lg-3,.sd-gy-lg-3{--sd-gutter-y: 1rem}.sd-g-lg-3,.sd-gx-lg-3{--sd-gutter-x: 1rem}.sd-g-lg-4,.sd-gy-lg-4{--sd-gutter-y: 1.5rem}.sd-g-lg-4,.sd-gx-lg-4{--sd-gutter-x: 1.5rem}.sd-g-lg-5,.sd-gy-lg-5{--sd-gutter-y: 3rem}.sd-g-lg-5,.sd-gx-lg-5{--sd-gutter-x: 3rem}}@media(min-width: 1200px){.sd-col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto}.sd-col-xl-1{-ms-flex:0 0 auto;flex:0 0 auto;width:8.3333333333%}.sd-col-xl-2{-ms-flex:0 0 auto;flex:0 0 auto;width:16.6666666667%}.sd-col-xl-3{-ms-flex:0 0 auto;flex:0 0 auto;width:25%}.sd-col-xl-4{-ms-flex:0 0 auto;flex:0 0 auto;width:33.3333333333%}.sd-col-xl-5{-ms-flex:0 0 auto;flex:0 0 auto;width:41.6666666667%}.sd-col-xl-6{-ms-flex:0 0 auto;flex:0 0 auto;width:50%}.sd-col-xl-7{-ms-flex:0 0 auto;flex:0 0 auto;width:58.3333333333%}.sd-col-xl-8{-ms-flex:0 0 auto;flex:0 0 auto;width:66.6666666667%}.sd-col-xl-9{-ms-flex:0 0 auto;flex:0 0 auto;width:75%}.sd-col-xl-10{-ms-flex:0 0 auto;flex:0 0 auto;width:83.3333333333%}.sd-col-xl-11{-ms-flex:0 0 auto;flex:0 0 auto;width:91.6666666667%}.sd-col-xl-12{-ms-flex:0 0 auto;flex:0 0 auto;width:100%}.sd-g-xl-0,.sd-gy-xl-0{--sd-gutter-y: 0}.sd-g-xl-0,.sd-gx-xl-0{--sd-gutter-x: 0}.sd-g-xl-1,.sd-gy-xl-1{--sd-gutter-y: 0.25rem}.sd-g-xl-1,.sd-gx-xl-1{--sd-gutter-x: 0.25rem}.sd-g-xl-2,.sd-gy-xl-2{--sd-gutter-y: 0.5rem}.sd-g-xl-2,.sd-gx-xl-2{--sd-gutter-x: 0.5rem}.sd-g-xl-3,.sd-gy-xl-3{--sd-gutter-y: 1rem}.sd-g-xl-3,.sd-gx-xl-3{--sd-gutter-x: 1rem}.sd-g-xl-4,.sd-gy-xl-4{--sd-gutter-y: 1.5rem}.sd-g-xl-4,.sd-gx-xl-4{--sd-gutter-x: 1.5rem}.sd-g-xl-5,.sd-gy-xl-5{--sd-gutter-y: 3rem}.sd-g-xl-5,.sd-gx-xl-5{--sd-gutter-x: 3rem}}.sd-flex-row-reverse{flex-direction:row-reverse !important}details.sd-dropdown{position:relative}details.sd-dropdown .sd-summary-title{font-weight:700;padding-right:3em !important;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none}details.sd-dropdown:hover{cursor:pointer}details.sd-dropdown .sd-summary-content{cursor:default}details.sd-dropdown summary{list-style:none;padding:1em}details.sd-dropdown summary .sd-octicon.no-title{vertical-align:middle}details.sd-dropdown[open] summary .sd-octicon.no-title{visibility:hidden}details.sd-dropdown summary::-webkit-details-marker{display:none}details.sd-dropdown summary:focus{outline:none}details.sd-dropdown .sd-summary-icon{margin-right:.5em}details.sd-dropdown .sd-summary-icon svg{opacity:.8}details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg{opacity:1;transform:scale(1.1)}details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg{display:block;opacity:.6}details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down{pointer-events:none;position:absolute;right:1em;top:1em}details.sd-dropdown[open]>.sd-summary-title .sd-summary-down{visibility:hidden}details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up{visibility:hidden}details.sd-dropdown:not([open]).sd-card{border:none}details.sd-dropdown:not([open])>.sd-card-header{border:1px solid var(--sd-color-card-border);border-radius:.25rem}details.sd-dropdown.sd-fade-in[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out;animation:sd-fade-in .5s ease-in-out}details.sd-dropdown.sd-fade-in-slide-down[open] summary~*{-moz-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;-webkit-animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out;animation:sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out}.sd-col>.sd-dropdown{width:100%}.sd-summary-content>.sd-tab-set:first-child{margin-top:0}@keyframes sd-fade-in{0%{opacity:0}100%{opacity:1}}@keyframes sd-slide-down{0%{transform:translate(0, -10px)}100%{transform:translate(0, 0)}}.sd-tab-set{border-radius:.125rem;display:flex;flex-wrap:wrap;margin:1em 0;position:relative}.sd-tab-set>input{opacity:0;position:absolute}.sd-tab-set>input:checked+label{border-color:var(--sd-color-tabs-underline-active);color:var(--sd-color-tabs-label-active)}.sd-tab-set>input:checked+label+.sd-tab-content{display:block}.sd-tab-set>input:not(:checked)+label:hover{color:var(--sd-color-tabs-label-hover);border-color:var(--sd-color-tabs-underline-hover)}.sd-tab-set>input:focus+label{outline-style:auto}.sd-tab-set>input:not(.focus-visible)+label{outline:none;-webkit-tap-highlight-color:transparent}.sd-tab-set>label{border-bottom:.125rem solid transparent;margin-bottom:0;color:var(--sd-color-tabs-label-inactive);border-color:var(--sd-color-tabs-underline-inactive);cursor:pointer;font-size:var(--sd-fontsize-tabs-label);font-weight:700;padding:1em 1.25em .5em;transition:color 250ms;width:auto;z-index:1}html .sd-tab-set>label:hover{color:var(--sd-color-tabs-label-active)}.sd-col>.sd-tab-set{width:100%}.sd-tab-content{box-shadow:0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline);display:none;order:99;padding-bottom:.75rem;padding-top:.75rem;width:100%}.sd-tab-content>:first-child{margin-top:0 !important}.sd-tab-content>:last-child{margin-bottom:0 !important}.sd-tab-content>.sd-tab-set{margin:0}.sd-sphinx-override,.sd-sphinx-override *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sd-sphinx-override p{margin-top:0}:root{--sd-color-primary: #0071bc;--sd-color-secondary: #6c757d;--sd-color-success: #28a745;--sd-color-info: #17a2b8;--sd-color-warning: #f0b37e;--sd-color-danger: #dc3545;--sd-color-light: #f8f9fa;--sd-color-muted: #6c757d;--sd-color-dark: #212529;--sd-color-black: black;--sd-color-white: white;--sd-color-primary-highlight: #0060a0;--sd-color-secondary-highlight: #5c636a;--sd-color-success-highlight: #228e3b;--sd-color-info-highlight: #148a9c;--sd-color-warning-highlight: #cc986b;--sd-color-danger-highlight: #bb2d3b;--sd-color-light-highlight: #d3d4d5;--sd-color-muted-highlight: #5c636a;--sd-color-dark-highlight: #1c1f23;--sd-color-black-highlight: black;--sd-color-white-highlight: #d9d9d9;--sd-color-primary-text: #fff;--sd-color-secondary-text: #fff;--sd-color-success-text: #fff;--sd-color-info-text: #fff;--sd-color-warning-text: #212529;--sd-color-danger-text: #fff;--sd-color-light-text: #212529;--sd-color-muted-text: #fff;--sd-color-dark-text: #fff;--sd-color-black-text: #fff;--sd-color-white-text: #212529;--sd-color-shadow: rgba(0, 0, 0, 0.15);--sd-color-card-border: rgba(0, 0, 0, 0.125);--sd-color-card-border-hover: hsla(231, 99%, 66%, 1);--sd-color-card-background: transparent;--sd-color-card-text: inherit;--sd-color-card-header: transparent;--sd-color-card-footer: transparent;--sd-color-tabs-label-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1);--sd-color-tabs-label-inactive: hsl(0, 0%, 66%);--sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1);--sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62);--sd-color-tabs-underline-inactive: transparent;--sd-color-tabs-overline: rgb(222, 222, 222);--sd-color-tabs-underline: rgb(222, 222, 222);--sd-fontsize-tabs-label: 1rem} diff --git a/_static/design-tabs.js b/_static/design-tabs.js new file mode 100644 index 0000000..36b38cf --- /dev/null +++ b/_static/design-tabs.js @@ -0,0 +1,27 @@ +var sd_labels_by_text = {}; + +function ready() { + const li = document.getElementsByClassName("sd-tab-label"); + for (const label of li) { + syncId = label.getAttribute("data-sync-id"); + if (syncId) { + label.onclick = onLabelClick; + if (!sd_labels_by_text[syncId]) { + sd_labels_by_text[syncId] = []; + } + sd_labels_by_text[syncId].push(label); + } + } +} + +function onLabelClick() { + // Activate other inputs with the same sync id. + syncId = this.getAttribute("data-sync-id"); + for (label of sd_labels_by_text[syncId]) { + if (label === this) continue; + label.previousElementSibling.checked = true; + } + window.localStorage.setItem("sphinx-design-last-tab", syncId); +} + +document.addEventListener("DOMContentLoaded", ready, false); diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 0000000..d06a71d --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/_static/documentation_options.js b/_static/documentation_options.js new file mode 100644 index 0000000..7e4c114 --- /dev/null +++ b/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 0000000..a858a41 Binary files /dev/null and b/_static/file.png differ diff --git a/_static/jquery.js b/_static/jquery.js new file mode 100644 index 0000000..c4c6022 --- /dev/null +++ b/_static/jquery.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0' + + '' + + _("Hide Search Matches") + + "
" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/call-for-logos/README.html b/call-for-logos/README.html new file mode 100644 index 0000000..3145390 --- /dev/null +++ b/call-for-logos/README.html @@ -0,0 +1,145 @@ + + + + + + +Logo 1
+ +Logo 2
+ +Logo 3
+ +Logo 4
+ +Logo 5
+ +Logo 6
++
+Logo 7
++
+A common problem when developing is needing to build multiple packages on top of +the stack to test changes in several repositories. One way of doing this is +using Spack but there is an experimental way using cmake.
+First, source the releases or the nightlies as usual. Then, run the following +command:
+/cvmfs/sw-nightlies.hsf.org/key4hep/experimental/setup.py pkg1 pkg2
+
Where pkg1
and pkg2
are the packages that will be cloned (can be empty). On
+top of that, setup.py
checks for folders (or symbolic links) in the current
+directory that contain CMakeLists.txt
. This can be useful if we want to use a
+local version and don’t need to clone some repositories. After running the
+command, a CMakeLists.txt file will appear. We may have to edit it manually if
+we are using packages that are not recognized or are in a different organization
+than the predefined ones. The information that we’ll need to edit is most likely
+one of the first lines at the top:
set(pkgs EDM4hep k4FWCore)
+
that sets the packages that will be built in their right build order.
+and the individual FetchContent_Declare
entries for each package.
After we are happy with the CMakeLists.txt file, it’s important that we set the +new environment variables:
+mkdir install
+cd install
+export PATH=$PWD/bin:$PATH
+export LD_LIBRARY_PATH=$PWD/lib:$PWD/lib64:$LD_LIBRARY_PATH
+export ROOT_INCLUDE_PATH=$PWD/include:$ROOT_INCLUDE_PATH
+export PYTHONPATH=$PWD/python:$PYTHONPATH
+export CMAKE_PREFIX_PATH=$PWD:$CMAKE_PREFIX_PATH
+cd ..
+
Then, we can run the usual commands for building:
+mkdir build
+cd build
+cmake .. -DCMAKE_INSTALL_PREFIX=../install
+make -j N install
+
and it will build all the packages at the same time, so it may take some time. Symbolic links are
+created in the build directory for each package that allow us to run ctest
like:
cd k4FWCore
+ctest -j 2
+
in case we are building k4FWCore.
+For the cloned directories, in case we want to clone a different commit or +branch from the master/main branch, this can be done by editing the +CMakeLists.txt
+Not everything has been tested so it’s likely some things won’t work. For +many packages there are recent changes that enable these builds so using older +versions probably won’t work.
+The following packages have been built together successfully so it should be +possible to build any combination of them:
+podio
EDM4hep
k4FWCore
LCIO
ILCUTIL
LCCD
GEAR
Marlin
k4EDM4hep2LcioConv
k4MarlinWrapper
If we don’t want to build the master or main branch of the repositories we are +cloning, we have two options:
+Set the commit or branch we want in the CMakeLists.txt
in the corresponding
+FetchContent_Declare
entry by changing GIT_TAG
to whatever commit or branch
+we want to checkout.
Go to the source directory, which can be found in the build directory under
+_deps/<pkg>-src
and checkout manually whatever commit or branch you want.
CMake is a tool for building software, which has become the de-facto +standard outside HEP. In HEP, it is for example used by the ILC/CLIC +communities and by the LHCb collaboration. For CMS people, CMake is the +equivalent of scram.
+The first step is adding all dependencies to the bash environment. +In case you are unsure, it is best to use the default init script, provided on CVMFS for Centos7:
+source /cvmfs/sw.hsf.org/key4hep/setup.sh
+
Note that mixing setup scripts (from another package, for example) may or may not work as intended - more likely not.
+For any requests to changes in the environment, feel free to contact the software team on the mailing list or any other channels.
+Developers may also look into spack
to have more fine-grained control over the build dependencies.
Create a build directory: mkdir build; cd build
Run CMake in the build directory: cmake ..
Change any cmake options by rerunning cmake.
+For example: cmake .. -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=Debug
.
+Tools like ccmake may also be useful: ccmake ..
Compile the software, using all the cpus available: make -j `getconf _NPROCESSORS_ONLN`
Install by running make install
In case any dependency is changed, most likely you need to remove all the contents of the build folder and rerun cmake and the compilation.
In order to run the code you just installed, there are a few environment variables to set up (assuming the installation directory is the working directory):
+mkdir build; cd build
+cmake .. -DCMAKE_INSTALL_PREFIX=../InstallArea
+make install
+cd ../InstallArea
+
export CMAKE_PREFIX_PATH=$PWD/:$CMAKE_PREFIX_PATH
in order to use this installation as a dependency for other packages
export PATH=$PWD/bin/:$PATH
in order to make any executables available on the command line
export LD_LIBRARY_PATH=$PWD/lib:$PWD/lib64:$LD_LIBRARY_PATH
in order to make libraries available for linking and for the plugin systems in Gaudi/DD4hep
export PYTHONPATH=$PWD/python:$PYTHONPATH
in order to make libraries available for linking and for the plugin systems in Gaudi/DD4hep
export ROOT_INCLUDE_PATH=$PWD/include:$ROOT_INCLUDE_PATH
in case the package builds ROOT dictionaries
export <PACKAGENAME>=$PWD/share/<PackageName>
some packages distribute data files that are found with a special environment variable, usually this is the package name in all caps.
e.g. export K4SIMDELPHES=$PWD/share/k4SimDelphes/
Colin provides a few simple CMake +examples. They are helpful to understand the basics of +CMake.
+Get these packages:
+git clone https://github.com/cbernet/cmake-examples.git
+cd cmake-examples
+
Follow the instructions in +README.md.
+When adding new source files to a package, the CMake build system needs
+to be made aware of them. Usually CMakeLists.txt
contains a wildcard
+expression that adds all implementation files in a subfolder, e.g.
+src/*.cpp
, so there is no need to explicitly add the names of the
+new files. To update the list of files, it is fastest to run
+make configure
.
Note that when changing the name of a property of an algorithm or a
+tool, make
(and not only make packagename
) needs to be run for
+Gaudi to be aware of the change.
Key4hep packages, in particular the gaudi framework components, consist of executables, headers, scripts, dynamic libraries, xmls and special files describing gaudi components. +In order to use these, some environment variables need to be set.
+Gaudi also offers the possibility to set up the environment via the xenv
command. This is done by simply prefixing the command you want to run with the run
script in the top level directory of FCCSW, or directly in the build directory.
./build/run key4run Examples/options/pythia.py
+
Sometimes it is convenient to run FCCSW directly from the binaries in the build directory without installing them.
+This can be done by using the run
script in the build directory, or setting the environment variables as in setup.sh
for the build folder.
+Note that the directories in the build folder differ a bit. Mostly it is important the the LD_LIBRARY_PATH is pre-fixed with the library directories. The fccrun command should pick up the components from the build folder then.
Key4hep also uses CMake for integration tests.
+They are added with add_test()
and can be run with make test
in the build folder. For Gaudi packages, the environment should be set so they can be run also in a build environments, see https://github.com/HEP-FCC/k4Gen/blob/main/k4Gen/CMakeLists.txt
An environment variable is used to forward command line arguments to the cmake command, for example to run cmake with the trace
option:
CMAKEFLAGS='--trace' make
+
{% callout “How do I check compilation flags?” %}
+Instead of running make
, run:
make VERBOSE=1
+
{% endcallout %}
+This page should allow users that are new to Git to get started with Key4hep software, and describes the workflow for accessing and contributing code.
+For a general introduction to git, have a look at these tutorials:
+ +Please refer to this tutorial and the GitHub help.
+We recommend to clone github repositories via SSH, especially if you want to +contribute code. For this to work, you need to generate ssh keys for +authentication. See the corresponding github +help-page.
+{% callout “Generate and set up ssh keys for github” %}
+If you only want to use the software it may be easier to use https. In that case you don’t need to generate the keys but have to replace git@github:
with https://github.com/
in all the instructions. Note that you’ll not be able to push to your repository when you are on lxplus. You can also start using https for now and later re-add your repository with ssh authentication, see the trouble shooting section.
{% endcallout %}
+It may be useful to install Git integration tools for your shell that allow tab-completion of most git commands and also can show you in your prompt on which branch you currently are, what changes you have pending, etc.
+For any key4hep repository (taking k4SimDelphes
as an example), you will be using (at least) 3 sources:
The official Key4hep repository on github
Your fork of the repository (see github help on what that means)
Your local repository in your work area (e.g. on AFS)
The repositories 1 and 2 are added as remote to the repository 3:
+git clone git@github.com:[YOUR_GITHUB_USER]/k4SimDelphes.git # create a local copy (3) of your fork (2)
+cd k4SimDelphes
+git remote add upstream git@github.com:key4hep/k4SimDelphes.git # add official repo (1) as additional remote
+
fetch all changes from the official repository (1)
+git fetch --all --prune
+
rebase your development area to the master branch from the official repository (1), please read this to avoid loss of work
+git rebase -i upstream/main
+
in this process you can also fix any commits that need touching up, be aware that deleting commits in the list will result also in the deletion of the corresponding changes (more info in the GitHub help and the Atlassian tutorial)
+push your local changes to your fork (2), see below how to create a local branch
+git push origin [NAME_OF_LOCAL_BRANCH]
+
if you are fixing a bug, first create an issue in the github issue tracker.
develop your feature in your local copy (3) on a local branch of your choice, to create a branch do:
+git branch -b [NAME_OF_LOCAL_BRANCH]
+
refer to this tutorial to see how to commit changes
occasionally, get new code from the official repository (1) as explained above and merge it in this branch
test:
+that the code compiles and all tests succeed (make && make test
)
that your code runs (even better: [add an automatic test]
that it produces the expected results
push your local branch to your fork (2) (see above)
create a pull request from your fork (2) to the offical repository’s (1) master branch (see github help-page)
+also see the recommendations for pull requests
Please always follow the recommendations below.
+if you’re working on a given topic, always create a branch for
+it, e.g. pythia_interface
. You may commit many times to this branch
+in your local repository. When you have something solid create a
+pull request to the official repository.
feel free to commit often to your local repository, make a pull request once the topic you are working on is finished
+if the feature you are working on is large, consider making a work in progress-pull request (see below)
git commits represent a snapshot of the software as a whole, and not only the difference to a previous commit (although that as well, in practice). It is recommended that each commit compiles and passes the tests. Take a look at the commit history of a key4hep repository and the histories of some individual files to find both good and bad examples.
always provide a meaningful comment for each commit
+if you are working on an issue, refer to that issue by adding “refs. #[issue id]”, see also +GitHub help
commit comments should look like the one below, so that they show up +correctly in git printouts.
+first version of a pythia interface # this line should be a short 1 liner
+
+Here, you may write a few more lines if needed
+
before opening a pull request it may be a good idea to check that your history makes sense (commit messages explain what you did, no unnecessary commits, etc.), check with:
+git log
+
if you see commits that you’d like to change, there are several ways of doing that, the most commonly used is git rebase
:
with the interactive version you can rebase your development branch to the official master and fix the history at the same time
git fetch upstream # get changes from the official repo
+git rebase -i upstream/main # do the actual rebase
+
git will guide you through the steps, where you can delete entire commits (and the corresponding changes), merge commits and change commit messages
more information can be found in this tutorial
Give a meaningful title that appropriately describes what you did (e.g. Add new calorimeter clustering)
+Pull requests of work in progress (to make people aware that you are working on a feature) create a PR starting with “[WIP]”
In the description, give a short bullet-point list of what was done
If your pull request fixes issues tracked in the issue tracker:
+Make sure you added a test that shows they are actually fixed
In the description mention that you fixed it by referring to the issue: “fixes #
Check with git remote -v
which remote repositories you have added to your local copy. You should see something like:
upstream git@github.com:key4hep/k4SimDelphes.git (fetch)
+upstream git@github.com:key4hep/k4SimDelphes.git (push)
+origin git@github.com:[your git user name]/k4SimDelphes.git (fetch)
+origin git@github.com:[your git user name]/k4SimDelphes.git (push)
+
If you see something similar but all the addresses start with https
, see below.
If you only see origin git@github.com:key4hep/k4SimDelphes.git
, you need to add your own repository, push to that one and do a pull request, as described above. To add your own repository do:
git remote rename origin hep-fcc
+git remote add myfccsw git@github.com:[your git user name]/FCCSW.git
+
You only need to change the URL of your remote pointing to your repository to one that uses SSH instead:
+git remote set-url [the remote name] git@github.com:[your git user name]/k4SimDelphes.git
+
Now you can push to that remote with:
+git push [the remote name] [the branch you want to push]
+
In case you have any questions on this guide, or need help to sort out +an issue with a repository, feel free to drop a mail to +key4hep-sw at CERN, and we’ll be happy to help you. +Alternatively create an issue in the bug tracker +.
+Sooner rather than later you will find it necessary write code for Key4hep. These pages cover some software development topics to remove any friction.
+CMakeBuild.md
+For quick changes of, for example, a single package, it’s possible to compile +the package using cmake (after having sourced the release or nightlies) and then +export some environment variables manually so that our local version will be +picked up instead of the one in cvmfs:
+export PATH=/path/to/install/bin:$PATH
+export LD_LIBRARY_PATH=/path/to/install/lib:/path/to/install/lib64:$LD_LIBRARY_PATH
+export ROOT_INCLUDE_PATH=/path/to/install/include:$ROOT_INCLUDE_PATH
+export PYTHONPATH=/path/to/install/python:$PYTHONPATH
+
where the path to the installation is the one we gave cmake with
+-DCMAKE_INSTALL_PREFIX
when configuring. It’s possible more environment
+variables need to be set depending on which package we are installing but the
+previous ones are the main ones for many of the packages of the key4hep stack.
While this approach works and any number of packages can be built this way, it +is cumbersome to do so for many packages, as one has to repeat the cycle of +configuring, building and installing and then exporting the environment +variables as many times as packages are installed. It is possible to miss +packages and then the cvmfs version will be used instead of the local one +without notice and it’s also cumbersome to reproduce the environment at a later +time.
+Using spack to develop software is somewhat pushing its intended usage to its +limits. However, it is not impossible and this is an area of spack that is +currently under active development. Unfortunately, this also means that the +spack documentation might not be fully up-to-date on these topics. Hence, this +page tries to collect some of the experiences the Key4hep developers have made.
+Tip
+To obtain and setup spack
take a look at Setting up Spack.
For a standalone spack installation where we are happy to install all the +dependencies the link above will suffice. However, it is possible to use the +key4hep stack from cvmfs that has all the dependencies installed and only +install the packages that we want to work on. For that, it is important to +reproduce the environment that was used for building whatever release we are +going to use. Otherwise spack will see that we have different versions of +packages and will try to compile and install more than what we need. As +explained here, there are three files that are provided with each release or +nightly, that we need to use. Let’s say we want to use the nigthly for +2023-07-18. Then the first thing we do is source the nightly:
+source /cvmfs/sw-nightlies.hsf.org/key4hep/releases/2023-07-18/x86_64-almalinux9-gcc11.3.1-opt/key4hep-stack/2023-07-18-kzukii/setup.sh
+
And then we clone spack and key4hep-spack, set up the environment and the
+upstream installation, and the latest build from scratch (that we have to find
+manually for now using, for example, find -iname .scratch
), in this case it
+happens to be 2023-06-24):
rel=/cvmfs/sw-nightlies.hsf.org/key4hep/releases/2023-07-18/x86_64-almalinux9-gcc11.3.1-opt
+latest_scratch=/cvmfs/sw-nightlies.hsf.org/key4hep/releases/2023-06-24/x86_64-almalinux9-gcc11.3.1-opt
+git clone https://github.com/key4hep/key4hep-spack --depth 1
+git clone https://github.com/spack/spack
+cd key4hep-spack
+git checkout $(cat $rel/.key4hep-spack-commit)
+cd ..
+cd spack
+git checkout $(cat $rel/.spack-commit)
+source $rel/.cherry-pick
+cd ..
+source spack/share/spack/setup-env.sh
+spack env activate key4hep-spack/environments/key4hep-nightly
+spack config add "upstreams:nightly:install_tree: $rel"
+spack config add "upstreams:nightly-scratch:install_tree: $latest_scratch"
+
And now we should have exactly the same version of spack and key4hep-spack that +was used to make the build, so the number of dependencies that spack tries to +install should be the minimum: it should find all the dependencies (in practice +this may not be the case but it should find most of them).
+When only developing on a single package it is possible to use the dev-build
command of spack.
+A brief tutorial can be found in the spack documentation.
+There is also a dedicated channel on slack spackpm.slack.com (to get an invitation, visit slack.spack.io) where questions regarding the development workflow can be discussed.
+It allows to build a given package directly from local sources in the same way as spack does it, and even makes this package available to other packages in the same way it does packages that have been installed by spack directly.
+Here we will use LCIO as an example since it can be installed without (or with only one) dependency.
As a first step let’s have a look at what installing lcio
with spack would entail.
+Note that we explicitly disable the ROOT dictionaries in order to limit the number of dependencies
spack spec -Il lcio ~rootdict
+
Input spec
+--------------------------------
+ - lcio~rootdict
+
+Concretized
+--------------------------------
+
+ - vdwx2aq lcio@2.16%gcc@9.3.0~examples~ipo~jar~rootdict build_type=RelWithDebInfo cxxstd=17 arch=linux-ubuntu20.04-skylake
+[+] utzbuq7 ^cmake@3.16.3%gcc@9.3.0~doc+ncurses+openssl+ownlibs~qt patches=1c540040c7e203dd8e27aa20345ecb07fe06570d56410a24a266ae570b1c4c39,bf695e3febb222da2ed94b3beea600650e4318975da90e4a71d6f31a6d5d8c3d arch=linux-ubuntu20.04-skylake
+[+] pljbs5a ^sio@0.0.4%gcc@9.3.0+builtin_zlib~ipo build_type=RelWithDebInfo cxxstd=17 arch=linux-ubuntu20.04-skylake
+
+
In this configuration lcio
has only two dependencies, sio
and cmake
, which
+are both already installed in this case. If these dependencies are not yet
+installed, spack will automatically install them for you when using the
+dev-build
command.
dev-build
In order to install a local version of LCIO with spack, first we have to clone it into a local directory
+git clone https://github.com/iLCSoft/LCIO
+
Now we can install this local version via
+cd LCIO
+spack dev-build lcio@master ~rootdict
+
This should install lcio
and all dependencies that are not yet fulfilled, giving you the full output of all the build stages ending on something like the following
...
+==> lcio: Successfully installed lcio-master-7dovpqn3kscbg672ham5wcqro7lg45gh
+ Fetch: 0.00s. Build: 1.62s. Total: 1.62s.
+[+] /home/tmadlener/work/spack/opt/spack/linux-ubuntu20.04-skylake/gcc-9.3.0/lcio-master-7dovpqn3kscbg672ham5wcqro7lg45gh
+
Note, that it is necessary to specify a single concrete version here for lcio
. We use @master
.
+This version has to be one that is already available for the package (use spack info
to find out which ones are available) and cannot be an arbitrary version.
+It also does not necessarily have to correspond to the actual version of the source code you are currently installing.
+However, it is of course encouraged to use a meaningful version specifier, since this package should also be useable as desired by dependent packages.
Now that the local version has been installed, it would of course be nice to be able to use it in downstream packages as well. +As far as spack is concerned, a package that has been built from local sources is not really different from one that has been built from automatically downloaded sources. +The main difference is that the fact that it has been built from local sources manifests in the spec
+spack find -lv lcio
+
will yield something like
+==> 1 installed package
+-- linux-ubuntu20.04-skylake / gcc@9.3.0 ------------------------
+7dovpqn lcio@master~examples~ipo~jar~rootdict build_type=RelWithDebInfo cxxstd=17 dev_path=/home/tmadlener/work/ILCSoft/LCIO
+
As you can see the local path from which this version was installed has become part of the spec for the installed package (the dev_path=...
part of the spec above).
+Hence, also the hash is affected by the fact that it has been built from a local source.
To use this specific version as a dependency the usual spack syntax can be used, e.g.
+spack install marlin ^lcio/7dovpqn
+
will install marlin
but use the version of lcio
that we have just built locally.
Note: If you have installed lcio following the description above you might have to uninstall it again first to follow these instructions, because spack will not overwrite an already installed package.
+The above instructions only dealt with installing a package from a local source, but not how to easily get a development environment allowing for a quick edit, compile cycle.
+This can be achieved by using the --drop-in
and the --before
/--until
arguments of the dev-build
command:
spack dev-build --drop-in bash --until cmake lcio@master ~rootdict
+
This command will first install all necessary dependencies, then run the install process for lcio
until after the cmake
stage and then drop you into a new bash shell with the proper build environment setup.
+It will also setup a build folder, which follows the naming scheme spack-build-${hash}
, in this case: spack-build-7dovpqn
.
+To compile lcio
simply go into this directory and run make
in there
cd spack-build-7dovpqn
+make -j4
+
You are now in an environment where you can easily edit the local source code and re-compile afterwards.
+Once all the development is done, it is still necessary to install everything to the appropriate location.
+This installation has to be registered in the spack database as well. Hence, simply calling make install
in the build directory will not do the trick.
+Another call to dev-build
is necessary.
cd .. # go back to the source directory where you started
+spack dev-build lcio@master ~rootdict
+
This will run the whole chain again, but it will not overwrite the build directory.
+Hence, it will not recompile everything again, but simply install all the build artifacts to the appropriate location.
+spack find -lv lcio
can be used to check if the installation was successful.
NOTE: You are probably still in the build environment at this stage. To return back to you original shell simply type exit
.
Developing on many packages simultaneously using the dev-build
command can become cumbersome and doesn’t really scale.
One way to develop on multiple packages simultaneously can be to setup an environment that contains the dependencies of all packages.
+As an example the following definition of an environment has been used to develop on
+podio
, EDM4HEP
and some other packages.
spack:
+ specs:
+ - python
+ - root@6.20.04 +davix+gsl+math~memstat+minuit+mlp~mysql+opengl~postgres~pythia6+pythia8+python~qt4+r+root7+rootfit+rpath~shadow+sqlite+ssl~table+tbb+threads+tmva+unuran+vc+vdt+vmc+x+xml+xrootd build_type=RelWithDebInfo cxxstd=17 patches=22af3471f3fd87c0fe8917bf9c811c6d806de6c8b9867d30a1e3d383a1b929d7
+ - dd4hep +geant4
+ - geant4
+ - heppdt
+ - hepmc@2.06.10
+ - tricktrack
+ - py-pyyaml
+ - py-jinja2
+ - cmake
+ - pythia8
+ - evtgen
+ concretization: together
+ view: true
+ packages:
+ all:
+ compiler: [gcc@9.3.0]
+ variants: cxxstd=17
+
Assuming this is the content of edm4hep_devel.yaml
an environment can be created, activated, concretized and installed with the following commands:
spack env create edm4hep-devel edm4hep_devel.yaml
+spack env activate -p edm4hep-devel
+spack concretize
+spack install
+
After an environment has been installed, it can easily be activated via
+spack env activate -p edm4hep-devel
+
which immediately drops you in an environment with all the packages stated in the environment file above available and properly set up. +Developing packages that depend on these should then be straight forward, especially for properly setup CMake based projects that can automatically find and configure their dependencies.
+The disadvantage of this approach is that the packages you want to develop on have to be on the top of the stack and if they depend on each other, you still have to properly handle these dependencies on your own.
+Recently spack gained the ability to setup environments and specify multiple packages that you would like to develop on (See spack/spack#256). +It is not yet really documented and it is not yet fully optimized, but it allows for a decent development experience if your package is not too deep down in the stack. +It is not impossible to develop on packages deep down the software stack, but this can imply frequently recompiling large parts of the software stack, since spack does not yet handle this in the best way, but instead builds all packages that you are not developing on from scratch. Hence, even if a simple relinking would have done the trick, spack will still build a lot of packages again. +Nevertheless, the feature is in a usable state and this section briefly describes how to use it. +Especially if you mainly develop on one package but sometimes want to check whether the rest of the stack, that depends on this package still compiles with the latest version, this can be a very useful workflow.
+As an example we will be using the k4simdelphes
package that depends on edm4hep
, which in turn depens again on podio
.
+Suppose we want to change podio
and edm4hep
and see if k4simdelphes
still compiles and works.
+We would then use an environment definition file similar to the usual environments. For this example it has the following content
spack:
+ spec:
+ - k4simdelphes
+ concretization: together
+ view: false
+ packages:
+ all:
+ compiler: [gcc@9.3.0]
+ variants: cxxstd=17
+ develop:
+ podio:
+ spec: podio@master +sio
+ path: ../../../../../podio
+ edm4hep:
+ spec: edm4hep@master
+ path: ../../../../../EDM4hep
+
The first part is the same as previously, but a new develop
section containing information about the packages that should be developed on has been added.
+For each package there is a spec
and a path
field. The spec
field tells spack which spec to build, while the path
field tells spack where the source files are located.
+The path is relative to the $(prefix)/var/spack/environments/${environment-name}
directory or an absolute path.
Assuming that you are currently in the directory that contains local spack
installation, the following steps are necessary to create the development environment
git clone https://github.com/AIDASoft/podio
+git clone https://github.com/key4hep/EDM4hep
+spack env create my-development-env development_env_packages.yaml
+
where development_env_packages.yaml
is the yaml file with the contents just described above.
It is now possible to activate this environment via
+spack env activate -p my-development-env
+
To install all the packages, including the local versions of podio
and edm4hep
it is now enough to simply do spack install
in the activated environment.
+This will build your local copies of podio
and edm4hep
and use these versions as dependencies for the k4simdelphes
package.
+Changes can also be made to either of the two packages.
+To compile only one package without installing it yet, it is easiest to simply go to the directory where the sources are.
+There should now be a few spack related files and a spack build folder among the other source files
[...]
+spack-configure-args.txt
+spack-build-env.txt
+spack-build-out.txt
+spack-build-${hash}
+
Here ${hash}
is the same that you get from spack find -l package
.
+After you have done all the necessary changes you can simply change into this build directory and run make
to compile the package again.
+Once all your development is done and you want to install the package spack install
will run the whole build chain again.
+This means that all the (local) development packages in your environment will only be recompiled as far as necessary, while all other packages that depend on the development packages will be re-built from scratch.
Once you are done developing, this environment can be used like any other environment simply by running spack env activate my-development-env
to activate it.
If you now realize that your changes to podio
or edm4hep
broke k4simdelphes
and you need to also implement some changes there, you do not have to define a new environment.
+Instead it is possible to add k4simdelphes
to the develop
section via spack develop
(assuming you are still in the activated environment and in the same directory where also the podio
and edm4hep
sources live)
git clone https://github.com/key4hep/k4SimDelphes
+spack develop --no-clone --path ../../../../../k4SimDelphes k4simdelphes@main
+
Here, the --path
is again either relative to the environment directory inside spack. It could also be an absolute path.
+You now have to concretize the environment again before you can install the packages.
spack concretize -f
+spack install
+
Now you can work on k4simdelphes
in the same way as you can for podio
or edm4hep
.
+You can also check that the environment now indeed uses your local version of k4simdelphes
via
spack find -lv k4simdelphes
+
which should now yield something along the lines of
+==> In environment my-development-env
+==> Root specs
+------- k4simdelphes@main
+
+==> 1 installed package
+-- linux-ubuntu20.04-broadwell / gcc@9.3.0 ----------------------
+m5khm2w k4simdelphes@main~ipo build_type=RelWithDebInfo dev_path=/home/tmadlener/work/spack/var/spack/environments/test-devel-env/../../../../../k4SimDelphes
+
where the path to the local source files has now again become part of the spec as can be seen by the dev_path=...
part of the spec.
Gaudi is an event-processing framework. Algorithms can be defined by users and +Gaudi will take care of running them for each event. In addition, Gaudi has a +set of services and tools like logging and support for running in a +multithreaded environment.
+The relationship between Gaudi with key4hep happens through
+k4FWCore. k4FWCore has tools and
+utilities needed to be able to use (almost) seamlessly EDM4hep collections in
+Gaudi algorithms. We recommend checking out the
+tests in this
+repository since they contain examples of algorithms (in particular of
+algorithms using Gaudi::Functional
).
Using Gaudi::Functional
is the recommended way of creating algorithms. The
+design is simple and at the same time enforces several constraints at
+compile-time, allowing for a quicker development cycle. In particular, we will
+see that our algorithms won’t have an internal state and we obtain the benefit
+of being able to run in a multithreaded environment (almost) trivially[1].
We will need Gaudi, k4FWCore and all their dependencies. Installing these by +ourselves is not easy but there are software stacks on cvmfs, see the +/setup-and-getting-started/README.md to set up the key4hep stack.
+The easiest way of having a working repository is to copy the template +repository that we provide in key4hep:
+git clone https://github.com/key4hep/k4-project-template
+
or ideally with ssh
+git clone git@github.com:key4hep/k4-project-template
+
This template repository already has the cmake code that will make our
+algorithms know where Gaudi and k4FWCore and to properly link to them. In
+addition there are a few examples that combined with the tests in k4FWCore
+provide an overview of what’s possible to do. The k4-project-template
+repository contains a CMake configuration (as described in more detail in the
+previous tutorial) so it can be built with:
cd k4-project-template
+mkdir build install
+cd build
+cmake .. -DCMAKE_INSTALL_PREFIX=../install
+make -j 4 install
+
To run the algorithms contained in this repository you can use k4run
, like:
k4run ../K4TestFWCore/options/createExampleEventData.py
+
Functional algorithms in Gaudi are relatively straightforward to write. For each
+algorithm we want, we have to create a class that will inherit from one of the
+Gaudi::Functional
classes. The most important function member will be
+operator()
which is what will run over our events (or over none in case we are
+generating). There are several base classes in Gaudi (see a more complete list
+in https://lhcb.github.io/DevelopKit/03a-gaudi/):
Consumer, one or more inputs, no outputs
Producer, one or more outputs, no inputs
Transformer (and MultiTransformer), one or more inputs, one or more outputs
The structure of our class (more precisely structs) will then be, in the general +case of the transformer:
+#include "GaudiAlg/Transformer.h"
+// Define BaseClass_t
+#include "k4FWCore/BaseClass.h"
+
+struct ExampleTransformer final
+ : Gaudi::Functional::Transformer<colltype_out(const colltype_in&), BaseClass_t> {
+
+ ExampleTransformer(const std::string& name, ISvcLocator* svcLoc);
+ colltype_out operator()(const colltype_in& input) const override;
+};
+
Some key points:
+The magic to make our algorithm work with EDM4hep collections happens by
+including BaseClass.h
and passing BaseClass_t
it as one of the template
+arguments to the Gaudi class we are inheriting from.
operator()
is const, which means that it can’t modify class members. This is
+intended and helps with multithreading by not having an internal state.
Let’s start with the first template argument. It’s the signature of a function +that returns one or more outputs and takes as input one or more inputs. +One possible example would be to have these two lines before the class definition:
+using colltype_in = edm4hep::MCParticleCollection;
+using colltype_out = edm4hep::MCParticleCollection;
+
and then we have a transformer that will take one MCParticleCollection
as
+input and return another one. If we have multiple inputs we keep adding
+arguments to the function arguments and if we don’t have any we can leave that
+empty. For the output this is slightly more complicated because if there are
+more than one output we have to return an std::tuple<OutputClass1, OutputClass2>
; if there aren’t any outputs we can simply return void
.
Then we reach the constructor. We’ll always initialize from the constructor of the
+class we’re inheriting (in this example a Transformer
) and then we’ll
+initialize a set of KeyValues
. These KeyValues
will be how we define the
+names of our inputs and outputs so they can be found by other algorithms, read
+from a file or saved to a file.
ExampleTransformer(const std::string& name, ISvcLocator* svcLoc)
+ : Transformer(name, svcLoc,
+ KeyValue("InputCollection", "MCParticles"),
+ KeyValue("OutputCollection", "NewMCParticles")) {
+ // possibly do something
+ }
+
Here we are defining how we will name our input collection in the steering value
+(InputCollection
) and giving it a default value. We’re doing the same with the
+output collection. The order is important here: first inputs and then outputs
+and they are ordered. When we have more inputs we just add another line, like
+the one above for the input collection. For outputs, since they are bundled
+together in a std::tuple
when there are several, we have to enclose the list
+of KeyValue
with brackets, like
ExampleMultiTransformer(const std::string& name, ISvcLocator* svcLoc)
+ : MultiTransformer(name, svcLoc,
+ KeyValue("InputCollection", "MCParticles"),
+ {
+ KeyValue("OutputCollection1", "NewMCParticles"),
+ KeyValue("OutputCollection2", "SimTrackerHits"),
+ KeyValue("OutputCollection3", "UsefulCollection"),
+ }
+ ) {
+ // possibly do something
+ }
+
Then in the operator()
we can do whatever we want to do with our collections
colltype_out operator()(const colltype_in& input) const override {
+ auto coll_out = edm4hep::MCParticleCollection();
+ for (const auto& particle : input) {
+ auto new_particle = edm4hep::MutableMCParticle();
+ new_particle.setPDG(particle.getPDG() + 10);
+ new_particle.setGeneratorStatus(particle.getGeneratorStatus() + 10);
+ new_particle.setSimulatorStatus(particle.getSimulatorStatus() + 10);
+ new_particle.setCharge(particle.getCharge() + 10);
+ new_particle.setTime(particle.getTime() + 10);
+ new_particle.setMass(particle.getMass() + 10);
+ coll_out->push_back(new_particle);
+ }
+ return coll_out;
+
When we return several collections we can bundle them in an std::tuple
like this:
return std::make_tuple(std::move(collection1), std::move(collection2));
+
The complete example for reference can be found in the tests of k4FWCore: +https://github.com/key4hep/k4FWCore/blob/main/test/k4FWCoreTest/src/components/ExampleFunctionalTransformer.cpp
+The steering file is the file where we define which algorithms will run, what +parameters they will use and how they will do it; what level of logging, if +using multithreading, etc.
+We start with some imports
+from Gaudi.Configuration import INFO
+from Configurables import ExampleFunctionalTransformer
+from Configurables import ApplicationMgr
+from Configurables import k4DataSvc
+from Configurables import PodioOutput
+from Configurables import PodioInput
+
it’s also possible to import everything from Configurables
but it’s better not
+to so that if we are using IDE or an editor with some kind of analysis it can
+tell us if we are using an undefined variable, for example.
Then, the input:
+podioevent = k4DataSvc("EventDataSvc")
+podioevent.input = "output_k4test_exampledata_producer.root"
+
+inp = PodioInput()
+inp.collections = [
+ "MCParticles",
+]
+
We select the name of the input file and which collections we’ll make available +for the rest of the algorithms.
+For the output:
+out = PodioOutput("out")
+out.filename = "output_k4test_exampledata_transformer.root"
+# The collections that we don't drop will also be present in the output file
+out.outputCommands = ["drop MCParticles"]
+
we can select which collections we keep in the output file. By default the
+collections in the output file will be the same as in the input file. Check the
+relevant
+documentation
+to learn more about PodioInput
and PodioOutput
.
Our algorithm will look like this:
+transformer = ExampleFunctionalTransformer("ExampleFunctionalTransformer",
+ InputCollection="MCParticles",
+ OutputCollection="NewMCParticles")
+
If we have defined Gaudi::Property
s for our algorithm it is also possible to
+change them by doing transformer.property = value
; however with the names of
+the collections, if they are provided, they are set when creating the python
+object with our algorithm.
Finally we define what to run:
+ApplicationMgr(TopAlg=[inp, transformer, out],
+ EvtSel="NONE",
+ EvtMax=10,
+ ExtSvc=[k4DataSvc("EventDataSvc")],
+ OutputLevel=INFO,
+ )
+
We pass a list of the algorithms in TopAlg
. PodioInput
will be the first one
+and PodioOutput
will be the last one when used. In EvtMax
we set what is the
+maximum number of event that we are processing. Use -1 not to limit it. That
+means if we are processing a file, then read all the events in the file. We pass
+extra services to ExtSvc
and set an OutputLevel
that could be DEBUG
,
+WARNING
or INFO
most of the time.
There are some occasions where we may want to run some code between the
+constructor and the operator()
; that is the place for initialize()
. There is
+also a way of doing something similar after processing with finalize()
. For that, we
+can add to our classes those functions (we can also add only one of these):
StatusCode initialize() override;
+ StatusCode finalize() override;
+
and then we can implement them.
+Make sure to remember to return the corresponding status code, otherwise +Gaudi will crash. For example:
+StatusCode MyAlgorithm::initialize() {
+ // do something
+ return StatusCode::SUCCESS;
+}
+
The GNU Project Debugger is supported by
+Gaudi and can be invoked by passing additional --gdb
parameter to the k4run
.
+For example:
k4run ../K4TestFWCore/options/createExampleEventData.py --gdb
+
This will start the GDB and attaches it to the Gaudi steering. After initial
+loading, user can start running of the steering by typing continue
into the
+GDB console. To interrupt running of the Gaudi steering use CTRL+C
.
More details how to run GDB with Gaudi can be found in +LHCb Code Analysis Tools (requires a CERN account to view).
+operator()
There is a way of working around operator()
being const and that is by adding
+the keyword mutable
to our data member. This will allow us to change our data
+member inside operator()
and will cause code that wasn’t compiling because of
+this to compile. Of course, this is not a good idea because unless the member of
+our class is thread-safe, that means that our algorithm is no longer thread-safe
+and running with multiple threads can cause different results. Even worse than
+that, it’s very possible that there are not any errors or crashes but the
+results are simply wrong from having several threads changing a member at the
+same time, for example.
This page contains a few brief How-Tos and Instructions on how to achieve +certain things within the Key4hep software stack. They are mainly aimed at +Key4hep users and are mostly designed to be reference material, rather than +tutorials.
+k4run
The lcio2edm4hep
executable reads LCIO (.slcio
) files and converts its
+contents into EDM4hep. Each LCEvent
of the input file will be put into a
+podio::Frame
in the output file (under the events
category). The most basic
+usage is simply
lcio2edm4hep <input.slcio> <output.edm4hep.root>
+
A major difference between LCIO and EDM4hep is that in LCIO an LCEvent
can
+effectively have arbitrary contents, whereas in EDM4hep the assumption is that
+each event consists of the same collections (even if some of them are empty).
+Hence, it is necessary to either ensure that all events in the LCIO file have
+the same contents or or to give lcio2edm4hep
some additional information such
+that it can patch in potentially missing collections on the fly. This additional
+information comes in the form of a third argument to lcio2edm4hep
and is
+effectively a list of collection names and their types that comprise the
+superset of all collections appearing in at least one event in the input LCIO
+file. The format looks like this
name[:output-name] type-name
+
Each collection is a single line containing the name first (including an +optional output name see below) and than its +type. The simplest form looks like this:
+SETSpacePoints TrackerHit
+RecoMCTruthLink LCRelation[ReconstructedParticle,MCParticle]
+
The easiest way to obtain such a file is to use the check_missing_cols
+executable that comes with LCIO using the --minimal
flag. The output of this
+can be directly consumed by lcio2edm4hep
Get the patch file
check_missing_cols --minimal \
+ /pnfs/desy.de/ilc/prod/ilc/mc-2020/ild/rec/250-SetA/higgs/ILD_l5_o2_v02/v02-02-01/00015671/000/rv02-02-01.sv02-02-01.mILD_l5_o2_v02.E250-SetA.I402005.Pe3e3h.eL.pR.n000_002.d_rec_00015671_493.slcio \
+ > patch.txt
+
Pass it to lcio2edm4hep
lcio2edm4hep \
+ /pnfs/desy.de/ilc/prod/ilc/mc-2020/ild/rec/250-SetA/higgs/ILD_l5_o2_v02/v02-02-01/00015671/000/rv02-02-01.sv02-02-01.mILD_l5_o2_v02.E250-SetA.I402005.Pe3e3h.eL.pR.n000_002.d_rec_00015671_493.slcio \
+ Output.root \
+ patch.txt
+
LCRelation
collectionsFor collections of LCRelation
type it is necessary to define the FromType
and
+ToType
as well, as otherwise the converter will not be able to create the
+correct edm4hep file. The check_missing_cols
executable will try to determine
+these types from the collection parameters and will warn if it cannot do it for
+certain collections. In this case it is the users responsibility to provide
+the missing types as otherwise the conversion will simply skip these
+collections, or potentially even crash.
Using the same mechanism as for patching collections it is also possible to only
+convert a subset of all available collections. lcio2edm4hep
uses the contents
+of the colltypefile
to determine the contents of the output. If that contains
+only a subset of all collections, only that subset will be converted. Missing
+collections will still be patched in, in this case.
The optional [:output-name]
part of each collection can be used to remap the
+names of the collections in the input LCIO file to a different name in the
+output EDM4hep file, e.g.
MCParticle:MCParticles MCParticle
+
will read the MCParticle
collection from the input file but store it as
+MCParticles
in the output file.
The conversion functions are designed to also be usable as a library. The overall design is to make the conversion a two step process. Step one is converting the data and step two being the resolving of the relations and filling of subset collection.
+The main entry point is convertCollection
which will automatically dispatch to
+the correct conversion function depending on the type information that is stored
+in the input LCCollection
. It is also possible to access the individual
+conversion functions for each type. All of the conversion functions take a map
+of LCIO to EDM4hep objects of their specific type that will be filled during the
+conversion. for convenience all necessary maps are bundled in the
+LcioEdmTypeMapping
struct.
Once all necessary collections have been converted, it is necessary to resolve
+the relations between the objects. This is done using the resolveRelations
+function. This will again dispatch to the correct relation resolving function
+for the corresponding types, which can obviously also be invoked directly.
Subset collections are handled similar to relations using the function
+fillSubset
. Internally this simply forwards to handleSubsetColl
which
+handles all the type details and can obviously also be used directly.
LCRelation
sLCRelation
only exist in LCIO and their conversion is limited to what is
+available in EDM4hep. They use the "FromType"
and "ToType"
collection
+parameters to get the necessary type information.
The AssociationCollections in EDM4hep are then created using createAssociations
.
Converting an entire event can be done calling the convertEvent
. This can also
+be used as an example to guide the implementation of custom conversions using
+the available functionality.
This can be done by calling convertObjectParameters
that will put all the event parameters into the passed podio::Frame
.
There are a few small differences between LCIO and EDM4hep that shine through in the conversion, these are:
+CaloHitContributions
are part of the SimCalorimeterHits in LCIO while being their own data type in EDM4hep. They are created by createCaloHitContributions
.
The event information like an event number is part of the LCEvent
in LCIO. In EDM4hep there is a separate EventHeader Collection. It can be created using EventHeaderCollection
which is stored under the name "EventHeader"
.
Particle IDs are converted during the conversion of the the reconstructed Particle collection.
#include "k4EDM4hep2LcioConv/k4Lcio2EDM4hepConv.h"
+
+// the struct defined in the header file is used for the maps linking Lcio particles
+// to their EDM counterparts.
+
+auto typeMapping = LcioEdmTypeMapping{};
+
+// We assume that this is a collection of ReconstructedParticles!
+LCEVENT::LCCollection* lcCollection;
+
+// Convert the data
+auto edmCollections = convertReconstructedParticle("name",
+ lcCollection,
+ typeMapping.recoParticles,
+ typeMapping.particleIDs);
+
+// Resolve relations (only converted objects will be available)
+// This has to be called at the very end, after all collection data has been
+// converted
+resolveRelations(typeMapping);
+
The facilities to read and write EDM4hep (or in general event data models based
+on podio) are provided by k4FWCore
.
+This page will describe their usage, but not go into too much details of their
+internals. This page also assumes a certain familiarity with Gaudi, i.e. most of
+the snippets just show a minimal configuration part, and not a complete runnable
+example.
k4DataSvc
Whenever you want to work with EDM4hep in the Gaudi based framework of Key4hep,
+you will need to use the k4DataSvc
as EventDataSvc. You can instantiate and
+configure this service like the following
from Gaudi.Configuration import *
+from Configurables import k4DataSvc
+
+evtSvc = k4DataSvc("EventDataSvc")
+
It is important that the name is EventDataSvc
in this case, as otherwise
+this is an assumption from Gaudi. Once you have the k4DataSvc
instantiated,
+you still have to make the ApplicationMgr
aware of it, by making sure that the
+evtSvc
is in the list of the external services (ExtSvc
):
from Configurables import ApplicationMgr
+ApplicationMgr(
+ # other args
+ ExtSvc = [evtSvc]
+)
+
To read events you will need to use the PodioInput
algorithm in addition to
+the k4DataSvc
. Currently, you will need to pass the input
+file to the k4DataSvc
via the input
option but pass the collections that you
+want to read to the PodioInput
. We are working on making this (discussion
+happens in this issue). The
+parts of your options file related to reading EDM4hep files will look something
+like this
from Configurables import PodioInput, k4DataSvc
+
+evtSvc = k4DataSvc("EventDataSvc")
+evtSvc.input = "/path/to/your/input-file.root"
+
+podioInput = PodioInput()
+
It is possible to change the input file from the command line via
+k4run <your-options-file> --EventDataSvc.input=<input-file>
+
By default the PodioInput
will read all collections that are available from
+the input file. It is possible to limit the collections that should become
+available via the collections
option
podioInput.collections = [
+ # List of collection names that should be made available
+]
+
To write events you will need to use the PodioOutput
algorithm in addition to
+the k4DataSvc
:
from Configurables import PodioOutput
+
+podioOutput = PodioOutput("PodioOutput", filename="my_output.root")
+
By default this will write the complete event contents to the output file.
+Sometimes it is desirable to limit the collections to a subset of all available
+collections from the EventStore. The PodioOutput
allows to do this via the
+outputCommands
option that takes a list of keep
or drop
commands. Each
+command must consist of the keep
/drop
command and a target. The target is a
+collection name that may include the ?
or *
wildcard patterns. This might
+look like the following
podioOutput.outputCommands = ["keep *"]
+
which will keep everything (the default), while
+podioOutput.outputCommands = ["drop *"]
+
will simply drop all collections and effectively write an empty file (apart from
+some metadata). A common pattern is to "drop *"
and then selectively adding
+keep
collections to keep, e.g. to only keep the highest level MC and reco
+information:
podioOutput.outputCommands = [
+ "drop *",
+ "keep MCParticlesSkimmed",
+ "keep PandoraPFOs",
+ "keep RecoMCTruthLink",
+]
+
k4run
It is possible to extend k4run
with custom arguments from a steering file using k4FWCore.parseArgs
.
Example:
+from k4FWCore.parseArgs import parser
+parser.add_argument("--trackingOnly", action="store_true", help="Run only track reconstruction", default=False)
+my_opts = parser.parse_known_args()[0]
+
+# later
+if my_opts.trackingOnly:
+ # only run track reconstruction
+
Behind the scenes parser is just a normal instance of pythons argparse.ArgumentParser
, please refer to its documentation for usage details. The only important thing to keep in mind is to always use parse_known_args()
instead of parse_args()
so that the normal k4run
arguments keep working.
This page describes how to run existing Marlin processors within the Gaudi
+framework. Marlin
and Gaudi
are two event processing frameworks available in
+the Key4hep software stack. The former was originally developed by the linear
+collider communities in iLCSoft, while the latter originally comes from LHCb. It
+is also the event processing framework for future developments within Key4hep.
+To enable using the existing functionality that has been developed for the
+linear collider studies and also to allow for a gradual migration the
+MarlinProcessorWrapper
has been developed. It allows to run Marlin processors
+within the Gaudi framework and it’s usage is described
+below
One of the major differences between Marlin processors and (Key4hep) Gaudi +algorithms is the event data model (EDM) that they use. While Marlin uses LCIO, +Gaudi in Key4hep uses EDM4hep. Since EDM4hep is +based on LCIO the differences are limited and it is possible to convert between +the two EDMs as necessary. We will also show how to do this +below.
+The following descriptions assume that you are somewhat familiar with how to
+configure and run Gaudi via k4run
, i.e. most of the snippets will just show
+the bare minimum of configuration, but will usually not work without
+modifications (e.g. in most cases the ApplicationMgr
as well as putting all
+the configured algorithms into the list of algorithms to run is missing
+entirely).
MarlinProcessorWrapper
Gaudi algorithmThe MarlinProcessorWrapper
is a standard Gaudi algorithm and can be used just
+like all others, i.e. in a Gaudi options file we simply have to import it via
from Gaudi.Configuration import *
+from Configurables import MarlinProcessorWrapper
+
It can then be configured just like any other algorithm by instantiating it and
+passing the necessary parameters to it. Each Marlin processor that you want to
+wrap needs its own instance. The main configuration parameters for the
+MarlinProcessorWrapper
are
ProcessorType
- a string with the Marlin processor type. The type is
+usually the class name of the Marlin processor, and corresponds to the type
+attribute in a Marlin XML configuration for a processor.
Parameters
- a dictionary of string keys and list of string values. Each
+parameter of the Marlin processor needs its own entry in this dictionary and
+all parameter values have to be strings as the parsing is done internally.
As a very brief example; The following snippet of a Marlin XML steering file
+ <processor name="StatMonitorAlg" type="StatusMonitor">
+ <parameter name="HowOften" type="int">1</parameter>
+ </processor>
+
could be converted to the following snippet of a Gaudi options file
+StatMonitorAlg = MarlinProcessorWrapper("StatMonitorAlg")
+StatMonitorAlg.ProcessorType = "StatusMonitor"
+StatMonitorAlg.Parameters = {"HowOften": ["1"]}
+
Note that wrapped Marlin processors still expect their inputs in LCIO +format! You can either read in the data in that format directly, or use +converters to convert from EDM4hep to LCIO first.
+In order to read in event data in LCIO format into the Gaudi world it is
+necessary to use the LcioEvent
Gaudi algorithm. It is configured in the same
+way as normal Gaudi algorithms, i.e. in a minimal standalone form
from Gaudi.Configurables import *
+from Configurables import LcioEvent
+
+read = LcioEvent()
+read.Files = ["inputfile1.slcio", "inputfile2.slcio"]
+
For writing LCIO events from Gaudi, simply use a MarlinProcessorWrapper
to
+wrap a LCIOOutputProcessor
, e.g.
from Configurables import MarlinProcessorWrapper
+
+Output_DST = MarlinProcessorWrapper("Output_DST")
+Output_DST.ProcessorType = "LCIOOutputProcessor"
+Output_DST.Parameters = {
+ "DropCollectionNames": [],
+ "DropCollectionTypes": ["MCParticle", "LCRelation", "SimCalorimeterHit"],
+ }
+
We provide the convertMarlinSteeringToGaudi.py
converter script to
+automatically convert Marlin steering files in XML format to Gaudi options
+python files. Usage is as simple as
convertMarlinSteeringToGaudi.py <input-steering.xml> <output-gaudi-options.py>
+
This converter script handles almost everything, but there are a few +short-comings which it cannot yet handle:
+Marlin XML steering files can have include
statements, e.g. <include ref="Tracking/TrackingDigi.xml"/>
. These cannot be resolved by the converter
+script, and it will issue a warning. The easiest way to fix this is to simply
+run Marlin -n
to resolve all these statements and then run the converter
+script again on the output file which will be named
+<inputfile-base>Parsed.xml
.
Marlin has a mechanism to resolve constants that are defined in the
+constants
section and used like ${someFancyConstant}
in the following. The
+converter script and the converted Gaudi options file handle these in general.
+However, it might be necessary to change the values of the constants inside
+the CONSTANTS
dictionary that can be found at the beginning of the created
+options file. Alternatively one can use Marlin -n
with e.g.
+--constant.someFancyConstant=<value>
to set the values in the Marlin
+steering file first and again parse the converted output.
Marlin supports conditional execution of processors via the condition
tag.
+These conditions can be configured via constant values from the constants
+section in the steering file, but in principle these can also be runtime
+values that are set, e.g. by a previously run processor. At the moment dynamic
+conditions (where the value might change on an event by event basis) are not
+supported by Gaudi. Additionally static conditions are only partially handled
+by the converter script. While it converts the necessary configuration, it
+will by default not put the converted algorithm into the algList
list of
+algorithms to run and you might have to comment / uncomment the algorithms you
+actually want to run.
If the value of the LCIOInputFiles
is empty in the input XML file, the
+converter script will put a value of "None"
into the read.Files
parameter.
+You will have to change this either in the steering file or them in via
+--LcioEvent.Files
.
Marlin is in some cases able to replace constant
s with the values stored in
+environment variables of the same name. In Gaudi these have to be retrieved
+from the environment explicitly via os.environ
.
The converters between EDM4hep and LCIO are implemented as so called
+GaudiTool
s. They can be attached to any MarlinProcessorWrapper
algorithm
+that is configured in the Gaudi options file. The tools are called
+Lcio2EDM4hepTool
and EDM4hep2LcioTool
respectively. Each wrapped processor
+can be equipped with both tools, so that it is possible to e.g. convert input
+from EDM4hep to LCIO and output from LCIO to EDM4hep again:
The (very) basic usage of the converter tools looks like the following
+Instantiate the necessary tools (and configure them as desired)
Attach the tools to a wrapped marlin processor via the Lcio2EDM4hepTool
+and/or EDM4hep2LcioTool
options
from Configurables import EDM4hep2LcioTool, Lcio2EDM4hepTool
+
+edm4hep2LcioConv = EDM4hep2LcioTool("EDM4hep2Lcio")
+lcio2edm4hepConv = Lcio2EDM4hepTool("Lcio2EDM4hep")
+
+wrappedProcAlg = MarlinProcessorWrapper("ProcessorToWrap")
+wrappedProcAlg.Lcio2EDM4hepTool = lcio2edm4hepConv
+wrappedProcAlg.EDM4hep2LcioTool = edm4hep2LcioConv
+
An arbitrary number of converter tools can be instantiated and attached to Gaudi +algorithms (taking into account that each algorithm can at most have one +converter for each direction attached). If you have multiple tools make sure to +give them meaningful names in order to avoid any confusion.
+By default each converter tool will try to convert the complete event content +that is currently available in the transient event store for the corresponding +source format. It will skip the conversion of a collection if the same +collection already exists in the other format. This check is done by collection +name. However, it is possible to control the conversion process with a +slightly higher granularity with two options that can be configured
+collNameMapping
- this is a dictionary of collection names, where a source
+collection name is mapped to a target collection name during the conversion.
+This makes it possible to rename collections on the fly. In combination with
+the convertAll
option this also allows to select the collections that should
+be converted. In that case if you want to keep the original collection name
+you can simply repeat it.
convertAll
- set this to False
if you do not want to convert all
+collections, but rather would like to select a subset to convert.
As an example, if you only want to convert the MCParticles
collection, you
+would configure the tool like this
edm4hep2LcioConv = EDM4hep2LcioTool("EDM4hep2Lcio")
+edm4hep2LcioConv.convertAll = False
+edm4hep2LcioConv.collNameMapping = {"MCParticles": "MCParticles"}
+
On the other hand if you want to convert all collections, but rename the
+MCParticle
(LCIO) input collection to the MCParticles
(EDM4hep) output
+collection in the process, you would configure the tool like so
lcio2edm4hepConv = Lcio2EDM4hepTool("Lcio2EDM4hep")
+lcio2edm4hepConv.collNameMapping = {"MCParticle": "MCParticles"}
+
EDM4hep is the common and shared Event Data Model (EDM) of the Key4hep project. +Here we will give a brief introduction to EDM4hep as well as some of the +technicalities behind it. We will also guide you towards documentation and try +to give you the knowledge to make sense of it.
+EDM4hep doxygen API reference page: edm4hep.web.cern.ch
EDM4hep github repository: github.com/key4hep/EDM4hep
podio documentation page (including API reference): key4hep.web.cern.ch/podio
podio github repository: github.com/AIDASoft/podio
We start with having a look at the EDM4hep doxygen API reference +page:
+You see a diagrammatic overview of EDM4hep with all the available data types, +broadly organized into different categories. The arrows depict two ways data +types can be related / associated with each other
+“Relations” (black arrows)
“Associations” (purple-ish arrows)
These are relations defined within the data types, and which are directly +accessible from the data types. They come in two flavors, depending on the +multiplicity of the relation
+OneToOneRelations
OneToManyRelations
Data types can relate to other instances of the same type (e.g. MCParticle
s
+usually form a hierarchy of mothers/daughters). Relations are directed, i.e. it
+is possible to go from one object to a related object, but vice versa this does
+usually not hold. For example, a ReconstructedParticle
can point to multiple
+Tracks
or Clusters
, but those do not point to a ReconstructedParticle
.
These are relations that are in a sense “external” to the data model definition. +They are currently mainly used to connect MC and RECO information, as a direct +link via a relation is not desirable as it would mix the two worlds. In contrast +to relations, associations are not directed, i.e. it is possible to access both +involved objects from the association.
+Just below the diagram is an overview table of all the types that are defined in +EDM4hep. Here they are organized into
+Components
- very simple types, that are used throughout the
Datatypes
- The data types that are defined in EDM4hep
Association
- The available associations between different data types
Clicking on any of these links will take you to the
+edm4hep.yaml
+definition file of EDM4hep, jumping directly to the definition of the respective
+datatype or component. For more information on this file check out the section
+about podio. In
+principle it is possible to have very educated guesses on how the interface of
+the classes will look like from this.
EDM4hep also brings a bit of utility functionality. You can find it in the
+edm4hep::utils
+namespace (click on
+Namespaces -> Namespace List
, then expand the edm4hep
namespace and then
+click on utils
to arrive at this link).
podio is an EDM toolkit that is used by and developed further in the Key4hep +context. The main purpose is to have an efficiently implemented, thread safe EDM +starting from a high level description. For more (gory) details have a look at +the github repository.
+Here we will describe the code generation, and its implications for EDM4hep. A
+bit further down we will describe how to read and
+write podio (root) files and the podio-dump
tool to inspect
+files without having to open them.
The podio code generator is a python script that reads in the EDM definition in +yaml format, does a few basic validation checks on the definition, and then +generates all the necessary code via the Jinja2 template engine.
+ +The generated code should (among other things)
+be efficient,
offer an easy to use interface,
offer performant I/O.
Having automated code generation has a few advantages:
+Freeing the user from the repetitive task of implementing all the types +themselves
Freeing the user from having to deal with all the details of how to do things +efficiently
Making it very easy to roll out improved implementations (or bug fixes) via +simply regenerating the code
To achieve the goals stated above podio favors composition over inheritance and +uses plain-old-data (POD) types wherever possible. To achieve this podio +employs a layered design, which makes it possible to have an efficient memory +layout and performant I/O implementation, while still offering an easy to use +interface
+ +The User Layer is the top most layer and it offers the full +functionality and is the only layer with which users interact directly. +It consists mainly of the collections and lightweight handle classes, i.e.
+XYZCollection
XYZ
MutableXYZ
The Object Layer consists of the XYZObj
classes, that take care of all
+resource management and which also enable the relations between different
+objects.
The POD Layer at the very bottom is where all the actual data lives in
+simple XYZData
POD structs. These are the things that are actually stored
+in, e.g. root files that are written by podio.
The generated c++ code offers so called value semantics. The exact details of +what this actually means are not very important, the main point is that you +can treat all objects as values and you don’t have to worry about inefficient +copies or managing resources:
+auto recos = edm4hep::ReconstructedParticleCollection();
+
+// ... fill, e.g. via
+auto p = recos.create();
+// or via
+auto p2 = edm4hep::ReconstructedParticle();
+recos.push_back(p2);
+
+// Loop over a collection
+for (auto reco : recos) {
+ auto vtx = reco.getStartVertex();
+ // do something with the vertex
+
+ // loop over related tracks
+ for (auto track : reco.getTracks()) {
+ // do something with this track
+ }
+}
+
This looks very similar to the equivalent python code (if you squint a bit, and ignore the auto
s, ;
and {}
;) )
recos = edm4hep.ReconstructedParticleCollection()
+
+# ... fill, e.g. via
+p = recos.create()
+# or via
+p2 = edm4hep.ReconstructedParticle()
+recos.push_back(p2)
+
+# Loop over a collection
+for reco in recos:
+ vtx = reco.getStartVertex()
+ # do something with the vertex
+
+ # loop over related tracks
+ for track in reco.getTracks():
+ # do something with the tracks
+
The python interface is functionally equivalent to the one c++ interface, since
+that is implemented via PyROOT. There are some additions that make the python
+interface more pythonic, e.g. len(recos)
is equivalent to recos.size()
.
+Nevertheless, the doxygen reference is valid for both interfaces.
Since all code is generated, it is usually pretty straight forward to guess how
+the interface will look like just from looking at the definition in the yaml
+file. For EDM4hep the general rule is to get a Member
variable, a
+OneToOneRelation
, a OneToManyRelation
or a VectorMember
is to simply
+stick a get
in front of the name in the yaml file and to capitalize the first
+letter., e.g.
Members:
+ - edm4hep::Vector3f momentum // the momentum in [GeV]
+
will turn into something like
+const edm4hep::Vector3f& getMomentum() const;
+
Similar, but in slightly more nuanced rules apply for the methods that are
+generated for setting a value. For Member
variables and OneToOneRelation
s
+the general rule is to stick a set
in front of the name in the yaml file and
+to capitalize the first letter, e.g. (continuing from above)
void setMomentum(edm4hep::Vector3f value);
+
For the OneToManyRelation
s and VectorMember
s the rule is to stick a
+addTo
in front of the name in the yaml file and to capitalize the first
+letter, e.g.
OneToManyRelation:
+ - MCParticle daughters // the daughters of this particle
+
will be generated to
+void addToDaughters(MCParticle daughter);
+
XYZ
and a MutableXYX
?The underlying technical reasons are rather complex, dive quite deepish into c++
+nuances, and definitely far beyond the scope of this tutorial. In short: We need
+two different handle classes in order to control whether users are allowed to
+modify things or not. As one of the main goals of podio generated EDMs is to be
+thread safe the default generated class for each data type allows only for
+immutable read access, i.e. it provides only the get
methods. Only the
+Mutable
classes actually have the set
methods, and can hence be used to
+actually modify objects. The most important implication of this is the
+following: Everything that you read from file, or that you get from the Gaudi
+TES (in gaudi, or that
+you get from a Frame
) is immutable. I.e. there
+is no way for you to change or update the values that you read. The only way to
+“update” values (or collections) is to actually copy the contents and then store
+the updated values back. Independent copies of objects can be obtained with the
+clone
method.
The Mutable
objects implicitly convert to an instance of a default class.
+Hence, always use the default classes when specifying function interfaces
+(obviously this only works if you only need read access in the function. There
+is no implicit conversion from the default, immutable objects to the Mutable
+objects!
As an example
+void printE(edm4hep::MCParticle particle) {
+ std::cout << particle.getEnergy() << '\n';
+}
+
+void printEMutable(edm4hep::MutableMCParticle particle) {
+ std::cout << particle.getEnergy() << '\n';
+}
+
+int main() {
+ auto mutP = edm4hep::MutableMCParticle();
+ p.setEnergy(3.14);
+
+ printE(mutP); // Works due to implicit conversion
+ printEMutable(mutP); // Obviously also works
+
+ // Now we create an immutable object
+ auto P = edm4hep::MCParticle();
+
+ printE(P); // Obviously works
+ printEMutable(P); // BREAKS: No conversion from default to Mutable
+
+ return 0;
+}
+
Similar to LCIO, podio generated EDMs offer a subset collection functionality. +This allows to create collections of objects, that are actually part of another +collection, e.g. to simply collect all the muons that are present in a larger +collection of reconstructed particles:
+ +To create a subset collection, simply do
+auto muons = edm4hep::ReconstructedParticleCollection();
+muons.setSubsetCollection();
+
+// You can now add objects that are part
+// of another collection to this one via push_back
+muons.push_back(recos[0]);
+
Reading a subset collection works exactly the same as reading a normal +collection. This is handled in a transparent way, such that you usually don’t +even realize that you are operating on a subset collection.
+podio::Frame
containerThe podio::Frame
is a generalized event. It is a container that aggregates
+all relevant data (and some meta data). It also defines an implicit interval of
+validity (but that is less relevant for this tutorial). It provides a thread
+safe interface for data access
Immutable read access only for collections that are stored inside the a
+Frame
All data that is inside a Frame
is owned by it, and this is also reflected
+in its interface.
Here we will just briefly introduce the main functionality, for more details see +the documentation in +podio.
+Frame
Assuming that event
is a podio::Frame
in the following code examples,
+getting a collection can be done via (c++)
auto& mcParticles = event.get<edm4hep::MCParticleCollection>("MCParticles");
+
or (python)
+mcParticles = event.get("MCParticles")
+
This retrieves the collection that is stored under the name MCParticles
with
+type edm4hep::MCParticleCollection
. If no such collection exists, it will
+simply return an empty collection of the desired type. As you can see, the type
+is automatically inferred in python. Note that get
returns a const&, so it
+is required to actually put the &
behind auto
in c++, otherwise there will
+be a compilation error complaining about a copy-constructor being marked
+delete
.
Frame
When putting a collection into a Frame
you give up ownership of this
+collection. To signal this to the users, it is necessary to move the
+collection into a Frame
. Again assuming event
is a podio::Frame
in the
+following examples, this looks like this
auto recos = edm4hep::ReconstructedParticleCollection();
+event.put(std::move(recos), "ReconstructedParticles");
+
Note the requirement to explicitly use std::move
in this case. At this point
+recos
is moved into the event
, and you are left with an object in a
+valid but unspecified state that you
+should under normal circumstances no longer use after this point. (Technically
+we do enough that you still can use this, but don’t expect the results to match
+your expectations).
EDM4hep files are read with tools provided by podio. As podio supports multiple
+different backends there are several, low level readers that support all the
+necessary functionality. You can obviously use these readers directly, but we
+recommend to use the Reader
class and the makeReader
function that will
+dispatch to the correct low level reader automatically.
#include <podio/Reader.h>
+
+#include <edm4hep/MCParticleCollection.h>
+
+int main() {
+ auto reader = podio::makeReader("some_file_containing_edm4hep.data.root");
+
+ // Loop over all events
+ for (size_t i = 0; i < reader.getEvents(); ++i) {
+ auto event = reader.readNextEvent());
+ auto& mcParticles = event.get<edm4hep::MCParticleCollection>("MCParticles");
+
+ // do more stuff with this event
+ }
+
+ return 0;
+}
+
ROOTReader
- The default reader for TTree based files
ROOTLegacyReader
- The reader for an old podio format based on TTrees
RNTupleReader
- A reader for RNTuple based files
SIOReader
- The reader for reading files using the SIO backend
SIOLegacyReader
- The reader for the SIO backend with an old podio format
The Legacy
readers are stated here mainly for completeness, in case you need
+to read a rather old file that still used the EventStore
which has been
+removed from podio some time ago. See
+here for more information on how to
+figure out whether the file you are interested in is a legacy file or not.
+As podio is a rather low level tool, also the interface of these readers feel
+somewhat low level. This is mostly visible in the fact, that you have to provide
+a category
(name) when getting the number of entries, or when reading the next
+entry. This is because in principle podio can handle multiple different
+categories of Frames in one file. For the purpose of this tutorial and also
+for the majority of use cases, simply use "events"
as category name. Readers
+in podio do not return a podio::Frame
directly, rather they just return some
+frame data from which a podio::Frame
can be constructed. Putting all of
+these things together, a simple event loop looks like this in c++:
#include "podio/ROOTReader.h"
+#include "podio/Frame.h"
+
+#include "edm4hep/MCParticleCollection.h"
+
+int main() {
+ auto reader = podio::ROOTReader();
+ reader.openFile("some_file_containing_edm4hep_data.root");
+
+ // Loop over all events
+ for (size_t i = 0; i < reader.getEntries("events"); ++i) {
+ auto event = podio::Frame(reader.readNextEntry("events"));
+ auto& mcParticles = event.get<edm4hep::MCParticleCollection>("MCParticles");
+
+ // do more stuff with this event
+ }
+
+ return 0;
+}
+
The equivalent python code looks like this
+from podio import root_io
+
+reader = root_io.Reader("some_file_containing_edm4hep_data.root")
+# if you want to read legacy files use root_io.LegacyReader
+
+for event in reader.get("events"):
+ mcParticles = event.get("MCParticles")
+ # do more stuff with this event
+
podio generated EDMs, i.e. also EDM4hep, use ROOT as their default I/O backend. +Since everything is based on PODs, the produced root files are pretty straight +forward to read and interpret (with some caveats). They are already almost flat +ntuples.
+ + +Use podio-dump
and it will tell you
$podio-dump /home/workarea/data/rv02-02.sv02-02.mILD_l5_o1_v02.E250-SetA.I402003.Pe2e2h.eL.pR.n000.d_dstm_15089_0_edm4hep.root
+input file: /home/workarea/data/rv02-02.sv02-02.mILD_l5_o1_v02.E250-SetA.I402003.Pe2e2h.eL.pR.n000.d_dstm_15089_0_edm4hep.root
+
+Frame categories in this file (this is a legacy file!):
+[...]
+
Peek inside the root file and look at the contents
+
podio-dump
The podio-dump
utility allows to inspect EDM4hep files from the command line.
+The synopsis looks like this
$podio-dump --help
+usage: podio-dump [-h] [-c CATEGORY] [-e ENTRIES] [-d] [--dump-edm DUMP_EDM] [--version] inputfile
+
+Dump contents of a podio file to stdout
+
+positional arguments:
+ inputfile Name of the file to dump content from
+
+options:
+ -h, --help show this help message and exit
+ -c CATEGORY, --category CATEGORY
+ Which Frame category to dump
+ -e ENTRIES, --entries ENTRIES
+ Which entries to print. A single number, comma separated list of numbers or "first:last" for an inclusive range of entries. Defaults to the first entry.
+ -d, --detailed Dump the full contents not just the collection info
+ --dump-edm DUMP_EDM Dump the specified EDM definition from the file in yaml format
+ --version show program's version number and exit
+
By default it prints how many events are present in the file and also a summary
+of the contents of the first event. This overview consists of the names, data
+types and number of elements of the collections that are stored in this event.
+Using the --detailed
flag, podio-dump
will print the complete contents of
+all collections in ASCII format. This can be quite a bit of information. Using
+the --entries
flag it is possible to choose which events to look at. The
+--categories
flag is an advanced feature and not necessary for this tutorial.
podio-dump
will also tell you whether the file that is passed to it is a
+legacy file in which case you will need the ROOTLegacyReader
or the
+SIOLegacyReader
to read it.
k4run
k4run
", "Wrapping Marlin processors in Gaudi", "EDM4hep - The common event data model", "Key4hep", "Getting started with Key4hep software", "Building Key4hep: For Librarians", "Spack Usage and Further Technical Topics", "Spack Buildcaches", "Nightly Builds with Spack", "Setting up Spack", "Talks and Presentations", "Key4hep Tutorials", "Running an Event Display with EDM4hep or LCIO input", "Using the Key4hep-Stack for CLIC Simulation and Reconstruction", "How to run multithreading with k4MarlinWrapper (Gaudi)", "Running Delphes fast simulation with EDM4hep output", "Running ILD simulation and reconstruction"], "terms": {"As": [1, 10, 16, 17], "maintain": 1, "thi": [1, 2, 5, 6, 7, 9, 10, 11, 12, 13, 14, 16, 17, 20, 21, 22, 24, 26, 27, 28, 29, 30, 31], "project": [1, 2, 10, 11, 17, 22], "we": [1, 2, 5, 7, 9, 10, 11, 13, 14, 16, 17, 19, 21, 25, 26, 27, 28, 30, 31], "pledg": 1, "respect": [1, 16, 17, 31], "all": [1, 2, 5, 6, 7, 8, 11, 13, 14, 16, 21, 22, 26, 27, 28, 29, 30, 31], "peopl": [1, 6, 7], "who": 1, "contribut": [1, 8, 18, 25], "through": [1, 7, 11, 13, 26], "report": [1, 2], "issu": [1, 2, 7, 14, 16, 21, 26, 31], "post": [1, 17], "featur": [1, 7, 10, 17, 19, 31], "request": [1, 2, 6, 8], "updat": [1, 6, 17, 25, 28], "document": [1, 10, 11, 15, 18, 20, 22], "submit": [1, 2], "pull": [1, 2, 8, 31], "patch": [1, 10, 18, 21], "other": [1, 3, 6, 8, 11, 14, 16, 17, 18, 21, 22, 24, 26, 28, 31], "activ": [1, 10, 24], "ar": [1, 2, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 16, 19, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31], "commit": [1, 8, 10, 22, 23], "make": [1, 2, 5, 6, 7, 10, 11, 13, 14, 16, 17, 19, 24, 27, 29, 31], "particip": 1, "harass": 1, "free": [1, 2, 6, 7, 17], "experi": [1, 8, 10, 18, 25], "everyon": 1, "regardless": [1, 21], "level": [1, 6, 11, 14, 29, 31], "gender": 1, "ident": 1, "express": [1, 6], "sexual": 1, "orient": 1, "disabl": [1, 10], "person": 1, "appear": [1, 5, 13], "bodi": 1, "size": [1, 17], "race": 1, "ethnic": 1, "ag": 1, "religion": 1, "exampl": [1, 3, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 21, 24, 26, 27, 28, 30, 31], "unaccept": 1, "behaviour": 1, "includ": [1, 5, 6, 9, 10, 11, 13, 14, 16, 17, 21, 23, 28, 31], "us": [1, 2, 7, 8, 9, 13, 14, 15, 17, 18, 20, 22, 23, 26, 29, 30], "languag": 1, "imageri": 1, "derogatori": 1, "comment": [1, 2, 8, 16, 28, 31], "attack": 1, "troll": 1, "public": 1, "privat": 1, "insult": 1, "unprofession": 1, "have": [1, 2, 6, 8, 9, 10, 11, 13, 14, 16, 17, 19, 21, 26, 27, 28, 29, 30, 31], "right": [1, 5, 21, 24], "respons": [1, 13], "remov": [1, 6, 8, 11, 17, 28], "edit": [1, 5, 10, 31], "reject": 1, "wiki": 1, "align": 1, "do": [1, 5, 6, 8, 9, 10, 11, 13, 14, 16, 21, 27, 28, 29, 30, 31], "follow": [1, 5, 6, 7, 10, 14, 16, 17, 20, 21, 22, 24, 26, 27, 28, 29, 30, 31], "mai": [1, 2, 5, 6, 7, 10, 11, 14, 28, 29], "from": [1, 2, 5, 6, 7, 10, 11, 12, 14, 15, 16, 18, 19, 21, 22, 24, 26, 27, 28, 29, 30], "team": [1, 2, 6], "instanc": [1, 15, 16, 17, 18, 20], "abus": 1, "otherwis": [1, 3, 10, 11, 13, 14, 17, 21], "open": [1, 2, 7, 17, 26], "an": [1, 2, 5, 6, 8, 11, 13, 14, 16, 17, 18, 21, 22, 23, 24, 26, 28, 29, 30, 31], "contact": [1, 6], "one": [1, 5, 7, 9, 10, 11, 13, 16, 17, 21, 24, 27, 28, 30, 31], "more": [1, 2, 6, 7, 8, 9, 11, 17, 20, 21, 22, 27, 31], "i": [1, 2, 5, 8, 9, 10, 11, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 26, 27, 28, 29, 30, 31], "adapt": [1, 26, 28, 29], "coven": 1, "version": [1, 5, 7, 8, 9, 11, 17, 19, 21, 22, 23, 24], "1": [1, 4, 6, 7, 10, 11, 16, 21, 24, 28, 29, 31], "0": [1, 3, 10, 15, 17, 21, 24], "avail": [1, 3, 6, 10, 11, 13, 14, 16, 19, 21, 24, 26, 29, 30, 31], "http": [1, 6, 8, 10, 11, 21, 22, 24, 25, 27, 28, 30, 31], "org": [1, 5, 6, 10, 19, 20, 21, 23, 24, 25, 27, 28, 30, 31], "key4hep": [2, 7, 9, 11, 14, 16, 17, 21, 22, 23, 25, 27, 31], "sourc": [2, 5, 6, 7, 9, 10, 16, 19, 20, 23, 24, 27, 28, 30, 31], "welcom": 2, "kind": [2, 11], "new": [2, 5, 6, 7, 10, 19, 24, 26, 28, 31], "lesson": 2, "fix": [2, 6, 7, 16, 17], "exist": [2, 13, 16, 17, 22, 24, 30, 31], "materi": [2, 12], "bug": [2, 7, 17], "review": 2, "propos": 2, "chang": [2, 8, 9, 10, 11, 14, 16, 17, 18, 19, 21, 23, 24, 27, 28, 31], "By": [2, 11, 14, 16, 17, 24], "you": [2, 5, 6, 7, 8, 10, 11, 14, 16, 17, 21, 26, 27, 28, 29, 30, 31], "agre": 2, "redistribut": 2, "your": [2, 8, 10, 14, 17, 18, 27, 28, 29, 30, 31], "work": [2, 5, 6, 7, 9, 10, 11, 14, 15, 16, 17, 21, 25, 26, 27, 31], "under": [2, 3, 5, 10, 13, 17, 21, 22, 24, 29], "licens": 2, "also": [2, 6, 7, 9, 10, 11, 13, 14, 16, 17, 19, 21, 22, 23, 24, 26, 27, 28, 30, 31], "abid": 2, "our": [2, 9, 11], "contributor": [2, 18, 21], "code": [2, 6, 8, 10, 11, 18, 23], "conduct": [2, 18], "fork": [2, 7, 24], "model": [2, 12, 14, 16, 18, 27, 31], "manag": [2, 17, 20, 29], "inform": [2, 5, 7, 10, 13, 14, 17, 19, 21, 22, 26], "about": [2, 10, 11, 17, 21], "repositori": [2, 5, 8, 11, 17, 23, 24, 26, 27, 28], "should": [2, 5, 6, 7, 10, 14, 16, 17, 24, 27, 28, 30, 31], "branch": [2, 7, 23], "against": [2, 22], "main": [2, 5, 6, 7, 9, 10, 11, 13, 16, 17, 23, 27, 29, 31], "some": [2, 5, 6, 7, 8, 9, 10, 11, 13, 14, 16, 19, 20, 21, 22, 23, 24, 27, 28, 29, 30, 31], "still": [2, 10, 13, 14, 16, 17, 21, 24, 31], "master": [2, 5, 7, 10, 22, 24], "futur": [2, 11, 16, 25], "If": [2, 5, 7, 10, 11, 13, 16, 17, 26, 27, 29, 31], "re": [2, 7, 10, 11, 21, 22, 24], "look": [2, 6, 7, 10, 11, 13, 14, 16, 17, 27, 31], "thing": [2, 5, 10, 12, 15, 18, 21, 31], "feel": [2, 6, 7, 17, 26], "touch": [2, 7], "dash": 2, "sw": [2, 5, 6, 7, 10, 19, 20, 21, 23, 24, 27, 28, 30, 31], "cern": [2, 7, 11, 17, 21, 22, 24, 25], "dot": 2, "ch": [2, 17, 21, 22, 24, 25], "can": [2, 5, 6, 8, 9, 10, 11, 13, 14, 16, 17, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31], "list": [2, 6, 7, 11, 13, 14, 16, 17, 24, 25, 26, 27, 28, 29, 31], "equal": 2, "except": 3, "where": [3, 5, 7, 9, 10, 11, 16, 17, 24, 25, 28, 31], "note": [3, 6, 7, 10, 16, 17, 21, 24, 28, 31], "program": [3, 17, 20, 25, 27], "provid": [3, 6, 7, 10, 11, 13, 14, 16, 17, 21, 24, 27, 30, 31], "carpentri": 3, "made": [3, 6, 10, 14, 21], "osi": 3, "approv": 3, "apach": 3, "2": [3, 4, 5, 7, 10, 21, 24], "3": [4, 7, 10, 17, 21, 25, 28, 29, 31], "4": [4, 10, 11, 21, 29], "5": [4, 21, 25], "6": [4, 10, 21], "7": [4, 21], "A": [5, 10, 13, 14, 17, 20, 21, 22, 25, 29], "common": [5, 12, 14, 18, 24, 25], "problem": [5, 21], "when": [5, 6, 8, 9, 10, 11, 17, 21, 27, 28, 30], "need": [5, 6, 8, 9, 10, 11, 14, 16, 18, 20, 21, 22, 24, 27, 28, 29, 30, 31], "multipl": [5, 8, 11, 16, 17, 18, 29], "top": [5, 6, 10, 17, 31], "stack": [5, 9, 10, 11, 12, 16, 18, 20, 21, 22, 23, 24, 25, 26, 30], "sever": [5, 7, 11, 17, 21, 26, 31], "One": [5, 10, 11, 16], "wai": [5, 7, 9, 10, 11, 13, 16, 17, 21, 24, 26, 28, 29, 30, 31], "spack": [5, 6, 8, 18, 20, 25, 28, 30], "experiment": 5, "first": [5, 6, 8, 10, 11, 13, 16, 17, 18, 27, 28, 29, 31], "releas": [5, 9, 10, 18, 19, 20, 22, 23, 27, 28, 30], "nightli": [5, 9, 10, 19, 27], "usual": [5, 6, 10, 16, 17, 21], "Then": [5, 10, 11, 28], "run": [5, 7, 8, 10, 11, 12, 15, 16, 18, 23, 24, 26, 28], "command": [5, 6, 7, 10, 14, 17, 21, 22, 24, 27, 28, 31], "cvmf": [5, 6, 9, 10, 11, 18, 20, 24, 27, 28, 30, 31], "hsf": [5, 6, 10, 19, 20, 21, 23, 24, 25, 27, 28, 30, 31], "setup": [5, 6, 8, 18, 19, 20, 21, 23, 24, 26, 27, 28, 29], "py": [5, 6, 10, 11, 16, 26, 27, 28], "pkg1": 5, "pkg2": 5, "clone": [5, 6, 8, 10, 11, 17, 24, 27, 28, 31], "empti": [5, 11, 13, 14, 16, 17], "On": [5, 16], "check": [5, 6, 7, 10, 11, 16, 17, 29, 31], "folder": [5, 6, 10, 28, 31], "symbol": 5, "link": [5, 6, 10, 11, 13, 17, 24], "current": [5, 7, 10, 14, 16, 17, 19, 21, 24], "directori": [5, 6, 10, 21, 22, 24, 27, 31], "contain": [5, 6, 10, 11, 12, 13, 18, 21, 26, 27, 28, 30, 31], "cmakelist": [5, 6], "txt": [5, 6, 10, 13], "want": [5, 6, 7, 10, 11, 14, 16, 17, 25, 27, 29, 31], "local": [5, 8, 9, 21, 24], "don": [5, 7, 11, 17, 19, 31], "t": [5, 8, 10, 11, 17, 19, 21, 31], "after": [5, 9, 10, 11, 13, 17, 19, 29, 31], "file": [5, 6, 7, 8, 10, 12, 13, 15, 18, 21, 22, 24, 26, 28, 29, 30], "manual": [5, 9, 10], "recogn": 5, "organ": [5, 17], "than": [5, 8, 10, 11, 12, 13, 19, 27], "predefin": 5, "ones": [5, 9, 10, 17, 21, 24, 28, 30], "The": [5, 6, 7, 8, 10, 12, 13, 15, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29, 30, 31], "ll": [5, 7, 11], "most": [5, 6, 7, 10, 11, 13, 14, 16, 17, 19, 27], "like": [5, 6, 7, 10, 11, 13, 14, 16, 17, 21, 26, 27, 31], "line": [5, 6, 7, 10, 11, 13, 14, 17, 21, 28, 31], "set": [5, 8, 9, 11, 16, 17, 18, 20, 23, 26, 29], "pkg": 5, "edm4hep": [5, 10, 11, 12, 16, 18, 24, 26, 29], "k4fwcore": [5, 11, 14, 15], "built": [5, 9, 10, 11, 22], "order": [5, 6, 10, 11, 16, 17, 21, 22, 23, 24, 27, 30, 31], "individu": [5, 7, 13, 21, 23], "fetchcontent_declar": 5, "entri": [5, 13, 16, 17, 31], "each": [5, 7, 10, 11, 13, 14, 16, 17, 29], "happi": [5, 7, 10, 26], "": [5, 7, 9, 10, 11, 13, 16, 17, 18, 21, 28, 29, 30, 31], "import": [5, 6, 10, 11, 14, 15, 16, 18, 19, 21, 27, 28, 29, 31], "environ": [5, 8, 9, 11, 16, 18, 19, 20, 26, 28, 29, 31], "variabl": [5, 6, 9, 11, 16, 17, 31], "mkdir": [5, 6, 11, 31], "instal": [5, 7, 8, 9, 11, 18, 20, 22, 23, 27, 28, 30], "cd": [5, 6, 7, 10, 11, 28, 31], "export": [5, 6, 9], "path": [5, 6, 9, 10, 14, 21, 24, 28], "pwd": [5, 6, 24], "bin": [5, 6, 9], "ld_library_path": [5, 6, 9], "lib": [5, 6, 9, 21], "lib64": [5, 6, 9], "root_include_path": [5, 6, 9], "pythonpath": [5, 6, 9], "python": [5, 6, 9, 10, 11, 15, 16, 17, 21, 28], "cmake_prefix_path": [5, 6], "dcmake_install_prefix": [5, 6, 9, 11], "j": [5, 6, 11], "n": [5, 16, 17, 28, 29, 31], "same": [5, 7, 10, 11, 13, 16, 17, 21, 22, 24, 30, 31], "time": [5, 8, 9, 11, 17, 18, 19, 26], "so": [5, 6, 7, 9, 10, 11, 15, 16, 19, 20, 21, 22, 24, 25, 27, 31], "take": [5, 7, 10, 11, 13, 14, 16, 17, 21, 22, 27, 29, 31], "creat": [5, 6, 7, 10, 11, 13, 16, 17, 18, 20, 21, 22, 24, 26, 28, 29, 30], "allow": [5, 7, 10, 11, 14, 16, 17, 21, 31], "u": [5, 11, 22, 26], "ctest": [5, 8, 18, 29], "case": [5, 6, 7, 10, 11, 13, 14, 16, 17, 21, 27, 28, 30, 31], "done": [5, 6, 7, 10, 13, 16, 17, 21, 26, 27, 31], "Not": [5, 29], "everyth": [5, 10, 11, 14, 16, 17, 27], "ha": [5, 6, 9, 10, 11, 13, 16, 17, 21, 24, 27, 31], "won": [5, 11], "mani": [5, 7, 9, 10, 21, 29], "recent": [5, 10], "enabl": [5, 16, 17, 28], "older": [5, 19], "probabl": [5, 10, 27], "togeth": [5, 10, 11, 17, 24], "successfulli": [5, 10], "ani": [5, 6, 7, 8, 9, 10, 11, 16, 17, 19, 21, 26, 27, 31], "combin": [5, 11, 16, 29], "them": [5, 6, 10, 11, 13, 16, 21, 24, 26, 27], "podio": [5, 10, 12, 13, 14, 18, 31], "lcio": [5, 10, 12, 17, 18, 21, 26, 29, 31], "ilcutil": 5, "lccd": 5, "gear": 5, "marlin": [5, 10, 12, 18, 26, 27, 29, 31], "k4edm4hep2lcioconv": [5, 13], "k4marlinwrapp": [5, 18, 26, 27, 31], "two": [5, 10, 11, 13, 16, 17, 19, 28, 29], "option": [5, 6, 11, 13, 14, 17, 21, 24, 26, 27, 29], "correspond": [5, 7, 10, 11, 13, 16, 31], "git_tag": 5, "whatev": [5, 10, 11, 31], "checkout": [5, 10], "go": [5, 10, 11, 14, 17, 25, 27, 30], "which": [5, 6, 7, 9, 10, 11, 12, 13, 14, 16, 18, 23, 24, 26, 27, 28, 29, 30, 31], "found": [5, 6, 7, 10, 11, 16, 25, 27, 28], "_dep": 5, "src": [5, 6, 11], "tool": [6, 7, 11, 16, 17, 20, 22, 23, 25, 31], "becom": [6, 10, 14], "de": [6, 13], "facto": 6, "standard": [6, 16, 30, 31], "outsid": 6, "hep": [6, 7, 21, 25, 30], "In": [6, 7, 10, 11, 13, 16, 17, 19, 20, 21, 22, 23, 24, 27, 28, 29, 30, 31], "ilc": [6, 13, 18], "clic": [6, 18, 26, 27, 29], "commun": [6, 16], "lhcb": [6, 11, 16], "collabor": [6, 25], "For": [6, 7, 8, 9, 11, 13, 16, 17, 18, 21, 22, 23, 24, 30, 31], "cm": 6, "equival": [6, 17], "scram": 6, "step": [6, 7, 10, 13, 24, 27, 28, 31], "ad": [6, 7, 8, 11, 12, 14, 18, 22, 24, 31], "depend": [6, 8, 9, 11, 13, 17, 18, 20, 24, 27, 28, 31], "bash": [6, 10, 21], "unsur": 6, "best": [6, 10, 21, 27], "default": [6, 11, 14, 15, 16, 17, 21, 24, 27, 29, 30, 31], "init": [6, 29], "script": [6, 16, 17, 19, 20, 21, 23, 24, 31], "centos7": [6, 19, 20, 23, 24], "sh": [6, 10, 19, 20, 23, 24, 27, 28, 30, 31], "mix": [6, 17], "anoth": [6, 8, 11, 17, 21, 28], "intend": [6, 10, 11, 17, 19, 22], "mail": [6, 7], "channel": [6, 10], "develop": [6, 11, 16, 17, 18, 19, 21, 23, 24, 25, 31], "fine": 6, "grain": 6, "control": [6, 16, 17], "over": [6, 11, 17, 21, 22, 27, 29], "rerun": 6, "dcmake_build_typ": 6, "debug": [6, 8, 18, 21, 24, 29], "ccmake": 6, "compil": [6, 7, 9, 10, 11, 17, 20, 22, 29], "cpu": 6, "getconf": 6, "_nprocessors_onln": 6, "content": [6, 10, 13, 14, 16, 17, 30], "just": [6, 10, 11, 14, 15, 16, 17, 20, 21, 24, 31], "few": [6, 7, 10, 11, 12, 13, 16, 17, 19, 21, 24, 27, 28, 31], "assum": [6, 10, 13, 14, 16, 17, 24, 27, 28, 30, 31], "installarea": 6, "execut": [6, 13, 16, 18, 26, 27], "librari": [6, 12, 18, 21], "plugin": 6, "system": [6, 24], "gaudi": [6, 8, 12, 17, 18, 26, 27], "dd4hep": [6, 10, 26, 27], "root": [6, 10, 11, 13, 14, 18, 21, 27, 28, 30, 31], "dictionari": [6, 10, 16], "packagenam": 6, "share": [6, 10, 17, 21, 24], "distribut": [6, 19, 21, 27], "data": [6, 11, 12, 14, 16, 18, 29, 31], "special": 6, "name": [6, 7, 10, 11, 13, 14, 16, 17, 27, 28, 30, 31], "cap": 6, "e": [6, 7, 10, 13, 14, 16, 17, 21, 27, 30, 31], "g": [6, 7, 10, 13, 14, 16, 17, 21, 27, 30], "k4simdelph": [6, 7, 10, 30], "colin": 6, "simpl": [6, 10, 11, 16, 17, 27], "thei": [6, 7, 10, 11, 12, 13, 16, 17, 19, 22, 24, 26, 30], "help": [6, 8, 11, 15, 17, 18, 21, 30], "understand": [6, 17], "basic": [6, 13, 16, 24, 27], "get": [6, 8, 10, 11, 13, 18, 27, 28, 30, 31], "git": [6, 8, 10, 11, 18, 21, 24, 27, 28, 31], "github": [6, 8, 10, 11, 17, 18, 21, 24, 27, 28, 31], "com": [6, 7, 10, 11, 17, 21, 24, 27, 28, 30, 31], "cbernet": 6, "instruct": [6, 7, 10, 18, 19, 24, 30, 31], "readm": [6, 11], "md": [6, 8, 11], "awar": [6, 7, 14], "wildcard": [6, 14], "add": [6, 7, 10, 11, 17, 21, 22, 24, 26, 27, 28, 31], "implement": [6, 10, 11, 13, 16, 17], "subfold": 6, "cpp": [6, 11], "explicitli": [6, 10, 16, 17, 28, 31], "To": [6, 7, 10, 11, 14, 16, 17, 21, 27, 28, 29, 30, 31], "fastest": 6, "properti": [6, 11, 29], "algorithm": [6, 8, 14, 18, 28, 29, 31], "onli": [6, 7, 10, 11, 15, 16, 17, 18, 21, 22, 24, 27, 29, 31], "particular": [6, 11, 30, 31], "framework": [6, 11, 14, 16, 18, 26, 31], "compon": [6, 11, 17, 29], "consist": [6, 13, 14, 17, 21], "header": [6, 13], "dynam": [6, 16], "xml": [6, 10, 18, 27, 28, 31], "describ": [6, 7, 10, 11, 14, 16, 17, 30], "offer": [6, 17, 30], "possibl": [6, 9, 10, 11, 13, 14, 15, 16, 17, 21, 22, 27, 30, 31], "via": [6, 7, 10, 14, 16, 17, 21, 27, 28, 30, 31], "xenv": 6, "simpli": [6, 10, 11, 13, 14, 16, 17, 24, 27, 31], "prefix": [6, 10, 21], "fccsw": [6, 7], "directli": [6, 10, 13, 16, 17, 27, 31], "key4run": 6, "pythia": [6, 7, 30], "sometim": [6, 10, 14, 24], "conveni": [6, 13, 31], "binari": [6, 22], "without": [6, 9, 10, 16, 17, 19, 21, 22], "differ": [6, 7, 10, 11, 16, 17, 18, 21, 22, 27, 30, 31], "bit": [6, 17, 31], "mostli": [6, 12, 17, 24], "pre": [6, 24], "fccrun": 6, "pick": [6, 9, 10, 21], "integr": [6, 7, 30], "test": [6, 7, 10, 11, 19, 23, 27, 28, 29], "add_test": 6, "see": [6, 7, 10, 11, 13, 17, 21, 24, 27, 30, 31], "fcc": [6, 7, 18, 25, 30], "k4gen": 6, "blob": [6, 11, 24], "forward": [6, 10, 13, 17, 31], "argument": [6, 10, 11, 12, 13, 17, 18, 21, 27, 28, 30, 31], "trace": 6, "cmakeflag": 6, "callout": [6, 7, 22], "flag": [6, 13, 17, 21, 31], "instead": [6, 7, 9, 10, 15, 21, 28], "verbos": [6, 21, 29], "endcallout": [6, 7, 22], "page": [7, 8, 10, 12, 14, 16, 20, 21, 26], "user": [7, 11, 12, 13, 17, 18, 20, 21], "start": [7, 8, 10, 11, 17, 18, 27, 28, 30, 31], "softwar": [7, 8, 10, 11, 12, 16, 18, 20, 21, 22, 24, 25, 26, 30, 31], "access": [7, 13, 17, 22, 28, 30], "introduct": [7, 17, 27, 31], "tutori": [7, 10, 11, 12, 17, 18, 31], "atlassian": 7, "interact": [7, 17], "book": 7, "pleas": [7, 15, 26], "refer": [7, 11, 12, 15, 22, 28], "especi": [7, 10, 17], "easier": [7, 17], "replac": [7, 16, 28, 31], "abl": [7, 10, 11, 13, 16, 31], "lxplu": [7, 20], "later": [7, 8, 9, 15, 28], "section": [7, 10, 16, 17], "It": [7, 9, 10, 11, 13, 14, 15, 16, 17, 21, 22, 23, 24, 27, 30, 31], "shell": [7, 10], "tab": 7, "complet": [7, 11, 14, 16, 17, 23, 27, 30, 31], "show": [7, 14, 16, 17, 21, 27, 31], "prompt": 7, "pend": 7, "etc": [7, 11, 24, 27], "least": [7, 13, 30], "offici": 7, "mean": [7, 10, 11, 17, 27], "area": [7, 10, 21, 24], "af": 7, "remot": 7, "your_github_us": 7, "copi": [7, 10, 11, 17, 21, 22, 24, 31], "upstream": [7, 10, 20, 21, 23], "repo": [7, 21, 24], "addit": [7, 11, 13, 14, 17, 19, 20, 28], "fetch": [7, 10], "prune": 7, "rebas": 7, "read": [7, 11, 12, 13, 18, 21, 22, 24, 28, 29, 30, 31], "avoid": [7, 8, 16, 18, 21], "loss": 7, "process": [7, 10, 11, 13, 16, 21, 28, 30], "delet": [7, 17, 19, 21], "result": [7, 11, 17, 21, 31], "info": [7, 10, 11, 17, 28, 31], "below": [7, 13, 16, 17, 24, 25, 30, 31], "how": [7, 8, 10, 16, 18, 19, 21, 26, 28, 30, 31], "origin": [7, 10, 16, 17, 28, 31], "name_of_local_branch": 7, "tracker": 7, "choic": [7, 21], "b": 7, "occasion": 7, "explain": [7, 10, 28], "abov": [7, 10, 11, 17, 21, 27, 30], "merg": 7, "succe": 7, "even": [7, 10, 11, 13, 17, 20, 22], "better": [7, 11], "automat": [7, 10, 13, 17, 18, 21, 22, 23, 24, 31], "produc": [7, 11, 17, 28, 30, 31], "expect": [7, 16, 17], "offic": 7, "alwai": [7, 11, 15, 17, 19, 21, 24], "given": [7, 10, 21, 29], "topic": [7, 8, 10], "pythia_interfac": 7, "someth": [7, 10, 11, 14, 17, 26, 31], "solid": 7, "often": [7, 24], "onc": [7, 10, 13, 14], "finish": 7, "larg": [7, 10, 20], "consid": [7, 21, 31], "progress": [7, 21], "repres": 7, "snapshot": 7, "whole": [7, 10, 20], "previou": [7, 9, 11], "although": [7, 11, 21, 24], "well": [7, 10, 13, 16, 17, 22, 26, 28, 30, 31], "practic": [7, 10, 24, 31], "pass": [7, 11, 13, 14, 16, 17, 21, 28, 29, 30, 31], "find": [7, 8, 10, 11, 17, 21, 24, 26], "both": [7, 10, 16, 17, 23, 28, 31], "good": [7, 11, 24], "bad": [7, 21], "meaning": [7, 10, 16, 31], "ref": [7, 16], "id": [7, 11, 13], "correctli": 7, "printout": 7, "interfac": [7, 21, 31], "short": [7, 16, 17], "liner": 7, "here": [7, 10, 11, 17, 25, 26, 27, 30, 31], "write": [7, 8, 12, 18, 22, 29, 31], "befor": [7, 10, 11, 31], "idea": [7, 11], "sens": [7, 17], "messag": [7, 17], "did": 7, "unnecessari": 7, "log": [7, 11], "d": [7, 17, 20, 25], "commonli": [7, 27], "actual": [7, 10, 16, 17, 21, 31], "entir": [7, 16, 18], "give": [7, 10, 11, 13, 16, 17, 24, 31], "titl": 7, "appropri": [7, 10], "calorimet": 7, "cluster": [7, 17], "pr": [7, 13, 17], "wip": 7, "descript": [7, 10, 16, 17, 27, 31], "bullet": 7, "point": [7, 11, 13, 17, 19, 22, 28], "wa": [7, 10, 11, 16, 22], "track": [7, 15, 16, 17, 27], "sure": [7, 11, 14, 16, 27, 31], "mention": 7, "close": 7, "v": [7, 21], "similar": [7, 10, 11, 13, 17, 21, 30, 31], "address": 7, "own": [7, 10, 13, 16, 17, 29], "renam": [7, 16, 18], "myfccsw": 7, "url": 7, "question": [7, 10], "sort": 7, "out": [7, 10, 11, 21, 24, 31], "drop": [7, 10, 11, 14, 31], "altern": [7, 16, 21, 24, 30], "sooner": 8, "rather": [8, 12, 16, 17, 21], "necessari": [8, 10, 13, 16, 17, 21, 28, 30, 31], "These": [8, 11, 16, 17, 24, 28, 29, 31], "cover": [8, 30], "friction": 8, "workflow": [8, 18, 20, 31], "guid": [8, 13, 17, 18], "overview": [8, 11, 18], "gener": [8, 11, 14, 16, 18, 21, 30, 31], "up": [8, 9, 11, 17, 18, 20, 22, 23, 26, 31], "ssh": [8, 11, 18, 21], "kei": [8, 11, 16, 18], "improv": [8, 17, 18], "keep": [8, 11, 14, 15, 16, 31], "date": [8, 10, 21, 22], "recommend": [8, 11, 17, 18, 24, 31], "clean": [8, 31], "histori": 8, "troubl": [8, 18], "shoot": [8, 18, 27], "try": [8, 10, 13, 16, 17, 26], "push": [8, 10], "authent": 8, "error": [8, 11, 17, 21], "now": [8, 10, 17, 21, 24, 27, 31], "my": [8, 10], "what": [8, 10, 11, 13, 17, 21, 24, 29], "cmake": [8, 9, 10, 11, 18, 21], "quick": [8, 9, 10, 18], "build": [8, 9, 11, 18, 19, 21, 22, 24, 27, 29, 30], "packag": [8, 18, 19, 20, 22, 23, 25, 30], "configur": [8, 9, 10, 11, 14, 18, 20, 21, 23, 27, 28, 29, 30, 31], "runtim": [8, 16], "custom": [8, 12, 13, 18, 24], "singl": [8, 13, 17, 18], "dev": 8, "advanc": [8, 17, 21], "usag": [8, 12, 14, 15, 16, 17, 18, 26], "function": [8, 12, 16, 18, 30], "walkthrough": [8, 18], "steer": [8, 15, 18, 28, 30, 31], "initi": [8, 18], "final": [8, 18, 31], "gdb": [8, 18], "const": [8, 17, 18], "oper": [8, 17, 18], "cmakebuild": 8, "gave": 9, "while": [9, 10, 13, 14, 16, 17, 24, 31], "approach": [9, 10], "number": [9, 10, 11, 13, 16, 17, 20, 21, 28, 29, 31], "cumbersom": [9, 10], "repeat": [9, 16], "cycl": [9, 10, 11], "miss": [9, 16, 18, 26], "notic": 9, "reproduc": [9, 10, 19, 31], "somewhat": [10, 16, 17], "its": [10, 13, 15, 16, 17, 21, 24, 29], "limit": [10, 11, 13, 14], "howev": [10, 11, 16, 19, 24, 27, 30, 31], "imposs": 10, "unfortun": [10, 21], "might": [10, 14, 16, 21, 22, 27, 31], "fulli": [10, 27], "henc": [10, 13, 17, 31], "tri": [10, 21], "collect": [10, 11, 16, 18, 21, 27, 28, 31], "obtain": [10, 11, 13, 17, 28], "standalon": [10, 12, 16, 18, 26], "suffic": 10, "three": 10, "let": [10, 11, 21, 26], "sai": 10, "nigthli": 10, "2023": [10, 25], "07": 10, "18": [10, 21], "x86_64": [10, 21, 24], "almalinux9": [10, 19], "gcc11": 10, "opt": 10, "kzukii": 10, "And": 10, "latest": [10, 19, 23, 24], "scratch": [10, 22], "inam": 10, "happen": [10, 11, 14, 19], "06": [10, 21], "24": [10, 25], "rel": [10, 11, 24], "latest_scratch": 10, "depth": 10, "cat": [10, 24], "cherri": 10, "env": [10, 24], "config": [10, 24, 28, 29, 30, 31], "install_tre": [10, 24], "exactli": [10, 17], "minimum": [10, 16], "brief": [10, 12, 16, 17], "There": [10, 11, 13, 17, 29], "dedic": 10, "slack": 10, "spackpm": 10, "invit": 10, "visit": 10, "io": [10, 11], "regard": 10, "discuss": [10, 14], "doe": [10, 17, 21], "been": [10, 13, 16, 17, 27, 31], "sinc": [10, 11, 16, 17, 21, 22, 24, 31], "would": [10, 11, 16, 17, 21, 26, 28, 31], "entail": 10, "spec": [10, 21, 24], "il": 10, "rootdict": 10, "input": [10, 11, 13, 14, 16, 17, 18, 21, 26, 29, 30, 31], "concret": [10, 21, 24], "vdwx2aq": 10, "16": [10, 21], "gcc": [10, 24], "9": [10, 19, 21], "ipo": [10, 21], "jar": 10, "build_typ": [10, 21], "relwithdebinfo": [10, 21], "cxxstd": [10, 21], "17": [10, 21, 24, 25], "arch": [10, 21], "linux": [10, 21], "ubuntu20": [10, 21], "04": [10, 19, 21], "skylak": 10, "utzbuq7": 10, "doc": [10, 21, 26], "ncurs": [10, 21], "openssl": [10, 21], "ownlib": [10, 21], "qt": [10, 21], "1c540040c7e203dd8e27aa20345ecb07fe06570d56410a24a266ae570b1c4c39": 10, "bf695e3febb222da2ed94b3beea600650e4318975da90e4a71d6f31a6d5d8c3d": 10, "pljbs5a": 10, "sio": [10, 17], "builtin_zlib": 10, "alreadi": [10, 11, 16, 17, 21, 22, 24, 27], "yet": [10, 16, 21, 31], "ilcsoft": [10, 16, 27, 28, 31], "fulfil": 10, "full": [10, 17, 31], "output": [10, 11, 13, 14, 16, 18, 26, 28, 29, 31], "stage": 10, "end": [10, 13, 28, 31], "7dovpqn3kscbg672ham5wcqro7lg45gh": 10, "00": 10, "62": 10, "total": [10, 29], "home": [10, 17, 21], "tmadlen": 10, "specifi": [10, 17, 31], "cannot": [10, 13, 16, 21, 24], "arbitrari": [10, 13, 16], "necessarili": 10, "cours": [10, 11, 31], "encourag": 10, "useabl": 10, "desir": [10, 14, 16, 17], "nice": 10, "downstream": 10, "far": [10, 17], "concern": 10, "realli": 10, "download": [10, 18, 20, 30], "fact": [10, 17], "manifest": 10, "lv": 10, "yield": 10, "7dovpqn": 10, "dev_path": 10, "part": [10, 13, 14, 17, 20, 27, 28, 30, 31], "hash": [10, 23], "affect": 10, "specif": [10, 13, 21], "syntax": 10, "uninstal": 10, "again": [10, 13, 16, 17, 31], "becaus": [10, 11, 17], "overwrit": 10, "dealt": 10, "easili": [10, 24], "achiev": [10, 12, 17, 29, 30, 31], "until": 10, "proper": [10, 27], "scheme": 10, "j4": 10, "afterward": 10, "locat": [10, 28, 29], "regist": [10, 21], "databas": 10, "call": [10, 13, 16, 17, 18, 22], "trick": 10, "back": [10, 17], "chain": [10, 31], "recompil": 10, "artifact": 10, "success": [10, 11, 29], "return": [10, 11, 17], "type": [10, 11, 13, 16, 29], "exit": [10, 17], "simultan": 10, "doesn": 10, "scale": [10, 20], "definit": [10, 11], "20": [10, 25, 31], "davix": 10, "gsl": 10, "math": 10, "memstat": 10, "minuit": 10, "mlp": 10, "mysql": 10, "opengl": 10, "postgr": 10, "pythia6": 10, "pythia8": [10, 21, 30], "qt4": 10, "r": [10, 20, 25, 29], "root7": 10, "rootfit": 10, "rpath": 10, "shadow": 10, "sqlite": 10, "ssl": 10, "tabl": 10, "tbb": [10, 29], "thread": [10, 11, 17, 21, 29], "tmva": 10, "unuran": 10, "vc": 10, "vdt": 10, "vmc": 10, "x": [10, 30], "xrootd": 10, "22af3471f3fd87c0fe8917bf9c811c6d806de6c8b9867d30a1e3d383a1b929d7": 10, "geant4": [10, 21], "heppdt": 10, "hepmc": [10, 21], "10": [10, 11, 21, 25, 27, 28, 29], "tricktrack": 10, "pyyaml": 10, "jinja2": [10, 17], "evtgen": [10, 21], "view": [10, 11, 21, 24], "true": [10, 29], "variant": 10, "edm4hep_devel": 10, "yaml": [10, 18, 20, 21], "devel": 10, "p": [10, 17, 24], "immedi": 10, "state": [10, 11, 17, 21, 31], "properli": [10, 11], "straight": [10, 17, 31], "base": [10, 11, 14, 16, 17, 31], "disadvantag": 10, "handl": [10, 16, 17, 18, 21, 31], "gain": 10, "abil": 10, "256": 10, "optim": [10, 21, 29], "decent": 10, "too": [10, 14], "deep": 10, "down": [10, 17], "impli": 10, "frequent": 10, "relink": 10, "lot": [10, 27], "nevertheless": [10, 17], "usabl": [10, 13, 29], "briefli": [10, 17], "mainli": [10, 12, 17], "whether": [10, 17, 24], "rest": [10, 11, 31], "veri": [10, 11, 13, 16, 17, 23, 24, 26, 31], "turn": [10, 17], "depen": 10, "suppos": 10, "fals": [10, 15, 16, 28], "previous": [10, 16, 31], "field": 10, "tell": [10, 11, 17], "var": 10, "absolut": 10, "aidasoft": [10, 17], "development_env_packag": 10, "enough": [10, 17, 21], "either": [10, 13, 16, 21, 28, 31], "easiest": [10, 11, 13, 16, 30, 31], "relat": [10, 14, 18], "among": [10, 17], "arg": [10, 14], "l": [10, 31], "realiz": [10, 17, 24], "broke": 10, "defin": [10, 11, 13, 16, 17, 28], "live": [10, 17], "insid": [10, 11, 16, 17], "could": [10, 11, 16, 31], "f": [10, 22, 24], "inde": 10, "along": [10, 31], "broadwel": [10, 21], "m5khm2w": 10, "seen": 10, "event": [11, 12, 18, 25, 26, 28, 30, 31], "care": [11, 17], "servic": [11, 14, 29], "support": [11, 16, 17, 18, 19, 21, 22, 26, 31], "multithread": [11, 18, 26], "relationship": 11, "between": [11, 16, 17, 18, 29, 31], "util": [11, 30], "almost": [11, 16, 17, 31], "seamlessli": 11, "design": [11, 12, 13, 17, 26], "enforc": [11, 21], "constraint": 11, "quicker": 11, "intern": [11, 13, 14, 16, 17, 25], "benefit": 11, "being": [11, 13, 17, 21, 31], "trivial": 11, "ourselv": 11, "easi": [11, 17, 24], "templat": [11, 17], "k4": 11, "ideal": [11, 22], "know": [11, 26], "detail": [11, 13, 14, 15, 17, 18, 26, 31], "k4run": [11, 12, 14, 16, 18, 26, 27, 28], "k4testfwcor": 11, "createexampleeventdata": 11, "straightforward": 11, "class": [11, 16], "inherit": [11, 17], "member": [11, 17, 29], "none": [11, 16, 21, 28, 29], "developkit": 11, "03a": 11, "consum": [11, 13], "transform": 11, "multitransform": 11, "structur": [11, 21], "precis": 11, "struct": [11, 13, 17], "gaudialg": 11, "h": [11, 13, 17, 30], "baseclass_t": 11, "baseclass": 11, "exampletransform": 11, "colltype_out": 11, "colltype_in": 11, "std": [11, 17], "string": [11, 16, 21], "isvcloc": 11, "svcloc": 11, "overrid": [11, 21], "magic": 11, "modifi": [11, 17, 24, 28], "signatur": 11, "mcparticlecollect": [11, 17], "leav": 11, "slightli": [11, 16, 17], "complic": 11, "tupl": 11, "outputclass1": 11, "outputclass2": 11, "aren": 11, "void": [11, 17], "reach": 11, "constructor": [11, 17], "keyvalu": 11, "save": 11, "inputcollect": 11, "mcparticl": [11, 13, 16, 17, 31], "outputcollect": 11, "newmcparticl": 11, "possibli": 11, "valu": [11, 16, 21, 29, 31], "bundl": [11, 13, 24], "enclos": 11, "bracket": 11, "examplemultitransform": 11, "outputcollection1": 11, "outputcollection2": 11, "simtrackerhit": 11, "outputcollection3": 11, "usefulcollect": 11, "auto": [11, 13, 17], "coll_out": 11, "particl": [11, 13, 17, 25, 27], "new_particl": 11, "mutablemcparticl": [11, 17], "setpdg": 11, "getpdg": 11, "setgeneratorstatu": 11, "getgeneratorstatu": 11, "setsimulatorstatu": 11, "getsimulatorstatu": 11, "setcharg": 11, "getcharg": 11, "settim": 11, "gettim": 11, "setmass": 11, "getmass": 11, "push_back": [11, 17], "make_tupl": 11, "move": [11, 17, 22, 29], "collection1": 11, "collection2": 11, "k4fwcoretest": 11, "examplefunctionaltransform": 11, "paramet": [11, 16, 18, 27, 28], "applicationmgr": [11, 14, 16, 28, 29, 31], "k4datasvc": [11, 18, 28, 29, 31], "podiooutput": [11, 14, 29, 31], "podioinput": [11, 14, 28, 29, 31], "editor": 11, "analysi": [11, 31], "undefin": 11, "podioev": 11, "eventdatasvc": [11, 14, 28, 29, 31], "output_k4test_exampledata_produc": 11, "inp": 11, "select": [11, 14, 16, 24], "filenam": [11, 14, 31], "output_k4test_exampledata_transform": 11, "present": [11, 17, 18, 26, 27], "outputcommand": [11, 14, 31], "relev": [11, 17, 21], "learn": [11, 31], "object": [11, 13, 17], "topalg": [11, 28, 29], "evtsel": [11, 28, 29], "evtmax": [11, 28, 29], "extsvc": [11, 14, 28, 29], "outputlevel": [11, 28, 29, 31], "last": [11, 17, 31], "maximum": 11, "That": 11, "extra": 11, "warn": [11, 13, 16, 19, 28, 29], "occas": 11, "place": 11, "those": [11, 17], "statuscod": 11, "rememb": [11, 31], "statu": [11, 25], "crash": [11, 13], "myalgorithm": 11, "gnu": 11, "debugg": 11, "invok": [11, 13, 21], "attach": [11, 16, 25, 31], "load": [11, 21, 24], "continu": [11, 17], "consol": 11, "interrupt": 11, "ctrl": 11, "c": [11, 17, 27], "requir": [11, 17, 28], "account": [11, 16], "around": 11, "keyword": 11, "mutabl": [11, 17], "caus": 11, "wasn": 11, "Of": 11, "unless": [11, 28], "safe": [11, 17, 21, 29], "longer": [11, 17, 22], "wors": 11, "wrong": 11, "written": [11, 17], "substitut": 11, "certain": [12, 13, 14], "within": [12, 16, 17, 29, 30, 31], "aim": [12, 31], "technic": [12, 18], "infrastructur": [12, 18], "wrap": [12, 18, 27, 28, 29, 31], "processor": [12, 18, 27, 28, 29, 31], "convers": [12, 17, 18, 27, 28, 31], "lcio2edm4hep": [13, 16], "slcio": [13, 16, 28, 31], "lcevent": 13, "put": [13, 16, 21, 22, 24], "frame": [13, 18], "categori": [13, 17], "major": [13, 16, 17, 30], "effect": [13, 14], "wherea": 13, "assumpt": [13, 14], "ensur": [13, 21], "potenti": [13, 31], "come": [13, 16, 17], "form": [13, 16, 17], "third": 13, "compris": [13, 20], "superset": 13, "format": [13, 16, 17, 28, 30, 31], "simplest": [13, 21], "setspacepoint": 13, "trackerhit": 13, "recomctruthlink": [13, 14, 31], "check_missing_col": 13, "minim": [13, 14, 16], "pnf": 13, "desi": 13, "prod": 13, "mc": [13, 14, 17], "2020": [13, 25], "ild": [13, 18, 26, 27], "rec": [13, 31], "250": 13, "seta": [13, 17], "higg": 13, "ild_l5_o2_v02": 13, "v02": 13, "02": [13, 17], "01": 13, "00015671": 13, "000": 13, "rv02": [13, 17], "sv02": [13, 17], "mild_l5_o2_v02": 13, "e250": [13, 17], "i402005": 13, "pe3e3h": 13, "el": [13, 17], "n000_002": 13, "d_rec_00015671_493": 13, "fromtyp": 13, "totyp": 13, "correct": [13, 17, 23], "determin": [13, 29], "skip": [13, 16], "mechan": [13, 16, 21], "colltypefil": 13, "remap": 13, "store": [13, 16, 17], "overal": 13, "resolv": [13, 16, 31], "fill": [13, 17], "convertcollect": 13, "dispatch": [13, 17], "lccollect": 13, "map": [13, 16], "dure": [13, 16, 21, 28], "lcioedmtypemap": 13, "resolverel": 13, "obvious": [13, 17], "fillsubset": 13, "handlesubsetcol": 13, "associationcollect": 13, "createassoci": 13, "convertev": 13, "convertobjectparamet": 13, "small": 13, "shine": 13, "calohitcontribut": [13, 17], "simcalorimeterhit": [13, 16], "createcalohitcontribut": 13, "separ": [13, 17, 22], "eventhead": [13, 31], "eventheadercollect": 13, "reconstruct": [13, 15, 17, 18, 26, 29], "k4lcio2edm4hepconv": 13, "edm": [13, 18, 28, 29], "counterpart": 13, "typemap": 13, "edmcollect": 13, "convertreconstructedparticl": 13, "recoparticl": 13, "particleid": 13, "facil": 14, "much": 14, "familiar": [14, 16], "snippet": [14, 16], "runnabl": 14, "whenev": 14, "instanti": [14, 16, 31], "evtsvc": [14, 28, 31], "extern": [14, 17, 20, 21], "my_output": 14, "eventstor": [14, 17, 29], "must": [14, 22, 29], "target": [14, 16, 22], "pattern": 14, "apart": 14, "metadata": 14, "highest": 14, "reco": [14, 17], "mcparticlesskim": [14, 31], "pandorapfo": [14, 31], "extend": 15, "parsearg": 15, "parser": 15, "add_argu": 15, "trackingonli": 15, "action": 15, "store_tru": 15, "my_opt": 15, "parse_known_arg": 15, "behind": [15, 17], "scene": 15, "normal": [15, 16, 17], "argpars": 15, "argumentpars": 15, "mind": 15, "parse_arg": 15, "former": 16, "linear": 16, "collid": [16, 18, 25], "latter": [16, 17, 28], "studi": [16, 25], "gradual": 16, "migrat": 16, "bare": 16, "modif": 16, "processortyp": [16, 27], "attribut": [16, 27], "pars": [16, 21], "statmonitoralg": 16, "statusmonitor": 16, "howoften": 16, "int": [16, 17], "world": [16, 17], "lcioevent": [16, 29, 31], "inputfile1": 16, "inputfile2": 16, "lciooutputprocessor": [16, 29], "output_dst": 16, "dropcollectionnam": 16, "dropcollectiontyp": 16, "lcrelat": [16, 18], "convertmarlinsteeringtogaudi": [16, 28, 31], "statement": [16, 31], "trackingdigi": 16, "inputfil": [16, 17, 27, 28, 31], "constant": [16, 31], "somefancyconst": 16, "begin": 16, "condit": 16, "tag": 16, "principl": [16, 17], "At": [16, 17, 28], "moment": [16, 19], "basi": 16, "addition": [16, 21], "static": [16, 21], "partial": 16, "alglist": [16, 28, 29, 31], "uncom": [16, 28], "lcioinputfil": [16, 28], "retriev": [16, 17], "o": [16, 17, 21, 28, 31], "gauditool": 16, "lcio2edm4heptool": [16, 29, 31], "edm4hep2lciotool": [16, 29, 31], "equip": 16, "edm4hep2lcioconv": [16, 31], "edm4hep2lcio": 16, "lcio2edm4hepconv": [16, 31], "wrappedprocalg": 16, "processortowrap": 16, "direct": [16, 17], "confus": 16, "transient": 16, "higher": 16, "granular": 16, "collnamemap": [16, 31], "fly": [16, 18, 27, 31], "convertal": 16, "subset": [16, 18], "hand": [16, 26], "toward": [17, 25], "knowledg": 17, "web": [17, 22], "diagrammat": 17, "broadli": 17, "arrow": 17, "depict": 17, "black": 17, "purpl": 17, "ish": 17, "flavor": 17, "onetoonerel": 17, "onetomanyrel": 17, "hierarchi": 17, "mother": 17, "daughter": 17, "vice": [17, 31], "versa": [17, 31], "hold": 17, "reconstructedparticl": [17, 18], "connect": [17, 27], "contrast": [17, 23], "involv": 17, "throughout": 17, "datatyp": 17, "click": 17, "jump": [17, 27], "educ": 17, "index": 17, "expand": 17, "namespac": [17, 21], "calohitcontributioncollect": 17, "calohitcontributioncollectiondata": 17, "calohitcontributioncollectioniter": 17, "calohitcontributiondata": 17, "calohitcontributionmutablecollectioniter": 17, "calohitcontributionobj": 17, "calohitcontributionsioblock": 17, "mutablecalohitcontribut": 17, "mark": 17, "bold": 17, "truli": 17, "visibl": 17, "helper": 17, "ever": 17, "style": 17, "herb": 17, "sutter": 17, "blog": 17, "digest": 17, "summari": 17, "purpos": [17, 27], "slight": 17, "detour": 17, "bring": 17, "arriv": 17, "toolkit": 17, "further": [17, 24, 31], "context": 17, "effici": [17, 20, 23], "high": [17, 25], "gori": 17, "implic": 17, "inspect": 17, "valid": 17, "engin": 17, "perform": [17, 28], "autom": 17, "advantag": 17, "repetit": 17, "task": 17, "themselv": 17, "deal": 17, "roll": [17, 22], "regener": 17, "goal": 17, "favor": 17, "composit": 17, "plain": 17, "old": 17, "pod": 17, "wherev": 17, "emploi": 17, "memori": [17, 31], "lightweight": 17, "xyzcollect": 17, "mutablexyz": 17, "xyzobj": 17, "bottom": [17, 28], "xyzdata": 17, "exact": [17, 21], "treat": [17, 21, 22], "worri": 17, "ineffici": 17, "reconstructedparticlecollect": 17, "p2": 17, "loop": [17, 29], "vtx": 17, "getstartvertex": 17, "vertex": 17, "gettrack": 17, "squint": 17, "ignor": 17, "pyroot": 17, "len": 17, "pretti": 17, "rule": 17, "vectormemb": 17, "stick": 17, "front": 17, "capit": 17, "letter": 17, "vector3f": 17, "momentum": [17, 21], "gev": [17, 21, 27], "getmomentum": 17, "nuanc": 17, "appli": 17, "method": [17, 29], "setmomentum": 17, "addto": 17, "addtodaught": 17, "underli": 17, "reason": 17, "complex": 17, "dive": 17, "quit": 17, "deepish": 17, "beyond": 17, "scope": [17, 24], "immut": 17, "te": 17, "independ": 17, "implicitli": 17, "convert": [17, 18, 28, 29, 30, 31], "implicit": 17, "print": [17, 30], "cout": 17, "getenergi": 17, "printemut": 17, "mutp": 17, "setenergi": 17, "14": [17, 21], "due": [17, 22], "break": [17, 19], "No": 17, "muon": [17, 18, 30], "larger": 17, "setsubsetcollect": 17, "transpar": 17, "aggreg": 17, "meta": 17, "interv": 17, "less": 17, "reflect": 17, "introduc": [17, 19], "infer": 17, "complain": 17, "ownership": 17, "signal": 17, "left": [17, 28], "unspecifi": 17, "circumst": 17, "match": 17, "backend": 17, "makeread": 17, "some_file_containing_edm4hep": 17, "size_t": 17, "getev": 17, "readnextev": 17, "stuff": 17, "rootread": 17, "ttree": 17, "rootlegacyread": 17, "rntupleread": 17, "rntupl": 17, "sioread": 17, "siolegacyread": 17, "ago": 17, "interest": [17, 21, 31], "next": [17, 31], "construct": 17, "openfil": 17, "some_file_containing_edm4hep_data": 17, "getentri": 17, "readnextentri": 17, "root_io": 17, "legacyread": 17, "interpret": 17, "caveat": 17, "flat": 17, "ntupl": 17, "workarea": 17, "mild_l5_o1_v02": 17, "i402003": 17, "pe2e2h": 17, "n000": 17, "d_dstm_15089_0_edm4hep": 17, "peek": 17, "synopsi": 17, "dump_edm": 17, "stdout": 17, "posit": 17, "comma": 17, "inclus": 17, "rang": 17, "element": 17, "ascii": 17, "choos": [17, 24, 31], "central": [18, 21, 22, 24], "Tos": 18, "resourc": [18, 30], "doxygen": 18, "api": 18, "layout": 18, "dump": [18, 21], "marlinprocessorwrapp": [18, 27, 28, 29, 31], "subtl": 18, "simul": [18, 26, 27], "displai": [18, 19, 26], "troubleshoot": [18, 26], "detector": [18, 25, 26, 28, 30, 31], "delph": [18, 26], "fast": [18, 26], "prerequisit": [18, 26], "librarian": 18, "talk": 18, "logo": 18, "cepc": 18, "everi": [19, 23], "month": 19, "demand": 19, "ubuntu22": 19, "el9": 19, "rockylinux9": 19, "almalinux": 19, "ubuntu": 19, "22": 19, "unannounc": 19, "anyth": [19, 27, 30, 31], "els": [19, 31], "fairli": [20, 23], "scientif": 20, "regularli": 20, "deploi": [20, 21, 23], "recip": 20, "known": 21, "workaround": [21, 31], "invoc": 21, "degre": 21, "decis": 21, "estim": 21, "long": 21, "proxi": 21, "solv": 21, "spit": 21, "solut": 21, "were": [21, 22, 31], "12": 21, "criteria": 21, "prioriti": 21, "criterion": 21, "tobuild": 21, "reus": 21, "weight": 21, "deprec": 21, "non": [21, 29], "prefer": 21, "8": 21, "11": [21, 24, 25], "mismatch": 21, "13": 21, "156": 21, "15": 21, "165": 21, "44": 21, "whizard": [21, 31], "fastjet": 21, "latex": 21, "lhapdf": 21, "openloop": 21, "openmp": 21, "hepmc3": 21, "rootio": 21, "1c54004": 21, "bf695e3": 21, "libtirpc": 21, "krb5": 21, "19": 21, "bison": 21, "diffutil": 21, "libiconv": 21, "m4": 21, "sigsegv": 21, "3877ab5": 21, "fc9b616": 21, "perl": 21, "30": 21, "cpanm": 21, "gettext": 21, "21": [21, 25], "bzip2": 21, "curs": 21, "libunistr": 21, "libxml2": 21, "tar": 21, "xz": 21, "pic": 21, "pkgconf": 21, "zlib": 21, "0d38234": 21, "symlink": 21, "termlib": 21, "abi": 21, "zip": 21, "pigz": 21, "1f": 21, "cert": 21, "mozilla": 21, "ocaml": 21, "forc": 21, "306": 21, "hdf5": 21, "madgraph5amc": 21, "mpich": 21, "openmpi": 21, "rivet": 21, "length": 21, "mm": 21, "rsync": 21, "alradi": 21, "hard": 21, "preced": 21, "detect": [21, 31], "perfectli": 21, "varieti": 21, "machin": [21, 22, 24, 29, 31], "bundlepackag": 21, "investig": [21, 22], "filesystem": 21, "usr": 21, "simplifi": 21, "thu": [21, 22], "platform": [21, 22, 24], "gracefulli": 21, "ongo": 21, "discourag": 21, "strenght": 21, "smoothli": 21, "publish": 21, "axv": 21, "inplac": 21, "compress": 21, "stricthostkeycheck": 21, "gssapiauthent": 21, "ye": 21, "gssapitrustdn": 21, "spackag": [21, 22, 23], "omit": 21, "preserv": 21, "expos": [21, 29], "gitlab": 21, "sft": [21, 24], "cc": 21, "cling": 21, "17488": 21, "difficulti": 22, "reloc": 22, "eo": 22, "space": [22, 28], "k": 22, "www": 22, "spack_build": 22, "mirror": 22, "lcg": [22, 24], "branchnam": 22, "indic": [22, 28, 29], "contrib": [22, 24], "subdirectori": 22, "permiss": 22, "subscrib": 22, "egroup": 22, "cernbox": 22, "writer": 22, "m": 22, "hour": 22, "search": [22, 24], "serv": 22, "quickli": 23, "stabl": 23, "typic": 23, "head": 23, "rebuild": 23, "dai": 23, "infrequ": 23, "setup_clingo_centos7": 24, "client": 24, "oss": 24, "bootstrap": 24, "clingo": 24, "suitabl": 24, "kept": 24, "therefor": 24, "variat": 24, "clang": 24, "compat": [24, 31], "essenti": [24, 30], "ci_setup_spack": 24, "global": [24, 28], "itself": 24, "hint": 24, "nudg": 24, "With": [24, 31], "obsolet": 24, "ship": [24, 30], "box": 24, "cp": [24, 28], "eot": 24, "spackages6": 24, "site": 24, "zotero": 25, "group": 25, "item": 25, "carcel": 25, "juan": 25, "miguel": 25, "juli": 25, "indico": 25, "1301872": 25, "5474076": 25, "2682457": 25, "4653446": 25, "carceller_key4hep_spack_2023": 25, "pdf": 25, "ep": 25, "meet": 25, "june": 25, "1253565": 25, "5265910": 25, "2591081": 25, "4628747": 25, "carceller_key4hep_20230621": 25, "volkl": 25, "valentin": 25, "ia": 25, "energi": [25, 27], "physic": [25, 30], "2021": 25, "januari": 25, "971970": 25, "timet": 25, "153": 25, "madlen": 25, "thoma": 25, "turnkei": 25, "xxvii": 25, "cracow": 25, "epiphani": 25, "confer": 25, "934666": 25, "4154229": 25, "2168411": 25, "3660367": 25, "key4hep_epiphany2021_cracow": 25, "helsen": 25, "clement": 25, "4154228": 25, "gani": 25, "gerardo": 25, "ust": 25, "hk": 25, "shared_doc": 25, "202001hep": 25, "workshop": 25, "exp": 25, "20200117_1038_am_gerri_gani": 25, "sailer": 25, "andr\u00e9": 25, "joint": 25, "charm": 25, "tau": 25, "factori": 25, "septemb": 25, "2019": 25, "rich2018": 25, "180": 25, "151": 25, "247": 25, "190924_sailer_softwar": 25, "comput": 25, "nuclear": 25, "773049": 25, "3474763": 25, "1938664": 25, "3213633": 25, "191105_sailer_key4hep": 25, "mato": 25, "pere": 25, "clicdp": 25, "august": 25, "28": 25, "792656": 25, "3536473": 25, "1898480": 25, "3132881": 25, "key4hep_clicdp_meet": 25, "session": 26, "incomplet": 26, "accept": 26, "suggest": [26, 31], "geometri": [26, 27], "ildreconstruct": 26, "ildconfig": 26, "inter": 26, "parallel": 26, "ced": 27, "cedview": 27, "concept": [27, 31], "self": 27, "clicperform": [27, 28], "ddsim": [27, 28, 31], "gun": 27, "photon": 27, "illustr": 27, "creation": 27, "minut": [27, 31], "steeringfil": [27, 28, 31], "clicconfig": [27, 28], "clic_steer": [27, 28], "compactfil": [27, 28, 31], "k4geo": [27, 28], "compact": [27, 28, 31], "clic_o3_v14": [27, 28], "enablegun": 27, "uniform": 27, "gamma": 27, "outputfil": [27, 28, 31], "gamma_10gev_edm4hep": 27, "numberofev": [27, 28], "ddcedview": 27, "wrapper": 27, "event_displai": 27, "glced": 27, "server": 27, "visualis": 27, "clic_o3_v06_c": 27, "mycedview": 27, "explanatori": 27, "cld": 27, "deriv": 27, "compar": 27, "hit": 27, "drawinlay": 27, "_edm4hep": 28, "ttbar_edm4hep": 28, "yyxyev_000": 28, "stdhep": [28, 30], "ttbar": 28, "clicreconstruct": [28, 29], "initdd4hep": 28, "dd4hepxmlfil": 28, "maxrecordnumb": 28, "overlayfals": 28, "trackingconform": 28, "sed": [28, 31], "append": [28, 29, 31], "myconformaltrack": 28, "clonesandsplittracksfind": 28, "renamecollect": 28, "lcgeo": 28, "wont": 28, "clicrec_e4h_input": 28, "marlindd4hep": 28, "initializedd4hep": 28, "k4simgeant4": 28, "geosvc": 28, "trackingcellidencodingsvc": 28, "svclist": 28, "join": 28, "test_dir": 28, "geoservic": 28, "clic_o3_v15": 28, "enablegeant4geo": 28, "cellidsvc": 28, "encodingstringparameternam": 28, "globaltrackerreadoutid": 28, "geosvcnam": 28, "lcioeventoutput": 29, "whiteboard": 29, "isfirstev": 29, "processev": 29, "multi": 29, "intel": 29, "hood": 29, "intra": 29, "hivewhiteboard": 29, "hiveslimeventloopmgr": 29, "avalancheschedulersvc": 29, "sequenc": 29, "hardwar": 29, "eventslot": 29, "schedul": 29, "flight": 29, "decid": [29, 31], "evtslot": 29, "slimeventloopmgr": 29, "schedulernam": 29, "threadpools": 29, "seq": 29, "eventloop": 29, "messagesvctyp": 29, "inertmessagesvc": 29, "cardin": 29, "gaudisequenc": 29, "sequenti": 29, "applic": 29, "alg1": 29, "alg2": 29, "alg3": 29, "alg4": 29, "algo": 29, "createviewseq": 29, "mode": 29, "clicrec_lcio_mt": 29, "fccee": 30, "zh": 30, "mu": 30, "z": 30, "decai": 30, "pair": 30, "opposit": 30, "charg": 30, "card": 30, "wget": [30, 31], "raw": [30, 31], "githubusercont": [30, 31], "spring2021": 30, "p8_nobes_ee_zh_ecm240": 30, "cmd": 30, "delphespythia8_edm4hep": 30, "delphespythia8": 30, "contrari": 30, "delphes_dir": 30, "delphes_card_idea": 30, "tcl": 30, "edm4hep_output_config": 30, "delphes_events_edm4hep": 30, "parameter": 30, "delphesstdhep_edm4hep": 30, "delphesroot_edm4hep": 30, "delpheshepmc": 30, "config_fil": 30, "output_config_fil": 30, "output_fil": 30, "input_fil": [30, 31], "todo": 30, "exercis": 31, "sim": 31, "conceptu": 31, "haven": 31, "remaind": 31, "key4hep_tut_ild_reco": 31, "minor": 31, "though": 31, "standardconfig": 31, "product": 31, "gaudi_ild_reco": 31, "zh_mumu": 31, "k4geo_dir": 31, "ild_l5_v02": 31, "ddsim_steer": 31, "zh_mumu_sim": 31, "meantim": 31, "detectormodel": 31, "ild_l5_o1_v02": 31, "outputfilebas": 31, "zh_mumu_rec": 31, "zh_mumu_aida": 31, "histogram": 31, "aida": 31, "zh_mumu_pfoanalysi": 31, "pandora": 31, "pfo": 31, "lciooutput": 31, "off": 31, "emd4hep": 31, "analys": 31, "exhibit": 31, "strongli": 31, "bulk": 31, "marlinstdreco": 31, "adjust": 31, "marlinstdrecopars": 31, "lcgeo_dir": 31, "dict": 31, "forget": 31, "exclud": 31, "bgoverlayww": 31, "bgoverlaybb": 31, "bgoverlaybw": 31, "bgoverlaywb": 31, "pairbgoverlai": 31, "popul": 31, "somewher": 31, "second": 31, "roughli": 31, "standardreco_": 31, "dst": 31, "pfoanalysi": 31, "outputbasenam": 31, "resp": 31, "sake": 31, "myaidaprocessor": 31, "mypfoanalysi": 31, "parseconst": 31, "reader": 31, "unchang": 31, "beamcalcollect": 31, "beamcalcollectioncontribut": 31, "ecalbarrelschitseven": 31, "ecalbarrelschitsevencontribut": 31, "ecalbarrelschitsodd": 31, "ecalbarrelschitsoddcontribut": 31, "ecalbarrelsihitseven": 31, "ecalbarrelsihitsevencontribut": 31, "ecalbarrelsihitsodd": 31, "ecalbarrelsihitsoddcontribut": 31, "ecalendcapringcollect": 31, "ecalendcapringcollectioncontribut": 31, "ecalendcapschitseven": 31, "ecalendcapschitsevencontribut": 31, "ecalendcapschitsodd": 31, "ecalendcapschitsoddcontribut": 31, "ecalendcapsihitseven": 31, "ecalendcapsihitsevencontribut": 31, "ecalendcapsihitsodd": 31, "ecalendcapsihitsoddcontribut": 31, "ftdcollect": 31, "hcalbarrelregcollect": 31, "hcalbarrelregcollectioncontribut": 31, "hcalbarrelrpchit": 31, "hcalbarrelrpchitscontribut": 31, "hcalecringrpchit": 31, "hcalecringrpchitscontribut": 31, "hcalendcapringcollect": 31, "hcalendcapringcollectioncontribut": 31, "hcalendcaprpchit": 31, "hcalendcaprpchitscontribut": 31, "hcalendcapscollect": 31, "hcalendcapscollectioncontribut": 31, "lhcalcollect": 31, "lhcalcollectioncontribut": 31, "lumicalcollect": 31, "lumicalcollectioncontribut": 31, "setcollect": 31, "sitcollect": 31, "tpccollect": 31, "tpclowptcollect": 31, "tpcspacepointcollect": 31, "vxdcollect": 31, "yokebarrelcollect": 31, "yokebarrelcollectioncontribut": 31, "yokeendcapscollect": 31, "yokeendcapscollectioncontribut": 31, "edm4hepoutput": 31, "zh_mumu_reco": 31, "num": 31, "glori": 31, "tweak": 31, "tier": 31}, "objects": {}, "objtypes": {}, "objnames": {}, "titleterms": {"contributor": 1, "code": [1, 7, 17], "conduct": 1, "contribut": [2, 7], "get": [2, 7, 17, 19], "start": [2, 6, 19], "softwar": [3, 6, 19], "call": 4, "logo": 4, "build": [5, 6, 10, 20, 23], "key4hep": [5, 6, 8, 10, 12, 18, 19, 20, 24, 26, 28, 30], "us": [5, 6, 10, 11, 16, 19, 21, 24, 27, 28, 31], "cmake": [5, 6], "For": [5, 10, 20], "develop": [5, 7, 8, 9, 10], "possibl": 5, "issu": 5, "packag": [5, 6, 9, 10, 21, 24], "have": [5, 7], "been": 5, "test": 5, "chang": [5, 6, 7], "differ": [5, 13], "commit": [5, 7], "branch": 5, "guid": [6, 7], "overview": [6, 7, 17], "quick": 6, "set": [6, 7, 10, 19, 21, 24, 27], "up": [6, 7, 10, 19, 21, 24, 27], "environ": [6, 10, 21, 24, 27], "run": [6, 17, 27, 29, 30, 31], "your": [6, 7], "local": [6, 7, 10], "instal": [6, 10, 19, 21, 24], "exampl": [6, 13, 29], "configur": [6, 16, 24], "runtim": [6, 21], "ctest": 6, "custom": [6, 15], "how": [6, 11, 12, 17, 29], "i": [6, 7, 17], "github": 7, "workflow": [7, 10, 21], "first": 7, "time": 7, "setup": [7, 10, 11, 30, 31], "git": 7, "gener": [7, 17], "ssh": 7, "kei": 7, "improv": 7, "experi": 7, "keep": 7, "repositori": [7, 21], "date": 7, "recommend": 7, "comment": 7, "clean": 7, "histori": 7, "pull": 7, "request": 7, "troubl": 7, "shoot": 7, "when": 7, "try": 7, "push": 7, "an": [7, 10, 27], "authent": 7, "error": 7, "clone": 7, "http": 7, "now": 7, "can": 7, "t": 7, "my": 7, "what": 7, "do": [7, 17], "need": [7, 17], "help": 7, "content": [8, 12, 18, 20], "singl": [9, 10], "spack": [10, 21, 22, 23, 24], "version": 10, "dev": 10, "depend": [10, 21], "more": 10, "advanc": 10, "usag": [10, 13, 21, 23, 30], "multipl": 10, "other": [10, 27, 30], "all": [10, 17], "ad": [10, 15], "anoth": 10, "write": [11, 14, 16, 17], "gaudi": [11, 14, 16, 28, 29, 31], "algorithm": [11, 16], "function": [11, 13, 17], "walkthrough": 11, "The": [11, 14, 16, 17], "steer": [11, 16], "file": [11, 14, 16, 17, 27, 31], "initi": 11, "final": 11, "debug": 11, "gdb": 11, "avoid": 11, "const": 11, "oper": 11, "Tos": 12, "instruct": 12, "standalon": [13, 30], "convers": [13, 16], "from": [13, 17, 31], "lcio": [13, 16, 27, 28], "edm4hep": [13, 14, 17, 27, 28, 30, 31], "patch": 13, "miss": 13, "collect": [13, 14, 17], "fly": 13, "convert": [13, 16], "lcrelat": 13, "onli": [13, 14], "subset": [13, 14, 17], "renam": 13, "librari": 13, "data": [13, 17, 21], "handl": 13, "relat": [13, 17], "entir": 13, "event": [13, 14, 16, 17, 27, 29], "paramet": 13, "subtl": 13, "between": 13, "reconstructedparticl": 13, "read": [14, 16, 17], "k4datasvc": 14, "argument": 15, "k4run": [15, 31], "wrap": 16, "marlin": [16, 28], "processor": 16, "marlinprocessorwrapp": 16, "automat": 16, "xml": 16, "limit": 16, "edm": [16, 17], "option": [16, 31], "common": 17, "model": 17, "import": 17, "resourc": 17, "doxygen": 17, "api": 17, "document": 17, "diagram": 17, "associ": 17, "tabl": 17, "avail": 17, "type": 17, "navig": 17, "refer": 17, "page": 17, "why": 17, "ar": 17, "so": 17, "mani": 17, "class": 17, "them": 17, "some": 17, "util": 17, "podio": 17, "technic": [17, 21, 23], "infrastructur": 17, "which": [17, 21], "thing": 17, "three": 17, "layer": 17, "basic": 17, "valu": 17, "semant": 17, "guess": 17, "interfac": 17, "yaml": [17, 24], "definit": 17, "xyz": 17, "mutablexyx": 17, "frame": 17, "contain": 17, "put": 17, "low": 17, "level": 17, "reader": 17, "root": 17, "layout": 17, "figur": 17, "out": 17, "legaci": 17, "dump": 17, "extern": 18, "link": 18, "stack": [19, 28], "central": 19, "cvmf": [19, 21, 23], "librarian": 20, "further": 21, "topic": 21, "check": 21, "newli": 21, "requir": 21, "certain": 21, "variant": 21, "global": 21, "system": 21, "target": 21, "architectur": 21, "bundl": 21, "compil": [21, 24], "duplic": 21, "recip": [21, 24], "downstream": 21, "wrapper": 21, "lcg": 21, "releas": [21, 24], "gcc": 21, "buildcach": 22, "nightli": 23, "inform": [23, 28], "download": 24, "instanc": 24, "user": 24, "upstream": 24, "addit": 24, "talk": 25, "present": 25, "tutori": 26, "exercis": 26, "displai": 27, "input": [27, 28], "creat": [27, 31], "detail": 27, "troubleshoot": 27, "detector": 27, "clic": 28, "simul": [28, 30, 31], "reconstruct": [28, 31], "through": 28, "k4marlinwrapp": [28, 29], "dd4hep": 28, "geometri": 28, "multithread": 29, "support": 29, "inter": 29, "parallel": 29, "delph": 30, "fast": 30, "output": 30, "prerequisit": 30, "execut": 30, "framework": 30, "ild": 31, "ildreconstruct": 31, "py": 31, "ildconfig": 31, "adapt": 31}, "envversion": {"sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 60}, "alltitles": {"Contributor Code of Conduct": [[1, "contributor-code-of-conduct"]], "Contributing": [[2, "contributing"]], "Getting Started": [[2, "getting-started"]], "Software": [[3, "software"]], "Call for logos": [[4, "call-for-logos"]], "Building Key4hep using CMake: For Developers": [[5, "building-key4hep-using-cmake-for-developers"]], "Possible issues": [[5, "possible-issues"]], "Packages that have been tested": [[5, "packages-that-have-been-tested"]], "Changing to a different commit or branch": [[5, "changing-to-a-different-commit-or-branch"]], "CMake guide for Key4hep software": [[6, "cmake-guide-for-key4hep-software"]], "Overview": [[6, "overview"], [7, "overview"]], "Quick start into building Key4hep Software": [[6, "quick-start-into-building-key4hep-software"]], "Set up the environment": [[6, "set-up-the-environment"]], "Running CMake": [[6, "running-cmake"]], "Using your local installation": [[6, "using-your-local-installation"]], "CMake example packages": [[6, "cmake-example-packages"]], "Changing the CMake Configuration": [[6, "changing-the-cmake-configuration"]], "Runtime Environment": [[6, "runtime-environment"]], "CTest in Key4hep": [[6, "ctest-in-key4hep"]], "Customizing how CMake is run": [[6, "customizing-how-cmake-is-run"]], "Github workflow and contribution guide": [[7, "github-workflow-and-contribution-guide"]], "First time setup of git": [[7, "first-time-setup-of-git"]], "Generate and set up ssh keys for github": [[7, "generate-and-set-up-ssh-keys-for-github"]], "Improving your git experience": [[7, "improving-your-git-experience"]], "Development workflow": [[7, "development-workflow"]], "Keeping your local repository up to date": [[7, "keeping-your-local-repository-up-to-date"]], "Contributing code": [[7, "contributing-code"]], "Recommendations": [[7, "recommendations"]], "General recommendations": [[7, "general-recommendations"]], "Commit comments": [[7, "commit-comments"]], "Cleaning history": [[7, "cleaning-history"]], "Pull requests": [[7, "pull-requests"]], "Trouble-shooting": [[7, "trouble-shooting"]], "When I try to push to the repository, I get an authentication error": [[7, "when-i-try-to-push-to-the-repository-i-get-an-authentication-error"]], "I have cloned with https and now I can\u2019t push my changes, what do I do?": [[7, "i-have-cloned-with-https-and-now-i-can-t-push-my-changes-what-do-i-do"]], "Need help?": [[7, "need-help"]], "Developing Key4hep": [[8, "developing-key4hep"]], "Contents:": [[8, null], [18, null], [20, null]], "Developing a single package": [[9, "developing-a-single-package"], [10, "developing-a-single-package"]], "Building Key4hep using Spack: For Developers": [[10, "building-key4hep-using-spack-for-developers"]], "Spack set up": [[10, "spack-set-up"]], "Installing a local version with dev-build": [[10, "installing-a-local-version-with-dev-build"]], "Using the local version as dependency": [[10, "using-the-local-version-as-dependency"]], "More advanced usage": [[10, "more-advanced-usage"]], "Developing multiple packages or dependencies of other packages": [[10, "developing-multiple-packages-or-dependencies-of-other-packages"]], "Using an environment to setup all dependencies": [[10, "using-an-environment-to-setup-all-dependencies"]], "Environments and a development workflow": [[10, "environments-and-a-development-workflow"]], "Adding another package to develop": [[10, "adding-another-package-to-develop"]], "Writing Gaudi Algorithms": [[11, "writing-gaudi-algorithms"]], "Gaudi": [[11, "gaudi"]], "Gaudi::Functional": [[11, "gaudi-functional"]], "Setup": [[11, "setup"], [31, "setup"]], "Walkthrough of Functional Algorithms": [[11, "walkthrough-of-functional-algorithms"]], "The steering file": [[11, "the-steering-file"]], "Initialize and finalize": [[11, "initialize-and-finalize"]], "Debugging: How to use GDB": [[11, "debugging-how-to-use-gdb"]], "Avoiding const in operator()": [[11, "avoiding-const-in-operator"]], "Key4hep How-Tos and Instructions": [[12, "key4hep-how-tos-and-instructions"]], "Contents": [[12, null]], "Standalone conversion from LCIO to EDM4hep": [[13, "standalone-conversion-from-lcio-to-edm4hep"]], "Patching missing collections on the fly": [[13, "patching-missing-collections-on-the-fly"]], "Example:": [[13, "example"]], "Converting LCRelation collections": [[13, "converting-lcrelation-collections"]], "Converting only a subset of collections": [[13, "converting-only-a-subset-of-collections"]], "Renaming collections on the fly": [[13, "renaming-collections-on-the-fly"]], "Library usage of the conversion functions": [[13, "library-usage-of-the-conversion-functions"]], "Converting collection (data)": [[13, "converting-collection-data"]], "Handling relations": [[13, "handling-relations"]], "Handling of subset collections": [[13, "handling-of-subset-collections"]], "Handling of LCRelations": [[13, "handling-of-lcrelations"]], "Converting entire events": [[13, "converting-entire-events"]], "Converting Event parameters": [[13, "converting-event-parameters"]], "Subtle differences between LCIO and EDM4hep": [[13, "subtle-differences-between-lcio-and-edm4hep"]], "Example for a ReconstructedParticle Collection": [[13, "example-for-a-reconstructedparticle-collection"]], "Reading and writing EDM4hep files in Gaudi": [[14, "reading-and-writing-edm4hep-files-in-gaudi"]], "The k4DataSvc": [[14, "the-k4datasvc"]], "Reading events": [[14, "reading-events"]], "Writing events": [[14, "writing-events"]], "Writing only a subset of collections": [[14, "writing-only-a-subset-of-collections"]], "Adding custom arguments to k4run": [[15, "adding-custom-arguments-to-k4run"]], "Wrapping Marlin processors in Gaudi": [[16, "wrapping-marlin-processors-in-gaudi"]], "The MarlinProcessorWrapper Gaudi algorithm": [[16, "the-marlinprocessorwrapper-gaudi-algorithm"]], "Reading and writing LCIO events with Gaudi": [[16, "reading-and-writing-lcio-events-with-gaudi"]], "Automatic conversion of Marlin XML steering files": [[16, "automatic-conversion-of-marlin-xml-steering-files"]], "Limitations": [[16, "limitations"]], "Using the EDM converters": [[16, "using-the-edm-converters"]], "Configuration options": [[16, "configuration-options"]], "EDM4hep - The common event data model": [[17, "edm4hep-the-common-event-data-model"]], "Important resources": [[17, "important-resources"]], "Doxygen API documentation": [[17, "doxygen-api-documentation"]], "The overview diagram": [[17, "the-overview-diagram"]], "Relations": [[17, "relations"]], "Associations": [[17, "associations"]], "The table of available types": [[17, "the-table-of-available-types"]], "Navigating the doxygen reference page": [[17, "navigating-the-doxygen-reference-page"]], "Why are there so many classes and do I need all of them?": [[17, "why-are-there-so-many-classes-and-do-i-need-all-of-them"]], "Some utility functionality": [[17, "some-utility-functionality"]], "podio - The technical infrastructure on which things run": [[17, "podio-the-technical-infrastructure-on-which-things-run"]], "podio code generation": [[17, "podio-code-generation"]], "The three layers of podio": [[17, "the-three-layers-of-podio"]], "Basics of generated code - value semantics": [[17, "basics-of-generated-code-value-semantics"]], "Guessing the interface from the yaml definition": [[17, "guessing-the-interface-from-the-yaml-definition"]], "Why is there a XYZ and a MutableXYX?": [[17, "why-is-there-a-xyz-and-a-mutablexyx"]], "Writing function interfaces": [[17, "writing-function-interfaces"]], "Subset collections": [[17, "subset-collections"]], "The podio::Frame container": [[17, "the-podio-frame-container"]], "Getting collections from a Frame": [[17, "getting-collections-from-a-frame"]], "Putting a collection into a Frame": [[17, "putting-a-collection-into-a-frame"]], "Reading EDM4hep files": [[17, "reading-edm4hep-files"]], "The available low level readers": [[17, "the-available-low-level-readers"]], "ROOT file layout of podio generated EDMs": [[17, "root-file-layout-of-podio-generated-edms"]], "How do I figure out if a file is legacy?": [[17, "how-do-i-figure-out-if-a-file-is-legacy"]], "podio-dump": [[17, "podio-dump"]], "Key4hep": [[18, "key4hep"]], "External links:": [[18, null]], "Getting started with Key4hep software": [[19, "getting-started-with-key4hep-software"]], "Setting up the Key4hep Software Stack": [[19, "setting-up-the-key4hep-software-stack"]], "Using a central installation on cvmfs": [[19, "using-a-central-installation-on-cvmfs"]], "Building Key4hep: For Librarians": [[20, "building-key4hep-for-librarians"]], "Spack Usage and Further Technical Topics": [[21, "spack-usage-and-further-technical-topics"]], "Checking which packages will be newly installed": [[21, "checking-which-packages-will-be-newly-installed"]], "Requiring certain variants globally": [[21, "requiring-certain-variants-globally"]], "System Dependencies": [[21, "system-dependencies"]], "Target Architectures": [[21, "target-architectures"]], "Bundle Packages and Environments": [[21, "bundle-packages-and-environments"]], "Setting Up Runtime Environments": [[21, "setting-up-runtime-environments"]], "Compiler Dependencies and Data Packages": [[21, "compiler-dependencies-and-data-packages"]], "Duplicating Recipes in Downstream Repositories": [[21, "duplicating-recipes-in-downstream-repositories"]], "CVMFS Installation Workflow": [[21, "cvmfs-installation-workflow"]], "Compiler Wrappers": [[21, "compiler-wrappers"]], "Spack-Installed LCG releases": [[21, "spack-installed-lcg-releases"]], "Using Spack-installed GCC": [[21, "using-spack-installed-gcc"]], "Spack Buildcaches": [[22, "spack-buildcaches"]], "Nightly Builds with Spack": [[23, "nightly-builds-with-spack"]], "Usage of the nightly builds on CVMFS": [[23, "usage-of-the-nightly-builds-on-cvmfs"]], "Technical Information": [[23, "technical-information"]], "Setting up Spack": [[24, "setting-up-spack"]], "Downloading a spack instance": [[24, "downloading-a-spack-instance"]], "Using Spack Environments": [[24, "using-spack-environments"]], "Using the key4hep-release-user environment": [[24, "using-the-key4hep-release-user-environment"]], "Configuring Spack": [[24, "configuring-spack"]], "Installing Spack": [[24, "installing-spack"]], "Installing the key4hep package recipes": [[24, "installing-the-key4hep-package-recipes"]], "Configuring packages.yaml": [[24, "configuring-packages-yaml"]], "Configuring upstreams.yaml": [[24, "configuring-upstreams-yaml"]], "Setting up additional compilers": [[24, "setting-up-additional-compilers"]], "Talks and Presentations": [[25, "talks-and-presentations"]], "Key4hep Tutorials": [[26, "key4hep-tutorials"]], "Exercises": [[26, null]], "Running an Event Display with EDM4hep or LCIO input": [[27, "running-an-event-display-with-edm4hep-or-lcio-input"]], "Setting up an environment": [[27, "setting-up-an-environment"]], "Creating an input file": [[27, "creating-an-input-file"]], "Running the event display": [[27, "running-the-event-display"]], "Details": [[27, "details"]], "Troubleshooting / Using other detectors": [[27, "troubleshooting-using-other-detectors"]], "Using the Key4hep-Stack for CLIC Simulation and Reconstruction": [[28, "using-the-key4hep-stack-for-clic-simulation-and-reconstruction"]], "Simulation": [[28, "simulation"]], "Reconstruction": [[28, "reconstruction"], [31, "reconstruction"]], "Reconstruction with Marlin": [[28, "reconstruction-with-marlin"]], "Reconstruction with Gaudi through k4MarlinWrapper": [[28, "reconstruction-with-gaudi-through-k4marlinwrapper"]], "Reconstruction with LCIO input": [[28, "reconstruction-with-lcio-input"]], "Reconstruction with EDM4hep input": [[28, "reconstruction-with-edm4hep-input"]], "DD4hep Geometry Information": [[28, "dd4hep-geometry-information"]], "How to run multithreading with k4MarlinWrapper (Gaudi)": [[29, "how-to-run-multithreading-with-k4marlinwrapper-gaudi"]], "Running Gaudi with multithreading support": [[29, "running-gaudi-with-multithreading-support"]], "How to run with inter-event parallelism": [[29, "how-to-run-with-inter-event-parallelism"]], "Running example": [[29, "running-example"]], "Running Delphes fast simulation with EDM4hep output": [[30, "running-delphes-fast-simulation-with-edm4hep-output"]], "Setup and prerequisites": [[30, "setup-and-prerequisites"]], "Standalone executables": [[30, "standalone-executables"]], "Other standalone executables": [[30, "other-standalone-executables"]], "Usage in the Key4hep framework": [[30, "usage-in-the-key4hep-framework"]], "Running ILD simulation and reconstruction": [[31, "running-ild-simulation-and-reconstruction"]], "Running the simulation": [[31, "running-the-simulation"]], "Using ILDReconstruction.py from ILDConfig": [[31, "using-ildreconstruction-py-from-ildconfig"]], "Creating a Gaudi options file": [[31, "creating-a-gaudi-options-file"]], "Adapting the options file for EDM4hep": [[31, "adapting-the-options-file-for-edm4hep"]], "Running the reconstruction with k4run": [[31, "running-the-reconstruction-with-k4run"]]}, "indexentries": {}})
\ No newline at end of file
diff --git a/setup-and-getting-started/README.html b/setup-and-getting-started/README.html
new file mode 100644
index 0000000..db6e207
--- /dev/null
+++ b/setup-and-getting-started/README.html
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+ Two builds with the key4hep stack are distributed on cvmfs. The releases happen +every few months on demand (for example, if there is a new important feature or +a breaking change) and at the moment Ubuntu22.04 and AlmaLinux9 (EL9, +RockyLinux9) are supported. We also have older releases for CentOS7 but are not +making any new builds for that.
+source /cvmfs/sw.hsf.org/key4hep/setup.sh
+
In addition, nightly builds for AlmaLinux 9 and Ubuntu 22.04 with the latest +version of most of the packages are available:
+source /cvmfs/sw-nightlies.hsf.org/key4hep/setup.sh
+
The setup.sh
script always points to the latest build and it will change
+without warning. However, after sourcing the script some information will be
+displayed with instructions on how to reproduce the current environment.
+Nightly builds are intended for development and testing and they will be
+deleted after some time from /cvmfs
. They will also introduce new features
+unannounced, so don’t use these for anything else than development!
Key4hep comprises a fairly large number of software and depends on even more externals, so some tooling is needed to efficiently build the whole software stack. The spack package manager can be used to build scientific software at scale, and is part of the Key4hep software R&D program.
+A spack install of Key4hep is regularly deployed to /cvmfs/sw.hsf.org/
, and can be used on lxplus/centos7 just by sourcing the following setup script:
source /cvmfs/sw.hsf.org/key4hep/setup.sh
+
In this page, the workflow to create this installation is documented.
+This page collects a few known workarounds for issues and areas of development in spack.
+Check also the issues in key4hep-spack for up-to-date information.
+Additionally, we also provide a few more advanced invocations of spack
commands that allow a certain degree of debugging of the decisions spack has made when installing a given package and its dependencies.
When installing a package it might be interesting to estimate how long it will take to do so.
+An important proxy for this is how many and which dependencies spack will install in order to build a package.
+This can be done with the spack solve
command, which invokes the concretizer and then spits out the solution that would be installed if the same arguments were passed to spack install
, e.g.
spack solve -I
+
==> Best of 12 considered solutions.
+==> Optimization Criteria:
+ Priority Criterion Installed ToBuild
+ 1 number of input specs not concretized - 0
+ 2 number of packages to build (vs. reuse) - 4
+ 3 requirement weight 0 0
+ 4 deprecated versions used 1 0
+ 5 version weight 0 0
+ 6 number of non-default variants (roots) 0 0
+ 7 preferred providers for roots 0 0
+ 8 default values of variants not being used (roots) 0 0
+ 9 number of non-default variants (non-roots) 3 0
+ 10 preferred providers (non-roots) 0 0
+ 11 compiler mismatches 0 0
+ 12 OS mismatches 0 0
+ 13 non-preferred OS's 0 0
+ 14 version badness 156 0
+ 15 default values of variants not being used (non-roots) 1 0
+ 16 non-preferred compilers 0 0
+ 17 target mismatches 0 0
+ 18 non-preferred targets 165 44
+
+ - whizard@3.0.3%gcc@10.3.0~fastjet~latex~lcio~lhapdf~openloops~openmp+pythia8 hepmc=3 arch=linux-ubuntu20.04-x86_64
+[+] ^hepmc3@3.2.4%gcc@10.3.0~interfaces~ipo~python~rootio build_type=RelWithDebInfo arch=linux-ubuntu20.04-x86_64
+[+] ^cmake@3.16.3%gcc@10.3.0~doc+ncurses+ownlibs~qt build_type=RelWithDebInfo patches=1c54004,bf695e3 arch=linux-ubuntu20.04-x86_64
+ - ^libtirpc@1.2.6%gcc@10.3.0 arch=linux-ubuntu20.04-x86_64
+ - ^krb5@1.19.3%gcc@10.3.0+shared arch=linux-ubuntu20.04-x86_64
+[+] ^bison@3.8.2%gcc@10.3.0 arch=linux-ubuntu20.04-x86_64
+[+] ^diffutils@3.8%gcc@10.3.0 arch=linux-ubuntu20.04-x86_64
+[+] ^libiconv@1.16%gcc@10.3.0 libs=shared,static arch=linux-ubuntu20.04-x86_64
+[+] ^m4@1.4.18%gcc@10.3.0+sigsegv patches=3877ab5,fc9b616 arch=linux-ubuntu20.04-x86_64
+[+] ^perl@5.30.0%gcc@10.3.0~cpanm+shared+threads arch=linux-ubuntu20.04-x86_64
+[+] ^gettext@0.21%gcc@10.3.0+bzip2+curses+git~libunistring+libxml2+tar+xz arch=linux-ubuntu20.04-x86_64
+[+] ^bzip2@1.0.8%gcc@10.3.0~debug~pic+shared arch=linux-ubuntu20.04-x86_64
+[+] ^libxml2@2.9.13%gcc@10.3.0~python arch=linux-ubuntu20.04-x86_64
+[+] ^pkgconf@1.8.0%gcc@10.3.0 arch=linux-ubuntu20.04-x86_64
+[+] ^xz@5.2.5%gcc@10.3.0~pic libs=shared,static arch=linux-ubuntu20.04-x86_64
+[+] ^zlib@1.2.12%gcc@10.3.0+optimize+pic+shared patches=0d38234 arch=linux-ubuntu20.04-x86_64
+[+] ^ncurses@6.2%gcc@10.3.0~symlinks+termlib abi=none arch=linux-ubuntu20.04-x86_64
+[+] ^tar@1.30%gcc@10.3.0 zip=pigz arch=linux-ubuntu20.04-x86_64
+[+] ^openssl@1.1.1f%gcc@10.3.0~docs~shared certs=mozilla arch=linux-ubuntu20.04-x86_64
+ - ^ocaml@4.13.1%gcc@10.3.0+force-safe-string arch=linux-ubuntu20.04-x86_64
+[+] ^pythia8@8.306%gcc@10.3.0~evtgen~fastjet~hdf5+hepmc+hepmc3~lhapdf~madgraph5amc~mpich~openmpi~python~rivet~root+shared arch=linux-ubuntu20.04-x86_64
+[+] ^hepmc@2.06.11%gcc@10.3.0~ipo build_type=RelWithDebInfo length=MM momentum=GEV arch=linux-ubuntu20.04-x86_64
+[+] ^rsync@3.1.3%gcc@10.3.0 arch=linux-ubuntu20.04-x86_64
+
The -I
flag shows which packages are alrady installed.
+spack solve
also shows some information about all the things that were considered during concretization. It can also be used to dump more information on the concretization process.
+Unfortunately, this information is rather hard to parse, and still a work in progress from the spack developers.
spack can be configured using some configuration
+files. Specifically
+using packages.yaml
which is read from the user directory, i.e. ~/.spack
(or
+/.spack/linux
) can be used to enforce the value of certain default variants
+globally. To solve the above problem it is enough to put the following into
+packages.yaml
:
packages:
+ all:
+ variants: cxxstd=17
+
It is still possible to override this for certain packages either by
+individually configuring them in packages.yaml
or via the command line which
+take precedence over all configuration files.
In the Key4hep software stack build recipes for releases, we use the same mechanism, as this configuration is also available from spack environments.
+Some spack packages have external find support. For these packages it is possible to let spack detect the variants and versions for system (or otherwise) installed packages.
+For such cases use the spack external find
command. It has to be noted that detecting external packages and using them does not always work perfectly.
Since HEP software is usually deployed on a variety of machines via cvmfs, installations need to pick a target architecture. broadwell
is for now the default choice, and can be set with:
packages:
+ all:
+ target: [broadwell]
+
in $HOME/.spack/linux/packages.yaml
Right now, key4hep is installed via a BundlePackage
, that depends on all other relevant packages.
+An alternative would be to use spack environments. This alternative is still under investigation.
The simplest way to set the environment to use spack installed packages is to use the spack load
command.
+In order for users not to have to set up spack when it is not needed, the key4hep-stack
bundle package includes a script that will automatically generate a bash setup script and install it into its prefix.
Spack can also create “filesystem views” of several packages, resulting in a directory structure similar what you would find in /usr/local
.
+This simplifies library and include paths, but the setup generation for views still has to be developed.
Some HEP packages (like geant4-data
) consist only of data files, and can thus be used on any platform.
+Spack cannot yet handle this gracefully, but an ongoing development tries to treat compilers as dependencies, which would help with re-using data packages.
Although it is possible to “patch” spack build recipes by overriding them in another repository (key4hep-spack, for example), this is discouraged. +The central repo is one of the strenghts of spack, with many contributors ensuring that packages build smoothly. +Also, packages are installed in different namespaces, so it is not possible to deprecate changed recipes and use the upstream ones without re-installing the packages.
+The distribution on cvmfs is an exact copy of the spack installation on the build machine, just copied with this rsync command on the publisher:
+rsync -axv --inplace --delete --verbose -e "ssh -T -o Compression=no -o StrictHostKeyChecking=no -o GSSAPIAuthentication=yes -o GSSAPITrustDNS=yes" user@build-machine:/cvmfs/sw.hsf.org/spackages/ /cvmfs/sw.hsf.org/spackages/
+
The --delete
option can be omitted in order to preserve already installed packages, regardless of the state of the build machine.
Spack uses compiler wrappers instead of exposing the actual compilers during the build.
+For packages like whizard, which register the compiler path to use during runtime, this will not work, as the wrappers are not available at runtime.
+For these packages, the current workaround is to force spack to use the actual compilers during build (see the build recipe of whizard
).
A spack installation that contains all packages in the LCG releases is work in progress, see https://gitlab.cern.ch/sft/sft-spack-repo.
+When installing gcc with spack, it is necessary to add a cc
symlink to $PATH
, in order to avoid errors with cling, see https://github.com/spack/spack/issues/17488.
{% callout “Spack documentation” %}
+Buildcaches were investigated, but are no longer supported for Key4hep software, due to the difficulty of relocating some packages.
+For more information refer to the spack documentation.
+{% endcallout %}
+It is possible to relocate and re-use binaries with the so-called buildcache.
+Some central buildcaches are on the key4hep eos
space under:
/eos/project/k/key4hep/www/key4hep/spack_build/mirror/spackages
+
spackages
is intended as the central buildcache for key4hep packages built from scratch,
+but there exist other buildcaches for packages built against the LCG releases, and rolling builds that are using the branchname master
or other moving targets.
+All packages versioned package@master
are treated by spack as the same version, even if master points to different commits, thus they must be installed to separate directories, ideally indicating the date.
+A buildcache called contrib
is intended for build tools such as compilers.
+Spack automatically creates subdirectory for different platforms and compiler versions.
For write permissions to this space, subscribe to the egroup cernbox-project-key4hep-writers
.
The following command can be used to put packages into the buildcache:
+# key4hep-stack was already installed with 'spack install key4hep-stack'
+spack mirror add key4hep /eos/project/k/key4hep/www/key4hep/spack_build/mirror/spackages
+spack buildcache create -m key4hep -u -a -f key4hep-stack
+
Since the packages need to be relocated as well as copied, this might take up to an hour.
+In order to install packages from the buildcache, use:
+spack buildcache install -u -a key4hep-stack
+
Spack will then search all added mirrors for key4hep-stack
.
+For read-only access on machines without eos
, these files are served also over http:
spack mirror add key4hep-web http://key4hep.web.cern.ch/key4hep/spack_build/mirror/spackages/
+
For Centos7, the latest nightly build can be set up by running:
+source /cvmfs/sw-nightlies.hsf.org/key4hep/setup.sh
+
Spack can also be configured to use /cvmfs/sw-nightlies.hsf.org/spackages
as an upstream installation.
Nightly builds can be a very useful tool, both to test code correctness and to quickly and automatically deploy the latest developments. +In contrast to the release builds, which use the latest stable version of the individual packages, nightly builds typically use the HEAD of the main development branch.
+It is not very efficient to completely rebuild the stack every day, as some packages change fairly infrequently. +The key4hep-spack repository includes some scripts in order to use commit hashes as versions.
+Spack is easy to set up: simply clone the key4hep fork, and use one of the provided spack “environments”, that is spack configuration that is created automatically from the current key4hep/key4hep-spack repository.
+git clone https://github.com/spack/spack
+git clone https://github.com/key4hep/key4hep-spack
+source spack/share/spack/setup-env.sh
+source key4hep-spack/environments/key4hep-release-user/setup_clingo_centos7.sh # NOTE: only needed on centos7
+spack env activate key4hep-spack/environments/key4hep-release-user # or other environment, see below
+
These instructions assume that a Centos7 machine with a running CVMFS client is used (for other OSs see below). Since Spack cannot bootstrap with the system compiler on Centos7, a setup script for Clingo ( a spack dependency ) is provided.
+The spack environments available in key4hep-spack/environments
bundle the spack configuration, setting up a suitable compiler from cvmfs, the key4hep package recipes, whether to create a view, etc. It is recommended to always use spack in an environment. New environments can be easily created by copying and modifying existing ones, but some use relative links to common configuration files in key4hep-spack/environments/key4hep-common
, so they should be kept in the key4hep/environments
directory.
The basic environment is key4hep-release
, which is used for the central installations and therefore uses /cvmfs
as install area. key4hep-debug
is a variation for debug builds. The default compiler is gcc, but an environment that uses clang is provided under key4hep-release-clang
.
+For local builds that use cvmfs read-only, key4hep-release-user
can be used.
The key4hep user environment has the key4hep-stack
bundle package in its spec list. By concretizing it, spack selects the latest compatible versions, re-using installations from cvmfs
spack concretize -f
+spack find # lists the available concretized packages
+
The environment can be installed as is, although this will just install the bundle packages. However, this will create a setup script that can be used to load the software.
+spack install
+
Custom builds can now be realized, by adding specs to the environment and concretizing together. For example, to build the stack with a local version of EDM4hep:
+spack add edm4hep@master
+git clone https://github.com/key4hep/edm4hep
+# make some local changes to edm4hep
+spack develop -p $PWD/edm4hep edm4hep@master
+spack concretize -f
+spack install
+
+
Alternatively, and for other platforms, spack can be configured in a few steps. These steps are essentially what is used to create the pre-configured spack instance in this script: https://github.com/key4hep/key4hep-spack/blob/master/scripts/ci_setup_spack.sh
+While this still puts the configuration files in the global scope of spack, it is recommended to use them in an environment, as provided by key4hep-spack.
+Spack itself is very easy to install - simply clone the repository with git.
+git clone https://github.com/spack/spack.git
+source spack/share/spack/setup-env.sh
+
The spack repository for key4hep packages is installed the same way:
+git clone https://github.com/key4hep/key4hep-spack.git
+spack repo add key4hep-spack
+
packages.yaml
In order to choose the right package versions and build options, spack sometimes needs a few hints and nudges. With the new concretizer (default as of spack version 0.17) this should be mostly obsolete. +key4hep-spack ships a spack config file that should give a good build customization out of the box, but can also be customized further. It just needs to be copied to the configuration where spack searches for configurations:
+cp key4hep-spack/environments/key4hep-common/packages.yaml spack/etc/spack/
+
upstreams.yaml
The cvmfs installation can be used as an “upstream installation”, by adding the following configuration:
+cat <<EOT >> spack/etc/spack/upstreams.yaml
+upstreams:
+ spack-instance-1:
+ install_tree: /cvmfs/sw.hsf.org/spackages6/
+EOT
+
Often it is practical to use a compiler already installed upstream. Spack provides the spack compiler find
command for this, but the compiler needs to be loaded into the PATH:
# loading the compiler from upstream
+source /cvmfs/sft.cern.ch/lcg/contrib/gcc/11.2.0/x86_64-centos7/setup.sh
+spack compiler find --scope site
+
A Zotero group with the items listed below can be found here.
+Carceller, Juan Miguel, Spack in Key4hep presented at the HSF Software +Developer Tools & Packaging Working Group July 11, 20 +https://indico.cern.ch/event/1301872/contributions/5474076/attachments/2682457/4653446/carceller_key4hep_spack_2023.pdf
Carceller, Juan Miguel, key4hep Update presented at the CERN EP R&D: Software meeting, June +21, 2023, +https://indico.cern.ch/event/1253565/contributions/5265910/attachments/2591081/4628747/carceller_key4hep_20230621.pdf
Volkl, Valentin, Status of the key4hep Software Development presented at +IAS Program on High Energy Physics (HEP 2021), January 20, 2021, +https://indico.cern.ch/event/971970/timetable/#153-3-status-of-the-key4hep-so
Madlener, Thomas. Key4HEP - Turnkey Software for Future Colliders +presented at the XXVII Cracow EPIPHANY Conference on Future of particle +physics, January 10, 2021. +https://indico.cern.ch/event/934666/contributions/4154229/attachments/2168411/3660367/key4hep_epiphany2021_cracow.pdf
Helsens, Clement, FCC software for physics and detector studies +presented at the XXVII Cracow EPIPHANY Conference on Future of particle +physics, January 10, 2021. +https://indico.cern.ch/event/934666/contributions/4154228/
Ganis, Gerardo. “The Turnkey Software Stack: Where Are We and Where We +Want to Go.” presented at the IAS HEP 2020, January 17, 2020. +http://ias.ust.hk/program/shared_doc/2020/202001hep/workshop/exp/20200117_1038_am_Gerri_GANIS.pdf.
Sailer, André. “Key4HEP: Turnkey Software for Future Collider +Experiments.” presented at the Joint Workshop on Future Charm–Tau Factory, +September 24, 2019. +https://rich2018.org/indico/event/3/contributions/180/attachments/151/247/190924_sailer_software.pdf.
Sailer, André. “Towards a Turnkey Software Stack for HEP Experiments.” +presented at the International Conference on Computing in High Energy & +Nuclear Physics 2019, September 5, 2019. +https://indico.cern.ch/event/773049/contributions/3474763/attachments/1938664/3213633/191105_sailer_key4hep.pdf.
Mato, Pere. “Key4HEP: The Common Turnkey Software Stack.” presented at +the CLICdp Collaboration Meeting, August 28, 2019. +https://indico.cern.ch/event/792656/contributions/3536473/attachments/1898480/3132881/Key4HEP_CLICdp_Meeting.pdf.
This page contains several tutorials for working in a Key4hep software stack. We +try to design and set them up in a way that they can be done at any time but we +present them at hands-on tutorial sessions as well. This is an incomplete list +of all available tutorials, which you can find in the +key4hep-tutorials repository.
+If you are following these tutorials and run into an issue please let us know
+by opening an issue
+on the key4hep-doc
repository. If
+you have the feeling that something is missing, we are also very happy to accept
+new tutorial suggestions. If you have a tutorial that you would like to add
+here.
It is possible to run the C Event Display (CED) via a wrapped CEDViewer Marlin Processor. This makes it possible to run the Event Display with EDM4hep input files using an on the fly conversion to LCIO for CED. This introduction shows the basic concepts and also provides a options file that should work for most use cases. This example will be using the CLIC detector but should also work for other DD4hep detector models. The example is fully self contained, if you already have everything set up you can jump directly to running the event display.
+The following steps have been tested with the Key4hep nightly builds release which can be setup using
+source /cvmfs/sw-nightlies.hsf.org/key4hep/setup.sh
+
To get the CLIC detector description we clone the CLICPerformance
repository
git clone https://github.com/iLCSoft/CLICPerformance
+
All the following steps assume that the environment is setup like above and that the detector description is in the CLICPerformance
directory. All commands start from the directory from which git clone
has been executed.
To create an input file for the event display we run a simple detector simulation using ddsim
and a particle gun that shoots photons. The input file that we create here for illustration purposes has only 10 events, which also means that the creation should only take a few minutes. The steps to create this file are the following
ddsim --steeringFile CLICPerformance/clicConfig/clic_steer.py \
+ --compactFile $K4GEO/CLIC/compact/CLIC_o3_v14/CLIC_o3_v14.xml \
+ --enableGun \
+ --gun.distribution uniform \
+ --gun.particle gamma \
+ --gun.energy 10*GeV \
+ --outputFile gamma_10GeV_edm4hep.root \
+ --numberOfEvents 10
+
You should now have a gamma_10GeV_edm4hep.root
file containing 10 events.
In order to run the event display via the DDCEDViewer
we use the Marlin wrapper. Here we simply present the most important steps, but do not go over all details of the DDCEDViewer
configuration, for that it is probably best to directly look at the CEDViewer repository directly. The complete Gaudi configuration can be found in k4MarlinWrapper/examples/event_display.py
which is also installed at $K4MARLINWRAPPER/examples/event_display.py
In order to run the event display we first have to start the glced
server program to which the wrapped CEDViewer
processor will then connect. Starting the server and running the wrapped processor can be done via
glced &
+
+k4run $K4MARLINWRAPPER/examples/event_display.py --inputFiles=gamma_10GeV_edm4hep.root
+
If you want to run the event display for a different geometry you can do so with the --compactFile
argument. However, depending on your detector model you might also need to change some of the DDCEDViewer
parameters. The default compact file is "CLICPerformance/Visualisation/CLIC_o3_v06_CED/CLIC_o3_v06_CED.xml"
.
The main work is done by the DDCEDViewer
, which we use via the MarlinProcessorWrapper
. It is the following part of example event_display.py
.
from Configurables import MarlinProcessorWrapper
+
+MyCEDViewer = MarlinProcessorWrapper("MyCEDViewer")
+MyCEDViewer.ProcessorType = "DDCEDViewer"
+MyCEDViewer.Parameters = {
+ # ... lots of CEDViewer configuration ...
+ }
+
Some of the more commonly used parameters have self explanatory names.
+When running this for a detector different than CLD, CLIC or ILD (or a derivative of one of them) you might not see anything in the event display.
+If you are not seeing the detector make sure that it has the proper visualisation attributes, e.g. by comparing it to the compact file used above.
+If you are not seeing any hits, tracks etc. from your event, make sure to add their collection names to the DrawInLayer
list in the DDCEDViewer
parameters.
This assumes that you have access to an installation of the Key4hep-stack, either via CVMFS
or spack install
.
+To setup the installation on cvmfs, do:
source /cvmfs/sw.hsf.org/key4hep/setup.sh
+
These commands will explain how one can run the CLIC detector simulation and reconstruction using the Key4hep-Stack.
+First we will obtain all the necessary steering and input files for CLIC, simulate a few events and run the
+reconstruction both with Marlin
and k4run
. These steps can be adapted to simulate or run other Marlin
+processors as well.
The CLICPerformance
repository contains the steering and input files.
git clone https://github.com/iLCSoft/CLICPerformance
+
Simulating a few events with ddsim
can produce output in EDM4hep or LCIO format.
To produce events in EDM4hep format one can run indicating --outputFile <name>_edm4hep.root
to produce the
+output in such format:
cd CLICPerformance/clicConfig
+
+ddsim --compactFile $K4GEO/CLIC/compact/CLIC_o3_v14/CLIC_o3_v14.xml \
+ --outputFile ttbar_edm4hep.root \
+ --steeringFile clic_steer.py \
+ --inputFiles ../Tests/yyxyev_000.stdhep \
+ --numberOfEvents 3
+
To produce events in LCIO format one can run indicating --outputFile <name>.slcio
to produce the output file
+in such format:
cd CLICPerformance/clicConfig
+
+ddsim --compactFile $K4GEO/CLIC/compact/CLIC_o3_v14/CLIC_o3_v14.xml \
+ --outputFile ttbar.slcio \
+ --steeringFile clic_steer.py \
+ --inputFiles ../Tests/yyxyev_000.stdhep \
+ --numberOfEvents 3
+
To run the reconstruction with Marlin
:
cd CLICPerformance/clicConfig
+
+Marlin clicReconstruction.xml \
+ --InitDD4hep.DD4hepXMLFile=$K4GEO/CLIC/compact/CLIC_o3_v14/CLIC_o3_v14.xml \
+ --global.LCIOInputFiles=ttbar.slcio \
+ --global.MaxRecordNumber=3
+
We can convert the xml
steering file to a Gaudi steering file (python):
cd CLICPerformance/clicConfig
+
+convertMarlinSteeringToGaudi.py clicReconstruction.xml clicReconstruction.py
+
Reconstruction can be performed with LCIO or EDM4hep input, depending on the output format of the events produced +during Simulation.
+When using LCIO format for the input events to be used in reconstruction:
+Modify the clicReconstruction.py
file to point to the ttbar.slcio
input file, and change the
+DD4hepXMLFile
parameter for the InitDD4hep
algorithm. In addition the two processors with the comment # Config.OverlayFalse
and # Config.TrackingConformal
should be enabled by uncommenting their line in the algList
+at the end of the file.
cd CLICPerformance/clicConfig
+
+sed -i '1s/^/import os\n/' clicReconstruction.py
+sed -i 's;read.Files = \[".*"\];read.Files = \["ttbar.slcio"\];' clicReconstruction.py
+sed -i 's;EvtMax = 10,;EvtMax = 3,;' clicReconstruction.py
+sed -i 's;"MaxRecordNumber": ["10"],;"MaxRecordNumber": ["3"],;' clicReconstruction.py
+sed -i 's;# algList.append(OverlayFalse);algList.append(OverlayFalse);' clicReconstruction.py
+sed -i 's;# algList.append(MyConformalTracking);algList.append(MyConformalTracking);' clicReconstruction.py
+sed -i 's;# algList.append(ClonesAndSplitTracksFinder);algList.append(ClonesAndSplitTracksFinder);' clicReconstruction.py
+sed -i 's;# algList.append(RenameCollection);algList.append(RenameCollection);' clicReconstruction.py
+sed -i 's;"DD4hepXMLFile": \[".*"\],; "DD4hepXMLFile": \[os.environ["LCGEO"]+"/CLIC/compact/CLIC_o3_v14/CLIC_o3_v14.xml"\],;' clicReconstruction.py
+
Then the reconstruction using the k4MarlinWrapper can be run with
+cd CLICPerformance/clicConfig
+
+k4run clicReconstruction.py
+
When using EDM4hep format for the input events to be used in reconstruction, refer to the EDM converters +included with k4MarlinWrapper. Note that:
+MarlinProcessorWrappers need input in LCIO format: EDM4hep collections need to be converted to LCIO
The output collections of MarlinProcessorWrappers may be used later by other algorithms:
+Output collections of MarlinProcessorWrappers will be in LCIO format unless these are explicitly converted
Some MarlinProcessorWrappers may modify collections instead of producing new ones: the original EDM4hep collection wont be updated in this case and would need conversion from LCIO to EDM4hep.
To run clicReconstruction with EDM4hep format, use the steering file found in the examples
folder of k4MarlinWrapper:
+k4MarlinWrapper/examples/clicRec_e4h_input.py
(this also gets installed to $K4MARLINWRAPPER/examples
in Key4hep releases)
Change the line where evtsvc.input
is defined to point to the location of your input file.
At the bottom of the file, in the ApplicationMgr
parameters, change EvtMax = 3,
to the number of events to run.
This can be run in the following way.
+cd CLICPerformance/clicConfig
+
+cp $K4MARLINWRAPPER/examples/clicRec_e4h_input.py .
+
+k4run clicRec_e4h_input.py --EventDataSvc.input ttbar_edm4hep.root
+
The MarlinDD4hep::InitializeDD4hep
processor can be replaced by the k4SimGeant4::GeoSvc
and the
+TrackingCellIDEncodingSvc
the latter of which is part of the k4MarlinWrapper repository.
+This requires removing the wrapped InitDD4hep
processor from the algList
and the two new processed be appended to the ExtSvc
argument in the ApplicationMgr
.
We will create another list, svcList
for this.
+In the space following
import os
+from Configurables import k4DataSvc, PodioInput
+evtsvc = k4DataSvc('EventDataSvc')
+evtsvc.input = os.path.join('$TEST_DIR/inputFiles/', os.environ.get("INPUTFILE", "ttbar_edm4hep.root"))
+
we can start the svcList
list and add the GeoSvc
and TrackingCellIDEncodingSvc
with;
svcList = []
+svcList.append(evtsvc)
+
+
+import os
+from Gaudi.Configuration import INFO
+from Configurables import GeoSvc, TrackingCellIDEncodingSvc
+
+geoservice = GeoSvc("GeoSvc")
+geoservice.detectors = [os.environ["K4GEO"]+"/CLIC/compact/CLIC_o3_v15/CLIC_o3_v15.xml"]
+geoservice.OutputLevel = INFO
+geoservice.EnableGeant4Geo = False
+svcList.append(geoservice)
+
+
+cellIDSvc = TrackingCellIDEncodingSvc("CellIDSvc")
+cellIDSvc.EncodingStringParameterName = "GlobalTrackerReadoutID"
+cellIDSvc.GeoSvcName = geoservice.name()
+cellIDSvc.OutputLevel = INFO
+svcList.append(cellIDSvc)
+
Then all that is left is to pass that to the ExtSvc
argument.
+At the bottom of the file:
ApplicationMgr( TopAlg = algList,
+ EvtSel = 'NONE',
+ EvtMax = 3,
+- ExtSvc = [evtsvc],
++ ExtSvc = svcList,
+ OutputLevel=WARNING
+ )
+
Supported
+Reading LCIO events with LcioEvent()
Writing LCIO events with LcioEventOutput()
Running MarlinProcessorWrapper
s with no converters
Using whiteboard
as ExtSvc
(no k4DataSvc or EventDataSvc)
Not supported
+Using EDM converters EDM4hep2LcioTool
and Lcio2EDM4hepTool()
Reading EDM4hep events with PodioInput()
Writing EDM4hep events with PodioOutput()
Writing EDM4hep events with MarlinProcessorWrapper
of type LCIOOutputProcessor
Running non-thread algorithms/processors in parallel
Running wrapped Marlin processors that make use of the isFirstEvent
method in their processEvent
method to do some setup only in the first event. There is no way to make this thread safe. If you want your processor to be usable on in a multi threaded environment, you have to move this setup to init
.
Gaudi uses Intel TBB under the hood for multithreading.
+Gaudi exposes two main levels of parallelism:
+Inter-event parallelism: running multiple events in parallel
Intra-event parallelism: running multiple algorithms in parallel, within an event
The two levels of parallelism can be combined: events can run in parallel, and algorithms within the events can run in parallel.
+The following components are used to achieve parallelism:
+from Configurables import (HiveWhiteBoard, HiveSlimEventLoopMgr, AvalancheSchedulerSvc)
+
These 3 components need to be configured to adapt the level of parallelism to the sequence, algorithms and hardware to be used.
+Event Data Service: HiveWhiteBoard
EventSlots: Number of events that may run in parallel, each with its own EventStore
This is the Event Data Service, which needs the number of EventSlots
Event Loop Manager: HiveSlimEventLoopMgr
Event Loop Manager with parallelism support
Thread Scheduling config: AvalancheSchedulerSvc
Scheduler to indicate the number of threads to use
In needs the total number of threads to use: this determines how many events and algorithms can be in flight (run in parallel)
Default value is -1
which indicate TBB to take over the machine with what it decides to be the optimal configuration
All these components can be set as follows in the options file:
+evtslots = 4
+threads = 4
+
+whiteboard = HiveWhiteBoard("EventDataSvc", EventSlots=evtslots)
+slimeventloopmgr = HiveSlimEventLoopMgr(SchedulerName="AvalancheSchedulerSvc", OutputLevel=DEBUG)
+scheduler = AvalancheSchedulerSvc(ThreadPoolSize=threads, OutputLevel=WARNING)
+
+from Configurables import ApplicationMgr
+ApplicationMgr( TopAlg = [seq],
+ EvtSel = 'NONE',
+ EvtMax = 10,
+ ExtSvc = [whiteboard],
+ EventLoop=slimeventloopmgr,
+ MessageSvcType="InertMessageSvc"
+ )
+
To only run events in parallel, with no parallelism between the algorithms within each event, the cardinality of the algorithms must be set:
+Given a list of algorithms, set the cardinality of all to be 1
Create a GaudiSequencer
with all the algorithms as Members
Set the GaudiSequencer
sequential property to true
Pass the created GaudiSequencer
to the Application Manager in the TopAlg
: TopAlg = [seq]
from Configurables import MarlinProcessorWrapper
+from Configurables import (GaudiSequencer)
+
+cardinality = 1
+
+alg1 = MarlinProcessorWrapper("alg1")
+alg2 = MarlinProcessorWrapper("alg2")
+alg3 = MarlinProcessorWrapper("alg3")
+alg4 = MarlinProcessorWrapper("alg4")
+
+algList = []
+
+algList.append(alg1)
+algList.append(alg2)
+algList.append(alg3)
+algList.append(alg4)
+
+for algo in algList:
+ algo.Cardinality = cardinality
+ algo.OutputLevel = DEBUG
+
+seq = GaudiSequencer(
+ "createViewSeq",
+ Members=algList,
+ Sequential=True,
+ OutputLevel=VERBOSE)
+
+from Configurables import ApplicationMgr
+ApplicationMgr( TopAlg = [seq],
+ EvtSel = 'NONE',
+ EvtMax = 10,
+ ExtSvc = [whiteboard],
+ EventLoop=slimeventloopmgr,
+ MessageSvcType="InertMessageSvc"
+ )
+
A multi-threaded CLIC Reconstruction can be run in multi-threaded mode, for LCIO input and output. +After successful compilation, from the build location:
+# Check available tests
+ctest -N
+
+# Run multi-threaded clicReconstruction test
+ctest -R clicRec_lcio_mt
+
The k4SimDelphes
package provides utilities to convert output from the Delphes fast simulation framework into the EDM4hep format. It offers standalone executables, similar to the ones Delphes offers, as well as integration into the Key4hep framework. Here we will provide examples of how to run the standalone executables as well as the usage in the Key4hep framework.
The following examples assume that you have access to an existing installation of the Key4hep software stack. The easiest way to achieve this to use an existing installation on cvmfs
source /cvmfs/sw.hsf.org/key4hep/setup.sh
+
Alternatively it is possible to build the complete stack via spack
, see the instructions for how to do this.
In order to run the examples below it is necessary to get some inputs that are used for the generation of the physics events. In the following we will be using pythia generator files that are also used by the FCCee. In particular we will be generating the following process
+e+e- -> ZH -> mu+mu- X (i.e. the Z decays into a pair of oppositely charged muons and the H to anything)
+To start we download the pythia cards for this process
+wget https://raw.githubusercontent.com/HEP-FCC/FCC-config/spring2021/FCCee/Generator/Pythia8/p8_noBES_ee_ZH_ecm240.cmd
+
All the other resources are available from within a Key4hep release.
+For this example we will be using the DelphesPythia8_EDM4HEP
standalone executable, which is essentially the same as the DelphesPythia8
executable that is provided by Delphes. Contrary to the Delphes executable the one provided by k4SimDelphes will produce output in the EDM4hep format.
To run the generation and fast detector simulation in one go run
+DelphesPythia8_EDM4HEP ${DELPHES_DIR}/cards/delphes_card_IDEA.tcl \
+ ${K4SIMDELPHES}/edm4hep_output_config.tcl \
+ p8_noBES_ee_ZH_ecm240.cmd \
+ delphes_events_edm4hep.root
+
The arguments in this case are (in the order they are passed)
+The delphes card that describes the (parameterized) detector. In this case we use one that is shipped with the Delphes installation
The output configuration for the Delphes to EDM4hep converter. Here we use the defaults that are provided by k4SimDelphes
, which should cover the majority of use cases. It is however possible to configure these to your needs if necessary.
The pythia card that describes the physics process as described above
The name of the output file that will be created and that will contain the generated and simulated events in EDM4hep format
k4SimDelphes provides other standalone executables that can read different inputs. They offer the same functionality as the ones available from Delphes:
+DelphesSTDHEP_EDM4HEP
- for reading STDHEP inputs
DelphesROOT_EDM4HEP
- for reading ROOT files in the Delphes format
DelphesPythia8_EDM4HEP
- for running Pythia8 as part of the simulation
For all executables it is possible to at least get the order of the input arguments via --help
or -h
, e.g.
DelphesSTDHEP_EDM4HEP --help
+
will print
+Usage: DelphesHepMC config_file output_config_file output_file [input_file(s)]
+config_file - configuration file in Tcl format,
+output_config_file - configuration file steering the content of the edm4hep output in Tcl format,
+output_file - output file in ROOT format,
+input_file(s) - input file(s) in STDHEP format,
+with no input_file, or when input_file is -, read standard input.
+
[ ] TODO
This exercise aims at showing you how to run full simulation as well as
+reconstruction using ddsim
and the Gaudi based Key4hep framework respectively.
+You will
Run ddsim
to produce SIM level input files for the reconstruction in EDM4hep
+format
Learn how to use the tools provided by
+k4MarlinWrapper
that allows to
+run workflows that were originally developed for the Marlin
in the Gaudi
+based framework of Key4hep. This includes
Converting a Marlin steering file to a Gaudi options file,
Adapting the options file to be able to read and write EDM4hep output
Running this Gaudi options file via k4run
In this particular case we are using the ILD configuration to do this but the +conceptual steps are very similar for other detector concepts that used Marlin +originally.
+If you haven’t done it yet, source a Key4hep software environment via
+source /cvmfs/sw.hsf.org/key4hep/setup.sh
+
For the remainder of the tutorial we will assume that you are working within the
+key4hep_tut_ild_reco
directory, i.e.
mkdir key4hep_tut_ild_reco
+cd key4hep_tut_ild_reco
+
However, this is a minor detail and you can choose whatever directory you want. +We do suggest a clean directory though.
+Next we will be using the standard simulation and reconstruction +configuration for ILD which we can get via
+git clone https://github.com/iLCSoft/ILDConfig
+
For the rest of this tutorial we will be working in the
+ILDConfig/StandardConfig/production
folder
cd ILDConfig/StandardConfig/production
+
We will use the output file of the whizard +tutorial +as generator level input. In case you have not done that exercise you can get +one via
+wget https://raw.githubusercontent.com/key4hep/key4hep-tutorials/main/gaudi_ild_reco/input_files/zh_mumu.slcio
+
Simulating a few events with ddsim
is straight forward. ddsim
can produce
+EDM4hep and LCIO format output files, and it decides which format to used based
+on the name of the output file:
Names ending on .slcio
will result in LCIO output files
Names ending in edm4hep.root
will result in in EDM4hep output files
In the course of this exercise we will only need the EDM4hep format, we simply +provide both options for convenience here.
+To run the simulation with EDM4hep output you can use the following command
+ddsim --compactFile $k4geo_DIR/ILD/compact/ILD_l5_v02/ILD_l5_v02.xml \
+ --steeringFile ddsim_steer.py \
+ --inputFiles zh_mumu.slcio \
+ --outputFile zh_mumu_SIM.edm4hep.root
+
To run the simulation with LCIO output you can use the following command
+ddsim --compactFile $k4geo_DIR/ILD/compact/ILD_l5_v02/ILD_l5_v02.xml \
+ --steeringFile ddsim_steer.py \
+ --inputFiles zh_mumu.slcio \
+ --outputFile zh_mumu_SIM.slcio
+
Depending on the machine where you are running this, this will take up to a few +minutes to complete. You can start this and read on in the meantime.
+To run the reconstruction we will use the Gaudi based Key4hep framework. Note
+that we can run the reconstruction just the same as within iLCSoft via Marlin
.
+However, we will not show that in this tutorial.
ILDReconstruction.py
from ILDConfigIn order to run the standard reconstruction simply run the following command
+k4run ILDReconstruction.py \
+ --detectorModel=ILD_l5_o1_v02 \
+ --inputFiles=zh_mumu_SIM.edm4hep.root \
+ --outputFileBase=zh_mumu
+
The ILDReconstruction.py
configuration can handle several different ILD
+detector configurations, so we have to choose one via the --detectorModel
+argument. Make sure that this is compatible to the one that has been used for
+simulation.
This will produce several new output files
+zh_mumu_REC.edm4hep.root
- The output of the reconstruction in EDM4hep
+format
zh_mumu_AIDA.root
- The histograms that were produce by wrapped processors
+using the AIDA interface
zh_mumu_PfoAnalysis.root
- The output file of the Pandora PFO analysis
+processor
ILDReconstruction.py
also supports reading LCIO inputs and will detect this
+automatically from the input file name. It also supports producing LCIO output
+files via the --lcioOutput
flag, which can either be off
(default), on
or
+only
(for not producing any EMD4hep output).
Check the introduction to EDM4hep / +podio +for more details on how to read and analyse this file.
+Warning
+These instructions show you how to convert an existing Marlin steering file to a +Gaudi options file using the full ILD reconstruction as an example since it +exhibits a few of the potential issues that you might run into along the way. +However, we strongly recommend using the existing reconstruction configuration +that is available from +ILDConfig +for actually running the reconstruction. It has more features and also +supports running with different detector models, something that the following +steps will not achieve!.
+The bulk of the work for creating such an options file from an existing Marlin
+steering file in XML format can be done with the
+convertMarlinSteeringToGaudi.py
converter script. We will start by converting
+the MarlinStdReco.xml
steering file and then do some minor adjustments to the
+converted options file. The main thing to consider for the ILD configuration is
+that MarlinStdReco.xml
makes use of several include statements to pull in more
+configuration. Hence, we first have to create a Marlin steering file with these
+includes resolved. We also have to provide a DetectorModel
constant here,
+since some of the includes depend on this.
Marlin -n MarlinStdReco.xml --constant.DetectorModel=ILD_l5_o1_v02
+
You should now have a MarlinStdRecoParsed.xml
file. This is the one that we
+will convert using the converter script via
convertMarlinSteeringToGaudi.py MarlinStdRecoParsed.xml MarlinStdReco.py
+
Since some parts of the Marlin steering file conversion can not be handled
+automatically we have to make a few adjustments to MarlinStdReco.py
. We
+recommend to simply edit the file directly, but you can also use the sed
+commands below to do these adjustments. The adjustments are:
Give the lcgeo_DIR
constant (first entry in the CONSTANTS
dict) a
+meaningful value. The easiest way to do this is to simply get the value of the
+corresponding environment variable via os.environ["lcgeo_DIR"]
(don’t forget
+to import os
at the top)
Exclude the BgOverlayWW
, BgOverlayBB
, BgOverlayBW
, BgOverlayWB
and PairBgOverlay
+algorithms from being run, by simply commenting out the lines where these are
+appended to the algList
(this list is populated at almost the end of the
+file).
sed
commands for adjustmentssed -i '1s/^/import os\n/' MarlinStdReco.py
+sed -i 's/\( *.lcgeo_DIR.:\).*/\1 os.environ["lcgeo_DIR"],'/ MarlinStdReco.py
+sed -i 's/algList.append(BgOverlayWW)/# algList.append(BgOverlayWW)/' MarlinStdReco.py
+sed -i 's/algList.append(BgOverlayWB)/# algList.append(BgOverlayWB)/' MarlinStdReco.py
+sed -i 's/algList.append(BgOverlayBW)/# algList.append(BgOverlayBW)/' MarlinStdReco.py
+sed -i 's/algList.append(BgOverlayBB)/# algList.append(BgOverlayBB)/' MarlinStdReco.py
+sed -i 's/algList.append(PairBgOverlay)/# algList.append(PairBgOverlay)/' MarlinStdReco.py
+
With the state the options file is in now, you would be able to run it with LCIO +input.
+To run the reconstruction with LCIO inputs and outputs we now simply need to +pass in the input file that we have created at the simulation step
+k4run MarlinStdReco.py --LcioEvent.Files=zh_mumu_SIM.slcio
+
This should take somewhere between 20 seconds up to roughly a minute to run. If +you haven’t changed anything else you should now have a few output files:
+ls StandardReco_*.*
+
should now show a REC
and DST
file, as well as a PfoAnalysis
and an AIDA
+file. You can change the names of these files by adjusting the OutputBaseName
,
+resp. The corresponding filename constants values in CONSTANTS
.
It is necessary to adapt the Gaudi options file a bit further:
+Replace the LcioEvent
algorithm with the PodioInput
algorithm
Make sure to replace the Files
option with the collections
option and to
+populate this option with the list of collections you want to read (see
+below)
Replace the EventDataSvc
with the k4DataSvc
(remember to instantiate it
+with "EventDataSvc"
as name)
Add a PodioOutput
algorithm to write EDM4hep output (don’t forget to add it
+to the algList
at the very end)
(For the sake of this exercise) configure this to only write the
+MCParticlesSkimmed
, PandoraPFOs
and the RecoMCTruthLink
collections
Attach the necessary in-memory on-the-fly converters between EDM4hep and LCIO +(and vice versa)
+For the conversion of the EDM4hep inputs to LCIO instantiate a
+EDM4hep2LcioTool
and attach it to the first wrapped processor that is run
+(MyAIDAProcessor
). See detailed description below.
For the conversion of the LCIO outputs to EDM4hep instantiate a
+Lcio2EDM4hepTool
and attach it to the last wrapped processor that is run
+before the PodioOutput
algorithm that you just added (MyPfoAnalysis
).
+Also see below.
For all of these steps make sure that you import
all the necessary tools and
+algorithms from Configurables
!
The top of your file should now look something like this
+from Configurables import (
+ PodioInput, PodioOutput, k4DataSvc, MarlinProcessorWrapper,
+ EDM4hep2LcioTool, Lcio2EDM4hepTool
+ )
+from k4MarlinWrapper.parseConstants import *
+algList = []
+evtsvc = k4DataSvc("EventDataSvc")
+
while the configuration for the input reader and the EDM4hep2LcioTool
should
+look like this
read = PodioInput()
+read.OutputLevel = INFO
+read.collections = [
+ # ... list of collection names
+]
+algList.append(read)
+
+edm4hep2LcioConv = EDM4hep2LcioTool()
+edm4hep2LcioConv.collNameMapping = {
+ "MCParticles": "MCParticle"
+}
+
+# ... Unchanged config of MyAIDAProcessor
+
+MyAIDAProcessor.EDM4hep2LcioTool = edm4hep2LcioConv
+
The list of collections that is populated by standard configuration of ILD for +simulation looks like this. You can simply copy this into the options file
+read.collections = [
+ "BeamCalCollection",
+ "BeamCalCollectionContributions",
+ "ECalBarrelScHitsEven",
+ "ECalBarrelScHitsEvenContributions",
+ "ECalBarrelScHitsOdd",
+ "ECalBarrelScHitsOddContributions",
+ "ECalBarrelSiHitsEven",
+ "ECalBarrelSiHitsEvenContributions",
+ "ECalBarrelSiHitsOdd",
+ "ECalBarrelSiHitsOddContributions",
+ "EcalEndcapRingCollection",
+ "EcalEndcapRingCollectionContributions",
+ "ECalEndcapScHitsEven",
+ "ECalEndcapScHitsEvenContributions",
+ "ECalEndcapScHitsOdd",
+ "ECalEndcapScHitsOddContributions",
+ "ECalEndcapSiHitsEven",
+ "ECalEndcapSiHitsEvenContributions",
+ "ECalEndcapSiHitsOdd",
+ "ECalEndcapSiHitsOddContributions",
+ "EventHeader",
+ "FTDCollection",
+ "HcalBarrelRegCollection",
+ "HcalBarrelRegCollectionContributions",
+ "HCalBarrelRPCHits",
+ "HCalBarrelRPCHitsContributions",
+ "HCalECRingRPCHits",
+ "HCalECRingRPCHitsContributions",
+ "HcalEndcapRingCollection",
+ "HcalEndcapRingCollectionContributions",
+ "HCalEndcapRPCHits",
+ "HCalEndcapRPCHitsContributions",
+ "HcalEndcapsCollection",
+ "HcalEndcapsCollectionContributions",
+ "LHCalCollection",
+ "LHCalCollectionContributions",
+ "LumiCalCollection",
+ "LumiCalCollectionContributions",
+ "MCParticles",
+ "SETCollection",
+ "SITCollection",
+ "TPCCollection",
+ "TPCLowPtCollection",
+ "TPCSpacePointCollection",
+ "VXDCollection",
+ "YokeBarrelCollection",
+ "YokeBarrelCollectionContributions",
+ "YokeEndcapsCollection",
+ "YokeEndcapsCollectionContributions",
+]
+
Finally, the PodioOutput
algorithm and the Lcio2EDM4hepTool
can be
+configuration should look something like this
# ... MyPfoAnalysis configuration unchanged
+
+lcio2edm4hepConv = Lcio2EDM4hepTool()
+lcio2edm4hepConv.collNameMapping = {
+ "MCParticle": "MCParticles"
+}
+MyPfoAnalysis.Lcio2EDM4hepTool = lcio2edm4hepConv
+
+edm4hepOutput = PodioOutput()
+edm4hepOutput.filename = "zh_mumu_reco.edm4hep.root"
+edm4hepOutput.outputCommands = [
+ "drop *",
+ "keep MCParticlesSkimmed",
+ "keep PandoraPFOs",
+ "keep RecoMCTruthLink",
+]
+
+# ... the complete algList
+algList.append(edm4hepOutput)
+
+# ... ApplicationMgr config
+
k4run
After all these adaptions it is now possible to run the full reconstruction
+chain on the previously simulated input with k4run
k4run MarlinStdReco.py --num-events=3 --EventDataSvc.input=zh_mumu_SIM.edm4hep.root
+
Here we are again using the command line to specify the input file, we could
+have just as well used the input
option of the evtsvc
in the options file.
+Note also that we explicitly pass in the number of events, this is a workaround
+for this issue.
You should now have a zh_mumu_reco.edm4hep.root
file that contains the
+complete events in all their glory. For a more practical output you can tweak
+the edm4hepOutput.outputCommands
option in order to keep only “interesting”
+collections. Also note that the REC and DST LCIO output files are still
+produced. Can you reproduce these data tiers for EDM4hep?