diff --git a/404.html b/404.html new file mode 100644 index 0000000..bd940f6 --- /dev/null +++ b/404.html @@ -0,0 +1,23 @@ + + + + + + BRAIN CoGS mini VR rigs + + + + + + + + + + + +

404

That's a Four-Oh-Four.
+ Take me home. +
+ + + diff --git a/assets/css/0.styles.6e54da3e.css b/assets/css/0.styles.6e54da3e.css new file mode 100644 index 0000000..d7245c8 --- /dev/null +++ b/assets/css/0.styles.6e54da3e.css @@ -0,0 +1 @@ +.medium-zoom-overlay{z-index:100}.medium-zoom-overlay~img{z-index:101}code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.block-comment,.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#999}.token.punctuation{color:#ccc}.token.attr-name,.token.deleted,.token.namespace,.token.tag{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.function,.token.number{color:#f08d49}.token.class-name,.token.constant,.token.property,.token.symbol{color:#f8c555}.token.atrule,.token.builtin,.token.important,.token.keyword,.token.selector{color:#cc99cd}.token.attr-value,.token.char,.token.regex,.token.string,.token.variable{color:#7ec699}.token.entity,.token.operator,.token.url{color:#67cdcc}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}.theme-default-content code{color:#476582;padding:.25rem .5rem;margin:0;font-size:.85em;background-color:rgba(27,31,35,.05);border-radius:3px}.theme-default-content code .token.deleted{color:#ec5975}.theme-default-content code .token.inserted{color:#3eaf7c}.theme-default-content pre,.theme-default-content pre[class*=language-]{line-height:1.4;padding:1.25rem 1.5rem;margin:.85rem 0;background-color:#282c34;border-radius:6px;overflow:auto}.theme-default-content pre[class*=language-] code,.theme-default-content pre code{color:#fff;padding:0;background-color:transparent;border-radius:0}div[class*=language-]{position:relative;background-color:#282c34;border-radius:6px}div[class*=language-] .highlight-lines{-webkit-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlighted{background-color:rgba(0,0,0,.66)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:transparent;position:relative;z-index:1}div[class*=language-]:before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:hsla(0,0%,100%,.4)}div[class*=language-]:not(.line-numbers-mode) .line-numbers-wrapper{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlighted{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlighted:before{content:" ";position:absolute;z-index:3;left:0;top:0;display:block;width:3.5rem;height:100%;background-color:rgba(0,0,0,.66)}div[class*=language-].line-numbers-mode pre{padding-left:4.5rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers-wrapper{position:absolute;top:0;width:3.5rem;text-align:center;color:hsla(0,0%,100%,.3);padding:1.25rem 0;line-height:1.4}div[class*=language-].line-numbers-mode .line-numbers-wrapper br{-webkit-user-select:none;user-select:none}div[class*=language-].line-numbers-mode .line-numbers-wrapper .line-number{position:relative;z-index:4;-webkit-user-select:none;user-select:none;font-size:.85em}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;z-index:2;top:0;left:0;width:3.5rem;height:100%;border-radius:6px 0 0 6px;border-right:1px solid rgba(0,0,0,.66);background-color:#282c34}div[class~=language-js]:before{content:"js"}div[class~=language-ts]:before{content:"ts"}div[class~=language-html]:before{content:"html"}div[class~=language-md]:before{content:"md"}div[class~=language-vue]:before{content:"vue"}div[class~=language-css]:before{content:"css"}div[class~=language-sass]:before{content:"sass"}div[class~=language-scss]:before{content:"scss"}div[class~=language-less]:before{content:"less"}div[class~=language-stylus]:before{content:"stylus"}div[class~=language-go]:before{content:"go"}div[class~=language-java]:before{content:"java"}div[class~=language-c]:before{content:"c"}div[class~=language-sh]:before{content:"sh"}div[class~=language-yaml]:before{content:"yaml"}div[class~=language-py]:before{content:"py"}div[class~=language-docker]:before{content:"docker"}div[class~=language-dockerfile]:before{content:"dockerfile"}div[class~=language-makefile]:before{content:"makefile"}div[class~=language-javascript]:before{content:"js"}div[class~=language-typescript]:before{content:"ts"}div[class~=language-markup]:before{content:"html"}div[class~=language-markdown]:before{content:"md"}div[class~=language-json]:before{content:"json"}div[class~=language-ruby]:before{content:"rb"}div[class~=language-python]:before{content:"py"}div[class~=language-bash]:before{content:"sh"}div[class~=language-php]:before{content:"php"}.custom-block .custom-block-title{font-weight:600;margin-bottom:-.4rem}.custom-block.danger,.custom-block.tip,.custom-block.warning{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-block.tip{background-color:#f3f5f7;border-color:#42b983}.custom-block.warning{background-color:rgba(255,229,100,.3);border-color:#e7c000;color:#6b5900}.custom-block.warning .custom-block-title{color:#b29400}.custom-block.warning a{color:#2c3e50}.custom-block.danger{background-color:#ffe6e6;border-color:#c00;color:#4d0000}.custom-block.danger .custom-block-title{color:#900}.custom-block.danger a{color:#2c3e50}.custom-block.details{display:block;position:relative;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:#eee}.custom-block.details h4{margin-top:0}.custom-block.details figure:last-child,.custom-block.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-block.details summary{outline:none;cursor:pointer}.arrow{display:inline-block;width:0;height:0}.arrow.up{border-bottom:6px solid #ccc}.arrow.down,.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent}.arrow.down{border-top:6px solid #ccc}.arrow.right{border-left:6px solid #ccc}.arrow.left,.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent}.arrow.left{border-right:6px solid #ccc}.theme-default-content:not(.custom){max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.theme-default-content:not(.custom){padding:2rem}}@media (max-width:419px){.theme-default-content:not(.custom){padding:1.5rem}}.table-of-contents .badge{vertical-align:middle}body,html{padding:0;margin:0;background-color:#fff}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:16px;color:#2c3e50}.page{padding-left:20rem}.navbar{z-index:20;right:0;height:3.6rem;background-color:#fff;box-sizing:border-box;border-bottom:1px solid #eaecef}.navbar,.sidebar-mask{position:fixed;top:0;left:0}.sidebar-mask{z-index:9;width:100vw;height:100vh;display:none}.sidebar{font-size:16px;background-color:#fff;width:20rem;position:fixed;z-index:10;margin:0;top:3.6rem;left:0;bottom:0;box-sizing:border-box;border-right:1px solid #eaecef;overflow-y:auto}.theme-default-content:not(.custom)>:first-child{margin-top:3.6rem}.theme-default-content:not(.custom) a:hover{text-decoration:underline}.theme-default-content:not(.custom) p.demo{padding:1rem 1.5rem;border:1px solid #ddd;border-radius:4px}.theme-default-content:not(.custom) img{max-width:100%}.theme-default-content.custom{padding:0;margin:0}.theme-default-content.custom img{max-width:100%}a{font-weight:500;text-decoration:none}a,p a code{color:#3eaf7c}p a code{font-weight:400}kbd{background:#eee;border:.15rem solid #ddd;border-bottom:.25rem solid #ddd;border-radius:.15rem;padding:0 .15em}blockquote{font-size:1rem;color:#999;border-left:.2rem solid #dfe2e5;margin:1rem 0;padding:.25rem 0 .25rem 1rem}blockquote>p{margin:0}ol,ul{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}.theme-default-content:not(.custom)>h1,.theme-default-content:not(.custom)>h2,.theme-default-content:not(.custom)>h3,.theme-default-content:not(.custom)>h4,.theme-default-content:not(.custom)>h5,.theme-default-content:not(.custom)>h6{margin-top:-3.1rem;padding-top:4.6rem;margin-bottom:0}.theme-default-content:not(.custom)>h1:first-child,.theme-default-content:not(.custom)>h2:first-child,.theme-default-content:not(.custom)>h3:first-child,.theme-default-content:not(.custom)>h4:first-child,.theme-default-content:not(.custom)>h5:first-child,.theme-default-content:not(.custom)>h6:first-child{margin-top:-1.5rem;margin-bottom:1rem}.theme-default-content:not(.custom)>h1:first-child+.custom-block,.theme-default-content:not(.custom)>h1:first-child+p,.theme-default-content:not(.custom)>h1:first-child+pre,.theme-default-content:not(.custom)>h2:first-child+.custom-block,.theme-default-content:not(.custom)>h2:first-child+p,.theme-default-content:not(.custom)>h2:first-child+pre,.theme-default-content:not(.custom)>h3:first-child+.custom-block,.theme-default-content:not(.custom)>h3:first-child+p,.theme-default-content:not(.custom)>h3:first-child+pre,.theme-default-content:not(.custom)>h4:first-child+.custom-block,.theme-default-content:not(.custom)>h4:first-child+p,.theme-default-content:not(.custom)>h4:first-child+pre,.theme-default-content:not(.custom)>h5:first-child+.custom-block,.theme-default-content:not(.custom)>h5:first-child+p,.theme-default-content:not(.custom)>h5:first-child+pre,.theme-default-content:not(.custom)>h6:first-child+.custom-block,.theme-default-content:not(.custom)>h6:first-child+p,.theme-default-content:not(.custom)>h6:first-child+pre{margin-top:2rem}h1:focus .header-anchor,h1:hover .header-anchor,h2:focus .header-anchor,h2:hover .header-anchor,h3:focus .header-anchor,h3:hover .header-anchor,h4:focus .header-anchor,h4:hover .header-anchor,h5:focus .header-anchor,h5:hover .header-anchor,h6:focus .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid #eaecef}h3{font-size:1.35rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;-webkit-user-select:none;user-select:none;opacity:0}a.header-anchor:focus,a.header-anchor:hover{text-decoration:none}.line-number,code,kbd{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}ol,p,ul{line-height:1.7}hr{border:0;border-top:1px solid #eaecef}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto}tr{border-top:1px solid #dfe2e5}tr:nth-child(2n){background-color:#f6f8fa}td,th{border:1px solid #dfe2e5;padding:.6em 1em}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.no-navbar .theme-default-content:not(.custom)>h1,.theme-container.no-navbar h2,.theme-container.no-navbar h3,.theme-container.no-navbar h4,.theme-container.no-navbar h5,.theme-container.no-navbar h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .sidebar{top:0}@media (min-width:720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}@media (max-width:959px){.sidebar{font-size:15px;width:16.4rem}.page{padding-left:16.4rem}}@media (max-width:719px){.sidebar{top:0;padding-top:3.6rem;transform:translateX(-100%);transition:transform .2s ease}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translateX(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width:419px){h1{font-size:1.9rem}.theme-default-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}.home .hero img{max-width:450px!important}#nprogress{pointer-events:none}#nprogress .bar{background:#3eaf7c;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #3eaf7c,0 0 5px #3eaf7c;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border-color:#3eaf7c transparent transparent #3eaf7c;border-style:solid;border-width:2px;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.go-to-top[data-v-5fd4ef0c]{cursor:pointer;position:fixed;bottom:2rem;right:2.5rem;width:2rem;color:#3eaf7c;z-index:1}.go-to-top[data-v-5fd4ef0c]:hover{color:#72cda4}@media (max-width:959px){.go-to-top[data-v-5fd4ef0c]{display:none}}.fade-enter-active[data-v-5fd4ef0c],.fade-leave-active[data-v-5fd4ef0c]{transition:opacity .3s}.fade-enter[data-v-5fd4ef0c],.fade-leave-to[data-v-5fd4ef0c]{opacity:0}.icon.outbound{color:#aaa;display:inline-block;vertical-align:middle;position:relative;top:-1px}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.algolia-search-wrapper>span{vertical-align:middle}.algolia-search-wrapper .algolia-autocomplete{line-height:normal}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu{background-color:#fff;border:1px solid #999;border-radius:4px;font-size:16px;margin:6px 0 0;padding:4px;text-align:left}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu:before{border-color:#999}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu [class*=ds-dataset-]{border:none;padding:0}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu .ds-suggestions{margin-top:0}.algolia-search-wrapper .algolia-autocomplete .ds-dropdown-menu .ds-suggestion{border-bottom:1px solid #eaecef}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion--highlight{color:#2c815b}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion{border-color:#eaecef;padding:0}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--category-header{padding:5px 10px;margin-top:0;background:#3eaf7c;color:#fff;font-weight:600}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--highlight{background:hsla(0,0%,100%,.6)}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--wrapper{padding:0}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--title{font-weight:600;margin-bottom:0;color:#2c3e50}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{vertical-align:top;padding:5px 7px 5px 5px;border-color:#eaecef;background:#f1f3f5}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:after{display:none}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column-text{color:#555}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-footer{border-color:#eaecef}.algolia-search-wrapper .algolia-autocomplete .ds-cursor .algolia-docsearch-suggestion--content{background-color:#e7edf3!important;color:#2c3e50}@media (min-width:719px){.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{float:none;width:150px;min-width:150px;display:table-cell}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content{float:none;display:table-cell;width:100%;vertical-align:top}.algolia-search-wrapper .algolia-autocomplete .algolia-docsearch-suggestion .ds-dropdown-menu{min-width:515px!important}}@media (max-width:719px){.algolia-search-wrapper .ds-dropdown-menu{min-width:calc(100vw - 4rem)!important;max-width:calc(100vw - 4rem)!important}.algolia-search-wrapper .algolia-docsearch-suggestion--wrapper{padding:5px 7px 5px 5px!important}.algolia-search-wrapper .algolia-docsearch-suggestion--subcategory-column{padding:0!important;background:#fff!important}.algolia-search-wrapper .algolia-docsearch-suggestion--subcategory-column-text:after{content:" > ";font-size:10px;line-height:14.4px;display:inline-block;width:5px;margin:-3px 3px 0;vertical-align:middle}}.home{padding:3.6rem 2rem 0;max-width:960px;margin:0 auto;display:block}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.8rem auto}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:#6a8bad}.home .hero .action-button{display:inline-block;font-size:1.2rem;color:#fff;background-color:#3eaf7c;padding:.8rem 1.6rem;border-radius:4px;transition:background-color .1s ease;box-sizing:border-box;border-bottom:1px solid #389d70}.home .hero .action-button:hover{background-color:#4abf8a}.home .features{border-top:1px solid #eaecef;padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:#3a5169}.home .feature p{color:#4e6e8e}.home .footer{padding:2.5rem;border-top:1px solid #eaecef;text-align:center;color:#4e6e8e}@media (max-width:719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width:419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero .action,.home .hero .description,.home .hero h1{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.search-box{display:inline-block;position:relative;margin-right:1rem}.search-box input{cursor:text;width:10rem;height:2rem;color:#4e6e8e;display:inline-block;border:1px solid #cfd4db;border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:none;transition:all .2s ease;background:#fff url(/assets/img/search.83621669.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:#3eaf7c}.search-box .suggestions{background:#fff;width:20rem;position:absolute;top:2rem;border:1px solid #cfd4db;border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestions.align-right{right:0}.search-box .suggestion{line-height:1.4;padding:.4rem .6rem;border-radius:4px;cursor:pointer}.search-box .suggestion a{white-space:normal;color:#5d82a6}.search-box .suggestion a .page-title{font-weight:600}.search-box .suggestion a .header{font-size:.9em;margin-left:.25em}.search-box .suggestion.focused{background-color:#f3f4f5}.search-box .suggestion.focused a{color:#3eaf7c}@media (max-width:959px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (-ms-high-contrast:none){.search-box input{height:2rem}}@media (max-width:959px) and (min-width:719px){.search-box .suggestions{left:0}}@media (max-width:719px){.search-box{margin-right:0}.search-box input{left:1rem}.search-box .suggestions{right:0}}@media (max-width:419px){.search-box .suggestions{width:calc(100vw - 4rem)}.search-box input:focus{width:8rem}}.sidebar-button{cursor:pointer;display:none;width:1.25rem;height:1.25rem;position:absolute;padding:.6rem;top:.6rem;left:1rem}.sidebar-button .icon{display:block;width:1.25rem;height:1.25rem}@media (max-width:719px){.sidebar-button{display:block}}.dropdown-enter,.dropdown-leave-to{height:0!important}.badge[data-v-15b7b770]{display:inline-block;font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:#fff}.badge.green[data-v-15b7b770],.badge.tip[data-v-15b7b770],.badge[data-v-15b7b770]{background-color:#42b983}.badge.error[data-v-15b7b770]{background-color:#da5961}.badge.warn[data-v-15b7b770],.badge.warning[data-v-15b7b770],.badge.yellow[data-v-15b7b770]{background-color:#e7c000}.badge+.badge[data-v-15b7b770]{margin-left:5px}.theme-code-block[data-v-759a7d02]{display:none}.theme-code-block__active[data-v-759a7d02]{display:block}.theme-code-block>pre[data-v-759a7d02]{background-color:orange}.theme-code-group__nav[data-v-deefee04]{margin-bottom:-35px;background-color:#282c34;padding-bottom:22px;border-top-left-radius:6px;border-top-right-radius:6px;padding-left:10px;padding-top:10px}.theme-code-group__ul[data-v-deefee04]{margin:auto 0;padding-left:0;display:inline-flex;list-style:none}.theme-code-group__nav-tab[data-v-deefee04]{border:0;padding:5px;cursor:pointer;background-color:transparent;font-size:.85em;line-height:1.4;color:hsla(0,0%,100%,.9);font-weight:600}.theme-code-group__nav-tab-active[data-v-deefee04]{border-bottom:1px solid #42b983}.pre-blank[data-v-deefee04]{color:#42b983}.searchbox{display:inline-block;position:relative;width:200px;height:32px!important;white-space:nowrap;box-sizing:border-box;visibility:visible!important}.searchbox .algolia-autocomplete{display:block;width:100%;height:100%}.searchbox__wrapper{width:100%;height:100%;z-index:999;position:relative}.searchbox__input{display:inline-block;box-sizing:border-box;transition:box-shadow .4s ease,background .4s ease;border:0;border-radius:16px;box-shadow:inset 0 0 0 1px #ccc;background:#fff!important;padding:0 26px 0 32px;width:100%;height:100%;vertical-align:middle;white-space:normal;font-size:12px;-webkit-appearance:none;-moz-appearance:none;appearance:none}.searchbox__input::-webkit-search-cancel-button,.searchbox__input::-webkit-search-decoration,.searchbox__input::-webkit-search-results-button,.searchbox__input::-webkit-search-results-decoration{display:none}.searchbox__input:hover{box-shadow:inset 0 0 0 1px #b3b3b3}.searchbox__input:active,.searchbox__input:focus{outline:0;box-shadow:inset 0 0 0 1px #aaa;background:#fff}.searchbox__input::-moz-placeholder{color:#aaa}.searchbox__input::placeholder{color:#aaa}.searchbox__submit{position:absolute;top:0;margin:0;border:0;border-radius:16px 0 0 16px;background-color:rgba(69,142,225,0);padding:0;width:32px;height:100%;vertical-align:middle;text-align:center;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;user-select:none;right:inherit;left:0}.searchbox__submit:before{display:inline-block;margin-right:-4px;height:100%;vertical-align:middle;content:""}.searchbox__submit:active,.searchbox__submit:hover{cursor:pointer}.searchbox__submit:focus{outline:0}.searchbox__submit svg{width:14px;height:14px;vertical-align:middle;fill:#6d7e96}.searchbox__reset{display:block;position:absolute;top:8px;right:8px;margin:0;border:0;background:none;cursor:pointer;padding:0;font-size:inherit;-webkit-user-select:none;-moz-user-select:none;user-select:none;fill:rgba(0,0,0,.5)}.searchbox__reset.hide{display:none}.searchbox__reset:focus{outline:0}.searchbox__reset svg{display:block;margin:4px;width:8px;height:8px}.searchbox__input:valid~.searchbox__reset{display:block;animation-name:sbx-reset-in;animation-duration:.15s}@keyframes sbx-reset-in{0%{transform:translate3d(-20%,0,0);opacity:0}to{transform:none;opacity:1}}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu{right:0!important;left:inherit!important}.algolia-autocomplete.algolia-autocomplete-right .ds-dropdown-menu:before{right:48px}.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu{left:0!important;right:inherit!important}.algolia-autocomplete.algolia-autocomplete-left .ds-dropdown-menu:before{left:48px}.algolia-autocomplete .ds-dropdown-menu{top:-6px;border-radius:4px;margin:6px 0 0;padding:0;text-align:left;height:auto;position:relative;background:transparent;border:none;z-index:999;max-width:600px;min-width:500px;box-shadow:0 1px 0 0 rgba(0,0,0,.2),0 2px 3px 0 rgba(0,0,0,.1)}.algolia-autocomplete .ds-dropdown-menu:before{display:block;position:absolute;content:"";width:14px;height:14px;background:#fff;z-index:1000;top:-7px;border-top:1px solid #d9d9d9;border-right:1px solid #d9d9d9;transform:rotate(-45deg);border-radius:2px}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions{position:relative;z-index:1000;margin-top:8px}.algolia-autocomplete .ds-dropdown-menu .ds-suggestions a:hover{text-decoration:none}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion{cursor:pointer}.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion.suggestion-layout-simple,.algolia-autocomplete .ds-dropdown-menu .ds-suggestion.ds-cursor .algolia-docsearch-suggestion:not(.suggestion-layout-simple) .algolia-docsearch-suggestion--content{background-color:rgba(69,142,225,.05)}.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-]{position:relative;border:1px solid #d9d9d9;background:#fff;border-radius:4px;overflow:auto;padding:0 8px 8px}.algolia-autocomplete .ds-dropdown-menu *{box-sizing:border-box}.algolia-autocomplete .algolia-docsearch-suggestion{display:block;position:relative;padding:0 8px;background:#fff;color:#02060c;overflow:hidden}.algolia-autocomplete .algolia-docsearch-suggestion--highlight{color:#174d8c;background:rgba(143,187,237,.1);padding:.1em .05em}.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl0 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--category-header .algolia-docsearch-suggestion--category-header-lvl1 .algolia-docsearch-suggestion--highlight,.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{padding:0 0 1px;background:inherit;box-shadow:inset 0 -2px 0 0 rgba(69,142,225,.8);color:inherit}.algolia-autocomplete .algolia-docsearch-suggestion--content{display:block;float:right;width:70%;position:relative;padding:5.33333px 0 5.33333px 10.66667px;cursor:pointer}.algolia-autocomplete .algolia-docsearch-suggestion--content:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;left:-1px}.algolia-autocomplete .algolia-docsearch-suggestion--category-header{position:relative;border-bottom:1px solid #ddd;display:none;margin-top:8px;padding:4px 0;font-size:1em;color:#33363d}.algolia-autocomplete .algolia-docsearch-suggestion--wrapper{width:100%;float:left;padding:8px 0 0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column{float:left;width:30%;text-align:right;position:relative;padding:5.33333px 10.66667px;color:#a4a7ae;font-size:.9em;word-wrap:break-word}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column:before{content:"";position:absolute;display:block;top:0;height:100%;width:1px;background:#ddd;right:0}.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-inline{display:none}.algolia-autocomplete .algolia-docsearch-suggestion--title{margin-bottom:4px;color:#02060c;font-size:.9em;font-weight:700}.algolia-autocomplete .algolia-docsearch-suggestion--text{display:block;line-height:1.2em;font-size:.85em;color:#63676d}.algolia-autocomplete .algolia-docsearch-suggestion--no-results{width:100%;padding:8px 0;text-align:center;font-size:1.2em}.algolia-autocomplete .algolia-docsearch-suggestion--no-results:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion code{padding:1px 5px;font-size:90%;border:none;color:#222;background-color:#ebebeb;border-radius:3px;font-family:Menlo,Monaco,Consolas,Courier New,monospace}.algolia-autocomplete .algolia-docsearch-suggestion code .algolia-docsearch-suggestion--highlight{background:none}.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__main .algolia-docsearch-suggestion--category-header,.algolia-autocomplete .algolia-docsearch-suggestion.algolia-docsearch-suggestion__secondary{display:block}@media (min-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:block}}@media (max-width:768px){.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column{display:inline-block;width:auto;float:left;padding:0;color:#02060c;font-size:.9em;font-weight:700;text-align:left;opacity:.5}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:before{display:none}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--subcategory-column:after{content:"|"}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content{display:inline-block;width:auto;text-align:left;float:left;padding:0}.algolia-autocomplete .algolia-docsearch-suggestion .algolia-docsearch-suggestion--content:before{display:none}}.algolia-autocomplete .suggestion-layout-simple.algolia-docsearch-suggestion{border-bottom:1px solid #eee;padding:8px;margin:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content{width:100%;padding:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--content:before{display:none}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header{margin:0;padding:0;display:block;width:100%;border:none}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl0,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1{opacity:.6;font-size:.85em}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--category-header-lvl1:before{background-image:url('data:image/svg+xml;utf8,');content:"";width:10px;height:10px;display:inline-block}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--wrapper{width:100%;float:left;margin:0;padding:0}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--duplicate-content,.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--subcategory-inline{display:none!important}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title{margin:0;color:#458ee1;font-size:.9em;font-weight:400}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--title:before{content:"#";font-weight:700;color:#458ee1;display:inline-block}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text{margin:4px 0 0;display:block;line-height:1.4em;padding:5.33333px 8px;background:#f8f8f8;font-size:.85em;opacity:.8}.algolia-autocomplete .suggestion-layout-simple .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight{color:#3f4145;font-weight:700;box-shadow:none}.algolia-autocomplete .algolia-docsearch-footer{width:134px;height:20px;z-index:2000;margin-top:10.66667px;float:right;font-size:0;line-height:0}.algolia-autocomplete .algolia-docsearch-footer--logo{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg width='168' height='24' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cpath d='M78.988.938h16.594a2.968 2.968 0 012.966 2.966V20.5a2.967 2.967 0 01-2.966 2.964H78.988a2.967 2.967 0 01-2.966-2.964V3.897A2.961 2.961 0 0178.988.938zm41.937 17.866c-4.386.02-4.386-3.54-4.386-4.106l-.007-13.336 2.675-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-10.846-2.18c.821 0 1.43-.047 1.855-.129v-2.719a6.334 6.334 0 00-1.574-.199 5.7 5.7 0 00-.897.069 2.699 2.699 0 00-.814.24c-.24.116-.439.28-.582.491-.15.212-.219.335-.219.656 0 .628.219.991.616 1.23s.938.362 1.615.362zm-.233-9.7c.883 0 1.629.109 2.231.328.602.218 1.088.525 1.444.915.363.396.609.922.76 1.483.157.56.232 1.175.232 1.85v6.874a32.5 32.5 0 01-1.868.314c-.834.123-1.772.185-2.813.185-.69 0-1.327-.069-1.895-.198a4.001 4.001 0 01-1.471-.636 3.085 3.085 0 01-.951-1.134c-.226-.465-.343-1.12-.343-1.803 0-.656.13-1.073.384-1.525a3.24 3.24 0 011.047-1.106c.445-.287.95-.492 1.532-.615a8.8 8.8 0 011.82-.185 8.404 8.404 0 011.972.24v-.438c0-.307-.035-.6-.11-.874a1.88 1.88 0 00-.384-.73 1.784 1.784 0 00-.724-.493 3.164 3.164 0 00-1.143-.205c-.616 0-1.177.075-1.69.164a7.735 7.735 0 00-1.26.307l-.321-2.192c.335-.117.834-.233 1.478-.349a10.98 10.98 0 012.073-.178zm52.842 9.626c.822 0 1.43-.048 1.854-.13V13.7a6.347 6.347 0 00-1.574-.199c-.294 0-.595.021-.896.069a2.7 2.7 0 00-.814.24 1.46 1.46 0 00-.582.491c-.15.212-.218.335-.218.656 0 .628.218.991.615 1.23.404.245.938.362 1.615.362zm-.226-9.694c.883 0 1.629.108 2.231.327.602.219 1.088.526 1.444.915.355.39.609.923.759 1.483a6.8 6.8 0 01.233 1.852v6.873c-.41.088-1.034.19-1.868.314-.834.123-1.772.184-2.813.184-.69 0-1.327-.068-1.895-.198a4.001 4.001 0 01-1.471-.635 3.085 3.085 0 01-.951-1.134c-.226-.465-.343-1.12-.343-1.804 0-.656.13-1.073.384-1.524.26-.45.608-.82 1.047-1.107.445-.286.95-.491 1.532-.614a8.803 8.803 0 012.751-.13c.329.034.671.096 1.04.185v-.437a3.3 3.3 0 00-.109-.875 1.873 1.873 0 00-.384-.731 1.784 1.784 0 00-.724-.492 3.165 3.165 0 00-1.143-.205c-.616 0-1.177.075-1.69.164a7.75 7.75 0 00-1.26.307l-.321-2.193c.335-.116.834-.232 1.478-.348a11.633 11.633 0 012.073-.177zm-8.034-1.271a1.626 1.626 0 01-1.628-1.62c0-.895.725-1.62 1.628-1.62.904 0 1.63.725 1.63 1.62 0 .895-.733 1.62-1.63 1.62zm1.348 13.22h-2.689V7.27l2.69-.423v11.956zm-4.714 0c-4.386.02-4.386-3.54-4.386-4.107l-.008-13.336 2.676-.424v13.254c0 .322 0 2.358 1.718 2.364v2.248zm-8.698-5.903c0-1.156-.253-2.119-.746-2.788-.493-.677-1.183-1.01-2.067-1.01-.882 0-1.574.333-2.065 1.01-.493.676-.733 1.632-.733 2.788 0 1.168.246 1.953.74 2.63.492.683 1.183 1.018 2.066 1.018.882 0 1.574-.342 2.067-1.019.492-.683.738-1.46.738-2.63zm2.737-.007c0 .902-.13 1.584-.397 2.33a5.52 5.52 0 01-1.128 1.906 4.986 4.986 0 01-1.752 1.223c-.685.286-1.739.45-2.265.45-.528-.006-1.574-.157-2.252-.45a5.096 5.096 0 01-1.744-1.223c-.487-.527-.863-1.162-1.137-1.906a6.345 6.345 0 01-.41-2.33c0-.902.123-1.77.397-2.508a5.554 5.554 0 011.15-1.892 5.133 5.133 0 011.75-1.216c.679-.287 1.425-.423 2.232-.423.808 0 1.553.142 2.237.423a4.88 4.88 0 011.753 1.216 5.644 5.644 0 011.135 1.892c.287.738.431 1.606.431 2.508zm-20.138 0c0 1.12.246 2.363.738 2.882.493.52 1.13.78 1.91.78.424 0 .828-.062 1.204-.178.377-.116.677-.253.917-.417V9.33a10.476 10.476 0 00-1.766-.226c-.971-.028-1.71.37-2.23 1.004-.513.636-.773 1.75-.773 2.788zm7.438 5.274c0 1.824-.466 3.156-1.404 4.004-.936.846-2.367 1.27-4.296 1.27-.705 0-2.17-.137-3.34-.396l.431-2.118c.98.205 2.272.26 2.95.26 1.074 0 1.84-.219 2.299-.656.459-.437.684-1.086.684-1.948v-.437a8.07 8.07 0 01-1.047.397c-.43.13-.93.198-1.492.198-.739 0-1.41-.116-2.018-.349a4.206 4.206 0 01-1.567-1.025c-.431-.45-.774-1.017-1.013-1.694-.24-.677-.363-1.885-.363-2.773 0-.834.13-1.88.384-2.577.26-.696.629-1.298 1.129-1.796.493-.498 1.095-.881 1.8-1.162a6.605 6.605 0 012.428-.457c.87 0 1.67.109 2.45.24.78.129 1.444.265 1.985.415V18.17z' fill='%235468FF'/%3E%3Cpath d='M6.972 6.677v1.627c-.712-.446-1.52-.67-2.425-.67-.585 0-1.045.13-1.38.391a1.24 1.24 0 00-.502 1.03c0 .425.164.765.494 1.02.33.256.835.532 1.516.83.447.192.795.356 1.045.495.25.138.537.332.862.582.324.25.563.548.718.894.154.345.23.741.23 1.188 0 .947-.334 1.691-1.004 2.234-.67.542-1.537.814-2.601.814-1.18 0-2.16-.229-2.936-.686v-1.708c.84.628 1.814.942 2.92.942.585 0 1.048-.136 1.388-.407.34-.271.51-.646.51-1.125 0-.287-.1-.55-.302-.79-.203-.24-.42-.42-.655-.542-.234-.123-.585-.29-1.053-.503a61.27 61.27 0 01-.582-.271 13.67 13.67 0 01-.55-.287 4.275 4.275 0 01-.567-.351 6.92 6.92 0 01-.455-.4c-.18-.17-.31-.34-.39-.51-.08-.17-.155-.37-.224-.598a2.553 2.553 0 01-.104-.742c0-.915.333-1.638.998-2.17.664-.532 1.523-.798 2.576-.798.968 0 1.793.17 2.473.51zm7.468 5.696v-.287c-.022-.607-.187-1.088-.495-1.444-.309-.357-.75-.535-1.324-.535-.532 0-.99.194-1.373.583-.382.388-.622.949-.717 1.683h3.909zm1.005 2.792v1.404c-.596.34-1.383.51-2.362.51-1.255 0-2.255-.377-3-1.132-.744-.755-1.116-1.744-1.116-2.968 0-1.297.34-2.316 1.021-3.055.68-.74 1.548-1.11 2.6-1.11 1.033 0 1.852.323 2.458.966.606.644.91 1.572.91 2.784 0 .33-.033.676-.096 1.038h-5.314c.107.702.405 1.239.894 1.611.49.372 1.106.558 1.85.558.862 0 1.58-.202 2.155-.606zm6.605-1.77h-1.212c-.596 0-1.045.116-1.349.35-.303.234-.454.532-.454.894 0 .372.117.664.35.877.235.213.575.32 1.022.32.51 0 .912-.142 1.204-.424.293-.281.44-.651.44-1.108v-.91zm-4.068-2.554V9.325c.627-.361 1.457-.542 2.489-.542 2.116 0 3.175 1.026 3.175 3.08V17h-1.548v-.957c-.415.68-1.143 1.02-2.186 1.02-.766 0-1.38-.22-1.843-.661-.462-.442-.694-1.003-.694-1.684 0-.776.293-1.38.878-1.81.585-.431 1.404-.647 2.457-.647h1.34V11.8c0-.554-.133-.971-.399-1.253-.266-.282-.707-.423-1.324-.423a4.07 4.07 0 00-2.345.718zm9.333-1.93v1.42c.394-1 1.101-1.5 2.123-1.5.148 0 .313.016.494.048v1.531a1.885 1.885 0 00-.75-.143c-.542 0-.989.24-1.34.718-.351.479-.527 1.048-.527 1.707V17h-1.563V8.91h1.563zm5.01 4.084c.022.82.272 1.492.75 2.019.479.526 1.15.79 2.01.79.639 0 1.235-.176 1.788-.527v1.404c-.521.319-1.186.479-1.995.479-1.265 0-2.276-.4-3.031-1.197-.755-.798-1.133-1.792-1.133-2.984 0-1.16.38-2.151 1.14-2.975.761-.825 1.79-1.237 3.088-1.237.702 0 1.346.149 1.93.447v1.436a3.242 3.242 0 00-1.77-.495c-.84 0-1.513.266-2.019.798-.505.532-.758 1.213-.758 2.042zM40.24 5.72v4.579c.458-1 1.293-1.5 2.505-1.5.787 0 1.42.245 1.899.734.479.49.718 1.17.718 2.042V17h-1.564v-5.106c0-.553-.14-.98-.422-1.284-.282-.303-.652-.455-1.11-.455-.531 0-1.002.202-1.411.606-.41.405-.615 1.022-.615 1.851V17h-1.563V5.72h1.563zm14.966 10.02c.596 0 1.096-.253 1.5-.758.404-.506.606-1.157.606-1.955 0-.915-.202-1.62-.606-2.114-.404-.495-.92-.742-1.548-.742-.553 0-1.05.224-1.491.67-.442.447-.662 1.133-.662 2.058 0 .958.212 1.67.638 2.138.425.469.946.703 1.563.703zM53.004 5.72v4.42c.574-.894 1.388-1.341 2.44-1.341 1.022 0 1.857.383 2.506 1.149.649.766.973 1.781.973 3.047 0 1.138-.309 2.109-.925 2.912-.617.803-1.463 1.205-2.537 1.205-1.075 0-1.894-.447-2.457-1.34V17h-1.58V5.72h1.58zm9.908 11.104l-3.223-7.913h1.739l1.005 2.632 1.26 3.415c.096-.32.48-1.458 1.15-3.415l.909-2.632h1.66l-2.92 7.866c-.777 2.074-1.963 3.11-3.559 3.11a2.92 2.92 0 01-.734-.079v-1.34c.17.042.351.064.543.064 1.032 0 1.755-.57 2.17-1.708z' fill='%235D6494'/%3E%3Cpath d='M89.632 5.967v-.772a.978.978 0 00-.978-.977h-2.28a.978.978 0 00-.978.977v.793c0 .088.082.15.171.13a7.127 7.127 0 011.984-.28c.65 0 1.295.088 1.917.259.082.02.164-.04.164-.13m-6.248 1.01l-.39-.389a.977.977 0 00-1.382 0l-.465.465a.973.973 0 000 1.38l.383.383c.062.061.15.047.205-.014.226-.307.472-.601.746-.874.281-.28.568-.526.883-.751.068-.042.075-.137.02-.2m4.16 2.453v3.341c0 .096.104.165.192.117l2.97-1.537c.068-.034.089-.117.055-.184a3.695 3.695 0 00-3.08-1.866c-.068 0-.136.054-.136.13m0 8.048a4.489 4.489 0 01-4.49-4.482 4.488 4.488 0 014.49-4.482 4.488 4.488 0 014.489 4.482 4.484 4.484 0 01-4.49 4.482m0-10.85a6.363 6.363 0 100 12.729 6.37 6.37 0 006.372-6.368 6.358 6.358 0 00-6.371-6.36' fill='%23FFF'/%3E%3C/g%3E%3C/svg%3E");background-repeat:no-repeat;background-position:50%;background-size:100%;overflow:hidden;text-indent:-9000px;padding:0!important;width:100%;height:100%;display:block}.dropdown-wrapper{cursor:pointer}.dropdown-wrapper .dropdown-title,.dropdown-wrapper .mobile-dropdown-title{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:transparent;border:none;font-weight:500;color:#2c3e50}.dropdown-wrapper .dropdown-title:hover,.dropdown-wrapper .mobile-dropdown-title:hover{border-color:transparent}.dropdown-wrapper .dropdown-title .arrow,.dropdown-wrapper .mobile-dropdown-title .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.dropdown-wrapper .mobile-dropdown-title{display:none;font-weight:600}.dropdown-wrapper .mobile-dropdown-title font-size inherit:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown .dropdown-item{color:inherit;line-height:1.7rem}.dropdown-wrapper .nav-dropdown .dropdown-item h4{margin:.45rem 0 0;border-top:1px solid #eee;padding:1rem 1.5rem .45rem 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper{padding:0;list-style:none}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem-wrapper .dropdown-subitem{font-size:.9em}.dropdown-wrapper .nav-dropdown .dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active,.dropdown-wrapper .nav-dropdown .dropdown-item a:hover{color:#3eaf7c}.dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid #3eaf7c;border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.dropdown-wrapper .nav-dropdown .dropdown-item:first-child h4{margin-top:0;padding-top:0;border-top:0}@media (max-width:719px){.dropdown-wrapper.open .dropdown-title{margin-bottom:.5rem}.dropdown-wrapper .dropdown-title{display:none}.dropdown-wrapper .mobile-dropdown-title{display:block}.dropdown-wrapper .nav-dropdown{transition:height .1s ease-out;overflow:hidden}.dropdown-wrapper .nav-dropdown .dropdown-item h4{border-top:0;margin-top:0;padding-top:0}.dropdown-wrapper .nav-dropdown .dropdown-item>a,.dropdown-wrapper .nav-dropdown .dropdown-item h4{font-size:15px;line-height:2rem}.dropdown-wrapper .nav-dropdown .dropdown-item .dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width:719px){.dropdown-wrapper{height:1.8rem}.dropdown-wrapper.open .nav-dropdown,.dropdown-wrapper:hover .nav-dropdown{display:block!important}.dropdown-wrapper .nav-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:#fff;padding:.6rem 0;border:1px solid;border-color:#ddd #ddd #ccc;text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}}.nav-links{display:inline-block}.nav-links a{line-height:1.4rem;color:inherit}.nav-links a.router-link-active,.nav-links a:hover{color:#3eaf7c}.nav-links .nav-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:2rem}.nav-links .nav-item:first-child{margin-left:0}.nav-links .repo-link{margin-left:1.5rem}@media (max-width:719px){.nav-links .nav-item,.nav-links .repo-link{margin-left:0}}@media (min-width:719px){.nav-links a.router-link-active,.nav-links a:hover{color:#2c3e50}.nav-item>a:not(.external).router-link-active,.nav-item>a:not(.external):hover{margin-bottom:-2px;border-bottom:2px solid #46bd87}}.navbar{padding:.7rem 1.5rem;line-height:2.2rem}.navbar a,.navbar img,.navbar span{display:inline-block}.navbar .logo{height:2.2rem;min-width:2.2rem;margin-right:.8rem;vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:#2c3e50;position:relative}.navbar .links{padding-left:1.5rem;box-sizing:border-box;background-color:#fff;white-space:nowrap;font-size:.9rem;position:absolute;right:1.5rem;top:.7rem;display:flex}.navbar .links .search-box{flex:0 0 auto;vertical-align:top}@media (max-width:719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .links{padding-left:1.5rem}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.page-edit{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-edit{padding:2rem}}@media (max-width:419px){.page-edit{padding:1.5rem}}.page-edit{padding-top:1rem;padding-bottom:1rem;overflow:auto}.page-edit .edit-link{display:inline-block}.page-edit .edit-link a{color:#4e6e8e;margin-right:.25rem}.page-edit .last-updated{float:right;font-size:.9em}.page-edit .last-updated .prefix{font-weight:500;color:#4e6e8e}.page-edit .last-updated .time{font-weight:400;color:#767676}@media (max-width:719px){.page-edit .edit-link{margin-bottom:.5rem}.page-edit .last-updated{font-size:.8em;float:none;text-align:left}}.page-nav{max-width:740px;margin:0 auto;padding:2rem 2.5rem}@media (max-width:959px){.page-nav{padding:2rem}}@media (max-width:419px){.page-nav{padding:1.5rem}}.page-nav{padding-top:1rem;padding-bottom:0}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid #eaecef;padding-top:1rem;overflow:auto}.page-nav .next{float:right}.page{padding-bottom:2rem;display:block}.sidebar-group .sidebar-group{padding-left:.5em}.sidebar-group:not(.collapsable) .sidebar-heading:not(.clickable){cursor:auto;color:inherit}.sidebar-group.is-sub-group{padding-left:0}.sidebar-group.is-sub-group>.sidebar-heading{font-size:.95em;line-height:1.4;font-weight:400;padding-left:2rem}.sidebar-group.is-sub-group>.sidebar-heading:not(.clickable){opacity:.5}.sidebar-group.is-sub-group>.sidebar-group-items{padding-left:1rem}.sidebar-group.is-sub-group>.sidebar-group-items>li>.sidebar-link{font-size:.95em;border-left:none}.sidebar-group.depth-2>.sidebar-heading{border-left:none}.sidebar-heading{color:#2c3e50;transition:color .15s ease;cursor:pointer;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0;border-left:.25rem solid transparent}.sidebar-heading.open,.sidebar-heading:hover{color:inherit}.sidebar-heading .arrow{position:relative;top:-.12em;left:.5em}.sidebar-heading.clickable.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-heading.clickable:hover{color:#3eaf7c}.sidebar-group-items{transition:height .1s ease-out;font-size:.95em;overflow:hidden}.sidebar .sidebar-sub-headers{padding-left:1rem;font-size:.95em}a.sidebar-link{font-size:1em;font-weight:400;display:inline-block;color:#2c3e50;border-left:.25rem solid transparent;padding:.35rem 1rem .35rem 1.25rem;line-height:1.4;width:100%;box-sizing:border-box}a.sidebar-link:hover{color:#3eaf7c}a.sidebar-link.active{font-weight:600;color:#3eaf7c;border-left-color:#3eaf7c}.sidebar-group a.sidebar-link{padding-left:2rem}.sidebar-sub-headers a.sidebar-link{padding-top:.25rem;padding-bottom:.25rem;border-left:none}.sidebar-sub-headers a.sidebar-link.active{font-weight:500}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .nav-links{display:none;border-bottom:1px solid #eaecef;padding:.5rem 0 .75rem}.sidebar .nav-links a{font-weight:600}.sidebar .nav-links .nav-item,.sidebar .nav-links .repo-link{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar>.sidebar-links{padding:1.5rem 0}.sidebar>.sidebar-links>li>a.sidebar-link{font-size:1.1em;line-height:1.7;font-weight:700}.sidebar>.sidebar-links>li:not(:first-child){margin-top:.75rem}@media (max-width:719px){.sidebar .nav-links{display:block}.sidebar .nav-links .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar>.sidebar-links{padding:1rem 0}} \ No newline at end of file diff --git a/assets/img/Action_tab_task_scheduler.68dfb29c.png b/assets/img/Action_tab_task_scheduler.68dfb29c.png new file mode 100644 index 0000000..ee964d3 Binary files /dev/null and b/assets/img/Action_tab_task_scheduler.68dfb29c.png differ diff --git a/assets/img/Add_surgery_data.f49a31af.png b/assets/img/Add_surgery_data.f49a31af.png new file mode 100644 index 0000000..cd72cd8 Binary files /dev/null and b/assets/img/Add_surgery_data.f49a31af.png differ diff --git a/assets/img/Alert_dataframe_example.f1a8b1a2.png b/assets/img/Alert_dataframe_example.f1a8b1a2.png new file mode 100644 index 0000000..d25a9b0 Binary files /dev/null and b/assets/img/Alert_dataframe_example.f1a8b1a2.png differ diff --git a/assets/img/Alert_message_example.e8176029.png b/assets/img/Alert_message_example.e8176029.png new file mode 100644 index 0000000..e970da2 Binary files /dev/null and b/assets/img/Alert_message_example.e8176029.png differ diff --git a/assets/img/Automation_GUI_main_screen.868ced35.png b/assets/img/Automation_GUI_main_screen.868ced35.png new file mode 100644 index 0000000..6f46254 Binary files /dev/null and b/assets/img/Automation_GUI_main_screen.868ced35.png differ diff --git a/assets/img/Configuration_needed_label.681126ce.png b/assets/img/Configuration_needed_label.681126ce.png new file mode 100644 index 0000000..8aa5287 Binary files /dev/null and b/assets/img/Configuration_needed_label.681126ce.png differ diff --git a/assets/img/Configuration_screen.27908033.png b/assets/img/Configuration_screen.27908033.png new file mode 100644 index 0000000..6638ac5 Binary files /dev/null and b/assets/img/Configuration_screen.27908033.png differ diff --git a/assets/img/Copying_session_dialog.b6e45324.png b/assets/img/Copying_session_dialog.b6e45324.png new file mode 100644 index 0000000..b9bb4b0 Binary files /dev/null and b/assets/img/Copying_session_dialog.b6e45324.png differ diff --git a/assets/img/Create_parameters_screen.35d572b5.png b/assets/img/Create_parameters_screen.35d572b5.png new file mode 100644 index 0000000..3a1b6fc Binary files /dev/null and b/assets/img/Create_parameters_screen.35d572b5.png differ diff --git a/assets/img/General_tab_task_scheduler.8b2d0eda.png b/assets/img/General_tab_task_scheduler.8b2d0eda.png new file mode 100644 index 0000000..81d0a38 Binary files /dev/null and b/assets/img/General_tab_task_scheduler.8b2d0eda.png differ diff --git a/assets/img/Job_table.b8241b12.png b/assets/img/Job_table.b8241b12.png new file mode 100644 index 0000000..6769e9e Binary files /dev/null and b/assets/img/Job_table.b8241b12.png differ diff --git a/assets/img/Matlab_shorcut.8e8ab5c7.png b/assets/img/Matlab_shorcut.8e8ab5c7.png new file mode 100644 index 0000000..518dcc9 Binary files /dev/null and b/assets/img/Matlab_shorcut.8e8ab5c7.png differ diff --git a/assets/img/Menu_task_scheduler.12db0039.png b/assets/img/Menu_task_scheduler.12db0039.png new file mode 100644 index 0000000..286958c Binary files /dev/null and b/assets/img/Menu_task_scheduler.12db0039.png differ diff --git a/assets/img/Optogenetics_pipeline.79e7de67.png b/assets/img/Optogenetics_pipeline.79e7de67.png new file mode 100644 index 0000000..4105043 Binary files /dev/null and b/assets/img/Optogenetics_pipeline.79e7de67.png differ diff --git a/assets/img/Processing_visualization.b4fd7fa5.png b/assets/img/Processing_visualization.b4fd7fa5.png new file mode 100644 index 0000000..fa591b3 Binary files /dev/null and b/assets/img/Processing_visualization.b4fd7fa5.png differ diff --git a/assets/img/Recording_registered.f223bd82.png b/assets/img/Recording_registered.f223bd82.png new file mode 100644 index 0000000..48425f5 Binary files /dev/null and b/assets/img/Recording_registered.f223bd82.png differ diff --git a/assets/img/Recording_table.edc64820.png b/assets/img/Recording_table.edc64820.png new file mode 100644 index 0000000..a5879a4 Binary files /dev/null and b/assets/img/Recording_table.edc64820.png differ diff --git a/assets/img/Select_parameters.d66945c9.png b/assets/img/Select_parameters.d66945c9.png new file mode 100644 index 0000000..bee75dc Binary files /dev/null and b/assets/img/Select_parameters.d66945c9.png differ diff --git a/assets/img/System_configured_dialog.b0f14d7a.png b/assets/img/System_configured_dialog.b0f14d7a.png new file mode 100644 index 0000000..0bf358a Binary files /dev/null and b/assets/img/System_configured_dialog.b0f14d7a.png differ diff --git a/assets/img/Thermal_pipeline_ERD.fe0616c1.png b/assets/img/Thermal_pipeline_ERD.fe0616c1.png new file mode 100644 index 0000000..c5c36d5 Binary files /dev/null and b/assets/img/Thermal_pipeline_ERD.fe0616c1.png differ diff --git a/assets/img/Thermal_schema_files.0c7dea0a.png b/assets/img/Thermal_schema_files.0c7dea0a.png new file mode 100644 index 0000000..897be93 Binary files /dev/null and b/assets/img/Thermal_schema_files.0c7dea0a.png differ diff --git a/assets/img/Trigger_tab_task_scheduler.d1fe7432.png b/assets/img/Trigger_tab_task_scheduler.d1fe7432.png new file mode 100644 index 0000000..7a33454 Binary files /dev/null and b/assets/img/Trigger_tab_task_scheduler.d1fe7432.png differ diff --git a/assets/img/Twolickspouts_subtask_files.971dd738.png b/assets/img/Twolickspouts_subtask_files.971dd738.png new file mode 100644 index 0000000..c5f183e Binary files /dev/null and b/assets/img/Twolickspouts_subtask_files.971dd738.png differ diff --git a/assets/img/add_animal_dialog_description.e1993549.png b/assets/img/add_animal_dialog_description.e1993549.png new file mode 100644 index 0000000..41d41a0 Binary files /dev/null and b/assets/img/add_animal_dialog_description.e1993549.png differ diff --git a/assets/img/add_animal_section.4d32c04a.png b/assets/img/add_animal_section.4d32c04a.png new file mode 100644 index 0000000..cdb255c Binary files /dev/null and b/assets/img/add_animal_section.4d32c04a.png differ diff --git a/assets/img/air-puffs-1.d4df2cb7.png b/assets/img/air-puffs-1.d4df2cb7.png new file mode 100644 index 0000000..55932fa Binary files /dev/null and b/assets/img/air-puffs-1.d4df2cb7.png differ diff --git a/assets/img/air-puffs-assembly-1.37791b9e.png b/assets/img/air-puffs-assembly-1.37791b9e.png new file mode 100644 index 0000000..084748c Binary files /dev/null and b/assets/img/air-puffs-assembly-1.37791b9e.png differ diff --git a/assets/img/air-puffs-assembly-2.24fed7c0.png b/assets/img/air-puffs-assembly-2.24fed7c0.png new file mode 100644 index 0000000..a5a8213 Binary files /dev/null and b/assets/img/air-puffs-assembly-2.24fed7c0.png differ diff --git a/assets/img/air-puffs-assembly-3.547d8721.png b/assets/img/air-puffs-assembly-3.547d8721.png new file mode 100644 index 0000000..7466321 Binary files /dev/null and b/assets/img/air-puffs-assembly-3.547d8721.png differ diff --git a/assets/img/air-puffs-assembly-4.fffb8216.png b/assets/img/air-puffs-assembly-4.fffb8216.png new file mode 100644 index 0000000..d9d89d5 Binary files /dev/null and b/assets/img/air-puffs-assembly-4.fffb8216.png differ diff --git a/assets/img/air-supply-1.b55dc9c2.png b/assets/img/air-supply-1.b55dc9c2.png new file mode 100644 index 0000000..dced12e Binary files /dev/null and b/assets/img/air-supply-1.b55dc9c2.png differ diff --git a/assets/img/air-supply-assembly-1.29f2b0ad.png b/assets/img/air-supply-assembly-1.29f2b0ad.png new file mode 100644 index 0000000..c4dfbd4 Binary files /dev/null and b/assets/img/air-supply-assembly-1.29f2b0ad.png differ diff --git a/assets/img/air-supply-assembly-10.a9ca8eca.png b/assets/img/air-supply-assembly-10.a9ca8eca.png new file mode 100644 index 0000000..5e3ced5 Binary files /dev/null and b/assets/img/air-supply-assembly-10.a9ca8eca.png differ diff --git a/assets/img/air-supply-assembly-2.ea81a458.png b/assets/img/air-supply-assembly-2.ea81a458.png new file mode 100644 index 0000000..3fd28ec Binary files /dev/null and b/assets/img/air-supply-assembly-2.ea81a458.png differ diff --git a/assets/img/air-supply-assembly-3.289d0cb4.png b/assets/img/air-supply-assembly-3.289d0cb4.png new file mode 100644 index 0000000..38c489f Binary files /dev/null and b/assets/img/air-supply-assembly-3.289d0cb4.png differ diff --git a/assets/img/air-supply-assembly-4.4479b2be.png b/assets/img/air-supply-assembly-4.4479b2be.png new file mode 100644 index 0000000..5b3e0ba Binary files /dev/null and b/assets/img/air-supply-assembly-4.4479b2be.png differ diff --git a/assets/img/air-supply-assembly-5.7b8ec64f.png b/assets/img/air-supply-assembly-5.7b8ec64f.png new file mode 100644 index 0000000..1120692 Binary files /dev/null and b/assets/img/air-supply-assembly-5.7b8ec64f.png differ diff --git a/assets/img/air-supply-assembly-6.1c08c16d.png b/assets/img/air-supply-assembly-6.1c08c16d.png new file mode 100644 index 0000000..cd3145b Binary files /dev/null and b/assets/img/air-supply-assembly-6.1c08c16d.png differ diff --git a/assets/img/air-supply-assembly-7.aefb75ce.png b/assets/img/air-supply-assembly-7.aefb75ce.png new file mode 100644 index 0000000..809aeaf Binary files /dev/null and b/assets/img/air-supply-assembly-7.aefb75ce.png differ diff --git a/assets/img/air-supply-assembly-8.f8966a11.png b/assets/img/air-supply-assembly-8.f8966a11.png new file mode 100644 index 0000000..a78ae88 Binary files /dev/null and b/assets/img/air-supply-assembly-8.f8966a11.png differ diff --git a/assets/img/air-supply-assembly-9.1b785f62.png b/assets/img/air-supply-assembly-9.1b785f62.png new file mode 100644 index 0000000..62715f8 Binary files /dev/null and b/assets/img/air-supply-assembly-9.1b785f62.png differ diff --git a/assets/img/anaconda_add_PATH.b4ba978b.png b/assets/img/anaconda_add_PATH.b4ba978b.png new file mode 100644 index 0000000..3c44176 Binary files /dev/null and b/assets/img/anaconda_add_PATH.b4ba978b.png differ diff --git a/assets/img/animal-position.bdb115ab.png b/assets/img/animal-position.bdb115ab.png new file mode 100644 index 0000000..f3424b3 Binary files /dev/null and b/assets/img/animal-position.bdb115ab.png differ diff --git a/assets/img/assembly-1.672195a3.png b/assets/img/assembly-1.672195a3.png new file mode 100644 index 0000000..6a4becd Binary files /dev/null and b/assets/img/assembly-1.672195a3.png differ diff --git a/assets/img/assembly-2.c36a8093.png b/assets/img/assembly-2.c36a8093.png new file mode 100644 index 0000000..794ff1c Binary files /dev/null and b/assets/img/assembly-2.c36a8093.png differ diff --git a/assets/img/assembly-3.b49e2e8b.png b/assets/img/assembly-3.b49e2e8b.png new file mode 100644 index 0000000..ad0ec7a Binary files /dev/null and b/assets/img/assembly-3.b49e2e8b.png differ diff --git a/assets/img/bottom-plate-assembly-1.bb5c1be5.png b/assets/img/bottom-plate-assembly-1.bb5c1be5.png new file mode 100644 index 0000000..8086454 Binary files /dev/null and b/assets/img/bottom-plate-assembly-1.bb5c1be5.png differ diff --git a/assets/img/bottom-plate-assembly-2.34499c3f.png b/assets/img/bottom-plate-assembly-2.34499c3f.png new file mode 100644 index 0000000..c11274e Binary files /dev/null and b/assets/img/bottom-plate-assembly-2.34499c3f.png differ diff --git a/assets/img/bottom-plate-assembly-3.ddc4213f.png b/assets/img/bottom-plate-assembly-3.ddc4213f.png new file mode 100644 index 0000000..4f9325c Binary files /dev/null and b/assets/img/bottom-plate-assembly-3.ddc4213f.png differ diff --git a/assets/img/cabinet-1.67653e95.png b/assets/img/cabinet-1.67653e95.png new file mode 100644 index 0000000..81f69e1 Binary files /dev/null and b/assets/img/cabinet-1.67653e95.png differ diff --git a/assets/img/cabinet-assembly-1.13ccccc9.png b/assets/img/cabinet-assembly-1.13ccccc9.png new file mode 100644 index 0000000..6bc119d Binary files /dev/null and b/assets/img/cabinet-assembly-1.13ccccc9.png differ diff --git a/assets/img/cabinet-assembly-10.66e4306a.png b/assets/img/cabinet-assembly-10.66e4306a.png new file mode 100644 index 0000000..cf96e9a Binary files /dev/null and b/assets/img/cabinet-assembly-10.66e4306a.png differ diff --git a/assets/img/cabinet-assembly-11.99ca124b.png b/assets/img/cabinet-assembly-11.99ca124b.png new file mode 100644 index 0000000..a519c38 Binary files /dev/null and b/assets/img/cabinet-assembly-11.99ca124b.png differ diff --git a/assets/img/cabinet-assembly-12.2fb54c9e.png b/assets/img/cabinet-assembly-12.2fb54c9e.png new file mode 100644 index 0000000..e428c10 Binary files /dev/null and b/assets/img/cabinet-assembly-12.2fb54c9e.png differ diff --git a/assets/img/cabinet-assembly-13.a7d42940.png b/assets/img/cabinet-assembly-13.a7d42940.png new file mode 100644 index 0000000..2d70808 Binary files /dev/null and b/assets/img/cabinet-assembly-13.a7d42940.png differ diff --git a/assets/img/cabinet-assembly-14.f657dbed.png b/assets/img/cabinet-assembly-14.f657dbed.png new file mode 100644 index 0000000..138fe12 Binary files /dev/null and b/assets/img/cabinet-assembly-14.f657dbed.png differ diff --git a/assets/img/cabinet-assembly-15.d2700ebc.png b/assets/img/cabinet-assembly-15.d2700ebc.png new file mode 100644 index 0000000..dfeca05 Binary files /dev/null and b/assets/img/cabinet-assembly-15.d2700ebc.png differ diff --git a/assets/img/cabinet-assembly-16.e1c48945.png b/assets/img/cabinet-assembly-16.e1c48945.png new file mode 100644 index 0000000..19b943d Binary files /dev/null and b/assets/img/cabinet-assembly-16.e1c48945.png differ diff --git a/assets/img/cabinet-assembly-17.13e13a17.png b/assets/img/cabinet-assembly-17.13e13a17.png new file mode 100644 index 0000000..6066c30 Binary files /dev/null and b/assets/img/cabinet-assembly-17.13e13a17.png differ diff --git a/assets/img/cabinet-assembly-18.968706b9.png b/assets/img/cabinet-assembly-18.968706b9.png new file mode 100644 index 0000000..febc2d8 Binary files /dev/null and b/assets/img/cabinet-assembly-18.968706b9.png differ diff --git a/assets/img/cabinet-assembly-19.677fc8b9.png b/assets/img/cabinet-assembly-19.677fc8b9.png new file mode 100644 index 0000000..8da092b Binary files /dev/null and b/assets/img/cabinet-assembly-19.677fc8b9.png differ diff --git a/assets/img/cabinet-assembly-2.3f687808.png b/assets/img/cabinet-assembly-2.3f687808.png new file mode 100644 index 0000000..46bba64 Binary files /dev/null and b/assets/img/cabinet-assembly-2.3f687808.png differ diff --git a/assets/img/cabinet-assembly-20.1f26db00.png b/assets/img/cabinet-assembly-20.1f26db00.png new file mode 100644 index 0000000..0de04c2 Binary files /dev/null and b/assets/img/cabinet-assembly-20.1f26db00.png differ diff --git a/assets/img/cabinet-assembly-21.2e8e54b5.png b/assets/img/cabinet-assembly-21.2e8e54b5.png new file mode 100644 index 0000000..fbd1540 Binary files /dev/null and b/assets/img/cabinet-assembly-21.2e8e54b5.png differ diff --git a/assets/img/cabinet-assembly-22.4cb21f1e.png b/assets/img/cabinet-assembly-22.4cb21f1e.png new file mode 100644 index 0000000..767f603 Binary files /dev/null and b/assets/img/cabinet-assembly-22.4cb21f1e.png differ diff --git a/assets/img/cabinet-assembly-3.92069fbf.png b/assets/img/cabinet-assembly-3.92069fbf.png new file mode 100644 index 0000000..15f30da Binary files /dev/null and b/assets/img/cabinet-assembly-3.92069fbf.png differ diff --git a/assets/img/cabinet-assembly-4.64afc3e2.png b/assets/img/cabinet-assembly-4.64afc3e2.png new file mode 100644 index 0000000..ecf3c4c Binary files /dev/null and b/assets/img/cabinet-assembly-4.64afc3e2.png differ diff --git a/assets/img/cabinet-assembly-5.822eb937.png b/assets/img/cabinet-assembly-5.822eb937.png new file mode 100644 index 0000000..bd11b06 Binary files /dev/null and b/assets/img/cabinet-assembly-5.822eb937.png differ diff --git a/assets/img/cabinet-assembly-6.d25eb191.png b/assets/img/cabinet-assembly-6.d25eb191.png new file mode 100644 index 0000000..ee1e482 Binary files /dev/null and b/assets/img/cabinet-assembly-6.d25eb191.png differ diff --git a/assets/img/cabinet-assembly-7.98f0662f.png b/assets/img/cabinet-assembly-7.98f0662f.png new file mode 100644 index 0000000..de4f3d6 Binary files /dev/null and b/assets/img/cabinet-assembly-7.98f0662f.png differ diff --git a/assets/img/cabinet-assembly-8.04c822ec.png b/assets/img/cabinet-assembly-8.04c822ec.png new file mode 100644 index 0000000..a92e168 Binary files /dev/null and b/assets/img/cabinet-assembly-8.04c822ec.png differ diff --git a/assets/img/cabinet-assembly-9.b0f9a0a9.png b/assets/img/cabinet-assembly-9.b0f9a0a9.png new file mode 100644 index 0000000..663b8a0 Binary files /dev/null and b/assets/img/cabinet-assembly-9.b0f9a0a9.png differ diff --git a/assets/img/cabinet-assembly-tip-1.08b8e88d.png b/assets/img/cabinet-assembly-tip-1.08b8e88d.png new file mode 100644 index 0000000..d0926f4 Binary files /dev/null and b/assets/img/cabinet-assembly-tip-1.08b8e88d.png differ diff --git a/assets/img/carrier-assembly-1.748029c5.png b/assets/img/carrier-assembly-1.748029c5.png new file mode 100644 index 0000000..32a13f2 Binary files /dev/null and b/assets/img/carrier-assembly-1.748029c5.png differ diff --git a/assets/img/carrier-assembly-2.eb42e186.png b/assets/img/carrier-assembly-2.eb42e186.png new file mode 100644 index 0000000..60f4259 Binary files /dev/null and b/assets/img/carrier-assembly-2.eb42e186.png differ diff --git a/assets/img/carrier-assembly-3.5332460c.png b/assets/img/carrier-assembly-3.5332460c.png new file mode 100644 index 0000000..0c6e6f5 Binary files /dev/null and b/assets/img/carrier-assembly-3.5332460c.png differ diff --git a/assets/img/control-1.31a5e2d2.png b/assets/img/control-1.31a5e2d2.png new file mode 100644 index 0000000..941e3f8 Binary files /dev/null and b/assets/img/control-1.31a5e2d2.png differ diff --git a/assets/img/control-assembly-1.3e1cb53a.png b/assets/img/control-assembly-1.3e1cb53a.png new file mode 100644 index 0000000..71f5a53 Binary files /dev/null and b/assets/img/control-assembly-1.3e1cb53a.png differ diff --git a/assets/img/control-assembly-10.92ccf29e.png b/assets/img/control-assembly-10.92ccf29e.png new file mode 100644 index 0000000..967d500 Binary files /dev/null and b/assets/img/control-assembly-10.92ccf29e.png differ diff --git a/assets/img/control-assembly-11.c0e33c40.png b/assets/img/control-assembly-11.c0e33c40.png new file mode 100644 index 0000000..23597c6 Binary files /dev/null and b/assets/img/control-assembly-11.c0e33c40.png differ diff --git a/assets/img/control-assembly-12.e58faff5.png b/assets/img/control-assembly-12.e58faff5.png new file mode 100644 index 0000000..407e27f Binary files /dev/null and b/assets/img/control-assembly-12.e58faff5.png differ diff --git a/assets/img/control-assembly-13.17922eb1.png b/assets/img/control-assembly-13.17922eb1.png new file mode 100644 index 0000000..c0966dd Binary files /dev/null and b/assets/img/control-assembly-13.17922eb1.png differ diff --git a/assets/img/control-assembly-14.da4ce5ef.png b/assets/img/control-assembly-14.da4ce5ef.png new file mode 100644 index 0000000..44adef2 Binary files /dev/null and b/assets/img/control-assembly-14.da4ce5ef.png differ diff --git a/assets/img/control-assembly-15.9864fdac.png b/assets/img/control-assembly-15.9864fdac.png new file mode 100644 index 0000000..03aa2f3 Binary files /dev/null and b/assets/img/control-assembly-15.9864fdac.png differ diff --git a/assets/img/control-assembly-16.d3892529.png b/assets/img/control-assembly-16.d3892529.png new file mode 100644 index 0000000..cf6cfd5 Binary files /dev/null and b/assets/img/control-assembly-16.d3892529.png differ diff --git a/assets/img/control-assembly-17.167fb961.png b/assets/img/control-assembly-17.167fb961.png new file mode 100644 index 0000000..c163a54 Binary files /dev/null and b/assets/img/control-assembly-17.167fb961.png differ diff --git a/assets/img/control-assembly-18.e06b9945.png b/assets/img/control-assembly-18.e06b9945.png new file mode 100644 index 0000000..ebaf8e4 Binary files /dev/null and b/assets/img/control-assembly-18.e06b9945.png differ diff --git a/assets/img/control-assembly-19.f1c2400d.png b/assets/img/control-assembly-19.f1c2400d.png new file mode 100644 index 0000000..f42d156 Binary files /dev/null and b/assets/img/control-assembly-19.f1c2400d.png differ diff --git a/assets/img/control-assembly-2.e729353b.png b/assets/img/control-assembly-2.e729353b.png new file mode 100644 index 0000000..bf3ea21 Binary files /dev/null and b/assets/img/control-assembly-2.e729353b.png differ diff --git a/assets/img/control-assembly-20.edc1b377.png b/assets/img/control-assembly-20.edc1b377.png new file mode 100644 index 0000000..ef1058f Binary files /dev/null and b/assets/img/control-assembly-20.edc1b377.png differ diff --git a/assets/img/control-assembly-21.cd2c2b31.png b/assets/img/control-assembly-21.cd2c2b31.png new file mode 100644 index 0000000..8213195 Binary files /dev/null and b/assets/img/control-assembly-21.cd2c2b31.png differ diff --git a/assets/img/control-assembly-3.3c613198.png b/assets/img/control-assembly-3.3c613198.png new file mode 100644 index 0000000..129b135 Binary files /dev/null and b/assets/img/control-assembly-3.3c613198.png differ diff --git a/assets/img/control-assembly-4.e9eb1fe1.png b/assets/img/control-assembly-4.e9eb1fe1.png new file mode 100644 index 0000000..a2c5b6e Binary files /dev/null and b/assets/img/control-assembly-4.e9eb1fe1.png differ diff --git a/assets/img/control-assembly-5.e85ae378.png b/assets/img/control-assembly-5.e85ae378.png new file mode 100644 index 0000000..3946d9c Binary files /dev/null and b/assets/img/control-assembly-5.e85ae378.png differ diff --git a/assets/img/control-assembly-6.548f0cbf.png b/assets/img/control-assembly-6.548f0cbf.png new file mode 100644 index 0000000..dda5100 Binary files /dev/null and b/assets/img/control-assembly-6.548f0cbf.png differ diff --git a/assets/img/control-assembly-7.516fd97f.png b/assets/img/control-assembly-7.516fd97f.png new file mode 100644 index 0000000..66a66c7 Binary files /dev/null and b/assets/img/control-assembly-7.516fd97f.png differ diff --git a/assets/img/control-assembly-8.9f7e66aa.png b/assets/img/control-assembly-8.9f7e66aa.png new file mode 100644 index 0000000..b53e6df Binary files /dev/null and b/assets/img/control-assembly-8.9f7e66aa.png differ diff --git a/assets/img/control-assembly-9.5188fee4.png b/assets/img/control-assembly-9.5188fee4.png new file mode 100644 index 0000000..8334322 Binary files /dev/null and b/assets/img/control-assembly-9.5188fee4.png differ diff --git a/assets/img/cup-assembly-1.4e833915.png b/assets/img/cup-assembly-1.4e833915.png new file mode 100644 index 0000000..9ba0e24 Binary files /dev/null and b/assets/img/cup-assembly-1.4e833915.png differ diff --git a/assets/img/cup-assembly-2.c8ce4dd4.png b/assets/img/cup-assembly-2.c8ce4dd4.png new file mode 100644 index 0000000..e1c7b05 Binary files /dev/null and b/assets/img/cup-assembly-2.c8ce4dd4.png differ diff --git a/assets/img/cup-assembly-3.f1330fe1.png b/assets/img/cup-assembly-3.f1330fe1.png new file mode 100644 index 0000000..8da07bb Binary files /dev/null and b/assets/img/cup-assembly-3.f1330fe1.png differ diff --git a/assets/img/cup-assembly-4.5abcb53b.png b/assets/img/cup-assembly-4.5abcb53b.png new file mode 100644 index 0000000..ebb6543 Binary files /dev/null and b/assets/img/cup-assembly-4.5abcb53b.png differ diff --git a/assets/img/cup-assembly-5.5a864976.png b/assets/img/cup-assembly-5.5a864976.png new file mode 100644 index 0000000..7a47080 Binary files /dev/null and b/assets/img/cup-assembly-5.5a864976.png differ diff --git a/assets/img/cup-with-optical-flow-sensor.a41b275e.png b/assets/img/cup-with-optical-flow-sensor.a41b275e.png new file mode 100644 index 0000000..38bd123 Binary files /dev/null and b/assets/img/cup-with-optical-flow-sensor.a41b275e.png differ diff --git a/assets/img/ephys_pipeline_basic_ERD.09d46df2.png b/assets/img/ephys_pipeline_basic_ERD.09d46df2.png new file mode 100644 index 0000000..cdcaa58 Binary files /dev/null and b/assets/img/ephys_pipeline_basic_ERD.09d46df2.png differ diff --git a/assets/img/experiment_code.5f9f7df4.png b/assets/img/experiment_code.5f9f7df4.png new file mode 100644 index 0000000..d136e93 Binary files /dev/null and b/assets/img/experiment_code.5f9f7df4.png differ diff --git a/assets/img/imaging_pipeline_basic_ERD.0e943a32.png b/assets/img/imaging_pipeline_basic_ERD.0e943a32.png new file mode 100644 index 0000000..b941e55 Binary files /dev/null and b/assets/img/imaging_pipeline_basic_ERD.0e943a32.png differ diff --git a/assets/img/lick-detection-1.52d3cd87.png b/assets/img/lick-detection-1.52d3cd87.png new file mode 100644 index 0000000..7953e97 Binary files /dev/null and b/assets/img/lick-detection-1.52d3cd87.png differ diff --git a/assets/img/lick-detection-2.042426c7.png b/assets/img/lick-detection-2.042426c7.png new file mode 100644 index 0000000..2b1176c Binary files /dev/null and b/assets/img/lick-detection-2.042426c7.png differ diff --git a/assets/img/manipulation_trainingGUI.37ef27b0.png b/assets/img/manipulation_trainingGUI.37ef27b0.png new file mode 100644 index 0000000..b39a828 Binary files /dev/null and b/assets/img/manipulation_trainingGUI.37ef27b0.png differ diff --git a/assets/img/mirror-assembly-1.dddd010c.png b/assets/img/mirror-assembly-1.dddd010c.png new file mode 100644 index 0000000..56b38a0 Binary files /dev/null and b/assets/img/mirror-assembly-1.dddd010c.png differ diff --git a/assets/img/mirror-assembly-2.9ec2a1d0.png b/assets/img/mirror-assembly-2.9ec2a1d0.png new file mode 100644 index 0000000..cc5af0e Binary files /dev/null and b/assets/img/mirror-assembly-2.9ec2a1d0.png differ diff --git a/assets/img/mirror-assembly-3.2b829575.png b/assets/img/mirror-assembly-3.2b829575.png new file mode 100644 index 0000000..2724991 Binary files /dev/null and b/assets/img/mirror-assembly-3.2b829575.png differ diff --git a/assets/img/mirror-assembly-4.09e46b5a.png b/assets/img/mirror-assembly-4.09e46b5a.png new file mode 100644 index 0000000..3a2e341 Binary files /dev/null and b/assets/img/mirror-assembly-4.09e46b5a.png differ diff --git a/assets/img/mirror-assembly-5.8a17e284.png b/assets/img/mirror-assembly-5.8a17e284.png new file mode 100644 index 0000000..5fd9f26 Binary files /dev/null and b/assets/img/mirror-assembly-5.8a17e284.png differ diff --git a/assets/img/motor_GUI.305a6fea.png b/assets/img/motor_GUI.305a6fea.png new file mode 100644 index 0000000..63cc1a9 Binary files /dev/null and b/assets/img/motor_GUI.305a6fea.png differ diff --git a/assets/img/path_table.8564e498.png b/assets/img/path_table.8564e498.png new file mode 100644 index 0000000..348d7b2 Binary files /dev/null and b/assets/img/path_table.8564e498.png differ diff --git a/assets/img/plot_frequency_sessions1.6ea83bcc.png b/assets/img/plot_frequency_sessions1.6ea83bcc.png new file mode 100644 index 0000000..6853a71 Binary files /dev/null and b/assets/img/plot_frequency_sessions1.6ea83bcc.png differ diff --git a/assets/img/plot_frequency_sessions2.302da2bb.png b/assets/img/plot_frequency_sessions2.302da2bb.png new file mode 100644 index 0000000..de1f2d2 Binary files /dev/null and b/assets/img/plot_frequency_sessions2.302da2bb.png differ diff --git a/assets/img/positioning-1.3c1fa371.png b/assets/img/positioning-1.3c1fa371.png new file mode 100644 index 0000000..35951d4 Binary files /dev/null and b/assets/img/positioning-1.3c1fa371.png differ diff --git a/assets/img/positioning-10.2d031a9c.png b/assets/img/positioning-10.2d031a9c.png new file mode 100644 index 0000000..5424ae3 Binary files /dev/null and b/assets/img/positioning-10.2d031a9c.png differ diff --git a/assets/img/positioning-2.2da2811b.png b/assets/img/positioning-2.2da2811b.png new file mode 100644 index 0000000..7669458 Binary files /dev/null and b/assets/img/positioning-2.2da2811b.png differ diff --git a/assets/img/positioning-3.025487a5.png b/assets/img/positioning-3.025487a5.png new file mode 100644 index 0000000..02b34d9 Binary files /dev/null and b/assets/img/positioning-3.025487a5.png differ diff --git a/assets/img/positioning-4.36296c6e.png b/assets/img/positioning-4.36296c6e.png new file mode 100644 index 0000000..de4d1c0 Binary files /dev/null and b/assets/img/positioning-4.36296c6e.png differ diff --git a/assets/img/positioning-5.4e122c4e.png b/assets/img/positioning-5.4e122c4e.png new file mode 100644 index 0000000..0b493ed Binary files /dev/null and b/assets/img/positioning-5.4e122c4e.png differ diff --git a/assets/img/positioning-6.dbcd6621.png b/assets/img/positioning-6.dbcd6621.png new file mode 100644 index 0000000..b0615ca Binary files /dev/null and b/assets/img/positioning-6.dbcd6621.png differ diff --git a/assets/img/positioning-7.6ec672a2.png b/assets/img/positioning-7.6ec672a2.png new file mode 100644 index 0000000..c063d9f Binary files /dev/null and b/assets/img/positioning-7.6ec672a2.png differ diff --git a/assets/img/positioning-8.0121a2e5.png b/assets/img/positioning-8.0121a2e5.png new file mode 100644 index 0000000..f5d7fd3 Binary files /dev/null and b/assets/img/positioning-8.0121a2e5.png differ diff --git a/assets/img/positioning-9.f1e7b05d.png b/assets/img/positioning-9.f1e7b05d.png new file mode 100644 index 0000000..b50d67e Binary files /dev/null and b/assets/img/positioning-9.f1e7b05d.png differ diff --git a/assets/img/positioning-tool.265ef066.png b/assets/img/positioning-tool.265ef066.png new file mode 100644 index 0000000..18ddca8 Binary files /dev/null and b/assets/img/positioning-tool.265ef066.png differ diff --git a/assets/img/program_wrapper_file.30569baa.png b/assets/img/program_wrapper_file.30569baa.png new file mode 100644 index 0000000..36040ee Binary files /dev/null and b/assets/img/program_wrapper_file.30569baa.png differ diff --git a/assets/img/projection-1.8e1de7a7.png b/assets/img/projection-1.8e1de7a7.png new file mode 100644 index 0000000..01fef9a Binary files /dev/null and b/assets/img/projection-1.8e1de7a7.png differ diff --git a/assets/img/projection-1.8f9e9c52.png b/assets/img/projection-1.8f9e9c52.png new file mode 100644 index 0000000..53d92fd Binary files /dev/null and b/assets/img/projection-1.8f9e9c52.png differ diff --git a/assets/img/projection-2.e4e10713.png b/assets/img/projection-2.e4e10713.png new file mode 100644 index 0000000..4c8f6f0 Binary files /dev/null and b/assets/img/projection-2.e4e10713.png differ diff --git a/assets/img/projector-assembly-1.d44c14c8.png b/assets/img/projector-assembly-1.d44c14c8.png new file mode 100644 index 0000000..e4e2349 Binary files /dev/null and b/assets/img/projector-assembly-1.d44c14c8.png differ diff --git a/assets/img/projector-assembly-2.46cdfb6f.png b/assets/img/projector-assembly-2.46cdfb6f.png new file mode 100644 index 0000000..ffe9c4c Binary files /dev/null and b/assets/img/projector-assembly-2.46cdfb6f.png differ diff --git a/assets/img/projector-assembly-3.d9afcd19.png b/assets/img/projector-assembly-3.d9afcd19.png new file mode 100644 index 0000000..8ad8873 Binary files /dev/null and b/assets/img/projector-assembly-3.d9afcd19.png differ diff --git a/assets/img/protocol_code.5e132141.png b/assets/img/protocol_code.5e132141.png new file mode 100644 index 0000000..28de781 Binary files /dev/null and b/assets/img/protocol_code.5e132141.png differ diff --git a/assets/img/pupillometry-1.ffd80c5b.png b/assets/img/pupillometry-1.ffd80c5b.png new file mode 100644 index 0000000..672a7c3 Binary files /dev/null and b/assets/img/pupillometry-1.ffd80c5b.png differ diff --git a/assets/img/pupillometry_DB_erd.55c680c5.png b/assets/img/pupillometry_DB_erd.55c680c5.png new file mode 100644 index 0000000..438118e Binary files /dev/null and b/assets/img/pupillometry_DB_erd.55c680c5.png differ diff --git a/assets/img/recording_automation_GUI_installer.a105b16c.png b/assets/img/recording_automation_GUI_installer.a105b16c.png new file mode 100644 index 0000000..5fb3e2e Binary files /dev/null and b/assets/img/recording_automation_GUI_installer.a105b16c.png differ diff --git a/assets/img/reward-1.6c17ae34.png b/assets/img/reward-1.6c17ae34.png new file mode 100644 index 0000000..daa7246 Binary files /dev/null and b/assets/img/reward-1.6c17ae34.png differ diff --git a/assets/img/reward-assembly-10.1ca5c246.png b/assets/img/reward-assembly-10.1ca5c246.png new file mode 100644 index 0000000..48c0240 Binary files /dev/null and b/assets/img/reward-assembly-10.1ca5c246.png differ diff --git a/assets/img/reward-assembly-5.76194562.png b/assets/img/reward-assembly-5.76194562.png new file mode 100644 index 0000000..e419e21 Binary files /dev/null and b/assets/img/reward-assembly-5.76194562.png differ diff --git a/assets/img/reward-assembly-6.baa00ee9.png b/assets/img/reward-assembly-6.baa00ee9.png new file mode 100644 index 0000000..519b84e Binary files /dev/null and b/assets/img/reward-assembly-6.baa00ee9.png differ diff --git a/assets/img/reward-assembly-7.6fbf9d86.png b/assets/img/reward-assembly-7.6fbf9d86.png new file mode 100644 index 0000000..568e0ae Binary files /dev/null and b/assets/img/reward-assembly-7.6fbf9d86.png differ diff --git a/assets/img/reward-assembly-8.f74b86a0.png b/assets/img/reward-assembly-8.f74b86a0.png new file mode 100644 index 0000000..8af295b Binary files /dev/null and b/assets/img/reward-assembly-8.f74b86a0.png differ diff --git a/assets/img/reward-assembly-9.171b8c2e.png b/assets/img/reward-assembly-9.171b8c2e.png new file mode 100644 index 0000000..e8bfbe9 Binary files /dev/null and b/assets/img/reward-assembly-9.171b8c2e.png differ diff --git a/assets/img/rigparameters_file.bacd3010.png b/assets/img/rigparameters_file.bacd3010.png new file mode 100644 index 0000000..6c9f9a2 Binary files /dev/null and b/assets/img/rigparameters_file.bacd3010.png differ diff --git a/assets/img/screen-assembly-1.c6af9ee1.png b/assets/img/screen-assembly-1.c6af9ee1.png new file mode 100644 index 0000000..ceba74d Binary files /dev/null and b/assets/img/screen-assembly-1.c6af9ee1.png differ diff --git a/assets/img/screen-assembly-2.c91f1041.png b/assets/img/screen-assembly-2.c91f1041.png new file mode 100644 index 0000000..6d1fc44 Binary files /dev/null and b/assets/img/screen-assembly-2.c91f1041.png differ diff --git a/assets/img/screen-building-1.ee236592.png b/assets/img/screen-building-1.ee236592.png new file mode 100644 index 0000000..b5e7cd4 Binary files /dev/null and b/assets/img/screen-building-1.ee236592.png differ diff --git a/assets/img/screen-building-10.72f36445.png b/assets/img/screen-building-10.72f36445.png new file mode 100644 index 0000000..cdc562e Binary files /dev/null and b/assets/img/screen-building-10.72f36445.png differ diff --git a/assets/img/screen-building-11.4d6b472c.png b/assets/img/screen-building-11.4d6b472c.png new file mode 100644 index 0000000..83b97dc Binary files /dev/null and b/assets/img/screen-building-11.4d6b472c.png differ diff --git a/assets/img/screen-building-12.aba7714f.png b/assets/img/screen-building-12.aba7714f.png new file mode 100644 index 0000000..85ef75e Binary files /dev/null and b/assets/img/screen-building-12.aba7714f.png differ diff --git a/assets/img/screen-building-13.9a91e736.png b/assets/img/screen-building-13.9a91e736.png new file mode 100644 index 0000000..017dc00 Binary files /dev/null and b/assets/img/screen-building-13.9a91e736.png differ diff --git a/assets/img/screen-building-14.a65cd15a.png b/assets/img/screen-building-14.a65cd15a.png new file mode 100644 index 0000000..ed06993 Binary files /dev/null and b/assets/img/screen-building-14.a65cd15a.png differ diff --git a/assets/img/screen-building-15.b1facc04.png b/assets/img/screen-building-15.b1facc04.png new file mode 100644 index 0000000..f9312e1 Binary files /dev/null and b/assets/img/screen-building-15.b1facc04.png differ diff --git a/assets/img/screen-building-16.494cb1d7.png b/assets/img/screen-building-16.494cb1d7.png new file mode 100644 index 0000000..45102bd Binary files /dev/null and b/assets/img/screen-building-16.494cb1d7.png differ diff --git a/assets/img/screen-building-17.224d15cd.png b/assets/img/screen-building-17.224d15cd.png new file mode 100644 index 0000000..2c92584 Binary files /dev/null and b/assets/img/screen-building-17.224d15cd.png differ diff --git a/assets/img/screen-building-18.9ce14e25.png b/assets/img/screen-building-18.9ce14e25.png new file mode 100644 index 0000000..4c5553d Binary files /dev/null and b/assets/img/screen-building-18.9ce14e25.png differ diff --git a/assets/img/screen-building-2.09e1ac3b.png b/assets/img/screen-building-2.09e1ac3b.png new file mode 100644 index 0000000..3cbf921 Binary files /dev/null and b/assets/img/screen-building-2.09e1ac3b.png differ diff --git a/assets/img/screen-building-3.8aa0d519.png b/assets/img/screen-building-3.8aa0d519.png new file mode 100644 index 0000000..424b3bc Binary files /dev/null and b/assets/img/screen-building-3.8aa0d519.png differ diff --git a/assets/img/screen-building-4.2bbcf29b.png b/assets/img/screen-building-4.2bbcf29b.png new file mode 100644 index 0000000..4f02153 Binary files /dev/null and b/assets/img/screen-building-4.2bbcf29b.png differ diff --git a/assets/img/screen-building-5.324c41de.png b/assets/img/screen-building-5.324c41de.png new file mode 100644 index 0000000..4291c79 Binary files /dev/null and b/assets/img/screen-building-5.324c41de.png differ diff --git a/assets/img/screen-building-6.22121c15.png b/assets/img/screen-building-6.22121c15.png new file mode 100644 index 0000000..275978c Binary files /dev/null and b/assets/img/screen-building-6.22121c15.png differ diff --git a/assets/img/screen-building-7.531f0362.png b/assets/img/screen-building-7.531f0362.png new file mode 100644 index 0000000..bdc40eb Binary files /dev/null and b/assets/img/screen-building-7.531f0362.png differ diff --git a/assets/img/screen-building-8.5cc97e50.png b/assets/img/screen-building-8.5cc97e50.png new file mode 100644 index 0000000..659ab1a Binary files /dev/null and b/assets/img/screen-building-8.5cc97e50.png differ diff --git a/assets/img/screen-building-9.1c05b188.png b/assets/img/screen-building-9.1c05b188.png new file mode 100644 index 0000000..a3af18e Binary files /dev/null and b/assets/img/screen-building-9.1c05b188.png differ diff --git a/assets/img/search.83621669.svg b/assets/img/search.83621669.svg new file mode 100644 index 0000000..03d8391 --- /dev/null +++ b/assets/img/search.83621669.svg @@ -0,0 +1 @@ + diff --git a/assets/img/sound-absorbing-sheet-1.ed30846e.png b/assets/img/sound-absorbing-sheet-1.ed30846e.png new file mode 100644 index 0000000..23587b3 Binary files /dev/null and b/assets/img/sound-absorbing-sheet-1.ed30846e.png differ diff --git a/assets/img/sound-absorbing-sheet-2.fb248b8d.png b/assets/img/sound-absorbing-sheet-2.fb248b8d.png new file mode 100644 index 0000000..729bea9 Binary files /dev/null and b/assets/img/sound-absorbing-sheet-2.fb248b8d.png differ diff --git a/assets/img/stage-1.850306fa.png b/assets/img/stage-1.850306fa.png new file mode 100644 index 0000000..71798de Binary files /dev/null and b/assets/img/stage-1.850306fa.png differ diff --git a/assets/img/stage-2.3f9d9bab.png b/assets/img/stage-2.3f9d9bab.png new file mode 100644 index 0000000..660f43a Binary files /dev/null and b/assets/img/stage-2.3f9d9bab.png differ diff --git a/assets/img/stage-3.0b818290.png b/assets/img/stage-3.0b818290.png new file mode 100644 index 0000000..da60ccf Binary files /dev/null and b/assets/img/stage-3.0b818290.png differ diff --git a/assets/img/stage-4.541fb6a2.png b/assets/img/stage-4.541fb6a2.png new file mode 100644 index 0000000..6be61a6 Binary files /dev/null and b/assets/img/stage-4.541fb6a2.png differ diff --git a/assets/img/stage-assembly-1.90c78380.png b/assets/img/stage-assembly-1.90c78380.png new file mode 100644 index 0000000..d578f35 Binary files /dev/null and b/assets/img/stage-assembly-1.90c78380.png differ diff --git a/assets/img/stage-assembly-2.fe4b9f02.png b/assets/img/stage-assembly-2.fe4b9f02.png new file mode 100644 index 0000000..b094465 Binary files /dev/null and b/assets/img/stage-assembly-2.fe4b9f02.png differ diff --git a/assets/img/stage-assembly-3.75e8edbc.png b/assets/img/stage-assembly-3.75e8edbc.png new file mode 100644 index 0000000..0daa2e2 Binary files /dev/null and b/assets/img/stage-assembly-3.75e8edbc.png differ diff --git a/assets/img/stage.f3e1f381.png b/assets/img/stage.f3e1f381.png new file mode 100644 index 0000000..1a74185 Binary files /dev/null and b/assets/img/stage.f3e1f381.png differ diff --git a/assets/img/subtask_trainingGUI.339eaae6.png b/assets/img/subtask_trainingGUI.339eaae6.png new file mode 100644 index 0000000..969b14b Binary files /dev/null and b/assets/img/subtask_trainingGUI.339eaae6.png differ diff --git a/assets/img/training-mini-vr.bc8b4a3a.png b/assets/img/training-mini-vr.bc8b4a3a.png new file mode 100644 index 0000000..6564620 Binary files /dev/null and b/assets/img/training-mini-vr.bc8b4a3a.png differ diff --git a/assets/img/training_GUI_description.88f68e6f.png b/assets/img/training_GUI_description.88f68e6f.png new file mode 100644 index 0000000..36c4c61 Binary files /dev/null and b/assets/img/training_GUI_description.88f68e6f.png differ diff --git a/assets/img/training_GUI_main.ab7e9891.png b/assets/img/training_GUI_main.ab7e9891.png new file mode 100644 index 0000000..87ea9bc Binary files /dev/null and b/assets/img/training_GUI_main.ab7e9891.png differ diff --git a/assets/img/training_GUI_main2.62046b80.png b/assets/img/training_GUI_main2.62046b80.png new file mode 100644 index 0000000..ce2a16b Binary files /dev/null and b/assets/img/training_GUI_main2.62046b80.png differ diff --git a/assets/img/training_gui_pupillometry.85699e0d.png b/assets/img/training_gui_pupillometry.85699e0d.png new file mode 100644 index 0000000..45c79f3 Binary files /dev/null and b/assets/img/training_gui_pupillometry.85699e0d.png differ diff --git a/assets/img/u19_automation_ERD.834911be.png b/assets/img/u19_automation_ERD.834911be.png new file mode 100644 index 0000000..785fcdd Binary files /dev/null and b/assets/img/u19_automation_ERD.834911be.png differ diff --git a/assets/img/velocity_subject.0e563aaf.png b/assets/img/velocity_subject.0e563aaf.png new file mode 100644 index 0000000..85e54f3 Binary files /dev/null and b/assets/img/velocity_subject.0e563aaf.png differ diff --git a/assets/img/virmen_gui.d5b4c0b7.png b/assets/img/virmen_gui.d5b4c0b7.png new file mode 100644 index 0000000..05a69d8 Binary files /dev/null and b/assets/img/virmen_gui.d5b4c0b7.png differ diff --git a/assets/img/vrrigs_login.84b9efc0.png b/assets/img/vrrigs_login.84b9efc0.png new file mode 100644 index 0000000..c7255f1 Binary files /dev/null and b/assets/img/vrrigs_login.84b9efc0.png differ diff --git a/assets/img/vrrigs_ssh_keys.56b1f880.png b/assets/img/vrrigs_ssh_keys.56b1f880.png new file mode 100644 index 0000000..6bfb7c0 Binary files /dev/null and b/assets/img/vrrigs_ssh_keys.56b1f880.png differ diff --git a/assets/img/workflow_manager_jobs.9d7f827b.png b/assets/img/workflow_manager_jobs.9d7f827b.png new file mode 100644 index 0000000..b88b20f Binary files /dev/null and b/assets/img/workflow_manager_jobs.9d7f827b.png differ diff --git a/assets/img/workflow_manager_recordings.e88a0dcc.png b/assets/img/workflow_manager_recordings.e88a0dcc.png new file mode 100644 index 0000000..43fbc7f Binary files /dev/null and b/assets/img/workflow_manager_recordings.e88a0dcc.png differ diff --git a/assets/js/1.c51b9512.js b/assets/js/1.c51b9512.js new file mode 100644 index 0000000..52cb7a0 --- /dev/null +++ b/assets/js/1.c51b9512.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[1,20,23,35,36,42],{242:function(t,e,n){"use strict";n.d(e,"d",(function(){return s})),n.d(e,"a",(function(){return r})),n.d(e,"i",(function(){return o})),n.d(e,"f",(function(){return l})),n.d(e,"g",(function(){return u})),n.d(e,"h",(function(){return c})),n.d(e,"b",(function(){return h})),n.d(e,"e",(function(){return f})),n.d(e,"k",(function(){return p})),n.d(e,"l",(function(){return d})),n.d(e,"c",(function(){return m})),n.d(e,"j",(function(){return k}));n(90);const s=/#.*$/,i=/\.(md|html)$/,r=/\/$/,o=/^[a-z]+:/i;function a(t){return decodeURI(t).replace(s,"").replace(i,"")}function l(t){return o.test(t)}function u(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function h(t){if(l(t))return t;const e=t.match(s),n=e?e[0]:"",i=a(t);return r.test(i)?t:i+".html"+n}function f(t,e){const n=decodeURIComponent(t.hash),i=function(t){const e=t.match(s);if(e)return e[0]}(e);if(i&&n!==i)return!1;return a(t.path)===a(e)}function p(t,e,n){if(l(e))return{type:"external",path:e};n&&(e=function(t,e,n){const s=t.charAt(0);if("/"===s)return t;if("?"===s||"#"===s)return e+t;const i=e.split("/");n&&i[i.length-1]||i.pop();const r=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(e,n,s,i=1){if("string"==typeof e)return p(n,e,s);if(Array.isArray(e))return Object.assign(p(n,e[0],s),{title:e[1]});{const r=e.children||[];return 0===r.length&&e.path?Object.assign(p(n,e.path,s),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:r.map(e=>t(e,n,s,i+1)),collapsable:!1!==e.collapsable}}}(t,i,n)):[]}return[]}function g(t){const e=m(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function m(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function k(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},243:function(t,e,n){},244:function(t,e,n){"use strict";n.r(e);var s=n(242),i={name:"NavLink",props:{item:{required:!0}},computed:{link(){return Object(s.b)(this.item.link)},exact(){return this.$site.locales?Object.keys(this.$site.locales).some(t=>t===this.link):"/"===this.link},isNonHttpURI(){return Object(s.g)(this.link)||Object(s.h)(this.link)},isBlankTarget(){return"_blank"===this.target},isInternal(){return!Object(s.f)(this.link)&&!this.isBlankTarget},target(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(s.f)(this.link)?"_blank":""},rel(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction(){this.$emit("focusout")}}},r=n(10),o=Object(r.a)(i,(function(){var t=this,e=t._self._c;return t.isInternal?e("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):e("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?e("OutboundLink"):t._e()],1)}),[],!1,null,null,null);e.default=o.exports},245:function(t,e,n){"use strict";n.r(e);var s={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},i=(n(246),n(10)),r=Object(i.a)(s,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.default=r.exports},246:function(t,e,n){"use strict";n(243)},247:function(t,e,n){},250:function(t,e,n){},254:function(t,e,n){"use strict";n(247)},257:function(t,e,n){"use strict";n.r(e);var s=n(244),i=n(245),r=n(91),o=n.n(r),a={name:"DropdownLink",components:{NavLink:s.default,DropdownTransition:i.default},props:{item:{required:!0}},data:()=>({open:!1}),computed:{dropdownAriaLabel(){return this.item.ariaLabel||this.item.text}},watch:{$route(){this.open=!1}},methods:{setOpen(t){this.open=t},isLastItemOfArray:(t,e)=>o()(e)===t,handleDropdown(){0===event.detail&&this.setOpen(!this.open)}}},l=(n(254),n(10)),u=Object(l.a)(a,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[e("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:t.handleDropdown}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow down"})]),t._v(" "),e("button",{staticClass:"mobile-dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),e("DropdownTransition",[e("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(n,s){return e("li",{key:n.link||s,staticClass:"dropdown-item"},["links"===n.type?e("h4",[t._v("\n "+t._s(n.text)+"\n ")]):t._e(),t._v(" "),"links"===n.type?e("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(n.items,(function(s){return e("li",{key:s.link,staticClass:"dropdown-subitem"},[e("NavLink",{attrs:{item:s},on:{focusout:function(e){t.isLastItemOfArray(s,n.items)&&t.isLastItemOfArray(n,t.item.items)&&t.setOpen(!1)}}})],1)})),0):e("NavLink",{attrs:{item:n},on:{focusout:function(e){t.isLastItemOfArray(n,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null);e.default=u.exports},260:function(t,e,n){"use strict";n(250)},261:function(t,e,n){},268:function(t,e,n){"use strict";n.r(e);var s=n(257),i=n(242),r={name:"NavLinks",components:{NavLink:n(244).default,DropdownLink:s.default},computed:{userNav(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav(){const{locales:t}=this.$site;if(t&&Object.keys(t).length>1){const e=this.$page.path,n=this.$router.options.routes,s=this.$site.themeConfig.locales||{},i={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(t).map(i=>{const r=t[i],o=s[i]&&s[i].label||r.lang;let a;return r.lang===this.$lang?a=e:(a=e.replace(this.$localeConfig.path,i),n.some(t=>t.path===a)||(a=i)),{text:o,link:a}})};return[...this.userNav,i]}return this.userNav},userLinks(){return(this.nav||[]).map(t=>Object.assign(Object(i.j)(t),{items:(t.items||[]).map(i.j)}))},repoLink(){const{repo:t}=this.$site.themeConfig;return t?/^https?:/.test(t)?t:"https://github.com/"+t:null},repoLabel(){if(!this.repoLink)return;if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;const t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"];for(let n=0;n{let s=i()(e,"title","");return i()(e,"frontmatter.tags")&&(s+=" "+e.frontmatter.tags.join(" ")),n&&(s+=" "+n),o(t,s)};const o=(t,e)=>{const n=t=>t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),s=new RegExp("[^\0-]"),i=t.split(/\s+/g).map(t=>t.trim()).filter(t=>!!t);if(s.test(t))return i.some(t=>e.toLowerCase().indexOf(t)>-1);{const s=t.endsWith(" ");return new RegExp(i.map((t,e)=>i.length!==e+1||s?`(?=.*\\b${n(t)}\\b)`:`(?=.*\\b${n(t)})`).join("")+".+","gi").test(e)}};var a={name:"SearchBox",data:()=>({query:"",focused:!1,focusIndex:0,placeholder:void 0}),computed:{showSuggestions(){return this.focused&&this.suggestions&&this.suggestions.length},suggestions(){const t=this.query.trim().toLowerCase();if(!t)return;const{pages:e}=this.$site,n=this.$site.themeConfig.searchMaxSuggestions||5,s=this.$localePath,i=[];for(let o=0;o=n);o++){const a=e[o];if(this.getPageLocalePath(a)===s&&this.isSearchable(a))if(r(t,a))i.push(a);else if(a.headers)for(let e=0;e=n);e++){const n=a.headers[e];n.title&&r(t,a,n.title)&&i.push(Object.assign({},a,{path:a.path+"#"+n.slug,header:n}))}}return i},alignRight(){return(this.$site.themeConfig.nav||[]).length+(this.$site.repo?1:0)<=2}},mounted(){this.placeholder=this.$site.themeConfig.searchPlaceholder||"",document.addEventListener("keydown",this.onHotkey)},beforeDestroy(){document.removeEventListener("keydown",this.onHotkey)},methods:{getPageLocalePath(t){for(const e in this.$site.locales||{})if("/"!==e&&0===t.path.indexOf(e))return e;return"/"},isSearchable(t){let e=null;return null===e||(e=Array.isArray(e)?e:new Array(e),e.filter(e=>t.path.match(e)).length>0)},onHotkey(t){t.srcElement===document.body&&["s","/"].includes(t.key)&&(this.$refs.input.focus(),t.preventDefault())},onUp(){this.showSuggestions&&(this.focusIndex>0?this.focusIndex--:this.focusIndex=this.suggestions.length-1)},onDown(){this.showSuggestions&&(this.focusIndex "+t._s(n.header.title))]):t._e()])])})),0):t._e()])}),[],!1,null,null,null).exports,c=n(288),h=n(268);function f(t,e){return t.ownerDocument.defaultView.getComputedStyle(t,null)[e]}var p={name:"Navbar",components:{SidebarButton:c.default,NavLinks:h.default,SearchBox:u,AlgoliaSearchBox:{}},data:()=>({linksWrapMaxWidth:null}),computed:{algolia(){return this.$themeLocaleConfig.algolia||this.$site.themeConfig.algolia||{}},isAlgoliaSearch(){return this.algolia&&this.algolia.apiKey&&this.algolia.indexName}},mounted(){const t=parseInt(f(this.$el,"paddingLeft"))+parseInt(f(this.$el,"paddingRight")),e=()=>{document.documentElement.clientWidth<719?this.linksWrapMaxWidth=null:this.linksWrapMaxWidth=this.$el.offsetWidth-t-(this.$refs.siteName&&this.$refs.siteName.offsetWidth||0)};e(),window.addEventListener("resize",e,!1)}},d=(n(295),Object(l.a)(p,(function(){var t=this,e=t._self._c;return e("header",{staticClass:"navbar"},[e("SidebarButton",{on:{"toggle-sidebar":function(e){return t.$emit("toggle-sidebar")}}}),t._v(" "),e("RouterLink",{staticClass:"home-link",attrs:{to:t.$localePath}},[t.$site.themeConfig.logo?e("img",{staticClass:"logo",attrs:{src:t.$withBase(t.$site.themeConfig.logo),alt:t.$siteTitle}}):t._e(),t._v(" "),t.$siteTitle?e("span",{ref:"siteName",staticClass:"site-name",class:{"can-hide":t.$site.themeConfig.logo}},[t._v(t._s(t.$siteTitle))]):t._e()]),t._v(" "),e("div",{staticClass:"links",style:t.linksWrapMaxWidth?{"max-width":t.linksWrapMaxWidth+"px"}:{}},[t.isAlgoliaSearch?e("AlgoliaSearchBox",{attrs:{options:t.algolia}}):!1!==t.$site.themeConfig.search&&!1!==t.$page.frontmatter.search?e("SearchBox"):t._e(),t._v(" "),e("NavLinks",{staticClass:"can-hide"})],1)],1)}),[],!1,null,null,null));e.default=d.exports}}]); \ No newline at end of file diff --git a/assets/js/10.28ab9cf5.js b/assets/js/10.28ab9cf5.js new file mode 100644 index 0000000..6bf2a85 --- /dev/null +++ b/assets/js/10.28ab9cf5.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[10],{380:function(e,t,a){e.exports=a.p+"assets/img/projection-1.8f9e9c52.png"},381:function(e,t,a){e.exports=a.p+"assets/img/mirror-assembly-1.dddd010c.png"},382:function(e,t,a){e.exports=a.p+"assets/img/mirror-assembly-2.9ec2a1d0.png"},383:function(e,t,a){e.exports=a.p+"assets/img/mirror-assembly-3.2b829575.png"},384:function(e,t,a){e.exports=a.p+"assets/img/mirror-assembly-4.09e46b5a.png"},385:function(e,t,a){e.exports=a.p+"assets/img/mirror-assembly-5.8a17e284.png"},386:function(e,t,a){e.exports=a.p+"assets/img/projector-assembly-1.d44c14c8.png"},387:function(e,t,a){e.exports=a.p+"assets/img/projector-assembly-2.46cdfb6f.png"},388:function(e,t,a){e.exports=a.p+"assets/img/projector-assembly-3.d9afcd19.png"},389:function(e,t,a){e.exports=a.p+"assets/img/screen-building-1.ee236592.png"},390:function(e,t,a){e.exports=a.p+"assets/img/screen-building-2.09e1ac3b.png"},391:function(e,t,a){e.exports=a.p+"assets/img/screen-building-3.8aa0d519.png"},392:function(e,t,a){e.exports=a.p+"assets/img/screen-building-4.2bbcf29b.png"},393:function(e,t,a){e.exports=a.p+"assets/img/screen-building-5.324c41de.png"},394:function(e,t,a){e.exports=a.p+"assets/img/screen-building-6.22121c15.png"},395:function(e,t,a){e.exports=a.p+"assets/img/screen-building-7.531f0362.png"},396:function(e,t,a){e.exports=a.p+"assets/img/screen-building-8.5cc97e50.png"},397:function(e,t,a){e.exports=a.p+"assets/img/screen-building-9.1c05b188.png"},398:function(e,t,a){e.exports=a.p+"assets/img/screen-building-10.72f36445.png"},399:function(e,t,a){e.exports=a.p+"assets/img/screen-building-11.4d6b472c.png"},400:function(e,t,a){e.exports=a.p+"assets/img/screen-building-12.aba7714f.png"},401:function(e,t,a){e.exports=a.p+"assets/img/screen-building-13.9a91e736.png"},402:function(e,t,a){e.exports=a.p+"assets/img/screen-building-14.a65cd15a.png"},403:function(e,t,a){e.exports=a.p+"assets/img/screen-building-15.b1facc04.png"},404:function(e,t,a){e.exports=a.p+"assets/img/screen-building-16.494cb1d7.png"},405:function(e,t,a){e.exports=a.p+"assets/img/screen-building-17.224d15cd.png"},406:function(e,t,a){e.exports=a.p+"assets/img/screen-building-18.9ce14e25.png"},407:function(e,t,a){e.exports=a.p+"assets/img/screen-assembly-1.c6af9ee1.png"},408:function(e,t,a){e.exports=a.p+"assets/img/screen-assembly-2.c91f1041.png"},510:function(e,t,a){"use strict";a.r(t);var r=a(10),s=Object(r.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("p",[e._v("The projection module consist on the screen assembly inside the cabinet, a projector is positioned at the back of the exterior part of the cabinet and it throws the image towards an spherical mirror attached to the cabinet positioned in the bottom part of the screen. The spherical mirror reflects the image onto the dome screen.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(380)}}),e._v(" "),t("center",[t("figcaption",[t("small",[e._v("Projection assembly. The projector is for display purposes only and it is not the same model than the actual one.")])])])],1),e._v(" "),t("h2",{attrs:{id:"mirror"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#mirror"}},[e._v("#")]),e._v(" Mirror")]),e._v(" "),t("p",[e._v("The spherical mirror is custom made from Thorlabs with the item number LA1740-P01-SP, be sure to contact them for a quote before polaceing the order and ask for the price breaks if you're planning to build more than 5 training rigs (it could go down up to 50% from 5 to 10 pieces).")]),e._v(" "),t("p",[e._v("We place the spherical mirror on an aluminum custom made base that is sent to a machine shop. The instruction for the assembly are descripted below.")]),e._v(" "),t("ol",[t("li",[e._v('Start by assembling the mirror holder, which is composed of the custom made holder, one 1" diameter 2" long post (RS1), one 1" diameter 1.5" long post (RS2) and a BA2 post base from Thorlabs. Use a screwdriver thin enough to pass through the hole at the center of the post and apply enough force to properly screw each piece onto each other.')])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(381)}})]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("To align the pieces, screw the base but not all the way. Then, place the pieces on a flat surface and make sure that both the mirror base and the BA2 post base lie completely flat on the surface, apply some force with one of your hands to make sure they stay that way and with the other hand tight screw the base.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(382)}})]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("Use a file to scratch the surface that will hold the mirror, then clean it with ethanol. Use estructural epoxy, follow the instruction on your specific type, and apply to the aluminum base. Make sure to use a nitrile gloves to carefully place the mirror on top of the base and apply some pressure to let it sit flat on the base surface, wait and clean apoxy leakage if any. Let the epoxy dry for 24 hrs.")])]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("Apply just a sufficient ammount of epoxy in the middle of the aluminum base, don't spread it all over since it could leak once you place the mirror and apply pressure on it.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(383)}})]),e._v(" "),t("figure",[t("img",{attrs:{src:a(384)}})]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[e._v("Screw the mirror and the base to the cabinet bottom plate using 1/4-20 screws, make sure to place the base as far as it can get from the stage (push it all the ways toward the projector, then screw it), as shown below.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(385)}})]),e._v(" "),t("h2",{attrs:{id:"projector"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#projector"}},[e._v("#")]),e._v(" Projector")]),e._v(" "),t("p",[e._v("The projector is installed at the back of the cabinet, at the top of a T-slotted frame structure. To assembly, use a couple of T-slot fasteners and place them on the frame at the back of the cabinet. Then, loosely screw the projector aluminum plate, measure 1 and 1/4 inches from the edge of the plate to the intersection of the frames as shown in the pictures below and tighten the screws. Finally, screw the projector to the aluminum plate.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(386)}})]),e._v(" "),t("figure",[t("img",{attrs:{src:a(387)}})]),e._v(" "),t("figure",[t("img",{attrs:{src:a(388)}})]),e._v(" "),t("h2",{attrs:{id:"screen-building"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#screen-building"}},[e._v("#")]),e._v(" Screen building")]),e._v(" "),t("p",[e._v("The whole process of screen building can take up to 5 days. We describe the whole process in steps, adding which steps we make in a day and the time it took for us to follow the steps. We recommend to do it this way to allow the materials to properly dry. You could use the time it takes to dry to parallelize the work and assembly other modules in the meantime.")]),e._v(" "),t("p",[e._v('The first step for building the projection module consist on the fabrication of the dome screen. A styrofoam ball of 18" outer diameter and 16" inner diameter is being fabricated by an external provider. For ease of transportation the screens were sent as half spheres.')]),e._v(" "),t("h3",{attrs:{id:"day-1-time-3-hours"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#day-1-time-3-hours"}},[e._v("#")]),e._v(" Day 1 [time: ~3 hours].")]),e._v(" "),t("ol",[t("li",[e._v('If the balls are shipped in halfs, first mark the equator in each of the half spheres. Use a thread to measure the outer diameter of the screen (should be around 18") and place a mark at the middle (or around 9"), place the thread at the bottom of the half sphere and mark at the sphere the joint of the thread and the middle (9") mark. We use a laser level to project a straight line through both marks and draw a line with a sharpie.')])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(389)}})]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("Use 3M Foam Fast 74 CA spray adhesive to glue both half spheres. Spray from 3 to 5 inches away both surfaces and wait for 1 minute, then attach both half spheres making sure to match the equator drawed lines, apply pressure on the union and leave it to dry and harden for at least 15 min.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(390)}})]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("Use lightweight joint compound to fill the line and the holes the adhesive might have caused, use a hand applicator to spread even on the surface trying to keep it as as smooth as possible. Let the joint compound dry from 30 min to 1 hour.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(391)}})]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[t("p",[e._v("Place the aluminum plate in a flat surface making sure is hanging with enough space to fit the screen. Use a sharpie to mark a straigth line by joining the marks in the aluminum plate (placed at the middle of the circle) as seen in the pictures. Place the screen in the plate, making sure to align the equator with the plate and the meridian (the mark where the half spheres where joined) with the plate marked line.")]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("Sometimes the diameter of the balls is different from the plate, you can use some paper or carboard and tape it to fill the space between the screen and the plate for it to hang properly.")])])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(392)}})]),e._v(" "),t("ol",{attrs:{start:"5"}},[t("li",[e._v("Glue about 5 inches of the sides and the back of the ball with an electric glue gun and wit for it to harden. Once cold, remove taped paper/cardboard and turn the plate around and glue the whole screen to the aluminum plate, wait for it to harden; turn once more time the plate and finish gluing the top part of the screen to the plate.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(393)}})]),e._v(" "),t("h3",{attrs:{id:"day-2-time-3-hours"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#day-2-time-3-hours"}},[e._v("#")]),e._v(" Day 2 [time: ~3 hours]")]),e._v(" "),t("ol",[t("li",[t("p",[e._v('Place the screen with the plate on a flat surface. We use a couple 14" (1 inch diameter) pillars, other stuff could potentially be used just making sure the ball is freely hanguing from the plate and have enough space (at least ~6 inches) from the bottom of the screen to the flat surface. We place the pillars diagonally for stability.')]),e._v(" "),t("p",[e._v('Mark a line below 4.75" from the equator of the screen. We use a set of Thorlabs BA2 and 1/2" post (with a post holder) with a 90 degrees 1/2" post holder to insert a sharpie marker as a tool to mark the line. We set the height of the post at 4.75" below the equator and then mark the screen by moving the shapie along making sure the tool is flat on the surface.')])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(394)}})]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("Place a mark at the half of the scren across the meridian using the same tool as step 1 in day 1. The place the laser level in the flat surface facing the screen, use the vertical laser to throw a projection and align both marks at the half of the screen across the meridian. Mark a line from the top to the bottom of the screen (at least at the bottom line).")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(395)}})]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v('Measure from the joint of the two half spheres 4" to the top and 4.75" to the sides, place a mark and draw by hand a half circle using those 3 points.')])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(396)}})]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[e._v('Place a mark at 4.75" and at 6" from the midline along the joint of the spheres (at the top) and along the equator. Use the laser level to project a line from the top marks to the marks on the equator and draw with a marker a pointed line.')])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(397)}})]),e._v(" "),t("ol",{attrs:{start:"5"}},[t("li",[e._v('Place a mark at 2.5" from the equator to the top of the ball along the 4.75" and 6" lines.')])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(398)}})]),e._v(" "),t("ol",{attrs:{start:"6"}},[t("li",[t("p",[e._v("Join with a marker (we used a different color to make it noticeable) the intersections between the pointed lines as shown in the pictures below.")]),e._v(" "),t("ul",[t("li",[e._v('(A & I) The intersection between the bottom 4.75" line from the equator and the 6" line from the meridian.')]),e._v(" "),t("li",[e._v('(B & H) The intersection between the top 2.5" line from the equator and the 6" line from the meridian.')]),e._v(" "),t("li",[e._v('(C & G) The intersection between the top 2.5" line from the equator and the 4.75" line from the meridian.')]),e._v(" "),t("li",[e._v('(D & F) The intersection between the top joint of the sphere and the 4.75" line from the meridian.')]),e._v(" "),t("li",[e._v('(E) The intersection between the top 4" mark from the top joint of the sphere and the meridian.')])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(399)}})])]),e._v(" "),t("li",[t("p",[e._v("Use a styrofoam cutter (we use the "),t("em",[e._v("200 W Pro Electric Hot Knife from RoMech Foam Cutter")]),e._v(") to cut the sphere though the marked lines. We recommend to use a bench vise or C-clamps to hold the sphere through the aluminum plate follow the next steps:")]),e._v(" "),t("ul",[t("li",[e._v('Cut the bottom part of the sphere following the line marked at 4.75" below the equator.')]),e._v(" "),t("li",[e._v("Cut the line through intersections (B) toward (A).")]),e._v(" "),t("li",[e._v("Cut the line through the instersection (D) toward (C).")]),e._v(" "),t("li",[e._v("Cut the line through the intersection (B) toward (C).")]),e._v(" "),t("li",[e._v("Repeat the steps for the other side.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(400)}})]),e._v(" "),t("ul",[t("li",[e._v("Cut the line through the intersection (D) toward (F).")]),e._v(" "),t("li",[e._v("Remove cutted styrofoam part as shown in the picture below.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(401)}})]),e._v(" "),t("ul",[t("li",[e._v("Cut a line from the mark (E) toward the bottom of the sphere.")]),e._v(" "),t("li",[e._v("Cut a line through the intersection (D) toward (E) and remove the cutted styrofoam part.")]),e._v(" "),t("li",[e._v("Cut a line through the intersection (F) toward (E) and remove the cutted styrofoam part.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(402)}})])]),e._v(" "),t("li",[t("p",[e._v("Apply joint compound to the crack on the half spheres intersection from the inside of the screen using a curved rubber wipe down knife. Let it dry overnight and apply a second hand if necessary to have a smooth surface.")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(403)}})]),e._v(" "),t("h3",{attrs:{id:"day-3-time-1-hour"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#day-3-time-1-hour"}},[e._v("#")]),e._v(" Day 3 [time: ~1 hour]")]),e._v(" "),t("ol",[t("li",[e._v("Apply All purpose foam coat + Bounce from Hot Wire Factory following the instructions for mixing (just make sure the mix is thin enough to handle but thick enough to work as a protective layer). Apply one coat to the exterior part of the sphere, if you find the layer to thin you can apply 2 layers. We recommend to first apply to the top part of the sphere from the aluminum plate, then the bottom part and finally the cutted edges of the sphere (everything but the inner surface of the sphere). Let it dry for 24 hrs.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(404)}})]),e._v(" "),t("h3",{attrs:{id:"day-4-time-1-2-hour-each-layer-plus-drying-time"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#day-4-time-1-2-hour-each-layer-plus-drying-time"}},[e._v("#")]),e._v(" Day 4 [time: ~1/2 hour each layer plus drying time]")]),e._v(" "),t("ol",[t("li",[e._v("Apply white lightweight spackling to the inner surface of the sphere using a curved rubber wipe down knife, making sure cover the imperfections on the surface as much as you can. Let it dry for ~3 hours (or more depending on ambient temperature and humidity), you can touch the surface and it shouldn't stick to your hand. Sand the surface and apply another layer. Repeat the process from 2 to 3 times until you get a smooth surface on the screen.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(405)}})]),e._v(" "),t("h3",{attrs:{id:"day-5-time-1-2-hour-each-layer-plus-drying-time"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#day-5-time-1-2-hour-each-layer-plus-drying-time"}},[e._v("#")]),e._v(" Day 5 [time: ~1/2 hour each layer plus drying time]")]),e._v(" "),t("ol",[t("li",[t("p",[e._v('Paint the outer part of the screen with a black matte paint (we recommend the black paint on screen wall and ceiling ambien light rejectting acoustic dampening) using a 3" or 4" brush. Do not paint the edges of the screen yet. Apply 2 layers of paint to the outer part.')])]),e._v(" "),t("li",[t("p",[e._v("Use a roller to paint the inner part of the screen. Apply 1 layer of primer (we recommend to use the paint on screen leveling primer) and 2 to 3 layers of silver paint (we use the paint on screen S1 Screen Plus).")])]),e._v(" "),t("li",[t("p",[e._v('Using a 1" brush paint the edges of the sphere with black matte paint.')])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(406)}})]),e._v(" "),t("h2",{attrs:{id:"screen-assembly"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#screen-assembly"}},[e._v("#")]),e._v(" Screen assembly")]),e._v(" "),t("p",[e._v("Once the screen is built, follow the isntructions to install them in the cabinet.")]),e._v(" "),t("ol",[t("li",[e._v('Assemble the 1.5" diameter 10" long posts (P10) by screwing a pair of mounting bases (BA2) from Thorlabs at the bottom. Then install the posts to the cabinet bottom plate using 1/4-20 screws at at the closest position to the projector as shown in the picture below.')])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(407)}})]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("Have the custom made aluminum screen plate to post adapter in a machine shop, then screw it to the screen plate and place it over the posts. Tight screw the screen to the posts.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(408)}})])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/11.b8e01274.js b/assets/js/11.b8e01274.js new file mode 100644 index 0000000..fbab31b --- /dev/null +++ b/assets/js/11.b8e01274.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{315:function(t,e,s){t.exports=s.p+"assets/img/cabinet-1.67653e95.png"},316:function(t,e,s){t.exports=s.p+"assets/img/sound-absorbing-sheet-1.ed30846e.png"},317:function(t,e,s){t.exports=s.p+"assets/img/sound-absorbing-sheet-2.fb248b8d.png"},318:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-1.13ccccc9.png"},319:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-2.3f687808.png"},320:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-3.92069fbf.png"},321:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-4.64afc3e2.png"},322:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-5.822eb937.png"},323:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-6.d25eb191.png"},324:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-7.98f0662f.png"},325:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-tip-1.08b8e88d.png"},326:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-8.04c822ec.png"},327:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-9.b0f9a0a9.png"},328:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-10.66e4306a.png"},329:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-14.f657dbed.png"},330:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-11.99ca124b.png"},331:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-12.2fb54c9e.png"},332:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-13.a7d42940.png"},333:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-15.d2700ebc.png"},334:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-16.e1c48945.png"},335:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-17.13e13a17.png"},336:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-18.968706b9.png"},337:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-19.677fc8b9.png"},338:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-21.2e8e54b5.png"},339:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-20.1f26db00.png"},340:function(t,e,s){t.exports=s.p+"assets/img/cabinet-assembly-22.4cb21f1e.png"},504:function(t,e,s){"use strict";s.r(e);var o=s(10),a=Object(o.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"frontmatter-title"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[t._v("#")]),t._v(" "+t._s(t.$frontmatter.title))]),t._v(" "),e("p",[t._v("The cabinet is the box made out of T-slotted frames and panels in which all the components of the training rig are going to be held, and works as an sound insulated space in which the mice wild be performing the tasks. All the control and other modules components are going to be placed on one of the sides of the cabinet, and the projector will be placed at the back of it.")]),t._v(" "),e("figure",[e("img",{attrs:{src:s(315)}}),t._v(" "),e("center",[e("figcaption",[e("small",[t._v("Training mini VR rig cabinet.")])])])],1),t._v(" "),e("h2",{attrs:{id:"sound-absorbing-sheet-preparation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#sound-absorbing-sheet-preparation"}},[t._v("#")]),t._v(" Sound absorbing sheet preparation")]),t._v(" "),e("p",[t._v("We use 75% sound absorbing sheets with adhesive backing that are glued at the internal part of all the panels of the cabinet, which helps to isolate the sound from the lab environment, nevertheless the rooms should be silent and darks when the animals are training.")]),t._v(" "),e("p",[t._v("Cut cardboard molds to cut the foams for the panels according to the following table.")]),t._v(" "),e("table",[e("thead",[e("tr",[e("th",[t._v("Panel")]),t._v(" "),e("th",[t._v("Size in inches")])])]),t._v(" "),e("tbody",[e("tr",[e("td",[t._v("Front doors")]),t._v(" "),e("td",[t._v('19" x 9 1/2"')])]),t._v(" "),e("tr",[e("td",[t._v("Back doors")]),t._v(" "),e("td",[t._v('9 3/8" x 9 3/8')])]),t._v(" "),e("tr",[e("td",[t._v("Sides")]),t._v(" "),e("td",[t._v('19" x 24 3/8"')])]),t._v(" "),e("tr",[e("td",[t._v("Top")]),t._v(" "),e("td",[t._v('24 1/2" x 22 3/8"')])]),t._v(" "),e("tr",[e("td",[t._v("Bottom back")]),t._v(" "),e("td",[t._v('7 11/16" x 22 3/8"')])])])]),t._v(" "),e("p",[t._v("Place the sound absorbing sheet with the foam looking up, then put the mold on top of it and use a black marker to draw through the edges.")]),t._v(" "),e("figure",[e("img",{attrs:{src:s(316)}})]),t._v(" "),e("p",[t._v("Then place a pair of profiles on top to keep the sheet flat, use a long ruler (or any flat and thin surface, I used a DIN rail to do this) to place it along the marked edges and apply a good ammount of pressure; with a sharp exacto knife cut the sheets following the marker square, we required to pass the knife two times to cut all the way through.")]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("Constantly change the blades of the exacto knife, a good indicator is if the blade doesn't flow smoothly and sometimes get stuck.")])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(317)}})]),t._v(" "),e("h2",{attrs:{id:"cabinet-assembly"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#cabinet-assembly"}},[t._v("#")]),t._v(" Cabinet assembly")]),t._v(" "),e("p",[t._v('We use 1.5" x 1.5" T-slotted profile to build the frame of the cabinet and 1/4" black harcell ABS (smooth side up) to build the panels. Our supplier the Knotts Company, which is an authorized supplier of 80/20, and sent them the drawings for a quote. Another option is to buy the pieces described in the drawing from other supplier or suppliers, but it will require to do adjustments, and a lot of holes. Assemble the cabinet following the steps below.')]),t._v(" "),e("ol",[e("li",[t._v('We start building the cabinet from the bottom up. Slide a pair of bottom plate holders (8020 - 2425) into the 24.5 inches long profile. Make sure the top part of the holder is at the same height as the top part of the profile, as shown in the picture below. Repeat the process for another 24.5" long profile.')])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(318)}})]),t._v(" "),e("ol",{attrs:{start:"2"}},[e("li",[t._v('Insert a standard end fastener to both ends of the 24.5" long profile with the bottom plate holders and to a pair of 22.5" long profiles. First insert the fastener into one of the slots and loosely screw it, repeat the process with the other end making sure the direction of the fastener is the same. Make this for both ends of the 4 profiles.')])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(319)}})]),t._v(" "),e("ol",{attrs:{start:"3"}},[e("li",[t._v('Arrange the profiles in a square, making sure that the profiles with the plate holders are facing each other to the left and right, and in the correct position (top part of the holder must be at the same height as the top part of the profile); and the 22.5" long profiles are fecing each other at the back and front. Use the 22.05" long profile with holes at 1.5" from the ends to join the front part, and use the 22.05" long profile with holes at 1.5" from both ends and a hole at 11.675" from the top down to join the back part of the rig. Introduce the profiles from the top down and tight screw trough the holes.')])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(320)}})]),t._v(" "),e("figure",[e("img",{attrs:{src:s(321)}})]),t._v(" "),e("ol",{attrs:{start:"4"}},[e("li",[t._v("Place the aluminum bottom plate on top of the frames, slide the bottom plate holders so that they match the plate holes. If the holes don't match in the lateral position, you can unscrew the holders just enough for them to reach the holes. Use 5/16-18 x 0.625\" long screws to tight screw the bottom plate to the holders.")])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("If working on an elevated table, you could push into the air the structure just enough to have visibility on the bottom and match the holders to the holes, then turn around the structure and repeat the process.")])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(322)}})]),t._v(" "),e("figure",[e("img",{attrs:{src:s(323)}})]),t._v(" "),e("figure",[e("img",{attrs:{src:s(324)}})]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("Use a permanent marker to draw two straight lines on top of the botomm plate using the groves at the sides as shown below, this will be extremely useful for the projection calibration.")]),t._v(" "),e("figure",[e("img",{attrs:{src:s(325)}})])]),t._v(" "),e("ol",{attrs:{start:"5"}},[e("li",[t._v('Cut 8.2 inches to the top base of the drawer slider, then use 1/4"-20 x 1/2" long low-profile screws to install the 26" long steel base-mount drawer sliders. Screw with M4x0.7 mm, 8 mm long screws the latch holder to the latch holder adapter, then use 1/4"-20 x 11/16" flat head screws to attach the latch holder with the adapter to the bottom plate.')])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(326)}})]),t._v(" "),e("ol",{attrs:{start:"6"}},[e("li",[t._v('Install the structure to hold the projector at the back of the rig. Set the height of the structure at 3 15/16" from a flat surfate to the top of the profile.')])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("You can install the projector bottom plate before measuring to make it easier to set the height.")])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(327)}})]),t._v(" "),e("ol",{attrs:{start:"7"}},[e("li",[t._v('To install the back panel of the rig, first make the hole for the projection to go trough. Make a hole at 2 3/4" from the top of the panel and at the middle of the panel, or 11 5/8" from the side. We recommend to do a small hole first and then use a 1" drill bit or hole saw.')])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(328)}})]),t._v(" "),e("p",[t._v("Install the soundproof foam, then cut the hole from the foam.")]),t._v(" "),e("figure",[e("img",{attrs:{src:s(329)}})]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("To install the soundproof foam first clean the smooth surface of the panel with a solution of 70% ethanol and let dry. Then remove just a small portion of the protective layer of the adhesive part of the sound absorbing sheet as shown below.")]),t._v(" "),e("figure",[e("img",{attrs:{src:s(330)}})]),t._v(" "),e("p",[t._v("Center the sheet in the panel and paste the uncovered portion by applying pressure along the sheet from the top down.")]),t._v(" "),e("figure",[e("img",{attrs:{src:s(331)}})]),t._v(" "),e("p",[t._v("Remove another small-medium portion of the protective layer and apply pressure onto the panel from the top down, repeat the process until the whole sound absorbing sheet is placed into the panel.")]),t._v(" "),e("figure",[e("img",{attrs:{src:s(332)}})])]),t._v(" "),e("p",[t._v('Finally, slide down the panel into the T-slotted profiles at the back of the rig, slidw down a 22.5" profile with fasteners already screwed until it reaches the panel and use the holes at the profiles sides to tighten the screws.')]),t._v(" "),e("figure",[e("img",{attrs:{src:s(333)}})]),t._v(" "),e("ol",{attrs:{start:"8"}},[e("li",[t._v('For the left panel, first cut the square in which the air supply adapter is going to be attached from the sound absorbing sheet, then glue the sheet to the panel and afterwards cut the hole for the cable and hoses (just like we did in the last step). Install both lateral panels first, then arrange two 24.5" long profile and two 22.5" long profile with fasteners loosely screwed at the four sides of the top panel and place them on top of the structure from the top down. Tight the screws when the structure is in place.')])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v("Sometimes when placing the top panel and profiles they don't fit in properly, if you are having troubles fitting them, loose the screws from the bottom of the four corners and the screws from the middle in the back of the frame so you can push down the top structure. Once the top structure is on place, tighten all the screws.")])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(334)}})]),t._v(" "),e("ol",{attrs:{start:"9"}},[e("li",[t._v('Assemble the doors by joining a U shape structure first. For the front doors screw at the bottom a 9.65" long profile and a pair of 22.05" long profile, for the back doors form the U shape with 9.65" long profiles. Then slide down the panels with the sound absorbing sheet already in place. After that, screw at the top a 9.65" long profile for both front and back doors. Finally, insert the joining strip along the out edges of the doors.')])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(335)}})]),t._v(" "),e("figure",[e("img",{attrs:{src:s(336)}})]),t._v(" "),e("figure",[e("img",{attrs:{src:s(337)}})]),t._v(" "),e("ol",{attrs:{start:"10"}},[e("li",[e("p",[t._v("Insert the joining strip to all of the panels in the cabinet.")])]),t._v(" "),e("li",[e("p",[t._v('Install the DIN rails by screwing 4 DIN rail mounting adapters into the profile using a T-slotted framing drop-in nut, 1/4"-20 thread size. We buy a 2 m long steel DIN rail and cut two pieces at 27.5". Then attach the pair of DIN rail to the mounting adapters and repeat the process for the other rail.')])])]),t._v(" "),e("div",{staticClass:"custom-block tip"},[e("p",{staticClass:"custom-block-title"},[t._v("TIP")]),t._v(" "),e("p",[t._v('Before placing the top DIN rail mounting adapter at the back of the rig, slide down the middle door hinge. Alternatively, you could replace the standard framing nut with a 1/4"-20 T-slotted framing drop-in nut to install that door hinge.')]),t._v(" "),e("figure",[e("img",{attrs:{src:s(338)}})])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(339)}})]),t._v(" "),e("ol",{attrs:{start:"12"}},[e("li",[t._v('Install the doors by screwing the lift-off hinges, you will need to place a couple of them for each door at the top and at the bottom. Finally install the lock using a 1/4"-20 screw and 1/4"-20 T-slotted framing drop-in nut.')])]),t._v(" "),e("figure",[e("img",{attrs:{src:s(340)}})])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/12.01f9d7cf.js b/assets/js/12.01f9d7cf.js new file mode 100644 index 0000000..bd4b9e7 --- /dev/null +++ b/assets/js/12.01f9d7cf.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[12],{341:function(e,t,o){e.exports=o.p+"assets/img/control-1.31a5e2d2.png"},342:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-1.3e1cb53a.png"},343:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-2.e729353b.png"},344:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-3.3c613198.png"},345:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-21.cd2c2b31.png"},346:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-4.e9eb1fe1.png"},347:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-5.e85ae378.png"},348:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-6.548f0cbf.png"},349:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-7.516fd97f.png"},350:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-8.9f7e66aa.png"},351:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-9.5188fee4.png"},352:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-10.92ccf29e.png"},353:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-11.c0e33c40.png"},354:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-12.e58faff5.png"},355:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-13.17922eb1.png"},356:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-14.da4ce5ef.png"},357:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-15.9864fdac.png"},358:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-16.d3892529.png"},359:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-17.167fb961.png"},360:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-18.e06b9945.png"},361:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-19.f1c2400d.png"},362:function(e,t,o){e.exports=o.p+"assets/img/control-assembly-20.edc1b377.png"},505:function(e,t,o){"use strict";o.r(t);var a=o(10),s=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("p",[e._v("The control module consist on a 24V power source, a couple of distribution blocks, which make it easier to connect any other stuff that works on 24V; a custom made solenoid valve driver, an USB NiDAQ card from National Instruments and an Arduino due that is inside a 3D printed housing with a DIN rail clip attached. Each of these parts will be explained in detail below with instructions for assembly.")]),e._v(" "),t("figure",[t("img",{attrs:{src:o(341)}}),e._v(" "),t("center",[t("figcaption",[t("small",[e._v("Control module.")])])])],1),e._v(" "),t("h2",{attrs:{id:"solenoid-valve-driver-assembly"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#solenoid-valve-driver-assembly"}},[e._v("#")]),e._v(" Solenoid valve driver assembly")]),e._v(" "),t("figure",[t("img",{attrs:{src:o(342)}})]),e._v(" "),t("p",[e._v("We designed a simple solenoid valve driver circuit using a MOSFET, the gate is driven by a digital input that will be supplied by the NIDAQ card, which open and closes the circuit from the solenoid valve to a 24V power supply. We added a diode to protect the circuit from discharge from the solenoid valve. To assembly the solenoid valve driver follow the next steps.")]),e._v(" "),t("ol",[t("li",[e._v("Have the PCB made (we use pcbway since they can make and ship the stencil, you can found our project "),t("a",{attrs:{href:"https://www.pcbway.com/project/shareproject/Simple_Solenoid_valve_driver_1340eb55.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(") and make sure to order a stencil. We use a manual printer for PCB stencil to spread the soldering paste across the PCB pads evenly. First, place the PCB on the surface using high temperature tape and place the stencil on top of it. Make sure to match the solder pads to the holes of the stencil.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(343)}})]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("Use solder paste and a flexible wipe down knife and spread evenly the solder paste into the pads. Then lift and remove the stencil.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(344)}})]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("Place each component into place, we place the resistances (R1, R3, R5, R7, and R9 resistor values are 10K Ohm and R2, R4, R6, R8 and R10 resistor values are 1K Ohm) first, then place the MOSFET and finally the diodes, make sure that the diodes are placed correctly (the band should match the ] symbol on the PCB). The picture below show the correct position of the components.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(345)}})]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("Each time you place a component in the pad make sure to slightly press it against the solder paste with the same tweezers that you use.")]),e._v(" "),t("figure",[t("img",{attrs:{src:o(346)}})])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(347)}})]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[e._v("Use a heat gun (we set the temperature at 1000F) at the lowest intensity allowed (to avoid components flying around) and move it around on top of the components until the solder melt and the components get attached in place.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(348)}})]),e._v(" "),t("ol",{attrs:{start:"5"}},[t("li",[e._v("Remove the high temperature tape and solder the pluggable terminal blocks, place the fillers and slide down the PCB into the case, then close the case.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(349)}})]),e._v(" "),t("figure",[t("img",{attrs:{src:o(350)}})]),e._v(" "),t("figure",[t("img",{attrs:{src:o(351)}})]),e._v(" "),t("ol",{attrs:{start:"7"}},[t("li",[e._v("Place the labels (make sure they are placed correctly) and place the driver on the DIN rail.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(352)}})]),e._v(" "),t("figure",[t("img",{attrs:{src:o(353)}})]),e._v(" "),t("h2",{attrs:{id:"power-supply-and-nidaq-control-assembly"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#power-supply-and-nidaq-control-assembly"}},[e._v("#")]),e._v(" Power supply and NIDAQ control assembly")]),e._v(" "),t("ol",[t("li",[e._v("Place the power supply and the distribution blocks on the DIN rails, connect the power supply to the distribution block input accordigly. The TRACO Power TBLC 50-124 is a 50W power supply, which is more than enough to power both the reward module solenoid valve (7 Watts) and the two air puffs solenoid valves (0.65 Watts each one), and have plenty of power left (~40W) for other modules if required. One power supply could be use for a stack of 2 or 3 rigs if desired.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(354)}})]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("Use a standard PC power cable and cut the portion of the connector that goes to the PC, cut the ground cable and connect the neutral cable to the negative input of the power supply and the hot cable to the positive input.")])]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("Open the NIDAQ case and make a hole at the middle of the back case. Screw the DIN rail mounting clip to it, then close the case and place the top screws only.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(355)}})]),e._v(" "),t("figure",[t("img",{attrs:{src:o(356)}})]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("Connect everything!")])]),e._v(" "),t("ul",[t("li",[e._v("Start by connecting the positive output of the power supply from one of the pins of the red distribution blocks to the V IN input of the solenoid valve driver, then the ground from one of the pins of the black distribution block to the GND pin of the solenoid valve driver.")]),e._v(" "),t("li",[e._v("Then connect the one of the GND pins of the solenoid valve driver to the the digital ground pin of the NIDAQ.")]),e._v(" "),t("li",[e._v("Connect the solenoid valve driver inputs to the NIDAQ outputs as follows: P0.0 from NIDAQ to V IN 1, P0.1 to V IN 2 and P0.2 to V IN 3.")]),e._v(" "),t("li",[e._v("Finally connect the solenoid valve driver outputs to the solenoid valve drivers. Since the solenoid valves doesn't have polarity, you should use the V OUT (+) as common in the valves, you can use one or multiple pins of the solenoid valve driver. Then connect the V OUT 1 (-) pin to the reward solenoid valve, the V OUT 2 (-) pin to the left solenoid valve and the V OUT 3 (-) to the right solenoid valve.")])]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("The solenoid valve driver has more outputs for you to connect and control with the NIDAQ digital outputs any other piece of hardware (like a 24 V IR light source for example), just make sure to wire the ports to the input and output of the driver and match them in the Rig Parameters portion of ViRMEN.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(357)}}),e._v(" "),t("center",[t("figcaption",[t("small",[e._v("Control module wiring diagram for solenoid valves.")])])])],1),e._v(" "),t("h2",{attrs:{id:"arduino-module-assembly"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#arduino-module-assembly"}},[e._v("#")]),e._v(" Arduino module assembly")]),e._v(" "),t("ol",[t("li",[e._v("Have printed the arduino case and screw the arduino. Insert the connector in place and crimp the cables. Make sure to follow the color code and connect the cables to the arduino.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(358)}}),e._v(" "),t("center",[t("figcaption",[t("small",[e._v("Wiring diagram for Arduino due to connector.")])])])],1),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("Cover the case and install the din rail mounting clip. Install the arduino module in the top DIN rail.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(359)}})]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[e._v("Make the cable to connect the arduino to the 3D printer cup. Unscrew the outer portion of the connector and insert it into the cable (you need to do this before connecting the cables, otherwise you will not be able to insert the cover and will have to do everything again). Unscrew all the conectors and insert the cable following the color code in the image below, screw them and place the connector cover.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(360)}})]),e._v(" "),t("figure",[t("img",{attrs:{src:o(361)}})]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("Place one connector first and connect it to the arduino box placed in the top DIN rail at the outer portion of the rig, then measure the lenght of the cable by inserting into the rig and into the cable carrier. Cut the cable and place the other connector, finally connect it to the 3D printed cup.")])]),e._v(" "),t("ol",{attrs:{start:"5"}},[t("li",[e._v("Connect the arduino to the computer using a "),t("a",{attrs:{href:"https://www.bhphotovideo.com/c/product/1387544-REG/tether_tools_cuc2515_blk_tetherpro_usb_c_to_2_0.html?sts=pi&pim=Y",target:"_blank",rel:"noopener noreferrer"}},[e._v("USB Type-C male to micro-USB Type-B male cable"),t("OutboundLink")],1),e._v(". Or any other cable matching your setup, we do recommend to use a single tether cable or USB 3.0 cable and avoid using either multiple cables or HUBs (or make sure everything is high speed rated).")])]),e._v(" "),t("h2",{attrs:{id:"programming-the-arduino"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#programming-the-arduino"}},[e._v("#")]),e._v(" Programming the Arduino")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Download the latest version of the "),t("a",{attrs:{href:"https://www.arduino.cc/en/software",target:"_blank",rel:"noopener noreferrer"}},[e._v("arduino IDE"),t("OutboundLink")],1),e._v(" and download the Arduino SAM Boards (32-bits ARM Cortex-M3) toolbox from the boards manager (Tools > Boards > Boards Manager), v1.6.11 has been working for us.")])]),e._v(" "),t("li",[t("p",[e._v("Connect the arduino to the computer using the "),t("a",{attrs:{href:"https://www.arduino.cc/en/uploads/Main/DueUSBPorts.jpg",target:"_blank",rel:"noopener noreferrer"}},[e._v("Programming port"),t("OutboundLink")],1),e._v(" (connect the cable to the USB port closest to the circular power connector). The arduino should be listed in the devices at the top of the window as "),t("code",[e._v("Arduino Due (Programming port)")]),e._v(".")])]),e._v(" "),t("li",[t("p",[e._v("Either download or open from Matlab the firmware from the repository. The file is inside "),t("strong",[e._v("sensors > ADNS_aout_wUSB_1sensor_or_squal_nativeport")]),e._v(" folder and is named "),t("code",[e._v("ADNS_aout_wUSB_1sensor_or_squal_nativeport.ino")]),e._v(". Make sure you have selecteed the board at the top of the window and upload the firmware by pressing the upload button (right arrow icon).")])]),e._v(" "),t("li",[t("p",[e._v("Wait until the firmware is uploaded (a message in the terminal of the arduino IDE should confirm this) and disconnect the USB cable from the Programming port and connect it to the "),t("a",{attrs:{href:"https://www.arduino.cc/en/uploads/Main/DueUSBPorts.jpg",target:"_blank",rel:"noopener noreferrer"}},[e._v("Native Port"),t("OutboundLink")],1),e._v(". The arduino should be programmed and working, you can confirm this by running the rig tester and pressing the "),t("em",[e._v("Arduino detection")]),e._v(" and "),t("em",[e._v("sensor quality")]),e._v(" buttons.")])])]),e._v(" "),t("h2",{attrs:{id:"usb-hub-and-speaker"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#usb-hub-and-speaker"}},[e._v("#")]),e._v(" USB HUB and Speaker")]),e._v(" "),t("ol",[t("li",[e._v("Use double side tape to glue the USB Hub to the cabinet at the top left portion above the DIN rail and connect everything that must be connected there (if using USB or USB powered speakers, the NIDAQ). Use a USB C extension to connect the hub to the computer.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:o(362)}})]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("Place the speaker inside the cabinet and connect to Hub - Make an upper hole on the cabinet for other cables as shown in the picture above. You can use a USB speakers or a desktop speakers and place them on top of the screen plate and connect it to the hub and, if necessary, to the computer audio input.")])])])}),[],!1,null,null,null);t.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/13.3e4bb9d9.js b/assets/js/13.3e4bb9d9.js new file mode 100644 index 0000000..6ef60a7 --- /dev/null +++ b/assets/js/13.3e4bb9d9.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[13,3,20,23,34,35,42],{242:function(t,e,n){"use strict";n.d(e,"d",(function(){return i})),n.d(e,"a",(function(){return r})),n.d(e,"i",(function(){return a})),n.d(e,"f",(function(){return l})),n.d(e,"g",(function(){return u})),n.d(e,"h",(function(){return c})),n.d(e,"b",(function(){return p})),n.d(e,"e",(function(){return h})),n.d(e,"k",(function(){return d})),n.d(e,"l",(function(){return f})),n.d(e,"c",(function(){return m})),n.d(e,"j",(function(){return g}));n(90);const i=/#.*$/,s=/\.(md|html)$/,r=/\/$/,a=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(i,"").replace(s,"")}function l(t){return a.test(t)}function u(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function p(t){if(l(t))return t;const e=t.match(i),n=e?e[0]:"",s=o(t);return r.test(s)?t:s+".html"+n}function h(t,e){const n=decodeURIComponent(t.hash),s=function(t){const e=t.match(i);if(e)return e[0]}(e);if(s&&n!==s)return!1;return o(t.path)===o(e)}function d(t,e,n){if(l(e))return{type:"external",path:e};n&&(e=function(t,e,n){const i=t.charAt(0);if("/"===i)return t;if("?"===i||"#"===i)return e+t;const s=e.split("/");n&&s[s.length-1]||s.pop();const r=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(e,n,i,s=1){if("string"==typeof e)return d(n,e,i);if(Array.isArray(e))return Object.assign(d(n,e[0],i),{title:e[1]});{const r=e.children||[];return 0===r.length&&e.path?Object.assign(d(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:r.map(e=>t(e,n,i,s+1)),collapsable:!1!==e.collapsable}}}(t,s,n)):[]}return[]}function b(t){const e=m(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function m(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function g(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},243:function(t,e,n){},244:function(t,e,n){"use strict";n.r(e);var i=n(242),s={name:"NavLink",props:{item:{required:!0}},computed:{link(){return Object(i.b)(this.item.link)},exact(){return this.$site.locales?Object.keys(this.$site.locales).some(t=>t===this.link):"/"===this.link},isNonHttpURI(){return Object(i.g)(this.link)||Object(i.h)(this.link)},isBlankTarget(){return"_blank"===this.target},isInternal(){return!Object(i.f)(this.link)&&!this.isBlankTarget},target(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(i.f)(this.link)?"_blank":""},rel(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction(){this.$emit("focusout")}}},r=n(10),a=Object(r.a)(s,(function(){var t=this,e=t._self._c;return t.isInternal?e("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):e("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?e("OutboundLink"):t._e()],1)}),[],!1,null,null,null);e.default=a.exports},245:function(t,e,n){"use strict";n.r(e);var i={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},s=(n(246),n(10)),r=Object(s.a)(i,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.default=r.exports},246:function(t,e,n){"use strict";n(243)},247:function(t,e,n){},248:function(t,e,n){},250:function(t,e,n){},253:function(t,e,n){},254:function(t,e,n){"use strict";n(247)},255:function(t,e,n){"use strict";n(248)},256:function(t,e,n){"use strict";n.r(e);var i=n(269),s=n(258),r=n(242);function a(t,e){if("group"===e.type){const n=e.path&&Object(r.e)(t,e.path),i=e.children.some(e=>"group"===e.type?a(t,e):"page"===e.type&&Object(r.e)(t,e.path));return n||i}return!1}var o={name:"SidebarLinks",components:{SidebarGroup:i.default,SidebarLink:s.default},props:["items","depth","sidebarDepth","initialOpenGroupIndex"],data(){return{openGroupIndex:this.initialOpenGroupIndex||0}},watch:{$route(){this.refreshIndex()}},created(){this.refreshIndex()},methods:{refreshIndex(){const t=function(t,e){for(let n=0;n-1&&(this.openGroupIndex=t)},toggleGroup(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive(t){return Object(r.e)(this.$route,t.regularPath)}}},l=n(10),u=Object(l.a)(o,(function(){var t=this,e=t._self._c;return t.items.length?e("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(n,i){return e("li",{key:i},["group"===n.type?e("SidebarGroup",{attrs:{item:n,open:i===t.openGroupIndex,collapsable:n.collapsable||n.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(i)}}}):e("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:n}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=u.exports},257:function(t,e,n){"use strict";n.r(e);var i=n(244),s=n(245),r=n(91),a=n.n(r),o={name:"DropdownLink",components:{NavLink:i.default,DropdownTransition:s.default},props:{item:{required:!0}},data:()=>({open:!1}),computed:{dropdownAriaLabel(){return this.item.ariaLabel||this.item.text}},watch:{$route(){this.open=!1}},methods:{setOpen(t){this.open=t},isLastItemOfArray:(t,e)=>a()(e)===t,handleDropdown(){0===event.detail&&this.setOpen(!this.open)}}},l=(n(254),n(10)),u=Object(l.a)(o,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[e("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:t.handleDropdown}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow down"})]),t._v(" "),e("button",{staticClass:"mobile-dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),e("DropdownTransition",[e("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(n,i){return e("li",{key:n.link||i,staticClass:"dropdown-item"},["links"===n.type?e("h4",[t._v("\n "+t._s(n.text)+"\n ")]):t._e(),t._v(" "),"links"===n.type?e("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(n.items,(function(i){return e("li",{key:i.link,staticClass:"dropdown-subitem"},[e("NavLink",{attrs:{item:i},on:{focusout:function(e){t.isLastItemOfArray(i,n.items)&&t.isLastItemOfArray(n,t.item.items)&&t.setOpen(!1)}}})],1)})),0):e("NavLink",{attrs:{item:n},on:{focusout:function(e){t.isLastItemOfArray(n,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null);e.default=u.exports},258:function(t,e,n){"use strict";n.r(e);var i=n(242);function s(t,e,n,i,s){const r={props:{to:e,activeClass:"",exactActiveClass:""},class:{active:i,"sidebar-link":!0}};return s>2&&(r.style={"padding-left":s+"rem"}),t("RouterLink",r,n)}function r(t,e,n,a,o,l=1){return!e||l>o?null:t("ul",{class:"sidebar-sub-headers"},e.map(e=>{const u=Object(i.e)(a,n+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[s(t,n+"#"+e.slug,e.title,u,e.level-1),r(t,e.children,n,a,o,l+1)])}))}var a={functional:!0,props:["item","sidebarDepth"],render(t,{parent:{$page:e,$site:n,$route:a,$themeConfig:o,$themeLocaleConfig:l},props:{item:u,sidebarDepth:c}}){const p=Object(i.e)(a,u.path),h="auto"===u.type?p||u.children.some(t=>Object(i.e)(a,u.basePath+"#"+t.slug)):p,d="external"===u.type?function(t,e,n){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[n,t("OutboundLink")])}(t,u.path,u.title||u.path):s(t,u.path,u.title||u.path,h),f=[e.frontmatter.sidebarDepth,c,l.sidebarDepth,o.sidebarDepth,1].find(t=>void 0!==t),b=l.displayAllHeaders||o.displayAllHeaders;if("auto"===u.type)return[d,r(t,u.children,u.basePath,a,f)];if((h||b)&&u.headers&&!i.d.test(u.path)){return[d,r(t,Object(i.c)(u.headers),u.path,a,f)]}return d}},o=(n(255),n(10)),l=Object(o.a)(a,void 0,void 0,!1,null,null,null);e.default=l.exports},260:function(t,e,n){"use strict";n(250)},266:function(t,e,n){"use strict";n(253)},267:function(t,e,n){},268:function(t,e,n){"use strict";n.r(e);var i=n(257),s=n(242),r={name:"NavLinks",components:{NavLink:n(244).default,DropdownLink:i.default},computed:{userNav(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav(){const{locales:t}=this.$site;if(t&&Object.keys(t).length>1){const e=this.$page.path,n=this.$router.options.routes,i=this.$site.themeConfig.locales||{},s={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(t).map(s=>{const r=t[s],a=i[s]&&i[s].label||r.lang;let o;return r.lang===this.$lang?o=e:(o=e.replace(this.$localeConfig.path,s),n.some(t=>t.path===o)||(o=s)),{text:a,link:o}})};return[...this.userNav,s]}return this.userNav},userLinks(){return(this.nav||[]).map(t=>Object.assign(Object(s.j)(t),{items:(t.items||[]).map(s.j)}))},repoLink(){const{repo:t}=this.$site.themeConfig;return t?/^https?:/.test(t)?t:"https://github.com/"+t:null},repoLabel(){if(!this.repoLink)return;if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;const t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"];for(let n=0;n>>"')]),t._v(" button")])]),t._v(" "),e("figure",[e("img",{attrs:{src:r(452)}}),t._v(" "),e("center",[e("figcaption",[t._v("Parameter selection main screen")])])],1),t._v(" "),e("ol",{attrs:{start:"4"}},[e("li",[t._v("On the "),e("strong",[t._v('"Select parameters"')]),t._v(" tab (assume that all probes/fovs are going to be processed with same parameters)")])]),t._v(" "),e("h3",{attrs:{id:"on-section-1"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-section-1"}},[t._v("#")]),t._v(" On section 1:")]),t._v(" "),e("ol",{attrs:{start:"5"}},[e("li",[t._v("In "),e("strong",[t._v("Preprocessing Params Lists")]),t._v(" dropdown Select a Preprocessing Param list")])]),t._v(" "),e("ul",[e("li",[t._v("You can check which preprocessing steps are defined for that list on the listbox to the right)")]),t._v(" "),e("li",[t._v("If you select a preprocessing step from the listbox you can check the specific parameters for that preprocessing step on the text area to the right.")])]),t._v(" "),e("h3",{attrs:{id:"on-section-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-section-2"}},[t._v("#")]),t._v(" On section 2:")]),t._v(" "),e("ol",{attrs:{start:"6"}},[e("li",[t._v("In "),e("strong",[t._v('Processing Params"')]),t._v(" dropdown select a Processing parameter suited for recording")])]),t._v(" "),e("ul",[e("li",[t._v("If you select a processing parameter from the dropdown you can check the specific parameters for it on the text area to the right.")])]),t._v(" "),e("ol",{attrs:{start:"7"}},[e("li",[t._v("Click "),e("strong",[t._v("Register Recording")]),t._v(" button.")])]),t._v(" "),e("ul",[e("li",[t._v("Next actions are idential to the "),e("strong",[t._v('"Default use"')]),t._v(" case")])]),t._v(" "),e("h2",{attrs:{id:"monitor-jobs"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#monitor-jobs"}},[t._v("#")]),t._v(" Monitor jobs")]),t._v(" "),e("ul",[e("li",[t._v("After a recording is submitted to processing the user is able to track, reprocess and visualize all jobs corresponsing to that recording.")])]),t._v(" "),e("figure",[e("img",{attrs:{src:r(453)}}),t._v(" "),e("center",[e("figcaption",[t._v("Manage Processing Jobs main screen")])])],1),t._v(" "),e("h3",{attrs:{id:"track-status"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#track-status"}},[t._v("#")]),t._v(" Track status")]),t._v(" "),e("ol",[e("li",[t._v("Switch to "),e("strong",[t._v('"Manage Processing Jobs"')]),t._v(" tab.")]),t._v(" "),e("li",[t._v("Use "),e("strong",[t._v('"User"')]),t._v(", "),e("strong",[t._v('"Subject"')]),t._v(" & "),e("strong",[t._v('"Date"')]),t._v(" dropdwons / edits to find desired jobs")]),t._v(" "),e("li",[t._v("Select row corresponding to the corresponding job:")])]),t._v(" "),e("ul",[e("li",[t._v("Corresponding Job Status history is shown for selected job.")])]),t._v(" "),e("h4",{attrs:{id:"if-status-of-job-is-in-error-status-1-2-error-in-recording-process"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#if-status-of-job-is-in-error-status-1-2-error-in-recording-process"}},[t._v("#")]),t._v(' If status of job is in error status (-1, -2; "Error in recording process"):')]),t._v(" "),e("ul",[e("li",[t._v("You can open the Error log file on the bottom right corner by clicking "),e("strong",[t._v('"Open Error Log File"')]),t._v(" button.")]),t._v(" "),e("li",[t._v("If you consider that what cause the error is solved now, you can rerun job by clicking "),e("strong",[t._v('"Rerun job"')]),t._v(" button.")])]),t._v(" "),e("h4",{attrs:{id:"if-status-of-job-is-in-finished-status-7-8-dat-in-element"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#if-status-of-job-is-in-finished-status-7-8-dat-in-element"}},[t._v("#")]),t._v(' If status of job is in finished status (7, 8; "Dat in element"):')]),t._v(" "),e("ul",[e("li",[t._v("You can open the Output log file on the bottom right corner by clicking "),e("strong",[t._v('"Open Output Log File"')]),t._v(" button.")]),t._v(" "),e("li",[t._v("You can visualize results from processing by clicking the bottom rightmost buttons: ("),e("strong",[t._v("Open Phy")]),t._v(", "),e("strong",[t._v("Open IBL Atlas")]),t._v(" for ephys "),e("strong",[t._v("Open Suite2p-GUI")]),t._v(" for imaging)")])]),t._v(" "),e("figure",[e("img",{attrs:{src:r(454)}}),t._v(" "),e("center",[e("figcaption",[t._v("Visualization tools available")])])],1),t._v(" "),e("h4",{attrs:{id:"rerun-jobs"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#rerun-jobs"}},[t._v("#")]),t._v(" Rerun jobs")]),t._v(" "),e("ul",[e("li",[t._v("A job can be rerun with different parameters by clicking "),e("strong",[t._v("New Job With different Parameters")]),t._v(" button.")]),t._v(" "),e("li",[t._v("Follow "),e("a",{attrs:{href:"https://braincogs.github.io/software/automation_pipeline.html#advanced-select-parameters-use-case"}},[t._v(' "Advanced" (select parameters) use case ')])])]),t._v(" "),e("h2",{attrs:{id:"create-new-sets-of-processing-parameters-for-recordings"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#create-new-sets-of-processing-parameters-for-recordings"}},[t._v("#")]),t._v(" Create new sets of processing parameters for recordings")]),t._v(" "),e("ul",[e("li",[t._v("In order to process recordings with parameters different than default you need at least one of the following:")])]),t._v(" "),e("ol",[e("li",[t._v("A new ser or processing parameters (parameters for the algorithm to process, e.g. kilosort, suite2p).")]),t._v(" "),e("li",[t._v("A list of preprocessing steps formed by a set of preprocessing params (e.g. perform catgt + tprime before kilosort).")])]),t._v(" "),e("figure",[e("img",{attrs:{src:r(455)}}),t._v(" "),e("center",[e("figcaption",[t._v("Create parameters screen")])])],1),t._v(" "),e("h3",{attrs:{id:"create-new-processing-parameters-algorithm-pararms"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#create-new-processing-parameters-algorithm-pararms"}},[t._v("#")]),t._v(" Create new Processing parameters (algorithm pararms)")]),t._v(" "),e("ul",[e("li",[t._v("Note: You need a json file with all parameters ready before starting this process.")]),t._v(" "),e("li",[e("a",{attrs:{href:r(456)}},[t._v("Here")]),t._v(" is an example of a kilosort parameter json file. It can serve you as an example for creating your own:")])]),t._v(" "),e("ol",[e("li",[t._v('Switch to "Create Parameters" tab.')])]),t._v(" "),e("h4",{attrs:{id:"on-section-0"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-section-0"}},[t._v("#")]),t._v(" On section 0:")]),t._v(" "),e("ol",{attrs:{start:"2"}},[e("li",[t._v('In "recordig modality" dropdown select to which modality the parameters correspond.')]),t._v(" "),e("li",[t._v('In "user" dropdown Select your NETID username (select general-user if this parameter will be shared by many users).')])]),t._v(" "),e("h4",{attrs:{id:"on-section-1a"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-section-1a"}},[t._v("#")]),t._v(" On section 1a:")]),t._v(" "),e("ol",{attrs:{start:"4"}},[e("li",[t._v('In "proc. Param Method" dropdown, select which method (algorithm) these parameters refer to.')])]),t._v(" "),e("h5",{attrs:{id:"if-the-algorithm-is-not-found-on-proc-param-method-dropdown"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#if-the-algorithm-is-not-found-on-proc-param-method-dropdown"}},[t._v("#")]),t._v(' If the algorithm is not found on "proc. Param Method" dropdown:')]),t._v(" "),e("ul",[e("li",[t._v('Check "define new proc. param method ?" checkbox.')]),t._v(" "),e("li",[t._v('Write new processing method name in "New Proc. Param. method" edit')]),t._v(" "),e("li",[t._v("Check automation pipeline developer guide to add corresponding processing code. (LINK MISSING)")])]),t._v(" "),e("ol",{attrs:{start:"5"}},[e("li",[t._v('In "proc. Param Set Description" edit, write a small description for the new parameters.')]),t._v(" "),e("li",[t._v('Click "Upload Proc-Parm Set json file" button and search/load for your json file with parameters. You can check your parameters on the text area on the right.')]),t._v(" "),e("li",[t._v('Click "Register Proc. Param Set" button.')])]),t._v(" "),e("h3",{attrs:{id:"create-new-preprocessing-parameters-a-single-step-on-preprocessing-list"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#create-new-preprocessing-parameters-a-single-step-on-preprocessing-list"}},[t._v("#")]),t._v(" Create new preprocessing parameters (a single step on preprocessing list)")]),t._v(" "),e("ul",[e("li",[t._v("Note: You need a json file with all parameters ready before starting this process.")]),t._v(" "),e("li",[e("a",{attrs:{href:r(457)}},[t._v("Here")]),t._v(" is an example of a catgt parameter json file. It can serve you as an example for creating your own:")])]),t._v(" "),e("ol",[e("li",[t._v('Switch to "Create Parameters" tab.')])]),t._v(" "),e("h3",{attrs:{id:"on-section-0-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-section-0-2"}},[t._v("#")]),t._v(" On section 0:")]),t._v(" "),e("ol",{attrs:{start:"2"}},[e("li",[t._v('In "recordig modality" dropdown select to which modality the parameters correspond.')]),t._v(" "),e("li",[t._v('In "user" dropdown Select your NETID username (select general-user if this parameter will be shared by many users).')])]),t._v(" "),e("h3",{attrs:{id:"on-section-1b"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-section-1b"}},[t._v("#")]),t._v(" On section 1b:")]),t._v(" "),e("ol",{attrs:{start:"4"}},[e("li",[t._v('In "Preproc.-Param Method" dropdown, select which method (tool) these parameters refer to.')])]),t._v(" "),e("h4",{attrs:{id:"if-the-tool-is-not-found-on-preproc-param-method-dropdown"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#if-the-tool-is-not-found-on-preproc-param-method-dropdown"}},[t._v("#")]),t._v(' If the tool is not found on "Preproc.-Param Method" dropdown:')]),t._v(" "),e("ul",[e("li",[t._v('Check "define new prerproc.-param method ?" checkbox.')]),t._v(" "),e("li",[t._v('Write new preprocessing method name in "New Preproc.-Param method" edit.')]),t._v(" "),e("li",[t._v("Check automation pipeline developer guide to add corresponding preprocessing code. (LINK MISSING).")])]),t._v(" "),e("ol",{attrs:{start:"5"}},[e("li",[t._v('In "Preproc.-Param Set Description" edit, write a small description for the new parameters.')]),t._v(" "),e("li",[t._v('Click "Upload Preproc.-Parm Set json file" button and search/load for your json file with parameters. You can check your parameters on the text area on the right.')]),t._v(" "),e("li",[t._v('Click "Register PreProc. Param Set" button.')])]),t._v(" "),e("h3",{attrs:{id:"create-new-preprocessing-parameters-list-a-set-of-preprocessing-paramaters"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#create-new-preprocessing-parameters-list-a-set-of-preprocessing-paramaters"}},[t._v("#")]),t._v(" Create new preprocessing parameters list (a set of preprocessing paramaters)")]),t._v(" "),e("ul",[e("li",[t._v("Note: If you just created a preprocessing parameter, restart GUI.")])]),t._v(" "),e("ol",[e("li",[t._v('Switch to "Create Parameters" tab.')])]),t._v(" "),e("h3",{attrs:{id:"on-section-0-3"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-section-0-3"}},[t._v("#")]),t._v(" On section 0:")]),t._v(" "),e("ol",{attrs:{start:"2"}},[e("li",[t._v('In "recordig modality" dropdown select to which modality the parameters correspond.')]),t._v(" "),e("li",[t._v('In "user" dropdown Select your NETID username (select general-user if this parameter will be shared by many users).')])]),t._v(" "),e("h3",{attrs:{id:"on-section-1c"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-section-1c"}},[t._v("#")]),t._v(" On section 1c:")]),t._v(" "),e("ol",{attrs:{start:"4"}},[e("li",[t._v('In "Pre-Params List Name" dropdown, write a suitable name for the list.')]),t._v(" "),e("li",[t._v('In "Pre.-Param List Description" edit, write a small description for the new list.')]),t._v(" "),e("li",[t._v('From "Pre.-Params steps" dropdown select the desired preprocessing step as part of the list.')]),t._v(" "),e("li",[t._v('Click "Add Preparam Steps" button')]),t._v(" "),e("li",[t._v("Repeat steps 6 & 7 to add all desired preprocessing steps for the list.")]),t._v(" "),e("li",[t._v('Use "v" & "^" buttons to set order of preprocessing steps.')]),t._v(" "),e("li",[t._v('Use "x" button to delete an unwanted preprocessing step.')]),t._v(" "),e("li",[t._v('Click "Register pre param list" button.')])])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/16.0d27a42c.js b/assets/js/16.0d27a42c.js new file mode 100644 index 0000000..6d085dd --- /dev/null +++ b/assets/js/16.0d27a42c.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[16],{367:function(t,e,o){t.exports=o.p+"assets/img/positioning-1.3c1fa371.png"},368:function(t,e,o){t.exports=o.p+"assets/img/animal-position.bdb115ab.png"},369:function(t,e,o){t.exports=o.p+"assets/img/positioning-2.2da2811b.png"},370:function(t,e,o){t.exports=o.p+"assets/img/positioning-3.025487a5.png"},371:function(t,e,o){t.exports=o.p+"assets/img/positioning-4.36296c6e.png"},372:function(t,e,o){t.exports=o.p+"assets/img/positioning-5.4e122c4e.png"},373:function(t,e,o){t.exports=o.p+"assets/img/positioning-6.dbcd6621.png"},374:function(t,e,o){t.exports=o.p+"assets/img/positioning-7.6ec672a2.png"},375:function(t,e,o){t.exports=o.p+"assets/img/positioning-8.0121a2e5.png"},376:function(t,e,o){t.exports=o.p+"assets/img/positioning-9.f1e7b05d.png"},377:function(t,e,o){t.exports=o.p+"assets/img/positioning-10.2d031a9c.png"},378:function(t,e,o){t.exports=o.p+"assets/img/positioning-tool.265ef066.png"},508:function(t,e,o){"use strict";o.r(e);var i=o(10),s=Object(i.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"frontmatter-title"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[t._v("#")]),t._v(" "+t._s(t.$frontmatter.title))]),t._v(" "),e("p",[t._v("The positioning system is designed to fix the subject within the projection and correct posture boundaries, but also to have high repeatibility, allowing to have specific coordinates for different subjects trained on the same rig. There are two different positioning systems currently used at our facilities, an automated positioning system that ensures repeatibility and personalized positioning for each subject across training rigs and training sessions; and the manual positioning system, which consist of low cost thorlabs components and a positioning tool developed in house.")]),t._v(" "),e("figure",[e("img",{attrs:{src:o(367)}}),t._v(" "),e("center",[e("figcaption",[e("small",[t._v("Automatic (left) and manual (right) positioning system.")])])])],1),t._v(" "),e("p",[t._v("The animal position in the ball should prioritize the correct posture for running whithin boundaries of the projection calibration. The projection is calibrated assuming the animal eyes are going to be positioned 0.256 inches behind the center of the ball on the X axis, 1 inch over the top of the center of the ball on the Y axis and centered along the Z axis. A 0.5 inches range error is acceptable.")]),t._v(" "),e("figure",[e("img",{attrs:{src:o(368)}}),t._v(" "),e("center",[e("figcaption",[e("small",[t._v("Projection calibration boundaries and animal position (mouse drawings by "),e("a",{attrs:{href:"https://doi.org/10.5281/zenodo.3926057"}},[t._v("Ethan Tyler")]),t._v(" and "),e("a",{attrs:{href:"https://zenodo.org/record/3925997#.YOcrtUwpDRY"}},[t._v("Federico Claudi")]),t._v(" )")])])])],1),t._v(" "),e("h2",{attrs:{id:"automated-positioning-system"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-positioning-system"}},[t._v("#")]),t._v(" Automated positioning system")]),t._v(" "),e("p",[t._v("The automated positioning system consist of a set of motorized platforms set in a XYZ configuration. We use the small factor 25mm linear stage (LSA25) from Zaber technologies. A 3D printed arm in Nylon 12 with glass beads - PA12 (MJF) from shapeways - from the top motor (height control) was designed, at the end of the arm we designed a stainless steel headplate holder. The whole assembly is attached to the stage breadboard using a custom adapter.")]),t._v(" "),e("figure",[e("img",{attrs:{src:o(369)}})]),t._v(" "),e("p",[t._v("The headplate holder has to be designed to fit the head plate to be used in order to minimize the variability in the pitch, roll and yaw of the head plate and the animal position. This way, the motors can have better repeatability by adjusting the antero-posterior, dorso-ventral and medio-lateral position of the animal.")]),t._v(" "),e("figure",[e("img",{attrs:{src:o(370)}})]),t._v(" "),e("p",[t._v("The positioning system is designed to be fixed at the expected position of the headplate in the antero-posterior (AP) and mediolateral (ML) position as shown in the picture below when the motorized stages are set at midrange.")]),t._v(" "),e("figure",[e("img",{attrs:{src:o(371)}})]),t._v(" "),e("p",[t._v('To assemble the positioning system, first attach the custom made breadboard adapter to the top stage breadboard at the position shown below using 82 Degree Countersink Angle, 1/4"-20 Thread Size, 1/2" Long Drive Flat Head screws. Then attach the first motorized stage at correct position as shown in the image below using Low-Profile, M3 x 0.5 mm Thread, 5 mm Long screws.')]),t._v(" "),e("figure",[e("img",{attrs:{src:o(372)}})]),t._v(" "),e("p",[t._v("Attach the second (AP position) motorized linear stage to the first one using the same kind of screws at the position shown in the image below. Then, attach the Z adapter from zaber technologies (AB106) to the stage using M2 x 0.4 mm Thread, 5 mm Long Low profile socket head screws at the position as shown below.")]),t._v(" "),e("figure",[e("img",{attrs:{src:o(373)}})]),t._v(" "),e("p",[t._v("Attach the third (DV position) motorized linear stage to the AB106 Zaber adapter using Low-Profile, M3 x 0.5 mm Thread, 5 mm Long screws at the position indicated in the image below. Finally, screw the 3D printed arm to the DV position motorized linear stage using M3 x 0.5 mm Thread, 30 mm Long Hex Drive Flat Head screws as shown below.")]),t._v(" "),e("figure",[e("img",{attrs:{src:o(374)}})]),t._v(" "),e("p",[t._v("One of the most importants variables for the mice on the VR tasks are the DV positioning (height), the mice needs to be comfortable enough to properly run on top of the styrofoam ball. The automated positioning system allows to set customizable heights for each subject. The whole coordinated of the subjects can also be stored on a DB and retrieved before training, which improves the repeatibility and decreases the time needed to set the subjects.")]),t._v(" "),e("h2",{attrs:{id:"manual-positioning-system"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#manual-positioning-system"}},[t._v("#")]),t._v(" Manual positioning system")]),t._v(" "),e("p",[t._v('The manual positioning system consist of a set of Thorlabs and custom made parts. To assemble it, first attach a 4" post (either PSR-4.0 from siskiyou or RS4 from Throlabs) at the position of the top stage breadboard shown in the image below. Then, attach a 3" post (RS3 from Thorlabs) on top of the previous installed posts.')]),t._v(" "),e("figure",[e("img",{attrs:{src:o(375)}})]),t._v(" "),e("p",[t._v("Screw down a RB2 part from Thorlabs down the right post (looking at the stage from behind), then attach a TR1 using a 4-40 screw to the RB2 clamp. Then slide down and tight a RA90 Thorlabs part to the TR1 post as indicated in the image below.")]),t._v(" "),e("figure",[e("img",{attrs:{src:o(376)}})]),t._v(" "),e("p",[t._v("Finally, screw the custom made stainless steel head plate adapter to the a TR2 post from Thorlans, then attach it to the RA90 and tight it down as shown below.")]),t._v(" "),e("figure",[e("img",{attrs:{src:o(377)}})]),t._v(" "),e("p",[t._v("A positioning tool was designed taking as reference the 2 pillars that are part of the stage of the mini VR rig. The tool consist on a 3D printed part that hold a glued transparency, lines are made with a marker for the Y position of the animal (1st and 2nd dents of the tool) and the Z line (A and B arrows on the tool). The user can easily use this tool to adjust the animal in the right X and Y position, and the height must be fine tuned to allow the animal to run comfortable.")]),t._v(" "),e("p",[t._v("The tool also has space to add a magnet fixed with epoxy resin on the pillars holes to be steady when placed on top of the pillars.")]),t._v(" "),e("div",{staticClass:"custom-block warning"},[e("p",{staticClass:"custom-block-title"},[t._v("WARNING")]),t._v(" "),e("p",[t._v("The pillars must be placed in the correct holes of the breadboard as shown in the figure, otherwise the distance from the center of the ball could be wrong.")])]),t._v(" "),e("figure",[e("img",{attrs:{src:o(378)}}),t._v(" "),e("center",[e("figcaption",[e("small",[t._v("Positioning tool and animal placement (mouse drawings by "),e("a",{attrs:{href:"https://zenodo.org/record/3925997#.YOcrtUwpDRY"}},[t._v("Federico Claudi")]),t._v(" )")])])])],1)])}),[],!1,null,null,null);e.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/17.bf76a0f7.js b/assets/js/17.bf76a0f7.js new file mode 100644 index 0000000..ad101c7 --- /dev/null +++ b/assets/js/17.bf76a0f7.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[17,25,29],{242:function(t,e,n){"use strict";n.d(e,"d",(function(){return r})),n.d(e,"a",(function(){return a})),n.d(e,"i",(function(){return s})),n.d(e,"f",(function(){return u})),n.d(e,"g",(function(){return c})),n.d(e,"h",(function(){return l})),n.d(e,"b",(function(){return p})),n.d(e,"e",(function(){return f})),n.d(e,"k",(function(){return d})),n.d(e,"l",(function(){return h})),n.d(e,"c",(function(){return v})),n.d(e,"j",(function(){return m}));n(90);const r=/#.*$/,i=/\.(md|html)$/,a=/\/$/,s=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(r,"").replace(i,"")}function u(t){return s.test(t)}function c(t){return/^mailto:/.test(t)}function l(t){return/^tel:/.test(t)}function p(t){if(u(t))return t;const e=t.match(r),n=e?e[0]:"",i=o(t);return a.test(i)?t:i+".html"+n}function f(t,e){const n=decodeURIComponent(t.hash),i=function(t){const e=t.match(r);if(e)return e[0]}(e);if(i&&n!==i)return!1;return o(t.path)===o(e)}function d(t,e,n){if(u(e))return{type:"external",path:e};n&&(e=function(t,e,n){const r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"===r)return e+t;const i=e.split("/");n&&i[i.length-1]||i.pop();const a=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(e,n,r,i=1){if("string"==typeof e)return d(n,e,r);if(Array.isArray(e))return Object.assign(d(n,e[0],r),{title:e[1]});{const a=e.children||[];return 0===a.length&&e.path?Object.assign(d(n,e.path,r),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:a.map(e=>t(e,n,r,i+1)),collapsable:!1!==e.collapsable}}}(t,i,n)):[]}return[]}function g(t){const e=v(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function v(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function m(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},249:function(t,e){t.exports=function(t){return null==t}},251:function(t,e,n){},252:function(t,e,n){},262:function(t,e,n){"use strict";n(251)},263:function(t,e,n){var r=n(12),i=n(4),a=n(11);t.exports=function(t){return"string"==typeof t||!i(t)&&a(t)&&"[object String]"==r(t)}},264:function(t,e,n){"use strict";n(252)},265:function(t,e,n){},270:function(t,e,n){"use strict";n.r(e);var r=n(249),i=n.n(r),a=n(242),s={name:"PageEdit",computed:{lastUpdated(){return this.$page.lastUpdated},lastUpdatedText(){return"string"==typeof this.$themeLocaleConfig.lastUpdated?this.$themeLocaleConfig.lastUpdated:"string"==typeof this.$site.themeConfig.lastUpdated?this.$site.themeConfig.lastUpdated:"Last Updated"},editLink(){const t=i()(this.$page.frontmatter.editLink)?this.$site.themeConfig.editLinks:this.$page.frontmatter.editLink,{repo:e,docsDir:n="",docsBranch:r="master",docsRepo:a=e}=this.$site.themeConfig;return t&&a&&this.$page.relativePath?this.createEditLink(e,a,n,r,this.$page.relativePath):null},editLinkText(){return this.$themeLocaleConfig.editLinkText||this.$site.themeConfig.editLinkText||"Edit this page"}},methods:{createEditLink(t,e,n,r,i){if(/bitbucket.org/.test(e)){return e.replace(a.a,"")+"/src"+`/${r}/`+(n?n.replace(a.a,"")+"/":"")+i+`?mode=edit&spa=0&at=${r}&fileviewer=file-view-default`}if(/gitlab.com/.test(e)){return e.replace(a.a,"")+"/-/edit"+`/${r}/`+(n?n.replace(a.a,"")+"/":"")+i}return(a.i.test(e)?e:"https://github.com/"+e).replace(a.a,"")+"/edit"+`/${r}/`+(n?n.replace(a.a,"")+"/":"")+i}}},o=(n(262),n(10)),u=Object(o.a)(s,(function(){var t=this,e=t._self._c;return e("footer",{staticClass:"page-edit"},[t.editLink?e("div",{staticClass:"edit-link"},[e("a",{attrs:{href:t.editLink,target:"_blank",rel:"noopener noreferrer"}},[t._v(t._s(t.editLinkText))]),t._v(" "),e("OutboundLink")],1):t._e(),t._v(" "),t.lastUpdated?e("div",{staticClass:"last-updated"},[e("span",{staticClass:"prefix"},[t._v(t._s(t.lastUpdatedText)+":")]),t._v(" "),e("span",{staticClass:"time"},[t._v(t._s(t.lastUpdated))])]):t._e()])}),[],!1,null,null,null);e.default=u.exports},271:function(t,e,n){"use strict";n.r(e);n(90);var r=n(242),i=n(263),a=n.n(i),s=n(249),o=n.n(s),u={name:"PageNav",props:["sidebarItems"],computed:{prev(){return l(c.PREV,this)},next(){return l(c.NEXT,this)}}};const c={NEXT:{resolveLink:function(t,e){return p(t,e,1)},getThemeLinkConfig:({nextLinks:t})=>t,getPageLinkConfig:({frontmatter:t})=>t.next},PREV:{resolveLink:function(t,e){return p(t,e,-1)},getThemeLinkConfig:({prevLinks:t})=>t,getPageLinkConfig:({frontmatter:t})=>t.prev}};function l(t,{$themeConfig:e,$page:n,$route:i,$site:s,sidebarItems:u}){const{resolveLink:c,getThemeLinkConfig:l,getPageLinkConfig:p}=t,f=l(e),d=p(n),h=o()(d)?f:d;return!1===h?void 0:a()(h)?Object(r.k)(s.pages,h,i.path):c(n,u)}function p(t,e,n){const r=[];!function t(e,n){for(let r=0,i=e.length;rOpen)")]),e._v(" "),t("li",[e._v("If no object is going to change, just modify "),t("strong",[e._v("Experiment code")]),e._v(" dropdown (Bottom left corner) value to match your experiment code filename.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(483)}}),e._v(" "),t("center",[t("figcaption",[e._v("ViRMEn GUI: to modify world files")])])],1),e._v(" "),t("h4",{attrs:{id:"protocol-file"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#protocol-file"}},[e._v("#")]),e._v(" Protocol file")]),e._v(" "),t("ul",[t("li",[e._v("Located in "),t("strong",[e._v("ViRMEn\\experiments\\protocols")]),e._v(" (Rigs) or "),t("strong",[e._v("tankmousevr\\experiments\\protocols")]),e._v(" (Personal computer) directory.")]),e._v(" "),t("li",[e._v("File that declares the number of levels, mazes settings and criteria to decide when to advance subjects to next levels.")]),e._v(" "),t("li",[e._v("Original file: "),t("code",[e._v("C:\\Experiments\\ViRMEn\\experiments\\protocols\\PoissonBlocksCondensed3m.m")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(484)}}),e._v(" "),t("center",[t("figcaption",[e._v("Protocol file Code")])])],1),e._v(" "),t("ul",[t("li",[e._v("Here are definition of structures and variables in protocol file:")])]),e._v(" "),t("ol",[t("li",[e._v("Maze structure:")])]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("Parameter name")]),e._v(" "),t("th",[e._v("Definition")]),e._v(" "),t("th",[e._v("Values accepted")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("lStart")]),e._v(" "),t("td",[e._v("Length of start region on track")]),e._v(" "),t("td",[e._v("Real number (>0)")])]),e._v(" "),t("tr",[t("td",[e._v("lCue")]),e._v(" "),t("td",[e._v("Length of cue region on track")]),e._v(" "),t("td",[e._v("Real Number (>0)")])]),e._v(" "),t("tr",[t("td",[e._v("lMemory")]),e._v(" "),t("td",[e._v("Length of delay region on track")]),e._v(" "),t("td",[e._v("Real Number (>0)")])]),e._v(" "),t("tr",[t("td",[e._v("Tri_turnHint")]),e._v(" "),t("td",[e._v("Are the turn hints present at all?")]),e._v(" "),t("td",[e._v("logical")])]),e._v(" "),t("tr",[t("td",[e._v("Tri_turnHint_Mem")]),e._v(" "),t("td",[e._v("Are turn hints present during delay period?")]),e._v(" "),t("td",[e._v("logical")])]),e._v(" "),t("tr",[t("td",[e._v("cueDuration")]),e._v(" "),t("td",[e._v("How long are towers present after they appear (i.e., do they disappear after they are passed, and if yes, after how much time)?")]),e._v(" "),t("td",[e._v("Real Number (>0, in seconds)")])]),e._v(" "),t("tr",[t("td",[e._v("cueVisibleAt")]),e._v(" "),t("td",[e._v("How far away from the navigator are towers visible?")]),e._v(" "),t("td",[e._v("Real Number (>0)")])]),e._v(" "),t("tr",[t("td",[e._v("cueProbability")]),e._v(" "),t("td",[e._v("Probability parameter that defines the ratio of salient vs. distractor towers")]),e._v(" "),t("td",[e._v("Real Number (>0, lower numbers make the ratio smaller on average) or inf (places all towers on correct side)")])]),e._v(" "),t("tr",[t("td",[e._v("cueDensityPerM")]),e._v(" "),t("td",[e._v("How many towers per meter in cue region are possible?")]),e._v(" "),t("td",[e._v("Real number")])]),e._v(" "),t("tr",[t("td",[e._v("antiFraction")]),e._v(" "),t("td",[e._v("Proportion of trials in which the correct choice is away from the side with more towers (i.e., fraction of trials with inverted reward")]),e._v(" "),t("td",[e._v("Real number ([0-1])")])]),e._v(" "),t("tr",[t("td",[e._v("world")]),e._v(" "),t("td",[e._v("Index of Virmen world in vr.worlds for that Maze")]),e._v(" "),t("td",[e._v("Index of virmen world ([1-N], where N is the max number of worlds)")])])])]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("Maze advancement criteria structure:")])]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("Parameter name")]),e._v(" "),t("th",[e._v("Definition")]),e._v(" "),t("th",[e._v("Values accepted")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("numTrials")]),e._v(" "),t("td",[e._v("Minimum number of trials the mouse must spend above performance")]),e._v(" "),t("td",[e._v("Natural number")])]),e._v(" "),t("tr",[t("td",[e._v("numTrialsPerMin")]),e._v(" "),t("td",[e._v("Number of trials required per minute to be considered maintaining “good” performance")]),e._v(" "),t("td",[e._v("Natural number")])]),e._v(" "),t("tr",[t("td",[e._v("criteriaNTrials")]),e._v(" "),t("td",[e._v("Number of trials in the running window used to measure performance for deciding whether to advance to the next maze")]),e._v(" "),t("td",[e._v("Natural number")])]),e._v(" "),t("tr",[t("td",[e._v("numSessions")]),e._v(" "),t("td",[e._v("Minimum number of sessions the navigator must have above criteria before advancing")]),e._v(" "),t("td",[e._v("Natural number")])]),e._v(" "),t("tr",[t("td",[e._v("Performance")]),e._v(" "),t("td",[e._v("Minimum performance criterion to advance maze")]),e._v(" "),t("td",[e._v("Real number ([0-1])")])]),e._v(" "),t("tr",[t("td",[e._v("maxBias")]),e._v(" "),t("td",[e._v("Max allowed side bias to advance maze")]),e._v(" "),t("td",[e._v("Real number ([0-1])")])]),e._v(" "),t("tr",[t("td",[e._v("warmupMaze")]),e._v(" "),t("td",[e._v("Index of Virmen world in vr.worlds for the warmup maze for that particular main maze, which occurs at the start of a given session")]),e._v(" "),t("td",[e._v("Index of virmen world ([1-N], where N is the max number of worlds)")])]),e._v(" "),t("tr",[t("td",[e._v("warmupPerform")]),e._v(" "),t("td",[e._v("Minimum performance allowed during warmup to advance to mainMaze")]),e._v(" "),t("td",[e._v("Real number ([0-1])")])]),e._v(" "),t("tr",[t("td",[e._v("warmupBias")]),e._v(" "),t("td",[e._v("Max allowed side bias allowed during warmup to advance to main maze")]),e._v(" "),t("td",[e._v("Real number ([0-1])")])]),e._v(" "),t("tr",[t("td",[e._v("warmupMotor")]),e._v(" "),t("td",[e._v('Max percentage of trials to have "bad" motor quality. (Too much travel distance inside the maze)')]),e._v(" "),t("td",[e._v("Real number ([0-1])")])]),e._v(" "),t("tr",[t("td",[e._v("easyBlock")]),e._v(" "),t("td",[e._v("Index of Virmen world in vr.worlds for the easy block maze for that particular main maze")]),e._v(" "),t("td",[e._v("Index of virmen world ([1-N], where N is the max number of worlds)")])]),e._v(" "),t("tr",[t("td",[e._v("easyBlockNTrials")]),e._v(" "),t("td",[e._v("Number of trials in an easy block")]),e._v(" "),t("td",[e._v("Natural number")])]),e._v(" "),t("tr",[t("td",[e._v("numBlockTrials")]),e._v(" "),t("td",[e._v("Number of trials within a block used to assess performance for demotion to an easy block")]),e._v(" "),t("td",[e._v("Natural number")])]),e._v(" "),t("tr",[t("td",[e._v("blockPerform")]),e._v(" "),t("td",[e._v("If running window performance (calculated over numBlockTrials) goes under this value, a switch to the easy block is triggered")]),e._v(" "),t("td",[e._v("Real number ([0-1])")])])])]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("Protocol extra variables:")])]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("Parameter name")]),e._v(" "),t("th",[e._v("Definition")]),e._v(" "),t("th",[e._v("Values accepted")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("globalSettings")]),e._v(" "),t("td",[e._v("Defines global settings for all mazes")]),e._v(" "),t("td",[e._v("Cell array of name-value pairs (see below for more details)")])]),e._v(" "),t("tr",[t("td",[e._v("vr.numMazesInProtocol")]),e._v(" "),t("td",[e._v("Total number of mazes in protocol")]),e._v(" "),t("td",[e._v("Natural number (likely the length of mazeIDs)")])]),e._v(" "),t("tr",[t("td",[e._v("vr.stimulusGenerator")]),e._v(" "),t("td",[e._v("Function to generate stimuli (i.e., distribution of towers along the maze)")]),e._v(" "),t("td",[e._v("@stimulusGeneratorFunc (e.g., @PoissonStimulusTrain)")])]),e._v(" "),t("tr",[t("td",[e._v("vr.stimulusParameters")]),e._v(" "),t("td",[e._v("Parameters for a stimulus inherited when running the experiment (so stimulus parameters that change between mazes but are not defined by the stimuli themselves)")]),e._v(" "),t("td",[e._v("Cell array (see below for more details)")])]),e._v(" "),t("tr",[t("td",[e._v("vr.inheritedVariables")]),e._v(" "),t("td",[e._v("Parameters for a maze inherited when running the experiment (so maze parameters that change between mazes but are not defined by the stimuli themselves)")]),e._v(" "),t("td",[e._v("Cell array (see below for more details)")])])])]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[e._v("Global settings variables:")])]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("Parameter name")]),e._v(" "),t("th",[e._v("Definition")]),e._v(" "),t("th",[e._v("Values accepted")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("cueMinSeparation")]),e._v(" "),t("td",[e._v("Min distance between two towers on the same side")]),e._v(" "),t("td",[e._v("Real number (>0)")])]),e._v(" "),t("tr",[t("td",[e._v("fracDuplicated")]),e._v(" "),t("td",[e._v("Proportion of trials that are duplicated")]),e._v(" "),t("td",[e._v("Real number ([0-1])")])]),e._v(" "),t("tr",[t("td",[e._v("trialDuplication")]),e._v(" "),t("td",[e._v("Number of times each set of stimulus parameters are duplicated, for a given fracDuplicated (i.e., number of exact replications of each trial type for the duplicated fraction of trials)")]),e._v(" "),t("td",[e._v("Natural number")])])])]),e._v(" "),t("h4",{attrs:{id:"stimuli-bank-file"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#stimuli-bank-file"}},[e._v("#")]),e._v(" Stimuli bank file")]),e._v(" "),t("ul",[t("li",[e._v("Located in "),t("strong",[e._v("ViRMEn\\experiments\\protocols")]),e._v(" (Rigs) or "),t("strong",[e._v("tankmousevr\\experiments\\protocols")]),e._v(" (Personal computer) directory.")]),e._v(" "),t("li",[e._v("File that contains stimuli sets that will be drawn for during session. It contains trial data: towers positions, number of towers for each maze level depending on protocol variables.")]),e._v(" "),t("li",[e._v("Original file: "),t("code",[e._v("C:\\Experiments\\ViRMEn\\experiments\\protocols\\stimulus_trains_PoissonBlocksCondensed3m.mat")])]),e._v(" "),t("li",[e._v("Most common use:")])]),e._v(" "),t("ol",[t("li",[e._v("Create protocol and world files.")]),e._v(" "),t("li",[e._v("Run "),t("code",[e._v("generatePoissonStimuli(('world_file'), @('protocol_file'))")]),e._v(". Substitute "),t("strong",[e._v("world_file & protocol_file")]),e._v(" with corresponding names.")])]),e._v(" "),t("h4",{attrs:{id:"program-wrapper-file"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#program-wrapper-file"}},[e._v("#")]),e._v(" Program wrapper file")]),e._v(" "),t("ul",[t("li",[e._v("Located in "),t("strong",[e._v("ViRMEn\\experiments\\programs")]),e._v(" (Rigs) or "),t("strong",[e._v("tankmousevr\\experiments\\programs")]),e._v(" (Personal computer) directory.")]),e._v(" "),t("li",[e._v("File to set up a cohort of animals on the training GUI.")]),e._v(" "),t("li",[e._v("Original file: "),t("code",[e._v("C:\\Experiments\\ViRMEn\\experiments\\programs\\trainPoissonBlocks_lp_cohort1.m")])]),e._v(" "),t("li",[e._v("Most common use:")])]),e._v(" "),t("ol",[t("li",[e._v("Copy the existing Program wrapper file from the most similar task.")]),e._v(" "),t("li",[e._v("Rename file to descriptive name (e.g. "),t("strong",[e._v('train"TaskName"_cohort(n).m')]),e._v(")")]),e._v(" "),t("li",[e._v("In the call to "),t("strong",[e._v("runCohortExperiment")]),e._v(" function rename first 3 parameters:")])]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("dataPath:")]),e._v(" should be "),t("code",[e._v("C:\\Data\\(NETID)\\(String to represent protocol, task or cohort)")])]),e._v(" "),t("li",[t("strong",[e._v("experName")]),e._v(" should be the Experiment Code name (without .m)")]),e._v(" "),t("li",[t("strong",[e._v("cohortName")]),e._v(" should be a string to identify Cohort.")])]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("experName & cohortName")]),e._v(" will be appended to behavior files.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(485)}}),e._v(" "),t("center",[t("figcaption",[e._v("Program Wrapper File")])])],1),e._v(" "),t("h4",{attrs:{id:"rigparameters-file"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#rigparameters-file"}},[e._v("#")]),e._v(" RigParameters file")]),e._v(" "),t("ul",[t("li",[e._v("Located in "),t("strong",[e._v("ViRMEn\\extras")]),e._v(" (Rigs) or "),t("strong",[e._v("tankmousevr\\extras")]),e._v(" (Personal computer) directory.")]),e._v(" "),t("li",[e._v("File that defines a bunch of parameters to control/adjust hardware, display and motion in task.")]),e._v(" "),t("li",[e._v("Only file: "),t("code",[e._v("C:\\Experiments\\extras\\RigParameters.m")])])]),e._v(" "),t("h5",{attrs:{id:"if-working-on-a-rig-computer"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#if-working-on-a-rig-computer"}},[e._v("#")]),e._v(" If working on a rig computer:")]),e._v(" "),t("ul",[t("li",[e._v("Most likely that this file has been set up by Lab Manager. Do nothing.")])]),e._v(" "),t("h5",{attrs:{id:"if-working-on-a-personal-computer"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#if-working-on-a-personal-computer"}},[e._v("#")]),e._v(" If working on a personal computer:")]),e._v(" "),t("ul",[t("li",[e._v("The most common use for this file when working on a personal computer is to run ViRMEn simulations without interacting with the hardware, to do this set:")]),e._v(" "),t("li",[t("code",[e._v("simulationMode: = true")])]),e._v(" "),t("li",[t("code",[e._v("hasDAQ: = false")])]),e._v(" "),t("li",[e._v("This will allow you to run simulations on any Windows computer and use the keyboard to simulate mouse movement.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(486)}}),e._v(" "),t("center",[t("figcaption",[e._v("RigParameters File")])])],1),e._v(" "),t("h2",{attrs:{id:"set-up-training"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#set-up-training"}},[e._v("#")]),e._v(" Set up training")]),e._v(" "),t("ol",[t("li",[e._v("Make sure you have all files needed on the section above.")]),e._v(" "),t("li",[e._v("Run your "),t("strong",[e._v("Program wrapper file")]),e._v(" (e.g. "),t("code",[e._v("trainPoissonBlocks_lp_cohort1()")]),e._v(").")]),e._v(" "),t("li",[e._v("Training GUI will be shown:")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(487)}}),e._v(" "),t("center",[t("figcaption",[e._v("Main screen training GUI")])])],1),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[e._v("Click on "),t("strong",[e._v("Connect to Database")]),e._v(" button.")]),e._v(" "),t("li",[e._v("Click on "),t("strong",[e._v("Add animal")]),e._v(" button.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(488)}}),e._v(" "),t("center",[t("figcaption",[e._v("Add animal dialog")])])],1),e._v(" "),t("ol",{attrs:{start:"6"}},[t("li",[e._v("Fill corresponding information for animal to train (see next section).")]),e._v(" "),t("li",[e._v("Click on "),t("strong",[e._v("Submit")]),e._v(" button.")]),e._v(" "),t("li",[e._v("Repeat steps 5-7 to add all animals from the cohort.")]),e._v(" "),t("li",[e._v("Click on "),t("strong",[e._v("Save regiment")]),e._v(" button.")]),e._v(" "),t("li",[e._v("Click on "),t("strong",[e._v('"Empty area" section')]),e._v(" where desired subject to train is shown.")]),e._v(" "),t("li",[e._v("Click on "),t("strong",[e._v('TRAIN "SubjectFullname"')]),e._v(" button")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(489)}}),e._v(" "),t("center",[t("figcaption",[e._v("Main screen training GUI with subject")])])],1),e._v(" "),t("h3",{attrs:{id:"set-up-motor-positioning"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#set-up-motor-positioning"}},[e._v("#")]),e._v(" Set up motor positioning")]),e._v(" "),t("ul",[t("li",[e._v("If the rig where training is happening has a motor positioning system (ask lab manager about it). It is needed to set up initial coordinates for each subject training in the rig.")])]),e._v(" "),t("ol",[t("li",[e._v("Adjust subject positioning for the first time in the rig with the motor GUI (installed in the rig computer).")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(490)}}),e._v(" "),t("center",[t("figcaption",[e._v("Motor GUI")])])],1),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("In MATLAB write the following (replace code in brackets with corresponding info for the subject):")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("new_record = struct\nnew_record.subject_fullname = ['efonseca_ef481_actpg004']; # Subject fullname \nnew_record.ml_position = [17.5] # ml position in mm (motor axis#1 position in GUI)\nnew_record.ap_position = [10] # ap position in mm (motor axis#2 position in GUI)\nnew_record.dv_position = [15.3] # dv position in mm (motor axis#3 position in GUI)\ninsert(subject.LickometerMotorPosition, new_record)\n")])])]),t("h2",{attrs:{id:"training-gui-detailed-description"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#training-gui-detailed-description"}},[e._v("#")]),e._v(" Training GUI detailed description")]),e._v(" "),t("p",[e._v("In this section all elements of the training GUI will be described:")]),e._v(" "),t("figure",[t("img",{attrs:{src:i(491)}}),e._v(" "),t("center",[t("figcaption",[e._v("Training GUI main screen parts")])])],1),e._v(" "),t("ul",[t("li",[e._v("From the main screen we have divided all elements in three categories ("),t("span",{staticStyle:{color:"red"}},[t("em",[e._v("red")]),e._v(" = rarely used or not used at all; ")]),t("span",{staticStyle:{color:"rgb(184, 146, 68)"}},[t("em",[e._v("yellow")]),e._v(" = used in specific situations; ")]),t("span",{staticStyle:{color:"green"}},[t("em",[e._v("green")]),e._v(" = widely used")]),e._v(").")])]),e._v(" "),t("ol",[t("li",[t("strong",[e._v("Branch information section:")]),e._v(' For git users, informs which branch is checked out right now and if the current version code has current changes on it. The vast majority of the times it should be written "master" & "synced". Go to section pulling/pushing code if not the case.')]),e._v(" "),t("li",[t("strong",[e._v("Schedule calendar:")]),e._v(" Day of the week & time when subjects should be trained. This information is not crucial for training at the moment.")]),e._v(" "),t("li",[t("strong",[e._v("Ball displacement plot:")]),e._v(" Figure that shows real time velocity in X & Y for the subject in the rig. This plot is used to detect ball movement sensor issues.")]),e._v(" "),t("li",[t("strong",[e._v("RigParameters info bar:")]),e._v(" This bar is in red color whenever simulation mode is activated or hasDaq parameter is set to false. If this is the case both parameters should be reset for training to start. If simulation mode is intended ignore this bar.")]),e._v(" "),t("li",[t("strong",[e._v("Test session checkbox:")]),e._v(" If next session goal will be to test code or behavior won't be analyzed check this box. Session will not be stored in our DB.")]),e._v(" "),t("li",[t("strong",[e._v("Open valve buttons:")]),e._v(" These buttons are used to give a little reward to subject in rig and/or to test valve function.")]),e._v(" "),t("li",[t("strong",[e._v("Connect to DB button:")]),e._v(" Use this button to connect to DB, it should be the first thing to do when training GUI is open. "),t("a",{attrs:{href:"https://braincogs.github.io//software/virmen_guide.html#set-up-training"}},[e._v("Check set up training seciton")])]),e._v(" "),t("li",[t("strong",[e._v("Add animal button:")]),e._v(" Use this button to add a new subject to cohort. "),t("a",{attrs:{href:"https://braincogs.github.io//software/virmen_guide.html#set-up-training"}},[e._v("Check set up training seciton")]),e._v(" and "),t("a",{attrs:{href:"https://braincogs.github.io//software/virmen_guide.html#add-animal-dialog-detailed-description"}},[e._v("Add animal dialog detailed description")])]),e._v(" "),t("li",[t("strong",[e._v("Edit animal button:")]),e._v(' Button to change some parameter on the "add animal button" dialog for an already added subject to the cohort.')]),e._v(" "),t("li",[t("strong",[e._v("Remove animal button:")]),e._v(" Button to remove subject from cohort (do this when animal has finished training).")]),e._v(" "),t("li",[t("strong",[e._v("Save regiment button:")]),e._v(" Click this button whenever a subject is added, edited or removed to save changes.")]),e._v(" "),t("li",[t("strong",[e._v("Train button:")]),e._v(" Click this button to start training of selected subject.")]),e._v(" "),t("li",[t("strong",[e._v("Close GUI:")]),e._v(" Click to close GUI.")]),e._v(" "),t("li",[t("strong",[e._v("Restart MATLAB shortcut:")]),e._v(" Click to restart MATLAB.")])]),e._v(" "),t("h2",{attrs:{id:"add-animal-dialog-detailed-description"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#add-animal-dialog-detailed-description"}},[e._v("#")]),e._v(" Add animal dialog detailed description")]),e._v(" "),t("figure",[t("img",{attrs:{src:i(492)}}),e._v(" "),t("center",[t("figcaption",[e._v("Training GUI main screen parts")])])],1),e._v(" "),t("ul",[t("li",[e._v("From the add animal dialog we have divided all elements in three categories ("),t("span",{staticStyle:{color:"red"}},[t("em",[e._v("red")]),e._v(" = rarely used or not used at all; ")]),t("span",{staticStyle:{color:"rgb(184, 146, 68)"}},[t("em",[e._v("yellow")]),e._v(" = used in specific situations; ")]),t("span",{staticStyle:{color:"green"}},[t("em",[e._v("green")]),e._v(" = widely used")]),e._v("). Sections not described are not used.")])]),e._v(" "),t("ol",[t("li",[t("strong",[e._v("Subject selection:")]),e._v(" Dropdown list of all available for training subjects in BRAINCoGS.")]),e._v(" "),t("li",[t("strong",[e._v("Reward Factor:")]),e._v(" Multiplier to be used for reward for each one of the warm-up & main mazes. Regularly reward is 4ul for each correct trial on Towers Task. (e.g. if "),t("code",[e._v("RewardFactor = 1.25 -> Reward = 4*1.25 = 5 ul")]),e._v(").")]),e._v(" "),t("li",[t("strong",[e._v("Motion blur range:")]),e._v(" Parameter to set up cue elongation effect opposite to direction of subject motion in virtual reality. 2x1 vector where first element is distance (in cm) from subject to tower cue to start elongation and second element is distance (in cm) to stop elongation effect. No motion blur effect if empty. Common values: "),t("code",[e._v("[28 5], []")])]),e._v(" "),t("li",[t("strong",[e._v("Restart or append session:")]),e._v(" Action to perform if a session is restarted.")])]),e._v(" "),t("ul",[t("li",[e._v("If "),t("strong",[e._v("APPEND SESSION")]),e._v(' is selected, every time session is restarted, the "new" session will be counted as new blocks of the same session.')]),e._v(" "),t("li",[e._v("If "),t("strong",[e._v("START NEW SESSION")]),e._v(" is selected, every time session is restarted a new session will be created (recommended when physiology recordings are performed to facilitare syncing process)")])]),e._v(" "),t("ol",{attrs:{start:"5"}},[t("li",[t("strong",[e._v("Protocol code file selector:")]),e._v(" Dropdown to select protocol code file, check "),t("a",{attrs:{href:"https://braincogs.github.io/software/virmen_guide.html#new-task-creation"}},[e._v("New task creation section for detailed information")])]),e._v(" "),t("li",[t("strong",[e._v("Experiment code file selector:")]),e._v(" Dropdown to select experiment code file, check "),t("a",{attrs:{href:"https://braincogs.github.io//software/virmen_guide.html#new-task-creation"}},[e._v("New task creation section for detailed information")])]),e._v(" "),t("li",[t("strong",[e._v("Stimulus bank file selector:")]),e._v(" Dropdown to select stimulus bank file, check "),t("a",{attrs:{href:"https://braincogs.github.io//software/virmen_guide.html#new-task-creation"}},[e._v("New task creation section for detailed information")])]),e._v(" "),t("li",[t("strong",[e._v("stimulus Set edit:")]),e._v(" If stimulus bank has more than one set it can be set from here. Only change this if you know deeply the stimulus bank file and you know what you are doing.")]),e._v(" "),t("li",[t("strong",[e._v("How warm up trials are drawn:")]),e._v(" Strategy to select left or right trials based on previous bias and performance. Default value eradeTrial described "),t("a",{attrs:{href:" https://pubmed.ncbi.nlm.nih.gov/11550944/"}},[e._v("here")])]),e._v(" "),t("li",[t("strong",[e._v("How main trials are drawn:")]),e._v(" Strategy to select left or right trials based on previous bias and performance. Default value eradeTrial described "),t("a",{attrs:{href:" https://pubmed.ncbi.nlm.nih.gov/11550944/"}},[e._v("here")])]),e._v(" "),t("li",[t("strong",[e._v("Subtask selector:")]),e._v(" If session is from a specific subtask you can select it here. Check "),t("a",{attrs:{href:"https://braincogs.github.io//software/subtask_pipeline.html"}},[e._v("subtask pipeline section")]),e._v(" for more information.")]),e._v(" "),t("li",[t("strong",[e._v("Pupillometry video:")]),e._v(" If pupillometry video is going to be captured, select video parameters here.")]),e._v(" "),t("li",[t("strong",[e._v("Behavior video:")]),e._v(" If behavior video is going to be captured, select video parameters here.")]),e._v(" "),t("li",[t("strong",[e._v("Manipulation selector:")]),e._v(" If session is from a specific manipulation you can select it here. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/manipulation_pipeline.html"}},[e._v("manipulation pipeline section")]),e._v(" for more information.")]),e._v(" "),t("li",[t("strong",[e._v("Stimulation protocol:")]),e._v(" If session is from a specific manipulation Select stimulation protocol in this dropdown. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/manipulation_pipeline.html"}},[e._v("manipulation pipeline section")]),e._v(" for more information.")]),e._v(" "),t("li",[t("strong",[e._v("Software parameters:")]),e._v(" If session is from a specific manipulation Select software parameters in this dropdown. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/manipulation_pipeline.html"}},[e._v("manipulation pipeline section")]),e._v(" for more information.")])]),e._v(" "),t("h2",{attrs:{id:"tips-and-tricks-experiment-code"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#tips-and-tricks-experiment-code"}},[e._v("#")]),e._v(" Tips and Tricks Experiment Code")]),e._v(" "),t("h3",{attrs:{id:"add-variables-to-behavior-file"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#add-variables-to-behavior-file"}},[e._v("#")]),e._v(" Add variables to behavior file")]),e._v(" "),t("ul",[t("li",[e._v("It is often needed to store more variables to behavior file for further analysis.")])]),e._v(" "),t("h4",{attrs:{id:"add-variables-on-the-trial-level"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#add-variables-on-the-trial-level"}},[e._v("#")]),e._v(" Add variables on the trial level")]),e._v(" "),t("ol",[t("li",[e._v("Go to function "),t("code",[e._v("setupTrials")]),e._v(" on the Experiment code")]),e._v(" "),t("li",[e._v("Find line like this: "),t("code",[e._v("cfg.trialData = { 'trialProb', 'trialType', 'choice', 'trialID' ... ")])]),e._v(" "),t("li",[e._v("Add variable name at the end of "),t("strong",[e._v("cfg.trialData")]),e._v(" cell array.")])]),e._v(" "),t("ul",[t("li",[e._v("Remember to define that variable as vr.(variableName) on "),t("code",[e._v("initializationCodeFun()")]),e._v(" or "),t("code",[e._v("runtimeCodeFun()")]),e._v(" before 1st trial is over.")])]),e._v(" "),t("h4",{attrs:{id:"add-variables-on-the-block-level"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#add-variables-on-the-block-level"}},[e._v("#")]),e._v(" Add variables on the block level")]),e._v(" "),t("ol",[t("li",[e._v("Go to function "),t("code",[e._v("setupTrials")]),e._v(" on the Experiment code")]),e._v(" "),t("li",[e._v("Find line like this: "),t("code",[e._v("cfg.blockData = { 'mazeID', 'mainMazeID', 'motionBlurRange', 'iterStr', 'shapingProtocol' ... ")])]),e._v(" "),t("li",[e._v("Add variable name at the end of "),t("strong",[e._v("cfg.trialData")]),e._v(" cell array.")])]),e._v(" "),t("ul",[t("li",[e._v("Remember to define that variable as vr.(variableName) on "),t("code",[e._v("initializationCodeFun()")]),e._v(" or "),t("code",[e._v("runtimeCodeFun()")]),e._v(" before 1st trial is over.")])]),e._v(" "),t("h3",{attrs:{id:"set-code-ready-for-simulation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#set-code-ready-for-simulation"}},[e._v("#")]),e._v(" Set code ready for simulation")]),e._v(" "),t("ul",[t("li",[e._v("It is useful to have Experiment code ready for simulations. To test all changes without interacting with the rig hardware.")]),e._v(" "),t("li",[e._v("Setting code for simulation also enable making trial by trial videos with "),t("a",{attrs:{href:"https://github.com/BrainCOGS/ReproduceTrialTowers"}},[e._v("ReproduceTrialTowers repository")])])]),e._v(" "),t("ol",[t("li",[e._v("Search all lines is experiment code that interact with hardware: (all lines starting with: "),t("strong",[e._v("nidaq..")]),e._v(" and "),t("strong",[e._v("updateDAQSyncSignals")]),e._v(" function. (hardware code lines)")]),e._v(" "),t("li",[e._v("Add this line "),t("code",[e._v("if RigParameters.hasDAQ")]),e._v(" before hardware code lines and close if after them.")])]),e._v(" "),t("h3",{attrs:{id:"solve-common-errors-during-training"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#solve-common-errors-during-training"}},[e._v("#")]),e._v(" Solve common errors during training")]),e._v(" "),t("h4",{attrs:{id:"arduino-serial-communication-error"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#arduino-serial-communication-error"}},[e._v("#")]),e._v(" Arduino Serial communication error")]),e._v(" "),t("ul",[t("li",[e._v("Errors like these:")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Open failed: Port: COM7 is not available. Available ports: COM1.\nUse INSTRFIND to determine if other instrument objects are connected to the requested device.\n")])])]),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Serial communications have not been properly initiated.\n")])])]),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Device Error: Unanticipated host error\n")])])]),t("ul",[t("li",[e._v("Are the most common error during training. Check if Arduino COM Port is found in device manager and restart MATLAB and/or system to solve this.")])]),e._v(" "),t("h4",{attrs:{id:"virmen-variable-not-properly-set"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#virmen-variable-not-properly-set"}},[e._v("#")]),e._v(" virmen variable not properly set")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Reference to non-existent field (variable_name)...\n")])])]),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Unrecognized field name (variable_name).\n")])])]),t("ul",[t("li",[e._v("This error is solved if variable is initialized in "),t("code",[e._v("initializationCodeFun()")]),e._v(" (e.g: "),t("code",[e._v("vr.(variable_name) = 0")]),e._v(")")])]),e._v(" "),t("h4",{attrs:{id:"nidaq-channel-is-busy-or-not-found"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#nidaq-channel-is-busy-or-not-found"}},[e._v("#")]),e._v(" Nidaq channel is busy or not found")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v(" [nidaqPulseRightReward:commit] Requested operation could not be performed, because the specified digital lines are either reserved or the device is not present in NI-DAQmx.\n It is possible that these lines are reserved by another task or the device is being reset. If you are using these lines with another task, wait for the task to complete. If you want to force the other task to relinquish the device, reset the device. If you are resetting the device, wait for the reset to finish.\n Device: Dev1\n\n Task Name: RightReward\n\n Status Code: -200587\n")])])]),t("ul",[t("li",[e._v("Review "),t("strong",[e._v("RigParameters.m")]),e._v(" file and check that there is no overlap between input/output channel variables: (rewardChannel, laserChannel, rightPuffChannel, leftPuffChannel,rightRewardChannel, leftRewardChannel, newIterationChannel, newTrialChannel, etc.)")])])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/2.f73e3e1e.js b/assets/js/2.f73e3e1e.js new file mode 100644 index 0000000..2fdf54c --- /dev/null +++ b/assets/js/2.f73e3e1e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{248:function(t,e,a){},249:function(t,e){t.exports=function(t){return null==t}},251:function(t,e,a){},252:function(t,e,a){},253:function(t,e,a){},255:function(t,e,a){"use strict";a(248)},256:function(t,e,a){"use strict";a.r(e);var n=a(269),s=a(258),i=a(242);function r(t,e){if("group"===e.type){const a=e.path&&Object(i.e)(t,e.path),n=e.children.some(e=>"group"===e.type?r(t,e):"page"===e.type&&Object(i.e)(t,e.path));return a||n}return!1}var o={name:"SidebarLinks",components:{SidebarGroup:n.default,SidebarLink:s.default},props:["items","depth","sidebarDepth","initialOpenGroupIndex"],data(){return{openGroupIndex:this.initialOpenGroupIndex||0}},watch:{$route(){this.refreshIndex()}},created(){this.refreshIndex()},methods:{refreshIndex(){const t=function(t,e){for(let a=0;a-1&&(this.openGroupIndex=t)},toggleGroup(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive(t){return Object(i.e)(this.$route,t.regularPath)}}},l=a(10),u=Object(l.a)(o,(function(){var t=this,e=t._self._c;return t.items.length?e("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(a,n){return e("li",{key:n},["group"===a.type?e("SidebarGroup",{attrs:{item:a,open:n===t.openGroupIndex,collapsable:a.collapsable||a.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(n)}}}):e("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:a}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=u.exports},258:function(t,e,a){"use strict";a.r(e);var n=a(242);function s(t,e,a,n,s){const i={props:{to:e,activeClass:"",exactActiveClass:""},class:{active:n,"sidebar-link":!0}};return s>2&&(i.style={"padding-left":s+"rem"}),t("RouterLink",i,a)}function i(t,e,a,r,o,l=1){return!e||l>o?null:t("ul",{class:"sidebar-sub-headers"},e.map(e=>{const u=Object(n.e)(r,a+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[s(t,a+"#"+e.slug,e.title,u,e.level-1),i(t,e.children,a,r,o,l+1)])}))}var r={functional:!0,props:["item","sidebarDepth"],render(t,{parent:{$page:e,$site:a,$route:r,$themeConfig:o,$themeLocaleConfig:l},props:{item:u,sidebarDepth:c}}){const p=Object(n.e)(r,u.path),d="auto"===u.type?p||u.children.some(t=>Object(n.e)(r,u.basePath+"#"+t.slug)):p,h="external"===u.type?function(t,e,a){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[a,t("OutboundLink")])}(t,u.path,u.title||u.path):s(t,u.path,u.title||u.path,d),f=[e.frontmatter.sidebarDepth,c,l.sidebarDepth,o.sidebarDepth,1].find(t=>void 0!==t),b=l.displayAllHeaders||o.displayAllHeaders;if("auto"===u.type)return[h,i(t,u.children,u.basePath,r,f)];if((d||b)&&u.headers&&!n.d.test(u.path)){return[h,i(t,Object(n.c)(u.headers),u.path,r,f)]}return h}},o=(a(255),a(10)),l=Object(o.a)(r,void 0,void 0,!1,null,null,null);e.default=l.exports},259:function(t,e,a){},262:function(t,e,a){"use strict";a(251)},263:function(t,e,a){var n=a(12),s=a(4),i=a(11);t.exports=function(t){return"string"==typeof t||!s(t)&&i(t)&&"[object String]"==n(t)}},264:function(t,e,a){"use strict";a(252)},265:function(t,e,a){},266:function(t,e,a){"use strict";a(253)},267:function(t,e,a){},269:function(t,e,a){"use strict";a.r(e);var n=a(242),s={name:"SidebarGroup",components:{DropdownTransition:a(245).default},props:["item","open","collapsable","depth"],beforeCreate(){this.$options.components.SidebarLinks=a(256).default},methods:{isActive:n.e}},i=(a(266),a(10)),r=Object(i.a)(s,(function(){var t=this,e=t._self._c;return e("section",{staticClass:"sidebar-group",class:[{collapsable:t.collapsable,"is-sub-group":0!==t.depth},"depth-"+t.depth]},[t.item.path?e("RouterLink",{staticClass:"sidebar-heading clickable",class:{open:t.open,active:t.isActive(t.$route,t.item.path)},attrs:{to:t.item.path},nativeOn:{click:function(e){return t.$emit("toggle")}}},[e("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?e("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]):e("p",{staticClass:"sidebar-heading",class:{open:t.open},on:{click:function(e){return t.$emit("toggle")}}},[e("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?e("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]),t._v(" "),e("DropdownTransition",[t.open||!t.collapsable?e("SidebarLinks",{staticClass:"sidebar-group-items",attrs:{items:t.item.children,"sidebar-depth":t.item.sidebarDepth,"initial-open-group-index":t.item.initialOpenGroupIndex,depth:t.depth+1}}):t._e()],1)],1)}),[],!1,null,null,null);e.default=r.exports},270:function(t,e,a){"use strict";a.r(e);var n=a(249),s=a.n(n),i=a(242),r={name:"PageEdit",computed:{lastUpdated(){return this.$page.lastUpdated},lastUpdatedText(){return"string"==typeof this.$themeLocaleConfig.lastUpdated?this.$themeLocaleConfig.lastUpdated:"string"==typeof this.$site.themeConfig.lastUpdated?this.$site.themeConfig.lastUpdated:"Last Updated"},editLink(){const t=s()(this.$page.frontmatter.editLink)?this.$site.themeConfig.editLinks:this.$page.frontmatter.editLink,{repo:e,docsDir:a="",docsBranch:n="master",docsRepo:i=e}=this.$site.themeConfig;return t&&i&&this.$page.relativePath?this.createEditLink(e,i,a,n,this.$page.relativePath):null},editLinkText(){return this.$themeLocaleConfig.editLinkText||this.$site.themeConfig.editLinkText||"Edit this page"}},methods:{createEditLink(t,e,a,n,s){if(/bitbucket.org/.test(e)){return e.replace(i.a,"")+"/src"+`/${n}/`+(a?a.replace(i.a,"")+"/":"")+s+`?mode=edit&spa=0&at=${n}&fileviewer=file-view-default`}if(/gitlab.com/.test(e)){return e.replace(i.a,"")+"/-/edit"+`/${n}/`+(a?a.replace(i.a,"")+"/":"")+s}return(i.i.test(e)?e:"https://github.com/"+e).replace(i.a,"")+"/edit"+`/${n}/`+(a?a.replace(i.a,"")+"/":"")+s}}},o=(a(262),a(10)),l=Object(o.a)(r,(function(){var t=this,e=t._self._c;return e("footer",{staticClass:"page-edit"},[t.editLink?e("div",{staticClass:"edit-link"},[e("a",{attrs:{href:t.editLink,target:"_blank",rel:"noopener noreferrer"}},[t._v(t._s(t.editLinkText))]),t._v(" "),e("OutboundLink")],1):t._e(),t._v(" "),t.lastUpdated?e("div",{staticClass:"last-updated"},[e("span",{staticClass:"prefix"},[t._v(t._s(t.lastUpdatedText)+":")]),t._v(" "),e("span",{staticClass:"time"},[t._v(t._s(t.lastUpdated))])]):t._e()])}),[],!1,null,null,null);e.default=l.exports},271:function(t,e,a){"use strict";a.r(e);a(90);var n=a(242),s=a(263),i=a.n(s),r=a(249),o=a.n(r),l={name:"PageNav",props:["sidebarItems"],computed:{prev(){return c(u.PREV,this)},next(){return c(u.NEXT,this)}}};const u={NEXT:{resolveLink:function(t,e){return p(t,e,1)},getThemeLinkConfig:({nextLinks:t})=>t,getPageLinkConfig:({frontmatter:t})=>t.next},PREV:{resolveLink:function(t,e){return p(t,e,-1)},getThemeLinkConfig:({prevLinks:t})=>t,getPageLinkConfig:({frontmatter:t})=>t.prev}};function c(t,{$themeConfig:e,$page:a,$route:s,$site:r,sidebarItems:l}){const{resolveLink:u,getThemeLinkConfig:c,getPageLinkConfig:p}=t,d=c(e),h=p(a),f=o()(h)?d:h;return!1===f?void 0:i()(f)?Object(n.k)(r.pages,f,s.path):u(a,l)}function p(t,e,a){const n=[];!function t(e,a){for(let n=0,s=e.length;n({isSidebarOpen:!1}),computed:{shouldShowNavbar(){const{themeConfig:t}=this.$site,{frontmatter:e}=this.$page;return!1!==e.navbar&&!1!==t.navbar&&(this.$title||t.logo||t.repo||t.nav||this.$themeLocaleConfig.nav)},shouldShowSidebar(){const{frontmatter:t}=this.$page;return!t.home&&!1!==t.sidebar&&this.sidebarItems.length},sidebarItems(){return Object(o.l)(this.$page,this.$page.regularPath,this.$site,this.$localePath)},pageClasses(){const t=this.$page.frontmatter.pageClass;return[{"no-navbar":!this.shouldShowNavbar,"sidebar-open":this.isSidebarOpen,"no-sidebar":!this.shouldShowSidebar},t]}},mounted(){this.$router.afterEach(()=>{this.isSidebarOpen=!1})},methods:{toggleSidebar(t){this.isSidebarOpen="boolean"==typeof t?t:!this.isSidebarOpen,this.$emit("toggle-sidebar",this.isSidebarOpen)},onTouchStart(t){this.touchStart={x:t.changedTouches[0].clientX,y:t.changedTouches[0].clientY}},onTouchEnd(t){const e=t.changedTouches[0].clientX-this.touchStart.x,a=t.changedTouches[0].clientY-this.touchStart.y;Math.abs(e)>Math.abs(a)&&Math.abs(e)>40&&(e>0&&this.touchStart.x<=80?this.toggleSidebar(!0):this.toggleSidebar(!1))}}},u=a(10),c=Object(u.a)(l,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"theme-container",class:t.pageClasses,on:{touchstart:t.onTouchStart,touchend:t.onTouchEnd}},[t.shouldShowNavbar?e("Navbar",{on:{"toggle-sidebar":t.toggleSidebar}}):t._e(),t._v(" "),e("div",{staticClass:"sidebar-mask",on:{click:function(e){return t.toggleSidebar(!1)}}}),t._v(" "),e("Sidebar",{attrs:{items:t.sidebarItems},on:{"toggle-sidebar":t.toggleSidebar},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("sidebar-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("sidebar-bottom")]},proxy:!0}],null,!0)}),t._v(" "),t.$page.frontmatter.home?e("Home"):e("Page",{attrs:{"sidebar-items":t.sidebarItems},scopedSlots:t._u([{key:"top",fn:function(){return[t._t("page-top")]},proxy:!0},{key:"bottom",fn:function(){return[t._t("page-bottom")]},proxy:!0}],null,!0)})],1)}),[],!1,null,null,null);e.default=c.exports}}]); \ No newline at end of file diff --git a/assets/js/20.aa1d6fa3.js b/assets/js/20.aa1d6fa3.js new file mode 100644 index 0000000..cfa6fe2 --- /dev/null +++ b/assets/js/20.aa1d6fa3.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[20,23,35,42],{242:function(t,e,n){"use strict";n.d(e,"d",(function(){return i})),n.d(e,"a",(function(){return s})),n.d(e,"i",(function(){return a})),n.d(e,"f",(function(){return l})),n.d(e,"g",(function(){return u})),n.d(e,"h",(function(){return c})),n.d(e,"b",(function(){return p})),n.d(e,"e",(function(){return h})),n.d(e,"k",(function(){return f})),n.d(e,"l",(function(){return d})),n.d(e,"c",(function(){return b})),n.d(e,"j",(function(){return g}));n(90);const i=/#.*$/,r=/\.(md|html)$/,s=/\/$/,a=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(i,"").replace(r,"")}function l(t){return a.test(t)}function u(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function p(t){if(l(t))return t;const e=t.match(i),n=e?e[0]:"",r=o(t);return s.test(r)?t:r+".html"+n}function h(t,e){const n=decodeURIComponent(t.hash),r=function(t){const e=t.match(i);if(e)return e[0]}(e);if(r&&n!==r)return!1;return o(t.path)===o(e)}function f(t,e,n){if(l(e))return{type:"external",path:e};n&&(e=function(t,e,n){const i=t.charAt(0);if("/"===i)return t;if("?"===i||"#"===i)return e+t;const r=e.split("/");n&&r[r.length-1]||r.pop();const s=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(e,n,i,r=1){if("string"==typeof e)return f(n,e,i);if(Array.isArray(e))return Object.assign(f(n,e[0],i),{title:e[1]});{const s=e.children||[];return 0===s.length&&e.path?Object.assign(f(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:s.map(e=>t(e,n,i,r+1)),collapsable:!1!==e.collapsable}}}(t,r,n)):[]}return[]}function m(t){const e=b(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function b(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function g(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},243:function(t,e,n){},244:function(t,e,n){"use strict";n.r(e);var i=n(242),r={name:"NavLink",props:{item:{required:!0}},computed:{link(){return Object(i.b)(this.item.link)},exact(){return this.$site.locales?Object.keys(this.$site.locales).some(t=>t===this.link):"/"===this.link},isNonHttpURI(){return Object(i.g)(this.link)||Object(i.h)(this.link)},isBlankTarget(){return"_blank"===this.target},isInternal(){return!Object(i.f)(this.link)&&!this.isBlankTarget},target(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(i.f)(this.link)?"_blank":""},rel(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction(){this.$emit("focusout")}}},s=n(10),a=Object(s.a)(r,(function(){var t=this,e=t._self._c;return t.isInternal?e("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):e("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?e("OutboundLink"):t._e()],1)}),[],!1,null,null,null);e.default=a.exports},245:function(t,e,n){"use strict";n.r(e);var i={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},r=(n(246),n(10)),s=Object(r.a)(i,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.default=s.exports},246:function(t,e,n){"use strict";n(243)},247:function(t,e,n){},250:function(t,e,n){},254:function(t,e,n){"use strict";n(247)},257:function(t,e,n){"use strict";n.r(e);var i=n(244),r=n(245),s=n(91),a=n.n(s),o={name:"DropdownLink",components:{NavLink:i.default,DropdownTransition:r.default},props:{item:{required:!0}},data:()=>({open:!1}),computed:{dropdownAriaLabel(){return this.item.ariaLabel||this.item.text}},watch:{$route(){this.open=!1}},methods:{setOpen(t){this.open=t},isLastItemOfArray:(t,e)=>a()(e)===t,handleDropdown(){0===event.detail&&this.setOpen(!this.open)}}},l=(n(254),n(10)),u=Object(l.a)(o,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[e("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:t.handleDropdown}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow down"})]),t._v(" "),e("button",{staticClass:"mobile-dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),e("DropdownTransition",[e("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(n,i){return e("li",{key:n.link||i,staticClass:"dropdown-item"},["links"===n.type?e("h4",[t._v("\n "+t._s(n.text)+"\n ")]):t._e(),t._v(" "),"links"===n.type?e("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(n.items,(function(i){return e("li",{key:i.link,staticClass:"dropdown-subitem"},[e("NavLink",{attrs:{item:i},on:{focusout:function(e){t.isLastItemOfArray(i,n.items)&&t.isLastItemOfArray(n,t.item.items)&&t.setOpen(!1)}}})],1)})),0):e("NavLink",{attrs:{item:n},on:{focusout:function(e){t.isLastItemOfArray(n,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null);e.default=u.exports},260:function(t,e,n){"use strict";n(250)},268:function(t,e,n){"use strict";n.r(e);var i=n(257),r=n(242),s={name:"NavLinks",components:{NavLink:n(244).default,DropdownLink:i.default},computed:{userNav(){return this.$themeLocaleConfig.nav||this.$site.themeConfig.nav||[]},nav(){const{locales:t}=this.$site;if(t&&Object.keys(t).length>1){const e=this.$page.path,n=this.$router.options.routes,i=this.$site.themeConfig.locales||{},r={text:this.$themeLocaleConfig.selectText||"Languages",ariaLabel:this.$themeLocaleConfig.ariaLabel||"Select language",items:Object.keys(t).map(r=>{const s=t[r],a=i[r]&&i[r].label||s.lang;let o;return s.lang===this.$lang?o=e:(o=e.replace(this.$localeConfig.path,r),n.some(t=>t.path===o)||(o=r)),{text:a,link:o}})};return[...this.userNav,r]}return this.userNav},userLinks(){return(this.nav||[]).map(t=>Object.assign(Object(r.j)(t),{items:(t.items||[]).map(r.j)}))},repoLink(){const{repo:t}=this.$site.themeConfig;return t?/^https?:/.test(t)?t:"https://github.com/"+t:null},repoLabel(){if(!this.repoLink)return;if(this.$site.themeConfig.repoLabel)return this.$site.themeConfig.repoLabel;const t=this.repoLink.match(/^https?:\/\/[^/]+/)[0],e=["GitHub","GitLab","Bitbucket"];for(let n=0;n SSH and GPG Keys")])]),t._v(" "),e("figure",[e("img",{attrs:{src:i(464)}}),t._v(" "),e("center",[e("figcaption",[t._v("Vrrigs ssh keys section")])])],1),t._v(" "),e("ol",{attrs:{start:"4"}},[e("li",[t._v("Click "),e("code",[t._v("New SSH Key")]),t._v(" button")]),t._v(" "),e("li",[t._v('Add a meaningful title to the key and paste public key from the clipboard in "Key" text area.')]),t._v(" "),e("li",[t._v("Click "),e("code",[t._v("Add SSH Key")]),t._v(" button")])]),t._v(" "),e("h4",{attrs:{id:"compiler"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#compiler"}},[t._v("#")]),t._v(" Compiler")]),t._v(" "),e("ol",[e("li",[t._v("Install Visual Studio Code Compiler; make sure to select C++ support from the menu. "),e("a",{attrs:{href:"https://visualstudio.microsoft.com/downloads/`"}},[t._v("https://visualstudio.microsoft.com/downloads/")])]),t._v(" "),e("li",[t._v("In MATLAB, Run "),e("code",[t._v("mex -setup -v")]),t._v('. This sets up the compiler. It should output something like found "Microsoft Visual C++ 2015"')])]),t._v(" "),e("h3",{attrs:{id:"u19-pipeline-matlab-repository"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#u19-pipeline-matlab-repository"}},[t._v("#")]),t._v(" U19-pipeline-matlab Repository")]),t._v(" "),e("ol",[e("li",[t._v("Open Git Bash and execute: "),e("code",[t._v("cd /c/Experiments")])]),t._v(" "),e("li",[t._v("Clone "),e("strong",[t._v("U19-pipeline-matlab")]),t._v(" Repository, "),e("code",[t._v("git clone git@github.com:BrainCOGS/U19-pipeline-matlab.git")])])]),t._v(" "),e("h4",{attrs:{id:"matlab-instructions"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#matlab-instructions"}},[t._v("#")]),t._v(" MATLAB Instructions")]),t._v(" "),e("ol",{attrs:{start:"3"}},[e("li",[t._v("Run "),e("code",[t._v("dj_initial_conf(0)")])]),t._v(" "),e("li",[t._v("Insert user and password for the DB")])]),t._v(" "),e("h3",{attrs:{id:"virmen-repository"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#virmen-repository"}},[t._v("#")]),t._v(" Virmen Repository")]),t._v(" "),e("ol",[e("li",[t._v("Create "),e("code",[t._v("C:\\Experiments")]),t._v(" directory")]),t._v(" "),e("li",[t._v("Open Git Bash and execute: "),e("code",[t._v("cd /c/Experiments")]),t._v(".")]),t._v(" "),e("li",[t._v("Execute in "),e("code",[t._v('git config --global user.email "alvaroluna.pni@gmail.com"')]),t._v(".")]),t._v(" "),e("li",[t._v("Clone Virmen Repository, called "),e("strong",[t._v("TankMouseVR")]),t._v(" "),e("code",[t._v("git clone https://github.com/BrainCOGS/TankMouseVR.git")]),t._v(".")]),t._v(" "),e("li",[t._v("Rename directory "),e("code",[t._v("C:\\Experiments\\TankMouseVR")]),t._v(" to "),e("code",[t._v("C:\\Experiments\\ViRMEn")]),t._v(".")])]),t._v(" "),e("h4",{attrs:{id:"matlab-instructions-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#matlab-instructions-2"}},[t._v("#")]),t._v(" MATLAB Instructions")]),t._v(" "),e("ol",{attrs:{start:"6"}},[e("li",[t._v("run "),e("code",[t._v("install_virmen")]),t._v(" inside "),e("code",[t._v("C:\\Experiments\\ViRMEn")])])]),t._v(" "),e("ul",[e("li",[t._v("If compilation fails. Run "),e("code",[t._v("mex -setup c++")]),t._v(" to select "),e("strong",[t._v("Visual Studio C++ Compiler")])])]),t._v(" "),e("ol",{attrs:{start:"7"}},[e("li",[t._v("Open file "),e("code",[t._v("C:\\Experiments\\ViRMEn\\RigParameters.m")]),t._v(" and edit corresponding variables:")])]),t._v(" "),e("ul",[e("li",[e("strong",[t._v("rig:")]),t._v(" (RigName on the format: "),e("code",[t._v('Room#-"Rig"#-T')]),t._v(")")]),t._v(" "),e("li",[e("strong",[t._v("rig_type:")]),t._v(" ("),e("code",[t._v("miniVR")]),t._v(" or "),e("code",[t._v("NormalVR")]),t._v(")")]),t._v(" "),e("li",[e("strong",[t._v("add NIDAQ Channles in corresponding variables")]),t._v(" (Ask lab manager about these parameters)")]),t._v(" "),e("li",[e("strong",[t._v("Mini VR projection parameters")]),t._v(" (Ask lab manager about these parameters)")])]),t._v(" "),e("ol",{attrs:{start:"8"}},[e("li",[t._v("run "),e("code",[t._v("lab.utils.add_behavior_rig(RigParameters.rig)")]),t._v(".")]),t._v(" "),e("li",[t._v("run "),e("code",[t._v("live_calibration")]),t._v(" experiment (Ask lab manager about this process).")]),t._v(" "),e("li",[t._v("Create a MATLAB shortcut and set "),e("strong",[t._v("Start in")]),t._v(" as "),e("code",[t._v("C:\\Experiments\\ViRMEn")]),t._v(".")]),t._v(" "),e("li",[t._v("Add this shortcut to the Windows task bar in the bottom.")])]),t._v(" "),e("figure",[e("img",{attrs:{src:i(465)}}),t._v(" "),e("center",[e("figcaption",[t._v("MATLAB Shorcut example")])])],1),t._v(" "),e("h3",{attrs:{id:"behavior-data-backup-task-schedule"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#behavior-data-backup-task-schedule"}},[t._v("#")]),t._v(" Behavior data backup task schedule")]),t._v(" "),e("ol",[e("li",[t._v("On Windows type "),e("strong",[t._v('"Task Scheduler"')])]),t._v(" "),e("li",[t._v("Open "),e("strong",[t._v("Task Scheduler")]),t._v(' "App"')]),t._v(" "),e("li",[t._v("On right hand side menu, click on "),e("strong",[t._v('"Create Task"')]),t._v(" Action")])]),t._v(" "),e("figure",[e("img",{attrs:{src:i(276)}}),t._v(" "),e("center",[e("figcaption",[t._v("Task scheduler menu")])])],1),t._v(" "),e("ol",{attrs:{start:"4"}},[e("li",[t._v("Name new task as "),e("strong",[t._v("new_data_backup")])])]),t._v(" "),e("figure",[e("img",{attrs:{src:i(466)}}),t._v(" "),e("center",[e("figcaption",[t._v("Task scheduler General Tab")])])],1),t._v(" "),e("ol",{attrs:{start:"5"}},[e("li",[t._v("Add a trigger to run task daily at 11:00 pm")])]),t._v(" "),e("figure",[e("img",{attrs:{src:i(277)}}),t._v(" "),e("center",[e("figcaption",[t._v("Task scheduler Trigger Tab")])])],1),t._v(" "),e("ol",{attrs:{start:"6"}},[e("li",[t._v("Add an action: add this line to the Program/script edit: "),e("code",[t._v("C:\\Experiments\\U19-pipeline-matlab\\scripts\\cmd_copy_behavior_files")])])]),t._v(" "),e("figure",[e("img",{attrs:{src:i(467)}}),t._v(" "),e("center",[e("figcaption",[t._v("Task scheduler Action Tab")])])],1),t._v(" "),e("ol",{attrs:{start:"7"}},[e("li",[t._v("Hit "),e("strong",[t._v("OK")]),t._v(" button")])]),t._v(" "),e("h2",{attrs:{id:"configure-new-recording-system"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#configure-new-recording-system"}},[t._v("#")]),t._v(" Configure new recording system")]),t._v(" "),e("ul",[e("li",[t._v("First install all things necessary for appropiate recording modality. (Spike GLX for electrophysiology, ScanImage for imaging).")])]),t._v(" "),e("ol",[e("li",[t._v('From Windows Explorer, select "Map Network Drive" and enter:')])]),t._v(" "),e("ul",[e("li",[e("code",[t._v("\\\\cup.pni.princeton.edu\\braininit\\")]),t._v(" (for braininit)")]),t._v(" "),e("li",[e("code",[t._v("\\\\cup.pni.princeton.edu\\u19_dj\\")]),t._v(" (for u19_dj)")])]),t._v(" "),e("ol",{attrs:{start:"2"}},[e("li",[t._v("Authenticate with your NetID and PU password (NOT your PNI password, which may be different). When prompted for your username, enter PRINCETON\\netid (note that PRINCETON can be upper or lower case) where netid is your PU NetID.")]),t._v(" "),e("li",[t._v("Copy Automation GUI files: copy "),e("code",[t._v("\\\\cup.pni.princeton.edu\\braininit\\Shared\\AutomationGUI_Installation\\AutomationGUI_update")]),t._v(" to the Desktop.")]),t._v(" "),e("li",[t._v("Run "),e("code",[t._v("Desktop\\AutomationGUI_update\\firstTimeAutomationGUI.BAT")])])]),t._v(" "),e("ul",[e("li",[t._v("Install git bash and anaconda from it.")])]),t._v(" "),e("figure",[e("img",{attrs:{src:i(468)}}),t._v(" "),e("center",[e("figcaption",[t._v("Anaconda avanced options step")])])],1),t._v(" "),e("ul",[e("li",[t._v("On Anaconda advanced options step: check "),e("strong",[t._v('"Add Anaconda3 to my PATH environment variable"')]),t._v(" checkbox.")])]),t._v(" "),e("ol",{attrs:{start:"5"}},[e("li",[t._v("Run "),e("code",[t._v("Desktop\\AutomationGUI_update\\update_AutomationGUI.BAT")])]),t._v(" "),e("li",[t._v("Follow instructions to install Recording Automation GUI. (Also called Workflow Console GUI).")])]),t._v(" "),e("figure",[e("img",{attrs:{src:i(469)}}),t._v(" "),e("center",[e("figcaption",[t._v("Anaconda avanced options step")])])],1),t._v(" "),e("h3",{attrs:{id:"register-recording-system"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#register-recording-system"}},[t._v("#")]),t._v(" Register recording system")]),t._v(" "),e("ul",[e("li",[t._v("On a computer with access to the database (e.g. any Rig Computer).")])]),t._v(" "),e("ol",[e("li",[t._v("Open MATLAB")]),t._v(" "),e("li",[t._v("Execute: "),e("code",[t._v("lab.utils.add_recording_system((recording_system_name), (modality))")]),t._v(" where:")])]),t._v(" "),e("ul",[e("li",[e("strong",[t._v("recording_system_name:")]),t._v(" (on the format: "),e("code",[t._v("Room#-Recording")]),t._v(").")]),t._v(" "),e("li",[e("strong",[t._v("modality:")]),t._v(" (one of the following: "),e("code",[t._v("electrophysiology, 2photon, 3photon, mesoscope")]),t._v(").")])])])}),[],!1,null,null,null);e.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/22.796e9949.js b/assets/js/22.796e9949.js new file mode 100644 index 0000000..42eaeae --- /dev/null +++ b/assets/js/22.796e9949.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[22],{278:function(e,t,a){"use strict";var i=TypeError;e.exports=function(e,t){if(e({placeholder:void 0}),watch:{$lang(e){this.update(this.options,e)},options(e){this.update(e,this.$lang)}},mounted(){this.initialize(this.options,this.$lang),this.placeholder=this.$site.themeConfig.searchPlaceholder||""},methods:{initialize(e,t){Promise.all([Promise.all([a.e(0),a.e(9)]).then(a.t.bind(null,494,7)),Promise.all([a.e(0),a.e(9)]).then(a.t.bind(null,495,7))]).then(([a])=>{a=a.default;const{algoliaOptions:i={}}=e;a(Object.assign({},e,{inputSelector:"#algolia-search-input",algoliaOptions:{...i,facetFilters:["lang:"+t].concat(i.facetFilters||[])},handleSelected:(e,t,a)=>{const{pathname:i,hash:n}=new URL(a.url),r=i.replace(this.$site.base,"/"),s=decodeURIComponent(n);this.$router.push(`${r}${s}`)}}))})},update(e,t){this.$el.innerHTML='',this.initialize(e,t)}}},n=(a(293),a(10)),r=Object(n.a)(i,(function(){var e=this._self._c;return e("form",{staticClass:"algolia-search-wrapper search-box",attrs:{id:"search-form",role:"search"}},[e("input",{staticClass:"search-query",attrs:{id:"algolia-search-input",placeholder:this.placeholder}})])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/23.cc03e5ad.js b/assets/js/23.cc03e5ad.js new file mode 100644 index 0000000..f4c1fb4 --- /dev/null +++ b/assets/js/23.cc03e5ad.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[23,35,42],{242:function(t,e,n){"use strict";n.d(e,"d",(function(){return i})),n.d(e,"a",(function(){return s})),n.d(e,"i",(function(){return o})),n.d(e,"f",(function(){return l})),n.d(e,"g",(function(){return u})),n.d(e,"h",(function(){return c})),n.d(e,"b",(function(){return p})),n.d(e,"e",(function(){return f})),n.d(e,"k",(function(){return h})),n.d(e,"l",(function(){return d})),n.d(e,"c",(function(){return b})),n.d(e,"j",(function(){return g}));n(90);const i=/#.*$/,r=/\.(md|html)$/,s=/\/$/,o=/^[a-z]+:/i;function a(t){return decodeURI(t).replace(i,"").replace(r,"")}function l(t){return o.test(t)}function u(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function p(t){if(l(t))return t;const e=t.match(i),n=e?e[0]:"",r=a(t);return s.test(r)?t:r+".html"+n}function f(t,e){const n=decodeURIComponent(t.hash),r=function(t){const e=t.match(i);if(e)return e[0]}(e);if(r&&n!==r)return!1;return a(t.path)===a(e)}function h(t,e,n){if(l(e))return{type:"external",path:e};n&&(e=function(t,e,n){const i=t.charAt(0);if("/"===i)return t;if("?"===i||"#"===i)return e+t;const r=e.split("/");n&&r[r.length-1]||r.pop();const s=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(e,n,i,r=1){if("string"==typeof e)return h(n,e,i);if(Array.isArray(e))return Object.assign(h(n,e[0],i),{title:e[1]});{const s=e.children||[];return 0===s.length&&e.path?Object.assign(h(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:s.map(e=>t(e,n,i,r+1)),collapsable:!1!==e.collapsable}}}(t,r,n)):[]}return[]}function m(t){const e=b(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function b(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function g(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},243:function(t,e,n){},244:function(t,e,n){"use strict";n.r(e);var i=n(242),r={name:"NavLink",props:{item:{required:!0}},computed:{link(){return Object(i.b)(this.item.link)},exact(){return this.$site.locales?Object.keys(this.$site.locales).some(t=>t===this.link):"/"===this.link},isNonHttpURI(){return Object(i.g)(this.link)||Object(i.h)(this.link)},isBlankTarget(){return"_blank"===this.target},isInternal(){return!Object(i.f)(this.link)&&!this.isBlankTarget},target(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(i.f)(this.link)?"_blank":""},rel(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction(){this.$emit("focusout")}}},s=n(10),o=Object(s.a)(r,(function(){var t=this,e=t._self._c;return t.isInternal?e("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):e("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?e("OutboundLink"):t._e()],1)}),[],!1,null,null,null);e.default=o.exports},245:function(t,e,n){"use strict";n.r(e);var i={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},r=(n(246),n(10)),s=Object(r.a)(i,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.default=s.exports},246:function(t,e,n){"use strict";n(243)},247:function(t,e,n){},254:function(t,e,n){"use strict";n(247)},257:function(t,e,n){"use strict";n.r(e);var i=n(244),r=n(245),s=n(91),o=n.n(s),a={name:"DropdownLink",components:{NavLink:i.default,DropdownTransition:r.default},props:{item:{required:!0}},data:()=>({open:!1}),computed:{dropdownAriaLabel(){return this.item.ariaLabel||this.item.text}},watch:{$route(){this.open=!1}},methods:{setOpen(t){this.open=t},isLastItemOfArray:(t,e)=>o()(e)===t,handleDropdown(){0===event.detail&&this.setOpen(!this.open)}}},l=(n(254),n(10)),u=Object(l.a)(a,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"dropdown-wrapper",class:{open:t.open}},[e("button",{staticClass:"dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:t.handleDropdown}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow down"})]),t._v(" "),e("button",{staticClass:"mobile-dropdown-title",attrs:{type:"button","aria-label":t.dropdownAriaLabel},on:{click:function(e){return t.setOpen(!t.open)}}},[e("span",{staticClass:"title"},[t._v(t._s(t.item.text))]),t._v(" "),e("span",{staticClass:"arrow",class:t.open?"down":"right"})]),t._v(" "),e("DropdownTransition",[e("ul",{directives:[{name:"show",rawName:"v-show",value:t.open,expression:"open"}],staticClass:"nav-dropdown"},t._l(t.item.items,(function(n,i){return e("li",{key:n.link||i,staticClass:"dropdown-item"},["links"===n.type?e("h4",[t._v("\n "+t._s(n.text)+"\n ")]):t._e(),t._v(" "),"links"===n.type?e("ul",{staticClass:"dropdown-subitem-wrapper"},t._l(n.items,(function(i){return e("li",{key:i.link,staticClass:"dropdown-subitem"},[e("NavLink",{attrs:{item:i},on:{focusout:function(e){t.isLastItemOfArray(i,n.items)&&t.isLastItemOfArray(n,t.item.items)&&t.setOpen(!1)}}})],1)})),0):e("NavLink",{attrs:{item:n},on:{focusout:function(e){t.isLastItemOfArray(n,t.item.items)&&t.setOpen(!1)}}})],1)})),0)])],1)}),[],!1,null,null,null);e.default=u.exports}}]); \ No newline at end of file diff --git a/assets/js/24.f1842dd7.js b/assets/js/24.f1842dd7.js new file mode 100644 index 0000000..55599fa --- /dev/null +++ b/assets/js/24.f1842dd7.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[24],{409:function(e,t,a){e.exports=a.p+"assets/img/reward-1.6c17ae34.png"},410:function(e,t,a){e.exports=a.p+"assets/img/reward-assembly-8.f74b86a0.png"},411:function(e,t,a){e.exports=a.p+"assets/img/reward-assembly-9.171b8c2e.png"},412:function(e,t,a){e.exports=a.p+"assets/img/reward-assembly-5.76194562.png"},413:function(e,t,a){e.exports=a.p+"assets/img/reward-assembly-6.baa00ee9.png"},414:function(e,t,a){e.exports=a.p+"assets/img/reward-assembly-7.6fbf9d86.png"},415:function(e,t,a){e.exports=a.p+"assets/img/reward-assembly-10.1ca5c246.png"},511:function(e,t,a){"use strict";a.r(t);var s=a(10),o=Object(s.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("p",[e._v("The reward module consist on a open srynge that holds the reward liquid that will be dispensed to the mice through a lick spout controlled by a solenoid valve.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(409)}}),e._v(" "),t("center",[t("figcaption",[t("small",[e._v("Reward spout module")])])])],1),e._v(" "),t("h2",{attrs:{id:"solenoid-valve-assembly"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#solenoid-valve-assembly"}},[e._v("#")]),e._v(" Solenoid valve assembly")]),e._v(" "),t("p",[e._v('The solneoid valve assembly consist of a standard plastic 60 mL srynge placed at the top of the rig conncected to a solenoid valve driver using Tygon PVC (for dairy) tubing. Since it\'s a gravity based module, it is recommended to place the srygne as high as possible. The srynge can be placed in the top frame of the rig cabinet using a 15/16" cable holder (you could use some thorlabs parts placed at the top of the rig to adjust the height of the srynge and place it in a higher position), remove the plunger from the srynge and use a luer lock to 1/16" ID tubing fitting to connect the srynge to the solenoid valve driver (we use the 003-0096-900 model from Parker).')]),e._v(" "),t("figure",[t("img",{attrs:{src:a(410)}}),e._v(" "),t("center",[t("figcaption",[t("small",[e._v("Reward srynge and solenoid valve driver, reward module assembly on the right.")])])])],1),e._v(" "),t("p",[e._v('To fix the reward solenoid valve to the DIN rail we use a 3D printed part, to which the solenoid valve is attached using 4-40 x 3/16" long screws and a DIN valve clip using a Rounded Head Thread-Forming Screws no. 8 5/16" long. Assemble them as shown in the picture below and attach it to the bottom DIN rail.')]),e._v(" "),t("figure",[t("img",{attrs:{src:a(411)}})]),e._v(" "),t("p",[e._v('Finally, connect the srynge to the IN plug of the solenoid valve driver and connect the OUT plug to the srynge inside the rig using 1/16" ID 1/8" OD Tygon soft tubing for food, beverages and dairy.')]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("Ee don't use the cable carrier for this tubing because it has to be replaced every month and it makes maintenance time consuming.")])]),e._v(" "),t("h2",{attrs:{id:"lick-spout-holder-assembly"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#lick-spout-holder-assembly"}},[e._v("#")]),e._v(" Lick spout holder assembly")]),e._v(" "),t("p",[e._v('The lick spout holder is designed to be fixed in the sagital and coronal position and adjustable in the Z (height) position. This way the variability in the position of both the mice and the spout is reduced. To this end, we designed a 3D printed arm that holds a spout holder, which also serves as the air puffs delivery system, that is attached to a kinetic base to make it easy to place and remove when the styrofoam ball need to be taken out. The kinetic base is screwed to a dovetail translation stage with 1/4" travel to adjust the height of the spout.')]),e._v(" "),t("p",[e._v("To assemble, follow the next steps.")]),e._v(" "),t("ol",[t("li",[e._v('Have printed the arm (we recommend an external service and PA12GB material) and install a 8-32 thread size, 0.312" installed length heath insert for plastic in the hole at the lower part of the arm that is going to be attached to the kinetic base. Then, screw the top part of the KB1X1 kinetic base from Thorlabs to the arm using an 8-32 thread size, 1/4" long low-profile screw.')])]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("To install the heat insert follow the instructions in the step 3 of the bottom plate assembly in the "),t("a",{attrs:{href:"/building/stage"}},[e._v("stage")]),e._v(" section.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(412)}})]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v('Install the 1/16" tube ID x 10-32 thread male pipe in the back of the spout holder and place it into the arm using a pair of 2-56 thread size, 5/32" long screws. Put the FNS-18-2-2 straight feeding needle from Kent scientific on the spout holder and fix the top part of the holder using a four 100 degree countersink, 0-80 thread, 7/32" long screws.')])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(413)}})]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v('Print or have printed the breadboard to DT12 adapter and screw the DT12 dovetail translation stage from Thorlabs to the adapter using a 8-32 thread size, 3/8" long flat head screw, making sure the screw to move the stage is facing up (to the ceiling of the rig). Attach at the other end the bottom part of the KB1X1 kinetic base from Thorlabs using an 8-32 thread size, 1/4" long low-profile screw. Finally, install into the breadboard using a pair of 1/4"-20 thread size, 11/16" long flat head screw.')])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(414)}})]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("Due to inaccuracies in the 3D printed part the spout might be out of position, if this problem is present it is recommended to use a different printed breadboard to DT 12 adapter as shown in the picture below, this way the position of the reward spout can be adjusted.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(415)}})])]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("Finally place the arm with the spout holder in place by connecting the top and bottom parts of the kinetic base.")])])])}),[],!1,null,null,null);t.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/25.1cc0ff2e.js b/assets/js/25.1cc0ff2e.js new file mode 100644 index 0000000..c7cc3dd --- /dev/null +++ b/assets/js/25.1cc0ff2e.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[25],{242:function(t,n,e){"use strict";e.d(n,"d",(function(){return r})),e.d(n,"a",(function(){return o})),e.d(n,"i",(function(){return a})),e.d(n,"f",(function(){return u})),e.d(n,"g",(function(){return c})),e.d(n,"h",(function(){return p})),e.d(n,"b",(function(){return l})),e.d(n,"e",(function(){return f})),e.d(n,"k",(function(){return h})),e.d(n,"l",(function(){return d})),e.d(n,"c",(function(){return v})),e.d(n,"j",(function(){return b}));e(90);const r=/#.*$/,i=/\.(md|html)$/,o=/\/$/,a=/^[a-z]+:/i;function s(t){return decodeURI(t).replace(r,"").replace(i,"")}function u(t){return a.test(t)}function c(t){return/^mailto:/.test(t)}function p(t){return/^tel:/.test(t)}function l(t){if(u(t))return t;const n=t.match(r),e=n?n[0]:"",i=s(t);return o.test(i)?t:i+".html"+e}function f(t,n){const e=decodeURIComponent(t.hash),i=function(t){const n=t.match(r);if(n)return n[0]}(n);if(i&&e!==i)return!1;return s(t.path)===s(n)}function h(t,n,e){if(u(n))return{type:"external",path:n};e&&(n=function(t,n,e){const r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"===r)return n+t;const i=n.split("/");e&&i[i.length-1]||i.pop();const o=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(n,e,r,i=1){if("string"==typeof n)return h(e,n,r);if(Array.isArray(n))return Object.assign(h(e,n[0],r),{title:n[1]});{const o=n.children||[];return 0===o.length&&n.path?Object.assign(h(e,n.path,r),{title:n.title}):{type:"group",path:n.path,title:n.title,sidebarDepth:n.sidebarDepth,initialOpenGroupIndex:n.initialOpenGroupIndex,children:o.map(n=>t(n,e,r,i+1)),collapsable:!1!==n.collapsable}}}(t,i,e)):[]}return[]}function g(t){const n=v(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:n.map(n=>({type:"auto",title:n.title,basePath:t.path,path:t.path+"#"+n.slug,children:n.children||[]}))}]}function v(t){let n;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?n=t:n&&(n.children||(n.children=[])).push(t)}),t.filter(t=>2===t.level)}function b(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},249:function(t,n){t.exports=function(t){return null==t}},252:function(t,n,e){},263:function(t,n,e){var r=e(12),i=e(4),o=e(11);t.exports=function(t){return"string"==typeof t||!i(t)&&o(t)&&"[object String]"==r(t)}},264:function(t,n,e){"use strict";e(252)},271:function(t,n,e){"use strict";e.r(n);e(90);var r=e(242),i=e(263),o=e.n(i),a=e(249),s=e.n(a),u={name:"PageNav",props:["sidebarItems"],computed:{prev(){return p(c.PREV,this)},next(){return p(c.NEXT,this)}}};const c={NEXT:{resolveLink:function(t,n){return l(t,n,1)},getThemeLinkConfig:({nextLinks:t})=>t,getPageLinkConfig:({frontmatter:t})=>t.next},PREV:{resolveLink:function(t,n){return l(t,n,-1)},getThemeLinkConfig:({prevLinks:t})=>t,getPageLinkConfig:({frontmatter:t})=>t.prev}};function p(t,{$themeConfig:n,$page:e,$route:i,$site:a,sidebarItems:u}){const{resolveLink:c,getThemeLinkConfig:p,getPageLinkConfig:l}=t,f=p(n),h=l(e),d=s()(h)?f:h;return!1===d?void 0:o()(d)?Object(r.k)(a.pages,d,i.path):c(e,u)}function l(t,n,e){const r=[];!function t(n,e){for(let r=0,i=n.length;rfunction t(e,n,i,r=1){if("string"==typeof e)return d(n,e,i);if(Array.isArray(e))return Object.assign(d(n,e[0],i),{title:e[1]});{const a=e.children||[];return 0===a.length&&e.path?Object.assign(d(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:a.map(e=>t(e,n,i,r+1)),collapsable:!1!==e.collapsable}}}(t,r,n)):[]}return[]}function m(t){const e=g(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function g(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function b(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},244:function(t,e,n){"use strict";n.r(e);var i=n(242),r={name:"NavLink",props:{item:{required:!0}},computed:{link(){return Object(i.b)(this.item.link)},exact(){return this.$site.locales?Object.keys(this.$site.locales).some(t=>t===this.link):"/"===this.link},isNonHttpURI(){return Object(i.g)(this.link)||Object(i.h)(this.link)},isBlankTarget(){return"_blank"===this.target},isInternal(){return!Object(i.f)(this.link)&&!this.isBlankTarget},target(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(i.f)(this.link)?"_blank":""},rel(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction(){this.$emit("focusout")}}},a=n(10),s=Object(a.a)(r,(function(){var t=this,e=t._self._c;return t.isInternal?e("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(e){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):e("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?e("OutboundLink"):t._e()],1)}),[],!1,null,null,null);e.default=s.exports},259:function(t,e,n){},272:function(t,e,n){"use strict";n(259)},285:function(t,e,n){"use strict";n.r(e);var i={name:"Home",components:{NavLink:n(244).default},computed:{data(){return this.$page.frontmatter},actionLink(){return{link:this.data.actionLink,text:this.data.actionText}}}},r=(n(272),n(10)),a=Object(r.a)(i,(function(){var t=this,e=t._self._c;return e("main",{staticClass:"home",attrs:{"aria-labelledby":null!==t.data.heroText?"main-title":null}},[e("header",{staticClass:"hero"},[t.data.heroImage?e("img",{attrs:{src:t.$withBase(t.data.heroImage),alt:t.data.heroAlt||"hero"}}):t._e(),t._v(" "),null!==t.data.heroText?e("h1",{attrs:{id:"main-title"}},[t._v("\n "+t._s(t.data.heroText||t.$title||"Hello")+"\n ")]):t._e(),t._v(" "),null!==t.data.tagline?e("p",{staticClass:"description"},[t._v("\n "+t._s(t.data.tagline||t.$description||"Welcome to your VuePress site")+"\n ")]):t._e(),t._v(" "),t.data.actionText&&t.data.actionLink?e("p",{staticClass:"action"},[e("NavLink",{staticClass:"action-button",attrs:{item:t.actionLink}})],1):t._e()]),t._v(" "),t.data.features&&t.data.features.length?e("div",{staticClass:"features"},t._l(t.data.features,(function(n,i){return e("div",{key:i,staticClass:"feature"},[e("h2",[t._v(t._s(n.title))]),t._v(" "),e("p",[t._v(t._s(n.details))])])})),0):t._e(),t._v(" "),e("Content",{staticClass:"theme-default-content custom"}),t._v(" "),t.data.footer?e("div",{staticClass:"footer"},[t._v("\n "+t._s(t.data.footer)+"\n ")]):e("Content",{staticClass:"footer",attrs:{"slot-key":"footer"}})],1)}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/29.13b12301.js b/assets/js/29.13b12301.js new file mode 100644 index 0000000..7c78390 --- /dev/null +++ b/assets/js/29.13b12301.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[29],{242:function(t,e,n){"use strict";n.d(e,"d",(function(){return i})),n.d(e,"a",(function(){return a})),n.d(e,"i",(function(){return s})),n.d(e,"f",(function(){return c})),n.d(e,"g",(function(){return u})),n.d(e,"h",(function(){return l})),n.d(e,"b",(function(){return d})),n.d(e,"e",(function(){return p})),n.d(e,"k",(function(){return f})),n.d(e,"l",(function(){return h})),n.d(e,"c",(function(){return m})),n.d(e,"j",(function(){return b}));n(90);const i=/#.*$/,r=/\.(md|html)$/,a=/\/$/,s=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(i,"").replace(r,"")}function c(t){return s.test(t)}function u(t){return/^mailto:/.test(t)}function l(t){return/^tel:/.test(t)}function d(t){if(c(t))return t;const e=t.match(i),n=e?e[0]:"",r=o(t);return a.test(r)?t:r+".html"+n}function p(t,e){const n=decodeURIComponent(t.hash),r=function(t){const e=t.match(i);if(e)return e[0]}(e);if(r&&n!==r)return!1;return o(t.path)===o(e)}function f(t,e,n){if(c(e))return{type:"external",path:e};n&&(e=function(t,e,n){const i=t.charAt(0);if("/"===i)return t;if("?"===i||"#"===i)return e+t;const r=e.split("/");n&&r[r.length-1]||r.pop();const a=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(e,n,i,r=1){if("string"==typeof e)return f(n,e,i);if(Array.isArray(e))return Object.assign(f(n,e[0],i),{title:e[1]});{const a=e.children||[];return 0===a.length&&e.path?Object.assign(f(n,e.path,i),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:a.map(e=>t(e,n,i,r+1)),collapsable:!1!==e.collapsable}}}(t,r,n)):[]}return[]}function g(t){const e=m(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function m(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function b(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},249:function(t,e){t.exports=function(t){return null==t}},251:function(t,e,n){},262:function(t,e,n){"use strict";n(251)},270:function(t,e,n){"use strict";n.r(e);var i=n(249),r=n.n(i),a=n(242),s={name:"PageEdit",computed:{lastUpdated(){return this.$page.lastUpdated},lastUpdatedText(){return"string"==typeof this.$themeLocaleConfig.lastUpdated?this.$themeLocaleConfig.lastUpdated:"string"==typeof this.$site.themeConfig.lastUpdated?this.$site.themeConfig.lastUpdated:"Last Updated"},editLink(){const t=r()(this.$page.frontmatter.editLink)?this.$site.themeConfig.editLinks:this.$page.frontmatter.editLink,{repo:e,docsDir:n="",docsBranch:i="master",docsRepo:a=e}=this.$site.themeConfig;return t&&a&&this.$page.relativePath?this.createEditLink(e,a,n,i,this.$page.relativePath):null},editLinkText(){return this.$themeLocaleConfig.editLinkText||this.$site.themeConfig.editLinkText||"Edit this page"}},methods:{createEditLink(t,e,n,i,r){if(/bitbucket.org/.test(e)){return e.replace(a.a,"")+"/src"+`/${i}/`+(n?n.replace(a.a,"")+"/":"")+r+`?mode=edit&spa=0&at=${i}&fileviewer=file-view-default`}if(/gitlab.com/.test(e)){return e.replace(a.a,"")+"/-/edit"+`/${i}/`+(n?n.replace(a.a,"")+"/":"")+r}return(a.i.test(e)?e:"https://github.com/"+e).replace(a.a,"")+"/edit"+`/${i}/`+(n?n.replace(a.a,"")+"/":"")+r}}},o=(n(262),n(10)),c=Object(o.a)(s,(function(){var t=this,e=t._self._c;return e("footer",{staticClass:"page-edit"},[t.editLink?e("div",{staticClass:"edit-link"},[e("a",{attrs:{href:t.editLink,target:"_blank",rel:"noopener noreferrer"}},[t._v(t._s(t.editLinkText))]),t._v(" "),e("OutboundLink")],1):t._e(),t._v(" "),t.lastUpdated?e("div",{staticClass:"last-updated"},[e("span",{staticClass:"prefix"},[t._v(t._s(t.lastUpdatedText)+":")]),t._v(" "),e("span",{staticClass:"time"},[t._v(t._s(t.lastUpdated))])]):t._e()])}),[],!1,null,null,null);e.default=c.exports}}]); \ No newline at end of file diff --git a/assets/js/3.e8951f3a.js b/assets/js/3.e8951f3a.js new file mode 100644 index 0000000..4eea26c --- /dev/null +++ b/assets/js/3.e8951f3a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[3,34,35],{242:function(t,e,n){"use strict";n.d(e,"d",(function(){return r})),n.d(e,"a",(function(){return s})),n.d(e,"i",(function(){return a})),n.d(e,"f",(function(){return l})),n.d(e,"g",(function(){return u})),n.d(e,"h",(function(){return c})),n.d(e,"b",(function(){return p})),n.d(e,"e",(function(){return d})),n.d(e,"k",(function(){return h})),n.d(e,"l",(function(){return f})),n.d(e,"c",(function(){return g})),n.d(e,"j",(function(){return m}));n(90);const r=/#.*$/,i=/\.(md|html)$/,s=/\/$/,a=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(r,"").replace(i,"")}function l(t){return a.test(t)}function u(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function p(t){if(l(t))return t;const e=t.match(r),n=e?e[0]:"",i=o(t);return s.test(i)?t:i+".html"+n}function d(t,e){const n=decodeURIComponent(t.hash),i=function(t){const e=t.match(r);if(e)return e[0]}(e);if(i&&n!==i)return!1;return o(t.path)===o(e)}function h(t,e,n){if(l(e))return{type:"external",path:e};n&&(e=function(t,e,n){const r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"===r)return e+t;const i=e.split("/");n&&i[i.length-1]||i.pop();const s=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(e,n,r,i=1){if("string"==typeof e)return h(n,e,r);if(Array.isArray(e))return Object.assign(h(n,e[0],r),{title:e[1]});{const s=e.children||[];return 0===s.length&&e.path?Object.assign(h(n,e.path,r),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:s.map(e=>t(e,n,r,i+1)),collapsable:!1!==e.collapsable}}}(t,i,n)):[]}return[]}function b(t){const e=g(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function g(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function m(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},243:function(t,e,n){},245:function(t,e,n){"use strict";n.r(e);var r={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},i=(n(246),n(10)),s=Object(i.a)(r,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.default=s.exports},246:function(t,e,n){"use strict";n(243)},248:function(t,e,n){},253:function(t,e,n){},255:function(t,e,n){"use strict";n(248)},256:function(t,e,n){"use strict";n.r(e);var r=n(269),i=n(258),s=n(242);function a(t,e){if("group"===e.type){const n=e.path&&Object(s.e)(t,e.path),r=e.children.some(e=>"group"===e.type?a(t,e):"page"===e.type&&Object(s.e)(t,e.path));return n||r}return!1}var o={name:"SidebarLinks",components:{SidebarGroup:r.default,SidebarLink:i.default},props:["items","depth","sidebarDepth","initialOpenGroupIndex"],data(){return{openGroupIndex:this.initialOpenGroupIndex||0}},watch:{$route(){this.refreshIndex()}},created(){this.refreshIndex()},methods:{refreshIndex(){const t=function(t,e){for(let n=0;n-1&&(this.openGroupIndex=t)},toggleGroup(t){this.openGroupIndex=t===this.openGroupIndex?-1:t},isActive(t){return Object(s.e)(this.$route,t.regularPath)}}},l=n(10),u=Object(l.a)(o,(function(){var t=this,e=t._self._c;return t.items.length?e("ul",{staticClass:"sidebar-links"},t._l(t.items,(function(n,r){return e("li",{key:r},["group"===n.type?e("SidebarGroup",{attrs:{item:n,open:r===t.openGroupIndex,collapsable:n.collapsable||n.collapsible,depth:t.depth},on:{toggle:function(e){return t.toggleGroup(r)}}}):e("SidebarLink",{attrs:{"sidebar-depth":t.sidebarDepth,item:n}})],1)})),0):t._e()}),[],!1,null,null,null);e.default=u.exports},258:function(t,e,n){"use strict";n.r(e);var r=n(242);function i(t,e,n,r,i){const s={props:{to:e,activeClass:"",exactActiveClass:""},class:{active:r,"sidebar-link":!0}};return i>2&&(s.style={"padding-left":i+"rem"}),t("RouterLink",s,n)}function s(t,e,n,a,o,l=1){return!e||l>o?null:t("ul",{class:"sidebar-sub-headers"},e.map(e=>{const u=Object(r.e)(a,n+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[i(t,n+"#"+e.slug,e.title,u,e.level-1),s(t,e.children,n,a,o,l+1)])}))}var a={functional:!0,props:["item","sidebarDepth"],render(t,{parent:{$page:e,$site:n,$route:a,$themeConfig:o,$themeLocaleConfig:l},props:{item:u,sidebarDepth:c}}){const p=Object(r.e)(a,u.path),d="auto"===u.type?p||u.children.some(t=>Object(r.e)(a,u.basePath+"#"+t.slug)):p,h="external"===u.type?function(t,e,n){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[n,t("OutboundLink")])}(t,u.path,u.title||u.path):i(t,u.path,u.title||u.path,d),f=[e.frontmatter.sidebarDepth,c,l.sidebarDepth,o.sidebarDepth,1].find(t=>void 0!==t),b=l.displayAllHeaders||o.displayAllHeaders;if("auto"===u.type)return[h,s(t,u.children,u.basePath,a,f)];if((d||b)&&u.headers&&!r.d.test(u.path)){return[h,s(t,Object(r.c)(u.headers),u.path,a,f)]}return h}},o=(n(255),n(10)),l=Object(o.a)(a,void 0,void 0,!1,null,null,null);e.default=l.exports},266:function(t,e,n){"use strict";n(253)},269:function(t,e,n){"use strict";n.r(e);var r=n(242),i={name:"SidebarGroup",components:{DropdownTransition:n(245).default},props:["item","open","collapsable","depth"],beforeCreate(){this.$options.components.SidebarLinks=n(256).default},methods:{isActive:r.e}},s=(n(266),n(10)),a=Object(s.a)(i,(function(){var t=this,e=t._self._c;return e("section",{staticClass:"sidebar-group",class:[{collapsable:t.collapsable,"is-sub-group":0!==t.depth},"depth-"+t.depth]},[t.item.path?e("RouterLink",{staticClass:"sidebar-heading clickable",class:{open:t.open,active:t.isActive(t.$route,t.item.path)},attrs:{to:t.item.path},nativeOn:{click:function(e){return t.$emit("toggle")}}},[e("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?e("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]):e("p",{staticClass:"sidebar-heading",class:{open:t.open},on:{click:function(e){return t.$emit("toggle")}}},[e("span",[t._v(t._s(t.item.title))]),t._v(" "),t.collapsable?e("span",{staticClass:"arrow",class:t.open?"down":"right"}):t._e()]),t._v(" "),e("DropdownTransition",[t.open||!t.collapsable?e("SidebarLinks",{staticClass:"sidebar-group-items",attrs:{items:t.item.children,"sidebar-depth":t.item.sidebarDepth,"initial-open-group-index":t.item.initialOpenGroupIndex,depth:t.depth+1}}):t._e()],1)],1)}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/30.75a380a5.js b/assets/js/30.75a380a5.js new file mode 100644 index 0000000..91b2fe8 --- /dev/null +++ b/assets/js/30.75a380a5.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[30],{438:function(e,t,a){e.exports=a.p+"assets/img/stage-1.850306fa.png"},439:function(e,t,a){e.exports=a.p+"assets/img/stage-2.3f9d9bab.png"},440:function(e,t,a){e.exports=a.p+"assets/img/stage-3.0b818290.png"},441:function(e,t,a){e.exports=a.p+"assets/img/stage-4.541fb6a2.png"},519:function(e,t,a){"use strict";a.r(t);var o=a(10),i=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("p",[e._v("The stage maintenance consist mainly on the replacement of the ball, and the optical flow sensor calibration.")]),e._v(" "),t("h2",{attrs:{id:"running-ball-replacement"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#running-ball-replacement"}},[e._v("#")]),e._v(" Running ball replacement")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Glue two "),t("a",{attrs:{href:"https://www.dickblick.com/items/smooth-foam-crafters-foam-half-ball-8-dia/",target:"_blank",rel:"noopener noreferrer"}},[e._v('8" diameter half balls'),t("OutboundLink")],1),e._v(" using "),t("a",{attrs:{href:"https://www.amazon.com/FloraCraft-Non-Toxic-Foam-Glue/dp/B000FFUCAI?th=1",target:"_blank",rel:"noopener noreferrer"}},[e._v("lightweight styrophoam glue"),t("OutboundLink")],1),e._v(". Make sure to use a fair ammount of glue, press each half against each other (make sure to squeeze them together for a few seconds to make sure the ball halves remain stuck to each other) and use your finger to flat the excess of glue laong the edges. Let them sit for a few hours or overnight.")])]),e._v(" "),t("li",[t("p",[e._v("Once set, use an "),t("a",{attrs:{href:"https://www.mcmaster.com/7451T32/",target:"_blank",rel:"noopener noreferrer"}},[e._v("abrasive brush"),t("OutboundLink")],1),e._v(" or a "),t("a",{attrs:{href:"https://www.mcmaster.com/4023A79/",target:"_blank",rel:"noopener noreferrer"}},[e._v("sanding sponge"),t("OutboundLink")],1),e._v(" to slighlty rough the surface of the ball, this will make help improving the quality of motion detection by the optical flow sensor.")])]),e._v(" "),t("li",[t("p",[e._v("Once the Styrofoam ball is smoothed, use a red sharpie to label the ball, then use a black industrial sharpie to mark the ball with a cross-hatch design - try to ensure that there are no large white gaps in-between the cross-hatch design.")])])]),e._v(" "),t("h2",{attrs:{id:"optical-flow-sensor-calibration"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#optical-flow-sensor-calibration"}},[e._v("#")]),e._v(" Optical flow sensor calibration")]),e._v(" "),t("h3",{attrs:{id:"image-quality-and-lens-focus"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#image-quality-and-lens-focus"}},[e._v("#")]),e._v(" Image quality and lens focus")]),e._v(" "),t("p",[e._v("The image quality from the optical sensor should be maximized in order for it to obtain reliable measurements, which can be achieved by:")]),e._v(" "),t("ul",[t("li",[t("p",[e._v("Ensuring sufficient infrared (IR) illumination (but increasing it past a certain threshold does not help).")])]),e._v(" "),t("li",[t("p",[e._v("Adjusting the focal plane of the M12 lens to be at the surface to be measured.")])]),e._v(" "),t("li",[t("p",[e._v("Using a surface with more texture (of the appropriate size given the limited number of sensor pixels).")])])]),e._v(" "),t("p",[e._v("The ADNS-3080 chip reports a SQUAL value that can be read out using software as explained below. This value needs to be at least 30 if the velocities to be measured are around 100cm/s-150cm/s. For lower values of SQUAL, the sensor tends to under-measure the actual displacement, with the size of the effect increasing with higher surface velocities. The following are examples of images of a Styrofoam ball at various SQUAL values ranging from unusable to ideal (for velocities not far exceeding 100cm/s).")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(438)}})]),e._v(" "),t("p",[e._v("Follow the procedure below to adjust the focus of the optical flow sensor lens.")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Load Arduino Code\\ADNS_image_v1\\ADNS_image_v1.ino in the Arduino IDE.")])]),e._v(" "),t("li",[t("p",[e._v("Edit the reset_pin to 6 and select_pin to 10 values (lines 20-24).")])]),e._v(" "),t("li",[t("p",[e._v("Upload the Arduino code to the board. Note that you will have to reprogram the board after this to use it as a displacement readout.")])]),e._v(" "),t("li",[t("p",[e._v("Print the left side of the following image (an optical spoke target) using a laser printer. The spoke target consists of lines of vanishing size towards the center, therefore allowing you to probe the single pixel limit of the optical sensor as shown in the calibrated image (from the sensor) in the right:")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(439)}})]),e._v(" "),t("ol",{attrs:{start:"5"}},[t("li",[t("p",[e._v("Find some way of placing the spoke target in front of the optical sensor at the same location and orientation as the actual surface to be measured. For example for the mouse virtual reality rig it can be taped onto a Styrofoam ball and the ball can be suspended at the height it would usually be at during experiments.")])]),e._v(" "),t("li",[t("p",[e._v("Run the Matlab Code\\Calibration\\display_image.m function. It is programmed to continuously display the sensor image for a predetermined amount of time, and can be terminated by pressing .")])]),e._v(" "),t("li",[t("p",[e._v("Adjust the IR LED so that it points towards the center of the surface to be imaged. You should see the illuminated region shift around in the display_image figure.")])]),e._v(" "),t("li",[t("p",[e._v("The display_image figure is normalized so that the brightest regions appear white and the darkest regions appear black, i.e. absolute luminosity information is not available. You can change this behavior by editing the code to replace imagesc(im) (line 66) with image(im) and setting the color scale manually: set(gca, 'CLim', […])\nOblique illumination can help increase feature contrast on uneven surfaces, but in general just illuminating the largest amount of surface available is sufficient.")])]),e._v(" "),t("li",[t("p",[e._v("Adjust the focus of the optical sensor lens by rotating it. You should see the spoke target lines get sharper and the SQUAL value increase if you’re going in the right direction. You should be able to find a distance at which the SQUAL value is maximal (there is a decent amount of leeway).")])]),e._v(" "),t("li",[t("p",[e._v("Replace the spoke target with the actual surface to be measured, and verify that the SQUAL value is still high enough (>> 30). Values of 50-80 have been achieved with Styrofoam balls, the higher end if they have been “weathered” by running mice.")])]),e._v(" "),t("li",[t("p",[e._v("If the SQUAL value is 30-ish or worse, consider using a more textured surface. For example, scour the Styrofoam ball with steel wool.")])])]),e._v(" "),t("h3",{attrs:{id:"lenght-scale-calibration"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#lenght-scale-calibration"}},[e._v("#")]),e._v(" Lenght scale calibration")]),e._v(" "),t("p",[e._v("Follow the procedure below to calibrate the lenght scale of the optical flow sensor.")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Load Arduino Code\\ADNS_aout_wUSB_1sensor\\ADNS_aout_wUSB_1sensor.ino in the Arduino IDE.")])]),e._v(" "),t("li",[t("p",[e._v("Upload the Arduino code to the board.")])]),e._v(" "),t("li",[t("p",[e._v("Suspend a Styrofoam ball on an axle, or a cylindrical Styrofoam wheel, at the position it would be in relative to the optical sensor in a real experiment. Mark a reference position on the ball, e.g. with a piece of black tape as shown in the mouse VR calibration photo below.")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(440)}})]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[t("p",[e._v("Ensure that Matlab Code\\Calibration\\calibrateBall.m is either in the current folder in the Matlab console, or otherwise in the Matlab path, before continuing the rest of this procedure.")])]),e._v(" "),t("li",[t("p",[e._v("While holding the ball in place, run the calibrateBall script.")])]),e._v(" "),t("li",[t("p",[e._v("Spin the ball 10 times (this can be done quickly), counting the number of times that the black tape returns to approximately its original location.")])]),e._v(" "),t("li",[t("p",[e._v("If necessary, a small correction can be made to rotate the ball further until the tape is exactly at its original position. This should cancel out errors incurred in the previous step.")])]),e._v(" "),t("li",[t("p",[e._v("Stop calibrateBall by pressing Ctrl+C.")])]),e._v(" "),t("li",[t("p",[e._v("Input fclose(instrfindall) at the Matlab command line to close Arduino communications.")])]),e._v(" "),t("li",[t("p",[e._v("Input [dx,dy] at the Matlab command line to view the accumulated displacements. If the optical sensor has been correctly aligned w.r.t. the axis of rotation of the ball, one of these displacements should be large (> thousands) and the other one small (< tens).")])]),e._v(" "),t("li",[t("p",[e._v("In the following the measured displacement along the axis of interest will be referred to as nDots, and the number of revolutions used as nRev.")])]),e._v(" "),t("li",[t("p",[e._v("Repeat this measurement until satisfied (with more rotations if necessary), then enter the obtained constants into RigParameters.m.")])])]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("ballCircumference")]),e._v(": Actual displacement (e.g. in cm) of the calibration surface per revolution. For an 8-inch diameter Styrofoam ball, this is its circumference, 63.8cm.")]),e._v(" "),t("li",[t("strong",[e._v("sensorDotsPerRev")]),e._v(": This should be set directly to "),t("em",[e._v("nDots/nRev")]),e._v(" in the case of a single sensor. In the case of two sensors, use the code "),t("code",[e._v("sensorDotsPerRev = RigParameters.sensorCalibration()")]),e._v(" and set the latter as described below.")]),e._v(" "),t("li",[t("strong",[e._v("sensorCalibration")]),e._v(": This is only used for two sensors, which may have differing constants. In this case use the appropriate MovementSensor label for the sensor of interest to record dotsPerRev, e.g.: "),t("code",[e._v("dotsPerRev(MovementSensor.FrontVelocity) = nDots/nRev;")])])]),e._v(" "),t("h2",{attrs:{id:"troubleshooting"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#troubleshooting"}},[e._v("#")]),e._v(" Troubleshooting")]),e._v(" "),t("p",[e._v("Troubleshooting should be done from cleaning the 3D cup and window first, making sure the ball is in proper conditions, and then the optical flow sensor replacement if necessary, then the arduino. If the arduino is the problem, refer to the troubleshooting guide in the control portion of the documentation.")]),e._v(" "),t("h3",{attrs:{id:"arduino-not-recognized"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#arduino-not-recognized"}},[e._v("#")]),e._v(" Arduino not recognized")]),e._v(" "),t("p",[e._v("If the arduino is not recognized by the rig tester arduino detection button follow the next steps:")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("First check if the arduino is being detected by the CPU by opening the device manager windows (typing device manager in the search bar) and clicking on the Ports (COM&LPT) label to display the list of devices connected.")]),e._v(" "),t("ul",[t("li",[e._v("If the Arduino is listed there, then the COM port might have changed. Make sure the COM port listed in the device manager matches the "),t("code",[e._v("arduinoPort")]),e._v(" variable in the rig parameters file. Restart Matlab and try again.")])])]),e._v(" "),t("li",[t("p",[e._v("If the Arduino is not listed on the device manager window it could be either a faulty cable or a broken Arduino. Start by troubleshooting the Arduino (cables might be harder to check since many times they have intricate paths behind the rig).")]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("You can perform a quick check before removing the arduino from the box to discard that the cable is faulty. Unplug the arduino USB cable from the black box on the DIN rail and connect a new arduino, if this one is recognized in the device manager window, then proceed to the following steps, otherwise go ahead and change the cable.")])]),e._v(" "),t("ul",[t("li",[t("p",[e._v("Disconnect both the cable and the connector of the black box holding the arduino and take it out of the DIN rail (by slightly pushing it downwards and pulling the bottom part towards you).")])]),e._v(" "),t("li",[t("p",[e._v("Open the box by unscrewing the 4 screws holding the cover and the 2 screws holding the arduino to the 3D printed box.")])]),e._v(" "),t("li",[t("p",[e._v("Remove the arduino and replace it with a new one. Screw it to the box and screw the cover. Place the box with the new arduino into the DIN rail and connect first the sensor cable and then the US cable.")])]),e._v(" "),t("li",[t("p",[e._v("Program the arduino following this "),t("RouterLink",{attrs:{to:"/building/control.html#programming-the-arduino"}},[e._v("instructions")]),e._v(".")],1)])])]),e._v(" "),t("li",[t("p",[e._v("If the cable is malfunctioning, then replace the cable. We recommend to use a "),t("a",{attrs:{href:"https://www.bhphotovideo.com/c/product/1387544-REG/tether_tools_cuc2515_blk_tetherpro_usb_c_to_2_0.html?sts=pi&pim=Y",target:"_blank",rel:"noopener noreferrer"}},[e._v("USB Type-C male to micro-USB Type-B male cable"),t("OutboundLink")],1),e._v(". Or any other cable matching your setup, but make sure it is a single tether cable or USB 3.0 cable, and avoid using either multiple cables or HUBs (or make sure everything is high speed rated).")])])]),e._v(" "),t("h3",{attrs:{id:"timed-out-while-waiting-for-a-reply"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#timed-out-while-waiting-for-a-reply"}},[e._v("#")]),e._v(" Timed out while waiting for a reply.")]),e._v(" "),t("figure",[t("img",{attrs:{src:a(441)}})]),e._v(" "),t("p",[e._v("This error could be caused by a corrupted firmware in the Arduino. To solve follow the steps on "),t("RouterLink",{attrs:{to:"/building/control.html#programming-the-arduino"}},[e._v("instructions")]),e._v(" to program the arduino again.")],1)])}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/31.e245e83a.js b/assets/js/31.e245e83a.js new file mode 100644 index 0000000..dd073fb --- /dev/null +++ b/assets/js/31.e245e83a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[31],{470:function(e,t,a){e.exports=a.p+"assets/img/plot_frequency_sessions1.6ea83bcc.png"},471:function(e,t,a){e.exports=a.p+"assets/img/plot_frequency_sessions2.302da2bb.png"},472:function(e,t,a){e.exports=a.p+"assets/img/velocity_subject.0e563aaf.png"},473:function(e,t,a){e.exports=a.p+"assets/img/path_table.8564e498.png"},526:function(e,t,a){"use strict";a.r(t);var s=a(10),r=Object(s.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("h2",{attrs:{id:"matlab"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#matlab"}},[e._v("#")]),e._v(" MATLAB")]),e._v(" "),t("h3",{attrs:{id:"prerequesites"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#prerequesites"}},[e._v("#")]),e._v(" Prerequesites")]),e._v(" "),t("ol",[t("li",[e._v("U19-pipeline-matlab repo added to MATLAB path")]),e._v(" "),t("li",[e._v("Mounted network cup drives (braininit, u19_dj)")])]),e._v(" "),t("ul",[t("li",[e._v("Check (see "),t("a",{attrs:{href:"https://braincogs.github.io/software/db_access.html"}},[e._v("Database access section")]),e._v(" ) for more info.")])]),e._v(" "),t("h3",{attrs:{id:"recommended-tutorial"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#recommended-tutorial"}},[e._v("#")]),e._v(" Recommended tutorial")]),e._v(" "),t("ul",[t("li",[e._v("Go through "),t("code",[e._v("U19-pipeline-matlab/tutorials/202103/session01_queries_fetches.mlx")]),e._v(" to learn basic tips on datajoint.")])]),e._v(" "),t("h3",{attrs:{id:"useful-scripts-and-functions-for-reseacher-general-use"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#useful-scripts-and-functions-for-reseacher-general-use"}},[e._v("#")]),e._v(" "),t("strong",[e._v("Useful scripts and functions")]),e._v(" for reseacher general use:")]),e._v(" "),t("h3",{attrs:{id:"read-behavior-file"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#read-behavior-file"}},[e._v("#")]),e._v(" Read behavior file:")]),e._v(" "),t("ol",[t("li",[e._v("Execute: (change key for desired session)")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');\n[status,data] = lab.utils.read_behavior_file(key)\n")])])]),t("ol",{attrs:{start:"2"}},[t("li",[e._v("If successful "),t("code",[e._v("status = 1")]),e._v(" and "),t("code",[e._v("data = log behavioral file")])])]),e._v(" "),t("h3",{attrs:{id:"get-behavior-file-location-local-for-spock-scotty"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#get-behavior-file-location-local-for-spock-scotty"}},[e._v("#")]),e._v(" Get behavior file location (local & for spock/scotty)")]),e._v(" "),t("ol",[t("li",[e._v("If you only need to know the path of behavior file use:")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');\nbaseDir = fetch1(acquisition.SessionStarted & key, 'new_remote_path_behavior_file');\n[bucket_path, local_path] = lab.utils.get_path_from_official_dir(baseDir)\n")])])]),t("h3",{attrs:{id:"get-full-trial-data-with-spatialtimeblobs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#get-full-trial-data-with-spatialtimeblobs"}},[e._v("#")]),e._v(" get_full_trial_data with SpatialTimeBlobs")]),e._v(" "),t("ul",[t("li",[e._v("Get trial data (position, velocity, etc) efficiently with DB.")]),e._v(" "),t("li",[e._v("New method to retrieve all trial data for multiple sessions faster.")])]),e._v(" "),t("ol",[t("li",[e._v("Execute:")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');\nget_full_trial_data(key)\n")])])]),t("ul",[t("li",[e._v("Get trial data from joined tables as well (e.g. "),t("strong",[e._v("TowersBlock")]),e._v("):")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');\nget_full_trial_data(key, behavior.TowersBlockTrial * behavior.TowersBlock)\n")])])]),t("ul",[t("li",[e._v("Get data from subtasks as well (e.g. "),t("strong",[e._v("Twolickspouts")]),e._v(" subtask)")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'efonseca_ef114_act114', 'session_date', '2023-01-11');\nall_tables = behavior.TowersBlockTrial * behavior.TowersBlock * behavior_subtask.TwolickspoutsBlockTrial * behavior_subtask.TwolickspoutsBlock\nget_full_trial_data(key, all_tables)\n")])])]),t("h3",{attrs:{id:"get-stats-from-session"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#get-stats-from-session"}},[e._v("#")]),e._v(" get stats from session")]),e._v(" "),t("ul",[t("li",[e._v("To get behavior file like stats (on the trial level) for a single or multiple sessions use this function")]),e._v(" "),t("li",[e._v("Stats include, but not limited to: ("),t("code",[e._v("correct_left, correct_right, cum_correct_trials, performance, goodFraction, numPerMin, numRewardsPerMin, bias")]),e._v(")")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');\nstat_struct = get_stats_from_session(key, \"all\")\n")])])]),t("h3",{attrs:{id:"get-behaviorfile-as-db"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#get-behaviorfile-as-db"}},[e._v("#")]),e._v(" get behaviorfile as db")]),e._v(" "),t("ul",[t("li",[e._v("Function to unnest behavior file structure to get a plain trial table (with block data merged).")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');\ndata_struct = get_behaviorfile_as_db(key)\n")])])]),t("h3",{attrs:{id:"get-time-from-iteration-variable"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#get-time-from-iteration-variable"}},[e._v("#")]),e._v(" get time from iteration variable")]),e._v(" "),t("ul",[t("li",[e._v('Example of how to "translate" a variable from iteration# to trial_time')]),e._v(" "),t("li",[e._v("In this case, 1st row of variable licks (iteration#) is translated to lick_times and then added to original trial structure")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'efonseca_ef114_act114', 'session_date', '2023-01-11');\ntrial_data = get_full_trial_data(key, behavior.TowersBlockTrial * behavior_subtask.TwolickspoutsBlockTrial);\nlicks_time_struct = struct;\nfor i=1:length(trial_data)\n licks_time_struct(i,1).lick_times = get_time_from_iter(trial_data(i).trial_time, trial_data(i).licks(1,:));\nend\ntrial_data = cat_struct(trial_data, licks_time_struct);\n")])])]),t("h3",{attrs:{id:"plot-framerate-frequency-sessions"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#plot-framerate-frequency-sessions"}},[e._v("#")]),e._v(" plot framerate frequency sessions")]),e._v(" "),t("ul",[t("li",[e._v("Plot trial by trial framerate of multiple sessions for comparison")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('key = \'subject_fullname like "mioffe%" and session_date > "2022-01-01" and session_date < "2022-01-30"\';\nanalyze_iteration_time(key)\n')])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(470)}}),e._v(" "),t("center",[t("figcaption",[e._v("Framerate trial by trial sessions")])])],1),e._v(" "),t("h3",{attrs:{id:"plot-framerate-frequency-levels-and-rigs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#plot-framerate-frequency-levels-and-rigs"}},[e._v("#")]),e._v(" plot framerate frequency levels and rigs")]),e._v(" "),t("ul",[t("li",[e._v("Plot mean framerate by level and rig for multiple sessions")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('key = \'subject_fullname like "mioffe%" and session_date > "2022-01-01" and session_date < "2022-12-10"\';\nanalyze_iteration_time_level_rig(key)\n')])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(471)}}),e._v(" "),t("center",[t("figcaption",[e._v("Mean framerate by level and rig ")])])],1),e._v(" "),t("h3",{attrs:{id:"plot-velocity-sessions"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#plot-velocity-sessions"}},[e._v("#")]),e._v(" plot velocity sessions")]),e._v(" "),t("ul",[t("li",[e._v("Plot mean - max range velocity by session for multiple behavior sessions")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'emdiamanti_gps7');\nplot_velocity_session(key)\n")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(472)}}),e._v(" "),t("center",[t("figcaption",[e._v("Velocity plot for multiple sessions")])])],1),e._v(" "),t("h3",{attrs:{id:"get-path-table"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#get-path-table"}},[e._v("#")]),e._v(" get path table")]),e._v(" "),t("ol",[t("li",[e._v("Get default paths for network cup drives for different OS and spock/scotty (bucket)")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');\nbaseDir = fetch1(acquisition.SessionStarted & key, 'new_remote_path_behavior_file');\n[bucket_path, local_path] = lab.utils.get_path_from_official_dir(baseDir)\n")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(473)}}),e._v(" "),t("center",[t("figcaption",[e._v("Path table data")])])],1),e._v(" "),t("h3",{attrs:{id:"common-errors-and-troubleshooting"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#common-errors-and-troubleshooting"}},[e._v("#")]),e._v(" Common errors and troubleshooting")]),e._v(" "),t("ol",[t("li",[e._v("When trying to fetch from a table with external storage and corresponding network cup drive is not mounted:")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Error using dj.store_plugins.File (line 89)\nDirectory `/Volumes/u19_dj/external_dj_blobs` not accessible.\n\nError in dj.internal.ExternalTable (line 52)\n self.spec = dj.store_plugins.(storePlugin)(config);\n")])])]),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Error using fread\nInvalid file identifier. Use fopen to generate a valid file identifier.\n\nError in dj.store_plugins.File.download_buffer (line 63)\n result = fread(fileID);\n")])])]),t("ul",[t("li",[e._v("Just mount all cup drives and try agian !!")])]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("key reference more than one session when function was supposed to work for single sessions")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("Error using dj.internal.GeneralRelvar/fetch1 (line 250)\nfetch1 can only retrieve a single existing tuple.\n")])])]),t("ul",[t("li",[e._v("Just recreate key to reference a single session.")])]),e._v(" "),t("h2",{attrs:{id:"python"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#python"}},[e._v("#")]),e._v(" PYTHON")]),e._v(" "),t("h3",{attrs:{id:"common-errors-and-troubleshooting-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#common-errors-and-troubleshooting-2"}},[e._v("#")]),e._v(" Common errors and troubleshooting")])])}),[],!1,null,null,null);t.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/32.9fca9676.js b/assets/js/32.9fca9676.js new file mode 100644 index 0000000..df77044 --- /dev/null +++ b/assets/js/32.9fca9676.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[32],{474:function(e,t,a){e.exports=a.p+"assets/img/Thermal_schema_files.0c7dea0a.png"},475:function(e,t,a){e.exports=a.p+"assets/img/Thermal_pipeline_ERD.fe0616c1.png"},476:function(e,t,a){e.exports=a.p+"assets/img/Optogenetics_pipeline.79e7de67.png"},477:function(e,t,a){e.exports=a.p+"assets/img/manipulation_trainingGUI.37ef27b0.png"},529:function(e,t,a){"use strict";a.r(t);var i=a(10),n=Object(i.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("ul",[t("li",[e._v("This documentation will guide the researcher through the process of creating a new manipulation pipeline.")]),e._v(" "),t("li",[e._v("At BRAINCoGS optogenetics and thermal manipulation are currently supported.")])]),e._v(" "),t("h2",{attrs:{id:"what-does-the-manipulation-pipeline-include"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#what-does-the-manipulation-pipeline-include"}},[e._v("#")]),e._v(" What does the “manipulation” pipeline include:")]),e._v(" "),t("ul",[t("li",[e._v("Minimum data framework to store in a DB all relevant data from a specific manipulation.")]),e._v(" "),t("li",[e._v("Behavior integration. Training system will include the manipulation as an option to be selected for a behavior session.")]),e._v(" "),t("li",[e._v("Generic software parameters to be used in behavior code.")])]),e._v(" "),t("h2",{attrs:{id:"prerequisites"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites"}},[e._v("#")]),e._v(" Prerequisites")]),e._v(" "),t("ul",[t("li",[e._v("In order to create a new manipulation it’s assumed that:")]),e._v(" "),t("li",[e._v("The researcher is able to connect to "),t("a",{attrs:{href:"https://braincogs.github.io/software/db_access.html#db-access-for-matlab-repository"}},[e._v("datajoint00.pni.princeton.edu DB")])]),e._v(" "),t("li",[e._v("Latest version of u19_pipeline_matlab repository.")])]),e._v(" "),t("h2",{attrs:{id:"initial-set-up"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#initial-set-up"}},[e._v("#")]),e._v(" Initial set-up")]),e._v(" "),t("ul",[t("li",[e._v("Connect to database "),t("code",[e._v("connect_datajoint00")])]),e._v(" "),t("li",[e._v("Create new manipulation schema (substitute manipulation_name with the real name of the manipulation: "),t("code",[e._v("create_new_manipulation_schema('(manipulation_name)', 1)")])]),e._v(" "),t("li",[e._v("This will create a new schema “base” code on the "),t("code",[e._v("U19-pipeline-matlab/schemas")]),e._v(" directory:")]),e._v(" "),t("li",[e._v("(We will use “thermal” manipulation for this example).")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(474)}})]),e._v(" "),t("figure",[t("img",{attrs:{src:a(475)}}),e._v(" "),t("center",[t("figcaption",[e._v("Thermal manipulation file creation & Entity-Relationship diagram on the BRAINCoGS DB")])])],1),e._v(" "),t("h2",{attrs:{id:"table-description"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#table-description"}},[e._v("#")]),e._v(" Table description")]),e._v(" "),t("ul",[t("li",[e._v("Throughout the table description chapter we are going to give an example of an already working manipulation pipeline. (Optogenetics)")])]),e._v(" "),t("h3",{attrs:{id:"manipulation-protocol-table"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#manipulation-protocol-table"}},[e._v("#")]),e._v(' "Manipulation" Protocol table')]),e._v(" "),t("ul",[t("li",[t("p",[e._v("The protocol table stores related information that defines the current manipulation “type” to be used on a behavior session.")])]),e._v(" "),t("li",[t("p",[e._v("Here is the minimum table definition for a manipulation protocol table, it is composed by an id to identify the protocol and a description field.")])]),e._v(" "),t("li",[t("p",[e._v("Generic "),t("strong",[e._v('"Manipulation" Protocol.m')])])])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("%{\n# Defined protocols for training\n_protocol_id : int AUTO_INCREMENT\n---\nprotocol_description : varchar(256) \n%}\n")])])]),t("h3",{attrs:{id:"adding-features-to-manipulation-protocol-table"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#adding-features-to-manipulation-protocol-table"}},[e._v("#")]),e._v(' Adding features to "Manipulation" Protocol table')]),e._v(" "),t("ul",[t("li",[t("p",[e._v("For each manipulation protocol it is possible to add from 0 to n “features” that will define & describe the protocol. We are going to describe all features added for "),t("strong",[e._v("OptogeneticsProtocol")]),e._v(" as an example:")])]),e._v(" "),t("li",[t("p",[e._v("It is important to know from an optogenetic experiment what kind of stimulation was given to the subject: Frequency, wavelength, power etc. All these variables can be stored into a “feature” table and be categorized as StimulationParameters.")])]),e._v(" "),t("li",[t("p",[e._v("What if stimulation was not a square pulse ? We can create a “feature” table to define (if needed) specific waveforms for a given session. (OptogeneticsWaveform)")])]),e._v(" "),t("li",[t("p",[e._v("What if different rooms have different laser systems models ? We can create a “feature” table to store all possible devices to be used in an optogenetic experiment (OptogeneticsDevice).")])]),e._v(" "),t("li",[t("p",[e._v("For each of these features we need to create a new table that encompasses the needed information for that feature. We will call all these extra tables a protocol “feature” table.")])]),e._v(" "),t("li",[t("p",[e._v("For a guide on how to define DJ tables go to: "),t("a",{attrs:{href:"https://docs.datajoint.org/matlab/definition/02-Creating-Tables.html"}},[e._v("this link")]),e._v(".")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(476)}}),e._v(" "),t("center",[t("figcaption",[e._v("Tables that define an optogenetic protocol for a session.")])])],1),e._v(" "),t("ul",[t("li",[e._v("For the current guide we will only show OptogeneticsStimulationParameters definition as an example:")])]),e._v(" "),t("h3",{attrs:{id:"optogeneticsstimulationparameters-m"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#optogeneticsstimulationparameters-m"}},[e._v("#")]),e._v(" OptogeneticsStimulationParameters.m:")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v(" %{\n # Parameters related to laser stimulation\n stim_parameter_set_id : int AUTO_INCREMENT # \n ---\n stim_parameter_description : varchar(256) #\n stim_wavelength : decimal(5,1) # (nm)\n stim_power : decimal(4,1) # (mW)\n stim_frequency : decimal(6,2) # (Hz)\n stim_pulse_width : decimal(5,1) # (ms)\n %}\n \n classdef OptogeneticStimulationParameter < dj.Lookup\n properties\n end\n end\n")])])]),t("ul",[t("li",[t("p",[e._v("Fields needed for a protocol “feature” table:")])]),e._v(" "),t("li",[t("p",[t("strong",[e._v("id field:")]),e._v(" as an int AUTO_INCREMENT type as the only primary key (e.g. stim_parameter_set_id).")])]),e._v(" "),t("li",[t("p",[t("strong",[e._v("extra_fields:")]),e._v(" Any other field that helps to define the feature.")])]),e._v(" "),t("li",[t("p",[e._v('After all feature tables are defined they should be added to the "Manipulation" Protocol table.')])]),e._v(" "),t("li",[t("p",[e._v("For our Optogenetics example:")])])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v('% Declare new "feature" table\noptogenetics.OptogeneticsStimulationParameters\n% Add the feature -> protocol table\nadd_feature_key_protocol_table(optogenetics.OptogeneticsProtocol, ... optogenetics.OptogeneticsStimulationParameters)\n% Sync definition from DB to .m file\nsyncDef(optogenetics.OptogeneticsProtocol);\n% clear previous connection and connect again\nclear all\nconnect_datajoint00\n')])])]),t("ul",[t("li",[e._v('After the “features” tables are added to the "Manipulation" Protocol table we are ready to add protocols to be “ready” and selectable for a behavior session:')])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v(" % Insert stim parameter record\n stim_parameter_rec.stim_parameter_description = 'cool stims'\n stim_parameter_rec.stim_wavelength = 473\n stim_parameter_rec.stim_power = 10 \n stim_parameter_rec.stim_frequency = 100 \n stim_parameter_rec.stim_pulse_width = 1\n insert(optogenetics.OptogeneticsStimulationParameters, stim_parameter_rec) \n\n % get last inserted stim_id\n stim_id = fetch(optogenetics.OptogeneticsStimulationParameters, 'ORDER BY stim_parameter_set_id desc LIMIT 1');\n\n % or look for a previously inserted parameter\n all_stim_params = fetch(optogenetics.OptogeneticsStimulationParameters, '*')\n stim_id = 1;\n\n % Insert new protocol with new stimulation parameter\n new_protocol.protocol_description = 'this_is_new_protocol'\n new_protocol.stim_parameter_set_id = stim_id;\n insert(optogenetics.OptogeneticsProtocol, new_protocol)\n")])])]),t("h3",{attrs:{id:"manipulation-softwareparameters-table"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#manipulation-softwareparameters-table"}},[e._v("#")]),e._v(' "Manipulation" SoftwareParameters table')]),e._v(" "),t("ul",[t("li",[e._v("The software parameters table stores a set of parameters (a matlab struct, a python dictionary) that the code that handles the behavior will use during the session.")]),e._v(" "),t("li",[e._v("We will show how to insert new software parameters:")]),e._v(" "),t("li",[e._v("This for the "),t("strong",[e._v("optogenetics.OptogeneticSoftwareParameter")]),e._v(" table")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("param_struct = struct();\nparam_struct.software_parameter_description = 'stimulation_sequence # 1';\n \n% All parameters goes in here \n%(P_on and lsrepoch are the common and needed for current opto experiments)\nparam_struct.software_parameters.P_on = 0.21;\nparam_struct.software_parameters.lsrepoch = 'cue';\n \n%Insert parameter\nsoftware_param_id = try_insert(optogenetics.OptogeneticSoftwareParameter, param_struct)\n")])])]),t("ul",[t("li",[e._v("Check "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline-matlab/blob/master/scripts/insert_software_parameters/insert_optogenetic_software_parameter.m"}},[e._v("insert_optogenetic_software_parameter")]),e._v(" script to use as example.")]),e._v(" "),t("li",[e._v("How to read software parameters on experiment code (ViRMEn)")]),e._v(" "),t("li",[e._v("Example to get software parameters on the initializatonCodeFun on virmen:")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("function vr = initializationCodeFun(vr)\n\nvr.software_params = vr.exper.userdata.trainee.softwareParams.software_parameters;\nvr.lsrepoch = vr.software_params.lsrepoch;\nvr.P_on = vr.software_params.P_on;\n")])])]),t("h3",{attrs:{id:"manipulation-session-table"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#manipulation-session-table"}},[e._v("#")]),e._v(' "Manipulation" Session table')]),e._v(" "),t("ul",[t("li",[e._v("This table stores manipulation data for a specific behavior session. This table “links” a manipulationProtocol & manipulationSoftwareParameters with a behavior Session.")]),e._v(" "),t("li",[e._v("This table does not need any additional code on it. (Unless extra fields from the behavior file are needed to be stored). "),t("strong",[e._v("Researcher should contact DB designer if that is their intention")])])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("OptogeneticSession.m \n%{\n# Information of a optogenetic session\n-> acquisition.Session\n---\n-> acquisition.SessionManipulation\n-> optogenetics.OptogeneticProtocol\n-> optogenetics.OptogeneticSoftwareParameter\n%}\n")])])]),t("h3",{attrs:{id:"manipulation-sessiontrial-table"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#manipulation-sessiontrial-table"}},[e._v("#")]),e._v(' "Manipulation" SessionTrial table')]),e._v(" "),t("ul",[t("li",[e._v("This table stores data, on a trial by trial basis, corresponding to the manipulation performed during the behavior session.")]),e._v(" "),t("li",[e._v('There is a section on any "Manipulation" SessionTrial class on the get_manipulation_trial_data function code where researcher has to add lines to fetch specific trial manipulation data:')])]),e._v(" "),t("p",[e._v("Code extract from "),t("strong",[e._v("OptogeneticSessionTrial")]),e._v(" table")]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("function trial_structure = get_manipulation_trials_data(~,session_key, log)\n.\n.\nfor itrial = 1:nTrials\n\n curr_trial = log.block(iBlock).trial(itrial); \n trial_data = session_key;\n trial_data.stim_on = curr_trial.lsrON;\n trial_data.t_stim_on = time_trial(curr_trial.iLaserOn);\n trial_data.stim_epoch = num2str(curr_trial.LaserTrialType);\n trial_structure(total_trials) = trial_data;\n")])])]),t("h3",{attrs:{id:"training-with-new-manipulation"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#training-with-new-manipulation"}},[e._v("#")]),e._v(" Training with new manipulation")]),e._v(" "),t("ul",[t("li",[e._v("After all code for new manipulation has been set up the researcher will be able to select a specific manipulation type, protocol & software parameters that will be associated with the schedule for a given animal. Subsequent behavior sessions will correspond to that selection.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(477)}}),e._v(" "),t("center",[t("figcaption",[e._v("Parameter selection (manipulation, protocol & software Parameter) for a training schedule of a subject.")])])],1),e._v(" "),t("h3",{attrs:{id:"fetching-data"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#fetching-data"}},[e._v("#")]),e._v(" Fetching Data")]),e._v(" "),t("ul",[t("li",[e._v("After training has occurred all relevant data will be accessible in the corresponding tables of the database.")]),e._v(" "),t("li",[t("a",{attrs:{href:"https://docs.datajoint.org/matlab/queries/03-Fetch.html"}},[e._v("Datajoint fetch guide")])])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'sbolkan_a2a_492', 'session_date', '2022-06-27')\nfetch(optogenetics.OptogeneticSessionTrial * optogenetics.OptogeneticSession & key,'*')\n\nans = \n\n 363×1 struct array with fields:\n\n subject_fullname\n session_date\n session_number\n block\n trial_idx\n stim_on\n t_stim_on\n t_stim_off\n stim_epoch\n")])])])])}),[],!1,null,null,null);t.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/33.0e3bba28.js b/assets/js/33.0e3bba28.js new file mode 100644 index 0000000..2014cc0 --- /dev/null +++ b/assets/js/33.0e3bba28.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[33],{276:function(e,t,i){e.exports=i.p+"assets/img/Menu_task_scheduler.12db0039.png"},277:function(e,t,i){e.exports=i.p+"assets/img/Trigger_tab_task_scheduler.d1fe7432.png"},478:function(e,t,i){e.exports=i.p+"assets/img/training_gui_pupillometry.85699e0d.png"},479:function(e,t,i){e.exports=i.p+"assets/img/pupillometry_DB_erd.55c680c5.png"},530:function(e,t,i){"use strict";i.r(t);var s=i(10),a=Object(s.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("ul",[t("li",[e._v("This documentation will guide the researcher through the process of register, monitor & review pupillometry data.")])]),e._v(" "),t("h2",{attrs:{id:"instructions-to-set-up-pupillometry-pipeline-on-a-rig-machine"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#instructions-to-set-up-pupillometry-pipeline-on-a-rig-machine"}},[e._v("#")]),e._v(" Instructions to Set up Pupillometry Pipeline on a Rig Machine")]),e._v(" "),t("ol",[t("li",[e._v("Ask your lab manager for helo to set up a camera in the rig.")]),e._v(" "),t("li",[e._v("If needed, add these parameters in "),t("strong",[e._v("RigParameters.m")])])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("%% Pupilometry video parameters\nvideo_parent_path = 'E:/VideoData'\nvideo_ext = '.mj2'\nvideo_acquisition_rate = 30\nvideo_record = true\nvideo_gain = 8\npreview = true\n")])])]),t("ol",{attrs:{start:"3"}},[t("li",[e._v("In Tranining GUI subject task selection menu, under "),t("code",[e._v("PupillometryVideo")]),e._v(" select "),t("code",[e._v("2. In RigParameters")]),e._v(":")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(478)}}),e._v(" "),t("center",[t("figcaption",[e._v("Training GUI for pupillometry")])])],1),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[e._v("In Experiment file add the following lines in "),t("code",[e._v("initializationcodeFun")]),e._v(" function (just after "),t("code",[e._v("vr = initializeGradedExperiment(vr);")]),e._v(" line):")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("% Start video acquisition\nif ~isempty(vr.trainee.pupillometryVideo) && vr.trainee.pupillometryVideo ~= 1\n vr = startVideoAcquisition(vr);\nend\n")])])]),t("ol",{attrs:{start:"5"}},[t("li",[e._v("In Experiment file add the following lines in "),t("code",[e._v("runtimeCodeFun")]),e._v(" function (just after "),t("code",[e._v("catch err displayException(err);")]),e._v(" line):")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("% Stop video acquisition\nif ~isempty(vr.trainee.pupillometryVideo) && vr.trainee.pupillometryVideo ~= 1\n vr = stopVideoAcquisition(vr);\nend\n")])])]),t("ol",{attrs:{start:"6"}},[t("li",[e._v("In Experiment file add the following lines in "),t("code",[e._v("terminationCodeFun")]),e._v(" function (the very first line):")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("% Stop video acquisition\nif ~isempty(vr.trainee.pupillometryVideo) && vr.trainee.pupillometryVideo ~= 1\n vr = stopVideoAcquisition(vr);\nend\n")])])]),t("h3",{attrs:{id:"pupillometry-backup-videos-task-schedule"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#pupillometry-backup-videos-task-schedule"}},[e._v("#")]),e._v(" Pupillometry backup videos task schedule")]),e._v(" "),t("ol",[t("li",[e._v("On Windows type "),t("strong",[e._v('"Task Scheduler"')])]),e._v(" "),t("li",[e._v("Open "),t("strong",[e._v("Task Scheduler")]),e._v(' "App"')]),e._v(" "),t("li",[e._v("On right hand side menu, click on "),t("strong",[e._v('"Create Task"')]),e._v(" Action")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(276)}}),e._v(" "),t("center",[t("figcaption",[e._v("Task scheduler menu")])])],1),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[e._v("Name new task as "),t("strong",[e._v("video_backup")])]),e._v(" "),t("li",[e._v("Add a trigger to run task daily at 11:30 pm")])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(277)}}),e._v(" "),t("center",[t("figcaption",[e._v("Task scheduler Trigger Tab")])])],1),e._v(" "),t("ol",{attrs:{start:"6"}},[t("li",[e._v("Add an action: add this line to the Program/script edit: "),t("code",[e._v("C:\\Experiments\\U19-pipeline-matlab\\scripts\\cmd_copy_video_files")])]),e._v(" "),t("li",[e._v("Hit "),t("strong",[e._v("OK")]),e._v(" button")])]),e._v(" "),t("h2",{attrs:{id:"pupillometry-db-and-data-organization"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#pupillometry-db-and-data-organization"}},[e._v("#")]),e._v(" Pupillometry DB and data organization")]),e._v(" "),t("ul",[t("li",[t("p",[e._v("Raw data (video files) are located in: "),t("code",[e._v("\\\\cup.pni.princeton. edu\\braininit\\Data\\Raw\\video_pupillometry\\(userid)\\(subjectfullname)\\(session_date)_g(session_number)\\(video_file)")])])]),e._v(" "),t("li",[t("p",[e._v("Processed data (h5 files) are located in: "),t("code",[e._v("\\\\cup.pni.princeton. edu\\braininit\\Data\\Processed\\video_pupillometry\\(userid)\\(subjectfullname)\\(session_date)_g(session_number)\\(h5_file)")])])]),e._v(" "),t("li",[t("p",[e._v("Video models are located in: "),t("code",[e._v("\\\\cup.pni.princeton. edu\\braininit\\Data\\Raw\\video_models\\(video_model_directory)")])])]),e._v(" "),t("li",[t("p",[e._v("Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/db_organization.html#_9-u19-pupillometry"}},[e._v(" DB Organization (pupillometry) ")]),e._v(" for a description for each pupillometry table.")])])]),e._v(" "),t("figure",[t("img",{attrs:{src:i(479)}}),e._v(" "),t("center",[t("figcaption",[e._v("Pupillometry pipeline DB schema")])])],1),e._v(" "),t("h2",{attrs:{id:"steps-executed-in-pupillometry-pipeline"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#steps-executed-in-pupillometry-pipeline"}},[e._v("#")]),e._v(" Steps executed in Pupillometry pipeline")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("When "),t("code",[e._v("pupillometry_video -> 2. In RigParameters ")]),e._v(" is selected in training GUI a new "),t("code",[e._v("session_video")]),e._v(" record is registered in the DB while ingesting Session. ("),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline-matlab/blob/master/schemas/%2Bacquisition/Session.m#L135"}},[e._v("Code here")]),e._v(")")])]),e._v(" "),t("li",[t("p",[e._v("The "),t("code",[e._v("cmd_copy_video_files")]),e._v(" task scheduler takes "),t("code",[e._v("session_video")]),e._v(" records and store new videos in this location: "),t("code",[e._v("\\\\cup.pni.princeton. edu\\braininit\\Data\\Raw\\video_pupillometry\\(userid)\\(subjectfullname)\\(session_date)_g(session_number)\\(video_file)")]),e._v(". "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline-matlab/blob/master/scripts/cmd_copy_behavior_files.BAT"}},[e._v("Script run by pupillometry backup videos task schedule")])])]),e._v(" "),t("li",[t("p",[e._v("During night cronjob: if video is found on cup location:")])])]),e._v(" "),t("ul",[t("li",[e._v("Populate "),t("code",[e._v("pupillometry_session")]),e._v(" table")]),e._v(" "),t("li",[e._v("Execute sync behavior code for video. "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline-matlab/blob/master/schemas/%2Bpupillometry/PupillometrySyncBehavior.m"}},[e._v(" Code here")]),e._v(".")]),e._v(" "),t("li",[e._v("Register default model to process video in "),t("code",[e._v(" pupillometry_session_model")]),e._v(" and "),t("code",[e._v("pupillometry_session_model_data")]),e._v(".")])]),e._v(" "),t("ol",{attrs:{start:"4"}},[t("li",[e._v("Queue/Checks job in "),t("code",[e._v("spockvm2")])])]),e._v(" "),t("ul",[t("li",[t("p",[e._v("Similar to ephys/imaging automation pipeline, pupillometry pipeline has a main (more simple) class to process all pupillometry jobs called "),t("code",[e._v("PupillometryProcessingHandler")]),e._v(". This class is located "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline_python/blob/master/u19_pipeline/automatic_job/pupillometry_handler.py"}},[e._v(" here ")]),e._v(".")])]),e._v(" "),t("li",[t("p",[e._v("Execute "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline_python/blob/master/u19_pipeline/automatic_job/call_pupillometry_queue_jobs.sh"}},[e._v("pupillometry_queue_jobs script")]),e._v(". This scripts calls "),t("code",[e._v("PupillometryProcessingHandler.check_pupillometry_sessions_queue")]),e._v(" function. Queues a processing job to all sessions where a model was registered.")])]),e._v(" "),t("li",[t("p",[e._v("Execute "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline_python/blob/master/u19_pipeline/automatic_job/call_pupillometry_check_jobs.sh"}},[e._v("pupillometry_check_jobs script")]),e._v(". This scripts calls "),t("code",[e._v("PupillometryProcessingHandler.check_processed_pupillometry_sessions")]),e._v(" function. If processing job is finished get final result (pupil_diameter) and stores it in "),t("code",[e._v("pupillometry_session_model_data")]),e._v(" table.")])])]),e._v(" "),t("h2",{attrs:{id:"monitor-pupillometry-processing-sessions"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#monitor-pupillometry-processing-sessions"}},[e._v("#")]),e._v(" Monitor pupillometry processing sessions")]),e._v(" "),t("ul",[t("li",[t("p",[e._v("A few MATLAB functions were built to check how pupillometry jobs are doing:")])]),e._v(" "),t("li",[t("p",[e._v("Get processed data from a session:")])])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("key = struct('subject_fullname', 'efonseca_ef317_act116', 'session_date', '2024-02-21')\npupillometry_data = fetch(pupillometry.PupillometrySessionModelData * pupillometry.PupillometrySyncBehavior & key, '*')\npupillometry_data = \n\n struct with fields:\n\n subject_fullname: 'efonseca_ef317_act116'\n session_date: '2024-02-21'\n session_number: 0\n model_id: 2\n pupillometry_job_id: 2984\n pupil_diameter: [108177×1 double]\n sync_video_frame_matrix: [108177×4 single]\n sync_behavior_matrix: [150227×5 single]\n")])])]),t("p",[t("strong",[e._v("pupil_diameter")]),e._v(": Pupil diameter for each video frame."),t("br"),e._v(" "),t("strong",[e._v("sync_video_frame_matrix")]),e._v(": Time & Block/Trial/Iteration for each video frame."),t("br"),e._v(" "),t("strong",[e._v("sync_behavior_matrix")]),e._v(": Time & video frame for each Block/Trial/Iteration.")]),e._v(" "),t("ul",[t("li",[e._v("Restart processing for failed processing\nSometimes processing fails for external factors (processing system was down, model was not properly selected, etc). As a first attempt to solve the issue a restart processing function was created:")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("psmd = pupillometry.PupillometrySessionModelData()\nkey = struct('subject_fullname', 'efonseca_ef317_act116', 'session_date', '2024-02-21')\npsmd.restart_pupillometry_failed_job(key)\n")])])]),t("p",[e._v("If processing fails again, contact Software Developer and check "),t("code",[e._v("#automation_pipeline_errors")]),e._v(" slack channel for more information about the error.")]),e._v(" "),t("ul",[t("li",[e._v("Check status for all sessions:")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("psmd = pupillometry.PupillometrySessionModelData()\nall_sessions_table = psmd.check_status_pupillometry_jobs()\n")])])]),t("ul",[t("li",[e._v("Check status for a specific session(s):")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("psmd = pupillometry.PupillometrySessionModelData()\nkey = struct('subject_fullname', 'efonseca_ef317_act116', 'session_date', '2024-02-21')\nsession_status = psmd.check_status_pupillometry_jobs(key)\n")])])]),t("ul",[t("li",[e._v("Get all succesfully processed sessions:")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("psmd = pupillometry.PupillometrySessionModelData()\npupillometry_finished_sessions = psmd.get_finished_jobs_pupillometry()\n")])])]),t("h2",{attrs:{id:"add-a-new-video-model-to-the-pipeline"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#add-a-new-video-model-to-the-pipeline"}},[e._v("#")]),e._v(" Add a new video model to the pipeline")]),e._v(" "),t("h2",{attrs:{id:""}},[t("a",{staticClass:"header-anchor",attrs:{href:"#"}},[e._v("#")])]),e._v(" "),t("h2",{attrs:{id:"review-processed-data"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#review-processed-data"}},[e._v("#")]),e._v(" Review processed data")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/34.220cdeed.js b/assets/js/34.220cdeed.js new file mode 100644 index 0000000..6343f2e --- /dev/null +++ b/assets/js/34.220cdeed.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[34],{242:function(t,e,n){"use strict";n.d(e,"d",(function(){return r})),n.d(e,"a",(function(){return a})),n.d(e,"i",(function(){return s})),n.d(e,"f",(function(){return o})),n.d(e,"g",(function(){return c})),n.d(e,"h",(function(){return l})),n.d(e,"b",(function(){return p})),n.d(e,"e",(function(){return f})),n.d(e,"k",(function(){return d})),n.d(e,"l",(function(){return h})),n.d(e,"c",(function(){return g})),n.d(e,"j",(function(){return m}));n(90);const r=/#.*$/,i=/\.(md|html)$/,a=/\/$/,s=/^[a-z]+:/i;function u(t){return decodeURI(t).replace(r,"").replace(i,"")}function o(t){return s.test(t)}function c(t){return/^mailto:/.test(t)}function l(t){return/^tel:/.test(t)}function p(t){if(o(t))return t;const e=t.match(r),n=e?e[0]:"",i=u(t);return a.test(i)?t:i+".html"+n}function f(t,e){const n=decodeURIComponent(t.hash),i=function(t){const e=t.match(r);if(e)return e[0]}(e);if(i&&n!==i)return!1;return u(t.path)===u(e)}function d(t,e,n){if(o(e))return{type:"external",path:e};n&&(e=function(t,e,n){const r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"===r)return e+t;const i=e.split("/");n&&i[i.length-1]||i.pop();const a=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(e,n,r,i=1){if("string"==typeof e)return d(n,e,r);if(Array.isArray(e))return Object.assign(d(n,e[0],r),{title:e[1]});{const a=e.children||[];return 0===a.length&&e.path?Object.assign(d(n,e.path,r),{title:e.title}):{type:"group",path:e.path,title:e.title,sidebarDepth:e.sidebarDepth,initialOpenGroupIndex:e.initialOpenGroupIndex,children:a.map(e=>t(e,n,r,i+1)),collapsable:!1!==e.collapsable}}}(t,i,n)):[]}return[]}function b(t){const e=g(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:e.map(e=>({type:"auto",title:e.title,basePath:t.path,path:t.path+"#"+e.slug,children:e.children||[]}))}]}function g(t){let e;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?e=t:e&&(e.children||(e.children=[])).push(t)}),t.filter(t=>2===t.level)}function m(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},248:function(t,e,n){},255:function(t,e,n){"use strict";n(248)},258:function(t,e,n){"use strict";n.r(e);var r=n(242);function i(t,e,n,r,i){const a={props:{to:e,activeClass:"",exactActiveClass:""},class:{active:r,"sidebar-link":!0}};return i>2&&(a.style={"padding-left":i+"rem"}),t("RouterLink",a,n)}function a(t,e,n,s,u,o=1){return!e||o>u?null:t("ul",{class:"sidebar-sub-headers"},e.map(e=>{const c=Object(r.e)(s,n+"#"+e.slug);return t("li",{class:"sidebar-sub-header"},[i(t,n+"#"+e.slug,e.title,c,e.level-1),a(t,e.children,n,s,u,o+1)])}))}var s={functional:!0,props:["item","sidebarDepth"],render(t,{parent:{$page:e,$site:n,$route:s,$themeConfig:u,$themeLocaleConfig:o},props:{item:c,sidebarDepth:l}}){const p=Object(r.e)(s,c.path),f="auto"===c.type?p||c.children.some(t=>Object(r.e)(s,c.basePath+"#"+t.slug)):p,d="external"===c.type?function(t,e,n){return t("a",{attrs:{href:e,target:"_blank",rel:"noopener noreferrer"},class:{"sidebar-link":!0}},[n,t("OutboundLink")])}(t,c.path,c.title||c.path):i(t,c.path,c.title||c.path,f),h=[e.frontmatter.sidebarDepth,l,o.sidebarDepth,u.sidebarDepth,1].find(t=>void 0!==t),b=o.displayAllHeaders||u.displayAllHeaders;if("auto"===c.type)return[d,a(t,c.children,c.basePath,s,h)];if((f||b)&&c.headers&&!r.d.test(c.path)){return[d,a(t,Object(r.c)(c.headers),c.path,s,h)]}return d}},u=(n(255),n(10)),o=Object(u.a)(s,void 0,void 0,!1,null,null,null);e.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/35.ecdec2a2.js b/assets/js/35.ecdec2a2.js new file mode 100644 index 0000000..d411087 --- /dev/null +++ b/assets/js/35.ecdec2a2.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[35],{243:function(t,e,n){},245:function(t,e,n){"use strict";n.r(e);var s={name:"DropdownTransition",methods:{setHeight(t){t.style.height=t.scrollHeight+"px"},unsetHeight(t){t.style.height=""}}},i=(n(246),n(10)),o=Object(i.a)(s,(function(){return(0,this._self._c)("transition",{attrs:{name:"dropdown"},on:{enter:this.setHeight,"after-enter":this.unsetHeight,"before-leave":this.setHeight}},[this._t("default")],2)}),[],!1,null,null,null);e.default=o.exports},246:function(t,e,n){"use strict";n(243)}}]); \ No newline at end of file diff --git a/assets/js/36.758a67d9.js b/assets/js/36.758a67d9.js new file mode 100644 index 0000000..96a2514 --- /dev/null +++ b/assets/js/36.758a67d9.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[36],{261:function(t,c,n){},273:function(t,c,n){"use strict";n(261)},288:function(t,c,n){"use strict";n.r(c);n(273);var i=n(10),s=Object(i.a)({},(function(){var t=this,c=t._self._c;return c("div",{staticClass:"sidebar-button",on:{click:function(c){return t.$emit("toggle-sidebar")}}},[c("svg",{staticClass:"icon",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",role:"img",viewBox:"0 0 448 512"}},[c("path",{attrs:{fill:"currentColor",d:"M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"}})])])}),[],!1,null,null,null);c.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/37.f2b19388.js b/assets/js/37.f2b19388.js new file mode 100644 index 0000000..0c74c5e --- /dev/null +++ b/assets/js/37.f2b19388.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[37],{363:function(t,e,n){t.exports=n.p+"assets/img/training-mini-vr.bc8b4a3a.png"},364:function(t,e,n){t.exports=n.p+"src/building/assets/drawings/Training mini VR rig.step.zip"},506:function(t,e,n){"use strict";n.r(e);var i=n(10),a=Object(i.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"frontmatter-title"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[t._v("#")]),t._v(" "+t._s(t.$frontmatter.title))]),t._v(" "),e("figure",[e("img",{attrs:{src:n(363)}})]),t._v(" "),e("h2",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),e("p",[t._v("This website is a central repository for the documentation regarding the "),e("strong",[t._v("building")]),t._v(" of mini virtual reality training rigs as part of BRAIN CoGS at Princeton Neuroscience Institute.")]),t._v(" "),e("p",[t._v("Building documentation is divided into modules, each module contains a detailed explanaiton of the building process. The STEP files for of the entire rig can be found "),e("a",{attrs:{href:n(364)}},[t._v("here")]),t._v(". And a list of parts can be found "),e("a",{attrs:{href:"https://docs.google.com/spreadsheets/d/e/2PACX-1vSSVNJ8194nIha6Z6vqLnmFLNS-IRL88ZfY1aRPxX1KbcyrDNHXVJ4QOEmY1oKVSrLkx7DTxyjK0ceC/pubhtml#",target:"_blank",rel:"noopener noreferrer"}},[t._v("here"),e("OutboundLink")],1),t._v(" or "),e("a",{attrs:{href:"https://docs.google.com/spreadsheets/d/e/2PACX-1vSSVNJ8194nIha6Z6vqLnmFLNS-IRL88ZfY1aRPxX1KbcyrDNHXVJ4QOEmY1oKVSrLkx7DTxyjK0ceC/pub?output=xlsx",target:"_blank",rel:"noopener noreferrer"}},[t._v("downloaded in xlsx format"),e("OutboundLink")],1)]),t._v(" "),e("p",[t._v("If you need any other file, any other format, need help or just wanted to reach out don't hesitate to contact "),e("a",{attrs:{href:"mailto:jl4459@princeton.edu"}},[t._v("Juan Luna")]),t._v(" or any other memeber of the BRAIN CoGS team.")]),t._v(" "),e("h2",{attrs:{id:"recommended-steps-to-assembly"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#recommended-steps-to-assembly"}},[t._v("#")]),t._v(" Recommended steps to assembly.")]),t._v(" "),e("ol",[e("li",[t._v("Begin with the assembly of the bottom part of the cabinet (steps 1-6 of "),e("RouterLink",{attrs:{to:"/building/cabinet.html#cabinet-assembly"}},[t._v("cabinet assembly")]),t._v("). In parallel, you can start with the construction of the "),e("RouterLink",{attrs:{to:"/building/projection.html#screen-building"}},[t._v("screen")]),t._v(".")],1),t._v(" "),e("li",[t._v("Follow the intructions to assemble the "),e("RouterLink",{attrs:{to:"/building/stage.html"}},[t._v("stage")]),t._v(" and "),e("RouterLink",{attrs:{to:"/building/stage.html#stage-installation"}},[t._v("install")]),t._v(" it in the cabinet.")],1),t._v(" "),e("li",[t._v("Screw the "),e("RouterLink",{attrs:{to:"/building/projection.html#mirror"}},[t._v("mirror")]),t._v(" and the "),e("RouterLink",{attrs:{to:"/building/projection.html#screen-assembly"}},[t._v("pillars")]),t._v(", but not the top plates that will hold the screen.")],1),t._v(" "),e("li",[t._v("Install the "),e("RouterLink",{attrs:{to:"/building/air-supply.html#air-flow-adapter"}},[t._v("air supply hose adapter")]),t._v(" on the side panel and make the holes on the panel if necessary, install the side panels on the cabinet (step 8 of "),e("RouterLink",{attrs:{to:"/building/cabinet.html#cabinet-assembly"}},[t._v("cabinet assembly")]),t._v(").")],1),t._v(" "),e("li",[t._v("Make the hole on the back panel for the projector if necessary, install the back panel and slide down the frame (step 7 of "),e("RouterLink",{attrs:{to:"/building/cabinet.html#cabinet-assembly"}},[t._v("cabinet assembly")]),t._v(") and insert the joining strip along the out edges of the panels.")],1),t._v(" "),e("li",[t._v("Place the adapters on top of the pillars and install the screen (step 2 of "),e("RouterLink",{attrs:{to:"/building/projection.html#screen-assembly"}},[t._v("screen assembly")]),t._v(").")],1),t._v(" "),e("li",[t._v("Assemble the top portion of the cabinet (step 8 of "),e("RouterLink",{attrs:{to:"/building/cabinet.html#cabinet-assembly"}},[t._v("cabinet assembly")]),t._v(").")],1),t._v(" "),e("li",[t._v("Install the DIN rails (steps 11 of "),e("RouterLink",{attrs:{to:"/building/cabinet.html#cabinet-assembly"}},[t._v("cabinet assembly")]),t._v(") and the "),e("RouterLink",{attrs:{to:"/building/air-supply.html"}},[t._v("air supply")]),t._v(", "),e("RouterLink",{attrs:{to:"/building/air-puffs.html"}},[t._v("air puffs")]),t._v(" if using, and "),e("RouterLink",{attrs:{to:"/building/control.html"}},[t._v("control")]),t._v(" module.")],1),t._v(" "),e("li",[t._v("Install the "),e("RouterLink",{attrs:{to:"/building/positioning.html"}},[t._v("positioning system")]),t._v(" in the stage of the rig.")],1),t._v(" "),e("li",[t._v("Assemble and install the doors (steps 9-10 of "),e("RouterLink",{attrs:{to:"/building/cabinet.html#cabinet-assembly"}},[t._v("cabinet assembly")]),t._v(").")],1)])])}),[],!1,null,null,null);e.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/38.ddeff521.js b/assets/js/38.ddeff521.js new file mode 100644 index 0000000..34702fb --- /dev/null +++ b/assets/js/38.ddeff521.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[38],{365:function(e,t,o){e.exports=o.p+"assets/img/lick-detection-1.52d3cd87.png"},366:function(e,t,o){e.exports=o.p+"assets/img/lick-detection-2.042426c7.png"},507:function(e,t,o){"use strict";o.r(t);var r=o(10),a=Object(r.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("p",[e._v("The lick detection module is based on a simple transistor design (Slotnick 2009), we modified the design to allow the detection of 2 lick spouts in the same module. Additionally, we added a DC-DC converter to isolate the circuit from the power source and added a 5V voltage regulator after the relays to have a TTL signal at the output of both circuits.")]),e._v(" "),t("p",[e._v("The module was designed this way to enable a specific task that require the use of two spouts, but it can also be used in a one spout setting (e.g count the number of licks during a task). Below is an example of a setup using two lick spouts during a decision making task developed by one member of the BRAIN CoGS team.")]),e._v(" "),t("h2",{attrs:{id:"two-lick-detection-module-assembly"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#two-lick-detection-module-assembly"}},[e._v("#")]),e._v(" Two lick detection module assembly")]),e._v(" "),t("p",[e._v("Have the PCB fabricated "),t("a",{attrs:{href:"https://www.pcbway.com/project/shareproject/Two_spouts_lick_detector_059c7e07.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("here"),t("OutboundLink")],1),e._v(" (or download the GERBER files and have it made elsewhere). The step by step instructions to solder the components on the solenoid valve driver from the "),t("RouterLink",{attrs:{to:"/building/control.html#solenoid-valve-driver-assembly"}},[e._v("control module")]),e._v(" can be used as well for this module, making sure to use the appropiate components and placing them as labeled in the PCB.")],1),e._v(" "),t("figure",[t("img",{attrs:{src:o(365)}})]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("Label")]),e._v(" "),t("th",[e._v("Part No.")]),e._v(" "),t("th",[e._v("Description")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("R1, R2, R4, R5")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/yageo/AC1206FR-0710ML/5897214",target:"_blank",rel:"noopener noreferrer"}},[e._v("AC1206FR-0710ML"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("10M Ohm resistors")])]),e._v(" "),t("tr",[t("td",[e._v("R3, R6")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/yageo/AC1206FR-0747KL/5897559",target:"_blank",rel:"noopener noreferrer"}},[e._v("AC1206FR-0747KL"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("47K Ohm resistors")])]),e._v(" "),t("tr",[t("td",[e._v("R7, R8")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/yageo/ac1206fr-0710kl/5897213",target:"_blank",rel:"noopener noreferrer"}},[e._v("AC1206FR-0710KL"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("10K Ohm resistors")])]),e._v(" "),t("tr",[t("td",[e._v("T1, T2, T3, T4")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/onsemi/mmbt2222lt1g/919595",target:"_blank",rel:"noopener noreferrer"}},[e._v("MMBT2222LT1G"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("BJT Transistor NPN")])]),e._v(" "),t("tr",[t("td",[e._v("8L61-12-011 (2)")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/coto-technology/8l61-12-011/1914969",target:"_blank",rel:"noopener noreferrer"}},[e._v("8L61-12-011"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("Relay reed SPDT 250MA 12V")])]),e._v(" "),t("tr",[t("td",[e._v("U2")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/texas-instruments/ua78l05acpke6/9860880",target:"_blank",rel:"noopener noreferrer"}},[e._v("UA78L05ACPKE6"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("Linear Voltage Regulator")])]),e._v(" "),t("tr",[t("td",[e._v("No label (middle big square)")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/traco-power/trs-2-2412/9383650",target:"_blank",rel:"noopener noreferrer"}},[e._v("TRS 2-2412"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("Isolated Module DC DC Converter")])]),e._v(" "),t("tr",[t("td",[e._v("C1")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/samsung-electro-mechanics/cl31b475kbhnnne/3888447",target:"_blank",rel:"noopener noreferrer"}},[e._v("CL31B475KBHNNNE"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("4.7 µF Ceramic Capacitor")])]),e._v(" "),t("tr",[t("td",[e._v("C2")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/samsung-electro-mechanics/cl31c151jbcnnnc/3888469",target:"_blank",rel:"noopener noreferrer"}},[e._v("CL31C151JBCNNNC"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("150 pF Ceramic Capacitor")])]),e._v(" "),t("tr",[t("td",[e._v("22 micro")]),e._v(" "),t("td",[t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/vishay-dale/ifsc1008aber220m01/2744218",target:"_blank",rel:"noopener noreferrer"}},[e._v("IFSC1008ABER220M01"),t("OutboundLink")],1)]),e._v(" "),t("td",[e._v("22 µH Shielded Inductor")])])])]),e._v(" "),t("p",[e._v("After assemblying the module, place the labels as shown in the picture below.")]),e._v(" "),t("figure",[t("img",{attrs:{src:o(366)}})]),e._v(" "),t("p",[e._v("The description of each pin of the lick detector module can be found in the table below.")]),e._v(" "),t("table",[t("thead",[t("tr",[t("th",[e._v("PIN")]),e._v(" "),t("th",[e._v("Description")])])]),e._v(" "),t("tbody",[t("tr",[t("td",[e._v("1. GROUND")]),e._v(" "),t("td",[e._v("Input - ground")])]),e._v(" "),t("tr",[t("td",[e._v("2. 24V")]),e._v(" "),t("td",[e._v("Input - 24V DC")])]),e._v(" "),t("tr",[t("td",[e._v("3. OUT LEFT")]),e._v(" "),t("td",[e._v("Output - TTL output pin for the left spout")])]),e._v(" "),t("tr",[t("td",[e._v("4. OUT RIGHT")]),e._v(" "),t("td",[e._v("Output - TTL output pin for the right spout")])]),e._v(" "),t("tr",[t("td",[e._v("5. RIGHT SPOUT")]),e._v(" "),t("td",[e._v("Input - Connect the right spout to this pin")])]),e._v(" "),t("tr",[t("td",[e._v("6. LEFT SPOUT")]),e._v(" "),t("td",[e._v("Input - Connect the left spout to this pin")])]),e._v(" "),t("tr",[t("td",[e._v("7. HEADPLATE")]),e._v(" "),t("td",[e._v("Input - Connect the headplate to this pin")])]),e._v(" "),t("tr",[t("td",[e._v("8. COMMON")]),e._v(" "),t("td",[e._v("Input - Connect the ground from the NiDAQ (or any acquisition device) to this pin")])])])]),e._v(" "),t("h3",{attrs:{id:"soldering-a-cable-to-the-feeding-spout-and-headplate-holder"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#soldering-a-cable-to-the-feeding-spout-and-headplate-holder"}},[e._v("#")]),e._v(" Soldering a cable to the feeding spout and headplate holder")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Use sandpaper to remove the outer layer of the stainless steel spout at one of the sides if the luer lock connector (as far as possible from the connector tip), do the same with the headplate (wherever you want to place the cable, we recommend to use the arm without the tapped hole to fit a heat shrinkable tube).")])]),e._v(" "),t("li",[t("p",[e._v("Clean the sanded surface with isopropyl alcohol and let it dry. In the meantime, prepare the coaxial cable (we recommend a "),t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/molex-temp-flex/1000660054/4368709",target:"_blank",rel:"noopener noreferrer"}},[e._v("26"),t("OutboundLink")],1),e._v(" or "),t("a",{attrs:{href:"https://www.digikey.com/en/products/detail/molex/1001935047/8566104",target:"_blank",rel:"noopener noreferrer"}},[e._v("28"),t("OutboundLink")],1),e._v(" AWG coaxial cable like these ones ) by removing the jacket and the shield, then expose the conductor by removing a portion of the insulation material. Repeat the process on the other end of the cable.")])]),e._v(" "),t("li",[t("p",[e._v("Drop a small drop of flux in the sanded surface and place the tip of the solder iron over the flux - the tip might stick to the stainless steel, that's normal - continue heating the surface and use soldering wire (we found lead works best) to solder the coaxial cable to the spout and headplate.")])]),e._v(" "),t("li",[t("p",[e._v("Use heat shrinkable tube to cover the soldering spot.")])])]),e._v(" "),t("p",[e._v("To close the circuit for detection, you need a contact in the mice body. We solder a lead (repeating steps 1-4) at the headplate holder, but that can be adjusted on different setups.")])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/39.dd78eec6.js b/assets/js/39.dd78eec6.js new file mode 100644 index 0000000..5831e0b --- /dev/null +++ b/assets/js/39.dd78eec6.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[39],{436:function(e,t,r){e.exports=r.p+"assets/img/projection-1.8e1de7a7.png"},437:function(e,t,r){e.exports=r.p+"assets/img/projection-2.e4e10713.png"},517:function(e,t,r){"use strict";r.r(t);var o=r(10),i=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("p",[e._v("The projection module maintenance consist primarily on the initial calibration and subsequent maintenance calibrations that should be performed every ~6 months, and the projector bulb replacement that must be done whenever the projector ask for it, since the projector has an internal counter of how many hours the bulb has been used.")]),e._v(" "),t("h2",{attrs:{id:"projection-calibration"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#projection-calibration"}},[e._v("#")]),e._v(" Projection calibration")]),e._v(" "),t("p",[e._v("The projection system use a spherical mirror to project into the dome. The image transformation is based on a "),t("a",{attrs:{href:"http://www.domerama.com/general/geodesic-dome-projection/hemispherical-dome-projection/",target:"_blank",rel:"noopener noreferrer"}},[e._v("hemispherical dome projection principle"),t("OutboundLink")],1),e._v(".")]),e._v(" "),t("p",[e._v("Creating correctly warped images given a particular projector, mirror, and dome arrangement requires finding the point on the projector frustum for any point on the dome. The problem is three-dimensional but can be turned into a simpler two dimensional problem by firstly translating the geometry so the spherical mirror is at the origin and then rotating the geometry so that the point on the mirror, dome, and projector lies in a single plane.")]),e._v(" "),t("p",[e._v("The projector is located at P1, the mirror is of radius r, and the position on the dome is P2. The path length from the projector to the mirror is L1, the path length from the dome to the mirror is L2. In the case of a spherical mirror: the line at mid-angle between the vectors OP1 and OP2 and its intersection with the surface of the mirror defines the reflection point.")]),e._v(" "),t("p",[e._v("Fermat’s principle states that light travels by the shortest route, so the reflection point on the mirror can be found by minimising the total light path length from the projector to the position on the dome, namely minimising (L1^2 + L2^2)^1/2. It is quite simple in the case of a spherical mirror: the line at mid-angle between the vectors OP1 and OP2 and its intersection with the surface of the mirror defines the reflection point.")]),e._v(" "),t("figure",[t("img",{attrs:{src:r(436)}})]),e._v(" "),t("p",[e._v("The projection calibration will align the projection within certain boundaries, specifically the horizon, the center and the left and right side will be aligned to the physical position of the dome. This method has a trade-off in the time that has to be inverted to perform the alignment vs the accuracy of the rendered projection, since the height of the towers might be different across systems.")]),e._v(" "),t("p",[e._v("To calibrate the projection:")]),e._v(" "),t("ol",[t("li",[e._v("Turn on the projector and make sure to mirror the projection horizontally, otherwise left/right will be inverted.")]),e._v(" "),t("li",[e._v("Place the alignment tool. We recommend to use a "),t("a",{attrs:{href:"https://www.grainger.com/product/BOSCH-Alignment-Laser-3-Beams-450W78?internalSearchTerm=Alignment+Laser%3A+3+Beams%2C+0+Dots%2C+0+Lines%2C+Red%2C+200+ft+Range+w%2Fo+Detector&suggestConfigId=8&searchBar=true&opr=THKS",target:"_blank",rel:"noopener noreferrer"}},[e._v("3 laser alignment tool"),t("OutboundLink")],1),e._v('. Use the marked lines at the bottom plate to align the center and sides lasers on the dome. Set the height of the horizontal laser to 12" from the bottom plate.')]),e._v(" "),t("li",[e._v("Create a new subject in the ViRMEn training GUI and select the livecalibration.mat experiment. This is the calibration world that was developed, it is necessary to set the simulation mode to true in the RigParameters file. This will project a static world with 3 towers set at the center and at the left and right of the mouse eyes. The goal is to align the horizon to the animal eyes position, the center tower to the center of the screen and the left and right towers to the mouse eyes position.")]),e._v(" "),t("li",[e._v("Set the initial vairables of the projection parameters as below (these parameters has been obatained empirically and they are a good starting point for the training mini VR rigs as they are built).")])]),e._v(" "),t("div",{staticClass:"language- extra-class"},[t("pre",{pre:!0,attrs:{class:"language-text"}},[t("code",[e._v("%% Mini VR projection parameters\n% Spherical screen radius\nproj_param_Rs = 8;\n\n% Screen's center location relative to the animal eyes\nproj_param_xsm = 1.814;\nproj_param_ysm = 0;\nproj_param_zsm = 0.47;\n\n% Mirror position relative to the animal eyes\n% Mirror position measurement is facilitated knowing that the center of \n%spherical mirror is (43.8-24.2=)19.6mm (0.77in) behind the back surface.\nproj_param_xOm = 5.582;\nproj_param_yOm = 0;\nproj_param_zOm = -6.62;\n\n% Radius of the spherical mirror (Silver coated lens LA1740-Thorlabs)\nproj_param_r = 1.724;\n\n% Projector position relative to the mirror center\nproj_param_xP1o = 11.1;\nproj_param_yP1o = 0;\nproj_param_zP1o = -0.6;\n\n% Horizontal coordinate shift and rescaling\nproj_param_hrescaling = 5.5;\nproj_param_hshift = 0.000;\n\n% Vertical coordinate shift and rescaling\nproj_param_vrescaling = 5.5;\nproj_param_vshift = -1.017;\n\n\n")])])]),t("ol",{attrs:{start:"4"}},[t("li",[e._v("First, try to align certain variables by physically moving the projector. Unscrew the plate that holds the projector and move it horizontally until the middle tower is centered with the laser. Make sure that the left and rigth towers are equidistant from the middle of the dome, you may be able to achieve this by slightly moving the plate forward from one side or the other.")])]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("The position of the towers will move when the plate is thightened, don't untight the screws all the way if it is not necessary, unthight until it is possible to move the plate and checking the projection, then thight and adjust accordingly.")])]),e._v(" "),t("p",[e._v("The goal of doing this physically instead of modifying the projection transformation parameters is that it decreases the differences across the projections in different training rigs.")]),e._v(" "),t("ol",{attrs:{start:"5"}},[t("li",[e._v("Adjust the rest of the parameters until the towers and horizon are aligned. A brief description of how each parameter adjust the projection can be found below.")])]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Rs")]),e._v(" should not be modified.")]),e._v(" "),t("li",[t("strong",[e._v("xsm")]),e._v(" will adjust the middle tower height without affecting the lateral towers, values should be around [1.5 - 2]. This value canbe adjusted since there will be idiosincrasies due to the screen fabrication.")]),e._v(" "),t("li",[t("strong",[e._v("zOm")]),e._v(" will adjust the horizon. This value can be adjusted since there can be differences in how the mirror is glued to its aluminum base.")]),e._v(" "),t("li",[t("strong",[e._v("xP1o")]),e._v(" will extend or contract the lateral towers and "),t("strong",[e._v("zP1o")]),e._v(" will lower or elevate the middle tower but will modify the distal part of the lateral towers. These values can be adjusted since there are idiosincrasies in the origin of the projection between projectors in their fabrication.")]),e._v(" "),t("li",[e._v("The "),t("strong",[e._v("hrescaling")]),e._v(" and the "),t("strong",[e._v("vrescaling")]),e._v(" should be the same, otherwise it will modify elongate or contract the projection, and there will be significant differences across sytems.")]),e._v(" "),t("li",[e._v("The "),t("strong",[e._v("hshift")]),e._v(" and "),t("strong",[e._v("vshift")]),e._v(" will move the entire projection up, down, left or right. Ideally the "),t("strong",[e._v("hshift")]),e._v(" should be 0 if the projection is calibrated manually, but it can be modified if necessary since it shouldn't affect significatly the projection across differente systems.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:r(437)}}),e._v(" "),t("center",[t("figcaption",[t("small",[e._v("Projection calibration. Due to the principle of the spherical mirror projection, the lateral towers will be slightly curved, the projection should be fine as long as they are equidistant and centered at the top (or the bottom, just make sure to keep the same policy across rigs).")])])])],1),e._v(" "),t("h2",{attrs:{id:"projector-bulb-replacement"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#projector-bulb-replacement"}},[e._v("#")]),e._v(" Projector bulb replacement.")]),e._v(" "),t("p",[e._v("The projector has a counter used to determine how long the bulb has been used, it will emit an alert that the bulb should be replaced. Make sure to have in stock projector bulbs and follow each projector instruction to replace it.")])])}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/4.8d93e77a.js b/assets/js/4.8d93e77a.js new file mode 100644 index 0000000..3425518 --- /dev/null +++ b/assets/js/4.8d93e77a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{282:function(t,e,n){},296:function(t,e,n){"use strict";n(282)},501:function(t,e,n){"use strict";n.r(e);var i={functional:!0,props:{type:{type:String,default:"tip"},text:String,vertical:{type:String,default:"top"}},render:(t,{props:e,slots:n})=>t("span",{class:["badge",e.type],style:{verticalAlign:e.vertical}},e.text||n().default)},p=(n(296),n(10)),l=Object(p.a)(i,void 0,void 0,!1,null,"15b7b770",null);e.default=l.exports}}]); \ No newline at end of file diff --git a/assets/js/40.080bf08b.js b/assets/js/40.080bf08b.js new file mode 100644 index 0000000..e94effa --- /dev/null +++ b/assets/js/40.080bf08b.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[40],{442:function(a,e,t){a.exports=t.p+"assets/img/Alert_dataframe_example.f1a8b1a2.png"},443:function(a,e,t){a.exports=t.p+"assets/img/Alert_message_example.e8176029.png"},520:function(a,e,t){"use strict";t.r(e);var s=t(10),n=Object(s.a)({},(function(){var a=this,e=a._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":a.$parent.slotKey}},[e("h1",{attrs:{id:"frontmatter-title"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[a._v("#")]),a._v(" "+a._s(a.$frontmatter.title))]),a._v(" "),e("h2",{attrs:{id:"set-up-custom-slack-alerts"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#set-up-custom-slack-alerts"}},[a._v("#")]),a._v(" Set up custom slack alerts")]),a._v(" "),e("ol",[e("li",[a._v("Follow "),e("a",{attrs:{href:"https://braincogs.github.io/software/db_access.html#db-access-for-python-repository"}},[a._v("Database Access with Python instructions")])]),a._v(" "),e("li",[a._v("On U19_pipeline_python repository open "),e("code",[a._v("u19_pipeline/alert_system/custom_alerts directory")])]),a._v(" "),e("li",[a._v("Create a new python file with a meaningful name for the alert: (e.g. "),e("code",[a._v("subject_bias.py")]),a._v(")")]),a._v(" "),e("li",[a._v("Copy skeleton code from "),e("code",[a._v("u19_pipeline/alert_system/alert_code_skeleton.py")])])]),a._v(" "),e("ul",[e("li",[a._v("All slack alert code has two parts: "),e("strong",[a._v("a slack channel configuration")]),a._v(" and a "),e("strong",[a._v("main function")]),a._v(" described on the next section:")])]),a._v(" "),e("h3",{attrs:{id:"main-function-guide"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#main-function-guide"}},[a._v("#")]),a._v(" main function guide")]),a._v(" "),e("ul",[e("li",[a._v("This function should return a pandas DataFrame where each row will be a slack alert message on configured channels.")]),a._v(" "),e("li",[a._v("You can use datajoint to get data for the alert (e.g. custom_alerts/rig_bias.py) or simply call os scripts (e.g. custom_alerts/braininit_storage.py)")]),a._v(" "),e("li",[a._v("All columns of the dataframe will be included in the alert. (Don't add too many !!)")]),a._v(" "),e("li",[a._v("Dataframe Example with slack notification message:")])]),a._v(" "),e("figure",[e("img",{attrs:{src:t(442)}}),a._v(" "),e("center",[e("figcaption",[a._v("Example Dataframe for notification ")])])],1),a._v(" "),e("figure",[e("img",{attrs:{src:t(443)}}),a._v(" "),e("center",[e("figcaption",[a._v("Example Notification from previous DataFrame")])])],1),a._v(" "),e("ul",[e("li",[a._v("You can check examples of some alers in the u19_pipeline/alert_system/custom_alerts directory")])]),a._v(" "),e("h3",{attrs:{id:"slack-channel-dictionary-configuration"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#slack-channel-dictionary-configuration"}},[a._v("#")]),a._v(" Slack channel dictionary configuration")]),a._v(" "),e("ul",[e("li",[e("p",[a._v("The slack channel configuration is a dictionary to link corresponding slack channels and conversations with an specific alert.")])]),a._v(" "),e("li",[e("p",[a._v("The dictionary has two keys: "),e("code",[a._v("'slack_notification_channel'")]),a._v(" and "),e("code",[a._v("'slack_users_channel'")])])]),a._v(" "),e("li",[e("p",[e("strong",[a._v("slack_notification_channel")]),a._v(" General channels names to send notifications.")])]),a._v(" "),e("li",[e("p",[e("strong",[a._v("slack_users_channel")]),a._v(" Private direct message to send notificatons.")])]),a._v(" "),e("li",[e("p",[a._v("You can add a list of channels to each of the keys:")])]),a._v(" "),e("li",[e("p",[e("strong",[a._v("slack_notification_channel")]),a._v(" Any "),e("code",[a._v("webhook_name")]),a._v(" (see next section)")])]),a._v(" "),e("li",[e("p",[e("strong",[a._v("slack_users_channel")]),a._v(" Any user_id with configured slack_weebhook (see next section)")])])]),a._v(" "),e("h4",{attrs:{id:"check-available-notification-channels"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#check-available-notification-channels"}},[a._v("#")]),a._v(" Check available notification channels:")]),a._v(" "),e("h5",{attrs:{id:"matlab"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#matlab"}},[a._v("#")]),a._v(" MATLAB")]),a._v(" "),e("ol",[e("li",[a._v("Execute "),e("code",[a._v("fetch(lab.SlackWebhooks,'*')")])])]),a._v(" "),e("h5",{attrs:{id:"python"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#python"}},[a._v("#")]),a._v(" Python")]),a._v(" "),e("ol",[e("li",[a._v("Execute:")])]),a._v(" "),e("ul",[e("li",[e("code",[a._v("lab = dj.create_virtual_module('lab', 'u19_lab')")])]),a._v(" "),e("li",[e("code",[a._v("lab.SlackWebhooks.fetch(as_dict=True)")])])]),a._v(" "),e("h4",{attrs:{id:"check-available-user-channels"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#check-available-user-channels"}},[a._v("#")]),a._v(" Check available user channels:")]),a._v(" "),e("h5",{attrs:{id:"matlab-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#matlab-2"}},[a._v("#")]),a._v(" MATLAB")]),a._v(" "),e("ol",[e("li",[a._v("Execute "),e("code",[a._v("fetch(lab.User & \"slack_webhook <> ''\",'slack_webhook')")])])]),a._v(" "),e("h5",{attrs:{id:"python-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#python-2"}},[a._v("#")]),a._v(" Python")]),a._v(" "),e("ol",[e("li",[a._v("Execute:")])]),a._v(" "),e("ul",[e("li",[e("code",[a._v("lab = dj.create_virtual_module('lab', 'u19_lab')")])]),a._v(" "),e("li",[e("code",[a._v("(lab.User & \"slack_webhook <> ''\").fetch('KEY', 'slack_webhook', as_dict=True)")])])]),a._v(" "),e("h3",{attrs:{id:"create-and-register-new-webhooks-for-alerts"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#create-and-register-new-webhooks-for-alerts"}},[a._v("#")]),a._v(" Create and register new webhooks for alerts:")]),a._v(" "),e("ol",[e("li",[a._v("Create a new slack channel if needed (for notification channels).")]),a._v(" "),e("li",[a._v("Follow instructions to create webhooks from: "),e("a",{attrs:{href:"https://slack.com/help/articles/115005265063-Incoming-webhooks-for-Slack"}},[a._v("Slack documentation")])]),a._v(" "),e("li",[a._v("Copy slack webhook from slack API web page.")])]),a._v(" "),e("h4",{attrs:{id:"add-notification-channels"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#add-notification-channels"}},[a._v("#")]),a._v(" Add notification channels:")]),a._v(" "),e("h5",{attrs:{id:"matlab-3"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#matlab-3"}},[a._v("#")]),a._v(" MATLAB")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("new_slack_webhook = struct\nnew_slack_webhook.webhook_name = (notification channel name)\nnew_slack_webhook.webhook_url = (webhook url from slack API)\ninsert(lab.SlackWebhooks,new_slack_webhook)\n")])])]),e("h5",{attrs:{id:"python-3"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#python-3"}},[a._v("#")]),a._v(" Python")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("lab = dj.create_virtual_module('lab', 'u19_lab')\nnew_slack_webhook = dict()\nnew_slack_webhook['webhook_name'] = (notification channel name)\nnew_slack_webhook['webhook_url'] = (webhook url from slack API)\nlab.SlackWebhooks.insert1(new_slack_webhook)\n")])])]),e("h4",{attrs:{id:"update-user-channel-webhook-notification-channels"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#update-user-channel-webhook-notification-channels"}},[a._v("#")]),a._v(" Update user channel webhook notification channels:")]),a._v(" "),e("h5",{attrs:{id:"matlab-4"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#matlab-4"}},[a._v("#")]),a._v(" MATLAB")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("user = struct\nuser.user_id = (NETID of user)\nupdate(lab.User & user,'slack_webhook', (webhook url from slack API))\n")])])]),e("h5",{attrs:{id:"python-4"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#python-4"}},[a._v("#")]),a._v(" Python")]),a._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[a._v("lab = dj.create_virtual_module('lab', 'u19_lab')\nuser = dict()\nuser['user_id'] = (NETID of user)\nuser['slack_webhook'] = (webhook url from slack API)\nlab.User.update1(user)\n")])])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/41.b5e0bbd1.js b/assets/js/41.b5e0bbd1.js new file mode 100644 index 0000000..cfcda90 --- /dev/null +++ b/assets/js/41.b5e0bbd1.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[41],{480:function(t,e,a){t.exports=a.p+"assets/img/Twolickspouts_subtask_files.971dd738.png"},481:function(t,e,a){t.exports=a.p+"assets/img/subtask_trainingGUI.339eaae6.png"},531:function(t,e,a){"use strict";a.r(e);var s=a(10),i=Object(s.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"frontmatter-title"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[t._v("#")]),t._v(" "+t._s(t.$frontmatter.title))]),t._v(" "),e("ul",[e("li",[t._v("This documentation will guide the researcher through the process of creating a new subtask pipeline.")]),t._v(" "),e("li",[t._v('Currently in BRAINCoGS data from our well known "VR Towers Task" is stored in the DB.')]),t._v(" "),e("li",[t._v("New behavior paradigms include new variables that are not included on our original design:")]),t._v(" "),e("li",[t._v("Context task")]),t._v(" "),e("li",[t._v("Doorstop task")]),t._v(" "),e("li",[t._v("Movie/Stationary task")]),t._v(" "),e("li",[t._v("This results on having only a subset of entire data stored on the DB.")]),t._v(" "),e("li",[t._v("The subtask pipeline was created to solve this issue. Its goal is to store specific subtask variables in a different subset of tables in the DB.")])]),t._v(" "),e("h2",{attrs:{id:"what-does-the-subtask-pipeline-include"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#what-does-the-subtask-pipeline-include"}},[t._v("#")]),t._v(" What does the “subtask” pipeline include:")]),t._v(" "),e("ul",[e("li",[t._v('Minimum data framework to store in a DB all relevant data from "VR Towers Task" variants.')]),t._v(" "),e("li",[t._v("Behavior integration. Training system will include the subtask as an option to be selected for a behavior session.")])]),t._v(" "),e("h2",{attrs:{id:"prerequisites"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites"}},[t._v("#")]),t._v(" Prerequisites")]),t._v(" "),e("ul",[e("li",[t._v("In order to create a new manipulation it’s assumed that:")]),t._v(" "),e("li",[t._v("The researcher is able to connect to "),e("a",{attrs:{href:"https://braincogs.github.io/software/db_access.html#db-access-for-matlab-repository"}},[t._v("datajoint00.pni.princeton.edu DB")])]),t._v(" "),e("li",[t._v("Latest version of u19_pipeline_matlab repository.")])]),t._v(" "),e("h2",{attrs:{id:"initial-set-up"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#initial-set-up"}},[t._v("#")]),t._v(" Initial set-up")]),t._v(" "),e("ul",[e("li",[t._v("Connect to database "),e("code",[t._v("connect_datajoint00")])]),t._v(" "),e("li",[t._v("Create new subtask base code (substitute subtask_name with the real name of the subtask: "),e("code",[t._v("create_new_subtask_classes('(subtask_name)')")])]),t._v(" "),e("li",[t._v("This will create table codes templates for subtask : "),e("strong",[t._v("(Subtask)Session.m, (Subtask)Block.m & (Subtask)Trial.m")]),t._v(" on the "),e("code",[t._v("U19-pipeline-matlab/schemas/+behavior_subtask")]),t._v(" directory:")]),t._v(" "),e("li",[t._v("(We will use "),e("strong",[t._v("“Twolickspouts” subtask")]),t._v(" for this example).")])]),t._v(" "),e("figure",[e("img",{attrs:{src:a(480)}}),t._v(" "),e("center",[e("figcaption",[t._v("Files created for Twolickspouts subtask on U19-pipeline-matlab/schemas/+behavior_subtask directory")])])],1),t._v(" "),e("h2",{attrs:{id:"table-description"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#table-description"}},[t._v("#")]),t._v(" Table description")]),t._v(" "),e("ul",[e("li",[t._v("Throughout the table description chapter we are going to give an example of an already working subtask pipeline. (Twolicksspouts).")])]),t._v(" "),e("h3",{attrs:{id:"task-subtask-table"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#task-subtask-table"}},[t._v("#")]),t._v(" task.Subtask table")]),t._v(" "),e("ul",[e("li",[t._v("This table registers all subtasks being created with this pipeline.")])]),t._v(" "),e("h3",{attrs:{id:"acquisition-sessionsubtask-table"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#acquisition-sessionsubtask-table"}},[t._v("#")]),t._v(" acquisition.SessionSubtask table")]),t._v(" "),e("ul",[e("li",[t._v("This table stores subtask register for a specific behavior session. This table “links” a Task.subtask table with acquisition.Sesison table.")])]),t._v(" "),e("h3",{attrs:{id:"subtask-session-table"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#subtask-session-table"}},[t._v("#")]),t._v(' "Subtask" Session table')]),t._v(" "),e("ul",[e("li",[t._v("The Session table stores related information for the entire session (review acquisition.Session for a related example).")])]),t._v(" "),e("h3",{attrs:{id:"subtask-block-table"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#subtask-block-table"}},[t._v("#")]),t._v(' "Subtask" Block table')]),t._v(" "),e("ul",[e("li",[t._v("The Block table stores related information for each block of the session (review behavior.TowersBlock for a related example).")])]),t._v(" "),e("h3",{attrs:{id:"subtask-blocktrial-table"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#subtask-blocktrial-table"}},[t._v("#")]),t._v(' "Subtask" BlockTrial table')]),t._v(" "),e("ul",[e("li",[t._v("The BlockTrial table stores related information for each trial of the session (review behavior.TowersBlockTrial for a related example).")])]),t._v(" "),e("h2",{attrs:{id:"adding-code-to-subtask-tables"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#adding-code-to-subtask-tables"}},[t._v("#")]),t._v(' Adding code to "Subtask" tables')]),t._v(" "),e("ul",[e("li",[t._v('For each subtask you can add all needed variables from the behavior file to the "Subtask" tables.')]),t._v(" "),e("li",[t._v("Example for "),e("strong",[t._v("“Twolickspouts” subtask")])])]),t._v(" "),e("h3",{attrs:{id:"twolickspoutssession-table-code"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#twolickspoutssession-table-code"}},[t._v("#")]),t._v(" TwolickspoutsSession table code")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v(" %{\n# Session level data for a twolickspouts subtask session\n-> acquisition.Session\n---\n%}\n\nclassdef TwolickspoutsSession < dj.Imported\n")])])]),e("ul",[e("li",[t._v("There is no extra field to add at session level, no code added to the file.")])]),t._v(" "),e("h3",{attrs:{id:"twolickspoutsblock-table-code"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#twolickspoutsblock-table-code"}},[t._v("#")]),t._v(" TwolickspoutsBlock table code")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("%{\n# Block level data for a twolickspouts subtask session\n-> behavior_subtask.TwolickspoutsSession\n-> acquisition.SessionBlock\n---\nsublevel : int # sublevel for the block\ntrial_params : blob # maze features of current block\n%}\n.\n.\n\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n%%%% fill here read corresponding TestSubtask data for each block\ntuple.sublevel = block_data.sublevel;\ntuple.trial_params = block_data.trialParams;\n%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")])])]),e("ul",[e("li",[t._v("In this example two fields were added to TwolickspoutsBlock table: (sublevel & trial_params)")]),t._v(" "),e("li",[t._v("Two things are needed:")])]),t._v(" "),e("ol",[e("li",[t._v("Adding them to the table definition (1st part of the code block)")]),t._v(" "),e("li",[t._v("Add how this fields are being set from "),e("strong",[t._v("block_data")]),t._v(" variable: (search for "),e("strong",[t._v("fill here")]),t._v(" section on the code). block_data has all block data from behavior file.")])]),t._v(" "),e("h3",{attrs:{id:"twolickspoutsblocktrial-table-code"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#twolickspoutsblocktrial-table-code"}},[t._v("#")]),t._v(" TwolickspoutsBlockTrial table code")]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v(" %{\n # Trial level data for a twolickspouts subtask session\n -> behavior_subtask.TwolickspoutsBlock\n -> acquisition.SessionBlockTrial\n ---\n licks : tinyblob # all iterations with lick detected and side\n trial_difficult_type : varchar(16) # trial type label (easy, medium, difficult, etc)\n forced_automatic_reward=null : tinyint # 1 if reward was forced for trial 0 otherwise\n %}\n .\n .\n %%%%%%%%%%%%%%%%%%%%%%%\n %%%% fill here read corresponding Twolickspouts data for each trial\n trial_data.licks = curr_trial.licks;\n if isfield(curr_trial, 'forced_automatic_reward')\n trial_data.forced_automatic_reward = curr_trial.forced_automatic_reward;\n else\n trial_data.forced_automatic_reward = NaN;\n end\n if isfield(curr_trial, 'trialDifficultyType')\n trial_data.trial_difficult_type = curr_trial.trialDifficultyType; \n else\n trial_data.trial_difficult_type = '';\n end\n %%%%%%%%%%%%%%%%%%%%%%%%\n")])])]),e("ul",[e("li",[t._v("In this example three fields were added to TwolickspoutsBlockTrial table: (licks & trial_difficult_type, forced_automatic_reward)")]),t._v(" "),e("li",[t._v("Two things are needed:")])]),t._v(" "),e("ol",[e("li",[t._v("Adding them to the table definition (1st part of the code block)")]),t._v(" "),e("li",[t._v("Add how this fields are being set from "),e("strong",[t._v("trial_data")]),t._v(" variable: (search for "),e("strong",[t._v("fill here")]),t._v(" section on the code). trial_data has all trial data from behavior file.")])]),t._v(" "),e("h3",{attrs:{id:"create-tables"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#create-tables"}},[t._v("#")]),t._v(" Create tables")]),t._v(" "),e("ul",[e("li",[t._v('After all code has been written on "Subtask"Session, "Subtask"Block & "Subtas"BlockTrial codebase it is needed to actually create the tables in the DB.')]),t._v(" "),e("li",[t._v("Execute: "),e("code",[t._v("create_new_subtask_tables('(subtask_name)')")])])]),t._v(" "),e("h3",{attrs:{id:"training-with-new-subtask"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#training-with-new-subtask"}},[t._v("#")]),t._v(" Training with new subtask")]),t._v(" "),e("ul",[e("li",[t._v("After all code for new sbutask has been set up and tables have been created the researcher will be able to select a specific subtask that will be associated with the schedule for a given animal. Subsequent behavior sessions will correspond to that selection.")])]),t._v(" "),e("figure",[e("img",{attrs:{src:a(481)}}),t._v(" "),e("center",[e("figcaption",[t._v("Subtask selection for a training schedule of a subject.")])])],1),t._v(" "),e("h3",{attrs:{id:"fetching-data"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#fetching-data"}},[t._v("#")]),t._v(" Fetching Data")]),t._v(" "),e("ul",[e("li",[t._v("After training has occurred all relevant data will be accessible in the corresponding tables on the behavior_subtask DB.")]),t._v(" "),e("li",[e("a",{attrs:{href:"https://docs.datajoint.org/matlab/queries/03-Fetch.html"}},[t._v("Datajoint fetch guide")])]),t._v(" "),e("li",[t._v("Example to fetch all Twolickspouts data for a single session:")])]),t._v(" "),e("div",{staticClass:"language- extra-class"},[e("pre",{pre:!0,attrs:{class:"language-text"}},[e("code",[t._v("key = struct('subject_fullname', 'testuser_T01', 'session_date', '2022-12-27')\nfetch(behavior_subtask.TwolickspoutsSession * behavior_subtask.TwolickspoutsBlock ...\n* behavior_subtask.TwolickspoutsBlockTrial & key, '*')\n\nans = \n\n 5×1 struct array with fields:\n\n subject_fullname\n session_date\n session_number\n subtask\n block\n trial_idx\n sublevel\n trial_params\n licks\n trial_difficult_type\n forced_automatic_reward\n")])])])])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/42.8fd55afd.js b/assets/js/42.8fd55afd.js new file mode 100644 index 0000000..7e0a312 --- /dev/null +++ b/assets/js/42.8fd55afd.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[42],{242:function(t,n,e){"use strict";e.d(n,"d",(function(){return r})),e.d(n,"a",(function(){return s})),e.d(n,"i",(function(){return u})),e.d(n,"f",(function(){return a})),e.d(n,"g",(function(){return l})),e.d(n,"h",(function(){return c})),e.d(n,"b",(function(){return f})),e.d(n,"e",(function(){return h})),e.d(n,"k",(function(){return p})),e.d(n,"l",(function(){return d})),e.d(n,"c",(function(){return b})),e.d(n,"j",(function(){return m}));e(90);const r=/#.*$/,i=/\.(md|html)$/,s=/\/$/,u=/^[a-z]+:/i;function o(t){return decodeURI(t).replace(r,"").replace(i,"")}function a(t){return u.test(t)}function l(t){return/^mailto:/.test(t)}function c(t){return/^tel:/.test(t)}function f(t){if(a(t))return t;const n=t.match(r),e=n?n[0]:"",i=o(t);return s.test(i)?t:i+".html"+e}function h(t,n){const e=decodeURIComponent(t.hash),i=function(t){const n=t.match(r);if(n)return n[0]}(n);if(i&&e!==i)return!1;return o(t.path)===o(n)}function p(t,n,e){if(a(n))return{type:"external",path:n};e&&(n=function(t,n,e){const r=t.charAt(0);if("/"===r)return t;if("?"===r||"#"===r)return n+t;const i=n.split("/");e&&i[i.length-1]||i.pop();const s=t.replace(/^\//,"").split("/");for(let t=0;tfunction t(n,e,r,i=1){if("string"==typeof n)return p(e,n,r);if(Array.isArray(n))return Object.assign(p(e,n[0],r),{title:n[1]});{const s=n.children||[];return 0===s.length&&n.path?Object.assign(p(e,n.path,r),{title:n.title}):{type:"group",path:n.path,title:n.title,sidebarDepth:n.sidebarDepth,initialOpenGroupIndex:n.initialOpenGroupIndex,children:s.map(n=>t(n,e,r,i+1)),collapsable:!1!==n.collapsable}}}(t,i,e)):[]}return[]}function g(t){const n=b(t.headers||[]);return[{type:"group",collapsable:!1,title:t.title,path:null,children:n.map(n=>({type:"auto",title:n.title,basePath:t.path,path:t.path+"#"+n.slug,children:n.children||[]}))}]}function b(t){let n;return(t=t.map(t=>Object.assign({},t))).forEach(t=>{2===t.level?n=t:n&&(n.children||(n.children=[])).push(t)}),t.filter(t=>2===t.level)}function m(t){return Object.assign(t,{type:t.items&&t.items.length?"links":"link"})}},244:function(t,n,e){"use strict";e.r(n);var r=e(242),i={name:"NavLink",props:{item:{required:!0}},computed:{link(){return Object(r.b)(this.item.link)},exact(){return this.$site.locales?Object.keys(this.$site.locales).some(t=>t===this.link):"/"===this.link},isNonHttpURI(){return Object(r.g)(this.link)||Object(r.h)(this.link)},isBlankTarget(){return"_blank"===this.target},isInternal(){return!Object(r.f)(this.link)&&!this.isBlankTarget},target(){return this.isNonHttpURI?null:this.item.target?this.item.target:Object(r.f)(this.link)?"_blank":""},rel(){return this.isNonHttpURI||!1===this.item.rel?null:this.item.rel?this.item.rel:this.isBlankTarget?"noopener noreferrer":null}},methods:{focusoutAction(){this.$emit("focusout")}}},s=e(10),u=Object(s.a)(i,(function(){var t=this,n=t._self._c;return t.isInternal?n("RouterLink",{staticClass:"nav-link",attrs:{to:t.link,exact:t.exact},nativeOn:{focusout:function(n){return t.focusoutAction.apply(null,arguments)}}},[t._v("\n "+t._s(t.item.text)+"\n")]):n("a",{staticClass:"nav-link external",attrs:{href:t.link,target:t.target,rel:t.rel},on:{focusout:t.focusoutAction}},[t._v("\n "+t._s(t.item.text)+"\n "),t.isBlankTarget?n("OutboundLink"):t._e()],1)}),[],!1,null,null,null);n.default=u.exports}}]); \ No newline at end of file diff --git a/assets/js/43.836fbed0.js b/assets/js/43.836fbed0.js new file mode 100644 index 0000000..86f361b --- /dev/null +++ b/assets/js/43.836fbed0.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[43],{379:function(e,t,a){e.exports=a.p+"assets/img/pupillometry-1.ffd80c5b.png"},509:function(e,t,a){"use strict";a.r(t);var o=a(10),i=Object(o.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("p",[e._v("The pupillometry module consist on a monochrome camera mounted at the side of the screen pointing laterally to the face of the mice, the lens used allows to frame the pupil with enough detail to be processed by markeless pose estimation software. The field of view obtained with the lens allows to track sniffing and whisking, altough that is out of the scope of this building guide.")]),e._v(" "),t("h2",{attrs:{id:"camera-set-up"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#camera-set-up"}},[e._v("#")]),e._v(" Camera set up")]),e._v(" "),t("p",[e._v("We use a Teledyne FLIR FFY-U3-04S2M-S camera, the small factor allows to place it right below the aluminum plate holding the screen without taking much space on the rig. We use a 0.4 MP, 121 FPS, monochromatic camera with an IR light source; a mono camera has better sensitivity and allow us to capture the details of the pupil better than the color sensor. Despite the fact that pupillometry can be detected at 30 Hz, we decided to use a 0.4 MP 121 FPS camera to have the flexibility in case we need another kind of measurement (whiskers move), but using the 1.6 MP 60 FPS camera should work fine for pupillometry and should result in a better image resolution.")]),e._v(" "),t("ol",[t("li",[e._v("Make a 1\" hole on the screen at the position showed below. If you're setting up a pupillometry module on a built screen first mark the position where the hole is going to be made, then use a precision knife to remove the outer part of the screen (make sure not to introduce the knife all the way into the other side), remove the outer part using your fingers and then use your fingers to remove the styrofoam up to the inner part of the screen (the paint layer). Then, use the precision knife to cut the paint layer in the inner part of the screen, this way the hole from the inside out will be cleaner and the smaller size possible (it will adjust to the diameter of the lens).")])]),e._v(" "),t("div",{staticClass:"custom-block tip"},[t("p",{staticClass:"custom-block-title"},[e._v("TIP")]),e._v(" "),t("p",[e._v("Despite the fact that the screen has a hole in one of the sides, we didn't observe any behavioral impact in any of the pilot -or subsequent- sessions. The position and the fact that the hole is tailored to the diameter of the lens can be the reason.")])]),e._v(" "),t("figure",[t("img",{attrs:{src:a(379)}})]),e._v(" "),t("ol",{attrs:{start:"2"}},[t("li",[e._v("Set up the camera and position it on the aluminum plate.")])]),e._v(" "),t("ol",{attrs:{start:"3"}},[t("li",[e._v("Connect it to the computer.")])]),e._v(" "),t("h2",{attrs:{id:"light-source-set-up"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#light-source-set-up"}},[e._v("#")]),e._v(" Light source set up")]),e._v(" "),t("p",[e._v("Explain how to set up the light source at the top of the rig.")]),e._v(" "),t("h2",{attrs:{id:"image-focus-and-camera-positioning"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#image-focus-and-camera-positioning"}},[e._v("#")]),e._v(" Image focus and camera positioning")]),e._v(" "),t("p",[e._v("Explain step by step how to focus the image and screw all the parts to get the camera in position.")]),e._v(" "),t("h2",{attrs:{id:"explanation-of-the-processing-and-how-to-set-up-the-pipeline"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#explanation-of-the-processing-and-how-to-set-up-the-pipeline"}},[e._v("#")]),e._v(" Explanation of the processing and how to set up the pipeline")]),e._v(" "),t("p",[e._v("Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/pupillometry_guide.html"}},[e._v(" Pupillometry Pipeline Guide ")]),e._v(" for more information.")])])}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/44.7558313c.js b/assets/js/44.7558313c.js new file mode 100644 index 0000000..a02c128 --- /dev/null +++ b/assets/js/44.7558313c.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[44],{512:function(t,n,s){"use strict";s.r(n);var e=s(10),o=Object(e.a)({},(function(){return(0,this._self._c)("ContentSlotsDistributor",{attrs:{"slot-key":this.$parent.slotKey}})}),[],!1,null,null,null);n.default=o.exports}}]); \ No newline at end of file diff --git a/assets/js/45.98c02387.js b/assets/js/45.98c02387.js new file mode 100644 index 0000000..065c57d --- /dev/null +++ b/assets/js/45.98c02387.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[45],{514:function(t,e,n){"use strict";n.r(e);var o=n(10),r=Object(o.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"frontmatter-title"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[t._v("#")]),t._v(" "+t._s(t.$frontmatter.title))]),t._v(" "),e("h2",{attrs:{id:"introduction"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),e("p",[t._v("This website is a central repository for the documentation regarding the "),e("strong",[t._v("maintenance")]),t._v(" of mini virtual reality rigs as part of BRAIN CoGS at Princeton Neuroscience Institute.")]),t._v(" "),e("p",[t._v("Maintenance documentation is also divided into modules, each module contains the process and tools needed to perform both preventive and corrective maintenance, as well as common troubleshooting.")])])}),[],!1,null,null,null);e.default=r.exports}}]); \ No newline at end of file diff --git a/assets/js/46.f7863950.js b/assets/js/46.f7863950.js new file mode 100644 index 0000000..69ac596 --- /dev/null +++ b/assets/js/46.f7863950.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[46],{515:function(e,t,r){"use strict";r.r(t);var a=r(10),i=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("h2",{attrs:{id:"_3d-printing"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_3d-printing"}},[e._v("#")]),e._v(" 3D Printing")]),e._v(" "),t("h3",{attrs:{id:"print"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#print"}},[e._v("#")]),e._v(" Print")]),e._v(" "),t("ol",[t("li",[e._v("Export 3D print design from software as STL file and make sure to select the units.")]),e._v(" "),t("li",[e._v("Use PreForm to open the STL file, use the orientation tool and generate the support structures as needed.")]),e._v(" "),t("li",[e._v("Ensure that the build platform is clean and placed correctly. Properly insert the resin tank and resin cartridge - making sure the tap is open.")]),e._v(" "),t("li",[e._v("Upload the print.")]),e._v(" "),t("li",[e._v("Printer will indicate if any component is missin, also will prompt if it needs leveling. Follow the instructions accordingly.")]),e._v(" "),t("li",[e._v("Once finished, remove the build platform and close the cover to avoid light exposure to uncured resin in the tank.")])]),e._v(" "),t("h3",{attrs:{id:"wash"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#wash"}},[e._v("#")]),e._v(" Wash")]),e._v(" "),t("ol",[t("li",[e._v("Put some gloves on. Remove the print from the platform using a scraper -or just remove the quick release platform by pushing inwards both arms.")]),e._v(" "),t("li",[e._v("Rinse the print with IPA using a squeeze bottle. You can use compressed air to remove resin from concealed areas.")]),e._v(" "),t("li",[e._v("Open the Form Wash and place the print inside.")]),e._v(" "),t("li",[e._v("Select "),t("a",{attrs:{href:"https://support.formlabs.com/s/article/Form-Wash-Time-Settings?language=en_US",target:"_blank",rel:"noopener noreferrer"}},[e._v("resin-appropiate wash cycle"),t("OutboundLink")],1),e._v(" and start.")]),e._v(" "),t("li",[e._v("Rinse additional uncured resin using the squeeze bottle and let it dry for at least 30 minutes.")])]),e._v(" "),t("h3",{attrs:{id:"cure"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#cure"}},[e._v("#")]),e._v(" Cure")]),e._v(" "),t("ol",[t("li",[e._v("Once the print is completely dry, place it inside the Form Cure and select the "),t("a",{attrs:{href:"https://support.formlabs.com/s/article/Form-Cure-Time-and-Temperature-Settings?language=en_US",target:"_blank",rel:"noopener noreferrer"}},[e._v("appropiate curing settings"),t("OutboundLink")],1),e._v(", then press start.")]),e._v(" "),t("li",[e._v("Once finished, allow the print to cool down to ambient temperature. This will avoid warping.")]),e._v(" "),t("li",[e._v("Remove the print and remove the supports.")]),e._v(" "),t("li",[e._v("Use sandpaper to remove any remaining suport marks.")])])])}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/47.58ee2c27.js b/assets/js/47.58ee2c27.js new file mode 100644 index 0000000..a6d009d --- /dev/null +++ b/assets/js/47.58ee2c27.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[47],{516:function(t,e,o){"use strict";o.r(e);var a=o(10),s=Object(a.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"frontmatter-title"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[t._v("#")]),t._v(" "+t._s(t.$frontmatter.title))]),t._v(" "),e("h1",{attrs:{id:"automated-positioning"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#automated-positioning"}},[t._v("#")]),t._v(" Automated positioning")]),t._v(" "),e("p",[t._v("The automated positioning system maintenance conssist of checking the motors and making sure everything is properly tighten (use loctite if necessary, altough it is recommended). Troubleshooting is mostly related to the motors driver.")]),t._v(" "),e("h2",{attrs:{id:"calibrating"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#calibrating"}},[t._v("#")]),t._v(" Calibrating")]),t._v(" "),e("p",[t._v("If the motors don't respond correctly, open the Zaber software. Select the 'Basic Movements' option and click on the home button. This action will take the motors to their absolute zero position.")]),t._v(" "),e("h2",{attrs:{id:"restore"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#restore"}},[t._v("#")]),t._v(" Restore")]),t._v(" "),e("p",[t._v("If sending the motors home doesn't work, the next step is to restore the affected motor. In the basic options, select the motor experiencing the issue, click on the settings icon, and choose 'Restore'.")]),t._v(" "),e("h3",{attrs:{id:"recomendation"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#recomendation"}},[t._v("#")]),t._v(" Recomendation")]),t._v(" "),e("p",[t._v("After completing the training, please send all the motors home.")]),t._v(" "),e("h1",{attrs:{id:"manual"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#manual"}},[t._v("#")]),t._v(" Manual")]),t._v(" "),e("p",[t._v("The manual positioning system is low maintenance and consist mainly of tightening the Thorlabs parts and maintening the positioning tool in shape.")])])}),[],!1,null,null,null);e.default=s.exports}}]); \ No newline at end of file diff --git a/assets/js/48.baf53650.js b/assets/js/48.baf53650.js new file mode 100644 index 0000000..a7b2764 --- /dev/null +++ b/assets/js/48.baf53650.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[48],{518:function(e,t,a){"use strict";a.r(t);var n=a(10),i=Object(n.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("p",[e._v("The reward module maintenance consist mainly on the daily cleaning of the lines and valves, valve calibration procedure done every 2 weeks and a monthly cleaning of the reward valves and replacement of the lines if using a combination of condensed milk and water (70-30).")]),e._v(" "),t("h2",{attrs:{id:"daily-clean"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#daily-clean"}},[e._v("#")]),e._v(" Daily clean")]),e._v(" "),t("p",[e._v("Follow the next procedure:")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Once the day’s training is complete, gently pull the rig’s central stage towards you, leaving some space between you and the rig’s edge. Take the reward spout out of its holding area and place it on the edge of the rig’s stage, reward spout pointed down, place a beaker under it to dispose all the liquids.")])]),e._v(" "),t("li",[t("p",[e._v("If milk was prepared that day, pour any remaining milk from the syringes into the milk bottle. Otherwise, empty all of the syringes into the beaker.")])]),e._v(" "),t("li",[t("p",[e._v("Pick up the bottle of H2O2 from the shelf labeled “Cleaning Supplies” and fill the syringe with the hydrogen peroxide up to the 40 mL line.")])]),e._v(" "),t("li",[t("p",[e._v("When ready, press the “Open Valve” button in the regiment window or open the valve using the rig tester and let the H2O2 drain into the beakers.")])]),e._v(" "),t("li",[t("p",[e._v("Once the syringes are empty, fill the syringes with 100 mL in total of distilled water and let them drain into the beakers. When the distilled water reaches the 10 mL line on the syringe, press the “Close Valve” button.")])])]),e._v(" "),t("h2",{attrs:{id:"lines-replacement-and-valve-cleaning"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#lines-replacement-and-valve-cleaning"}},[e._v("#")]),e._v(" Lines replacement and valve cleaning")]),e._v(" "),t("p",[e._v("This maintenance procedure should be done monthly if using a combination of condensed milk and water as reward during mice training, we currently don't have an accurate range for other kind of reward liquid but estimate to do it every 2 months for sucrose and water solutions and way longer for plain water.")]),e._v(" "),t("p",[e._v("Follow the procedure below.")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Remove all liquids in the circuit, first by emptying the srynge into a dispose beaker and then open the valve to realease the rest of the liquid into the same beaker.")])]),e._v(" "),t("li",[t("p",[e._v("Take off the lines from the srynge to the valve and from the valve to the spout, use those lines to measure and cut the new lines from tubing.")])]),e._v(" "),t("li",[t("p",[e._v("Follow the appropiate instructions to clean the valves, for the 003-0096-900 model from Parkerparker valves fill a srynge with hydrogen peroxide, connect it to the IN port and flush it while the valve is open, repeat the process filling the srynge with air this time.")])]),e._v(" "),t("li",[t("p",[e._v("Use a srynge to flush the spout with hydrogen peroxide, then fill the srynge with air and flush it once more.")])]),e._v(" "),t("li",[t("p",[e._v("Install a new srynge and connect the circuit with the new lines.")])])]),e._v(" "),t("h2",{attrs:{id:"valve-calibration"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#valve-calibration"}},[e._v("#")]),e._v(" Valve calibration")]),e._v(" "),t("p",[e._v("To perform the valve calibration we determine the time required to deliver 0.1 ml in total after valve opened 25 times. That is, each drop should have volume of 4 microliters. Follow the steps below.")]),e._v(" "),t("ol",[t("li",[t("p",[e._v("Gather the following materials: A one mL Eppendorf with a mark at 0.1 mL and a blunt metal tipped syringe.")])]),e._v(" "),t("li",[t("p",[e._v("Open MatLab and open the solenoidValveCalibration.m and RigParameters files.")])]),e._v(" "),t("li",[t("p",[e._v("Make sure that the spout is a vertical position at the same height as it would be with an animal, place the eppendorf under the reward spout and run the solenoid valve calibration script.")])]),e._v(" "),t("li",[t("p",[e._v("Once the run time has ended and every drop collected, use the blunt metal tipped syringe to drag any extraneous drops into the pool at the bottom of the eppendorf. If the pool of milk isn't at 0.1 ml (whether it is over or under), change the run duration time next to the command that reads “timeValveOpen =” in the Solenoid Valve Calibration window, and click “Run” when ready, keep adjusting until the pool of milk is at 0.1 mL.")])]),e._v(" "),t("li",[t("p",[e._v("Once the milk is close to the 1 ml mark, then change the value of the "),t("strong",[e._v("rewardDuration")]),e._v(" parameter in the Rig Parameters window.")])]),e._v(" "),t("li",[t("p",[e._v("Be sure to save (click Ctrl and S at the same time) what was changed in the Rig Parameters window if the run duration was changed.")])])]),e._v(" "),t("h2",{attrs:{id:"troubleshooting"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#troubleshooting"}},[e._v("#")]),e._v(" Troubleshooting")]),e._v(" "),t("p",[e._v("Troubleshooting is mostly done from top down. Check first for clogging or anything else from srynge to valve, then from valve in to valve out, then from valve out to spout, and clean or replace accordingly.")])])}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/49.5a74915a.js b/assets/js/49.5a74915a.js new file mode 100644 index 0000000..8d3e8b1 --- /dev/null +++ b/assets/js/49.5a74915a.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[49],{521:function(e,t,o){"use strict";o.r(t);var i=o(10),a=Object(i.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("ul",[t("li",[e._v("There are some processes that are triggered automatically in BRAINCoGS.")]),e._v(" "),t("li",[e._v("All these processes are handled by "),t("strong",[e._v("u19proc")]),e._v(" virtual machine administered by PNI Help. Contact Garrett T. McGrath gmcgrath@princeton.edu for permissions to it.")]),e._v(" "),t("li",[e._v("All processes are handled by "),t("strong",[e._v("u19prod")]),e._v(" user account so it's not linked to any personal account.")])]),e._v(" "),t("h2",{attrs:{id:"list-of-automate-processes-in-braincogs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#list-of-automate-processes-in-braincogs"}},[e._v("#")]),e._v(" List of automate processes in BRAINCoGS")]),e._v(" "),t("ul",[t("li",[e._v("Behavior, Manipulation, Optogenetics, Pupillometry tables ingestion")]),e._v(" "),t("li",[e._v("Alert system daily routine")]),e._v(" "),t("li",[e._v("Ephys/Imaging Automation Pipeline process")])]),e._v(" "),t("h2",{attrs:{id:"behavior-manipulation-optogenetics-pupillometry-tables-ingestion-matlab-cronjob"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#behavior-manipulation-optogenetics-pupillometry-tables-ingestion-matlab-cronjob"}},[e._v("#")]),e._v(" Behavior, Manipulation, Optogenetics, Pupillometry tables ingestion (MATLAB Cronjob)")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Execution schedule:")]),e._v(" daily at 4:00 am")]),e._v(" "),t("li",[t("strong",[e._v("Location in u19proc:")]),e._v(" /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline-matlab/scripts/call_u19_night_cronjob.sh")]),e._v(" "),t("li",[t("strong",[e._v("Overview:")]),e._v(" Call "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline-matlab/blob/master/scripts/populate_tables.m "}},[e._v(" populate_tables.m script")]),e._v(". Ingest all Behavior related tables from acquision.SessionStarted & acquisition.Session new records from that day. Check the populate_tables.m script for more information")])]),e._v(" "),t("h2",{attrs:{id:"alert-system-daily-routine"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#alert-system-daily-routine"}},[e._v("#")]),e._v(" Alert system daily routine")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Execution schedule:")]),e._v(" daily at 3:00 am")]),e._v(" "),t("li",[t("strong",[e._v("Location in u19proc:")]),e._v(" /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline_python/u19_pipeline/alert_system/call_cronjob_alert.sh")]),e._v(" "),t("li",[t("strong",[e._v("Overview:")]),e._v(" Call "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline_python/blob/master/u19_pipeline/alert_system/cronjob_alert.py "}},[e._v(" cronjob_alert.py script ")]),e._v(".")]),e._v(" "),t("li",[e._v("Read "),t("a",{attrs:{href:"https://braincogs.github.io/software/alert_system.html"}},[e._v(" Alert System section ")]),e._v(" for more information.")])]),e._v(" "),t("h2",{attrs:{id:"ephys-imaging-automation-pipeline-process"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ephys-imaging-automation-pipeline-process"}},[e._v("#")]),e._v(" Ephys/Imaging Automation Pipeline process")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Called when:")]),e._v(" at every 30th minute.")]),e._v(" "),t("li",[t("strong",[e._v("Location in u19proc:")]),e._v(" /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline_python/u19_pipeline/automatic_job/call_cronjob_automatic_job.sh")]),e._v(" "),t("li",[t("strong",[e._v("Overview:")]),e._v(" Call "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline_python/blob/masteru19_pipeline/automatic_job/cronjob_automatic_job.py"}},[e._v(" cronjob_automatic_job.py (Ephys Imaging cronjob script) ")]),e._v(". Check if a new recording has been added from "),t("a",{attrs:{href:"https://github.com/BrainCOGS/RecordingProcessJobGUI "}},[e._v(" RecordingProcessJobGUI ")]),e._v(' or a job (recording process) has advanced to a new status. If any of these have occurred the "next" function or process is called for the recording and/or job.')])]),e._v(" "),t("h2",{attrs:{id:"pupillometry-pipeline-queue-process"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#pupillometry-pipeline-queue-process"}},[e._v("#")]),e._v(" Pupillometry Pipeline Queue process")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Called when:")]),e._v(" at every 20th minute.")]),e._v(" "),t("li",[t("strong",[e._v("Location in u19proc:")]),e._v(" /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline_python/u19_pipeline/automatic_job/call_pupillometry_queue_jobs.sh")]),e._v(" "),t("li",[t("strong",[e._v("Overview:")]),e._v(" Call "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline_python/blob/master/u19_pipeline/automatic_job/pupillometry_handler.py#L256"}},[e._v(" pupillometry handler check_pupillometry_sessions_queue ")]),e._v(". Queue new job to "),t("code",[e._v("spockvm2")]),e._v(" for pupillometry session.")])]),e._v(" "),t("h2",{attrs:{id:"pupillometry-pipeline-check-process"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#pupillometry-pipeline-check-process"}},[e._v("#")]),e._v(" Pupillometry Pipeline Check process")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Called when:")]),e._v(" daily at 2:00 am")]),e._v(" "),t("li",[t("strong",[e._v("Location in u19proc:")]),e._v(" /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline_python/u19_pipeline/automatic_job/call_pupillometry_check_jobs.sh")]),e._v(" "),t("li",[t("strong",[e._v("Overview:")]),e._v(" Call "),t("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline_python/blob/master/u19_pipeline/automatic_job/pupillometry_handler.py#L338"}},[e._v(" pupillometry handler check_processed_pupillometry_sessions ")]),e._v(". Check if job in "),t("code",[e._v("spockvm2")]),e._v(" for pupillometry has finished and retrieve data to ingest in "),t("code",[e._v("pupillometry_session_model_data")]),e._v(" table.")])])])}),[],!1,null,null,null);t.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/5.6ffcefef.js b/assets/js/5.6ffcefef.js new file mode 100644 index 0000000..261f719 --- /dev/null +++ b/assets/js/5.6ffcefef.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[5],{283:function(t,e,a){},297:function(t,e,a){"use strict";a(283)},497:function(t,e,a){"use strict";a.r(e);var s={name:"CodeBlock",props:{title:{type:String,required:!0},active:{type:Boolean,default:!1}},mounted(){this.$parent&&this.$parent.loadTabs&&this.$parent.loadTabs()}},i=(a(297),a(10)),n=Object(i.a)(s,(function(){return(0,this._self._c)("div",{staticClass:"theme-code-block",class:{"theme-code-block__active":this.active}},[this._t("default")],2)}),[],!1,null,"759a7d02",null);e.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/50.557a1eb8.js b/assets/js/50.557a1eb8.js new file mode 100644 index 0000000..c8cc790 --- /dev/null +++ b/assets/js/50.557a1eb8.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[50],{524:function(t,e,a){"use strict";a.r(e);var r=a(10),n=Object(r.a)({},(function(){var t=this,e=t._self._c;return e("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[e("h1",{attrs:{id:"frontmatter-title"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[t._v("#")]),t._v(" "+t._s(t.$frontmatter.title))]),t._v(" "),e("h2",{attrs:{id:"first-steps"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#first-steps"}},[t._v("#")]),t._v(" First steps")]),t._v(" "),e("ul",[e("li",[t._v("Fill the next "),e("a",{attrs:{href:"https://frevvo-prod.princeton.edu/frevvo/web/tn/pu.nplc/u/5a6d697c-0163-4307-b751-fcc0742900a9/app/_sO14QHzSEemyQZ_M7RLPOg/formtype/_-XYdEEK2Eeqtf7JjRFmYDQ/popupform"}},[t._v("Datajoint host access form")])]),t._v(" "),e("li",[t._v("Fill the next "),e("a",{attrs:{href:"https://frevvo-prod.princeton.edu/frevvo/web/tn/pu.nplc/u/5a6d697c-0163-4307-b751-fcc0742900a9/app/_sO14QHzSEemyQZ_M7RLPOg/formtype/_b4L9oHz4EemyQZ_M7RLPOg/popupform"}},[t._v("PNI account form")])]),t._v(" "),e("li",[t._v("Clone repostiory:\n"),e("ul",[e("li",[t._v("For "),e("strong",[t._v("Python")]),t._v(": "),e("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline_python"}},[t._v("https://github.com/BrainCOGS/U19-pipeline_python")])]),t._v(" "),e("li",[t._v("For "),e("strong",[t._v("MATLAB")]),t._v(": "),e("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline-matlab"}},[t._v("https://github.com/BrainCOGS/U19-pipeline-matlab")])])])])]),t._v(" "),e("h2",{attrs:{id:"mount-file-server-volumes"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#mount-file-server-volumes"}},[t._v("#")]),t._v(" Mount file server volumes")]),t._v(" "),e("ul",[e("li",[e("p",[t._v("There are several data files (behavior, imaging & electrophysiology) that are referenced in the database")])]),t._v(" "),e("li",[e("p",[t._v("To access these files you should mount PNI file server volumes on your system.")])]),t._v(" "),e("li",[e("p",[t._v("There are three main file servers across PNI where data is stored (braininit, Bezos & u19_dj)")])])]),t._v(" "),e("h3",{attrs:{id:"on-windows-systems"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-windows-systems"}},[t._v("#")]),t._v(" On windows systems")]),t._v(" "),e("ol",[e("li",[t._v('From Windows Explorer, select "Map Network Drive" and enter:')])]),t._v(" "),e("ul",[e("li",[e("code",[t._v("\\\\cup.pni.princeton.edu\\braininit\\")]),t._v(" (for braininit)")]),t._v(" "),e("li",[e("code",[t._v("\\\\cup.pni.princeton.edu\\Bezos-center\\")]),t._v(" (for Bezos)")]),t._v(" "),e("li",[e("code",[t._v("\\\\cup.pni.princeton.edu\\u19_dj\\")]),t._v(" (for u19_dj)")])]),t._v(" "),e("ol",{attrs:{start:"2"}},[e("li",[t._v("Authenticate with your NetID and PU password (NOT your PNI password, which may be different). When prompted for your username, enter PRINCETON\\netid (note that PRINCETON can be upper or lower case) where netid is your PU NetID.")])]),t._v(" "),e("h3",{attrs:{id:"on-os-x-systems"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-os-x-systems"}},[t._v("#")]),t._v(" On OS X systems")]),t._v(" "),e("ol",[e("li",[t._v('Select "Go->Connect to Server..." from Finder and enter:')])]),t._v(" "),e("ul",[e("li",[e("code",[t._v("smb://cup.pni.princeton.edu/braininit/")]),t._v(" (for braininit)")]),t._v(" "),e("li",[e("code",[t._v("smb://cup.pni.princeton.edu/Bezos-center/")]),t._v(" (for Bezos)")]),t._v(" "),e("li",[e("code",[t._v("smb://cup.pni.princeton.edu/u19_dj/")]),t._v(" (for u19_dj)")])]),t._v(" "),e("ol",{attrs:{start:"2"}},[e("li",[t._v("Authenticate with your NetID and PU password (NOT your PNI password, which may be different).")])]),t._v(" "),e("h3",{attrs:{id:"on-linux-systems"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#on-linux-systems"}},[t._v("#")]),t._v(" On Linux systems")]),t._v(" "),e("ol",[e("li",[t._v("Follow extra steps depicted in this: "),e("a",{attrs:{href:"https://npcdocs.princeton.edu/index.php/Mounting_the_PNI_file_server_on_your_desktop"}},[t._v("link")])])]),t._v(" "),e("h2",{attrs:{id:"db-access-for-python-repository"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#db-access-for-python-repository"}},[t._v("#")]),t._v(" DB Access for Python repository")]),t._v(" "),e("h3",{attrs:{id:"prerequisites"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites"}},[t._v("#")]),t._v(" Prerequisites")]),t._v(" "),e("details",[e("summary",[t._v("Click to expand details")]),t._v(" "),e("h4",{attrs:{id:"install-an-integrated-development-environment"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#install-an-integrated-development-environment"}},[t._v("#")]),t._v(" Install an integrated development environment")]),t._v(" "),e("ul",[e("li",[e("p",[t._v("DataJoint development and use can be done with a plain text editor in the\nterminal. However, an integrated development environment (IDE) can improve your\nexperience. Several IDEs are available.")])]),t._v(" "),e("li",[e("p",[t._v("In this setup example, we will use Microsoft's Visual Studio Code.\n"),e("a",{attrs:{href:"https://code.visualstudio.com/download",target:"_blank",rel:"noopener noreferrer"}},[t._v("Installation instructions here."),e("OutboundLink")],1)])]),t._v(" "),e("li",[e("p",[t._v("Install the Jupyter extension for VS Code.")])])]),t._v(" "),e("h4",{attrs:{id:"install-a-virtual-environment"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#install-a-virtual-environment"}},[t._v("#")]),t._v(" Install a virtual environment")]),t._v(" "),e("ul",[e("li",[e("p",[t._v("A virtual environment allows you to install the packages required for a\nspecific project within an isolated environment on your computer.")])]),t._v(" "),e("li",[e("p",[t._v("It is highly recommended to create a virtual environment to run the workflow.")])]),t._v(" "),e("li",[e("p",[t._v("Conda and virtualenv are virtual environment managers and you can use either\noption. Below are the commands for Conda.")])]),t._v(" "),e("li",[e("p",[t._v("If you are setting up the pipeline on your local machine follow the instructions below for Conda. If you are using "),e("code",[t._v("spock.pni.princeton.edu")]),t._v(" or "),e("code",[t._v("scotty.pni.princeton.edu")]),t._v(", Conda is preinstalled and you can access it by running "),e("code",[t._v("module load anacondapy/2021.11")]),t._v(".")])]),t._v(" "),e("li",[e("p",[t._v("We will install Miniconda which is a minimal installer for conda.")])]),t._v(" "),e("li",[e("p",[t._v("Select the "),e("a",{attrs:{href:"https://conda.io/en/latest/miniconda.html",target:"_blank",rel:"noopener noreferrer"}},[t._v("Miniconda installer link"),e("OutboundLink")],1),t._v(" for your operating system and follow the instructions.")]),t._v(" "),e("ul",[e("li",[e("p",[t._v("You may need to add the Miniconda directory to the PATH environment\nvariable")]),t._v(" "),e("ul",[e("li",[e("p",[t._v("First locate the Miniconda directory")])]),t._v(" "),e("li",[e("p",[t._v("Then modify and run the following command")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("export")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[e("span",{pre:!0,attrs:{class:"token environment constant"}},[t._v("PATH")])]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),e("span",{pre:!0,attrs:{class:"token string"}},[t._v('"/bin:'),e("span",{pre:!0,attrs:{class:"token environment constant"}},[t._v("$PATH")]),t._v('"')]),t._v("\n")])])])])])]),t._v(" "),e("li",[e("p",[t._v("Create a new conda environment")]),t._v(" "),e("ul",[e("li",[e("p",[t._v("Type the following command into a terminal window")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("conda create "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-n")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("environment_name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("python")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("version"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n")])])])]),t._v(" "),e("li",[e("p",[t._v("Example command to create a conda environment")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("conda create "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-n")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("environment_name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token assign-left variable"}},[t._v("python")]),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),e("span",{pre:!0,attrs:{class:"token number"}},[t._v("3.9")]),t._v("\n")])])])])])]),t._v(" "),e("li",[e("p",[t._v("Activate the conda environment")]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("conda activate "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("environment_name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n")])])])])]),t._v(" "),e("h4",{attrs:{id:"other-installs"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#other-installs"}},[t._v("#")]),t._v(" Other installs")]),t._v(" "),e("ul",[e("li",[e("strong",[t._v("Git:")]),t._v(" Linux and Mac operating systems have Git preinstalled. If running in Windows get "),e("a",{attrs:{href:"https://gitforwindows.org/",target:"_blank",rel:"noopener noreferrer"}},[t._v("Git"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("li",[e("strong",[t._v("Graphviz:")]),t._v(" To display DataJoint Diagrams, "),e("a",{attrs:{href:"https://graphviz.org/download/",target:"_blank",rel:"noopener noreferrer"}},[t._v("install graphviz"),e("OutboundLink")],1),t._v(".")]),t._v(" "),e("li",[t._v("Clone the "),e("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline_python"}},[t._v("U19-pipeline_python repository")])])])])])]),t._v(" "),e("h3",{attrs:{id:"first-time-configuration"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#first-time-configuration"}},[t._v("#")]),t._v(" First time configuration")]),t._v(" "),e("ul",[e("li",[t._v("The following instructions will configure DJ and connect to DB.")])]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("conda activate "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("environment_name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v("cd")]),t._v(" U19-pipeline_python\npip "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("install")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token parameter variable"}},[t._v("-e")]),t._v(" "),e("span",{pre:!0,attrs:{class:"token builtin class-name"}},[t._v(".")]),t._v("\npython initial_conf.py\n")])])]),e("p",[t._v("(Username and password will be prompted at this moment: Princeton NETiD & NetiD password usually works)")]),t._v(" "),e("ul",[e("li",[t._v("The "),e("code",[t._v("initial_conf.py")]),t._v(" script will store a local file with credtentials to access DB and configuration variables/filepaths.")]),t._v(" "),e("li",[t._v("Now that the virtual modules are created to access the tables in the database, you can query and fetch from the database.")])]),t._v(" "),e("h3",{attrs:{id:"connection-after-configuration"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#connection-after-configuration"}},[t._v("#")]),t._v(" Connection after configuration")]),t._v(" "),e("ul",[e("li",[t._v("The following instructions will load DJ configuration and connect to DB")])]),t._v(" "),e("div",{staticClass:"language-bash extra-class"},[e("pre",{pre:!0,attrs:{class:"language-bash"}},[e("code",[t._v("conda activate "),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<")]),t._v("environment_name"),e("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v("\npython\nfrom scripts.conf_file_finding "),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("import")]),t._v(" try_find_conf_file\ntry_find_conf_file"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),e("span",{pre:!0,attrs:{class:"token function"}},[t._v("import")]),t._v(" datajoint as dj\ndj.conn"),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),e("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n")])])]),e("h2",{attrs:{id:"db-access-for-matlab-repository"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#db-access-for-matlab-repository"}},[t._v("#")]),t._v(" DB Access for MATLAB repository")]),t._v(" "),e("h3",{attrs:{id:"prerequisites-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites-2"}},[t._v("#")]),t._v(" Prerequisites")]),t._v(" "),e("details",[e("summary",[t._v("Click to expand details")]),t._v(" "),e("ul",[e("li",[t._v("Install DataJoint for MATLAB")]),t._v(" "),e("li",[t._v("Utilize MATLAB built-in GUI i.e. Top Ribbon -> Add-Ons -> Get Add-Ons")]),t._v(" "),e("li",[t._v("Search, select, and install DataJoint")]),t._v(" "),e("li",[t._v("Clone the "),e("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline-matlab"}},[t._v("U19-pipeline-matlab repository")])])])]),t._v(" "),e("h3",{attrs:{id:"first-time-configuration-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#first-time-configuration-2"}},[t._v("#")]),t._v(" First time configuration")]),t._v(" "),e("ul",[e("li",[t._v("Add this repository to MATLAB Path or cd to this repository folder.")]),t._v(" "),e("li",[t._v("Run "),e("code",[t._v("dj_initial_conf(1)")])]),t._v(" "),e("li",[t._v("Insert user and password for the DB")])]),t._v(" "),e("p",[e("strong",[t._v("Note")]),t._v(" if you are configuring repository on a public computer, there are two options:")]),t._v(" "),e("ul",[e("li",[t._v("Run"),e("code",[t._v("dj_initial_conf(0)")]),t._v(" instead, to not store user & pass in configuration file.")]),t._v(" "),e("li",[t._v("Run"),e("code",[t._v("dj_initial_conf(1)")]),t._v(" and login to the DB with a public user like u19tech.")])]),t._v(" "),e("h3",{attrs:{id:"connection-after-configuration-2"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#connection-after-configuration-2"}},[t._v("#")]),t._v(" Connection after configuration")]),t._v(" "),e("ul",[e("li",[t._v("Add this repository to MATLAB Path or cd to this repository folder.")]),t._v(" "),e("li",[e("code",[t._v("connect_datajoint00")])])]),t._v(" "),e("h2",{attrs:{id:"db-access-for-matlab-repository-cluster-computing"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#db-access-for-matlab-repository-cluster-computing"}},[t._v("#")]),t._v(" DB Access for MATLAB repository (cluster computing)")]),t._v(" "),e("h3",{attrs:{id:"prerequisites-3"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#prerequisites-3"}},[t._v("#")]),t._v(" Prerequisites")]),t._v(" "),e("details",[e("summary",[t._v("Click to expand details")]),t._v(" "),e("ul",[e("li",[t._v("Clone the "),e("a",{attrs:{href:"https://github.com/BrainCOGS/U19-pipeline-matlab"}},[t._v("U19-pipeline-matlab repository")])]),t._v(" "),e("li",[t._v("Create a directory on same location named "),e("code",[t._v("datajoint_matlab_libs")])]),t._v(" "),e("li",[t._v("Change directory to "),e("code",[t._v("datajoint_matlab_libs")]),t._v(" and clone the following repositories:\n"),e("ul",[e("li",[e("a",{attrs:{href:"https://github.com/datajoint/datajoint-matlab.git"}},[t._v("https://github.com/datajoint/datajoint-matlab.git")])]),t._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/datajoint/mym.git"}},[t._v("https://github.com/datajoint/mym.git")])]),t._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/datajoint/GHToolbox.git"}},[t._v("https://github.com/datajoint/GHToolbox.git")])]),t._v(" "),e("li",[e("a",{attrs:{href:"https://github.com/guzman-raphael/compareVersions.git"}},[t._v("https://github.com/guzman-raphael/compareVersions.git")])])])])])]),t._v(" "),e("h3",{attrs:{id:"first-time-configuration-3"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#first-time-configuration-3"}},[t._v("#")]),t._v(" First time configuration")]),t._v(" "),e("ul",[e("li",[t._v("Add this repository to MATLAB Path")]),t._v(" "),e("li",[t._v("Run "),e("code",[t._v("startup_virtual_machine.m")])]),t._v(" "),e("li",[t._v("Run "),e("code",[t._v("dj_initial_conf(1)")])]),t._v(" "),e("li",[t._v("Insert user and password for the DB")])]),t._v(" "),e("p",[e("strong",[t._v("Note")]),t._v(" if you are configuring repository on a public computer, there are two options:")]),t._v(" "),e("ul",[e("li",[t._v("Run"),e("code",[t._v("dj_initial_conf(0)")]),t._v(" instead, to not store user & pass in configuration file.")]),t._v(" "),e("li",[t._v("Run"),e("code",[t._v("dj_initial_conf(1)")]),t._v(" and login to the DB with a public user like u19tech.")])]),t._v(" "),e("h3",{attrs:{id:"connection-after-configuration-3"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#connection-after-configuration-3"}},[t._v("#")]),t._v(" Connection after configuration")]),t._v(" "),e("ul",[e("li",[t._v("Add this repository to MATLAB Path")]),t._v(" "),e("li",[t._v("Run "),e("code",[t._v("startup_virtual_machine.m")])])]),t._v(" "),e("h2",{attrs:{id:"add-researcher-to-user-table"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#add-researcher-to-user-table"}},[t._v("#")]),t._v(" Add researcher to user table")]),t._v(" "),e("ul",[e("li",[t._v("This set of instructions only apply for users that will have subjects on his/her supervision:")])]),t._v(" "),e("h3",{attrs:{id:"add-researcher-to-user-table-with-matlab"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#add-researcher-to-user-table-with-matlab"}},[t._v("#")]),t._v(" Add researcher to user table with MATLAB")]),t._v(" "),e("ul",[e("li",[t._v("Connect to DB")]),t._v(" "),e("li",[t._v("Run "),e("code",[t._v("lab.utils.add_researcher_user_table('NETID', 'full name', 'email', 'phone')")])]),t._v(" "),e("li",[e("strong",[t._v("Note:")]),t._v(" (All data in function call should be written inside quotes)")])]),t._v(" "),e("h3",{attrs:{id:"add-researcher-to-user-table-with-python"}},[e("a",{staticClass:"header-anchor",attrs:{href:"#add-researcher-to-user-table-with-python"}},[t._v("#")]),t._v(" Add researcher to user table with PYTHON")]),t._v(" "),e("ul",[e("li",[t._v("Activate conda environment and start a python command line")]),t._v(" "),e("li",[e("code",[t._v("import u19_pipeline.utils.insert_miscelaneous_db as imd")]),t._v(" "),e("code",[t._v("imd.add_researcher_user_table('NETID', 'full name', 'email', 'phone')")])]),t._v(" "),e("li",[e("strong",[t._v("Note:")]),t._v(" (All data in function call should be written inside quotes)")])])])}),[],!1,null,null,null);e.default=n.exports}}]); \ No newline at end of file diff --git a/assets/js/51.6351139d.js b/assets/js/51.6351139d.js new file mode 100644 index 0000000..a744d24 --- /dev/null +++ b/assets/js/51.6351139d.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[51],{527:function(e,t,s){"use strict";s.r(t);var a=s(10),i=Object(a.a)({},(function(){var e=this,t=e._self._c;return t("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[t("h1",{attrs:{id:"frontmatter-title"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[e._v("#")]),e._v(" "+e._s(e.$frontmatter.title))]),e._v(" "),t("ul",[t("li",[e._v("The next sections will describe all DBs on the BRAINCoGS host (datajoint00.pni.princeton.edu). DBs are subdivided in these categories:")])]),e._v(" "),t("ol",[t("li",[e._v("Lab & subject DBs")]),e._v(" "),t("li",[e._v("Behavior DBs")]),e._v(" "),t("li",[e._v("Ephys & Imaging DBs")])]),e._v(" "),t("h2",{attrs:{id:"lab-subject-dbs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#lab-subject-dbs"}},[e._v("#")]),e._v(" Lab & Subject DBs")]),e._v(" "),t("h3",{attrs:{id:"_1-u19-lab"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_1-u19-lab"}},[e._v("#")]),e._v(" "),t("strong",[e._v("1. u19_lab")])]),e._v(" "),t("ul",[t("li",[e._v("Stores all general information that apply for entire BRAINCoGS projects. Aditionally general information for researchers are stored here.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("User")]),e._v(" Stores general information for all researchers and technicians in BRAINCoGS. Being registered in this table is a requirement to add subjects in your behalf Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/db_access.html#add-researcher-to-user-table.html"}},[e._v(" here ")]),e._v(" for more information. Important fields include, user_id (NETID), active_gui_user & slack_webhook URLS for users (for notifications). Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/alert_system.html#set-up-custom-slack-alerts.html"}},[e._v(" set slack alerts ")]),e._v(" for more info.")]),e._v(" "),t("li",[t("strong",[e._v("Location")]),e._v(" All systems associated with rigs, recordings & technician use. All behavior sessions are associated with one of the systems recorded here, each recording (ephys/imaging) is associated with a system recorded here. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/db_access.html#add-researcher-to-user-table.html"}},[e._v(" here ")]),e._v(" for more information. Important fields include, user_id (NETID), active_gui_user & slack_webhook (for notifications). Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/alert_system.html#configure_systems.html"}},[e._v(" Configure systems section ")]),e._v(" for more info.")]),e._v(" "),t("li",[t("strong",[e._v("Path")]),e._v(" Paths for the cup drives in BRAINCoGS. Paths are divided by OS and local or network system types.")]),e._v(" "),t("li",[t("strong",[e._v("AcquisitionType")]),e._v(" All possible acquisitions modalities in BRAINCoGS. (Each location in Path is associated with one modality as well). Modalities include: behavior, electrophysiology, 2photon, mesoscope, etc).")]),e._v(" "),t("li",[t("strong",[e._v("DjCustomVariables")]),e._v(" Configuration variables for datajoint, mainly paths for special directories. This table is used in the background when DB access configuration is set for a system is made. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/db_access.html#db-access-for-matlab-repository"}},[e._v(" DB Access section ")])]),e._v(" "),t("li",[t("strong",[e._v("DjStores")]),e._v(" External storage path locations on the network drives (cup) for several Datajoint tables. This table is used in the background when DB access configuration is set for a system is made. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/db_access.html#db-access-for-matlab-repository"}},[e._v(" DB Access section ")])]),e._v(" "),t("li",[t("strong",[e._v("InsertionDevice")]),e._v(" Device types for insertion in subjects. (From ephys electrodes, to optogenetic cannula). Paired with u19_action.SurgeryLocation table.")]),e._v(" "),t("li",[t("strong",[e._v("SlackWebhooks")]),e._v(" Slack webhooks URLs for general notifications. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/alert_system.html#set-up-custom-slack-alerts.html"}},[e._v(" set slack alerts ")]),e._v(" for more info.")])]),e._v(" "),t("h3",{attrs:{id:"_2-u19-subject"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_2-u19-subject"}},[e._v("#")]),e._v(" "),t("strong",[e._v("2. u19_subject")])]),e._v(" "),t("ul",[t("li",[e._v("Stores all general information for subjects (mice) registered for experiments.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-2"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-2"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Subject")]),e._v(" Stores general information for all subjects in BRAINCoGS. Being registered in this table is a requirement to train and perform behavior sessions.")]),e._v(" "),t("li",[t("strong",[e._v("LickometerMotorPosition")]),e._v(" Stores ml, ap, & dv motor coordinates for a subject in a rig with positioning motor installed. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/virmen_guide.html#set-up-training"}},[e._v(" Set up motor positioning subsection ")]),e._v(" for more information.")]),e._v(" "),t("li",[t("strong",[e._v("CagingStatus")]),e._v(" Subject-Cage relationship storage.")]),e._v(" "),t("li",[t("strong",[e._v("HealthStatus")]),e._v(" Daily health assesment for subject. Fields like normal_behavior, posture_grooming, technician_comments etc.")]),e._v(" "),t("li",[t("strong",[e._v("Allele")]),e._v(" All subjects' genotypes in BRAINCoGS.")]),e._v(" "),t("li",[t("strong",[e._v("Cage")]),e._v(" Cage list for subjects.")])]),e._v(" "),t("h2",{attrs:{id:"behavior-dbs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#behavior-dbs"}},[e._v("#")]),e._v(" Behavior DBs")]),e._v(" "),t("h3",{attrs:{id:"_1-u19-acquisition"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_1-u19-acquisition"}},[e._v("#")]),e._v(" "),t("strong",[e._v("1. u19_acquisition:")])]),e._v(" "),t("ul",[t("li",[e._v("Stores all reference and general information of behavior sessions. Other tables in this DB also stores reference to blocks, trials, manipulation and subtasks of a behavior session.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-3"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-3"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("SessionStarted")]),e._v(" Reference to all sessions that are started with training GUI. Path to behavior file ia located here.")]),e._v(" "),t("li",[t("strong",[e._v("Session")]),e._v(" Basic information (performance, experiment code used, etc.) for a behavior session. Record written after training is finished")]),e._v(" "),t("li",[t("strong",[e._v("SessionBlock")]),e._v(" Basic reference to all blocks from all behavior sessions.")]),e._v(" "),t("li",[t("strong",[e._v("SessionBlockTrial")]),e._v(" Basic reference to all trials from all behavior sessions.")]),e._v(" "),t("li",[t("strong",[e._v("SessionManipulation")]),e._v(" Reference to which manipulation (if any) was performed for a behavior session. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/manipulation_pipeline.html"}},[e._v("manipulation pipeline section")]),e._v(" for more information.")]),e._v(" "),t("li",[t("strong",[e._v("SessioSubtask")]),e._v(" Reference to which subtask (if any) was performed for a behavior session. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/subtask_pipeline.html"}},[e._v("subtask pipeline section")]),e._v(" for more information.")]),e._v(" "),t("li",[t("strong",[e._v("SessionVideo")]),e._v(" Reference to video adquisition if performed while behavior session. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/pupillometry_guide.html"}},[e._v("Pupillometry Pipeline Guide")]),e._v(" for more information.")])]),e._v(" "),t("h3",{attrs:{id:"_2-u19-action"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_2-u19-action"}},[e._v("#")]),e._v(" "),t("strong",[e._v("2. u19_action:")])]),e._v(" "),t("ul",[t("li",[e._v("Stores daily, recurrent and specific actions performed to subjects.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-4"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-4"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Weighing")]),e._v(" Records daily weight of subjects. Written by weighingGUI used by technicians.")]),e._v(" "),t("li",[t("strong",[e._v("WaterAdministration")]),e._v(" Records daily water administration to subjects. Earned water written at the end of training. Supplement water Written by weighingGUI used by technicians.")]),e._v(" "),t("li",[t("strong",[e._v("Surgery")]),e._v(" Records from surgeries performed to subjects. Written by "),t("a",{attrs:{href:"https://braincogs.github.io/software/automation_pipeline.html"}},[e._v("Ephys/Imaging automation pipeline section")])]),e._v(" "),t("li",[t("strong",[e._v("SurgeryLocation")]),e._v(" Records device locations implanted to subjects from surgeries (eg. NeuroPixel probes). . Written by "),t("a",{attrs:{href:"https://braincogs.github.io/software/automation_pipeline.html"}},[e._v("Ephys/Imaging automation pipeline section")])]),e._v(" "),t("li",[t("strong",[e._v("DaiyPositionData")]),e._v(" For subjects with automatic motor positioning on rig, stores daily ml,ap & dv coordinates. If cameras are present on rig a lateral and tops reference images are also stored.")])]),e._v(" "),t("h3",{attrs:{id:"_3-u19-behavior"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_3-u19-behavior"}},[e._v("#")]),e._v(" "),t("strong",[e._v("3. u19_behavior:")])]),e._v(" "),t("ul",[t("li",[e._v("Stores detailed data for behavior sessions. DB built to support Towers Task data but stores data from all behavior sessions.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-5"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-5"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("TowersBlock")]),e._v(" Specific block data from behavior sessions. (level, main_level, block_performance, etc).")]),e._v(" "),t("li",[t("strong",[e._v("TowersBlockTrial")]),e._v(" Specific trial data from behavior sessions. (towers positions, trial_type, choice, position, velocity etc).")]),e._v(" "),t("li",[t("strong",[e._v("SpatialTimeBlobs")]),e._v(" Efficient time, position, velocity storage (per session and not by trial). Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/db_analysis.html#matlab"}},[e._v("get_full_trial_data with SpatialTimeBlobs ")]),e._v(" to know how to use this.")]),e._v(" "),t("li",[t("strong",[e._v("Towers Session/Subject ** Psych")]),e._v(" Group of tables with Psychometric Curves parameters per session, block_type (main, guiding), subject, etc. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/db_analysis.html"}},[e._v("Using psychometric data")]),e._v(" to know how to use this. Check "),t("a",{attrs:{href:"https://braincogs01.pni.princeton.edu/"}},[e._v("BRAINCoGS Data viewer ")]),e._v(" to check psychometric curves.")])]),e._v(" "),t("h3",{attrs:{id:"_4-u19-behavior-subtask"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_4-u19-behavior-subtask"}},[e._v("#")]),e._v(" "),t("strong",[e._v("4. u19_behavior_subtask:")])]),e._v(" "),t("ul",[t("li",[e._v("Stores specific data for different subtask sessions. . Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/subtask_pipeline.html"}},[e._v("subtask pipeline section")]),e._v(" for more information.")])]),e._v(" "),t("h3",{attrs:{id:"_5-u19-optogenetics"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_5-u19-optogenetics"}},[e._v("#")]),e._v(" "),t("strong",[e._v("5. u19_optogenetics")])]),e._v(" "),t("ul",[t("li",[e._v("Optogenetic manipulation data. Review "),t("a",{attrs:{href:"https://braincogs.github.io/software/manipulation_pipeline.html"}},[e._v("Manipulation pipeline section")]),e._v(" for more information and examples.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-6"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-6"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("OptogeneticSession")]),e._v(" Reference to a behavior session that is also an optogenetic session. Stores which protocol and software parameter set were used fot the session.")]),e._v(" "),t("li",[t("strong",[e._v("OptogeneticSessionTrial")]),e._v(" Stores specific optogenetic data on a trial by trial basis.")]),e._v(" "),t("li",[t("strong",[e._v("OptogeneticSoftwareParameters")]),e._v(" MATLAB Structure with parameters to be used during the behavior session specific for a subset of optogenetic sessions.")]),e._v(" "),t("li",[t("strong",[e._v("OptogeneticProtocol")]),e._v(" Describes metadata that will be associated with optogenetic sessions. (e.g. laser wavelength, stimulation frequency, etc.)")])]),e._v(" "),t("h3",{attrs:{id:"_6-u19-thermal"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_6-u19-thermal"}},[e._v("#")]),e._v(" "),t("strong",[e._v("6. u19_thermal")])]),e._v(" "),t("ul",[t("li",[e._v("Thermal manipulation data. Review "),t("a",{attrs:{href:"https://braincogs.github.io/software/manipulation_pipeline.html"}},[e._v("Manipulation pipeline section")]),e._v(" for more information and examples. Identical structure as Optogenetic DB.")])]),e._v(" "),t("h3",{attrs:{id:"_7-u19-puffs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_7-u19-puffs"}},[e._v("#")]),e._v(" "),t("strong",[e._v("7. u19_puffs")])]),e._v(" "),t("ul",[t("li",[e._v("Air puff task sessions specific data.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-7"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-7"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("PuffsSession")]),e._v(" Reference to a behavior session that is also a puff session.")]),e._v(" "),t("li",[t("strong",[e._v("PuffsSessionTrial")]),e._v(" Stores specific puffs data on a trial by trial basis.")])]),e._v(" "),t("h2",{attrs:{id:"ephys-imaging-dbs"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#ephys-imaging-dbs"}},[e._v("#")]),e._v(" Ephys/Imaging DBs")]),e._v(" "),t("h3",{attrs:{id:"_1-u19-recording"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_1-u19-recording"}},[e._v("#")]),e._v(" "),t("strong",[e._v("1. u19_recording:")])]),e._v(" "),t("ul",[t("li",[e._v("Stores all reference to any recording (ephys & imaging) performed on BRAINCoGS. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/automation_pipeline.html"}},[e._v("Automation pipeline section")]),e._v(" for more information.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-8"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-8"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Recording")]),e._v(" Reference to all recordings. Stores information like location, status_recording & recording directory on the network drives.")]),e._v(" "),t("li",[t("strong",[e._v("RecordingBehaviorSessions")]),e._v(" Relationship between recordings and behavior sessions. "),t("strong",[e._v("(recording_id <-> session_key (subject, date, #)")])]),e._v(" "),t("li",[t("strong",[e._v("RecordingRecordingSession")]),e._v(" Relationship between recordings and subject/date. Used when no behavior is attached to recording.")]),e._v(" "),t("li",[t("strong",[e._v("Modality")]),e._v(" List of all possible modalities supported by the automation pipeline.")])]),e._v(" "),t("h3",{attrs:{id:"_2-u19-recording-process"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_2-u19-recording-process"}},[e._v("#")]),e._v(" "),t("strong",[e._v("2. u19_recording_process:")])]),e._v(" "),t("ul",[t("li",[e._v("Stores all reference to all processing jobs for ephys & imaging on the automation pipeline. Almost all information in this table is shown in the "),t("a",{attrs:{href:"https://braincogs.github.io/software/automation_pipeline.html#monitor-jobs"}},[e._v("Automation pipeline GUI ")]),e._v(".")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-9"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-9"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Processing")]),e._v(" Reference to all processing jobs. For ephys it has a one to one relationship with recording probes. For imaging it has a one to one relationship with Field of View. Stores "),t("strong",[e._v("status_processing, raw_path (recording_process_pre_path), processed_path (recording_process_post_path)")]),e._v(' for each of these "fragments" of recording.')]),e._v(" "),t("li",[t("strong",[e._v("ProcessingEphysParams")]),e._v(" Relationship between jobs & which ephys processing parameters were used for that job.")]),e._v(" "),t("li",[t("strong",[e._v("ProcessingImagingParams")]),e._v(" Relationship between jobs & which imaging processing parameters were used for that job.")]),e._v(" "),t("li",[t("strong",[e._v("LogStatus")]),e._v(" Stores all status change for processing jobs and corresponding messages & exceptions if applicable.")])]),e._v(" "),t("h3",{attrs:{id:"_3-u19-ephys-pipeline"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_3-u19-ephys-pipeline"}},[e._v("#")]),e._v(" "),t("strong",[e._v("3. u19_ephys_pipeline:")])]),e._v(" "),t("ul",[t("li",[e._v("Basic reference to recordings and behavior synchronization data.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-10"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-10"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("EphysPipelineSession")]),e._v(" List of recording_ids that correspond with ephys recordings.")]),e._v(" "),t("li",[t("strong",[e._v("BehaviorSync")]),e._v(" Synchronization data between ephys recording and behavior session. "),t("strong",[e._v("trial_index_nidq & iteration_index_nidq")]),e._v(" are trial and iteration # for each sample on the electrophysiology data.")])]),e._v(" "),t("h3",{attrs:{id:"_4-u19-pipeline-ephys-element"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_4-u19-pipeline-ephys-element"}},[e._v("#")]),e._v(" "),t("strong",[e._v("4. u19_pipeline_ephys_element:")])]),e._v(" "),t("ul",[t("li",[e._v("Datajoint element array electrophysiology DB. Database schema is designed to store all data from an ephys recording and subsequent kilosort processing. More info: "),t("a",{attrs:{href:"https://datajoint.com/docs/elements/element-array-ephys/0.2/"}},[e._v("Datajoint element array electrophysiology docs")]),e._v(". For BRAINCoGS "),t("strong",[e._v("ephys_precluster")]),e._v(" schema was used.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-11"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-11"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("ClusteringParamSet")]),e._v(" Table that contains a list of parameter dictionaries/structures used for sorting process.")]),e._v(" "),t("li",[t("strong",[e._v("PreClusterparamSet")]),e._v(" Table that contains a list of parameter dictionaries/structures used for preprocessing steps.")]),e._v(" "),t("li",[t("strong",[e._v("PreClusterparamSteps")]),e._v(" Table that contains lists of lists of preCluster param Sets that form a preprocessing sequence for recordings.\npreprocessing steps. (e.g. catgt)")]),e._v(" "),t("li",[t("strong",[e._v("CuratedClusteringUnit")]),e._v(" Main data for all the units found in sorting process. ("),t("strong",[e._v("spike_times, cluster_quality_label")]),e._v(", etc.)")]),e._v(" "),t("li",[t("strong",[e._v("LFPElectrode")]),e._v(" LFP data for each of the electrodes in recording.")]),e._v(" "),t("li",[t("strong",[e._v("WaveformSetWaveform")]),e._v(" All waveforms from a unit captured by each electrode in recording.")]),e._v(" "),t("li",[t("strong",[e._v("ProbeInsertion")]),e._v(" Records which probe was used for the corresponding recording-insertion_number pair. Check "),t("strong",[e._v("5. u19_pipeline_probe_element")]),e._v(".")])]),e._v(" "),t("h3",{attrs:{id:"_5-u19-pipeline-probe-element"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_5-u19-pipeline-probe-element"}},[e._v("#")]),e._v(" "),t("strong",[e._v("5. u19_pipeline_probe_element:")])]),e._v(" "),t("ul",[t("li",[e._v("Datajoint element array electrophysiology DB for probes. Database schema is designed to store probes and electorde configurations used in recordings. More info: "),t("a",{attrs:{href:"https://datajoint.com/docs/elements/element-array-ephys/0.2/"}},[e._v("Datajoint element array electrophysiology docs")]),e._v(". For BRAINCoGS "),t("strong",[e._v("ephys_precluster")]),e._v(" schema was used.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-12"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-12"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("Probe")]),e._v(" Table that contains all physicial probes used in recordings.")]),e._v(" "),t("li",[t("strong",[e._v("ProbeTypElectrode")]),e._v(" Table that contains coordinates, shank# and id for each electrode in a probe.")])]),e._v(" "),t("h3",{attrs:{id:"_6-u19-imaging-pipeline"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_6-u19-imaging-pipeline"}},[e._v("#")]),e._v(" "),t("strong",[e._v("6. u19_imaging_pipeline:")])]),e._v(" "),t("ul",[t("li",[e._v("Reference to all imaging recordings and subsequent fields of view (FOV) identification and splitting for processing.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-13"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-13"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("ImagingPipelineSession")]),e._v(" List of recording_ids that correspond with imaging recordings.")]),e._v(" "),t("li",[t("strong",[e._v("TiffSplit")]),e._v(" Identified fields of view for a single recording (regularly 2photon = 1 FOV, mesoscope = 3 FOV). Each FOV is processed separately.")]),e._v(" "),t("li",[t("strong",[e._v("AcquiredTiff")]),e._v(" TIFF file header metadata for each FOV.")]),e._v(" "),t("li",[t("strong",[e._v("SyncImagingBehavior")]),e._v(" Synchronization data between imaging recording and behavior session. "),t("strong",[e._v("sync_behav_%%_by_im_frame")]),e._v(" = Correspoding behavior block, trial and iteration for each imaging frame.\n"),t("strong",[e._v("sync_im_frame_span_by_behav_%%")]),e._v(" = Fist and last imaging frame for each behavior block, trial and iteration.")])]),e._v(" "),t("h3",{attrs:{id:"_7-u19-pipeline-imaging-element"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_7-u19-pipeline-imaging-element"}},[e._v("#")]),e._v(" "),t("strong",[e._v("7. u19_pipeline_imaging_element:")])]),e._v(" "),t("ul",[t("li",[e._v("Datajoint element calcium imaging DB. Database schema is designed to store all data from an imaging recording and subsequent segmentation process. More info: "),t("a",{attrs:{href:"https://datajoint.com/docs/elements/element-calcium-imaging/0.5/"}},[e._v("Datajoint element calcium imaging docs")]),e._v(".")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-14"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-14"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("ProcessingParamSet")]),e._v(" Table that contains a list of parameter dictionaries/structures used for segmentation process.")]),e._v(" "),t("li",[t("strong",[e._v("ActivityTrace")]),e._v(" Activity trace signals for all masks identified in segmentation process.")]),e._v(" "),t("li",[t("strong",[e._v("FluorescenceTrace")]),e._v(" Fluorescence trace signals for all masks identified in segmentation process.")]),e._v(" "),t("li",[t("strong",[e._v("MaskClassificationMaskType")]),e._v(" Mask types (soma, blob, doughnut, etc) and confidence for each mask identified in segmentation process.")]),e._v(" "),t("li",[t("strong",[e._v("MotionCorrection(non)RigidMotionCorrection")]),e._v(" Motion correction details (shifts, outlier_frames, etc) performed durinc processing.")]),e._v(" "),t("li",[t("strong",[e._v("MotionCorrectionSummary")]),e._v(" Summary (average, correlation, max_proj) images for each field and channel after motion correction.")])]),e._v(" "),t("h3",{attrs:{id:"_8-u19-pipeline-scan-element"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_8-u19-pipeline-scan-element"}},[e._v("#")]),e._v(" "),t("strong",[e._v("8. u19_pipeline_scan_element:")])]),e._v(" "),t("ul",[t("li",[e._v("Datajoint element calcium imaging DB. Database schema is designed to store scan info and metadata from imaging files. More info: "),t("a",{attrs:{href:"https://datajoint.com/docs/elements/element-calcium-imaging/0.5/"}},[e._v("Datajoint element calcium imaging docs")]),e._v(".")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-15"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-15"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("ScanInfo")]),e._v(" Similar to "),t("strong",[e._v("u19_imaging_pipeline.Acquiredtiff")]),e._v(". General data and metadata from scans.")]),e._v(" "),t("li",[t("strong",[e._v("ScanInfoField")]),e._v(" Data specific to each of the fields of the scan.")]),e._v(" "),t("li",[t("strong",[e._v("ScanInfoScanFile")]),e._v(" All files that are part of a scan.")])]),e._v(" "),t("h3",{attrs:{id:"_9-u19-pupillometry"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#_9-u19-pupillometry"}},[e._v("#")]),e._v(" "),t("strong",[e._v("9. u19_pupillometry:")])]),e._v(" "),t("ul",[t("li",[e._v("Stores all thing related to pupillometry recordings. From reference to behavior sessions to final results. Check "),t("a",{attrs:{href:"https://braincogs.github.io/software/pupillometry_guide.html"}},[e._v(" Pupillometry Pipeline Guide ")]),e._v(" for more information.")])]),e._v(" "),t("h4",{attrs:{id:"main-tables-16"}},[t("a",{staticClass:"header-anchor",attrs:{href:"#main-tables-16"}},[e._v("#")]),e._v(" Main tables")]),e._v(" "),t("ul",[t("li",[t("strong",[e._v("PupillometrySession")]),e._v(" Reference to behavior session that had pupillometry acquisition.")]),e._v(" "),t("li",[t("strong",[e._v("PupillometryModels")]),e._v(" Training models ready to use for processing pupillometry data.")]),e._v(" "),t("li",[t("strong",[e._v("PupillometrySyncBehavior")]),e._v(" Time correspondence between each trial-iteration in behavior file and each video frame.")]),e._v(" "),t("li",[t("strong",[e._v("PupillometrySyncBehavior")]),e._v(" Time correspondence between each trial-iteration in behavior file and each video frame.")]),e._v(" "),t("li",[t("strong",[e._v("PupillometrySessionModel")]),e._v(" Reference to which model was used to process a behavior session (More than one model can be used to process data from a session).")]),e._v(" "),t("li",[t("strong",[e._v("PupillometrySessionModelData")]),e._v(" Status of pupillometry processing and final result storage.")])])])}),[],!1,null,null,null);t.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/52.9cb0c7c8.js b/assets/js/52.9cb0c7c8.js new file mode 100644 index 0000000..c54cd9c --- /dev/null +++ b/assets/js/52.9cb0c7c8.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[52],{528:function(t,o,e){"use strict";e.r(o);var n=e(10),a=Object(n.a)({},(function(){var t=this,o=t._self._c;return o("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[o("h1",{attrs:{id:"frontmatter-title"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#frontmatter-title"}},[t._v("#")]),t._v(" "+t._s(t.$frontmatter.title))]),t._v(" "),o("h2",{attrs:{id:"introduction"}},[o("a",{staticClass:"header-anchor",attrs:{href:"#introduction"}},[t._v("#")]),t._v(" Introduction")]),t._v(" "),o("p",[t._v("In this section, we will document all "),o("strong",[t._v("software and database tools and pipelines")]),t._v(" developed for BRAIN CoGS community.")]),t._v(" "),o("p",[t._v("Software documentation is divided in sections, in each section you will find the information you need to access as a user or how to modify things as a developer. Many sections will also have MATLAB and Python subsection for you to choose your preferred language.")])])}),[],!1,null,null,null);o.default=a.exports}}]); \ No newline at end of file diff --git a/assets/js/6.f914edf2.js b/assets/js/6.f914edf2.js new file mode 100644 index 0000000..95b8a81 --- /dev/null +++ b/assets/js/6.f914edf2.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[6],{284:function(e,t,a){},298:function(e,t,a){"use strict";a(284)},498:function(e,t,a){"use strict";a.r(t);var o={name:"CodeGroup",data:()=>({codeTabs:[],activeCodeTabIndex:-1}),watch:{activeCodeTabIndex(e){this.activateCodeTab(e)}},mounted(){this.loadTabs()},methods:{changeCodeTab(e){this.activeCodeTabIndex=e},loadTabs(){this.codeTabs=(this.$slots.default||[]).filter(e=>Boolean(e.componentOptions)).map((e,t)=>(""===e.componentOptions.propsData.active&&(this.activeCodeTabIndex=t),{title:e.componentOptions.propsData.title,elm:e.elm})),-1===this.activeCodeTabIndex&&this.codeTabs.length>0&&(this.activeCodeTabIndex=0),this.activateCodeTab(0)},activateCodeTab(e){this.codeTabs.forEach(e=>{e.elm&&e.elm.classList.remove("theme-code-block__active")}),this.codeTabs[e].elm&&this.codeTabs[e].elm.classList.add("theme-code-block__active")}}},s=(a(298),a(10)),c=Object(s.a)(o,(function(){var e=this,t=e._self._c;return t("ClientOnly",[t("div",{staticClass:"theme-code-group"},[t("div",{staticClass:"theme-code-group__nav"},[t("ul",{staticClass:"theme-code-group__ul"},e._l(e.codeTabs,(function(a,o){return t("li",{key:a.title,staticClass:"theme-code-group__li"},[t("button",{staticClass:"theme-code-group__nav-tab",class:{"theme-code-group__nav-tab-active":o===e.activeCodeTabIndex},on:{click:function(t){return e.changeCodeTab(o)}}},[e._v("\n "+e._s(a.title)+"\n ")])])})),0)]),e._v(" "),e._t("default"),e._v(" "),e.codeTabs.length<1?t("pre",{staticClass:"pre-blank"},[e._v("// Make sure to add code blocks to your code group")]):e._e()],2)])}),[],!1,null,"deefee04",null);t.default=c.exports}}]); \ No newline at end of file diff --git a/assets/js/7.ea5c102c.js b/assets/js/7.ea5c102c.js new file mode 100644 index 0000000..1e87141 --- /dev/null +++ b/assets/js/7.ea5c102c.js @@ -0,0 +1 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[7],{499:function(t,e,s){"use strict";s.r(e);const o=["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."];var n={methods:{getMsg:()=>o[Math.floor(Math.random()*o.length)]}},h=s(10),i=Object(h.a)(n,(function(){var t=this._self._c;return t("div",{staticClass:"theme-container"},[t("div",{staticClass:"theme-default-content"},[t("h1",[this._v("404")]),this._v(" "),t("blockquote",[this._v(this._s(this.getMsg()))]),this._v(" "),t("RouterLink",{attrs:{to:"/"}},[this._v("\n Take me home.\n ")])],1)])}),[],!1,null,null,null);e.default=i.exports}}]); \ No newline at end of file diff --git a/assets/js/app.2e1d0086.js b/assets/js/app.2e1d0086.js new file mode 100644 index 0000000..d0859a1 --- /dev/null +++ b/assets/js/app.2e1d0086.js @@ -0,0 +1,16 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[0],[]]);!function(t){function e(e){for(var r,a,s=e[0],l=e[1],u=e[2],f=0,p=[];f=e||n<0||m&&t-u>=i}function w(){var t=d();if(_(t))return x(t);s=setTimeout(w,function(t){var n=e-(t-l);return m?p(n,i-(t-u)):n}(t))}function x(t){return s=void 0,g&&r?y(t):(r=o=void 0,a)}function k(){var t=d(),n=_(t);if(r=arguments,o=this,l=t,n){if(void 0===s)return b(l);if(m)return s=setTimeout(w,e),y(l)}return void 0===s&&(s=setTimeout(w,e)),a}return e=v(e)||0,h(n)&&(c=!!n.leading,i=(m="maxWait"in n)?f(v(n.maxWait)||0,e):i,g="trailing"in n?!!n.trailing:g),k.cancel=function(){void 0!==s&&clearTimeout(s),u=0,r=l=o=s=void 0},k.flush=function(){return void 0===s?a:x(d())},k}},function(t,e,n){var r,o; +/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress + * @license MIT */void 0===(o="function"==typeof(r=function(){var t,e,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function o(t,e,n){return tn?n:t}function i(t){return 100*(-1+t)}n.configure=function(t){var e,n;for(e in t)void 0!==(n=t[e])&&t.hasOwnProperty(e)&&(r[e]=n);return this},n.status=null,n.set=function(t){var e=n.isStarted();t=o(t,r.minimum,1),n.status=1===t?null:t;var l=n.render(!e),u=l.querySelector(r.barSelector),c=r.speed,f=r.easing;return l.offsetWidth,a((function(e){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(u,function(t,e,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+i(t)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+i(t)+"%,0)"}:{"margin-left":i(t)+"%"}).transition="all "+e+"ms "+n,o}(t,c,f)),1===t?(s(l,{transition:"none",opacity:1}),l.offsetWidth,setTimeout((function(){s(l,{transition:"all "+c+"ms linear",opacity:0}),setTimeout((function(){n.remove(),e()}),c)}),c)):setTimeout(e,c)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var t=function(){setTimeout((function(){n.status&&(n.trickle(),t())}),r.trickleSpeed)};return r.trickle&&t(),this},n.done=function(t){return t||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(t){var e=n.status;return e?("number"!=typeof t&&(t=(1-e)*o(Math.random()*e,.1,.95)),e=o(e+t,0,.994),n.set(e)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},t=0,e=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===e&&n.start(),t++,e++,r.always((function(){0==--e?(t=0,n.done()):n.set((t-e)/t)})),this):this},n.render=function(t){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var e=document.createElement("div");e.id="nprogress",e.innerHTML=r.template;var o,a=e.querySelector(r.barSelector),l=t?"-100":i(n.status||0),c=document.querySelector(r.parent);return s(a,{transition:"all 0 linear",transform:"translate3d("+l+"%,0,0)"}),r.showSpinner||(o=e.querySelector(r.spinnerSelector))&&p(o),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(e),e},n.remove=function(){c(document.documentElement,"nprogress-busy"),c(document.querySelector(r.parent),"nprogress-custom-parent");var t=document.getElementById("nprogress");t&&p(t)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var t=document.body.style,e="WebkitTransform"in t?"Webkit":"MozTransform"in t?"Moz":"msTransform"in t?"ms":"OTransform"in t?"O":"";return e+"Perspective"in t?"translate3d":e+"Transform"in t?"translate":"margin"};var a=function(){var t=[];function e(){var n=t.shift();n&&n(e)}return function(n){t.push(n),1==t.length&&e()}}(),s=function(){var t=["Webkit","O","Moz","ms"],e={};function n(n){return n=n.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(t,e){return e.toUpperCase()})),e[n]||(e[n]=function(e){var n=document.body.style;if(e in n)return e;for(var r,o=t.length,i=e.charAt(0).toUpperCase()+e.slice(1);o--;)if((r=t[o]+i)in n)return r;return e}(n))}function r(t,e,r){e=n(e),t.style[e]=r}return function(t,e){var n,o,i=arguments;if(2==i.length)for(n in e)void 0!==(o=e[n])&&e.hasOwnProperty(n)&&r(t,n,o);else r(t,i[1],i[2])}}();function l(t,e){return("string"==typeof t?t:f(t)).indexOf(" "+e+" ")>=0}function u(t,e){var n=f(t),r=n+e;l(n,e)||(t.className=r.substring(1))}function c(t,e){var n,r=f(t);l(t,e)&&(n=r.replace(" "+e+" "," "),t.className=n.substring(1,n.length-1))}function f(t){return(" "+(t.className||"")+" ").replace(/\s+/gi," ")}function p(t){t&&t.parentNode&&t.parentNode.removeChild(t)}return n})?r.call(e,n,e,t):r)||(t.exports=o)},function(t,e,n){"use strict";var r=n(0),o=n(46).f,i=n(13),a=n(92),s=n(33),l=n(61),u=n(120);t.exports=function(t,e){var n,c,f,p,d,h=t.target,v=t.global,m=t.stat;if(n=v?r:m?r[h]||s(h,{}):r[h]&&r[h].prototype)for(c in e){if(p=e[c],f=t.dontCallGetSet?(d=o(n,c))&&d.value:n[c],!u(v?c:h+(m?".":"#")+c,t.forced)&&void 0!==f){if(typeof p==typeof f)continue;l(p,f)}(t.sham||f&&f.sham)&&i(p,"sham",!0),a(n,c,p,t)}}},function(t,e,n){"use strict";var r=n(26),o=Function.prototype.call;t.exports=r?o.bind(o):function(){return o.apply(o,arguments)}},function(t,e,n){"use strict";var r=n(3);t.exports=!r((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},function(t,e,n){"use strict";t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){"use strict";var r=n(47),o=n(48);t.exports=function(t){return r(o(t))}},function(t,e,n){"use strict";var r=n(0),o=n(1),i=function(t){return o(t)?t:void 0};t.exports=function(t,e){return arguments.length<2?i(r[t]):r[t]&&r[t][e]}},function(t,e,n){"use strict";var r=n(1),o=n(102),i=TypeError;t.exports=function(t){if(r(t))return t;throw new i(o(t)+" is not a function")}},function(t,e,n){"use strict";var r=n(0),o=n(56),i=n(8),a=n(58),s=n(54),l=n(53),u=r.Symbol,c=o("wks"),f=l?u.for||u:u&&u.withoutSetter||a;t.exports=function(t){return i(c,t)||(c[t]=s&&i(u,t)?u[t]:f("Symbol."+t)),c[t]}},function(t,e,n){"use strict";var r=n(57),o=n(0),i=n(33),a=t.exports=o["__core-js_shared__"]||i("__core-js_shared__",{});(a.versions||(a.versions=[])).push({version:"3.36.0",mode:r?"pure":"global",copyright:"© 2014-2024 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.36.0/LICENSE",source:"https://github.com/zloirock/core-js"})},function(t,e,n){"use strict";var r=n(0),o=Object.defineProperty;t.exports=function(t,e){try{o(r,t,{value:e,configurable:!0,writable:!0})}catch(n){r[t]=e}return e}},function(t,e,n){"use strict";var r=n(48),o=Object;t.exports=function(t){return o(r(t))}},function(t,e,n){"use strict";var r=n(7),o=String,i=TypeError;t.exports=function(t){if(r(t))return t;throw new i(o(t)+" is not an object")}},function(t,e,n){"use strict";var r=n(117);t.exports=function(t){return r(t.length)}},function(t,e,n){var r=n(144),o=n(11),i=Object.prototype,a=i.hasOwnProperty,s=i.propertyIsEnumerable,l=r(function(){return arguments}())?r:function(t){return o(t)&&a.call(t,"callee")&&!s.call(t,"callee")};t.exports=l},function(t,e,n){var r=n(9)(n(6),"Map");t.exports=r},function(t,e){t.exports=function(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}},function(t,e,n){var r=n(164),o=n(171),i=n(173),a=n(174),s=n(175);function l(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e-1&&t%1==0&&t<=9007199254740991}},function(t,e,n){var r=n(4),o=n(44),i=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,a=/^\w*$/;t.exports=function(t,e){if(r(t))return!1;var n=typeof t;return!("number"!=n&&"symbol"!=n&&"boolean"!=n&&null!=t&&!o(t))||(a.test(t)||!i.test(t)||null!=e&&t in Object(e))}},function(t,e,n){var r=n(12),o=n(11);t.exports=function(t){return"symbol"==typeof t||o(t)&&"[object Symbol]"==r(t)}},function(t,e){t.exports=function(t){return t}},function(t,e,n){"use strict";var r=n(5),o=n(25),i=n(98),a=n(27),s=n(28),l=n(50),u=n(8),c=n(59),f=Object.getOwnPropertyDescriptor;e.f=r?f:function(t,e){if(t=s(t),e=l(e),c)try{return f(t,e)}catch(t){}if(u(t,e))return a(!o(i.f,t,e),t[e])}},function(t,e,n){"use strict";var r=n(2),o=n(3),i=n(16),a=Object,s=r("".split);t.exports=o((function(){return!a("z").propertyIsEnumerable(0)}))?function(t){return"String"===i(t)?s(t,""):a(t)}:a},function(t,e,n){"use strict";var r=n(49),o=TypeError;t.exports=function(t){if(r(t))throw new o("Can't call method on "+t);return t}},function(t,e,n){"use strict";t.exports=function(t){return null==t}},function(t,e,n){"use strict";var r=n(99),o=n(51);t.exports=function(t){var e=r(t,"string");return o(e)?e:e+""}},function(t,e,n){"use strict";var r=n(29),o=n(1),i=n(52),a=n(53),s=Object;t.exports=a?function(t){return"symbol"==typeof t}:function(t){var e=r("Symbol");return o(e)&&i(e.prototype,s(t))}},function(t,e,n){"use strict";var r=n(2);t.exports=r({}.isPrototypeOf)},function(t,e,n){"use strict";var r=n(54);t.exports=r&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},function(t,e,n){"use strict";var r=n(55),o=n(3),i=n(0).String;t.exports=!!Object.getOwnPropertySymbols&&!o((function(){var t=Symbol("symbol detection");return!i(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&r&&r<41}))},function(t,e,n){"use strict";var r,o,i=n(0),a=n(100),s=i.process,l=i.Deno,u=s&&s.versions||l&&l.version,c=u&&u.v8;c&&(o=(r=c.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!o&&a&&(!(r=a.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=a.match(/Chrome\/(\d+)/))&&(o=+r[1]),t.exports=o},function(t,e,n){"use strict";var r=n(32);t.exports=function(t,e){return r[t]||(r[t]=e||{})}},function(t,e,n){"use strict";t.exports=!1},function(t,e,n){"use strict";var r=n(2),o=0,i=Math.random(),a=r(1..toString);t.exports=function(t){return"Symbol("+(void 0===t?"":t)+")_"+a(++o+i,36)}},function(t,e,n){"use strict";var r=n(5),o=n(3),i=n(104);t.exports=!r&&!o((function(){return 7!==Object.defineProperty(i("div"),"a",{get:function(){return 7}}).a}))},function(t,e,n){"use strict";t.exports={}},function(t,e,n){"use strict";var r=n(8),o=n(111),i=n(46),a=n(15);t.exports=function(t,e,n){for(var s=o(e),l=a.f,u=i.f,c=0;cc))return!1;var p=l.get(t),d=l.get(e);if(p&&d)return p==e&&d==t;var h=-1,v=!0,m=2&n?new r:void 0;for(l.set(t,e),l.set(e,t);++h-1&&t%1==0&&t]/;t.exports=function(t){var e,n=""+t,o=r.exec(n);if(!o)return n;var i="",a=0,s=0;for(a=o.index;a79&&a<83||!i("reduce")},{reduce:function(t){var e=arguments.length;return o(this,t,e,e>1?arguments[1]:void 0)}})},function(t,e,n){"use strict";var r={}.propertyIsEnumerable,o=Object.getOwnPropertyDescriptor,i=o&&!r.call({1:2},1);e.f=i?function(t){var e=o(this,t);return!!e&&e.enumerable}:r},function(t,e,n){"use strict";var r=n(25),o=n(7),i=n(51),a=n(101),s=n(103),l=n(31),u=TypeError,c=l("toPrimitive");t.exports=function(t,e){if(!o(t)||i(t))return t;var n,l=a(t,c);if(l){if(void 0===e&&(e="default"),n=r(l,t,e),!o(n)||i(n))return n;throw new u("Can't convert object to primitive value")}return void 0===e&&(e="number"),s(t,e)}},function(t,e,n){"use strict";t.exports="undefined"!=typeof navigator&&String(navigator.userAgent)||""},function(t,e,n){"use strict";var r=n(30),o=n(49);t.exports=function(t,e){var n=t[e];return o(n)?void 0:r(n)}},function(t,e,n){"use strict";var r=String;t.exports=function(t){try{return r(t)}catch(t){return"Object"}}},function(t,e,n){"use strict";var r=n(25),o=n(1),i=n(7),a=TypeError;t.exports=function(t,e){var n,s;if("string"===e&&o(n=t.toString)&&!i(s=r(n,t)))return s;if(o(n=t.valueOf)&&!i(s=r(n,t)))return s;if("string"!==e&&o(n=t.toString)&&!i(s=r(n,t)))return s;throw new a("Can't convert object to primitive value")}},function(t,e,n){"use strict";var r=n(0),o=n(7),i=r.document,a=o(i)&&o(i.createElement);t.exports=function(t){return a?i.createElement(t):{}}},function(t,e,n){"use strict";var r=n(5),o=n(3);t.exports=r&&o((function(){return 42!==Object.defineProperty((function(){}),"prototype",{value:42,writable:!1}).prototype}))},function(t,e,n){"use strict";var r=n(5),o=n(8),i=Function.prototype,a=r&&Object.getOwnPropertyDescriptor,s=o(i,"name"),l=s&&"something"===function(){}.name,u=s&&(!r||r&&a(i,"name").configurable);t.exports={EXISTS:s,PROPER:l,CONFIGURABLE:u}},function(t,e,n){"use strict";var r=n(2),o=n(1),i=n(32),a=r(Function.toString);o(i.inspectSource)||(i.inspectSource=function(t){return a(t)}),t.exports=i.inspectSource},function(t,e,n){"use strict";var r,o,i,a=n(109),s=n(0),l=n(7),u=n(13),c=n(8),f=n(32),p=n(110),d=n(60),h=s.TypeError,v=s.WeakMap;if(a||f.state){var m=f.state||(f.state=new v);m.get=m.get,m.has=m.has,m.set=m.set,r=function(t,e){if(m.has(t))throw new h("Object already initialized");return e.facade=t,m.set(t,e),e},o=function(t){return m.get(t)||{}},i=function(t){return m.has(t)}}else{var g=p("state");d[g]=!0,r=function(t,e){if(c(t,g))throw new h("Object already initialized");return e.facade=t,u(t,g,e),e},o=function(t){return c(t,g)?t[g]:{}},i=function(t){return c(t,g)}}t.exports={set:r,get:o,has:i,enforce:function(t){return i(t)?o(t):r(t,{})},getterFor:function(t){return function(e){var n;if(!l(e)||(n=o(e)).type!==t)throw new h("Incompatible receiver, "+t+" required");return n}}}},function(t,e,n){"use strict";var r=n(0),o=n(1),i=r.WeakMap;t.exports=o(i)&&/native code/.test(String(i))},function(t,e,n){"use strict";var r=n(56),o=n(58),i=r("keys");t.exports=function(t){return i[t]||(i[t]=o(t))}},function(t,e,n){"use strict";var r=n(29),o=n(2),i=n(112),a=n(119),s=n(35),l=o([].concat);t.exports=r("Reflect","ownKeys")||function(t){var e=i.f(s(t)),n=a.f;return n?l(e,n(t)):e}},function(t,e,n){"use strict";var r=n(113),o=n(118).concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return r(t,o)}},function(t,e,n){"use strict";var r=n(2),o=n(8),i=n(28),a=n(114).indexOf,s=n(60),l=r([].push);t.exports=function(t,e){var n,r=i(t),u=0,c=[];for(n in r)!o(s,n)&&o(r,n)&&l(c,n);for(;e.length>u;)o(r,n=e[u++])&&(~a(c,n)||l(c,n));return c}},function(t,e,n){"use strict";var r=n(28),o=n(115),i=n(36),a=function(t){return function(e,n,a){var s=r(e),l=i(s);if(0===l)return!t&&-1;var u,c=o(a,l);if(t&&n!=n){for(;l>c;)if((u=s[c++])!=u)return!0}else for(;l>c;c++)if((t||c in s)&&s[c]===n)return t||c||0;return!t&&-1}};t.exports={includes:a(!0),indexOf:a(!1)}},function(t,e,n){"use strict";var r=n(62),o=Math.max,i=Math.min;t.exports=function(t,e){var n=r(t);return n<0?o(n+e,0):i(n,e)}},function(t,e,n){"use strict";var r=Math.ceil,o=Math.floor;t.exports=Math.trunc||function(t){var e=+t;return(e>0?o:r)(e)}},function(t,e,n){"use strict";var r=n(62),o=Math.min;t.exports=function(t){var e=r(t);return e>0?o(e,9007199254740991):0}},function(t,e,n){"use strict";t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},function(t,e,n){"use strict";e.f=Object.getOwnPropertySymbols},function(t,e,n){"use strict";var r=n(3),o=n(1),i=/#|\.prototype\./,a=function(t,e){var n=l[s(t)];return n===c||n!==u&&(o(e)?r(e):!!e)},s=a.normalize=function(t){return String(t).replace(i,".").toLowerCase()},l=a.data={},u=a.NATIVE="N",c=a.POLYFILL="P";t.exports=a},function(t,e,n){"use strict";var r=n(30),o=n(34),i=n(47),a=n(36),s=TypeError,l="Reduce of empty array with no initial value",u=function(t){return function(e,n,u,c){var f=o(e),p=i(f),d=a(f);if(r(n),0===d&&u<2)throw new s(l);var h=t?d-1:0,v=t?-1:1;if(u<2)for(;;){if(h in p){c=p[h],h+=v;break}if(h+=v,t?h<0:d<=h)throw new s(l)}for(;t?h>=0:d>h;h+=v)h in p&&(c=n(c,p[h],h,f));return c}};t.exports={left:u(!1),right:u(!0)}},function(t,e,n){"use strict";var r=n(3);t.exports=function(t,e){var n=[][t];return!!n&&r((function(){n.call(null,e||function(){return 1},1)}))}},function(t,e,n){"use strict";var r=n(0),o=n(16);t.exports="process"===o(r.process)},function(t,e,n){"use strict";var r=n(24),o=n(0),i=n(125),a=n(126),s=o.WebAssembly,l=7!==new Error("e",{cause:7}).cause,u=function(t,e){var n={};n[t]=a(t,e,l),r({global:!0,constructor:!0,arity:1,forced:l},n)},c=function(t,e){if(s&&s[t]){var n={};n[t]=a("WebAssembly."+t,e,l),r({target:"WebAssembly",stat:!0,constructor:!0,arity:1,forced:l},n)}};u("Error",(function(t){return function(e){return i(t,this,arguments)}})),u("EvalError",(function(t){return function(e){return i(t,this,arguments)}})),u("RangeError",(function(t){return function(e){return i(t,this,arguments)}})),u("ReferenceError",(function(t){return function(e){return i(t,this,arguments)}})),u("SyntaxError",(function(t){return function(e){return i(t,this,arguments)}})),u("TypeError",(function(t){return function(e){return i(t,this,arguments)}})),u("URIError",(function(t){return function(e){return i(t,this,arguments)}})),c("CompileError",(function(t){return function(e){return i(t,this,arguments)}})),c("LinkError",(function(t){return function(e){return i(t,this,arguments)}})),c("RuntimeError",(function(t){return function(e){return i(t,this,arguments)}}))},function(t,e,n){"use strict";var r=n(26),o=Function.prototype,i=o.apply,a=o.call;t.exports="object"==typeof Reflect&&Reflect.apply||(r?a.bind(i):function(){return a.apply(i,arguments)})},function(t,e,n){"use strict";var r=n(29),o=n(8),i=n(13),a=n(52),s=n(63),l=n(61),u=n(130),c=n(131),f=n(132),p=n(135),d=n(136),h=n(5),v=n(57);t.exports=function(t,e,n,m){var g=m?2:1,y=t.split("."),b=y[y.length-1],_=r.apply(null,y);if(_){var w=_.prototype;if(!v&&o(w,"cause")&&delete w.cause,!n)return _;var x=r("Error"),k=e((function(t,e){var n=f(m?e:t,void 0),r=m?new _(t):new _;return void 0!==n&&i(r,"message",n),d(r,k,r.stack,2),this&&a(w,this)&&c(r,this,k),arguments.length>g&&p(r,arguments[g]),r}));if(k.prototype=w,"Error"!==b?s?s(k,x):l(k,x,{name:!0}):h&&"stackTraceLimit"in _&&(u(k,_,"stackTraceLimit"),u(k,_,"prepareStackTrace")),l(k,_),!v)try{w.name!==b&&i(w,"name",b),w.constructor=k}catch(t){}return k}}},function(t,e,n){"use strict";var r=n(2),o=n(30);t.exports=function(t,e,n){try{return r(o(Object.getOwnPropertyDescriptor(t,e)[n]))}catch(t){}}},function(t,e,n){"use strict";var r=n(129),o=String,i=TypeError;t.exports=function(t){if(r(t))return t;throw new i("Can't set "+o(t)+" as a prototype")}},function(t,e,n){"use strict";var r=n(7);t.exports=function(t){return r(t)||null===t}},function(t,e,n){"use strict";var r=n(15).f;t.exports=function(t,e,n){n in t||r(t,n,{configurable:!0,get:function(){return e[n]},set:function(t){e[n]=t}})}},function(t,e,n){"use strict";var r=n(1),o=n(7),i=n(63);t.exports=function(t,e,n){var a,s;return i&&r(a=e.constructor)&&a!==n&&o(s=a.prototype)&&s!==n.prototype&&i(t,s),t}},function(t,e,n){"use strict";var r=n(93);t.exports=function(t,e){return void 0===t?arguments.length<2?"":e:r(t)}},function(t,e,n){"use strict";var r=n(134),o=n(1),i=n(16),a=n(31)("toStringTag"),s=Object,l="Arguments"===i(function(){return arguments}());t.exports=r?i:function(t){var e,n,r;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=function(t,e){try{return t[e]}catch(t){}}(e=s(t),a))?n:l?i(e):"Object"===(r=i(e))&&o(e.callee)?"Arguments":r}},function(t,e,n){"use strict";var r={};r[n(31)("toStringTag")]="z",t.exports="[object z]"===String(r)},function(t,e,n){"use strict";var r=n(7),o=n(13);t.exports=function(t,e){r(e)&&"cause"in e&&o(t,"cause",e.cause)}},function(t,e,n){"use strict";var r=n(13),o=n(137),i=n(138),a=Error.captureStackTrace;t.exports=function(t,e,n,s){i&&(a?a(t,e):r(t,"stack",o(n,s)))}},function(t,e,n){"use strict";var r=n(2),o=Error,i=r("".replace),a=String(new o("zxcasd").stack),s=/\n\s*at [^:]*:[^\n]*/,l=s.test(a);t.exports=function(t,e){if(l&&"string"==typeof t&&!o.prepareStackTrace)for(;e--;)t=i(t,s,"");return t}},function(t,e,n){"use strict";var r=n(3),o=n(27);t.exports=!r((function(){var t=new Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",o(1,7)),7!==t.stack)}))},function(t,e,n){"use strict";var r=n(5),o=n(140),i=TypeError,a=Object.getOwnPropertyDescriptor,s=r&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(t){return t instanceof TypeError}}();t.exports=s?function(t,e){if(o(t)&&!a(t,"length").writable)throw new i("Cannot set read only .length");return t.length=e}:function(t,e){return t.length=e}},function(t,e,n){"use strict";var r=n(16);t.exports=Array.isArray||function(t){return"Array"===r(t)}},function(t,e,n){"use strict";var r=TypeError;t.exports=function(t){if(t>9007199254740991)throw r("Maximum allowed index exceeded");return t}},function(t,e,n){var r=n(64),o=n(143);t.exports=function t(e,n,i,a,s){var l=-1,u=e.length;for(i||(i=o),s||(s=[]);++l0&&i(c)?n>1?t(c,n-1,i,a,s):r(s,c):a||(s[s.length]=c)}return s}},function(t,e,n){var r=n(14),o=n(37),i=n(4),a=r?r.isConcatSpreadable:void 0;t.exports=function(t){return i(t)||o(t)||!!(a&&t&&t[a])}},function(t,e,n){var r=n(12),o=n(11);t.exports=function(t){return o(t)&&"[object Arguments]"==r(t)}},function(t,e,n){var r=n(14),o=Object.prototype,i=o.hasOwnProperty,a=o.toString,s=r?r.toStringTag:void 0;t.exports=function(t){var e=i.call(t,s),n=t[s];try{t[s]=void 0;var r=!0}catch(t){}var o=a.call(t);return r&&(e?t[s]=n:delete t[s]),o}},function(t,e){var n=Object.prototype.toString;t.exports=function(t){return n.call(t)}},function(t,e,n){var r=n(148),o=n(204),i=n(45),a=n(4),s=n(214);t.exports=function(t){return"function"==typeof t?t:null==t?i:"object"==typeof t?a(t)?o(t[0],t[1]):r(t):s(t)}},function(t,e,n){var r=n(149),o=n(203),i=n(82);t.exports=function(t){var e=o(t);return 1==e.length&&e[0][2]?i(e[0][0],e[0][1]):function(n){return n===t||r(n,t,e)}}},function(t,e,n){var r=n(66),o=n(70);t.exports=function(t,e,n,i){var a=n.length,s=a,l=!i;if(null==t)return!s;for(t=Object(t);a--;){var u=n[a];if(l&&u[2]?u[1]!==t[u[0]]:!(u[0]in t))return!1}for(;++a-1}},function(t,e,n){var r=n(18);t.exports=function(t,e){var n=this.__data__,o=r(n,t);return o<0?(++this.size,n.push([t,e])):n[o][1]=e,this}},function(t,e,n){var r=n(17);t.exports=function(){this.__data__=new r,this.size=0}},function(t,e){t.exports=function(t){var e=this.__data__,n=e.delete(t);return this.size=e.size,n}},function(t,e){t.exports=function(t){return this.__data__.get(t)}},function(t,e){t.exports=function(t){return this.__data__.has(t)}},function(t,e,n){var r=n(17),o=n(38),i=n(40);t.exports=function(t,e){var n=this.__data__;if(n instanceof r){var a=n.__data__;if(!o||a.length<199)return a.push([t,e]),this.size=++n.size,this;n=this.__data__=new i(a)}return n.set(t,e),this.size=n.size,this}},function(t,e,n){var r=n(68),o=n(161),i=n(39),a=n(69),s=/^\[object .+?Constructor\]$/,l=Function.prototype,u=Object.prototype,c=l.toString,f=u.hasOwnProperty,p=RegExp("^"+c.call(f).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");t.exports=function(t){return!(!i(t)||o(t))&&(r(t)?p:s).test(a(t))}},function(t,e,n){var r,o=n(162),i=(r=/[^.]+$/.exec(o&&o.keys&&o.keys.IE_PROTO||""))?"Symbol(src)_1."+r:"";t.exports=function(t){return!!i&&i in t}},function(t,e,n){var r=n(6)["__core-js_shared__"];t.exports=r},function(t,e){t.exports=function(t,e){return null==t?void 0:t[e]}},function(t,e,n){var r=n(165),o=n(17),i=n(38);t.exports=function(){this.size=0,this.__data__={hash:new r,map:new(i||o),string:new r}}},function(t,e,n){var r=n(166),o=n(167),i=n(168),a=n(169),s=n(170);function l(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e0){if(++e>=800)return arguments[0]}else e=0;return t.apply(void 0,arguments)}}},function(t,e,n){var r=n(72),o=n(226),i=n(231),a=n(73),s=n(232),l=n(41);t.exports=function(t,e,n){var u=-1,c=o,f=t.length,p=!0,d=[],h=d;if(n)p=!1,c=i;else if(f>=200){var v=e?null:s(t);if(v)return l(v);p=!1,c=a,h=new r}else h=e?[]:d;t:for(;++u-1}},function(t,e,n){var r=n(228),o=n(229),i=n(230);t.exports=function(t,e,n){return e==e?i(t,e,n):r(t,o,n)}},function(t,e){t.exports=function(t,e,n,r){for(var o=t.length,i=n+(r?1:-1);r?i--:++i=0&&Math.floor(e)===e&&isFinite(t)}function v(t){return a(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function m(t){return null==t?"":Array.isArray(t)||p(t)&&t.toString===f?JSON.stringify(t,g,2):String(t)}function g(t,e){return e&&e.__v_isRef?e.value:e}function y(t){var e=parseFloat(t);return isNaN(e)?t:e}function b(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(r,1)}}var x=Object.prototype.hasOwnProperty;function k(t,e){return x.call(t,e)}function S(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var C=/-(\w)/g,O=S((function(t){return t.replace(C,(function(t,e){return e?e.toUpperCase():""}))})),j=S((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),$=/\B([A-Z])/g,E=S((function(t){return t.replace($,"-$1").toLowerCase()}));var P=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function A(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function T(t,e){for(var n in e)t[n]=e[n];return t}function L(t){for(var e={},n=0;n0,Q=X&&X.indexOf("edge/")>0;X&&X.indexOf("android");var tt=X&&/iphone|ipad|ipod|ios/.test(X);X&&/chrome\/\d+/.test(X),X&&/phantomjs/.test(X);var et,nt=X&&X.match(/firefox\/(\d+)/),rt={}.watch,ot=!1;if(Y)try{var it={};Object.defineProperty(it,"passive",{get:function(){ot=!0}}),window.addEventListener("test-passive",null,it)}catch(t){}var at=function(){return void 0===et&&(et=!Y&&"undefined"!=typeof global&&(global.process&&"server"===global.process.env.VUE_ENV)),et},st=Y&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function lt(t){return"function"==typeof t&&/native code/.test(t.toString())}var ut,ct="undefined"!=typeof Symbol&<(Symbol)&&"undefined"!=typeof Reflect&<(Reflect.ownKeys);ut="undefined"!=typeof Set&<(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var ft=null;function pt(t){void 0===t&&(t=null),t||ft&&ft._scope.off(),ft=t,t&&t._scope.on()}var dt=function(){function t(t,e,n,r,o,i,a,s){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=o,this.ns=void 0,this.context=i,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1}return Object.defineProperty(t.prototype,"child",{get:function(){return this.componentInstance},enumerable:!1,configurable:!0}),t}(),ht=function(t){void 0===t&&(t="");var e=new dt;return e.text=t,e.isComment=!0,e};function vt(t){return new dt(void 0,void 0,void 0,String(t))}function mt(t){var e=new dt(t.tag,t.data,t.children&&t.children.slice(),t.text,t.elm,t.context,t.componentOptions,t.asyncFactory);return e.ns=t.ns,e.isStatic=t.isStatic,e.key=t.key,e.isComment=t.isComment,e.fnContext=t.fnContext,e.fnOptions=t.fnOptions,e.fnScopeId=t.fnScopeId,e.asyncMeta=t.asyncMeta,e.isCloned=!0,e}"function"==typeof SuppressedError&&SuppressedError;var gt=0,yt=[],bt=function(){function t(){this._pending=!1,this.id=gt++,this.subs=[]}return t.prototype.addSub=function(t){this.subs.push(t)},t.prototype.removeSub=function(t){this.subs[this.subs.indexOf(t)]=null,this._pending||(this._pending=!0,yt.push(this))},t.prototype.depend=function(e){t.target&&t.target.addDep(this)},t.prototype.notify=function(t){var e=this.subs.filter((function(t){return t}));for(var n=0,r=e.length;n0&&(Xt((u=t(u,"".concat(n||"","_").concat(r)))[0])&&Xt(f)&&(p[c]=vt(f.text+u[0].text),u.shift()),p.push.apply(p,u)):l(u)?Xt(f)?p[c]=vt(f.text+u):""!==u&&p.push(vt(u)):Xt(u)&&Xt(f)?p[c]=vt(f.text+u.text):(s(e._isVList)&&a(u.tag)&&i(u.key)&&a(n)&&(u.key="__vlist".concat(n,"_").concat(r,"__")),p.push(u)));return p}(t):void 0}function Xt(t){return a(t)&&a(t.text)&&!1===t.isComment}function Jt(t,e){var n,r,i,s,l=null;if(o(t)||"string"==typeof t)for(l=new Array(t.length),n=0,r=t.length;n0,s=e?!!e.$stable:!a,l=e&&e.$key;if(e){if(e._normalized)return e._normalized;if(s&&o&&o!==r&&l===o.$key&&!a&&!o.$hasNormal)return o;for(var u in i={},e)e[u]&&"$"!==u[0]&&(i[u]=me(t,n,u,e[u]))}else i={};for(var c in n)c in i||(i[c]=ge(n,c));return e&&Object.isExtensible(e)&&(e._normalized=i),W(i,"$stable",s),W(i,"$key",l),W(i,"$hasNormal",a),i}function me(t,e,n,r){var i=function(){var e=ft;pt(t);var n=arguments.length?r.apply(null,arguments):r({}),i=(n=n&&"object"==typeof n&&!o(n)?[n]:Yt(n))&&n[0];return pt(e),n&&(!i||1===n.length&&i.isComment&&!he(i))?void 0:n};return r.proxy&&Object.defineProperty(e,n,{get:i,enumerable:!0,configurable:!0}),i}function ge(t,e){return function(){return t[e]}}function ye(t){return{get attrs(){if(!t._attrsProxy){var e=t._attrsProxy={};W(e,"_v_attr_proxy",!0),be(e,t.$attrs,r,t,"$attrs")}return t._attrsProxy},get listeners(){t._listenersProxy||be(t._listenersProxy={},t.$listeners,r,t,"$listeners");return t._listenersProxy},get slots(){return function(t){t._slotsProxy||we(t._slotsProxy={},t.$scopedSlots);return t._slotsProxy}(t)},emit:P(t.$emit,t),expose:function(e){e&&Object.keys(e).forEach((function(n){return Ut(t,e,n)}))}}}function be(t,e,n,r,o){var i=!1;for(var a in e)a in t?e[a]!==n[a]&&(i=!0):(i=!0,_e(t,a,r,o));for(var a in t)a in e||(i=!0,delete t[a]);return i}function _e(t,e,n,r){Object.defineProperty(t,e,{enumerable:!0,configurable:!0,get:function(){return n[r][e]}})}function we(t,e){for(var n in e)t[n]=e[n];for(var n in t)n in e||delete t[n]}var xe=null;function ke(t,e){return(t.__esModule||ct&&"Module"===t[Symbol.toStringTag])&&(t=t.default),c(t)?e.extend(t):t}function Se(t){if(o(t))for(var e=0;edocument.createEvent("Event").timeStamp&&(un=function(){return cn.now()})}var fn=function(t,e){if(t.post){if(!e.post)return 1}else if(e.post)return-1;return t.id-e.id};function pn(){var t,e;for(ln=un(),an=!0,en.sort(fn),sn=0;snsn&&en[n].id>t.id;)n--;en.splice(n+1,0,t)}else en.push(t);on||(on=!0,Ne(pn))}}function hn(t,e){if(t){for(var n=Object.create(null),r=ct?Reflect.ownKeys(t):Object.keys(t),o=0;o-1)if(i&&!k(o,"default"))a=!1;else if(""===a||a===E(t)){var l=Mn(String,o.type);(l<0||s-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!d(t)&&t.test(e)}function Jn(t,e){var n=t.cache,r=t.keys,o=t._vnode,i=t.$vnode;for(var a in n){var s=n[a];if(s){var l=s.name;l&&!e(l)&&Zn(n,a,r,o)}}i.componentOptions.children=void 0}function Zn(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,w(n,e)}Gn.prototype._init=function(t){var e=this;e._uid=Vn++,e._isVue=!0,e.__v_skip=!0,e._scope=new Ft(!0),e._scope.parent=void 0,e._scope._vm=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=Pn(Wn(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._provided=n?n._provided:Object.create(null),t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Ye(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,n=t.$vnode=e._parentVnode,o=n&&n.context;t.$slots=pe(e._renderChildren,o),t.$scopedSlots=n?ve(t.$parent,n.data.scopedSlots,t.$slots):r,t._c=function(e,n,r,o){return Ce(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return Ce(t,e,n,r,o,!0)};var i=n&&n.data;Tt(t,"$attrs",i&&i.attrs||r,null,!0),Tt(t,"$listeners",e._parentListeners||r,null,!0)}(e),tn(e,"beforeCreate",void 0,!1),function(t){var e=hn(t.$options.inject,t);e&&($t(!1),Object.keys(e).forEach((function(n){Tt(t,n,e[n])})),$t(!0))}(e),Nn(e),function(t){var e=t.$options.provide;if(e){var n=u(e)?e.call(t):e;if(!c(n))return;for(var r=Ht(t),o=ct?Reflect.ownKeys(n):Object.keys(n),i=0;i1?A(n):n;for(var r=A(arguments,1),o='event handler for "'.concat(t,'"'),i=0,a=n.length;iparseInt(this.max)&&Zn(t,e[0],e,this._vnode),this.vnodeToCache=null}}},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)Zn(this.cache,t,this.keys)},mounted:function(){var t=this;this.cacheVNode(),this.$watch("include",(function(e){Jn(t,(function(t){return Xn(e,t)}))})),this.$watch("exclude",(function(e){Jn(t,(function(t){return!Xn(e,t)}))}))},updated:function(){this.cacheVNode()},render:function(){var t=this.$slots.default,e=Se(t),n=e&&e.componentOptions;if(n){var r=Yn(n),o=this.include,i=this.exclude;if(o&&(!r||!Xn(o,r))||i&&r&&Xn(i,r))return e;var a=this.cache,s=this.keys,l=null==e.key?n.Ctor.cid+(n.tag?"::".concat(n.tag):""):e.key;a[l]?(e.componentInstance=a[l].componentInstance,w(s,l),s.push(l)):(this.vnodeToCache=e,this.keyToCache=l),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return H}};Object.defineProperty(t,"config",e),t.util={warn:kn,extend:T,mergeOptions:Pn,defineReactive:Tt},t.set=Lt,t.delete=Rt,t.nextTick=Ne,t.observable=function(t){return At(t),t},t.options=Object.create(null),B.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,T(t.options.components,tr),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=A(arguments,1);return n.unshift(this),u(t.install)?t.install.apply(t,n):u(t)&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Pn(this.options,t),this}}(t),Kn(t),function(t){B.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&p(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&u(n)&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(Gn),Object.defineProperty(Gn.prototype,"$isServer",{get:at}),Object.defineProperty(Gn.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(Gn,"FunctionalRenderContext",{value:vn}),Gn.version="2.7.16";var er=b("style,class"),nr=b("input,textarea,option,select,progress"),rr=b("contenteditable,draggable,spellcheck"),or=b("events,caret,typing,plaintext-only"),ir=b("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,truespeed,typemustmatch,visible"),ar="http://www.w3.org/1999/xlink",sr=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},lr=function(t){return sr(t)?t.slice(6,t.length):""},ur=function(t){return null==t||!1===t};function cr(t){for(var e=t.data,n=t,r=t;a(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(e=fr(r.data,e));for(;a(n=n.parent);)n&&n.data&&(e=fr(e,n.data));return function(t,e){if(a(t)||a(e))return pr(t,dr(e));return""}(e.staticClass,e.class)}function fr(t,e){return{staticClass:pr(t.staticClass,e.staticClass),class:a(t.class)?[t.class,e.class]:e.class}}function pr(t,e){return t?e?t+" "+e:t:e||""}function dr(t){return Array.isArray(t)?function(t){for(var e,n="",r=0,o=t.length;r-1?Ir(t,e,n):ir(e)?ur(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):rr(e)?t.setAttribute(e,function(t,e){return ur(e)||"false"===e?"false":"contenteditable"===t&&or(e)?e:"true"}(e,n)):sr(e)?ur(n)?t.removeAttributeNS(ar,lr(e)):t.setAttributeNS(ar,e,n):Ir(t,e,n)}function Ir(t,e,n){if(ur(n))t.removeAttribute(e);else{if(J&&!Z&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var Dr={create:zr,update:zr};function Nr(t,e){var n=e.elm,r=e.data,o=t.data;if(!(i(r.staticClass)&&i(r.class)&&(i(o)||i(o.staticClass)&&i(o.class)))){var s=cr(e),l=n._transitionClasses;a(l)&&(s=pr(s,dr(l))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}var Ur,Br={create:Nr,update:Nr};function Fr(t,e,n){var r=Ur;return function o(){var i=e.apply(null,arguments);null!==i&&Vr(t,o,n,r)}}var Hr=Ae&&!(nt&&Number(nt[1])<=53);function qr(t,e,n,r){if(Hr){var o=ln,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}Ur.addEventListener(t,e,ot?{capture:n,passive:r}:n)}function Vr(t,e,n,r){(r||Ur).removeEventListener(t,e._wrapper||e,n)}function Wr(t,e){if(!i(t.data.on)||!i(e.data.on)){var n=e.data.on||{},r=t.data.on||{};Ur=e.elm||t.elm,function(t){if(a(t.__r)){var e=J?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}a(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(n),Wt(n,r,qr,Vr,Fr,e.context),Ur=void 0}}var Gr,Kr={create:Wr,update:Wr,destroy:function(t){return Wr(t,Sr)}};function Yr(t,e){if(!i(t.data.domProps)||!i(e.data.domProps)){var n,r,o=e.elm,l=t.data.domProps||{},u=e.data.domProps||{};for(n in(a(u.__ob__)||s(u._v_attr_proxy))&&(u=e.data.domProps=T({},u)),l)n in u||(o[n]="");for(n in u){if(r=u[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),r===l[n])continue;1===o.childNodes.length&&o.removeChild(o.childNodes[0])}if("value"===n&&"PROGRESS"!==o.tagName){o._value=r;var c=i(r)?"":String(r);Xr(o,c)&&(o.value=c)}else if("innerHTML"===n&&mr(o.tagName)&&i(o.innerHTML)){(Gr=Gr||document.createElement("div")).innerHTML="".concat(r,"");for(var f=Gr.firstChild;o.firstChild;)o.removeChild(o.firstChild);for(;f.firstChild;)o.appendChild(f.firstChild)}else if(r!==l[n])try{o[n]=r}catch(t){}}}}function Xr(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,r=t._vModifiers;if(a(r)){if(r.number)return y(n)!==y(e);if(r.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Jr={create:Yr,update:Yr},Zr=S((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function Qr(t){var e=to(t.style);return t.staticStyle?T(t.staticStyle,e):e}function to(t){return Array.isArray(t)?L(t):"string"==typeof t?Zr(t):t}var eo,no=/^--/,ro=/\s*!important$/,oo=function(t,e,n){if(no.test(e))t.style.setProperty(e,n);else if(ro.test(n))t.style.setProperty(E(e),n.replace(ro,""),"important");else{var r=ao(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(uo).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" ".concat(t.getAttribute("class")||""," ");n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function fo(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(uo).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" ".concat(t.getAttribute("class")||""," "),r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function po(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&T(e,ho(t.name||"v")),T(e,t),e}return"string"==typeof t?ho(t):void 0}}var ho=S((function(t){return{enterClass:"".concat(t,"-enter"),enterToClass:"".concat(t,"-enter-to"),enterActiveClass:"".concat(t,"-enter-active"),leaveClass:"".concat(t,"-leave"),leaveToClass:"".concat(t,"-leave-to"),leaveActiveClass:"".concat(t,"-leave-active")}})),vo=Y&&!Z,mo="transition",go="transitionend",yo="animation",bo="animationend";vo&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(mo="WebkitTransition",go="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(yo="WebkitAnimation",bo="webkitAnimationEnd"));var _o=Y?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function wo(t){_o((function(){_o(t)}))}function xo(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),co(t,e))}function ko(t,e){t._transitionClasses&&w(t._transitionClasses,e),fo(t,e)}function So(t,e,n){var r=Oo(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s="transition"===o?go:bo,l=0,u=function(){t.removeEventListener(s,c),n()},c=function(e){e.target===t&&++l>=a&&u()};setTimeout((function(){l0&&(n="transition",c=a,f=i.length):"animation"===e?u>0&&(n="animation",c=u,f=l.length):f=(n=(c=Math.max(a,u))>0?a>u?"transition":"animation":null)?"transition"===n?i.length:l.length:0,{type:n,timeout:c,propCount:f,hasTransform:"transition"===n&&Co.test(r[mo+"Property"])}}function jo(t,e){for(;t.length1}function Lo(t,e){!0!==e.data.show&&Eo(e)}var Ro=function(t){var e,n,r={},u=t.modules,c=t.nodeOps;for(e=0;eh?_(t,i(n[g+1])?null:n[g+1].elm,n,d,g,r):d>g&&x(e,f,h)}(f,v,g,n,u):a(g)?(a(t.text)&&c.setTextContent(f,""),_(f,null,g,0,g.length-1,n)):a(v)?x(v,0,v.length-1):a(t.text)&&c.setTextContent(f,""):t.text!==e.text&&c.setTextContent(f,e.text),a(h)&&a(d=h.hook)&&a(d=d.postpatch)&&d(t,e)}}}function O(t,e,n){if(s(n)&&a(t.parent))t.parent.data.pendingInsert=e;else for(var r=0;r-1,a.selected!==i&&(a.selected=i);else if(I(No(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function Do(t,e){return e.every((function(e){return!I(e,t)}))}function No(t){return"_value"in t?t._value:t.value}function Uo(t){t.target.composing=!0}function Bo(t){t.target.composing&&(t.target.composing=!1,Fo(t.target,"input"))}function Fo(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function Ho(t){return!t.componentInstance||t.data&&t.data.transition?t:Ho(t.componentInstance._vnode)}var qo={model:zo,show:{bind:function(t,e,n){var r=e.value,o=(n=Ho(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,Eo(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=Ho(n)).data&&n.data.transition?(n.data.show=!0,r?Eo(n,(function(){t.style.display=t.__vOriginalDisplay})):Po(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},Vo={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Wo(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Wo(Se(e.children)):t}function Go(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var r in o)e[O(r)]=o[r];return e}function Ko(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Yo=function(t){return t.tag||he(t)},Xo=function(t){return"show"===t.name},Jo={name:"transition",props:Vo,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Yo)).length){0;var r=this.mode;0;var o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var i=Wo(o);if(!i)return o;if(this._leaving)return Ko(t,o);var a="__transition-".concat(this._uid,"-");i.key=null==i.key?i.isComment?a+"comment":a+i.tag:l(i.key)?0===String(i.key).indexOf(a)?i.key:a+i.key:i.key;var s=(i.data||(i.data={})).transition=Go(this),u=this._vnode,c=Wo(u);if(i.data.directives&&i.data.directives.some(Xo)&&(i.data.show=!0),c&&c.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(i,c)&&!he(c)&&(!c.componentInstance||!c.componentInstance._vnode.isComment)){var f=c.data.transition=T({},s);if("out-in"===r)return this._leaving=!0,Gt(f,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),Ko(t,o);if("in-out"===r){if(he(i))return u;var p,d=function(){p()};Gt(s,"afterEnter",d),Gt(s,"enterCancelled",d),Gt(f,"delayLeave",(function(t){p=t}))}}return o}}},Zo=T({tag:String,moveClass:String},Vo);function Qo(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function ti(t){t.data.newPos=t.elm.getBoundingClientRect()}function ei(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate(".concat(r,"px,").concat(o,"px)"),i.transitionDuration="0s"}}delete Zo.mode;var ni={Transition:Jo,TransitionGroup:{props:Zo,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=Je(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=Go(this),s=0;s-1?yr[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:yr[t]=/HTMLUnknownElement/.test(e.toString())},T(Gn.options.directives,qo),T(Gn.options.components,ni),Gn.prototype.__patch__=Y?Ro:R,Gn.prototype.$mount=function(t,e){return function(t,e,n){var r;t.$el=e,t.$options.render||(t.$options.render=ht),tn(t,"beforeMount"),r=function(){t._update(t._render(),n)},new Ve(t,r,R,{before:function(){t._isMounted&&!t._isDestroyed&&tn(t,"beforeUpdate")}},!0),n=!1;var o=t._preWatchers;if(o)for(var i=0;i=0&&(e=t.slice(r),t=t.slice(0,r));var o=t.indexOf("?");return o>=0&&(n=t.slice(o+1),t=t.slice(0,o)),{path:t,query:n,hash:e}}(o.path||""),u=e&&e.path||"/",c=l.path?ki(l.path,u,n||o.append):u,f=function(t,e,n){void 0===e&&(e={});var r,o=n||ci;try{r=o(t||"")}catch(t){r={}}for(var i in e){var a=e[i];r[i]=Array.isArray(a)?a.map(ui):ui(a)}return r}(l.query,o.query,r&&r.options.parseQuery),p=o.hash||l.hash;return p&&"#"!==p.charAt(0)&&(p="#"+p),{_normalized:!0,path:c,query:f,hash:p}}var qi,Vi=function(){},Wi={name:"RouterLink",props:{to:{type:[String,Object],required:!0},tag:{type:String,default:"a"},custom:Boolean,exact:Boolean,exactPath:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,ariaCurrentValue:{type:String,default:"page"},event:{type:[String,Array],default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,o=n.resolve(this.to,r,this.append),i=o.location,a=o.route,s=o.href,l={},u=n.options.linkActiveClass,c=n.options.linkExactActiveClass,f=null==u?"router-link-active":u,p=null==c?"router-link-exact-active":c,d=null==this.activeClass?f:this.activeClass,h=null==this.exactActiveClass?p:this.exactActiveClass,v=a.redirectedFrom?di(null,Hi(a.redirectedFrom),null,n):a;l[h]=yi(r,v,this.exactPath),l[d]=this.exact||this.exactPath?l[h]:function(t,e){return 0===t.path.replace(pi,"/").indexOf(e.path.replace(pi,"/"))&&(!e.hash||t.hash===e.hash)&&function(t,e){for(var n in e)if(!(n in t))return!1;return!0}(t.query,e.query)}(r,v);var m=l[h]?this.ariaCurrentValue:null,g=function(t){Gi(t)&&(e.replace?n.replace(i,Vi):n.push(i,Vi))},y={click:Gi};Array.isArray(this.event)?this.event.forEach((function(t){y[t]=g})):y[this.event]=g;var b={class:l},_=!this.$scopedSlots.$hasNormal&&this.$scopedSlots.default&&this.$scopedSlots.default({href:s,route:a,navigate:g,isActive:l[d],isExactActive:l[h]});if(_){if(1===_.length)return _[0];if(_.length>1||!_.length)return 0===_.length?t():t("span",{},_)}if("a"===this.tag)b.on=y,b.attrs={href:s,"aria-current":m};else{var w=function t(e){var n;if(e)for(var r=0;r-1&&(s.params[p]=n.params[p]);return s.path=Fi(c.path,s.params),l(c,s,a)}if(s.path){s.params={};for(var d=0;d-1}function Sa(t,e){return ka(t)&&t._isRouter&&(null==e||t.type===e)}function Ca(t,e,n){var r=function(o){o>=t.length?n():t[o]?e(t[o],(function(){r(o+1)})):r(o+1)};r(0)}function Oa(t){return function(e,n,r){var o=!1,i=0,a=null;ja(t,(function(t,e,n,s){if("function"==typeof t&&void 0===t.cid){o=!0,i++;var l,u=Pa((function(e){var o;((o=e).__esModule||Ea&&"Module"===o[Symbol.toStringTag])&&(e=e.default),t.resolved="function"==typeof e?e:qi.extend(e),n.components[s]=e,--i<=0&&r()})),c=Pa((function(t){var e="Failed to resolve async component "+s+": "+t;a||(a=ka(t)?t:new Error(e),r(a))}));try{l=t(u,c)}catch(t){c(t)}if(l)if("function"==typeof l.then)l.then(u,c);else{var f=l.component;f&&"function"==typeof f.then&&f.then(u,c)}}})),o||r()}}function ja(t,e){return $a(t.map((function(t){return Object.keys(t.components).map((function(n){return e(t.components[n],t.instances[n],t,n)}))})))}function $a(t){return Array.prototype.concat.apply([],t)}var Ea="function"==typeof Symbol&&"symbol"==typeof Symbol.toStringTag;function Pa(t){var e=!1;return function(){for(var n=[],r=arguments.length;r--;)n[r]=arguments[r];if(!e)return e=!0,t.apply(this,n)}}var Aa=function(t,e){this.router=t,this.base=function(t){if(!t)if(Ki){var e=document.querySelector("base");t=(t=e&&e.getAttribute("href")||"/").replace(/^https?:\/\/[^\/]+/,"")}else t="/";"/"!==t.charAt(0)&&(t="/"+t);return t.replace(/\/$/,"")}(e),this.current=vi,this.pending=null,this.ready=!1,this.readyCbs=[],this.readyErrorCbs=[],this.errorCbs=[],this.listeners=[]};function Ta(t,e,n,r){var o=ja(t,(function(t,r,o,i){var a=function(t,e){"function"!=typeof t&&(t=qi.extend(t));return t.options[e]}(t,e);if(a)return Array.isArray(a)?a.map((function(t){return n(t,r,o,i)})):n(a,r,o,i)}));return $a(r?o.reverse():o)}function La(t,e){if(e)return function(){return t.apply(e,arguments)}}Aa.prototype.listen=function(t){this.cb=t},Aa.prototype.onReady=function(t,e){this.ready?t():(this.readyCbs.push(t),e&&this.readyErrorCbs.push(e))},Aa.prototype.onError=function(t){this.errorCbs.push(t)},Aa.prototype.transitionTo=function(t,e,n){var r,o=this;try{r=this.router.match(t,this.current)}catch(t){throw this.errorCbs.forEach((function(e){e(t)})),t}var i=this.current;this.confirmTransition(r,(function(){o.updateRoute(r),e&&e(r),o.ensureURL(),o.router.afterHooks.forEach((function(t){t&&t(r,i)})),o.ready||(o.ready=!0,o.readyCbs.forEach((function(t){t(r)})))}),(function(t){n&&n(t),t&&!o.ready&&(Sa(t,ya.redirected)&&i===vi||(o.ready=!0,o.readyErrorCbs.forEach((function(e){e(t)}))))}))},Aa.prototype.confirmTransition=function(t,e,n){var r=this,o=this.current;this.pending=t;var i,a,s=function(t){!Sa(t)&&ka(t)&&(r.errorCbs.length?r.errorCbs.forEach((function(e){e(t)})):console.error(t)),n&&n(t)},l=t.matched.length-1,u=o.matched.length-1;if(yi(t,o)&&l===u&&t.matched[l]===o.matched[u])return this.ensureURL(),t.hash&&aa(this.router,o,t,!1),s(((a=wa(i=o,t,ya.duplicated,'Avoided redundant navigation to current location: "'+i.fullPath+'".')).name="NavigationDuplicated",a));var c=function(t,e){var n,r=Math.max(t.length,e.length);for(n=0;n0)){var e=this.router,n=e.options.scrollBehavior,r=va&&n;r&&this.listeners.push(ia());var o=function(){var n=t.current,o=za(t.base);t.current===vi&&o===t._startLocation||t.transitionTo(o,(function(t){r&&aa(e,t,n,!0)}))};window.addEventListener("popstate",o),this.listeners.push((function(){window.removeEventListener("popstate",o)}))}},e.prototype.go=function(t){window.history.go(t)},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ma(Si(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){ga(Si(r.base+t.fullPath)),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.ensureURL=function(t){if(za(this.base)!==this.current.fullPath){var e=Si(this.base+this.current.fullPath);t?ma(e):ga(e)}},e.prototype.getCurrentLocation=function(){return za(this.base)},e}(Aa);function za(t){var e=window.location.pathname,n=e.toLowerCase(),r=t.toLowerCase();return!t||n!==r&&0!==n.indexOf(Si(r+"/"))||(e=e.slice(t.length)),(e||"/")+window.location.search+window.location.hash}var Ma=function(t){function e(e,n,r){t.call(this,e,n),r&&function(t){var e=za(t);if(!/^\/#/.test(e))return window.location.replace(Si(t+"/#"+e)),!0}(this.base)||Ia()}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.setupListeners=function(){var t=this;if(!(this.listeners.length>0)){var e=this.router.options.scrollBehavior,n=va&&e;n&&this.listeners.push(ia());var r=function(){var e=t.current;Ia()&&t.transitionTo(Da(),(function(r){n&&aa(t.router,r,e,!0),va||Ba(r.fullPath)}))},o=va?"popstate":"hashchange";window.addEventListener(o,r),this.listeners.push((function(){window.removeEventListener(o,r)}))}},e.prototype.push=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Ua(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this,o=this.current;this.transitionTo(t,(function(t){Ba(t.fullPath),aa(r.router,t,o,!1),e&&e(t)}),n)},e.prototype.go=function(t){window.history.go(t)},e.prototype.ensureURL=function(t){var e=this.current.fullPath;Da()!==e&&(t?Ua(e):Ba(e))},e.prototype.getCurrentLocation=function(){return Da()},e}(Aa);function Ia(){var t=Da();return"/"===t.charAt(0)||(Ba("/"+t),!1)}function Da(){var t=window.location.href,e=t.indexOf("#");return e<0?"":t=t.slice(e+1)}function Na(t){var e=window.location.href,n=e.indexOf("#");return(n>=0?e.slice(0,n):e)+"#"+t}function Ua(t){va?ma(Na(t)):window.location.hash=t}function Ba(t){va?ga(Na(t)):window.location.replace(Na(t))}var Fa=function(t){function e(e,n){t.call(this,e,n),this.stack=[],this.index=-1}return t&&(e.__proto__=t),e.prototype=Object.create(t&&t.prototype),e.prototype.constructor=e,e.prototype.push=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index+1).concat(t),r.index++,e&&e(t)}),n)},e.prototype.replace=function(t,e,n){var r=this;this.transitionTo(t,(function(t){r.stack=r.stack.slice(0,r.index).concat(t),e&&e(t)}),n)},e.prototype.go=function(t){var e=this,n=this.index+t;if(!(n<0||n>=this.stack.length)){var r=this.stack[n];this.confirmTransition(r,(function(){var t=e.current;e.index=n,e.updateRoute(r),e.router.afterHooks.forEach((function(e){e&&e(r,t)}))}),(function(t){Sa(t,ya.duplicated)&&(e.index=n)}))}},e.prototype.getCurrentLocation=function(){var t=this.stack[this.stack.length-1];return t?t.fullPath:"/"},e.prototype.ensureURL=function(){},e}(Aa),Ha=function(t){void 0===t&&(t={}),this.app=null,this.apps=[],this.options=t,this.beforeHooks=[],this.resolveHooks=[],this.afterHooks=[],this.matcher=Ji(t.routes||[],this);var e=t.mode||"hash";switch(this.fallback="history"===e&&!va&&!1!==t.fallback,this.fallback&&(e="hash"),Ki||(e="abstract"),this.mode=e,e){case"history":this.history=new Ra(this,t.base);break;case"hash":this.history=new Ma(this,t.base,this.fallback);break;case"abstract":this.history=new Fa(this,t.base);break;default:0}},qa={currentRoute:{configurable:!0}};Ha.prototype.match=function(t,e,n){return this.matcher.match(t,e,n)},qa.currentRoute.get=function(){return this.history&&this.history.current},Ha.prototype.init=function(t){var e=this;if(this.apps.push(t),t.$once("hook:destroyed",(function(){var n=e.apps.indexOf(t);n>-1&&e.apps.splice(n,1),e.app===t&&(e.app=e.apps[0]||null),e.app||e.history.teardown()})),!this.app){this.app=t;var n=this.history;if(n instanceof Ra||n instanceof Ma){var r=function(t){n.setupListeners(),function(t){var r=n.current,o=e.options.scrollBehavior;va&&o&&"fullPath"in t&&aa(e,t,r,!1)}(t)};n.transitionTo(n.getCurrentLocation(),r,r)}n.listen((function(t){e.apps.forEach((function(e){e._route=t}))}))}},Ha.prototype.beforeEach=function(t){return Wa(this.beforeHooks,t)},Ha.prototype.beforeResolve=function(t){return Wa(this.resolveHooks,t)},Ha.prototype.afterEach=function(t){return Wa(this.afterHooks,t)},Ha.prototype.onReady=function(t,e){this.history.onReady(t,e)},Ha.prototype.onError=function(t){this.history.onError(t)},Ha.prototype.push=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.push(t,e,n)}));this.history.push(t,e,n)},Ha.prototype.replace=function(t,e,n){var r=this;if(!e&&!n&&"undefined"!=typeof Promise)return new Promise((function(e,n){r.history.replace(t,e,n)}));this.history.replace(t,e,n)},Ha.prototype.go=function(t){this.history.go(t)},Ha.prototype.back=function(){this.go(-1)},Ha.prototype.forward=function(){this.go(1)},Ha.prototype.getMatchedComponents=function(t){var e=t?t.matched?t:this.resolve(t).route:this.currentRoute;return e?[].concat.apply([],e.matched.map((function(t){return Object.keys(t.components).map((function(e){return t.components[e]}))}))):[]},Ha.prototype.resolve=function(t,e,n){var r=Hi(t,e=e||this.history.current,n,this),o=this.match(r,e),i=o.redirectedFrom||o.fullPath;return{location:r,route:o,href:function(t,e,n){var r="hash"===n?"#"+e:e;return t?Si(t+"/"+r):r}(this.history.base,i,this.mode),normalizedTo:r,resolved:o}},Ha.prototype.getRoutes=function(){return this.matcher.getRoutes()},Ha.prototype.addRoute=function(t,e){this.matcher.addRoute(t,e),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},Ha.prototype.addRoutes=function(t){this.matcher.addRoutes(t),this.history.current!==vi&&this.history.transitionTo(this.history.getCurrentLocation())},Object.defineProperties(Ha.prototype,qa);var Va=Ha;function Wa(t,e){return t.push(e),function(){var n=t.indexOf(e);n>-1&&t.splice(n,1)}}Ha.install=function t(e){if(!t.installed||qi!==e){t.installed=!0,qi=e;var n=function(t){return void 0!==t},r=function(t,e){var r=t.$options._parentVnode;n(r)&&n(r=r.data)&&n(r=r.registerRouteInstance)&&r(t,e)};e.mixin({beforeCreate:function(){n(this.$options.router)?(this._routerRoot=this,this._router=this.$options.router,this._router.init(this),e.util.defineReactive(this,"_route",this._router.history.current)):this._routerRoot=this.$parent&&this.$parent._routerRoot||this,r(this,this)},destroyed:function(){r(this)}}),Object.defineProperty(e.prototype,"$router",{get:function(){return this._routerRoot._router}}),Object.defineProperty(e.prototype,"$route",{get:function(){return this._routerRoot._route}}),e.component("RouterView",wi),e.component("RouterLink",Wi);var o=e.config.optionMergeStrategies;o.beforeRouteEnter=o.beforeRouteLeave=o.beforeRouteUpdate=o.created}},Ha.version="3.6.5",Ha.isNavigationFailure=Sa,Ha.NavigationFailureType=ya,Ha.START_LOCATION=vi,Ki&&window.Vue&&window.Vue.use(Ha);n(97);n(124),n(90);var Ga={"components/AlgoliaSearchBox":()=>Promise.all([n.e(0),n.e(22)]).then(n.bind(null,496)),"components/DropdownLink":()=>Promise.all([n.e(0),n.e(23)]).then(n.bind(null,257)),"components/DropdownTransition":()=>Promise.all([n.e(0),n.e(35)]).then(n.bind(null,245)),"components/Home":()=>Promise.all([n.e(0),n.e(28)]).then(n.bind(null,285)),"components/NavLink":()=>n.e(42).then(n.bind(null,244)),"components/NavLinks":()=>Promise.all([n.e(0),n.e(20)]).then(n.bind(null,268)),"components/Navbar":()=>Promise.all([n.e(0),n.e(1)]).then(n.bind(null,493)),"components/Page":()=>Promise.all([n.e(0),n.e(17)]).then(n.bind(null,286)),"components/PageEdit":()=>Promise.all([n.e(0),n.e(29)]).then(n.bind(null,270)),"components/PageNav":()=>Promise.all([n.e(0),n.e(25)]).then(n.bind(null,271)),"components/Sidebar":()=>Promise.all([n.e(0),n.e(13)]).then(n.bind(null,287)),"components/SidebarButton":()=>Promise.all([n.e(0),n.e(36)]).then(n.bind(null,288)),"components/SidebarGroup":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,269)),"components/SidebarLink":()=>Promise.all([n.e(0),n.e(34)]).then(n.bind(null,258)),"components/SidebarLinks":()=>Promise.all([n.e(0),n.e(3)]).then(n.bind(null,256)),"global-components/Badge":()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,501)),"global-components/CodeBlock":()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,497)),"global-components/CodeGroup":()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,498)),"layouts/404":()=>n.e(7).then(n.bind(null,499)),"layouts/Layout":()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,500)),NotFound:()=>n.e(7).then(n.bind(null,499)),Layout:()=>Promise.all([n.e(0),n.e(1),n.e(2)]).then(n.bind(null,500))},Ka={"v-3928e857":()=>n.e(26).then(n.bind(null,502)),"v-7b9862ab":()=>n.e(18).then(n.bind(null,503)),"v-f273fc06":()=>n.e(11).then(n.bind(null,504)),"v-056c16b3":()=>n.e(12).then(n.bind(null,505)),"v-ae0f79fc":()=>n.e(37).then(n.bind(null,506)),"v-013d4bea":()=>n.e(38).then(n.bind(null,507)),"v-704c4f3b":()=>n.e(16).then(n.bind(null,508)),"v-6c7e8ceb":()=>n.e(43).then(n.bind(null,509)),"v-de22c96a":()=>n.e(10).then(n.bind(null,510)),"v-33036d6a":()=>n.e(24).then(n.bind(null,511)),"v-956dd9f8":()=>n.e(44).then(n.bind(null,512)),"v-26584971":()=>n.e(14).then(n.bind(null,513)),"v-e6ca92f8":()=>n.e(45).then(n.bind(null,514)),"v-00f2c74b":()=>n.e(46).then(n.bind(null,515)),"v-a239bdaa":()=>n.e(47).then(n.bind(null,516)),"v-d88216be":()=>n.e(39).then(n.bind(null,517)),"v-4b031461":()=>n.e(48).then(n.bind(null,518)),"v-aa17ed6a":()=>n.e(30).then(n.bind(null,519)),"v-e9450f6a":()=>n.e(40).then(n.bind(null,520)),"v-f8229d2a":()=>n.e(49).then(n.bind(null,521)),"v-1f8621f3":()=>n.e(15).then(n.bind(null,522)),"v-9d304e46":()=>n.e(27).then(n.bind(null,523)),"v-d7208806":()=>n.e(50).then(n.bind(null,524)),"v-4edd81f1":()=>n.e(21).then(n.bind(null,525)),"v-9d28b566":()=>n.e(31).then(n.bind(null,526)),"v-60282e5f":()=>n.e(51).then(n.bind(null,527)),"v-499f409c":()=>n.e(52).then(n.bind(null,528)),"v-e52c6902":()=>n.e(32).then(n.bind(null,529)),"v-01c068eb":()=>n.e(33).then(n.bind(null,530)),"v-358893ea":()=>n.e(41).then(n.bind(null,531)),"v-3faa660b":()=>n.e(19).then(n.bind(null,532))};function Ya(t){const e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}const Xa=/-(\w)/g,Ja=Ya(t=>t.replace(Xa,(t,e)=>e?e.toUpperCase():"")),Za=/\B([A-Z])/g,Qa=Ya(t=>t.replace(Za,"-$1").toLowerCase()),ts=Ya(t=>t.charAt(0).toUpperCase()+t.slice(1));function es(t,e){if(!e)return;if(t(e))return t(e);return e.includes("-")?t(ts(Ja(e))):t(ts(e))||t(Qa(e))}const ns=Object.assign({},Ga,Ka),rs=t=>ns[t],os=t=>Ka[t],is=t=>Ga[t],as=t=>Gn.component(t);function ss(t){return es(os,t)}function ls(t){return es(is,t)}function us(t){return es(rs,t)}function cs(t){return es(as,t)}function fs(...t){return Promise.all(t.filter(t=>t).map(async t=>{if(!cs(t)&&us(t)){const e=await us(t)();Gn.component(t,e.default)}}))}function ps(t,e){"undefined"!=typeof window&&window.__VUEPRESS__&&(window.__VUEPRESS__[t]=e)}var ds=n(88),hs=n.n(ds),vs=n(89),ms=n.n(vs),gs={created(){if(this.siteMeta=this.$site.headTags.filter(([t])=>"meta"===t).map(([t,e])=>e),this.$ssrContext){const e=this.getMergedMetaTags();this.$ssrContext.title=this.$title,this.$ssrContext.lang=this.$lang,this.$ssrContext.pageMeta=(t=e)?t.map(t=>{let e="{e+=` ${n}="${ms()(t[n])}"`}),e+">"}).join("\n "):"",this.$ssrContext.canonicalLink=bs(this.$canonicalUrl)}var t},mounted(){this.currentMetaTags=[...document.querySelectorAll("meta")],this.updateMeta(),this.updateCanonicalLink()},methods:{updateMeta(){document.title=this.$title,document.documentElement.lang=this.$lang;const t=this.getMergedMetaTags();this.currentMetaTags=_s(t,this.currentMetaTags)},getMergedMetaTags(){const t=this.$page.frontmatter.meta||[];return hs()([{name:"description",content:this.$description}],t,this.siteMeta,ws)},updateCanonicalLink(){ys(),this.$canonicalUrl&&document.head.insertAdjacentHTML("beforeend",bs(this.$canonicalUrl))}},watch:{$page(){this.updateMeta(),this.updateCanonicalLink()}},beforeDestroy(){_s(null,this.currentMetaTags),ys()}};function ys(){const t=document.querySelector("link[rel='canonical']");t&&t.remove()}function bs(t=""){return t?``:""}function _s(t,e){if(e&&[...e].filter(t=>t.parentNode===document.head).forEach(t=>document.head.removeChild(t)),t)return t.map(t=>{const e=document.createElement("meta");return Object.keys(t).forEach(n=>{e.setAttribute(n,t[n])}),document.head.appendChild(e),e})}function ws(t){for(const e of["name","property","itemprop"])if(t.hasOwnProperty(e))return t[e]+e;return JSON.stringify(t)}var xs=n(22),ks=n.n(xs),Ss={mounted(){window.addEventListener("scroll",this.onScroll)},methods:{onScroll:ks()((function(){this.setActiveHash()}),300),setActiveHash(){const t=[].slice.call(document.querySelectorAll(".sidebar-link")),e=[].slice.call(document.querySelectorAll(".header-anchor")).filter(e=>t.some(t=>t.hash===e.hash)),n=Math.max(window.pageYOffset,document.documentElement.scrollTop,document.body.scrollTop),r=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),o=window.innerHeight+n;for(let t=0;t=i.parentElement.offsetTop+10&&(!a||n{this.$nextTick(()=>{this.$vuepress.$set("disableScrollBehavior",!1)})})}}}},beforeDestroy(){window.removeEventListener("scroll",this.onScroll)}},Cs=n(23),Os=n.n(Cs),js={mounted(){Os.a.configure({showSpinner:!1}),this.$router.beforeEach((t,e,n)=>{t.path===e.path||Gn.component(t.name)||Os.a.start(),n()}),this.$router.afterEach(()=>{Os.a.done(),this.isSidebarOpen=!1})}},$s=(n(235),Object.assign||function(t){for(var e=1;e1&&void 0!==arguments[1]?arguments[1]:{},r=window.Promise||function(t){function e(){}t(e,e)},o=function(t){var e=t.target;e!==C?-1!==b.indexOf(e)&&v({target:e}):h()},i=function(){if(!w&&S.original){var t=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(x-t)>k.scrollOffset&&setTimeout(h,150)}},a=function(t){var e=t.key||t.keyCode;"Escape"!==e&&"Esc"!==e&&27!==e||h()},s=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t;if(t.background&&(C.style.background=t.background),t.container&&t.container instanceof Object&&(e.container=$s({},k.container,t.container)),t.template){var n=Ps(t.template)?t.template:document.querySelector(t.template);e.template=n}return k=$s({},k,e),b.forEach((function(t){t.dispatchEvent(zs("medium-zoom:update",{detail:{zoom:O}}))})),O},l=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return t($s({},k,e))},u=function(){for(var t=arguments.length,e=Array(t),n=0;n0?e.reduce((function(t,e){return[].concat(t,Ts(e))}),[]):b;return r.forEach((function(t){t.classList.remove("medium-zoom-image"),t.dispatchEvent(zs("medium-zoom:detach",{detail:{zoom:O}}))})),b=b.filter((function(t){return-1===r.indexOf(t)})),O},f=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return b.forEach((function(r){r.addEventListener("medium-zoom:"+t,e,n)})),_.push({type:"medium-zoom:"+t,listener:e,options:n}),O},p=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return b.forEach((function(r){r.removeEventListener("medium-zoom:"+t,e,n)})),_=_.filter((function(n){return!(n.type==="medium-zoom:"+t&&n.listener.toString()===e.toString())})),O},d=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.target,n=function(){var t={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},e=void 0,n=void 0;if(k.container)if(k.container instanceof Object)e=(t=$s({},t,k.container)).width-t.left-t.right-2*k.margin,n=t.height-t.top-t.bottom-2*k.margin;else{var r=(Ps(k.container)?k.container:document.querySelector(k.container)).getBoundingClientRect(),o=r.width,i=r.height,a=r.left,s=r.top;t=$s({},t,{width:o,height:i,left:a,top:s})}e=e||t.width-2*k.margin,n=n||t.height-2*k.margin;var l=S.zoomedHd||S.original,u=As(l)?e:l.naturalWidth||e,c=As(l)?n:l.naturalHeight||n,f=l.getBoundingClientRect(),p=f.top,d=f.left,h=f.width,v=f.height,m=Math.min(Math.max(h,u),e)/h,g=Math.min(Math.max(v,c),n)/v,y=Math.min(m,g),b="scale("+y+") translate3d("+((e-h)/2-d+k.margin+t.left)/y+"px, "+((n-v)/2-p+k.margin+t.top)/y+"px, 0)";S.zoomed.style.transform=b,S.zoomedHd&&(S.zoomedHd.style.transform=b)};return new r((function(t){if(e&&-1===b.indexOf(e))t(O);else{if(S.zoomed)t(O);else{if(e)S.original=e;else{if(!(b.length>0))return void t(O);var r=b;S.original=r[0]}if(S.original.dispatchEvent(zs("medium-zoom:open",{detail:{zoom:O}})),x=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,w=!0,S.zoomed=Rs(S.original),document.body.appendChild(C),k.template){var o=Ps(k.template)?k.template:document.querySelector(k.template);S.template=document.createElement("div"),S.template.appendChild(o.content.cloneNode(!0)),document.body.appendChild(S.template)}if(S.original.parentElement&&"PICTURE"===S.original.parentElement.tagName&&S.original.currentSrc&&(S.zoomed.src=S.original.currentSrc),document.body.appendChild(S.zoomed),window.requestAnimationFrame((function(){document.body.classList.add("medium-zoom--opened")})),S.original.classList.add("medium-zoom-image--hidden"),S.zoomed.classList.add("medium-zoom-image--opened"),S.zoomed.addEventListener("click",h),S.zoomed.addEventListener("transitionend",(function e(){w=!1,S.zoomed.removeEventListener("transitionend",e),S.original.dispatchEvent(zs("medium-zoom:opened",{detail:{zoom:O}})),t(O)})),S.original.getAttribute("data-zoom-src")){S.zoomedHd=S.zoomed.cloneNode(),S.zoomedHd.removeAttribute("srcset"),S.zoomedHd.removeAttribute("sizes"),S.zoomedHd.removeAttribute("loading"),S.zoomedHd.src=S.zoomed.getAttribute("data-zoom-src"),S.zoomedHd.onerror=function(){clearInterval(i),console.warn("Unable to reach the zoom image target "+S.zoomedHd.src),S.zoomedHd=null,n()};var i=setInterval((function(){S.zoomedHd.complete&&(clearInterval(i),S.zoomedHd.classList.add("medium-zoom-image--opened"),S.zoomedHd.addEventListener("click",h),document.body.appendChild(S.zoomedHd),n())}),10)}else if(S.original.hasAttribute("srcset")){S.zoomedHd=S.zoomed.cloneNode(),S.zoomedHd.removeAttribute("sizes"),S.zoomedHd.removeAttribute("loading");var a=S.zoomedHd.addEventListener("load",(function(){S.zoomedHd.removeEventListener("load",a),S.zoomedHd.classList.add("medium-zoom-image--opened"),S.zoomedHd.addEventListener("click",h),document.body.appendChild(S.zoomedHd),n()}))}else n()}}}))},h=function(){return new r((function(t){if(!w&&S.original){w=!0,document.body.classList.remove("medium-zoom--opened"),S.zoomed.style.transform="",S.zoomedHd&&(S.zoomedHd.style.transform=""),S.template&&(S.template.style.transition="opacity 150ms",S.template.style.opacity=0),S.original.dispatchEvent(zs("medium-zoom:close",{detail:{zoom:O}})),S.zoomed.addEventListener("transitionend",(function e(){S.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(S.zoomed),S.zoomedHd&&document.body.removeChild(S.zoomedHd),document.body.removeChild(C),S.zoomed.classList.remove("medium-zoom-image--opened"),S.template&&document.body.removeChild(S.template),w=!1,S.zoomed.removeEventListener("transitionend",e),S.original.dispatchEvent(zs("medium-zoom:closed",{detail:{zoom:O}})),S.original=null,S.zoomed=null,S.zoomedHd=null,S.template=null,t(O)}))}else t(O)}))},v=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.target;return S.original?h():d({target:e})},m=function(){return k},g=function(){return b},y=function(){return S.original},b=[],_=[],w=!1,x=0,k=n,S={original:null,zoomed:null,zoomedHd:null,template:null};"[object Object]"===Object.prototype.toString.call(e)?k=e:(e||"string"==typeof e)&&u(e),k=$s({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},k);var C=Ls(k.background);document.addEventListener("click",o),document.addEventListener("keyup",a),document.addEventListener("scroll",i),window.addEventListener("resize",h);var O={open:d,close:h,toggle:v,update:s,clone:l,attach:u,detach:c,on:f,off:p,getOptions:m,getImages:g,getZoomedImage:y};return O},Is=[gs,Ss,js,{data:()=>({zoom:null}),mounted(){this.updateZoom()},updated(){this.updateZoom()},methods:{updateZoom(){setTimeout(()=>{this.zoom&&this.zoom.detach(),this.zoom=Ms(".theme-default-content :not(a) > img",void 0)},1e3)}}}],Ds={name:"GlobalLayout",computed:{layout(){const t=this.getLayout();return ps("layout",t),Gn.component(t)}},methods:{getLayout(){if(this.$page.path){const t=this.$page.frontmatter.layout;return t&&(this.$vuepress.getLayoutAsyncComponent(t)||this.$vuepress.getVueComponent(t))?t:"Layout"}return"NotFound"}}},Ns=n(10),Us=Object(Ns.a)(Ds,(function(){return(0,this._self._c)(this.layout,{tag:"component"})}),[],!1,null,null,null).exports;!function(t,e,n){switch(e){case"components":t[e]||(t[e]={}),Object.assign(t[e],n);break;case"mixins":t[e]||(t[e]=[]),t[e].push(...n);break;default:throw new Error("Unknown option name.")}}(Us,"mixins",Is);const Bs=[{name:"v-3928e857",path:"/building/air-puffs.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-3928e857").then(n)}},{name:"v-7b9862ab",path:"/building/air-supply.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-7b9862ab").then(n)}},{name:"v-f273fc06",path:"/building/cabinet.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-f273fc06").then(n)}},{name:"v-056c16b3",path:"/building/control.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-056c16b3").then(n)}},{name:"v-ae0f79fc",path:"/building/",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-ae0f79fc").then(n)}},{path:"/building/index.html",redirect:"/building/"},{name:"v-013d4bea",path:"/building/lick-detection.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-013d4bea").then(n)}},{name:"v-704c4f3b",path:"/building/positioning.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-704c4f3b").then(n)}},{name:"v-6c7e8ceb",path:"/building/pupillometry.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-6c7e8ceb").then(n)}},{name:"v-de22c96a",path:"/building/projection.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-de22c96a").then(n)}},{name:"v-33036d6a",path:"/building/reward.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-33036d6a").then(n)}},{name:"v-956dd9f8",path:"/",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-956dd9f8").then(n)}},{path:"/index.html",redirect:"/"},{name:"v-26584971",path:"/building/stage.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-26584971").then(n)}},{name:"v-e6ca92f8",path:"/maintenance/",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-e6ca92f8").then(n)}},{path:"/maintenance/index.html",redirect:"/maintenance/"},{name:"v-00f2c74b",path:"/maintenance/miscellaneous.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-00f2c74b").then(n)}},{name:"v-a239bdaa",path:"/maintenance/positioning.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-a239bdaa").then(n)}},{name:"v-d88216be",path:"/maintenance/projection.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-d88216be").then(n)}},{name:"v-4b031461",path:"/maintenance/reward.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-4b031461").then(n)}},{name:"v-aa17ed6a",path:"/maintenance/stage.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-aa17ed6a").then(n)}},{name:"v-e9450f6a",path:"/software/alert_system.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-e9450f6a").then(n)}},{name:"v-f8229d2a",path:"/software/automated_cronjobs.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-f8229d2a").then(n)}},{name:"v-1f8621f3",path:"/software/automation_pipeline.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-1f8621f3").then(n)}},{name:"v-9d304e46",path:"/software/automation_pipeline_developer.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-9d304e46").then(n)}},{name:"v-d7208806",path:"/software/db_access.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-d7208806").then(n)}},{name:"v-4edd81f1",path:"/software/configure_systems.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-4edd81f1").then(n)}},{name:"v-9d28b566",path:"/software/db_analysis.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-9d28b566").then(n)}},{name:"v-60282e5f",path:"/software/db_organization.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-60282e5f").then(n)}},{name:"v-499f409c",path:"/software/",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-499f409c").then(n)}},{path:"/software/index.html",redirect:"/software/"},{name:"v-e52c6902",path:"/software/manipulation_pipeline.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-e52c6902").then(n)}},{name:"v-01c068eb",path:"/software/pupillometry_guide.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-01c068eb").then(n)}},{name:"v-358893ea",path:"/software/subtask_pipeline.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-358893ea").then(n)}},{name:"v-3faa660b",path:"/software/virmen_guide.html",component:Us,beforeEnter:(t,e,n)=>{fs("Layout","v-3faa660b").then(n)}},{path:"*",component:Us}],Fs={title:"BRAIN CoGS mini VR rigs",description:"Documentation for virtual reality rigs at Princeton BRAIN CoGS project",base:"/",headTags:[["meta",{name:"theme-color",content:"#3eaf7c"}],["meta",{name:"apple-mobile-web-app-capable",content:"yes"}],["meta",{name:"apple-mobile-web-app-status-bar-style",content:"black"}]],pages:[{title:"Air puffs",frontmatter:{title:"Air puffs",lang:"en-US"},regularPath:"/building/air-puffs.html",relativePath:"building/air-puffs.md",key:"v-3928e857",path:"/building/air-puffs.html",headers:[{level:2,title:"Pressure regulator assembly",slug:"pressure-regulator-assembly"},{level:2,title:"Control manifold assembly",slug:"control-manifold-assembly"}]},{title:"Air supply",frontmatter:{title:"Air supply",lang:"en-US"},regularPath:"/building/air-supply.html",relativePath:"building/air-supply.md",key:"v-7b9862ab",path:"/building/air-supply.html",headers:[{level:2,title:"Manifold assembly",slug:"manifold-assembly"},{level:2,title:"Air flowmeter assembly",slug:"air-flowmeter-assembly"},{level:2,title:"Air flow adapter",slug:"air-flow-adapter"}]},{title:"Cabinet",frontmatter:{title:"Cabinet",lang:"en-US"},regularPath:"/building/cabinet.html",relativePath:"building/cabinet.md",key:"v-f273fc06",path:"/building/cabinet.html",headers:[{level:2,title:"Sound absorbing sheet preparation",slug:"sound-absorbing-sheet-preparation"},{level:2,title:"Cabinet assembly",slug:"cabinet-assembly"}]},{title:"Control",frontmatter:{title:"Control",lang:"en-US"},regularPath:"/building/control.html",relativePath:"building/control.md",key:"v-056c16b3",path:"/building/control.html",headers:[{level:2,title:"Solenoid valve driver assembly",slug:"solenoid-valve-driver-assembly"},{level:2,title:"Power supply and NIDAQ control assembly",slug:"power-supply-and-nidaq-control-assembly"},{level:2,title:"Arduino module assembly",slug:"arduino-module-assembly"},{level:2,title:"Programming the Arduino",slug:"programming-the-arduino"},{level:2,title:"USB HUB and Speaker",slug:"usb-hub-and-speaker"}]},{title:"Building a mini VR rig",frontmatter:{title:"Building a mini VR rig",lang:"en-US"},regularPath:"/building/",relativePath:"building/index.md",key:"v-ae0f79fc",path:"/building/",headers:[{level:2,title:"Introduction",slug:"introduction"},{level:2,title:"Recommended steps to assembly.",slug:"recommended-steps-to-assembly"}]},{title:"Lick detection",frontmatter:{title:"Lick detection",lang:"en-US"},regularPath:"/building/lick-detection.html",relativePath:"building/lick-detection.md",key:"v-013d4bea",path:"/building/lick-detection.html",headers:[{level:2,title:"Two lick detection module assembly",slug:"two-lick-detection-module-assembly"},{level:3,title:"Soldering a cable to the feeding spout and headplate holder",slug:"soldering-a-cable-to-the-feeding-spout-and-headplate-holder"}]},{title:"Positioning",frontmatter:{title:"Positioning",lang:"en-US"},regularPath:"/building/positioning.html",relativePath:"building/positioning.md",key:"v-704c4f3b",path:"/building/positioning.html",headers:[{level:2,title:"Automated positioning system",slug:"automated-positioning-system"},{level:2,title:"Manual positioning system",slug:"manual-positioning-system"}]},{title:"Pupillometry",frontmatter:{title:"Pupillometry",lang:"en-US"},regularPath:"/building/pupillometry.html",relativePath:"building/pupillometry.md",key:"v-6c7e8ceb",path:"/building/pupillometry.html",headers:[{level:2,title:"Camera set up",slug:"camera-set-up"},{level:2,title:"Light source set up",slug:"light-source-set-up"},{level:2,title:"Image focus and camera positioning",slug:"image-focus-and-camera-positioning"},{level:2,title:"Explanation of the processing and how to set up the pipeline",slug:"explanation-of-the-processing-and-how-to-set-up-the-pipeline"}]},{title:"Projection",frontmatter:{title:"Projection",lang:"en-US"},regularPath:"/building/projection.html",relativePath:"building/projection.md",key:"v-de22c96a",path:"/building/projection.html",headers:[{level:2,title:"Mirror",slug:"mirror"},{level:2,title:"Projector",slug:"projector"},{level:2,title:"Screen building",slug:"screen-building"},{level:3,title:"Day 1 [time: ~3 hours].",slug:"day-1-time-3-hours"},{level:3,title:"Day 2 [time: ~3 hours]",slug:"day-2-time-3-hours"},{level:3,title:"Day 3 [time: ~1 hour]",slug:"day-3-time-1-hour"},{level:3,title:"Day 4 [time: ~1/2 hour each layer plus drying time]",slug:"day-4-time-1-2-hour-each-layer-plus-drying-time"},{level:3,title:"Day 5 [time: ~1/2 hour each layer plus drying time]",slug:"day-5-time-1-2-hour-each-layer-plus-drying-time"},{level:2,title:"Screen assembly",slug:"screen-assembly"}]},{title:"Reward",frontmatter:{title:"Reward",lang:"en-US"},regularPath:"/building/reward.html",relativePath:"building/reward.md",key:"v-33036d6a",path:"/building/reward.html",headers:[{level:2,title:"Solenoid valve assembly",slug:"solenoid-valve-assembly"},{level:2,title:"Lick spout holder assembly",slug:"lick-spout-holder-assembly"}]},{title:"Home",frontmatter:{home:!0,heroImage:"./images/braincogslogo.png",tagline:"Documentation for building and mantain mini virtual reality rigs at Princeton BRAIN CoGS",actionText:"Quick start",actionLink:"/building/",features:[{title:"Build a mini VR rig",details:"Detailed documentation to build a mini VR rig from scratch"},{title:"Maintenance of a mini VR",details:"Documentation for the maintenance of a mini virtual reality rig modules"},{title:"Software",details:"Documentation for the software"}],footer:"Made by BRAIN CoGS at Princeton Neuroscience Institute"},regularPath:"/",relativePath:"index.md",key:"v-956dd9f8",path:"/"},{title:"Stage",frontmatter:{title:"Stage",lang:"en-US"},regularPath:"/building/stage.html",relativePath:"building/stage.md",key:"v-26584971",path:"/building/stage.html",headers:[{level:2,title:"Stage installation",slug:"stage-installation"},{level:2,title:"Cup with optical flow sensor",slug:"cup-with-optical-flow-sensor"},{level:3,title:"Cup assembly",slug:"cup-assembly"},{level:3,title:"Bottom plate assembly",slug:"bottom-plate-assembly"},{level:3,title:"Assembly",slug:"assembly"},{level:2,title:"Cable and hose carrier (optional)",slug:"cable-and-hose-carrier-optional"},{level:2,title:"GERBER files",slug:"gerber-files"}]},{title:"Maintenance of a mini VR rig",frontmatter:{title:"Maintenance of a mini VR rig",lang:"en-US"},regularPath:"/maintenance/",relativePath:"maintenance/index.md",key:"v-e6ca92f8",path:"/maintenance/",headers:[{level:2,title:"Introduction",slug:"introduction"}]},{title:"Miscellaneous",frontmatter:{title:"Miscellaneous",lang:"en-US"},regularPath:"/maintenance/miscellaneous.html",relativePath:"maintenance/miscellaneous.md",key:"v-00f2c74b",path:"/maintenance/miscellaneous.html",headers:[{level:2,title:"3D Printing",slug:"_3d-printing"},{level:3,title:"Print",slug:"print"},{level:3,title:"Wash",slug:"wash"},{level:3,title:"Cure",slug:"cure"}]},{title:"Positioning",frontmatter:{title:"Positioning",lang:"en-US"},regularPath:"/maintenance/positioning.html",relativePath:"maintenance/positioning.md",key:"v-a239bdaa",path:"/maintenance/positioning.html",headers:[{level:2,title:"Calibrating",slug:"calibrating"},{level:2,title:"Restore",slug:"restore"},{level:3,title:"Recomendation",slug:"recomendation"}]},{title:"Projection",frontmatter:{title:"Projection",lang:"en-US"},regularPath:"/maintenance/projection.html",relativePath:"maintenance/projection.md",key:"v-d88216be",path:"/maintenance/projection.html",headers:[{level:2,title:"Projection calibration",slug:"projection-calibration"},{level:2,title:"Projector bulb replacement.",slug:"projector-bulb-replacement"}]},{title:"Reward",frontmatter:{title:"Reward",lang:"en-US"},regularPath:"/maintenance/reward.html",relativePath:"maintenance/reward.md",key:"v-4b031461",path:"/maintenance/reward.html",headers:[{level:2,title:"Daily clean",slug:"daily-clean"},{level:2,title:"Lines replacement and valve cleaning",slug:"lines-replacement-and-valve-cleaning"},{level:2,title:"Valve calibration",slug:"valve-calibration"},{level:2,title:"Troubleshooting",slug:"troubleshooting"}]},{title:"Stage",frontmatter:{title:"Stage",lang:"en-US"},regularPath:"/maintenance/stage.html",relativePath:"maintenance/stage.md",key:"v-aa17ed6a",path:"/maintenance/stage.html",headers:[{level:2,title:"Running ball replacement",slug:"running-ball-replacement"},{level:2,title:"Optical flow sensor calibration",slug:"optical-flow-sensor-calibration"},{level:3,title:"Image quality and lens focus",slug:"image-quality-and-lens-focus"},{level:3,title:"Lenght scale calibration",slug:"lenght-scale-calibration"},{level:2,title:"Troubleshooting",slug:"troubleshooting"},{level:3,title:"Arduino not recognized",slug:"arduino-not-recognized"},{level:3,title:"Timed out while waiting for a reply.",slug:"timed-out-while-waiting-for-a-reply"}]},{title:"Configure custom slack alerts",frontmatter:{title:"Configure custom slack alerts",lang:"en-US"},regularPath:"/software/alert_system.html",relativePath:"software/alert_system.md",key:"v-e9450f6a",path:"/software/alert_system.html",headers:[{level:2,title:"Set up custom slack alerts",slug:"set-up-custom-slack-alerts"},{level:3,title:"main function guide",slug:"main-function-guide"},{level:3,title:"Slack channel dictionary configuration",slug:"slack-channel-dictionary-configuration"},{level:3,title:"Create and register new webhooks for alerts:",slug:"create-and-register-new-webhooks-for-alerts"}]},{title:"Automated cronjobs in BRAINCoGS (Developer Guide)",frontmatter:{title:"Automated cronjobs in BRAINCoGS (Developer Guide)",lang:"en-US"},regularPath:"/software/automated_cronjobs.html",relativePath:"software/automated_cronjobs.md",key:"v-f8229d2a",path:"/software/automated_cronjobs.html",headers:[{level:2,title:"List of automate processes in BRAINCoGS",slug:"list-of-automate-processes-in-braincogs"},{level:2,title:"Behavior, Manipulation, Optogenetics, Pupillometry tables ingestion (MATLAB Cronjob)",slug:"behavior-manipulation-optogenetics-pupillometry-tables-ingestion-matlab-cronjob"},{level:2,title:"Alert system daily routine",slug:"alert-system-daily-routine"},{level:2,title:"Ephys/Imaging Automation Pipeline process",slug:"ephys-imaging-automation-pipeline-process"},{level:2,title:"Pupillometry Pipeline Queue process",slug:"pupillometry-pipeline-queue-process"},{level:2,title:"Pupillometry Pipeline Check process",slug:"pupillometry-pipeline-check-process"}]},{title:"Ephys/Imaging Automation Pipeline",frontmatter:{title:"Ephys/Imaging Automation Pipeline",lang:"en-US"},regularPath:"/software/automation_pipeline.html",relativePath:"software/automation_pipeline.md",key:"v-1f8621f3",path:"/software/automation_pipeline.html",headers:[{level:2,title:"Initial configuration",slug:"initial-configuration"},{level:2,title:'Automation GUI "regular use" Manual',slug:"automation-gui-regular-use-manual"},{level:3,title:"Default use case",slug:"default-use-case"},{level:2,title:'"Advanced" (select parameters) use case',slug:"advanced-select-parameters-use-case"},{level:3,title:"On section 1:",slug:"on-section-1"},{level:3,title:"On section 2:",slug:"on-section-2"},{level:2,title:"Monitor jobs",slug:"monitor-jobs"},{level:3,title:"Track status",slug:"track-status"},{level:2,title:"Create new sets of processing parameters for recordings",slug:"create-new-sets-of-processing-parameters-for-recordings"},{level:3,title:"Create new Processing parameters (algorithm pararms)",slug:"create-new-processing-parameters-algorithm-pararms"},{level:3,title:"Create new preprocessing parameters (a single step on preprocessing list)",slug:"create-new-preprocessing-parameters-a-single-step-on-preprocessing-list"},{level:3,title:"On section 0:",slug:"on-section-0-2"},{level:3,title:"On section 1b:",slug:"on-section-1b"},{level:3,title:"Create new preprocessing parameters list (a set of preprocessing paramaters)",slug:"create-new-preprocessing-parameters-list-a-set-of-preprocessing-paramaters"},{level:3,title:"On section 0:",slug:"on-section-0-3"},{level:3,title:"On section 1c:",slug:"on-section-1c"}]},{title:"Ephys/Imaging Automation Pipeline in BRAINCoGS (Developer Guide)",frontmatter:{title:"Ephys/Imaging Automation Pipeline in BRAINCoGS (Developer Guide)",lang:"en-US"},regularPath:"/software/automation_pipeline_developer.html",relativePath:"software/automation_pipeline_developer.md",key:"v-9d304e46",path:"/software/automation_pipeline_developer.html",headers:[{level:2,title:"Ephys/Imaging Automation GUI",slug:"ephys-imaging-automation-gui"},{level:2,title:"Workflow management description",slug:"workflow-management-description"},{level:3,title:"Main functions and variables in recording workflow manager",slug:"main-functions-and-variables-in-recording-workflow-manager"},{level:3,title:"Main functions and variables in recording_process workflow manager",slug:"main-functions-and-variables-in-recording-process-workflow-manager"},{level:2,title:"Collab reposiotries to handle Ephys/Imaging Processing",slug:"collab-reposiotries-to-handle-ephys-imaging-processing"},{level:3,title:"BrainCogsEphysSorters",slug:"braincogsephyssorters"}]},{title:"Database Access",frontmatter:{title:"Database Access",lang:"en-US"},regularPath:"/software/db_access.html",relativePath:"software/db_access.md",key:"v-d7208806",path:"/software/db_access.html",headers:[{level:2,title:"First steps",slug:"first-steps"},{level:2,title:"Mount file server volumes",slug:"mount-file-server-volumes"},{level:3,title:"On windows systems",slug:"on-windows-systems"},{level:3,title:"On OS X systems",slug:"on-os-x-systems"},{level:3,title:"On Linux systems",slug:"on-linux-systems"},{level:2,title:"DB Access for Python repository",slug:"db-access-for-python-repository"},{level:3,title:"Prerequisites",slug:"prerequisites"},{level:3,title:"First time configuration",slug:"first-time-configuration"},{level:3,title:"Connection after configuration",slug:"connection-after-configuration"},{level:2,title:"DB Access for MATLAB repository",slug:"db-access-for-matlab-repository"},{level:3,title:"Prerequisites",slug:"prerequisites-2"},{level:3,title:"First time configuration",slug:"first-time-configuration-2"},{level:3,title:"Connection after configuration",slug:"connection-after-configuration-2"},{level:2,title:"DB Access for MATLAB repository (cluster computing)",slug:"db-access-for-matlab-repository-cluster-computing"},{level:3,title:"Prerequisites",slug:"prerequisites-3"},{level:3,title:"First time configuration",slug:"first-time-configuration-3"},{level:3,title:"Connection after configuration",slug:"connection-after-configuration-3"},{level:2,title:"Add researcher to user table",slug:"add-researcher-to-user-table"},{level:3,title:"Add researcher to user table with MATLAB",slug:"add-researcher-to-user-table-with-matlab"},{level:3,title:"Add researcher to user table with PYTHON",slug:"add-researcher-to-user-table-with-python"}]},{title:"Configure behavior & recording systems",frontmatter:{title:"Configure behavior & recording systems",lang:"en-US"},regularPath:"/software/configure_systems.html",relativePath:"software/configure_systems.md",key:"v-4edd81f1",path:"/software/configure_systems.html",headers:[{level:2,title:"Configure new behavior rig system",slug:"configure-new-behavior-rig-system"},{level:3,title:"First steps",slug:"first-steps"},{level:3,title:"U19-pipeline-matlab Repository",slug:"u19-pipeline-matlab-repository"},{level:3,title:"Virmen Repository",slug:"virmen-repository"},{level:3,title:"Behavior data backup task schedule",slug:"behavior-data-backup-task-schedule"},{level:2,title:"Configure new recording system",slug:"configure-new-recording-system"},{level:3,title:"Register recording system",slug:"register-recording-system"}]},{title:"How to use DB (tips, tricks and more)",frontmatter:{title:"How to use DB (tips, tricks and more)",lang:"en-US"},regularPath:"/software/db_analysis.html",relativePath:"software/db_analysis.md",key:"v-9d28b566",path:"/software/db_analysis.html",headers:[{level:2,title:"MATLAB",slug:"matlab"},{level:3,title:"Prerequesites",slug:"prerequesites"},{level:3,title:"Recommended tutorial",slug:"recommended-tutorial"},{level:3,title:"Useful scripts and functions for reseacher general use:",slug:"useful-scripts-and-functions-for-reseacher-general-use"},{level:3,title:"Read behavior file:",slug:"read-behavior-file"},{level:3,title:"Get behavior file location (local & for spock/scotty)",slug:"get-behavior-file-location-local-for-spock-scotty"},{level:3,title:"getfulltrial_data with SpatialTimeBlobs",slug:"get-full-trial-data-with-spatialtimeblobs"},{level:3,title:"get stats from session",slug:"get-stats-from-session"},{level:3,title:"get behaviorfile as db",slug:"get-behaviorfile-as-db"},{level:3,title:"get time from iteration variable",slug:"get-time-from-iteration-variable"},{level:3,title:"plot framerate frequency sessions",slug:"plot-framerate-frequency-sessions"},{level:3,title:"plot framerate frequency levels and rigs",slug:"plot-framerate-frequency-levels-and-rigs"},{level:3,title:"plot velocity sessions",slug:"plot-velocity-sessions"},{level:3,title:"get path table",slug:"get-path-table"},{level:3,title:"Common errors and troubleshooting",slug:"common-errors-and-troubleshooting"},{level:2,title:"PYTHON",slug:"python"},{level:3,title:"Common errors and troubleshooting",slug:"common-errors-and-troubleshooting-2"}]},{title:"Database Organization",frontmatter:{title:"Database Organization",lang:"en-US"},regularPath:"/software/db_organization.html",relativePath:"software/db_organization.md",key:"v-60282e5f",path:"/software/db_organization.html",headers:[{level:2,title:"Lab & Subject DBs",slug:"lab-subject-dbs"},{level:3,title:"1. u19_lab",slug:"_1-u19-lab"},{level:3,title:"2. u19_subject",slug:"_2-u19-subject"},{level:2,title:"Behavior DBs",slug:"behavior-dbs"},{level:3,title:"1. u19_acquisition:",slug:"_1-u19-acquisition"},{level:3,title:"2. u19_action:",slug:"_2-u19-action"},{level:3,title:"3. u19_behavior:",slug:"_3-u19-behavior"},{level:3,title:"4. u19_behavior_subtask:",slug:"_4-u19-behavior-subtask"},{level:3,title:"5. u19_optogenetics",slug:"_5-u19-optogenetics"},{level:3,title:"6. u19_thermal",slug:"_6-u19-thermal"},{level:3,title:"7. u19_puffs",slug:"_7-u19-puffs"},{level:2,title:"Ephys/Imaging DBs",slug:"ephys-imaging-dbs"},{level:3,title:"1. u19_recording:",slug:"_1-u19-recording"},{level:3,title:"2. u19_recording_process:",slug:"_2-u19-recording-process"},{level:3,title:"3. u19_ephys_pipeline:",slug:"_3-u19-ephys-pipeline"},{level:3,title:"4. u19_pipeline_ephys_element:",slug:"_4-u19-pipeline-ephys-element"},{level:3,title:"5. u19_pipeline_probe_element:",slug:"_5-u19-pipeline-probe-element"},{level:3,title:"6. u19_imaging_pipeline:",slug:"_6-u19-imaging-pipeline"},{level:3,title:"7. u19_pipeline_imaging_element:",slug:"_7-u19-pipeline-imaging-element"},{level:3,title:"8. u19_pipeline_scan_element:",slug:"_8-u19-pipeline-scan-element"},{level:3,title:"9. u19_pupillometry:",slug:"_9-u19-pupillometry"}]},{title:"Software",frontmatter:{title:"Software",lang:"en-US"},regularPath:"/software/",relativePath:"software/index.md",key:"v-499f409c",path:"/software/",headers:[{level:2,title:"Introduction",slug:"introduction"}]},{title:"Manipulation pipeline",frontmatter:{title:"Manipulation pipeline",lang:"en-US"},regularPath:"/software/manipulation_pipeline.html",relativePath:"software/manipulation_pipeline.md",key:"v-e52c6902",path:"/software/manipulation_pipeline.html",headers:[{level:2,title:"What does the “manipulation” pipeline include:",slug:"what-does-the-manipulation-pipeline-include"},{level:2,title:"Prerequisites",slug:"prerequisites"},{level:2,title:"Initial set-up",slug:"initial-set-up"},{level:2,title:"Table description",slug:"table-description"},{level:3,title:'"Manipulation" Protocol table',slug:"manipulation-protocol-table"},{level:3,title:'Adding features to "Manipulation" Protocol table',slug:"adding-features-to-manipulation-protocol-table"},{level:3,title:"OptogeneticsStimulationParameters.m:",slug:"optogeneticsstimulationparameters-m"},{level:3,title:'"Manipulation" SoftwareParameters table',slug:"manipulation-softwareparameters-table"},{level:3,title:'"Manipulation" Session table',slug:"manipulation-session-table"},{level:3,title:'"Manipulation" SessionTrial table',slug:"manipulation-sessiontrial-table"},{level:3,title:"Training with new manipulation",slug:"training-with-new-manipulation"},{level:3,title:"Fetching Data",slug:"fetching-data"}]},{title:"Pupillometry Pipeline Guide",frontmatter:{title:"Pupillometry Pipeline Guide",lang:"en-US"},regularPath:"/software/pupillometry_guide.html",relativePath:"software/pupillometry_guide.md",key:"v-01c068eb",path:"/software/pupillometry_guide.html",headers:[{level:2,title:"Instructions to Set up Pupillometry Pipeline on a Rig Machine",slug:"instructions-to-set-up-pupillometry-pipeline-on-a-rig-machine"},{level:3,title:"Pupillometry backup videos task schedule",slug:"pupillometry-backup-videos-task-schedule"},{level:2,title:"Pupillometry DB and data organization",slug:"pupillometry-db-and-data-organization"},{level:2,title:"Steps executed in Pupillometry pipeline",slug:"steps-executed-in-pupillometry-pipeline"},{level:2,title:"Monitor pupillometry processing sessions",slug:"monitor-pupillometry-processing-sessions"},{level:2,title:"Add a new video model to the pipeline",slug:"add-a-new-video-model-to-the-pipeline"},{level:2,title:"",slug:""},{level:2,title:"Review processed data",slug:"review-processed-data"}]},{title:"Subtask pipeline",frontmatter:{title:"Subtask pipeline",lang:"en-US"},regularPath:"/software/subtask_pipeline.html",relativePath:"software/subtask_pipeline.md",key:"v-358893ea",path:"/software/subtask_pipeline.html",headers:[{level:2,title:"What does the “subtask” pipeline include:",slug:"what-does-the-subtask-pipeline-include"},{level:2,title:"Prerequisites",slug:"prerequisites"},{level:2,title:"Initial set-up",slug:"initial-set-up"},{level:2,title:"Table description",slug:"table-description"},{level:3,title:"task.Subtask table",slug:"task-subtask-table"},{level:3,title:"acquisition.SessionSubtask table",slug:"acquisition-sessionsubtask-table"},{level:3,title:'"Subtask" Session table',slug:"subtask-session-table"},{level:3,title:'"Subtask" Block table',slug:"subtask-block-table"},{level:3,title:'"Subtask" BlockTrial table',slug:"subtask-blocktrial-table"},{level:2,title:'Adding code to "Subtask" tables',slug:"adding-code-to-subtask-tables"},{level:3,title:"TwolickspoutsSession table code",slug:"twolickspoutssession-table-code"},{level:3,title:"TwolickspoutsBlock table code",slug:"twolickspoutsblock-table-code"},{level:3,title:"TwolickspoutsBlockTrial table code",slug:"twolickspoutsblocktrial-table-code"},{level:3,title:"Create tables",slug:"create-tables"},{level:3,title:"Training with new subtask",slug:"training-with-new-subtask"},{level:3,title:"Fetching Data",slug:"fetching-data"}]},{title:"ViRMEn User/Developer Guide",frontmatter:{title:"ViRMEn User/Developer Guide",lang:"en-US"},regularPath:"/software/virmen_guide.html",relativePath:"software/virmen_guide.md",key:"v-3faa660b",path:"/software/virmen_guide.html",headers:[{level:2,title:"New task Creation",slug:"new-task-creation"},{level:3,title:"Prerequisites",slug:"prerequisites"},{level:3,title:"Initial set-up",slug:"initial-set-up"},{level:2,title:"Set up training",slug:"set-up-training"},{level:3,title:"Set up motor positioning",slug:"set-up-motor-positioning"},{level:2,title:"Training GUI detailed description",slug:"training-gui-detailed-description"},{level:2,title:"Add animal dialog detailed description",slug:"add-animal-dialog-detailed-description"},{level:2,title:"Tips and Tricks Experiment Code",slug:"tips-and-tricks-experiment-code"},{level:3,title:"Add variables to behavior file",slug:"add-variables-to-behavior-file"},{level:3,title:"Set code ready for simulation",slug:"set-code-ready-for-simulation"},{level:3,title:"Solve common errors during training",slug:"solve-common-errors-during-training"}]}],themeConfig:{repo:"",editLinks:!1,docsDir:"",editLinkText:"",lastUpdated:!1,nav:[{text:"Building",link:"/building/"},{text:"Maintenance",link:"/maintenance/"},{text:"Software",link:"/software/"}],sidebar:{"/building/":["","cabinet","stage","air-supply","positioning","projection","reward","air-puffs","control","pupillometry","lick-detection"],"/maintenance/":["","projection","reward","stage","positioning","miscellaneous"],"/software/":["","db_access","db_organization","db_analysis","virmen_guide","automation_pipeline","automated_cronjobs","automation_pipeline_developer","configure_systems","alert_system","manipulation_pipeline","pupillometry_guide","subtask_pipeline"]}}};n(236);Gn.component("Badge",()=>Promise.all([n.e(0),n.e(4)]).then(n.bind(null,501))),Gn.component("CodeBlock",()=>Promise.all([n.e(0),n.e(5)]).then(n.bind(null,497))),Gn.component("CodeGroup",()=>Promise.all([n.e(0),n.e(6)]).then(n.bind(null,498)));n(237);var Hs={name:"BackToTop",props:{threshold:{type:Number,default:300}},data:()=>({scrollTop:null}),computed:{show(){return this.scrollTop>this.threshold}},mounted(){this.scrollTop=this.getScrollTop(),window.addEventListener("scroll",ks()(()=>{this.scrollTop=this.getScrollTop()},100))},methods:{getScrollTop:()=>window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,scrollToTop(){window.scrollTo({top:0,behavior:"smooth"}),this.scrollTop=0}}},qs=(n(238),Object(Ns.a)(Hs,(function(){var t=this._self._c;return t("transition",{attrs:{name:"fade"}},[this.show?t("svg",{staticClass:"go-to-top",attrs:{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 49.484 28.284"},on:{click:this.scrollToTop}},[t("g",{attrs:{transform:"translate(-229 -126.358)"}},[t("rect",{attrs:{fill:"currentColor",width:"35",height:"5",rx:"2",transform:"translate(229 151.107) rotate(-45)"}}),this._v(" "),t("rect",{attrs:{fill:"currentColor",width:"35",height:"5",rx:"2",transform:"translate(274.949 154.642) rotate(-135)"}})])]):this._e()])}),[],!1,null,"5fd4ef0c",null).exports),Vs=[({Vue:t,options:e,router:n,siteData:r})=>{},{},({Vue:t})=>{t.mixin({computed:{$dataBlock(){return this.$options.__data__block__}}})},{},{},({Vue:t})=>{t.component("BackToTop",qs)}],Ws=["BackToTop"];class Gs extends class{constructor(){this.store=new Gn({data:{state:{}}})}$get(t){return this.store.state[t]}$set(t,e){Gn.set(this.store.state,t,e)}$emit(...t){this.store.$emit(...t)}$on(...t){this.store.$on(...t)}}{}Object.assign(Gs.prototype,{getPageAsyncComponent:ss,getLayoutAsyncComponent:ls,getAsyncComponent:us,getVueComponent:cs});var Ks={install(t){const e=new Gs;t.$vuepress=e,t.prototype.$vuepress=e}};function Ys(t,e){const n=e.toLowerCase();return t.options.routes.some(t=>t.path.toLowerCase()===n)}var Xs={props:{pageKey:String,slotKey:{type:String,default:"default"}},render(t){const e=this.pageKey||this.$parent.$page.key;return ps("pageKey",e),Gn.component(e)||Gn.component(e,ss(e)),Gn.component(e)?t(e):t("")}},Js={functional:!0,props:{slotKey:String,required:!0},render:(t,{props:e,slots:n})=>t("div",{class:["content__"+e.slotKey]},n()[e.slotKey])},Zs={computed:{openInNewWindowTitle(){return this.$themeLocaleConfig.openNewWindowText||"(opens new window)"}}},Qs=(n(239),n(240),Object(Ns.a)(Zs,(function(){var t=this._self._c;return t("span",[t("svg",{staticClass:"icon outbound",attrs:{xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"}},[t("path",{attrs:{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}}),this._v(" "),t("polygon",{attrs:{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"}})]),this._v(" "),t("span",{staticClass:"sr-only"},[this._v(this._s(this.openInNewWindowTitle))])])}),[],!1,null,null,null).exports),tl={functional:!0,render(t,{parent:e,children:n}){if(e._isMounted)return n;e.$once("hook:mounted",()=>{e.$forceUpdate()})}};Gn.config.productionTip=!1,Gn.use(Va),Gn.use(Ks),Gn.mixin(function(t,e,n=Gn){!function(t){t.locales&&Object.keys(t.locales).forEach(e=>{t.locales[e].path=e});Object.freeze(t)}(e),n.$vuepress.$set("siteData",e);const r=new(t(n.$vuepress.$get("siteData"))),o=Object.getOwnPropertyDescriptors(Object.getPrototypeOf(r)),i={};return Object.keys(o).reduce((t,e)=>(e.startsWith("$")&&(t[e]=o[e].get),t),i),{computed:i}}(t=>class{setPage(t){this.__page=t}get $site(){return t}get $themeConfig(){return this.$site.themeConfig}get $frontmatter(){return this.$page.frontmatter}get $localeConfig(){const{locales:t={}}=this.$site;let e,n;for(const r in t)"/"===r?n=t[r]:0===this.$page.path.indexOf(r)&&(e=t[r]);return e||n||{}}get $siteTitle(){return this.$localeConfig.title||this.$site.title||""}get $canonicalUrl(){const{canonicalUrl:t}=this.$page.frontmatter;return"string"==typeof t&&t}get $title(){const t=this.$page,{metaTitle:e}=this.$page.frontmatter;if("string"==typeof e)return e;const n=this.$siteTitle,r=t.frontmatter.home?null:t.frontmatter.title||t.title;return n?r?r+" | "+n:n:r||"VuePress"}get $description(){const t=function(t){if(t){const e=t.filter(t=>"description"===t.name)[0];if(e)return e.content}}(this.$page.frontmatter.meta);return t||(this.$page.frontmatter.description||this.$localeConfig.description||this.$site.description||"")}get $lang(){return this.$page.frontmatter.lang||this.$localeConfig.lang||"en-US"}get $localePath(){return this.$localeConfig.path||"/"}get $themeLocaleConfig(){return(this.$site.themeConfig.locales||{})[this.$localePath]||{}}get $page(){return this.__page?this.__page:function(t,e){for(let n=0;nn||(t.hash?!Gn.$vuepress.$get("disableScrollBehavior")&&{selector:decodeURIComponent(t.hash)}:{x:0,y:0})});!function(t){t.beforeEach((e,n,r)=>{if(Ys(t,e.path))r();else if(/(\/|\.html)$/.test(e.path))if(/\/$/.test(e.path)){const n=e.path.replace(/\/$/,"")+".html";Ys(t,n)?r(n):r()}else r();else{const n=e.path+"/",o=e.path+".html";Ys(t,o)?r(o):Ys(t,n)?r(n):r()}})}(n);const r={};try{await Promise.all(Vs.filter(t=>"function"==typeof t).map(e=>e({Vue:Gn,options:r,router:n,siteData:Fs,isServer:t})))}catch(t){console.error(t)}return{app:new Gn(Object.assign(r,{router:n,render:t=>t("div",{attrs:{id:"app"}},[t("RouterView",{ref:"layout"}),t("div",{class:"global-ui"},Ws.map(e=>t(e)))])})),router:n}}(!1).then(({app:t,router:e})=>{e.onReady(()=>{t.$mount("#app")})})}]); \ No newline at end of file diff --git a/assets/js/vendors~docsearch.d116d088.js b/assets/js/vendors~docsearch.d116d088.js new file mode 100644 index 0000000..10b58e0 --- /dev/null +++ b/assets/js/vendors~docsearch.d116d088.js @@ -0,0 +1,3 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[9],{494:function(t,e,n){ +/*! docsearch 2.6.3 | © Algolia | github.com/algolia/docsearch */ +var r;"undefined"!=typeof self&&self,r=function(){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=22)}([function(t,e,n){"use strict";var r,i=n(1);function s(t){return t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}t.exports={isArray:null,isFunction:null,isObject:null,bind:null,each:null,map:null,mixin:null,isMsie:function(t){if(void 0===t&&(t=navigator.userAgent),/(msie|trident)/i.test(t)){var e=t.match(/(msie |rv:)(\d+(.\d+)?)/i);if(e)return e[2]}return!1},escapeRegExChars:function(t){return t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isNumber:function(t){return"number"==typeof t},toStr:function(t){return null==t?"":t+""},cloneDeep:function(t){var e=this.mixin({},t),n=this;return this.each(e,(function(t,r){t&&(n.isArray(t)?e[r]=[].concat(t):n.isObject(t)&&(e[r]=n.cloneDeep(t)))})),e},error:function(t){throw new Error(t)},every:function(t,e){var n=!0;return t?(this.each(t,(function(r,i){n&&(n=e.call(null,r,i,t)&&n)})),!!n):n},any:function(t,e){var n=!1;return t?(this.each(t,(function(r,i){if(e.call(null,r,i,t))return n=!0,!1})),n):n},getUniqueId:(r=0,function(){return r++}),templatify:function(t){if(this.isFunction(t))return t;var e=i.element(t);return"SCRIPT"===e.prop("tagName")?function(){return e.text()}:function(){return String(t)}},defer:function(t){setTimeout(t,0)},noop:function(){},formatPrefix:function(t,e){return e?"":t+"-"},className:function(t,e,n){return(n?"":".")+t+e},escapeHighlightedString:function(t,e,n){e=e||"";var r=document.createElement("div");r.appendChild(document.createTextNode(e)),n=n||"";var i=document.createElement("div");i.appendChild(document.createTextNode(n));var o=document.createElement("div");return o.appendChild(document.createTextNode(t)),o.innerHTML.replace(RegExp(s(r.innerHTML),"g"),e).replace(RegExp(s(i.innerHTML),"g"),n)}}},function(t,e,n){"use strict";t.exports={element:null}},function(t,e){var n=Object.prototype.hasOwnProperty,r=Object.prototype.toString;t.exports=function(t,e,i){if("[object Function]"!==r.call(e))throw new TypeError("iterator must be a function");var s=t.length;if(s===+s)for(var o=0;o was loaded but did not call our provided callback"),JSONPScriptError:s("JSONPScriptError"," + + diff --git a/building/air-supply.html b/building/air-supply.html new file mode 100644 index 0000000..bd9a6bf --- /dev/null +++ b/building/air-supply.html @@ -0,0 +1,42 @@ + + + + + + Air supply | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Air supply

The air supply module consist of a manifold that is connected to the main lab air supply, a air flow control valve that is connected into the manifold and its output goes to a airflowmeter, which provides a constant flow of air trough an adapter placed in the panel of the cabinet to the cup to make the styrofoam ball float. The manifold also provide air to other modules, such as the air puffs, and has the flexibility to add another manifold if other modules require an air supply.

Air supply module.

# Manifold assembly

If the air puffs are going to be used, we recommend to add the pressure gauge during this step, otherwise place a plug instead of the gauge on the second outlet of the manifold. First, install a 1/2 NPT plug and a Push-to-Connect tube fitting for air straight sdapter, for 3/8" Tube OD x 1/2 NPT Male in the manifold. Then install the pressure gauge or another plug if air puffs are not going to be installed. Finally, install a 3/8 NPT male inlet x 3/8" push-to-connect female outlet air flow control valve into the first outlet of the manifold.

Once assembled, place the manifold in the lower T-slotted profile at the left side of the cabinet (the same as the DIN rails). First, use a T-slotted framing drop-in nut with spring tab, 5/16"-18 thread size and insert a pair of them on the profile. Then, place the pair of 10-24 square nuts at the back of the 3D printed frame to manifold adapter and using 5/16"-18 x 1/2" long low-profile screws screw it to the frame.

Attach the manifold to the adapter using a pair of 10-24 x 1-7/8" long screws.

# Air flowmeter assembly

To assemble the air flowmeter first attach at the top outlet a push-to-connect tube fitting for air +90 degree swivel elbow, for 1/4" tube OD x 1/4 NPT male, and at the bottom inlet a push-to-connect tube fitting for air 90 degree swivel elbow, for 3/8" tube OD x 1/4 NPT male. Then, use a couple of 10-32 x 5/16" long screws to attach the air flowmeter to DIN mounting clip adapter to the air flowmeter. Finally, use a number 8 x 5/16" long rounded head thread-forming screws to attach a spring clip DIN rail mounting adapter.

Attach the airflowmeter to the din rail by inserting the bottom part only and push it from the bottom up and forward at the same time.

Then, insert a firm polyurethane tubing for air 1/4" ID, 3/8" OD from one end into the inlet of the air flowmeter until it click and the tube can't come out of the connector, then measure the distance to the air flow control valve outler connector (bottom of the connector, as seen in the pictures below), cut the hose and connect the hose.

# Air flow adapter

To install the air flow adapter, first screw the push-to-connect tube fitting through-wall adapter, 1/4" tube OD x 1/4 NPT female in the cabinet hole. Then, screw the 1/4 NPT male air nozzle from inside the cabinet in the adapter, and over it insert the air supply to ball adapter to panel gasket and the 3D printed sose to panel adapter, use 4 1/4"-20 x 3/4" long screws and 4 1/4"-20 locknuts to attach it to the panel. Follow the same procedure to connect a 1/8" ID, 1/4" OD firm polyurethane tubing for air from the flowmeter outlet to the cabinet inlet.

Use a very flexible PVC duct hose, 1 1/4" ID, 1 1/2" OD, and attach one screw-on fitting, PVC, for 1 1/4" ID to one end and connect it to the adapter in the cabinet; pull the stage all the way out and measure the length of the hose, cut it and attach a fitting to the other end, finally connect it to the cup in the stage.

+ + + diff --git a/building/cabinet.html b/building/cabinet.html new file mode 100644 index 0000000..61f0d2d --- /dev/null +++ b/building/cabinet.html @@ -0,0 +1,41 @@ + + + + + + Cabinet | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Cabinet

The cabinet is the box made out of T-slotted frames and panels in which all the components of the training rig are going to be held, and works as an sound insulated space in which the mice wild be performing the tasks. All the control and other modules components are going to be placed on one of the sides of the cabinet, and the projector will be placed at the back of it.

Training mini VR rig cabinet.

# Sound absorbing sheet preparation

We use 75% sound absorbing sheets with adhesive backing that are glued at the internal part of all the panels of the cabinet, which helps to isolate the sound from the lab environment, nevertheless the rooms should be silent and darks when the animals are training.

Cut cardboard molds to cut the foams for the panels according to the following table.

Panel Size in inches
Front doors 19" x 9 1/2"
Back doors 9 3/8" x 9 3/8
Sides 19" x 24 3/8"
Top 24 1/2" x 22 3/8"
Bottom back 7 11/16" x 22 3/8"

Place the sound absorbing sheet with the foam looking up, then put the mold on top of it and use a black marker to draw through the edges.

Then place a pair of profiles on top to keep the sheet flat, use a long ruler (or any flat and thin surface, I used a DIN rail to do this) to place it along the marked edges and apply a good ammount of pressure; with a sharp exacto knife cut the sheets following the marker square, we required to pass the knife two times to cut all the way through.

TIP

Constantly change the blades of the exacto knife, a good indicator is if the blade doesn't flow smoothly and sometimes get stuck.

# Cabinet assembly

We use 1.5" x 1.5" T-slotted profile to build the frame of the cabinet and 1/4" black harcell ABS (smooth side up) to build the panels. Our supplier the Knotts Company, which is an authorized supplier of 80/20, and sent them the drawings for a quote. Another option is to buy the pieces described in the drawing from other supplier or suppliers, but it will require to do adjustments, and a lot of holes. Assemble the cabinet following the steps below.

  1. We start building the cabinet from the bottom up. Slide a pair of bottom plate holders (8020 - 2425) into the 24.5 inches long profile. Make sure the top part of the holder is at the same height as the top part of the profile, as shown in the picture below. Repeat the process for another 24.5" long profile.
  1. Insert a standard end fastener to both ends of the 24.5" long profile with the bottom plate holders and to a pair of 22.5" long profiles. First insert the fastener into one of the slots and loosely screw it, repeat the process with the other end making sure the direction of the fastener is the same. Make this for both ends of the 4 profiles.
  1. Arrange the profiles in a square, making sure that the profiles with the plate holders are facing each other to the left and right, and in the correct position (top part of the holder must be at the same height as the top part of the profile); and the 22.5" long profiles are fecing each other at the back and front. Use the 22.05" long profile with holes at 1.5" from the ends to join the front part, and use the 22.05" long profile with holes at 1.5" from both ends and a hole at 11.675" from the top down to join the back part of the rig. Introduce the profiles from the top down and tight screw trough the holes.
  1. Place the aluminum bottom plate on top of the frames, slide the bottom plate holders so that they match the plate holes. If the holes don't match in the lateral position, you can unscrew the holders just enough for them to reach the holes. Use 5/16-18 x 0.625" long screws to tight screw the bottom plate to the holders.

TIP

If working on an elevated table, you could push into the air the structure just enough to have visibility on the bottom and match the holders to the holes, then turn around the structure and repeat the process.

TIP

Use a permanent marker to draw two straight lines on top of the botomm plate using the groves at the sides as shown below, this will be extremely useful for the projection calibration.

  1. Cut 8.2 inches to the top base of the drawer slider, then use 1/4"-20 x 1/2" long low-profile screws to install the 26" long steel base-mount drawer sliders. Screw with M4x0.7 mm, 8 mm long screws the latch holder to the latch holder adapter, then use 1/4"-20 x 11/16" flat head screws to attach the latch holder with the adapter to the bottom plate.
  1. Install the structure to hold the projector at the back of the rig. Set the height of the structure at 3 15/16" from a flat surfate to the top of the profile.

TIP

You can install the projector bottom plate before measuring to make it easier to set the height.

  1. To install the back panel of the rig, first make the hole for the projection to go trough. Make a hole at 2 3/4" from the top of the panel and at the middle of the panel, or 11 5/8" from the side. We recommend to do a small hole first and then use a 1" drill bit or hole saw.

Install the soundproof foam, then cut the hole from the foam.

TIP

To install the soundproof foam first clean the smooth surface of the panel with a solution of 70% ethanol and let dry. Then remove just a small portion of the protective layer of the adhesive part of the sound absorbing sheet as shown below.

Center the sheet in the panel and paste the uncovered portion by applying pressure along the sheet from the top down.

Remove another small-medium portion of the protective layer and apply pressure onto the panel from the top down, repeat the process until the whole sound absorbing sheet is placed into the panel.

Finally, slide down the panel into the T-slotted profiles at the back of the rig, slidw down a 22.5" profile with fasteners already screwed until it reaches the panel and use the holes at the profiles sides to tighten the screws.

  1. For the left panel, first cut the square in which the air supply adapter is going to be attached from the sound absorbing sheet, then glue the sheet to the panel and afterwards cut the hole for the cable and hoses (just like we did in the last step). Install both lateral panels first, then arrange two 24.5" long profile and two 22.5" long profile with fasteners loosely screwed at the four sides of the top panel and place them on top of the structure from the top down. Tight the screws when the structure is in place.

TIP

Sometimes when placing the top panel and profiles they don't fit in properly, if you are having troubles fitting them, loose the screws from the bottom of the four corners and the screws from the middle in the back of the frame so you can push down the top structure. Once the top structure is on place, tighten all the screws.

  1. Assemble the doors by joining a U shape structure first. For the front doors screw at the bottom a 9.65" long profile and a pair of 22.05" long profile, for the back doors form the U shape with 9.65" long profiles. Then slide down the panels with the sound absorbing sheet already in place. After that, screw at the top a 9.65" long profile for both front and back doors. Finally, insert the joining strip along the out edges of the doors.
  1. Insert the joining strip to all of the panels in the cabinet.

  2. Install the DIN rails by screwing 4 DIN rail mounting adapters into the profile using a T-slotted framing drop-in nut, 1/4"-20 thread size. We buy a 2 m long steel DIN rail and cut two pieces at 27.5". Then attach the pair of DIN rail to the mounting adapters and repeat the process for the other rail.

TIP

Before placing the top DIN rail mounting adapter at the back of the rig, slide down the middle door hinge. Alternatively, you could replace the standard framing nut with a 1/4"-20 T-slotted framing drop-in nut to install that door hinge.

  1. Install the doors by screwing the lift-off hinges, you will need to place a couple of them for each door at the top and at the bottom. Finally install the lock using a 1/4"-20 screw and 1/4"-20 T-slotted framing drop-in nut.
+ + + diff --git a/building/control.html b/building/control.html new file mode 100644 index 0000000..ab129cf --- /dev/null +++ b/building/control.html @@ -0,0 +1,41 @@ + + + + + + Control | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Control

The control module consist on a 24V power source, a couple of distribution blocks, which make it easier to connect any other stuff that works on 24V; a custom made solenoid valve driver, an USB NiDAQ card from National Instruments and an Arduino due that is inside a 3D printed housing with a DIN rail clip attached. Each of these parts will be explained in detail below with instructions for assembly.

Control module.

# Solenoid valve driver assembly

We designed a simple solenoid valve driver circuit using a MOSFET, the gate is driven by a digital input that will be supplied by the NIDAQ card, which open and closes the circuit from the solenoid valve to a 24V power supply. We added a diode to protect the circuit from discharge from the solenoid valve. To assembly the solenoid valve driver follow the next steps.

  1. Have the PCB made (we use pcbway since they can make and ship the stencil, you can found our project here (opens new window)) and make sure to order a stencil. We use a manual printer for PCB stencil to spread the soldering paste across the PCB pads evenly. First, place the PCB on the surface using high temperature tape and place the stencil on top of it. Make sure to match the solder pads to the holes of the stencil.
  1. Use solder paste and a flexible wipe down knife and spread evenly the solder paste into the pads. Then lift and remove the stencil.
  1. Place each component into place, we place the resistances (R1, R3, R5, R7, and R9 resistor values are 10K Ohm and R2, R4, R6, R8 and R10 resistor values are 1K Ohm) first, then place the MOSFET and finally the diodes, make sure that the diodes are placed correctly (the band should match the ] symbol on the PCB). The picture below show the correct position of the components.

TIP

Each time you place a component in the pad make sure to slightly press it against the solder paste with the same tweezers that you use.

  1. Use a heat gun (we set the temperature at 1000F) at the lowest intensity allowed (to avoid components flying around) and move it around on top of the components until the solder melt and the components get attached in place.
  1. Remove the high temperature tape and solder the pluggable terminal blocks, place the fillers and slide down the PCB into the case, then close the case.
  1. Place the labels (make sure they are placed correctly) and place the driver on the DIN rail.

# Power supply and NIDAQ control assembly

  1. Place the power supply and the distribution blocks on the DIN rails, connect the power supply to the distribution block input accordigly. The TRACO Power TBLC 50-124 is a 50W power supply, which is more than enough to power both the reward module solenoid valve (7 Watts) and the two air puffs solenoid valves (0.65 Watts each one), and have plenty of power left (~40W) for other modules if required. One power supply could be use for a stack of 2 or 3 rigs if desired.

TIP

Use a standard PC power cable and cut the portion of the connector that goes to the PC, cut the ground cable and connect the neutral cable to the negative input of the power supply and the hot cable to the positive input.

  1. Open the NIDAQ case and make a hole at the middle of the back case. Screw the DIN rail mounting clip to it, then close the case and place the top screws only.
  1. Connect everything!
  • Start by connecting the positive output of the power supply from one of the pins of the red distribution blocks to the V IN input of the solenoid valve driver, then the ground from one of the pins of the black distribution block to the GND pin of the solenoid valve driver.
  • Then connect the one of the GND pins of the solenoid valve driver to the the digital ground pin of the NIDAQ.
  • Connect the solenoid valve driver inputs to the NIDAQ outputs as follows: P0.0 from NIDAQ to V IN 1, P0.1 to V IN 2 and P0.2 to V IN 3.
  • Finally connect the solenoid valve driver outputs to the solenoid valve drivers. Since the solenoid valves doesn't have polarity, you should use the V OUT (+) as common in the valves, you can use one or multiple pins of the solenoid valve driver. Then connect the V OUT 1 (-) pin to the reward solenoid valve, the V OUT 2 (-) pin to the left solenoid valve and the V OUT 3 (-) to the right solenoid valve.

TIP

The solenoid valve driver has more outputs for you to connect and control with the NIDAQ digital outputs any other piece of hardware (like a 24 V IR light source for example), just make sure to wire the ports to the input and output of the driver and match them in the Rig Parameters portion of ViRMEN.

Control module wiring diagram for solenoid valves.

# Arduino module assembly

  1. Have printed the arduino case and screw the arduino. Insert the connector in place and crimp the cables. Make sure to follow the color code and connect the cables to the arduino.
Wiring diagram for Arduino due to connector.
  1. Cover the case and install the din rail mounting clip. Install the arduino module in the top DIN rail.
  1. Make the cable to connect the arduino to the 3D printer cup. Unscrew the outer portion of the connector and insert it into the cable (you need to do this before connecting the cables, otherwise you will not be able to insert the cover and will have to do everything again). Unscrew all the conectors and insert the cable following the color code in the image below, screw them and place the connector cover.

TIP

Place one connector first and connect it to the arduino box placed in the top DIN rail at the outer portion of the rig, then measure the lenght of the cable by inserting into the rig and into the cable carrier. Cut the cable and place the other connector, finally connect it to the 3D printed cup.

  1. Connect the arduino to the computer using a USB Type-C male to micro-USB Type-B male cable (opens new window). Or any other cable matching your setup, we do recommend to use a single tether cable or USB 3.0 cable and avoid using either multiple cables or HUBs (or make sure everything is high speed rated).

# Programming the Arduino

  1. Download the latest version of the arduino IDE (opens new window) and download the Arduino SAM Boards (32-bits ARM Cortex-M3) toolbox from the boards manager (Tools > Boards > Boards Manager), v1.6.11 has been working for us.

  2. Connect the arduino to the computer using the Programming port (opens new window) (connect the cable to the USB port closest to the circular power connector). The arduino should be listed in the devices at the top of the window as Arduino Due (Programming port).

  3. Either download or open from Matlab the firmware from the repository. The file is inside sensors > ADNS_aout_wUSB_1sensor_or_squal_nativeport folder and is named ADNS_aout_wUSB_1sensor_or_squal_nativeport.ino. Make sure you have selecteed the board at the top of the window and upload the firmware by pressing the upload button (right arrow icon).

  4. Wait until the firmware is uploaded (a message in the terminal of the arduino IDE should confirm this) and disconnect the USB cable from the Programming port and connect it to the Native Port (opens new window). The arduino should be programmed and working, you can confirm this by running the rig tester and pressing the Arduino detection and sensor quality buttons.

# USB HUB and Speaker

  1. Use double side tape to glue the USB Hub to the cabinet at the top left portion above the DIN rail and connect everything that must be connected there (if using USB or USB powered speakers, the NIDAQ). Use a USB C extension to connect the hub to the computer.
  1. Place the speaker inside the cabinet and connect to Hub - Make an upper hole on the cabinet for other cables as shown in the picture above. You can use a USB speakers or a desktop speakers and place them on top of the screen plate and connect it to the hub and, if necessary, to the computer audio input.
+ + + diff --git a/building/index.html b/building/index.html new file mode 100644 index 0000000..5006087 --- /dev/null +++ b/building/index.html @@ -0,0 +1,37 @@ + + + + + + Building a mini VR rig | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Building a mini VR rig

# Introduction

This website is a central repository for the documentation regarding the building of mini virtual reality training rigs as part of BRAIN CoGS at Princeton Neuroscience Institute.

Building documentation is divided into modules, each module contains a detailed explanaiton of the building process. The STEP files for of the entire rig can be found here. And a list of parts can be found here (opens new window) or downloaded in xlsx format (opens new window)

If you need any other file, any other format, need help or just wanted to reach out don't hesitate to contact Juan Luna or any other memeber of the BRAIN CoGS team.

  1. Begin with the assembly of the bottom part of the cabinet (steps 1-6 of cabinet assembly). In parallel, you can start with the construction of the screen.
  2. Follow the intructions to assemble the stage and install it in the cabinet.
  3. Screw the mirror and the pillars, but not the top plates that will hold the screen.
  4. Install the air supply hose adapter on the side panel and make the holes on the panel if necessary, install the side panels on the cabinet (step 8 of cabinet assembly).
  5. Make the hole on the back panel for the projector if necessary, install the back panel and slide down the frame (step 7 of cabinet assembly) and insert the joining strip along the out edges of the panels.
  6. Place the adapters on top of the pillars and install the screen (step 2 of screen assembly).
  7. Assemble the top portion of the cabinet (step 8 of cabinet assembly).
  8. Install the DIN rails (steps 11 of cabinet assembly) and the air supply, air puffs if using, and control module.
  9. Install the positioning system in the stage of the rig.
  10. Assemble and install the doors (steps 9-10 of cabinet assembly).
+ + + diff --git a/building/lick-detection.html b/building/lick-detection.html new file mode 100644 index 0000000..1a13547 --- /dev/null +++ b/building/lick-detection.html @@ -0,0 +1,37 @@ + + + + + + Lick detection | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Lick detection

The lick detection module is based on a simple transistor design (Slotnick 2009), we modified the design to allow the detection of 2 lick spouts in the same module. Additionally, we added a DC-DC converter to isolate the circuit from the power source and added a 5V voltage regulator after the relays to have a TTL signal at the output of both circuits.

The module was designed this way to enable a specific task that require the use of two spouts, but it can also be used in a one spout setting (e.g count the number of licks during a task). Below is an example of a setup using two lick spouts during a decision making task developed by one member of the BRAIN CoGS team.

# Two lick detection module assembly

Have the PCB fabricated here (opens new window) (or download the GERBER files and have it made elsewhere). The step by step instructions to solder the components on the solenoid valve driver from the control module can be used as well for this module, making sure to use the appropiate components and placing them as labeled in the PCB.

Label Part No. Description
R1, R2, R4, R5 AC1206FR-0710ML (opens new window) 10M Ohm resistors
R3, R6 AC1206FR-0747KL (opens new window) 47K Ohm resistors
R7, R8 AC1206FR-0710KL (opens new window) 10K Ohm resistors
T1, T2, T3, T4 MMBT2222LT1G (opens new window) BJT Transistor NPN
8L61-12-011 (2) 8L61-12-011 (opens new window) Relay reed SPDT 250MA 12V
U2 UA78L05ACPKE6 (opens new window) Linear Voltage Regulator
No label (middle big square) TRS 2-2412 (opens new window) Isolated Module DC DC Converter
C1 CL31B475KBHNNNE (opens new window) 4.7 µF Ceramic Capacitor
C2 CL31C151JBCNNNC (opens new window) 150 pF Ceramic Capacitor
22 micro IFSC1008ABER220M01 (opens new window) 22 µH Shielded Inductor

After assemblying the module, place the labels as shown in the picture below.

The description of each pin of the lick detector module can be found in the table below.

PIN Description
1. GROUND Input - ground
2. 24V Input - 24V DC
3. OUT LEFT Output - TTL output pin for the left spout
4. OUT RIGHT Output - TTL output pin for the right spout
5. RIGHT SPOUT Input - Connect the right spout to this pin
6. LEFT SPOUT Input - Connect the left spout to this pin
7. HEADPLATE Input - Connect the headplate to this pin
8. COMMON Input - Connect the ground from the NiDAQ (or any acquisition device) to this pin

# Soldering a cable to the feeding spout and headplate holder

  1. Use sandpaper to remove the outer layer of the stainless steel spout at one of the sides if the luer lock connector (as far as possible from the connector tip), do the same with the headplate (wherever you want to place the cable, we recommend to use the arm without the tapped hole to fit a heat shrinkable tube).

  2. Clean the sanded surface with isopropyl alcohol and let it dry. In the meantime, prepare the coaxial cable (we recommend a 26 (opens new window) or 28 (opens new window) AWG coaxial cable like these ones ) by removing the jacket and the shield, then expose the conductor by removing a portion of the insulation material. Repeat the process on the other end of the cable.

  3. Drop a small drop of flux in the sanded surface and place the tip of the solder iron over the flux - the tip might stick to the stainless steel, that's normal - continue heating the surface and use soldering wire (we found lead works best) to solder the coaxial cable to the spout and headplate.

  4. Use heat shrinkable tube to cover the soldering spot.

To close the circuit for detection, you need a contact in the mice body. We solder a lead (repeating steps 1-4) at the headplate holder, but that can be adjusted on different setups.

+ + + diff --git a/building/positioning.html b/building/positioning.html new file mode 100644 index 0000000..7eb5375 --- /dev/null +++ b/building/positioning.html @@ -0,0 +1,41 @@ + + + + + + Positioning | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Positioning

The positioning system is designed to fix the subject within the projection and correct posture boundaries, but also to have high repeatibility, allowing to have specific coordinates for different subjects trained on the same rig. There are two different positioning systems currently used at our facilities, an automated positioning system that ensures repeatibility and personalized positioning for each subject across training rigs and training sessions; and the manual positioning system, which consist of low cost thorlabs components and a positioning tool developed in house.

Automatic (left) and manual (right) positioning system.

The animal position in the ball should prioritize the correct posture for running whithin boundaries of the projection calibration. The projection is calibrated assuming the animal eyes are going to be positioned 0.256 inches behind the center of the ball on the X axis, 1 inch over the top of the center of the ball on the Y axis and centered along the Z axis. A 0.5 inches range error is acceptable.

Projection calibration boundaries and animal position (mouse drawings by Ethan Tyler and Federico Claudi )

# Automated positioning system

The automated positioning system consist of a set of motorized platforms set in a XYZ configuration. We use the small factor 25mm linear stage (LSA25) from Zaber technologies. A 3D printed arm in Nylon 12 with glass beads - PA12 (MJF) from shapeways - from the top motor (height control) was designed, at the end of the arm we designed a stainless steel headplate holder. The whole assembly is attached to the stage breadboard using a custom adapter.

The headplate holder has to be designed to fit the head plate to be used in order to minimize the variability in the pitch, roll and yaw of the head plate and the animal position. This way, the motors can have better repeatability by adjusting the antero-posterior, dorso-ventral and medio-lateral position of the animal.

The positioning system is designed to be fixed at the expected position of the headplate in the antero-posterior (AP) and mediolateral (ML) position as shown in the picture below when the motorized stages are set at midrange.

To assemble the positioning system, first attach the custom made breadboard adapter to the top stage breadboard at the position shown below using 82 Degree Countersink Angle, 1/4"-20 Thread Size, 1/2" Long Drive Flat Head screws. Then attach the first motorized stage at correct position as shown in the image below using Low-Profile, M3 x 0.5 mm Thread, 5 mm Long screws.

Attach the second (AP position) motorized linear stage to the first one using the same kind of screws at the position shown in the image below. Then, attach the Z adapter from zaber technologies (AB106) to the stage using M2 x 0.4 mm Thread, 5 mm Long Low profile socket head screws at the position as shown below.

Attach the third (DV position) motorized linear stage to the AB106 Zaber adapter using Low-Profile, M3 x 0.5 mm Thread, 5 mm Long screws at the position indicated in the image below. Finally, screw the 3D printed arm to the DV position motorized linear stage using M3 x 0.5 mm Thread, 30 mm Long Hex Drive Flat Head screws as shown below.

One of the most importants variables for the mice on the VR tasks are the DV positioning (height), the mice needs to be comfortable enough to properly run on top of the styrofoam ball. The automated positioning system allows to set customizable heights for each subject. The whole coordinated of the subjects can also be stored on a DB and retrieved before training, which improves the repeatibility and decreases the time needed to set the subjects.

# Manual positioning system

The manual positioning system consist of a set of Thorlabs and custom made parts. To assemble it, first attach a 4" post (either PSR-4.0 from siskiyou or RS4 from Throlabs) at the position of the top stage breadboard shown in the image below. Then, attach a 3" post (RS3 from Thorlabs) on top of the previous installed posts.

Screw down a RB2 part from Thorlabs down the right post (looking at the stage from behind), then attach a TR1 using a 4-40 screw to the RB2 clamp. Then slide down and tight a RA90 Thorlabs part to the TR1 post as indicated in the image below.

Finally, screw the custom made stainless steel head plate adapter to the a TR2 post from Thorlans, then attach it to the RA90 and tight it down as shown below.

A positioning tool was designed taking as reference the 2 pillars that are part of the stage of the mini VR rig. The tool consist on a 3D printed part that hold a glued transparency, lines are made with a marker for the Y position of the animal (1st and 2nd dents of the tool) and the Z line (A and B arrows on the tool). The user can easily use this tool to adjust the animal in the right X and Y position, and the height must be fine tuned to allow the animal to run comfortable.

The tool also has space to add a magnet fixed with epoxy resin on the pillars holes to be steady when placed on top of the pillars.

WARNING

The pillars must be placed in the correct holes of the breadboard as shown in the figure, otherwise the distance from the center of the ball could be wrong.

Positioning tool and animal placement (mouse drawings by Federico Claudi )
+ + + diff --git a/building/projection.html b/building/projection.html new file mode 100644 index 0000000..a88da57 --- /dev/null +++ b/building/projection.html @@ -0,0 +1,41 @@ + + + + + + Projection | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Projection

The projection module consist on the screen assembly inside the cabinet, a projector is positioned at the back of the exterior part of the cabinet and it throws the image towards an spherical mirror attached to the cabinet positioned in the bottom part of the screen. The spherical mirror reflects the image onto the dome screen.

Projection assembly. The projector is for display purposes only and it is not the same model than the actual one.

# Mirror

The spherical mirror is custom made from Thorlabs with the item number LA1740-P01-SP, be sure to contact them for a quote before polaceing the order and ask for the price breaks if you're planning to build more than 5 training rigs (it could go down up to 50% from 5 to 10 pieces).

We place the spherical mirror on an aluminum custom made base that is sent to a machine shop. The instruction for the assembly are descripted below.

  1. Start by assembling the mirror holder, which is composed of the custom made holder, one 1" diameter 2" long post (RS1), one 1" diameter 1.5" long post (RS2) and a BA2 post base from Thorlabs. Use a screwdriver thin enough to pass through the hole at the center of the post and apply enough force to properly screw each piece onto each other.
  1. To align the pieces, screw the base but not all the way. Then, place the pieces on a flat surface and make sure that both the mirror base and the BA2 post base lie completely flat on the surface, apply some force with one of your hands to make sure they stay that way and with the other hand tight screw the base.
  1. Use a file to scratch the surface that will hold the mirror, then clean it with ethanol. Use estructural epoxy, follow the instruction on your specific type, and apply to the aluminum base. Make sure to use a nitrile gloves to carefully place the mirror on top of the base and apply some pressure to let it sit flat on the base surface, wait and clean apoxy leakage if any. Let the epoxy dry for 24 hrs.

TIP

Apply just a sufficient ammount of epoxy in the middle of the aluminum base, don't spread it all over since it could leak once you place the mirror and apply pressure on it.

  1. Screw the mirror and the base to the cabinet bottom plate using 1/4-20 screws, make sure to place the base as far as it can get from the stage (push it all the ways toward the projector, then screw it), as shown below.

# Projector

The projector is installed at the back of the cabinet, at the top of a T-slotted frame structure. To assembly, use a couple of T-slot fasteners and place them on the frame at the back of the cabinet. Then, loosely screw the projector aluminum plate, measure 1 and 1/4 inches from the edge of the plate to the intersection of the frames as shown in the pictures below and tighten the screws. Finally, screw the projector to the aluminum plate.

# Screen building

The whole process of screen building can take up to 5 days. We describe the whole process in steps, adding which steps we make in a day and the time it took for us to follow the steps. We recommend to do it this way to allow the materials to properly dry. You could use the time it takes to dry to parallelize the work and assembly other modules in the meantime.

The first step for building the projection module consist on the fabrication of the dome screen. A styrofoam ball of 18" outer diameter and 16" inner diameter is being fabricated by an external provider. For ease of transportation the screens were sent as half spheres.

# Day 1 [time: ~3 hours].

  1. If the balls are shipped in halfs, first mark the equator in each of the half spheres. Use a thread to measure the outer diameter of the screen (should be around 18") and place a mark at the middle (or around 9"), place the thread at the bottom of the half sphere and mark at the sphere the joint of the thread and the middle (9") mark. We use a laser level to project a straight line through both marks and draw a line with a sharpie.
  1. Use 3M Foam Fast 74 CA spray adhesive to glue both half spheres. Spray from 3 to 5 inches away both surfaces and wait for 1 minute, then attach both half spheres making sure to match the equator drawed lines, apply pressure on the union and leave it to dry and harden for at least 15 min.
  1. Use lightweight joint compound to fill the line and the holes the adhesive might have caused, use a hand applicator to spread even on the surface trying to keep it as as smooth as possible. Let the joint compound dry from 30 min to 1 hour.
  1. Place the aluminum plate in a flat surface making sure is hanging with enough space to fit the screen. Use a sharpie to mark a straigth line by joining the marks in the aluminum plate (placed at the middle of the circle) as seen in the pictures. Place the screen in the plate, making sure to align the equator with the plate and the meridian (the mark where the half spheres where joined) with the plate marked line.

    TIP

    Sometimes the diameter of the balls is different from the plate, you can use some paper or carboard and tape it to fill the space between the screen and the plate for it to hang properly.

  1. Glue about 5 inches of the sides and the back of the ball with an electric glue gun and wit for it to harden. Once cold, remove taped paper/cardboard and turn the plate around and glue the whole screen to the aluminum plate, wait for it to harden; turn once more time the plate and finish gluing the top part of the screen to the plate.

# Day 2 [time: ~3 hours]

  1. Place the screen with the plate on a flat surface. We use a couple 14" (1 inch diameter) pillars, other stuff could potentially be used just making sure the ball is freely hanguing from the plate and have enough space (at least ~6 inches) from the bottom of the screen to the flat surface. We place the pillars diagonally for stability.

    Mark a line below 4.75" from the equator of the screen. We use a set of Thorlabs BA2 and 1/2" post (with a post holder) with a 90 degrees 1/2" post holder to insert a sharpie marker as a tool to mark the line. We set the height of the post at 4.75" below the equator and then mark the screen by moving the shapie along making sure the tool is flat on the surface.

  1. Place a mark at the half of the scren across the meridian using the same tool as step 1 in day 1. The place the laser level in the flat surface facing the screen, use the vertical laser to throw a projection and align both marks at the half of the screen across the meridian. Mark a line from the top to the bottom of the screen (at least at the bottom line).
  1. Measure from the joint of the two half spheres 4" to the top and 4.75" to the sides, place a mark and draw by hand a half circle using those 3 points.
  1. Place a mark at 4.75" and at 6" from the midline along the joint of the spheres (at the top) and along the equator. Use the laser level to project a line from the top marks to the marks on the equator and draw with a marker a pointed line.
  1. Place a mark at 2.5" from the equator to the top of the ball along the 4.75" and 6" lines.
  1. Join with a marker (we used a different color to make it noticeable) the intersections between the pointed lines as shown in the pictures below.

    • (A & I) The intersection between the bottom 4.75" line from the equator and the 6" line from the meridian.
    • (B & H) The intersection between the top 2.5" line from the equator and the 6" line from the meridian.
    • (C & G) The intersection between the top 2.5" line from the equator and the 4.75" line from the meridian.
    • (D & F) The intersection between the top joint of the sphere and the 4.75" line from the meridian.
    • (E) The intersection between the top 4" mark from the top joint of the sphere and the meridian.
  2. Use a styrofoam cutter (we use the 200 W Pro Electric Hot Knife from RoMech Foam Cutter) to cut the sphere though the marked lines. We recommend to use a bench vise or C-clamps to hold the sphere through the aluminum plate follow the next steps:

    • Cut the bottom part of the sphere following the line marked at 4.75" below the equator.
    • Cut the line through intersections (B) toward (A).
    • Cut the line through the instersection (D) toward (C).
    • Cut the line through the intersection (B) toward (C).
    • Repeat the steps for the other side.
    • Cut the line through the intersection (D) toward (F).
    • Remove cutted styrofoam part as shown in the picture below.
    • Cut a line from the mark (E) toward the bottom of the sphere.
    • Cut a line through the intersection (D) toward (E) and remove the cutted styrofoam part.
    • Cut a line through the intersection (F) toward (E) and remove the cutted styrofoam part.
  3. Apply joint compound to the crack on the half spheres intersection from the inside of the screen using a curved rubber wipe down knife. Let it dry overnight and apply a second hand if necessary to have a smooth surface.

# Day 3 [time: ~1 hour]

  1. Apply All purpose foam coat + Bounce from Hot Wire Factory following the instructions for mixing (just make sure the mix is thin enough to handle but thick enough to work as a protective layer). Apply one coat to the exterior part of the sphere, if you find the layer to thin you can apply 2 layers. We recommend to first apply to the top part of the sphere from the aluminum plate, then the bottom part and finally the cutted edges of the sphere (everything but the inner surface of the sphere). Let it dry for 24 hrs.

# Day 4 [time: ~1/2 hour each layer plus drying time]

  1. Apply white lightweight spackling to the inner surface of the sphere using a curved rubber wipe down knife, making sure cover the imperfections on the surface as much as you can. Let it dry for ~3 hours (or more depending on ambient temperature and humidity), you can touch the surface and it shouldn't stick to your hand. Sand the surface and apply another layer. Repeat the process from 2 to 3 times until you get a smooth surface on the screen.

# Day 5 [time: ~1/2 hour each layer plus drying time]

  1. Paint the outer part of the screen with a black matte paint (we recommend the black paint on screen wall and ceiling ambien light rejectting acoustic dampening) using a 3" or 4" brush. Do not paint the edges of the screen yet. Apply 2 layers of paint to the outer part.

  2. Use a roller to paint the inner part of the screen. Apply 1 layer of primer (we recommend to use the paint on screen leveling primer) and 2 to 3 layers of silver paint (we use the paint on screen S1 Screen Plus).

  3. Using a 1" brush paint the edges of the sphere with black matte paint.

# Screen assembly

Once the screen is built, follow the isntructions to install them in the cabinet.

  1. Assemble the 1.5" diameter 10" long posts (P10) by screwing a pair of mounting bases (BA2) from Thorlabs at the bottom. Then install the posts to the cabinet bottom plate using 1/4-20 screws at at the closest position to the projector as shown in the picture below.
  1. Have the custom made aluminum screen plate to post adapter in a machine shop, then screw it to the screen plate and place it over the posts. Tight screw the screen to the posts.
+ + + diff --git a/building/pupillometry.html b/building/pupillometry.html new file mode 100644 index 0000000..a96952a --- /dev/null +++ b/building/pupillometry.html @@ -0,0 +1,41 @@ + + + + + + Pupillometry | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Pupillometry

The pupillometry module consist on a monochrome camera mounted at the side of the screen pointing laterally to the face of the mice, the lens used allows to frame the pupil with enough detail to be processed by markeless pose estimation software. The field of view obtained with the lens allows to track sniffing and whisking, altough that is out of the scope of this building guide.

# Camera set up

We use a Teledyne FLIR FFY-U3-04S2M-S camera, the small factor allows to place it right below the aluminum plate holding the screen without taking much space on the rig. We use a 0.4 MP, 121 FPS, monochromatic camera with an IR light source; a mono camera has better sensitivity and allow us to capture the details of the pupil better than the color sensor. Despite the fact that pupillometry can be detected at 30 Hz, we decided to use a 0.4 MP 121 FPS camera to have the flexibility in case we need another kind of measurement (whiskers move), but using the 1.6 MP 60 FPS camera should work fine for pupillometry and should result in a better image resolution.

  1. Make a 1" hole on the screen at the position showed below. If you're setting up a pupillometry module on a built screen first mark the position where the hole is going to be made, then use a precision knife to remove the outer part of the screen (make sure not to introduce the knife all the way into the other side), remove the outer part using your fingers and then use your fingers to remove the styrofoam up to the inner part of the screen (the paint layer). Then, use the precision knife to cut the paint layer in the inner part of the screen, this way the hole from the inside out will be cleaner and the smaller size possible (it will adjust to the diameter of the lens).

TIP

Despite the fact that the screen has a hole in one of the sides, we didn't observe any behavioral impact in any of the pilot -or subsequent- sessions. The position and the fact that the hole is tailored to the diameter of the lens can be the reason.

  1. Set up the camera and position it on the aluminum plate.
  1. Connect it to the computer.

# Light source set up

Explain how to set up the light source at the top of the rig.

# Image focus and camera positioning

Explain step by step how to focus the image and screw all the parts to get the camera in position.

# Explanation of the processing and how to set up the pipeline

Check Pupillometry Pipeline Guide for more information.

+ + + diff --git a/building/reward.html b/building/reward.html new file mode 100644 index 0000000..fea0eb7 --- /dev/null +++ b/building/reward.html @@ -0,0 +1,41 @@ + + + + + + Reward | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Reward

The reward module consist on a open srynge that holds the reward liquid that will be dispensed to the mice through a lick spout controlled by a solenoid valve.

Reward spout module

# Solenoid valve assembly

The solneoid valve assembly consist of a standard plastic 60 mL srynge placed at the top of the rig conncected to a solenoid valve driver using Tygon PVC (for dairy) tubing. Since it's a gravity based module, it is recommended to place the srygne as high as possible. The srynge can be placed in the top frame of the rig cabinet using a 15/16" cable holder (you could use some thorlabs parts placed at the top of the rig to adjust the height of the srynge and place it in a higher position), remove the plunger from the srynge and use a luer lock to 1/16" ID tubing fitting to connect the srynge to the solenoid valve driver (we use the 003-0096-900 model from Parker).

Reward srynge and solenoid valve driver, reward module assembly on the right.

To fix the reward solenoid valve to the DIN rail we use a 3D printed part, to which the solenoid valve is attached using 4-40 x 3/16" long screws and a DIN valve clip using a Rounded Head Thread-Forming Screws no. 8 5/16" long. Assemble them as shown in the picture below and attach it to the bottom DIN rail.

Finally, connect the srynge to the IN plug of the solenoid valve driver and connect the OUT plug to the srynge inside the rig using 1/16" ID 1/8" OD Tygon soft tubing for food, beverages and dairy.

TIP

Ee don't use the cable carrier for this tubing because it has to be replaced every month and it makes maintenance time consuming.

# Lick spout holder assembly

The lick spout holder is designed to be fixed in the sagital and coronal position and adjustable in the Z (height) position. This way the variability in the position of both the mice and the spout is reduced. To this end, we designed a 3D printed arm that holds a spout holder, which also serves as the air puffs delivery system, that is attached to a kinetic base to make it easy to place and remove when the styrofoam ball need to be taken out. The kinetic base is screwed to a dovetail translation stage with 1/4" travel to adjust the height of the spout.

To assemble, follow the next steps.

  1. Have printed the arm (we recommend an external service and PA12GB material) and install a 8-32 thread size, 0.312" installed length heath insert for plastic in the hole at the lower part of the arm that is going to be attached to the kinetic base. Then, screw the top part of the KB1X1 kinetic base from Thorlabs to the arm using an 8-32 thread size, 1/4" long low-profile screw.

TIP

To install the heat insert follow the instructions in the step 3 of the bottom plate assembly in the stage section.

  1. Install the 1/16" tube ID x 10-32 thread male pipe in the back of the spout holder and place it into the arm using a pair of 2-56 thread size, 5/32" long screws. Put the FNS-18-2-2 straight feeding needle from Kent scientific on the spout holder and fix the top part of the holder using a four 100 degree countersink, 0-80 thread, 7/32" long screws.
  1. Print or have printed the breadboard to DT12 adapter and screw the DT12 dovetail translation stage from Thorlabs to the adapter using a 8-32 thread size, 3/8" long flat head screw, making sure the screw to move the stage is facing up (to the ceiling of the rig). Attach at the other end the bottom part of the KB1X1 kinetic base from Thorlabs using an 8-32 thread size, 1/4" long low-profile screw. Finally, install into the breadboard using a pair of 1/4"-20 thread size, 11/16" long flat head screw.

TIP

Due to inaccuracies in the 3D printed part the spout might be out of position, if this problem is present it is recommended to use a different printed breadboard to DT 12 adapter as shown in the picture below, this way the position of the reward spout can be adjusted.

  1. Finally place the arm with the spout holder in place by connecting the top and bottom parts of the kinetic base.
+ + + diff --git a/building/stage.html b/building/stage.html new file mode 100644 index 0000000..c0aca8a --- /dev/null +++ b/building/stage.html @@ -0,0 +1,41 @@ + + + + + + Stage | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Stage

The stage holds a 3D printed cup where the optical flow sensor is placed at the bottom and a hose is connected to deliver a constant air flow to make a styrofoam ball float at the top. The mice is head fixed on top of the ball, allowing it to run, while the optical flow sensor update the virtual world projected on the screen.

Stage assembly with 3D printed cup.

The stage consist on a pair of optical breadboards attached by a set of posts. The posts lenght is calculated so that the stage has the proper height at which the mice will be positioned and the projection will be calibrated. The top optical breadboard is modified to insert the cup that will direct the constant air flow to the bottom of the styrofoam ball and will make it float, allowing the mice to freely move and run.

We send the optical breadboard to be modified at a machine shop. To assemble the stage you have to first screw the 4 posts by attaching a 1" diameter 1" long post to a 1" diamater 2" long post using a 1/4" set screw (alternatively, you can use a 1" diamater 3" long post). Then attach both the top plate and the bottom plate to each end of the 4 posts using 1/4" screws.

Send the adapter to be made at a machine shop, then attach the latch holder to the adapter using a pair of M4 x 0.7mm, 8mm long screws. Attach the adapter to the bottom part of the bottom plate, in the intersection of the middle columns and the second row as shown in the picture below.

# Stage installation

Install the stage into the cabinet using 1/4"-20 1/2" long low profile socket head screws from the bottom of the drawer slider into the breadboard (the stage can be installed in the cabinet before or after placing the 3D printed cup). Extend the drawer all the way out and place the stage on top of it, align it according to the image below.

# Cup with optical flow sensor

The cup has 2 main components, the cup itself that includes a circular arm through which a constant air flow will be introduced to the inner part and a connector that will transmit the power and data from the sensor to the arduino that is part of the control module of the training mini VR. The second main component is the bottom plate, that has attached the optical flow sensor, a mirror, and a LED printed circuit board (PCB).

Cup with optical flow sensor.

# Cup assembly

We use a 3D printing external service to manufacture the cup, Nylon 12 works fine and ideally the top curved surface of the cup should be smooth (smoothing it manually with fine sandpaper does the work).

  1. Use a transparent epoxy to place a small ammount aroung the circular hole in the middle of the cup from the bottom up and place the 30 mm gorilla glass window, gently press the window making sure the epoxy covers the edges to avoid air leakage but making sure it doesn't spread into the middle of the mirror.
  1. Cut the cables from the 8 pin connector to 4 inches and remove the tip of the plastic protective cover, also remove the unused lead (in this case the dark purple/ brown cable), cut the black and red 26 AWG cables at 3 inches and remove the plastic cover from the tips as well. Place a female crimp pin in each cable one at the time and use the crimping tool following the instructions here (opens new window). For the grey and red cables, crimp the black and red 26 AWG cables with them respectively; as shown in the picture below.

    WARNING

    Leads colors might change depending on the connector used, just make sure to follow the same color code across the circuit.

  1. Insert each crimped cable into the housing with the correct position, according to the following picture.

    TIP

    The strain relief barrel sometimes ends up a little overly flattened, making it too wide to fit comfortably into the crimp pin housing. In such situations, you can use a pair of pliers to gently squeeze the wider axis of the barrel into a more cylindrical shape that will slide easily into the housing. This tip is taken directly from the source (opens new window)

  1. Insert the connector into the cup hole and screw.

# Bottom plate assembly

The bottom plate design is sent to a machine shop to be made in aluminum. The bottom plate will hold the optical flow sensor which, due to space constrains, is place horizontally in the front part of the plate (toward the mice and the back to the screen) facing a 45 degrees mirror right below the gorilla glass window, instead of being placed directly at the bottom of the styrofoam ball. We also add a printed circuit board with a resistance and an IR LED to illuminate the bottom part of the ball.

  1. We send the sensor holder to be made at a machine shop in aluminum, but i could also be 3D printed. Solder the 90 degrees angled pins to the optical flow sensor, then use a pair of 4-40 1/4" long screws to screw the sensor to the sensor holder (one at the top left and one at the bottom right is enough).

  2. We use an external service to make our PCBs using the GERBER files, some options are PCBway or OSH park. Add some solder to the pads, then place the IR LED on top, making sure the pin ID matches the PCB ID mark as seen in the picture below (the ID pin is a small dent on one of the square corners of the LED, you might need a magnifying glass for this) and use a fine tip to solder it to the PCB. Repeat the process with the resistance and finally solder the pins.

  1. Use the heat insert installation tool to install a 4-40 x 0.17" long heat insert in the mirror and IR LED printed holder. Insert the correct tip into the soldering iron, then place the insert in the tip and connect it to a wall outlet; wait for a few seconds until it is hot and place it in the holes of the mirror holder. Press until the whole insert is inside and the surface is flat.
  1. Cut a first surface mirror in a 1" x 0.75" square. Use a strong 2 side tape and cut some squares to fill both of the surfaces of the mirror and IR LED holder. Paste both the mirror and the PCB.
  1. Screw the sensor and the mirror to the aluminum bottom plate.

# Assembly

  1. Laser cut a rubber gasket to be placed between the aluminum plate and the cup. Connect the cables from the connector to the optical flow sensor, making sure the ground cable (grey) is at the bottom pin of the sensor (the one closer to the bottom plate). Use the thin red and black cables to connect to the IR LED PCB to the positive and negative pin respectively.
  1. Place the rubber gasket between the bottom plate and the 3D printed cup and screw the bottom plate. Make sure that the optical flow sensor is between the cables connector and the air hose connector as shown in the figure below.
  1. Screw the bottom plate to the cup and screw the cup to the top plate of the stage, the air hose connector should be facing the upper right part of the top optical breadboard, so that the optical flow sensor is directed toward facing the mice.

# Cable and hose carrier (optional)

We place a cable and hose carrier to avoid them to be crushed or damaged while the stage is taken in and out. It is also useful to keep the working space clean and neat. Follow the next steps for assembly.

  1. Print the carrier to breadboard adapter and install it in the bottom part of the top breadboard (it is easier to screw it before the posts, but you can always take the top breadboard apart or screw brom the bottom). Place the M6 x 1mm square nuts on the square hole in the bottom part of the adapter and use a pair of M6 x 1mm, 10 mm long to screw the carrier mounting bracket to it.
  1. Place the second mounting bracket for the carrier on the 2 holes at the bottom left part of the aluminum bottom plate in the cabinet.
  1. We order a 3 ft. long cable and hose carrier. Count 17 pieces of the carrier and snap off the rest of them. Attach the carrier to both mounting brackets.

# GERBER files

  1. Gerber files for the IR LED available here.
+ + + diff --git a/images/braincogslogo.png b/images/braincogslogo.png new file mode 100644 index 0000000..bf3de8c Binary files /dev/null and b/images/braincogslogo.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..6917ebc --- /dev/null +++ b/index.html @@ -0,0 +1,41 @@ + + + + + + BRAIN CoGS mini VR rigs + + + + + + + + + + + +
hero

+ BRAIN CoGS mini VR rigs +

+ Documentation for building and mantain mini virtual reality rigs at Princeton BRAIN CoGS +

+ Quick start +

Build a mini VR rig

Detailed documentation to build a mini VR rig from scratch

Maintenance of a mini VR

Documentation for the maintenance of a mini virtual reality rig modules

Software

Documentation for the software

+ + + diff --git a/maintenance/index.html b/maintenance/index.html new file mode 100644 index 0000000..f0c250b --- /dev/null +++ b/maintenance/index.html @@ -0,0 +1,37 @@ + + + + + + Maintenance of a mini VR rig | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Maintenance of a mini VR rig

# Introduction

This website is a central repository for the documentation regarding the maintenance of mini virtual reality rigs as part of BRAIN CoGS at Princeton Neuroscience Institute.

Maintenance documentation is also divided into modules, each module contains the process and tools needed to perform both preventive and corrective maintenance, as well as common troubleshooting.

+ + + diff --git a/maintenance/miscellaneous.html b/maintenance/miscellaneous.html new file mode 100644 index 0000000..8374a8e --- /dev/null +++ b/maintenance/miscellaneous.html @@ -0,0 +1,37 @@ + + + + + + Miscellaneous | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Miscellaneous

# 3D Printing

# Print

  1. Export 3D print design from software as STL file and make sure to select the units.
  2. Use PreForm to open the STL file, use the orientation tool and generate the support structures as needed.
  3. Ensure that the build platform is clean and placed correctly. Properly insert the resin tank and resin cartridge - making sure the tap is open.
  4. Upload the print.
  5. Printer will indicate if any component is missin, also will prompt if it needs leveling. Follow the instructions accordingly.
  6. Once finished, remove the build platform and close the cover to avoid light exposure to uncured resin in the tank.

# Wash

  1. Put some gloves on. Remove the print from the platform using a scraper -or just remove the quick release platform by pushing inwards both arms.
  2. Rinse the print with IPA using a squeeze bottle. You can use compressed air to remove resin from concealed areas.
  3. Open the Form Wash and place the print inside.
  4. Select resin-appropiate wash cycle (opens new window) and start.
  5. Rinse additional uncured resin using the squeeze bottle and let it dry for at least 30 minutes.

# Cure

  1. Once the print is completely dry, place it inside the Form Cure and select the appropiate curing settings (opens new window), then press start.
  2. Once finished, allow the print to cool down to ambient temperature. This will avoid warping.
  3. Remove the print and remove the supports.
  4. Use sandpaper to remove any remaining suport marks.
+ + + diff --git a/maintenance/positioning.html b/maintenance/positioning.html new file mode 100644 index 0000000..2273010 --- /dev/null +++ b/maintenance/positioning.html @@ -0,0 +1,41 @@ + + + + + + Positioning | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Positioning

# Automated positioning

The automated positioning system maintenance conssist of checking the motors and making sure everything is properly tighten (use loctite if necessary, altough it is recommended). Troubleshooting is mostly related to the motors driver.

# Calibrating

If the motors don't respond correctly, open the Zaber software. Select the 'Basic Movements' option and click on the home button. This action will take the motors to their absolute zero position.

# Restore

If sending the motors home doesn't work, the next step is to restore the affected motor. In the basic options, select the motor experiencing the issue, click on the settings icon, and choose 'Restore'.

# Recomendation

After completing the training, please send all the motors home.

# Manual

The manual positioning system is low maintenance and consist mainly of tightening the Thorlabs parts and maintening the positioning tool in shape.

+ + + diff --git a/maintenance/projection.html b/maintenance/projection.html new file mode 100644 index 0000000..2b07072 --- /dev/null +++ b/maintenance/projection.html @@ -0,0 +1,74 @@ + + + + + + Projection | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Projection

The projection module maintenance consist primarily on the initial calibration and subsequent maintenance calibrations that should be performed every ~6 months, and the projector bulb replacement that must be done whenever the projector ask for it, since the projector has an internal counter of how many hours the bulb has been used.

# Projection calibration

The projection system use a spherical mirror to project into the dome. The image transformation is based on a hemispherical dome projection principle (opens new window).

Creating correctly warped images given a particular projector, mirror, and dome arrangement requires finding the point on the projector frustum for any point on the dome. The problem is three-dimensional but can be turned into a simpler two dimensional problem by firstly translating the geometry so the spherical mirror is at the origin and then rotating the geometry so that the point on the mirror, dome, and projector lies in a single plane.

The projector is located at P1, the mirror is of radius r, and the position on the dome is P2. The path length from the projector to the mirror is L1, the path length from the dome to the mirror is L2. In the case of a spherical mirror: the line at mid-angle between the vectors OP1 and OP2 and its intersection with the surface of the mirror defines the reflection point.

Fermat’s principle states that light travels by the shortest route, so the reflection point on the mirror can be found by minimising the total light path length from the projector to the position on the dome, namely minimising (L1^2 + L2^2)^1/2. It is quite simple in the case of a spherical mirror: the line at mid-angle between the vectors OP1 and OP2 and its intersection with the surface of the mirror defines the reflection point.

The projection calibration will align the projection within certain boundaries, specifically the horizon, the center and the left and right side will be aligned to the physical position of the dome. This method has a trade-off in the time that has to be inverted to perform the alignment vs the accuracy of the rendered projection, since the height of the towers might be different across systems.

To calibrate the projection:

  1. Turn on the projector and make sure to mirror the projection horizontally, otherwise left/right will be inverted.
  2. Place the alignment tool. We recommend to use a 3 laser alignment tool (opens new window). Use the marked lines at the bottom plate to align the center and sides lasers on the dome. Set the height of the horizontal laser to 12" from the bottom plate.
  3. Create a new subject in the ViRMEn training GUI and select the livecalibration.mat experiment. This is the calibration world that was developed, it is necessary to set the simulation mode to true in the RigParameters file. This will project a static world with 3 towers set at the center and at the left and right of the mouse eyes. The goal is to align the horizon to the animal eyes position, the center tower to the center of the screen and the left and right towers to the mouse eyes position.
  4. Set the initial vairables of the projection parameters as below (these parameters has been obatained empirically and they are a good starting point for the training mini VR rigs as they are built).
%% Mini VR projection parameters
+% Spherical screen radius
+proj_param_Rs           =    8;
+
+% Screen's center location relative to the animal eyes
+proj_param_xsm          =    1.814;
+proj_param_ysm          =    0;
+proj_param_zsm          =    0.47;
+
+% Mirror position relative to the animal eyes
+% Mirror position measurement is facilitated knowing that the center of 
+%spherical mirror is (43.8-24.2=)19.6mm (0.77in) behind the back surface.
+proj_param_xOm          =   5.582;
+proj_param_yOm          =   0;
+proj_param_zOm          =   -6.62;
+
+% Radius of the spherical mirror (Silver coated lens LA1740-Thorlabs)
+proj_param_r            =   1.724;
+
+% Projector position relative to the mirror center
+proj_param_xP1o         =   11.1;
+proj_param_yP1o         =   0;
+proj_param_zP1o         =   -0.6;
+
+% Horizontal coordinate shift and rescaling
+proj_param_hrescaling   =   5.5;
+proj_param_hshift       =   0.000;
+
+% Vertical coordinate shift and rescaling
+proj_param_vrescaling   =   5.5;
+proj_param_vshift       =   -1.017;
+
+
+
  1. First, try to align certain variables by physically moving the projector. Unscrew the plate that holds the projector and move it horizontally until the middle tower is centered with the laser. Make sure that the left and rigth towers are equidistant from the middle of the dome, you may be able to achieve this by slightly moving the plate forward from one side or the other.

TIP

The position of the towers will move when the plate is thightened, don't untight the screws all the way if it is not necessary, unthight until it is possible to move the plate and checking the projection, then thight and adjust accordingly.

The goal of doing this physically instead of modifying the projection transformation parameters is that it decreases the differences across the projections in different training rigs.

  1. Adjust the rest of the parameters until the towers and horizon are aligned. A brief description of how each parameter adjust the projection can be found below.
  • Rs should not be modified.
  • xsm will adjust the middle tower height without affecting the lateral towers, values should be around [1.5 - 2]. This value canbe adjusted since there will be idiosincrasies due to the screen fabrication.
  • zOm will adjust the horizon. This value can be adjusted since there can be differences in how the mirror is glued to its aluminum base.
  • xP1o will extend or contract the lateral towers and zP1o will lower or elevate the middle tower but will modify the distal part of the lateral towers. These values can be adjusted since there are idiosincrasies in the origin of the projection between projectors in their fabrication.
  • The hrescaling and the vrescaling should be the same, otherwise it will modify elongate or contract the projection, and there will be significant differences across sytems.
  • The hshift and vshift will move the entire projection up, down, left or right. Ideally the hshift should be 0 if the projection is calibrated manually, but it can be modified if necessary since it shouldn't affect significatly the projection across differente systems.
Projection calibration. Due to the principle of the spherical mirror projection, the lateral towers will be slightly curved, the projection should be fine as long as they are equidistant and centered at the top (or the bottom, just make sure to keep the same policy across rigs).

# Projector bulb replacement.

The projector has a counter used to determine how long the bulb has been used, it will emit an alert that the bulb should be replaced. Make sure to have in stock projector bulbs and follow each projector instruction to replace it.

+ + + diff --git a/maintenance/reward.html b/maintenance/reward.html new file mode 100644 index 0000000..23c695f --- /dev/null +++ b/maintenance/reward.html @@ -0,0 +1,41 @@ + + + + + + Reward | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Reward

The reward module maintenance consist mainly on the daily cleaning of the lines and valves, valve calibration procedure done every 2 weeks and a monthly cleaning of the reward valves and replacement of the lines if using a combination of condensed milk and water (70-30).

# Daily clean

Follow the next procedure:

  1. Once the day’s training is complete, gently pull the rig’s central stage towards you, leaving some space between you and the rig’s edge. Take the reward spout out of its holding area and place it on the edge of the rig’s stage, reward spout pointed down, place a beaker under it to dispose all the liquids.

  2. If milk was prepared that day, pour any remaining milk from the syringes into the milk bottle. Otherwise, empty all of the syringes into the beaker.

  3. Pick up the bottle of H2O2 from the shelf labeled “Cleaning Supplies” and fill the syringe with the hydrogen peroxide up to the 40 mL line.

  4. When ready, press the “Open Valve” button in the regiment window or open the valve using the rig tester and let the H2O2 drain into the beakers.

  5. Once the syringes are empty, fill the syringes with 100 mL in total of distilled water and let them drain into the beakers. When the distilled water reaches the 10 mL line on the syringe, press the “Close Valve” button.

# Lines replacement and valve cleaning

This maintenance procedure should be done monthly if using a combination of condensed milk and water as reward during mice training, we currently don't have an accurate range for other kind of reward liquid but estimate to do it every 2 months for sucrose and water solutions and way longer for plain water.

Follow the procedure below.

  1. Remove all liquids in the circuit, first by emptying the srynge into a dispose beaker and then open the valve to realease the rest of the liquid into the same beaker.

  2. Take off the lines from the srynge to the valve and from the valve to the spout, use those lines to measure and cut the new lines from tubing.

  3. Follow the appropiate instructions to clean the valves, for the 003-0096-900 model from Parkerparker valves fill a srynge with hydrogen peroxide, connect it to the IN port and flush it while the valve is open, repeat the process filling the srynge with air this time.

  4. Use a srynge to flush the spout with hydrogen peroxide, then fill the srynge with air and flush it once more.

  5. Install a new srynge and connect the circuit with the new lines.

# Valve calibration

To perform the valve calibration we determine the time required to deliver 0.1 ml in total after valve opened 25 times. That is, each drop should have volume of 4 microliters. Follow the steps below.

  1. Gather the following materials: A one mL Eppendorf with a mark at 0.1 mL and a blunt metal tipped syringe.

  2. Open MatLab and open the solenoidValveCalibration.m and RigParameters files.

  3. Make sure that the spout is a vertical position at the same height as it would be with an animal, place the eppendorf under the reward spout and run the solenoid valve calibration script.

  4. Once the run time has ended and every drop collected, use the blunt metal tipped syringe to drag any extraneous drops into the pool at the bottom of the eppendorf. If the pool of milk isn't at 0.1 ml (whether it is over or under), change the run duration time next to the command that reads “timeValveOpen =” in the Solenoid Valve Calibration window, and click “Run” when ready, keep adjusting until the pool of milk is at 0.1 mL.

  5. Once the milk is close to the 1 ml mark, then change the value of the rewardDuration parameter in the Rig Parameters window.

  6. Be sure to save (click Ctrl and S at the same time) what was changed in the Rig Parameters window if the run duration was changed.

# Troubleshooting

Troubleshooting is mostly done from top down. Check first for clogging or anything else from srynge to valve, then from valve in to valve out, then from valve out to spout, and clean or replace accordingly.

+ + + diff --git a/maintenance/stage.html b/maintenance/stage.html new file mode 100644 index 0000000..f059d87 --- /dev/null +++ b/maintenance/stage.html @@ -0,0 +1,42 @@ + + + + + + Stage | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Stage

The stage maintenance consist mainly on the replacement of the ball, and the optical flow sensor calibration.

# Running ball replacement

  1. Glue two 8" diameter half balls (opens new window) using lightweight styrophoam glue (opens new window). Make sure to use a fair ammount of glue, press each half against each other (make sure to squeeze them together for a few seconds to make sure the ball halves remain stuck to each other) and use your finger to flat the excess of glue laong the edges. Let them sit for a few hours or overnight.

  2. Once set, use an abrasive brush (opens new window) or a sanding sponge (opens new window) to slighlty rough the surface of the ball, this will make help improving the quality of motion detection by the optical flow sensor.

  3. Once the Styrofoam ball is smoothed, use a red sharpie to label the ball, then use a black industrial sharpie to mark the ball with a cross-hatch design - try to ensure that there are no large white gaps in-between the cross-hatch design.

# Optical flow sensor calibration

# Image quality and lens focus

The image quality from the optical sensor should be maximized in order for it to obtain reliable measurements, which can be achieved by:

  • Ensuring sufficient infrared (IR) illumination (but increasing it past a certain threshold does not help).

  • Adjusting the focal plane of the M12 lens to be at the surface to be measured.

  • Using a surface with more texture (of the appropriate size given the limited number of sensor pixels).

The ADNS-3080 chip reports a SQUAL value that can be read out using software as explained below. This value needs to be at least 30 if the velocities to be measured are around 100cm/s-150cm/s. For lower values of SQUAL, the sensor tends to under-measure the actual displacement, with the size of the effect increasing with higher surface velocities. The following are examples of images of a Styrofoam ball at various SQUAL values ranging from unusable to ideal (for velocities not far exceeding 100cm/s).

Follow the procedure below to adjust the focus of the optical flow sensor lens.

  1. Load Arduino Code\ADNS_image_v1\ADNS_image_v1.ino in the Arduino IDE.

  2. Edit the reset_pin to 6 and select_pin to 10 values (lines 20-24).

  3. Upload the Arduino code to the board. Note that you will have to reprogram the board after this to use it as a displacement readout.

  4. Print the left side of the following image (an optical spoke target) using a laser printer. The spoke target consists of lines of vanishing size towards the center, therefore allowing you to probe the single pixel limit of the optical sensor as shown in the calibrated image (from the sensor) in the right:

  1. Find some way of placing the spoke target in front of the optical sensor at the same location and orientation as the actual surface to be measured. For example for the mouse virtual reality rig it can be taped onto a Styrofoam ball and the ball can be suspended at the height it would usually be at during experiments.

  2. Run the Matlab Code\Calibration\display_image.m function. It is programmed to continuously display the sensor image for a predetermined amount of time, and can be terminated by pressing <Ctrl+C>.

  3. Adjust the IR LED so that it points towards the center of the surface to be imaged. You should see the illuminated region shift around in the display_image figure.

  4. The display_image figure is normalized so that the brightest regions appear white and the darkest regions appear black, i.e. absolute luminosity information is not available. You can change this behavior by editing the code to replace imagesc(im) (line 66) with image(im) and setting the color scale manually: set(gca, 'CLim', […]) +Oblique illumination can help increase feature contrast on uneven surfaces, but in general just illuminating the largest amount of surface available is sufficient.

  5. Adjust the focus of the optical sensor lens by rotating it. You should see the spoke target lines get sharper and the SQUAL value increase if you’re going in the right direction. You should be able to find a distance at which the SQUAL value is maximal (there is a decent amount of leeway).

  6. Replace the spoke target with the actual surface to be measured, and verify that the SQUAL value is still high enough (>> 30). Values of 50-80 have been achieved with Styrofoam balls, the higher end if they have been “weathered” by running mice.

  7. If the SQUAL value is 30-ish or worse, consider using a more textured surface. For example, scour the Styrofoam ball with steel wool.

# Lenght scale calibration

Follow the procedure below to calibrate the lenght scale of the optical flow sensor.

  1. Load Arduino Code\ADNS_aout_wUSB_1sensor\ADNS_aout_wUSB_1sensor.ino in the Arduino IDE.

  2. Upload the Arduino code to the board.

  3. Suspend a Styrofoam ball on an axle, or a cylindrical Styrofoam wheel, at the position it would be in relative to the optical sensor in a real experiment. Mark a reference position on the ball, e.g. with a piece of black tape as shown in the mouse VR calibration photo below.

  1. Ensure that Matlab Code\Calibration\calibrateBall.m is either in the current folder in the Matlab console, or otherwise in the Matlab path, before continuing the rest of this procedure.

  2. While holding the ball in place, run the calibrateBall script.

  3. Spin the ball 10 times (this can be done quickly), counting the number of times that the black tape returns to approximately its original location.

  4. If necessary, a small correction can be made to rotate the ball further until the tape is exactly at its original position. This should cancel out errors incurred in the previous step.

  5. Stop calibrateBall by pressing Ctrl+C.

  6. Input fclose(instrfindall) at the Matlab command line to close Arduino communications.

  7. Input [dx,dy] at the Matlab command line to view the accumulated displacements. If the optical sensor has been correctly aligned w.r.t. the axis of rotation of the ball, one of these displacements should be large (> thousands) and the other one small (< tens).

  8. In the following the measured displacement along the axis of interest will be referred to as nDots, and the number of revolutions used as nRev.

  9. Repeat this measurement until satisfied (with more rotations if necessary), then enter the obtained constants into RigParameters.m.

  • ballCircumference: Actual displacement (e.g. in cm) of the calibration surface per revolution. For an 8-inch diameter Styrofoam ball, this is its circumference, 63.8cm.
  • sensorDotsPerRev: This should be set directly to nDots/nRev in the case of a single sensor. In the case of two sensors, use the code sensorDotsPerRev = RigParameters.sensorCalibration() and set the latter as described below.
  • sensorCalibration: This is only used for two sensors, which may have differing constants. In this case use the appropriate MovementSensor label for the sensor of interest to record dotsPerRev, e.g.: dotsPerRev(MovementSensor.FrontVelocity) = nDots/nRev;

# Troubleshooting

Troubleshooting should be done from cleaning the 3D cup and window first, making sure the ball is in proper conditions, and then the optical flow sensor replacement if necessary, then the arduino. If the arduino is the problem, refer to the troubleshooting guide in the control portion of the documentation.

# Arduino not recognized

If the arduino is not recognized by the rig tester arduino detection button follow the next steps:

  1. First check if the arduino is being detected by the CPU by opening the device manager windows (typing device manager in the search bar) and clicking on the Ports (COM&LPT) label to display the list of devices connected.

    • If the Arduino is listed there, then the COM port might have changed. Make sure the COM port listed in the device manager matches the arduinoPort variable in the rig parameters file. Restart Matlab and try again.
  2. If the Arduino is not listed on the device manager window it could be either a faulty cable or a broken Arduino. Start by troubleshooting the Arduino (cables might be harder to check since many times they have intricate paths behind the rig).

    TIP

    You can perform a quick check before removing the arduino from the box to discard that the cable is faulty. Unplug the arduino USB cable from the black box on the DIN rail and connect a new arduino, if this one is recognized in the device manager window, then proceed to the following steps, otherwise go ahead and change the cable.

    • Disconnect both the cable and the connector of the black box holding the arduino and take it out of the DIN rail (by slightly pushing it downwards and pulling the bottom part towards you).

    • Open the box by unscrewing the 4 screws holding the cover and the 2 screws holding the arduino to the 3D printed box.

    • Remove the arduino and replace it with a new one. Screw it to the box and screw the cover. Place the box with the new arduino into the DIN rail and connect first the sensor cable and then the US cable.

    • Program the arduino following this instructions.

  3. If the cable is malfunctioning, then replace the cable. We recommend to use a USB Type-C male to micro-USB Type-B male cable (opens new window). Or any other cable matching your setup, but make sure it is a single tether cable or USB 3.0 cable, and avoid using either multiple cables or HUBs (or make sure everything is high speed rated).

# Timed out while waiting for a reply.

This error could be caused by a corrupted firmware in the Arduino. To solve follow the steps on instructions to program the arduino again.

+ + + diff --git a/software/alert_system.html b/software/alert_system.html new file mode 100644 index 0000000..e2adca3 --- /dev/null +++ b/software/alert_system.html @@ -0,0 +1,58 @@ + + + + + + Configure custom slack alerts | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Configure custom slack alerts

# Set up custom slack alerts

  1. Follow Database Access with Python instructions
  2. On U19_pipeline_python repository open u19_pipeline/alert_system/custom_alerts directory
  3. Create a new python file with a meaningful name for the alert: (e.g. subject_bias.py)
  4. Copy skeleton code from u19_pipeline/alert_system/alert_code_skeleton.py
  • All slack alert code has two parts: a slack channel configuration and a main function described on the next section:

# main function guide

  • This function should return a pandas DataFrame where each row will be a slack alert message on configured channels.
  • You can use datajoint to get data for the alert (e.g. custom_alerts/rig_bias.py) or simply call os scripts (e.g. custom_alerts/braininit_storage.py)
  • All columns of the dataframe will be included in the alert. (Don't add too many !!)
  • Dataframe Example with slack notification message:
Example Dataframe for notification
Example Notification from previous DataFrame
  • You can check examples of some alers in the u19_pipeline/alert_system/custom_alerts directory

# Slack channel dictionary configuration

  • The slack channel configuration is a dictionary to link corresponding slack channels and conversations with an specific alert.

  • The dictionary has two keys: 'slack_notification_channel' and 'slack_users_channel'

  • slack_notification_channel General channels names to send notifications.

  • slack_users_channel Private direct message to send notificatons.

  • You can add a list of channels to each of the keys:

  • slack_notification_channel Any webhook_name (see next section)

  • slack_users_channel Any user_id with configured slack_weebhook (see next section)

# Check available notification channels:

# MATLAB
  1. Execute fetch(lab.SlackWebhooks,'*')
# Python
  1. Execute:
  • lab = dj.create_virtual_module('lab', 'u19_lab')
  • lab.SlackWebhooks.fetch(as_dict=True)

# Check available user channels:

# MATLAB
  1. Execute fetch(lab.User & "slack_webhook <> ''",'slack_webhook')
# Python
  1. Execute:
  • lab = dj.create_virtual_module('lab', 'u19_lab')
  • (lab.User & "slack_webhook <> ''").fetch('KEY', 'slack_webhook', as_dict=True)

# Create and register new webhooks for alerts:

  1. Create a new slack channel if needed (for notification channels).
  2. Follow instructions to create webhooks from: Slack documentation
  3. Copy slack webhook from slack API web page.

# Add notification channels:

# MATLAB
new_slack_webhook = struct
+new_slack_webhook.webhook_name = (notification channel name)
+new_slack_webhook.webhook_url  = (webhook url from slack API)
+insert(lab.SlackWebhooks,new_slack_webhook)
+
# Python
lab = dj.create_virtual_module('lab', 'u19_lab')
+new_slack_webhook = dict()
+new_slack_webhook['webhook_name'] = (notification channel name)
+new_slack_webhook['webhook_url']  = (webhook url from slack API)
+lab.SlackWebhooks.insert1(new_slack_webhook)
+

# Update user channel webhook notification channels:

# MATLAB
user = struct
+user.user_id = (NETID of user)
+update(lab.User & user,'slack_webhook', (webhook url from slack API))
+
# Python
lab = dj.create_virtual_module('lab', 'u19_lab')
+user = dict()
+user['user_id'] = (NETID of user)
+user['slack_webhook'] = (webhook url from slack API)
+lab.User.update1(user)
+
+ + + diff --git a/software/automated_cronjobs.html b/software/automated_cronjobs.html new file mode 100644 index 0000000..def5fde --- /dev/null +++ b/software/automated_cronjobs.html @@ -0,0 +1,41 @@ + + + + + + Automated cronjobs in BRAINCoGS (Developer Guide) | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Automated cronjobs in BRAINCoGS (Developer Guide)

  • There are some processes that are triggered automatically in BRAINCoGS.
  • All these processes are handled by u19proc virtual machine administered by PNI Help. Contact Garrett T. McGrath gmcgrath@princeton.edu for permissions to it.
  • All processes are handled by u19prod user account so it's not linked to any personal account.

# List of automate processes in BRAINCoGS

  • Behavior, Manipulation, Optogenetics, Pupillometry tables ingestion
  • Alert system daily routine
  • Ephys/Imaging Automation Pipeline process

# Behavior, Manipulation, Optogenetics, Pupillometry tables ingestion (MATLAB Cronjob)

  • Execution schedule: daily at 4:00 am
  • Location in u19proc: /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline-matlab/scripts/call_u19_night_cronjob.sh
  • Overview: Call populate_tables.m script. Ingest all Behavior related tables from acquision.SessionStarted & acquisition.Session new records from that day. Check the populate_tables.m script for more information

# Alert system daily routine

  • Execution schedule: daily at 3:00 am
  • Location in u19proc: /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline_python/u19_pipeline/alert_system/call_cronjob_alert.sh
  • Overview: Call cronjob_alert.py script .
  • Read Alert System section for more information.

# Ephys/Imaging Automation Pipeline process

  • Called when: at every 30th minute.
  • Location in u19proc: /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline_python/u19_pipeline/automatic_job/call_cronjob_automatic_job.sh
  • Overview: Call cronjob_automatic_job.py (Ephys Imaging cronjob script) . Check if a new recording has been added from RecordingProcessJobGUI or a job (recording process) has advanced to a new status. If any of these have occurred the "next" function or process is called for the recording and/or job.

# Pupillometry Pipeline Queue process

  • Called when: at every 20th minute.
  • Location in u19proc: /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline_python/u19_pipeline/automatic_job/call_pupillometry_queue_jobs.sh
  • Overview: Call pupillometry handler check_pupillometry_sessions_queue . Queue new job to spockvm2 for pupillometry session.

# Pupillometry Pipeline Check process

  • Called when: daily at 2:00 am
  • Location in u19proc: /home/u19prod@pu.win.princeton.edu/Datajoint_projs/U19-pipeline_python/u19_pipeline/automatic_job/call_pupillometry_check_jobs.sh
  • Overview: Call pupillometry handler check_processed_pupillometry_sessions . Check if job in spockvm2 for pupillometry has finished and retrieve data to ingest in pupillometry_session_model_data table.
+ + + diff --git a/software/automation_pipeline.html b/software/automation_pipeline.html new file mode 100644 index 0000000..1b06821 --- /dev/null +++ b/software/automation_pipeline.html @@ -0,0 +1,41 @@ + + + + + + Ephys/Imaging Automation Pipeline | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Ephys/Imaging Automation Pipeline

# Initial configuration

  • Note: These steps are only needed if a label in red with "Configuration needed" is shown on the top right corner of the GUI.
Configuration needed label
Configuration screen
  1. Switch to "System Configuration" tab.
  2. Click "Start Configuration" button.
  3. In "System Name" dropdown, select corresponding system (normally named room#-Recording#).
  4. In "Associated Behavior Rig" dropdown, select corresponding rig paired with recording system.
  5. Click "Add Rig to System" button.
  6. Repeat steps 4 & 5 until all rigs associated to recording system are added.
  7. In "Recording Modality" dropdown select corresponsing modality of the recording system.
  8. In "Recording Root Folder" area, click folder button to search for Parent path where all recordings will be stored.
  9. Click "Configure System" button.
System configured correctly

If something was configured incorrectly, you can repeat the whole process.

# Automation GUI "regular use" Manual

  • The automation GUI is located on the desktop in all microscope/ephys recording system across BRAINCoGS. You can identify it by a desktop BRAINCoGS icon called "Recording_Automation_GUI".
  • It is encouraged to register & process every recording with the Automation GUI just after recording has ended.

# Default use case

  1. Open the GUI just after recording has ended.
  2. Select the recording directory from dropdown list in section 1.
  • If no behavior associated with this recording uncheck ****
  1. Check "Add surgery & insertion device if missing" checkbox if you want to add electrode/microscope/optic fiber insertion coordinates.
  2. Select behavior session corresponding to recording from dropdown list in section 2.
  3. Click Register Recording button.
Automation GUI main screen
  • If no surgery data is found for the subject, a small form to insert surgery and device insertion coordinates will be shown.
Add surgery data form
  • Common coordinates for previous recordings:
Area ml(mm) ap(mm) depth(mm) theta(°) phi(°) rho(°)
mPFC L HEMIS -0.6 1.8 3.8 -45 -9 180
mPFC R HEMIS 0.6 1.8 3.8 45 9 0
HPC L HEMIS -1.5 2 1.8 -45 -9 180
HPC R HEMIS 1.5 2 1.8 45 9 0
  • Wait until recording has been copied to PNI storage resources (cup).
Dialog shown while copying session
  1. After recording has been transferred a small dialog with recording id will be shown.
Dialog shown when recording has been transferred
  1. User can check basic info of the new recording in the "Recording Table" tab. This tab will be active after recording is transferred.
Recording table tab screenshot

# Notes

  • This use case assumes that default parameters will be used to process the recording.

# "Advanced" (select parameters) use case

  1. Follow 1-4 from Default use case
  2. Uncheck "Use default processing parameters for recording?" checkbox
  3. Click "Select parameters >>>" button
Parameter selection main screen
  1. On the "Select parameters" tab (assume that all probes/fovs are going to be processed with same parameters)

# On section 1:

  1. In Preprocessing Params Lists dropdown Select a Preprocessing Param list
  • You can check which preprocessing steps are defined for that list on the listbox to the right)
  • If you select a preprocessing step from the listbox you can check the specific parameters for that preprocessing step on the text area to the right.

# On section 2:

  1. In Processing Params" dropdown select a Processing parameter suited for recording
  • If you select a processing parameter from the dropdown you can check the specific parameters for it on the text area to the right.
  1. Click Register Recording button.
  • Next actions are idential to the "Default use" case

# Monitor jobs

  • After a recording is submitted to processing the user is able to track, reprocess and visualize all jobs corresponsing to that recording.
Manage Processing Jobs main screen

# Track status

  1. Switch to "Manage Processing Jobs" tab.
  2. Use "User", "Subject" & "Date" dropdwons / edits to find desired jobs
  3. Select row corresponding to the corresponding job:
  • Corresponding Job Status history is shown for selected job.

# If status of job is in error status (-1, -2; "Error in recording process"):

  • You can open the Error log file on the bottom right corner by clicking "Open Error Log File" button.
  • If you consider that what cause the error is solved now, you can rerun job by clicking "Rerun job" button.

# If status of job is in finished status (7, 8; "Dat in element"):

  • You can open the Output log file on the bottom right corner by clicking "Open Output Log File" button.
  • You can visualize results from processing by clicking the bottom rightmost buttons: (Open Phy, Open IBL Atlas for ephys Open Suite2p-GUI for imaging)
Visualization tools available

# Rerun jobs

# Create new sets of processing parameters for recordings

  • In order to process recordings with parameters different than default you need at least one of the following:
  1. A new ser or processing parameters (parameters for the algorithm to process, e.g. kilosort, suite2p).
  2. A list of preprocessing steps formed by a set of preprocessing params (e.g. perform catgt + tprime before kilosort).
Create parameters screen

# Create new Processing parameters (algorithm pararms)

  • Note: You need a json file with all parameters ready before starting this process.
  • Here is an example of a kilosort parameter json file. It can serve you as an example for creating your own:
  1. Switch to "Create Parameters" tab.

# On section 0:

  1. In "recordig modality" dropdown select to which modality the parameters correspond.
  2. In "user" dropdown Select your NETID username (select general-user if this parameter will be shared by many users).

# On section 1a:

  1. In "proc. Param Method" dropdown, select which method (algorithm) these parameters refer to.
# If the algorithm is not found on "proc. Param Method" dropdown:
  • Check "define new proc. param method ?" checkbox.
  • Write new processing method name in "New Proc. Param. method" edit
  • Check automation pipeline developer guide to add corresponding processing code. (LINK MISSING)
  1. In "proc. Param Set Description" edit, write a small description for the new parameters.
  2. Click "Upload Proc-Parm Set json file" button and search/load for your json file with parameters. You can check your parameters on the text area on the right.
  3. Click "Register Proc. Param Set" button.

# Create new preprocessing parameters (a single step on preprocessing list)

  • Note: You need a json file with all parameters ready before starting this process.
  • Here is an example of a catgt parameter json file. It can serve you as an example for creating your own:
  1. Switch to "Create Parameters" tab.

# On section 0:

  1. In "recordig modality" dropdown select to which modality the parameters correspond.
  2. In "user" dropdown Select your NETID username (select general-user if this parameter will be shared by many users).

# On section 1b:

  1. In "Preproc.-Param Method" dropdown, select which method (tool) these parameters refer to.

# If the tool is not found on "Preproc.-Param Method" dropdown:

  • Check "define new prerproc.-param method ?" checkbox.
  • Write new preprocessing method name in "New Preproc.-Param method" edit.
  • Check automation pipeline developer guide to add corresponding preprocessing code. (LINK MISSING).
  1. In "Preproc.-Param Set Description" edit, write a small description for the new parameters.
  2. Click "Upload Preproc.-Parm Set json file" button and search/load for your json file with parameters. You can check your parameters on the text area on the right.
  3. Click "Register PreProc. Param Set" button.

# Create new preprocessing parameters list (a set of preprocessing paramaters)

  • Note: If you just created a preprocessing parameter, restart GUI.
  1. Switch to "Create Parameters" tab.

# On section 0:

  1. In "recordig modality" dropdown select to which modality the parameters correspond.
  2. In "user" dropdown Select your NETID username (select general-user if this parameter will be shared by many users).

# On section 1c:

  1. In "Pre-Params List Name" dropdown, write a suitable name for the list.
  2. In "Pre.-Param List Description" edit, write a small description for the new list.
  3. From "Pre.-Params steps" dropdown select the desired preprocessing step as part of the list.
  4. Click "Add Preparam Steps" button
  5. Repeat steps 6 & 7 to add all desired preprocessing steps for the list.
  6. Use "v" & "^" buttons to set order of preprocessing steps.
  7. Use "x" button to delete an unwanted preprocessing step.
  8. Click "Register pre param list" button.
+ + + diff --git a/software/automation_pipeline_developer.html b/software/automation_pipeline_developer.html new file mode 100644 index 0000000..576b17f --- /dev/null +++ b/software/automation_pipeline_developer.html @@ -0,0 +1,47 @@ + + + + + + Ephys/Imaging Automation Pipeline in BRAINCoGS (Developer Guide) | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Ephys/Imaging Automation Pipeline in BRAINCoGS (Developer Guide)

The Ephys/Imaging Automation Pipeline in BRAINCoGS main goals are:

  • Automate spike sorting and imaging segmentation for all recordings
  • Centralize/Standardize paths for Recording Data Storage
  • Unify & Register Ephys/Imaging Processing
  • Store processed data in BRAINCoGS Database (DJ)

To accomplish this we developed three tools:

# Ephys/Imaging Automation GUI

# Workflow management description

Workflow management code creates and coordinates of a set of tasks for all recordings that were registered with the GUI to make sure they are entirely processed.

Shell code executed as a cronjob for workflow management: +(call_cronjob_automatic_job.sh +)

Workflow management is composed mainly by two classes that handles recordings and recording_processes (recording_processes or jobs are how recordings are composed)

  • Ephys recordings are composed by one or many independent probe electrophysiology recordings. Each probe recording correspond to a job in the workflow management
  • Calcium imaging recordings are composed by one or many independent field of views image stacks. Each field of view image stack correspond to a job in the workflow management.

The class that manages workflow at the recording level is (RecordingHandler)

Workflow manager diagam at the recording level

# Main functions and variables in recording workflow manager

  • recording_status_dict in (Params Config file): This dictionary defines status definitions and corresponding functions to execute.
  • pipeline_handler_main in (RecordingHandler): Main function in recording workflow +
    1. Executes corresponding functions based in status.
    2. Executed every 30 minutes to check for new recordings to be handled.
    3. Send notifications for processed and failed functions.
  • modality_preingestion in (RecordingHandler): Main ingestion function from recording to recording_process tables. There are subcalls depending on modality of recording (ephys or imaging).

# Imaging preingestion main steps:

  • imaging_preingestion in (RecordingHandler): Ingestion to recording_process table for an imaging recording. Get all FOVs (TIFF stacks) for the recording and assign a new job for each one with corresponding parameters fetched from selection done in automation GUI. +AcquiredTiff populate function in (Imaging pipeline): Auxiliar script to call populate_Imaging_AcquiredTiff script in MATLAB.
  • populate_Imaging_AcquiredTiff in (populate_Imaging_AcquiredTiff): Population calls to: +
    1. u19_imaging_pipeline.AcquiredTiff: Each recording is divided into Tiff Splits (e.g. Mesoscope recordings contain multiple tiff stacks that will be processed independently). (Code here)
    2. u19_imaging_pipeline.SyncImagingBehavior: Find correspondence between virtual reality frame in the behavior experiment and Calcium Imaging frame in recording. +(Code here)
ERD for imaging pipeline at the recording level

# Ephys preingestion main steps:

  • electrophysiology_preingestion in (RecordingHandler): Ingestion to recording_process table for an ephys recording. Get all probes for the recording and assign a new job for each one with corresponding parameters fetched from selection done in automation GUI.
  1. Ingest ephys_pipeline.EphysPipelineSession table
  2. Ingest ephys_element.ProbeInsertion table
  3. Ingest ephys_element.EphysRecording table
  4. Ingest ephys_pipeline.BehaviorSync table: Find corresponding iteration in ephys recording with frame from Virmen behavior task (Code here ) ( and here ).
  5. For each probe (insertion_number) in EphysSession insert a Processing (job) in u19_recording_process.Processing
ERD for ephys pipeline at the recording level

# Main functions and variables in recording_process workflow manager

  • recording_process_status_dict in (Params Config file): This dictionary defines status definitions and corresponding functions to execute.
  • pipeline_handler_main in (RecProcessHandler): Main function in recording process workflow
  1. Executes corresponding functions based in status.
  2. Executed every 30 minutes to check for new recordings to be handled.
  3. Send notifications for processed and failed functions.
  • transfer check/review in (transfer_check/review): Executes and monitors globus transfer from PNI to PrincetonUniversity clusters. (Deprecated)
  • slurm_job_queue/check in (slurm_job_functions): Generate slurm file and queue the job in the cluster that will process recording process. Monitor job to check if it has already finished.
  • populate_element in (slurm_job_queuew): After processing jobs populate imaging or ephys element tables downstream from results file.
Workflow manager diagam at the recording process level
ERD from behavior session to recording process tables

# Collab reposiotries to handle Ephys/Imaging Processing

# BrainCogsEphysSorters

# Set up instructions for BrainCogsEphysSorters in cluster system

+ + + diff --git a/software/configure_systems.html b/software/configure_systems.html new file mode 100644 index 0000000..7f27f5a --- /dev/null +++ b/software/configure_systems.html @@ -0,0 +1,41 @@ + + + + + + Configure behavior & recording systems | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Configure behavior & recording systems

# Configure new behavior rig system

# First steps

# Mount cup PNI drives

  1. From Windows Explorer, select "Map Network Drive" and enter:
  • \\cup.pni.princeton.edu\braininit\ (for braininit)
  • \\cup.pni.princeton.edu\u19_dj\ (for u19_dj)
  1. Authenticate with your NetID and PU password (NOT your PNI password, which may be different). When prompted for your username, enter PRINCETON\netid (note that PRINCETON can be upper or lower case) where netid is your PU NetID.

# Install MATLAB 2019 or higher

# Download and install NiDAQmx from National Instruments website

# Download and install Microsoft visual studio community 2019. Make sure to select the option desktop development with C++

# Instal Git for Windows

  1. Install from this link
# Installation options:
  • Use Git from the Windows Command Prompt (5th pane)
  • Checkout as-is, commit as-is (6th pane)

# Create ssh key to clone repositories

  1. Open Git Bash
  2. ssh-keygen -t ed25519 -C "alvaroluna.pni@gmail.com"
  3. Leave empty passphrase (Hit Enter two times)
  4. eval "$(ssh-agent -s)"
  5. ssh-add ~/.ssh/id_ed25519

# Add key to virmen user in github

  1. Copy ssh public key to clipboard in Git Bash clip < ~/.ssh/id_ed25519.pub
  2. Open https://github.com/login
  3. Login with vrrigs user (ask your Lab Manager for password)
Vrrigs GitHub login
  1. Access Settings -> SSH and GPG Keys
Vrrigs ssh keys section
  1. Click New SSH Key button
  2. Add a meaningful title to the key and paste public key from the clipboard in "Key" text area.
  3. Click Add SSH Key button

# Compiler

  1. Install Visual Studio Code Compiler; make sure to select C++ support from the menu. https://visualstudio.microsoft.com/downloads/
  2. In MATLAB, Run mex -setup -v. This sets up the compiler. It should output something like found "Microsoft Visual C++ 2015"

# U19-pipeline-matlab Repository

  1. Open Git Bash and execute: cd /c/Experiments
  2. Clone U19-pipeline-matlab Repository, git clone git@github.com:BrainCOGS/U19-pipeline-matlab.git

# MATLAB Instructions

  1. Run dj_initial_conf(0)
  2. Insert user and password for the DB

# Virmen Repository

  1. Create C:\Experiments directory
  2. Open Git Bash and execute: cd /c/Experiments.
  3. Execute in git config --global user.email "alvaroluna.pni@gmail.com".
  4. Clone Virmen Repository, called TankMouseVR git clone https://github.com/BrainCOGS/TankMouseVR.git.
  5. Rename directory C:\Experiments\TankMouseVR to C:\Experiments\ViRMEn.

# MATLAB Instructions

  1. run install_virmen inside C:\Experiments\ViRMEn
  • If compilation fails. Run mex -setup c++ to select Visual Studio C++ Compiler
  1. Open file C:\Experiments\ViRMEn\RigParameters.m and edit corresponding variables:
  • rig: (RigName on the format: Room#-"Rig"#-T)
  • rig_type: (miniVR or NormalVR)
  • add NIDAQ Channles in corresponding variables (Ask lab manager about these parameters)
  • Mini VR projection parameters (Ask lab manager about these parameters)
  1. run lab.utils.add_behavior_rig(RigParameters.rig).
  2. run live_calibration experiment (Ask lab manager about this process).
  3. Create a MATLAB shortcut and set Start in as C:\Experiments\ViRMEn.
  4. Add this shortcut to the Windows task bar in the bottom.
MATLAB Shorcut example

# Behavior data backup task schedule

  1. On Windows type "Task Scheduler"
  2. Open Task Scheduler "App"
  3. On right hand side menu, click on "Create Task" Action
Task scheduler menu
  1. Name new task as new_data_backup
Task scheduler General Tab
  1. Add a trigger to run task daily at 11:00 pm
Task scheduler Trigger Tab
  1. Add an action: add this line to the Program/script edit: C:\Experiments\U19-pipeline-matlab\scripts\cmd_copy_behavior_files
Task scheduler Action Tab
  1. Hit OK button

# Configure new recording system

  • First install all things necessary for appropiate recording modality. (Spike GLX for electrophysiology, ScanImage for imaging).
  1. From Windows Explorer, select "Map Network Drive" and enter:
  • \\cup.pni.princeton.edu\braininit\ (for braininit)
  • \\cup.pni.princeton.edu\u19_dj\ (for u19_dj)
  1. Authenticate with your NetID and PU password (NOT your PNI password, which may be different). When prompted for your username, enter PRINCETON\netid (note that PRINCETON can be upper or lower case) where netid is your PU NetID.
  2. Copy Automation GUI files: copy \\cup.pni.princeton.edu\braininit\Shared\AutomationGUI_Installation\AutomationGUI_update to the Desktop.
  3. Run Desktop\AutomationGUI_update\firstTimeAutomationGUI.BAT
  • Install git bash and anaconda from it.
Anaconda avanced options step
  • On Anaconda advanced options step: check "Add Anaconda3 to my PATH environment variable" checkbox.
  1. Run Desktop\AutomationGUI_update\update_AutomationGUI.BAT
  2. Follow instructions to install Recording Automation GUI. (Also called Workflow Console GUI).
Anaconda avanced options step

# Register recording system

  • On a computer with access to the database (e.g. any Rig Computer).
  1. Open MATLAB
  2. Execute: lab.utils.add_recording_system((recording_system_name), (modality)) where:
  • recording_system_name: (on the format: Room#-Recording).
  • modality: (one of the following: electrophysiology, 2photon, 3photon, mesoscope).
+ + + diff --git a/software/db_access.html b/software/db_access.html new file mode 100644 index 0000000..112b878 --- /dev/null +++ b/software/db_access.html @@ -0,0 +1,63 @@ + + + + + + Database Access | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Database Access

# First steps

# Mount file server volumes

  • There are several data files (behavior, imaging & electrophysiology) that are referenced in the database

  • To access these files you should mount PNI file server volumes on your system.

  • There are three main file servers across PNI where data is stored (braininit, Bezos & u19_dj)

# On windows systems

  1. From Windows Explorer, select "Map Network Drive" and enter:
  • \\cup.pni.princeton.edu\braininit\ (for braininit)
  • \\cup.pni.princeton.edu\Bezos-center\ (for Bezos)
  • \\cup.pni.princeton.edu\u19_dj\ (for u19_dj)
  1. Authenticate with your NetID and PU password (NOT your PNI password, which may be different). When prompted for your username, enter PRINCETON\netid (note that PRINCETON can be upper or lower case) where netid is your PU NetID.

# On OS X systems

  1. Select "Go->Connect to Server..." from Finder and enter:
  • smb://cup.pni.princeton.edu/braininit/ (for braininit)
  • smb://cup.pni.princeton.edu/Bezos-center/ (for Bezos)
  • smb://cup.pni.princeton.edu/u19_dj/ (for u19_dj)
  1. Authenticate with your NetID and PU password (NOT your PNI password, which may be different).

# On Linux systems

  1. Follow extra steps depicted in this: link

# DB Access for Python repository

# Prerequisites

Click to expand details

# Install an integrated development environment

  • DataJoint development and use can be done with a plain text editor in the +terminal. However, an integrated development environment (IDE) can improve your +experience. Several IDEs are available.

  • In this setup example, we will use Microsoft's Visual Studio Code. +Installation instructions here. (opens new window)

  • Install the Jupyter extension for VS Code.

# Install a virtual environment

  • A virtual environment allows you to install the packages required for a +specific project within an isolated environment on your computer.

  • It is highly recommended to create a virtual environment to run the workflow.

  • Conda and virtualenv are virtual environment managers and you can use either +option. Below are the commands for Conda.

  • If you are setting up the pipeline on your local machine follow the instructions below for Conda. If you are using spock.pni.princeton.edu or scotty.pni.princeton.edu, Conda is preinstalled and you can access it by running module load anacondapy/2021.11.

  • We will install Miniconda which is a minimal installer for conda.

  • Select the Miniconda installer link (opens new window) for your operating system and follow the instructions.

    • You may need to add the Miniconda directory to the PATH environment +variable

      • First locate the Miniconda directory

      • Then modify and run the following command

        export PATH="<absolute-path-to-miniconda-directory>/bin:$PATH"
        +
    • Create a new conda environment

      • Type the following command into a terminal window

        conda create -n <environment_name> python=<version>
        +
      • Example command to create a conda environment

        conda create -n <environment_name> python=3.9
        +
    • Activate the conda environment

      conda activate <environment_name>
      +

    # Other installs

# First time configuration

  • The following instructions will configure DJ and connect to DB.
conda activate <environment_name>
+cd U19-pipeline_python
+pip install -e .
+python initial_conf.py
+

(Username and password will be prompted at this moment: Princeton NETiD & NetiD password usually works)

  • The initial_conf.py script will store a local file with credtentials to access DB and configuration variables/filepaths.
  • Now that the virtual modules are created to access the tables in the database, you can query and fetch from the database.

# Connection after configuration

  • The following instructions will load DJ configuration and connect to DB
conda activate <environment_name>
+python
+from scripts.conf_file_finding import try_find_conf_file
+try_find_conf_file()
+import datajoint as dj
+dj.conn()
+

# DB Access for MATLAB repository

# Prerequisites

Click to expand details
  • Install DataJoint for MATLAB
  • Utilize MATLAB built-in GUI i.e. Top Ribbon -> Add-Ons -> Get Add-Ons
  • Search, select, and install DataJoint
  • Clone the U19-pipeline-matlab repository

# First time configuration

  • Add this repository to MATLAB Path or cd to this repository folder.
  • Run dj_initial_conf(1)
  • Insert user and password for the DB

Note if you are configuring repository on a public computer, there are two options:

  • Rundj_initial_conf(0) instead, to not store user & pass in configuration file.
  • Rundj_initial_conf(1) and login to the DB with a public user like u19tech.

# Connection after configuration

  • Add this repository to MATLAB Path or cd to this repository folder.
  • connect_datajoint00

# DB Access for MATLAB repository (cluster computing)

# Prerequisites

Click to expand details

# First time configuration

  • Add this repository to MATLAB Path
  • Run startup_virtual_machine.m
  • Run dj_initial_conf(1)
  • Insert user and password for the DB

Note if you are configuring repository on a public computer, there are two options:

  • Rundj_initial_conf(0) instead, to not store user & pass in configuration file.
  • Rundj_initial_conf(1) and login to the DB with a public user like u19tech.

# Connection after configuration

  • Add this repository to MATLAB Path
  • Run startup_virtual_machine.m

# Add researcher to user table

  • This set of instructions only apply for users that will have subjects on his/her supervision:

# Add researcher to user table with MATLAB

  • Connect to DB
  • Run lab.utils.add_researcher_user_table('NETID', 'full name', 'email', 'phone')
  • Note: (All data in function call should be written inside quotes)

# Add researcher to user table with PYTHON

  • Activate conda environment and start a python command line
  • import u19_pipeline.utils.insert_miscelaneous_db as imd imd.add_researcher_user_table('NETID', 'full name', 'email', 'phone')
  • Note: (All data in function call should be written inside quotes)
+ + + diff --git a/software/db_analysis.html b/software/db_analysis.html new file mode 100644 index 0000000..92a6be6 --- /dev/null +++ b/software/db_analysis.html @@ -0,0 +1,85 @@ + + + + + + How to use DB (tips, tricks and more) | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# How to use DB (tips, tricks and more)

# MATLAB

# Prerequesites

  1. U19-pipeline-matlab repo added to MATLAB path
  2. Mounted network cup drives (braininit, u19_dj)
  • Go through U19-pipeline-matlab/tutorials/202103/session01_queries_fetches.mlx to learn basic tips on datajoint.

# Useful scripts and functions for reseacher general use:

# Read behavior file:

  1. Execute: (change key for desired session)
key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');
+[status,data] = lab.utils.read_behavior_file(key)
+
  1. If successful status = 1 and data = log behavioral file

# Get behavior file location (local & for spock/scotty)

  1. If you only need to know the path of behavior file use:
key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');
+baseDir = fetch1(acquisition.SessionStarted & key, 'new_remote_path_behavior_file');
+[bucket_path, local_path] =  lab.utils.get_path_from_official_dir(baseDir)
+

# get_full_trial_data with SpatialTimeBlobs

  • Get trial data (position, velocity, etc) efficiently with DB.
  • New method to retrieve all trial data for multiple sessions faster.
  1. Execute:
key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');
+get_full_trial_data(key)
+
  • Get trial data from joined tables as well (e.g. TowersBlock):
key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');
+get_full_trial_data(key, behavior.TowersBlockTrial * behavior.TowersBlock)
+
  • Get data from subtasks as well (e.g. Twolickspouts subtask)
key = struct('subject_fullname', 'efonseca_ef114_act114', 'session_date', '2023-01-11');
+all_tables = behavior.TowersBlockTrial * behavior.TowersBlock * behavior_subtask.TwolickspoutsBlockTrial * behavior_subtask.TwolickspoutsBlock
+get_full_trial_data(key, all_tables)
+

# get stats from session

  • To get behavior file like stats (on the trial level) for a single or multiple sessions use this function
  • Stats include, but not limited to: (correct_left, correct_right, cum_correct_trials, performance, goodFraction, numPerMin, numRewardsPerMin, bias)
key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');
+stat_struct = get_stats_from_session(key, "all")
+

# get behaviorfile as db

  • Function to unnest behavior file structure to get a plain trial table (with block data merged).
key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');
+data_struct = get_behaviorfile_as_db(key)
+

# get time from iteration variable

  • Example of how to "translate" a variable from iteration# to trial_time
  • In this case, 1st row of variable licks (iteration#) is translated to lick_times and then added to original trial structure
key = struct('subject_fullname', 'efonseca_ef114_act114', 'session_date', '2023-01-11');
+trial_data = get_full_trial_data(key, behavior.TowersBlockTrial * behavior_subtask.TwolickspoutsBlockTrial);
+licks_time_struct = struct;
+for i=1:length(trial_data)
+   licks_time_struct(i,1).lick_times = get_time_from_iter(trial_data(i).trial_time, trial_data(i).licks(1,:));
+end
+trial_data = cat_struct(trial_data, licks_time_struct);
+

# plot framerate frequency sessions

  • Plot trial by trial framerate of multiple sessions for comparison
key = 'subject_fullname like "mioffe%" and session_date > "2022-01-01" and session_date < "2022-01-30"';
+analyze_iteration_time(key)
+
Framerate trial by trial sessions

# plot framerate frequency levels and rigs

  • Plot mean framerate by level and rig for multiple sessions
key = 'subject_fullname like "mioffe%" and session_date > "2022-01-01" and session_date < "2022-12-10"';
+analyze_iteration_time_level_rig(key)
+
Mean framerate by level and rig

# plot velocity sessions

  • Plot mean - max range velocity by session for multiple behavior sessions
key = struct('subject_fullname', 'emdiamanti_gps7');
+plot_velocity_session(key)
+
Velocity plot for multiple sessions

# get path table

  1. Get default paths for network cup drives for different OS and spock/scotty (bucket)
key = struct('subject_fullname', 'testuser_T06', 'session_date', '2022-04-20');
+baseDir = fetch1(acquisition.SessionStarted & key, 'new_remote_path_behavior_file');
+[bucket_path, local_path] =  lab.utils.get_path_from_official_dir(baseDir)
+
Path table data

# Common errors and troubleshooting

  1. When trying to fetch from a table with external storage and corresponding network cup drive is not mounted:
Error using dj.store_plugins.File (line 89)
+Directory `/Volumes/u19_dj/external_dj_blobs` not accessible.
+
+Error in dj.internal.ExternalTable (line 52)
+           self.spec = dj.store_plugins.(storePlugin)(config);
+
Error using fread
+Invalid file identifier. Use fopen to generate a valid file identifier.
+
+Error in dj.store_plugins.File.download_buffer (line 63)
+           result = fread(fileID);
+
  • Just mount all cup drives and try agian !!
  1. key reference more than one session when function was supposed to work for single sessions
Error using dj.internal.GeneralRelvar/fetch1 (line 250)
+fetch1 can only retrieve a single existing tuple.
+
  • Just recreate key to reference a single session.

# PYTHON

# Common errors and troubleshooting

+ + + diff --git a/software/db_organization.html b/software/db_organization.html new file mode 100644 index 0000000..ce6c4b8 --- /dev/null +++ b/software/db_organization.html @@ -0,0 +1,43 @@ + + + + + + Database Organization | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Database Organization

  • The next sections will describe all DBs on the BRAINCoGS host (datajoint00.pni.princeton.edu). DBs are subdivided in these categories:
  1. Lab & subject DBs
  2. Behavior DBs
  3. Ephys & Imaging DBs

# Lab & Subject DBs

# 1. u19_lab

  • Stores all general information that apply for entire BRAINCoGS projects. Aditionally general information for researchers are stored here.

# Main tables

  • User Stores general information for all researchers and technicians in BRAINCoGS. Being registered in this table is a requirement to add subjects in your behalf Check here for more information. Important fields include, user_id (NETID), active_gui_user & slack_webhook URLS for users (for notifications). Check set slack alerts for more info.
  • Location All systems associated with rigs, recordings & technician use. All behavior sessions are associated with one of the systems recorded here, each recording (ephys/imaging) is associated with a system recorded here. Check here for more information. Important fields include, user_id (NETID), active_gui_user & slack_webhook (for notifications). Check Configure systems section for more info.
  • Path Paths for the cup drives in BRAINCoGS. Paths are divided by OS and local or network system types.
  • AcquisitionType All possible acquisitions modalities in BRAINCoGS. (Each location in Path is associated with one modality as well). Modalities include: behavior, electrophysiology, 2photon, mesoscope, etc).
  • DjCustomVariables Configuration variables for datajoint, mainly paths for special directories. This table is used in the background when DB access configuration is set for a system is made. Check DB Access section
  • DjStores External storage path locations on the network drives (cup) for several Datajoint tables. This table is used in the background when DB access configuration is set for a system is made. Check DB Access section
  • InsertionDevice Device types for insertion in subjects. (From ephys electrodes, to optogenetic cannula). Paired with u19_action.SurgeryLocation table.
  • SlackWebhooks Slack webhooks URLs for general notifications. Check set slack alerts for more info.

# 2. u19_subject

  • Stores all general information for subjects (mice) registered for experiments.

# Main tables

  • Subject Stores general information for all subjects in BRAINCoGS. Being registered in this table is a requirement to train and perform behavior sessions.
  • LickometerMotorPosition Stores ml, ap, & dv motor coordinates for a subject in a rig with positioning motor installed. Check Set up motor positioning subsection for more information.
  • CagingStatus Subject-Cage relationship storage.
  • HealthStatus Daily health assesment for subject. Fields like normal_behavior, posture_grooming, technician_comments etc.
  • Allele All subjects' genotypes in BRAINCoGS.
  • Cage Cage list for subjects.

# Behavior DBs

# 1. u19_acquisition:

  • Stores all reference and general information of behavior sessions. Other tables in this DB also stores reference to blocks, trials, manipulation and subtasks of a behavior session.

# Main tables

  • SessionStarted Reference to all sessions that are started with training GUI. Path to behavior file ia located here.
  • Session Basic information (performance, experiment code used, etc.) for a behavior session. Record written after training is finished
  • SessionBlock Basic reference to all blocks from all behavior sessions.
  • SessionBlockTrial Basic reference to all trials from all behavior sessions.
  • SessionManipulation Reference to which manipulation (if any) was performed for a behavior session. Check manipulation pipeline section for more information.
  • SessioSubtask Reference to which subtask (if any) was performed for a behavior session. Check subtask pipeline section for more information.
  • SessionVideo Reference to video adquisition if performed while behavior session. Check Pupillometry Pipeline Guide for more information.

# 2. u19_action:

  • Stores daily, recurrent and specific actions performed to subjects.

# Main tables

  • Weighing Records daily weight of subjects. Written by weighingGUI used by technicians.
  • WaterAdministration Records daily water administration to subjects. Earned water written at the end of training. Supplement water Written by weighingGUI used by technicians.
  • Surgery Records from surgeries performed to subjects. Written by Ephys/Imaging automation pipeline section
  • SurgeryLocation Records device locations implanted to subjects from surgeries (eg. NeuroPixel probes). . Written by Ephys/Imaging automation pipeline section
  • DaiyPositionData For subjects with automatic motor positioning on rig, stores daily ml,ap & dv coordinates. If cameras are present on rig a lateral and tops reference images are also stored.

# 3. u19_behavior:

  • Stores detailed data for behavior sessions. DB built to support Towers Task data but stores data from all behavior sessions.

# Main tables

  • TowersBlock Specific block data from behavior sessions. (level, main_level, block_performance, etc).
  • TowersBlockTrial Specific trial data from behavior sessions. (towers positions, trial_type, choice, position, velocity etc).
  • SpatialTimeBlobs Efficient time, position, velocity storage (per session and not by trial). Check get_full_trial_data with SpatialTimeBlobs to know how to use this.
  • Towers Session/Subject ** Psych Group of tables with Psychometric Curves parameters per session, block_type (main, guiding), subject, etc. Check Using psychometric data to know how to use this. Check BRAINCoGS Data viewer to check psychometric curves.

# 4. u19_behavior_subtask:

# 5. u19_optogenetics

# Main tables

  • OptogeneticSession Reference to a behavior session that is also an optogenetic session. Stores which protocol and software parameter set were used fot the session.
  • OptogeneticSessionTrial Stores specific optogenetic data on a trial by trial basis.
  • OptogeneticSoftwareParameters MATLAB Structure with parameters to be used during the behavior session specific for a subset of optogenetic sessions.
  • OptogeneticProtocol Describes metadata that will be associated with optogenetic sessions. (e.g. laser wavelength, stimulation frequency, etc.)

# 6. u19_thermal

# 7. u19_puffs

  • Air puff task sessions specific data.

# Main tables

  • PuffsSession Reference to a behavior session that is also a puff session.
  • PuffsSessionTrial Stores specific puffs data on a trial by trial basis.

# Ephys/Imaging DBs

# 1. u19_recording:

  • Stores all reference to any recording (ephys & imaging) performed on BRAINCoGS. Check Automation pipeline section for more information.

# Main tables

  • Recording Reference to all recordings. Stores information like location, status_recording & recording directory on the network drives.
  • RecordingBehaviorSessions Relationship between recordings and behavior sessions. (recording_id <-> session_key (subject, date, #)
  • RecordingRecordingSession Relationship between recordings and subject/date. Used when no behavior is attached to recording.
  • Modality List of all possible modalities supported by the automation pipeline.

# 2. u19_recording_process:

  • Stores all reference to all processing jobs for ephys & imaging on the automation pipeline. Almost all information in this table is shown in the Automation pipeline GUI .

# Main tables

  • Processing Reference to all processing jobs. For ephys it has a one to one relationship with recording probes. For imaging it has a one to one relationship with Field of View. Stores status_processing, raw_path (recording_process_pre_path), processed_path (recording_process_post_path) for each of these "fragments" of recording.
  • ProcessingEphysParams Relationship between jobs & which ephys processing parameters were used for that job.
  • ProcessingImagingParams Relationship between jobs & which imaging processing parameters were used for that job.
  • LogStatus Stores all status change for processing jobs and corresponding messages & exceptions if applicable.

# 3. u19_ephys_pipeline:

  • Basic reference to recordings and behavior synchronization data.

# Main tables

  • EphysPipelineSession List of recording_ids that correspond with ephys recordings.
  • BehaviorSync Synchronization data between ephys recording and behavior session. trial_index_nidq & iteration_index_nidq are trial and iteration # for each sample on the electrophysiology data.

# 4. u19_pipeline_ephys_element:

  • Datajoint element array electrophysiology DB. Database schema is designed to store all data from an ephys recording and subsequent kilosort processing. More info: Datajoint element array electrophysiology docs. For BRAINCoGS ephys_precluster schema was used.

# Main tables

  • ClusteringParamSet Table that contains a list of parameter dictionaries/structures used for sorting process.
  • PreClusterparamSet Table that contains a list of parameter dictionaries/structures used for preprocessing steps.
  • PreClusterparamSteps Table that contains lists of lists of preCluster param Sets that form a preprocessing sequence for recordings. +preprocessing steps. (e.g. catgt)
  • CuratedClusteringUnit Main data for all the units found in sorting process. (spike_times, cluster_quality_label, etc.)
  • LFPElectrode LFP data for each of the electrodes in recording.
  • WaveformSetWaveform All waveforms from a unit captured by each electrode in recording.
  • ProbeInsertion Records which probe was used for the corresponding recording-insertion_number pair. Check 5. u19_pipeline_probe_element.

# 5. u19_pipeline_probe_element:

  • Datajoint element array electrophysiology DB for probes. Database schema is designed to store probes and electorde configurations used in recordings. More info: Datajoint element array electrophysiology docs. For BRAINCoGS ephys_precluster schema was used.

# Main tables

  • Probe Table that contains all physicial probes used in recordings.
  • ProbeTypElectrode Table that contains coordinates, shank# and id for each electrode in a probe.

# 6. u19_imaging_pipeline:

  • Reference to all imaging recordings and subsequent fields of view (FOV) identification and splitting for processing.

# Main tables

  • ImagingPipelineSession List of recording_ids that correspond with imaging recordings.
  • TiffSplit Identified fields of view for a single recording (regularly 2photon = 1 FOV, mesoscope = 3 FOV). Each FOV is processed separately.
  • AcquiredTiff TIFF file header metadata for each FOV.
  • SyncImagingBehavior Synchronization data between imaging recording and behavior session. sync_behav_%%_by_im_frame = Correspoding behavior block, trial and iteration for each imaging frame. +sync_im_frame_span_by_behav_%% = Fist and last imaging frame for each behavior block, trial and iteration.

# 7. u19_pipeline_imaging_element:

  • Datajoint element calcium imaging DB. Database schema is designed to store all data from an imaging recording and subsequent segmentation process. More info: Datajoint element calcium imaging docs.

# Main tables

  • ProcessingParamSet Table that contains a list of parameter dictionaries/structures used for segmentation process.
  • ActivityTrace Activity trace signals for all masks identified in segmentation process.
  • FluorescenceTrace Fluorescence trace signals for all masks identified in segmentation process.
  • MaskClassificationMaskType Mask types (soma, blob, doughnut, etc) and confidence for each mask identified in segmentation process.
  • MotionCorrection(non)RigidMotionCorrection Motion correction details (shifts, outlier_frames, etc) performed durinc processing.
  • MotionCorrectionSummary Summary (average, correlation, max_proj) images for each field and channel after motion correction.

# 8. u19_pipeline_scan_element:

# Main tables

  • ScanInfo Similar to u19_imaging_pipeline.Acquiredtiff. General data and metadata from scans.
  • ScanInfoField Data specific to each of the fields of the scan.
  • ScanInfoScanFile All files that are part of a scan.

# 9. u19_pupillometry:

  • Stores all thing related to pupillometry recordings. From reference to behavior sessions to final results. Check Pupillometry Pipeline Guide for more information.

# Main tables

  • PupillometrySession Reference to behavior session that had pupillometry acquisition.
  • PupillometryModels Training models ready to use for processing pupillometry data.
  • PupillometrySyncBehavior Time correspondence between each trial-iteration in behavior file and each video frame.
  • PupillometrySyncBehavior Time correspondence between each trial-iteration in behavior file and each video frame.
  • PupillometrySessionModel Reference to which model was used to process a behavior session (More than one model can be used to process data from a session).
  • PupillometrySessionModelData Status of pupillometry processing and final result storage.
+ + + diff --git a/software/index.html b/software/index.html new file mode 100644 index 0000000..1e73dee --- /dev/null +++ b/software/index.html @@ -0,0 +1,37 @@ + + + + + + Software | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Software

# Introduction

In this section, we will document all software and database tools and pipelines developed for BRAIN CoGS community.

Software documentation is divided in sections, in each section you will find the information you need to access as a user or how to modify things as a developer. Many sections will also have MATLAB and Python subsection for you to choose your preferred language.

+ + + diff --git a/software/manipulation_pipeline.html b/software/manipulation_pipeline.html new file mode 100644 index 0000000..a988e6c --- /dev/null +++ b/software/manipulation_pipeline.html @@ -0,0 +1,141 @@ + + + + + + Manipulation pipeline | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Manipulation pipeline

  • This documentation will guide the researcher through the process of creating a new manipulation pipeline.
  • At BRAINCoGS optogenetics and thermal manipulation are currently supported.

# What does the “manipulation” pipeline include:

  • Minimum data framework to store in a DB all relevant data from a specific manipulation.
  • Behavior integration. Training system will include the manipulation as an option to be selected for a behavior session.
  • Generic software parameters to be used in behavior code.

# Prerequisites

  • In order to create a new manipulation it’s assumed that:
  • The researcher is able to connect to datajoint00.pni.princeton.edu DB
  • Latest version of u19_pipeline_matlab repository.

# Initial set-up

  • Connect to database connect_datajoint00
  • Create new manipulation schema (substitute manipulation_name with the real name of the manipulation: create_new_manipulation_schema('(manipulation_name)', 1)
  • This will create a new schema “base” code on the U19-pipeline-matlab/schemas directory:
  • (We will use “thermal” manipulation for this example).
Thermal manipulation file creation & Entity-Relationship diagram on the BRAINCoGS DB

# Table description

  • Throughout the table description chapter we are going to give an example of an already working manipulation pipeline. (Optogenetics)

# "Manipulation" Protocol table

  • The protocol table stores related information that defines the current manipulation “type” to be used on a behavior session.

  • Here is the minimum table definition for a manipulation protocol table, it is composed by an id to identify the protocol and a description field.

  • Generic "Manipulation" Protocol.m

%{
+# Defined <manipulation> protocols for training
+<manipulation>_protocol_id     : int AUTO_INCREMENT
+---
+protocol_description        : varchar(256)                  
+%}
+

# Adding features to "Manipulation" Protocol table

  • For each manipulation protocol it is possible to add from 0 to n “features” that will define & describe the protocol. We are going to describe all features added for OptogeneticsProtocol as an example:

  • It is important to know from an optogenetic experiment what kind of stimulation was given to the subject: Frequency, wavelength, power etc. All these variables can be stored into a “feature” table and be categorized as StimulationParameters.

  • What if stimulation was not a square pulse ? We can create a “feature” table to define (if needed) specific waveforms for a given session. (OptogeneticsWaveform)

  • What if different rooms have different laser systems models ? We can create a “feature” table to store all possible devices to be used in an optogenetic experiment (OptogeneticsDevice).

  • For each of these features we need to create a new table that encompasses the needed information for that feature. We will call all these extra tables a protocol “feature” table.

  • For a guide on how to define DJ tables go to: this link.

Tables that define an optogenetic protocol for a session.
  • For the current guide we will only show OptogeneticsStimulationParameters definition as an example:

# OptogeneticsStimulationParameters.m:

 %{
+ # Parameters related to laser stimulation
+ stim_parameter_set_id       : int AUTO_INCREMENT  # 
+ ---
+ stim_parameter_description  : varchar(256)        #
+ stim_wavelength             : decimal(5,1)        # (nm)
+ stim_power                  : decimal(4,1)        # (mW)
+ stim_frequency              : decimal(6,2)        # (Hz)
+ stim_pulse_width            : decimal(5,1)        # (ms)
+ %}
+ 
+ classdef OptogeneticStimulationParameter < dj.Lookup
+   properties
+   end
+ end
+
  • Fields needed for a protocol “feature” table:

  • id field: as an int AUTO_INCREMENT type as the only primary key (e.g. stim_parameter_set_id).

  • extra_fields: Any other field that helps to define the feature.

  • After all feature tables are defined they should be added to the "Manipulation" Protocol table.

  • For our Optogenetics example:

% Declare new "feature" table
+optogenetics.OptogeneticsStimulationParameters
+% Add the feature -> protocol table
+add_feature_key_protocol_table(optogenetics.OptogeneticsProtocol, ... optogenetics.OptogeneticsStimulationParameters)
+% Sync definition from DB to .m file
+syncDef(optogenetics.OptogeneticsProtocol);
+% clear previous connection and connect again
+clear all
+connect_datajoint00
+
  • After the “features” tables are added to the "Manipulation" Protocol table we are ready to add protocols to be “ready” and selectable for a behavior session:
 % Insert stim parameter record
+ stim_parameter_rec.stim_parameter_description = 'cool stims'
+ stim_parameter_rec.stim_wavelength = 473
+ stim_parameter_rec.stim_power = 10                
+ stim_parameter_rec.stim_frequency = 100        
+ stim_parameter_rec.stim_pulse_width = 1
+ insert(optogenetics.OptogeneticsStimulationParameters, stim_parameter_rec)  
+
+ % get last inserted stim_id
+ stim_id = fetch(optogenetics.OptogeneticsStimulationParameters, 'ORDER BY stim_parameter_set_id desc LIMIT 1');
+
+ % or look for a previously inserted parameter
+ all_stim_params = fetch(optogenetics.OptogeneticsStimulationParameters, '*')
+ stim_id = 1;
+
+ % Insert new protocol with new stimulation parameter
+ new_protocol.protocol_description = 'this_is_new_protocol'
+ new_protocol.stim_parameter_set_id = stim_id;
+ insert(optogenetics.OptogeneticsProtocol, new_protocol)
+

# "Manipulation" SoftwareParameters table

  • The software parameters table stores a set of parameters (a matlab struct, a python dictionary) that the code that handles the behavior will use during the session.
  • We will show how to insert new software parameters:
  • This for the optogenetics.OptogeneticSoftwareParameter table
param_struct = struct();
+param_struct.software_parameter_description =  'stimulation_sequence # 1';
+ 
+% All parameters goes in here 
+%(P_on and lsrepoch are the common and needed for current opto experiments)
+param_struct.software_parameters.P_on      = 0.21;
+param_struct.software_parameters.lsrepoch  = 'cue';
+  
+%Insert parameter
+software_param_id = try_insert(optogenetics.OptogeneticSoftwareParameter, param_struct)
+
  • Check insert_optogenetic_software_parameter script to use as example.
  • How to read software parameters on experiment code (ViRMEn)
  • Example to get software parameters on the initializatonCodeFun on virmen:
function vr = initializationCodeFun(vr)
+
+vr.software_params     = vr.exper.userdata.trainee.softwareParams.software_parameters;
+vr.lsrepoch = vr.software_params.lsrepoch;
+vr.P_on = vr.software_params.P_on;
+

# "Manipulation" Session table

  • This table stores manipulation data for a specific behavior session. This table “links” a manipulationProtocol & manipulationSoftwareParameters with a behavior Session.
  • This table does not need any additional code on it. (Unless extra fields from the behavior file are needed to be stored). Researcher should contact DB designer if that is their intention
OptogeneticSession.m 
+%{
+# Information of a optogenetic session
+-> acquisition.Session
+---
+-> acquisition.SessionManipulation
+-> optogenetics.OptogeneticProtocol
+-> optogenetics.OptogeneticSoftwareParameter
+%}
+

# "Manipulation" SessionTrial table

  • This table stores data, on a trial by trial basis, corresponding to the manipulation performed during the behavior session.
  • There is a section on any "Manipulation" SessionTrial class on the get_manipulation_trial_data function code where researcher has to add lines to fetch specific trial manipulation data:

Code extract from OptogeneticSessionTrial table

function trial_structure = get_manipulation_trials_data(~,session_key, log)
+.
+.
+for itrial = 1:nTrials
+
+  curr_trial = log.block(iBlock).trial(itrial);                            
+  trial_data = session_key;
+  trial_data.stim_on           = curr_trial.lsrON;
+  trial_data.t_stim_on  = time_trial(curr_trial.iLaserOn);
+  trial_data.stim_epoch = num2str(curr_trial.LaserTrialType);
+  trial_structure(total_trials) = trial_data;
+

# Training with new manipulation

  • After all code for new manipulation has been set up the researcher will be able to select a specific manipulation type, protocol & software parameters that will be associated with the schedule for a given animal. Subsequent behavior sessions will correspond to that selection.
Parameter selection (manipulation, protocol & software Parameter) for a training schedule of a subject.

# Fetching Data

  • After training has occurred all relevant data will be accessible in the corresponding tables of the database.
  • Datajoint fetch guide
key = struct('subject_fullname', 'sbolkan_a2a_492', 'session_date', '2022-06-27')
+fetch(optogenetics.OptogeneticSessionTrial * optogenetics.OptogeneticSession & key,'*')
+
+ans = 
+
+  363×1 struct array with fields:
+
+    subject_fullname
+    session_date
+    session_number
+    block
+    trial_idx
+    stim_on
+    t_stim_on
+    t_stim_off
+    stim_epoch
+
+ + + diff --git a/software/pupillometry_guide.html b/software/pupillometry_guide.html new file mode 100644 index 0000000..6809c50 --- /dev/null +++ b/software/pupillometry_guide.html @@ -0,0 +1,85 @@ + + + + + + Pupillometry Pipeline Guide | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Pupillometry Pipeline Guide

  • This documentation will guide the researcher through the process of register, monitor & review pupillometry data.

# Instructions to Set up Pupillometry Pipeline on a Rig Machine

  1. Ask your lab manager for helo to set up a camera in the rig.
  2. If needed, add these parameters in RigParameters.m
%% Pupilometry video parameters
+video_parent_path               =   'E:/VideoData'
+video_ext                       =   '.mj2'
+video_acquisition_rate          =   30
+video_record                    =   true
+video_gain                      =   8
+preview                         =   true
+
  1. In Tranining GUI subject task selection menu, under PupillometryVideo select 2. In RigParameters:
Training GUI for pupillometry
  1. In Experiment file add the following lines in initializationcodeFun function (just after vr = initializeGradedExperiment(vr); line):
% Start video acquisition
+if ~isempty(vr.trainee.pupillometryVideo) && vr.trainee.pupillometryVideo ~= 1
+    vr = startVideoAcquisition(vr);
+end
+
  1. In Experiment file add the following lines in runtimeCodeFun function (just after catch err displayException(err); line):
% Stop video acquisition
+if ~isempty(vr.trainee.pupillometryVideo) && vr.trainee.pupillometryVideo ~= 1
+        vr = stopVideoAcquisition(vr);
+end
+
  1. In Experiment file add the following lines in terminationCodeFun function (the very first line):
% Stop video acquisition
+if ~isempty(vr.trainee.pupillometryVideo) && vr.trainee.pupillometryVideo ~= 1
+        vr = stopVideoAcquisition(vr);
+end
+

# Pupillometry backup videos task schedule

  1. On Windows type "Task Scheduler"
  2. Open Task Scheduler "App"
  3. On right hand side menu, click on "Create Task" Action
Task scheduler menu
  1. Name new task as video_backup
  2. Add a trigger to run task daily at 11:30 pm
Task scheduler Trigger Tab
  1. Add an action: add this line to the Program/script edit: C:\Experiments\U19-pipeline-matlab\scripts\cmd_copy_video_files
  2. Hit OK button

# Pupillometry DB and data organization

  • Raw data (video files) are located in: \\cup.pni.princeton. edu\braininit\Data\Raw\video_pupillometry\(userid)\(subjectfullname)\(session_date)_g(session_number)\(video_file)

  • Processed data (h5 files) are located in: \\cup.pni.princeton. edu\braininit\Data\Processed\video_pupillometry\(userid)\(subjectfullname)\(session_date)_g(session_number)\(h5_file)

  • Video models are located in: \\cup.pni.princeton. edu\braininit\Data\Raw\video_models\(video_model_directory)

  • Check DB Organization (pupillometry) for a description for each pupillometry table.

Pupillometry pipeline DB schema

# Steps executed in Pupillometry pipeline

  1. When pupillometry_video -> 2. In RigParameters is selected in training GUI a new session_video record is registered in the DB while ingesting Session. (Code here)

  2. The cmd_copy_video_files task scheduler takes session_video records and store new videos in this location: \\cup.pni.princeton. edu\braininit\Data\Raw\video_pupillometry\(userid)\(subjectfullname)\(session_date)_g(session_number)\(video_file). Script run by pupillometry backup videos task schedule

  3. During night cronjob: if video is found on cup location:

  • Populate pupillometry_session table
  • Execute sync behavior code for video. Code here.
  • Register default model to process video in pupillometry_session_model and pupillometry_session_model_data.
  1. Queue/Checks job in spockvm2
  • Similar to ephys/imaging automation pipeline, pupillometry pipeline has a main (more simple) class to process all pupillometry jobs called PupillometryProcessingHandler. This class is located here .

  • Execute pupillometry_queue_jobs script. This scripts calls PupillometryProcessingHandler.check_pupillometry_sessions_queue function. Queues a processing job to all sessions where a model was registered.

  • Execute pupillometry_check_jobs script. This scripts calls PupillometryProcessingHandler.check_processed_pupillometry_sessions function. If processing job is finished get final result (pupil_diameter) and stores it in pupillometry_session_model_data table.

# Monitor pupillometry processing sessions

  • A few MATLAB functions were built to check how pupillometry jobs are doing:

  • Get processed data from a session:

key = struct('subject_fullname', 'efonseca_ef317_act116', 'session_date', '2024-02-21')
+pupillometry_data = fetch(pupillometry.PupillometrySessionModelData * pupillometry.PupillometrySyncBehavior & key, '*')
+pupillometry_data = 
+
+  struct with fields:
+
+           subject_fullname: 'efonseca_ef317_act116'
+               session_date: '2024-02-21'
+             session_number: 0
+                   model_id: 2
+        pupillometry_job_id: 2984
+             pupil_diameter: [108177×1 double]
+    sync_video_frame_matrix: [108177×4 single]
+       sync_behavior_matrix: [150227×5 single]
+

pupil_diameter: Pupil diameter for each video frame.
sync_video_frame_matrix: Time & Block/Trial/Iteration for each video frame.
sync_behavior_matrix: Time & video frame for each Block/Trial/Iteration.

  • Restart processing for failed processing +Sometimes processing fails for external factors (processing system was down, model was not properly selected, etc). As a first attempt to solve the issue a restart processing function was created:
psmd = pupillometry.PupillometrySessionModelData()
+key = struct('subject_fullname', 'efonseca_ef317_act116', 'session_date', '2024-02-21')
+psmd.restart_pupillometry_failed_job(key)
+

If processing fails again, contact Software Developer and check #automation_pipeline_errors slack channel for more information about the error.

  • Check status for all sessions:
psmd = pupillometry.PupillometrySessionModelData()
+all_sessions_table = psmd.check_status_pupillometry_jobs()
+
  • Check status for a specific session(s):
psmd = pupillometry.PupillometrySessionModelData()
+key = struct('subject_fullname', 'efonseca_ef317_act116', 'session_date', '2024-02-21')
+session_status = psmd.check_status_pupillometry_jobs(key)
+
  • Get all succesfully processed sessions:
psmd = pupillometry.PupillometrySessionModelData()
+pupillometry_finished_sessions = psmd.get_finished_jobs_pupillometry()
+

# Add a new video model to the pipeline

#

# Review processed data

+ + + diff --git a/software/subtask_pipeline.html b/software/subtask_pipeline.html new file mode 100644 index 0000000..bac5485 --- /dev/null +++ b/software/subtask_pipeline.html @@ -0,0 +1,104 @@ + + + + + + Subtask pipeline | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# Subtask pipeline

  • This documentation will guide the researcher through the process of creating a new subtask pipeline.
  • Currently in BRAINCoGS data from our well known "VR Towers Task" is stored in the DB.
  • New behavior paradigms include new variables that are not included on our original design:
  • Context task
  • Doorstop task
  • Movie/Stationary task
  • This results on having only a subset of entire data stored on the DB.
  • The subtask pipeline was created to solve this issue. Its goal is to store specific subtask variables in a different subset of tables in the DB.

# What does the “subtask” pipeline include:

  • Minimum data framework to store in a DB all relevant data from "VR Towers Task" variants.
  • Behavior integration. Training system will include the subtask as an option to be selected for a behavior session.

# Prerequisites

  • In order to create a new manipulation it’s assumed that:
  • The researcher is able to connect to datajoint00.pni.princeton.edu DB
  • Latest version of u19_pipeline_matlab repository.

# Initial set-up

  • Connect to database connect_datajoint00
  • Create new subtask base code (substitute subtask_name with the real name of the subtask: create_new_subtask_classes('(subtask_name)')
  • This will create table codes templates for subtask : (Subtask)Session.m, (Subtask)Block.m & (Subtask)Trial.m on the U19-pipeline-matlab/schemas/+behavior_subtask directory:
  • (We will use “Twolickspouts” subtask for this example).
Files created for Twolickspouts subtask on U19-pipeline-matlab/schemas/+behavior_subtask directory

# Table description

  • Throughout the table description chapter we are going to give an example of an already working subtask pipeline. (Twolicksspouts).

# task.Subtask table

  • This table registers all subtasks being created with this pipeline.

# acquisition.SessionSubtask table

  • This table stores subtask register for a specific behavior session. This table “links” a Task.subtask table with acquisition.Sesison table.

# "Subtask" Session table

  • The Session table stores related information for the entire session (review acquisition.Session for a related example).

# "Subtask" Block table

  • The Block table stores related information for each block of the session (review behavior.TowersBlock for a related example).

# "Subtask" BlockTrial table

  • The BlockTrial table stores related information for each trial of the session (review behavior.TowersBlockTrial for a related example).

# Adding code to "Subtask" tables

  • For each subtask you can add all needed variables from the behavior file to the "Subtask" tables.
  • Example for “Twolickspouts” subtask

# TwolickspoutsSession table code

 %{
+# Session level data for a twolickspouts subtask session
+-> acquisition.Session
+---
+%}
+
+classdef TwolickspoutsSession < dj.Imported
+
  • There is no extra field to add at session level, no code added to the file.

# TwolickspoutsBlock table code

%{
+# Block level data for a twolickspouts subtask session
+-> behavior_subtask.TwolickspoutsSession
+-> acquisition.SessionBlock
+---
+sublevel                  : int                           # sublevel for the block
+trial_params              : blob                          # maze features of current block
+%}
+.
+.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% fill here read corresponding TestSubtask data for each block
+tuple.sublevel = block_data.sublevel;
+tuple.trial_params = block_data.trialParams;
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
  • In this example two fields were added to TwolickspoutsBlock table: (sublevel & trial_params)
  • Two things are needed:
  1. Adding them to the table definition (1st part of the code block)
  2. Add how this fields are being set from block_data variable: (search for fill here section on the code). block_data has all block data from behavior file.

# TwolickspoutsBlockTrial table code

 %{
+ # Trial level data for a twolickspouts subtask session
+ -> behavior_subtask.TwolickspoutsBlock
+ -> acquisition.SessionBlockTrial
+ ---
+ licks                        : tinyblob                      # all iterations with lick detected and side
+ trial_difficult_type         : varchar(16)                   # trial type label (easy, medium, difficult, etc)
+ forced_automatic_reward=null : tinyint                       # 1 if reward was forced for trial 0 otherwise
+ %}
+ .
+ .
+ %%%%%%%%%%%%%%%%%%%%%%%
+ %%%% fill here read corresponding Twolickspouts data for each trial
+ trial_data.licks = curr_trial.licks;
+ if isfield(curr_trial, 'forced_automatic_reward')
+   trial_data.forced_automatic_reward = curr_trial.forced_automatic_reward;
+ else
+   trial_data.forced_automatic_reward = NaN;
+ end
+ if isfield(curr_trial, 'trialDifficultyType')
+   trial_data.trial_difficult_type = curr_trial.trialDifficultyType;  
+ else
+   trial_data.trial_difficult_type = '';
+ end
+ %%%%%%%%%%%%%%%%%%%%%%%%
+
  • In this example three fields were added to TwolickspoutsBlockTrial table: (licks & trial_difficult_type, forced_automatic_reward)
  • Two things are needed:
  1. Adding them to the table definition (1st part of the code block)
  2. Add how this fields are being set from trial_data variable: (search for fill here section on the code). trial_data has all trial data from behavior file.

# Create tables

  • After all code has been written on "Subtask"Session, "Subtask"Block & "Subtas"BlockTrial codebase it is needed to actually create the tables in the DB.
  • Execute: create_new_subtask_tables('(subtask_name)')

# Training with new subtask

  • After all code for new sbutask has been set up and tables have been created the researcher will be able to select a specific subtask that will be associated with the schedule for a given animal. Subsequent behavior sessions will correspond to that selection.
Subtask selection for a training schedule of a subject.

# Fetching Data

  • After training has occurred all relevant data will be accessible in the corresponding tables on the behavior_subtask DB.
  • Datajoint fetch guide
  • Example to fetch all Twolickspouts data for a single session:
key = struct('subject_fullname', 'testuser_T01', 'session_date', '2022-12-27')
+fetch(behavior_subtask.TwolickspoutsSession * behavior_subtask.TwolickspoutsBlock ...
+* behavior_subtask.TwolickspoutsBlockTrial & key, '*')
+
+ans = 
+
+  5×1 struct array with fields:
+
+    subject_fullname
+    session_date
+    session_number
+    subtask
+    block
+    trial_idx
+    sublevel
+    trial_params
+    licks
+    trial_difficult_type
+    forced_automatic_reward
+
+ + + diff --git a/software/virmen_guide.html b/software/virmen_guide.html new file mode 100644 index 0000000..f0d43a7 --- /dev/null +++ b/software/virmen_guide.html @@ -0,0 +1,60 @@ + + + + + + ViRMEn User/Developer Guide | BRAIN CoGS mini VR rigs + + + + + + + + + + + +

# ViRMEn User/Developer Guide

  • This documentation will guide the researcher through all steps, tricks & tips to train within the ViRMEn/Datajoint Environment.

# New task Creation

# Prerequisites

  • Read ViRMEn Manual. Access from virmen Repository (login to github first): Virmen Manual Link

# Initial set-up

  • Each task is conformed by a group of files (2 .mat files and 4 .m functions) that make everything work. All files are described here:

# Experiment code file

  • Located in ViRMEn\experiments (Rigs) or tankmousevr\experiments (Personal computer) directory.
  • File that controls stimulus presentation and trial/block progression. Each frame this code is executed, it's general structure is a state machine that follow the trial schema.
  • Detailed guide on how to modify things on ViRMEn Manual.
  • Original file: C:\Experiments\ViRMEn\experiments\poisson_blocks.m
  • Most common use:
  1. Copy the existing Experiment code file from the most similar task.
  2. Rename file to descriptive name (e.g. "TaskName"_ExperimentCode.mat)
  3. Change Experiment code logic.
  4. Check "Tips and Tricks to modify Experiment Code" for detailed tips
ViRMEn Experiment Code

# World file

  • Located in ViRMEn\experiments (Rigs) or tankmousevr\experiments (Personal computer) directory.
  • File that defines the structure of the Virmen world(s) settings.
  • Detailed guide on how to modify things on ViRMEn Manual.
  • Original file: C:\Experiments\ViRMEn\experiments\poisson_blocks.mat
  • Most common use:
  1. Copy the existing World file from the most similar task.
  2. Rename file to descriptive name (e.g. "TaskName"_World.mat)
  3. Execute virmen in MATLAB and open world (Experiment->Open)
  4. If no object is going to change, just modify Experiment code dropdown (Bottom left corner) value to match your experiment code filename.
ViRMEn GUI: to modify world files

# Protocol file

  • Located in ViRMEn\experiments\protocols (Rigs) or tankmousevr\experiments\protocols (Personal computer) directory.
  • File that declares the number of levels, mazes settings and criteria to decide when to advance subjects to next levels.
  • Original file: C:\Experiments\ViRMEn\experiments\protocols\PoissonBlocksCondensed3m.m
Protocol file Code
  • Here are definition of structures and variables in protocol file:
  1. Maze structure:
Parameter name Definition Values accepted
lStart Length of start region on track Real number (>0)
lCue Length of cue region on track Real Number (>0)
lMemory Length of delay region on track Real Number (>0)
Tri_turnHint Are the turn hints present at all? logical
Tri_turnHint_Mem Are turn hints present during delay period? logical
cueDuration How long are towers present after they appear (i.e., do they disappear after they are passed, and if yes, after how much time)? Real Number (>0, in seconds)
cueVisibleAt How far away from the navigator are towers visible? Real Number (>0)
cueProbability Probability parameter that defines the ratio of salient vs. distractor towers Real Number (>0, lower numbers make the ratio smaller on average) or inf (places all towers on correct side)
cueDensityPerM How many towers per meter in cue region are possible? Real number
antiFraction Proportion of trials in which the correct choice is away from the side with more towers (i.e., fraction of trials with inverted reward Real number ([0-1])
world Index of Virmen world in vr.worlds for that Maze Index of virmen world ([1-N], where N is the max number of worlds)
  1. Maze advancement criteria structure:
Parameter name Definition Values accepted
numTrials Minimum number of trials the mouse must spend above performance Natural number
numTrialsPerMin Number of trials required per minute to be considered maintaining “good” performance Natural number
criteriaNTrials Number of trials in the running window used to measure performance for deciding whether to advance to the next maze Natural number
numSessions Minimum number of sessions the navigator must have above criteria before advancing Natural number
Performance Minimum performance criterion to advance maze Real number ([0-1])
maxBias Max allowed side bias to advance maze Real number ([0-1])
warmupMaze Index of Virmen world in vr.worlds for the warmup maze for that particular main maze, which occurs at the start of a given session Index of virmen world ([1-N], where N is the max number of worlds)
warmupPerform Minimum performance allowed during warmup to advance to mainMaze Real number ([0-1])
warmupBias Max allowed side bias allowed during warmup to advance to main maze Real number ([0-1])
warmupMotor Max percentage of trials to have "bad" motor quality. (Too much travel distance inside the maze) Real number ([0-1])
easyBlock Index of Virmen world in vr.worlds for the easy block maze for that particular main maze Index of virmen world ([1-N], where N is the max number of worlds)
easyBlockNTrials Number of trials in an easy block Natural number
numBlockTrials Number of trials within a block used to assess performance for demotion to an easy block Natural number
blockPerform If running window performance (calculated over numBlockTrials) goes under this value, a switch to the easy block is triggered Real number ([0-1])
  1. Protocol extra variables:
Parameter name Definition Values accepted
globalSettings Defines global settings for all mazes Cell array of name-value pairs (see below for more details)
vr.numMazesInProtocol Total number of mazes in protocol Natural number (likely the length of mazeIDs)
vr.stimulusGenerator Function to generate stimuli (i.e., distribution of towers along the maze) @stimulusGeneratorFunc (e.g., @PoissonStimulusTrain)
vr.stimulusParameters Parameters for a stimulus inherited when running the experiment (so stimulus parameters that change between mazes but are not defined by the stimuli themselves) Cell array (see below for more details)
vr.inheritedVariables Parameters for a maze inherited when running the experiment (so maze parameters that change between mazes but are not defined by the stimuli themselves) Cell array (see below for more details)
  1. Global settings variables:
Parameter name Definition Values accepted
cueMinSeparation Min distance between two towers on the same side Real number (>0)
fracDuplicated Proportion of trials that are duplicated Real number ([0-1])
trialDuplication Number of times each set of stimulus parameters are duplicated, for a given fracDuplicated (i.e., number of exact replications of each trial type for the duplicated fraction of trials) Natural number

# Stimuli bank file

  • Located in ViRMEn\experiments\protocols (Rigs) or tankmousevr\experiments\protocols (Personal computer) directory.
  • File that contains stimuli sets that will be drawn for during session. It contains trial data: towers positions, number of towers for each maze level depending on protocol variables.
  • Original file: C:\Experiments\ViRMEn\experiments\protocols\stimulus_trains_PoissonBlocksCondensed3m.mat
  • Most common use:
  1. Create protocol and world files.
  2. Run generatePoissonStimuli(('world_file'), @('protocol_file')). Substitute world_file & protocol_file with corresponding names.

# Program wrapper file

  • Located in ViRMEn\experiments\programs (Rigs) or tankmousevr\experiments\programs (Personal computer) directory.
  • File to set up a cohort of animals on the training GUI.
  • Original file: C:\Experiments\ViRMEn\experiments\programs\trainPoissonBlocks_lp_cohort1.m
  • Most common use:
  1. Copy the existing Program wrapper file from the most similar task.
  2. Rename file to descriptive name (e.g. train"TaskName"_cohort(n).m)
  3. In the call to runCohortExperiment function rename first 3 parameters:
  • dataPath: should be C:\Data\(NETID)\(String to represent protocol, task or cohort)
  • experName should be the Experiment Code name (without .m)
  • cohortName should be a string to identify Cohort.
  • experName & cohortName will be appended to behavior files.
Program Wrapper File

# RigParameters file

  • Located in ViRMEn\extras (Rigs) or tankmousevr\extras (Personal computer) directory.
  • File that defines a bunch of parameters to control/adjust hardware, display and motion in task.
  • Only file: C:\Experiments\extras\RigParameters.m
# If working on a rig computer:
  • Most likely that this file has been set up by Lab Manager. Do nothing.
# If working on a personal computer:
  • The most common use for this file when working on a personal computer is to run ViRMEn simulations without interacting with the hardware, to do this set:
  • simulationMode: = true
  • hasDAQ: = false
  • This will allow you to run simulations on any Windows computer and use the keyboard to simulate mouse movement.
RigParameters File

# Set up training

  1. Make sure you have all files needed on the section above.
  2. Run your Program wrapper file (e.g. trainPoissonBlocks_lp_cohort1()).
  3. Training GUI will be shown:
Main screen training GUI
  1. Click on Connect to Database button.
  2. Click on Add animal button.
Add animal dialog
  1. Fill corresponding information for animal to train (see next section).
  2. Click on Submit button.
  3. Repeat steps 5-7 to add all animals from the cohort.
  4. Click on Save regiment button.
  5. Click on "Empty area" section where desired subject to train is shown.
  6. Click on TRAIN "SubjectFullname" button
Main screen training GUI with subject

# Set up motor positioning

  • If the rig where training is happening has a motor positioning system (ask lab manager about it). It is needed to set up initial coordinates for each subject training in the rig.
  1. Adjust subject positioning for the first time in the rig with the motor GUI (installed in the rig computer).
Motor GUI
  1. In MATLAB write the following (replace code in brackets with corresponding info for the subject):
new_record = struct
+new_record.subject_fullname = ['efonseca_ef481_actpg004']; # Subject fullname 
+new_record.ml_position = [17.5]   # ml position in mm (motor axis#1 position in GUI)
+new_record.ap_position = [10]     # ap position in mm (motor axis#2 position in GUI)
+new_record.dv_position = [15.3]    # dv position in mm (motor axis#3 position in GUI)
+insert(subject.LickometerMotorPosition, new_record)
+

# Training GUI detailed description

In this section all elements of the training GUI will be described:

Training GUI main screen parts
  • From the main screen we have divided all elements in three categories (red = rarely used or not used at all; yellow = used in specific situations; green = widely used).
  1. Branch information section: For git users, informs which branch is checked out right now and if the current version code has current changes on it. The vast majority of the times it should be written "master" & "synced". Go to section pulling/pushing code if not the case.
  2. Schedule calendar: Day of the week & time when subjects should be trained. This information is not crucial for training at the moment.
  3. Ball displacement plot: Figure that shows real time velocity in X & Y for the subject in the rig. This plot is used to detect ball movement sensor issues.
  4. RigParameters info bar: This bar is in red color whenever simulation mode is activated or hasDaq parameter is set to false. If this is the case both parameters should be reset for training to start. If simulation mode is intended ignore this bar.
  5. Test session checkbox: If next session goal will be to test code or behavior won't be analyzed check this box. Session will not be stored in our DB.
  6. Open valve buttons: These buttons are used to give a little reward to subject in rig and/or to test valve function.
  7. Connect to DB button: Use this button to connect to DB, it should be the first thing to do when training GUI is open. Check set up training seciton
  8. Add animal button: Use this button to add a new subject to cohort. Check set up training seciton and Add animal dialog detailed description
  9. Edit animal button: Button to change some parameter on the "add animal button" dialog for an already added subject to the cohort.
  10. Remove animal button: Button to remove subject from cohort (do this when animal has finished training).
  11. Save regiment button: Click this button whenever a subject is added, edited or removed to save changes.
  12. Train button: Click this button to start training of selected subject.
  13. Close GUI: Click to close GUI.
  14. Restart MATLAB shortcut: Click to restart MATLAB.

# Add animal dialog detailed description

Training GUI main screen parts
  • From the add animal dialog we have divided all elements in three categories (red = rarely used or not used at all; yellow = used in specific situations; green = widely used). Sections not described are not used.
  1. Subject selection: Dropdown list of all available for training subjects in BRAINCoGS.
  2. Reward Factor: Multiplier to be used for reward for each one of the warm-up & main mazes. Regularly reward is 4ul for each correct trial on Towers Task. (e.g. if RewardFactor = 1.25 -> Reward = 4*1.25 = 5 ul).
  3. Motion blur range: Parameter to set up cue elongation effect opposite to direction of subject motion in virtual reality. 2x1 vector where first element is distance (in cm) from subject to tower cue to start elongation and second element is distance (in cm) to stop elongation effect. No motion blur effect if empty. Common values: [28 5], []
  4. Restart or append session: Action to perform if a session is restarted.
  • If APPEND SESSION is selected, every time session is restarted, the "new" session will be counted as new blocks of the same session.
  • If START NEW SESSION is selected, every time session is restarted a new session will be created (recommended when physiology recordings are performed to facilitare syncing process)
  1. Protocol code file selector: Dropdown to select protocol code file, check New task creation section for detailed information
  2. Experiment code file selector: Dropdown to select experiment code file, check New task creation section for detailed information
  3. Stimulus bank file selector: Dropdown to select stimulus bank file, check New task creation section for detailed information
  4. stimulus Set edit: If stimulus bank has more than one set it can be set from here. Only change this if you know deeply the stimulus bank file and you know what you are doing.
  5. How warm up trials are drawn: Strategy to select left or right trials based on previous bias and performance. Default value eradeTrial described here
  6. How main trials are drawn: Strategy to select left or right trials based on previous bias and performance. Default value eradeTrial described here
  7. Subtask selector: If session is from a specific subtask you can select it here. Check subtask pipeline section for more information.
  8. Pupillometry video: If pupillometry video is going to be captured, select video parameters here.
  9. Behavior video: If behavior video is going to be captured, select video parameters here.
  10. Manipulation selector: If session is from a specific manipulation you can select it here. Check manipulation pipeline section for more information.
  11. Stimulation protocol: If session is from a specific manipulation Select stimulation protocol in this dropdown. Check manipulation pipeline section for more information.
  12. Software parameters: If session is from a specific manipulation Select software parameters in this dropdown. Check manipulation pipeline section for more information.

# Tips and Tricks Experiment Code

# Add variables to behavior file

  • It is often needed to store more variables to behavior file for further analysis.

# Add variables on the trial level

  1. Go to function setupTrials on the Experiment code
  2. Find line like this: cfg.trialData = { 'trialProb', 'trialType', 'choice', 'trialID' ...
  3. Add variable name at the end of cfg.trialData cell array.
  • Remember to define that variable as vr.(variableName) on initializationCodeFun() or runtimeCodeFun() before 1st trial is over.

# Add variables on the block level

  1. Go to function setupTrials on the Experiment code
  2. Find line like this: cfg.blockData = { 'mazeID', 'mainMazeID', 'motionBlurRange', 'iterStr', 'shapingProtocol' ...
  3. Add variable name at the end of cfg.trialData cell array.
  • Remember to define that variable as vr.(variableName) on initializationCodeFun() or runtimeCodeFun() before 1st trial is over.

# Set code ready for simulation

  • It is useful to have Experiment code ready for simulations. To test all changes without interacting with the rig hardware.
  • Setting code for simulation also enable making trial by trial videos with ReproduceTrialTowers repository
  1. Search all lines is experiment code that interact with hardware: (all lines starting with: nidaq.. and updateDAQSyncSignals function. (hardware code lines)
  2. Add this line if RigParameters.hasDAQ before hardware code lines and close if after them.

# Solve common errors during training

# Arduino Serial communication error

  • Errors like these:
Open failed: Port: COM7 is not available. Available ports: COM1.
+Use INSTRFIND to determine if other instrument objects are connected to the requested device.
+
Serial communications have not been properly initiated.
+
Device Error: Unanticipated host error
+
  • Are the most common error during training. Check if Arduino COM Port is found in device manager and restart MATLAB and/or system to solve this.

# virmen variable not properly set

Reference to non-existent field (variable_name)...
+
Unrecognized field name (variable_name).
+
  • This error is solved if variable is initialized in initializationCodeFun() (e.g: vr.(variable_name) = 0)

# Nidaq channel is busy or not found

 [nidaqPulseRightReward:commit]  Requested operation could not be performed, because the specified digital lines are either reserved or the device is not present in NI-DAQmx.
+ It is possible that these lines are reserved by another task or the device is being reset. If you are using these lines with another task, wait for the task to complete.  If you want to force the other task to relinquish the device, reset the device. If you are resetting the device, wait for the reset to finish.
+ Device:  Dev1
+
+ Task Name: RightReward
+
+ Status Code: -200587
+
  • Review RigParameters.m file and check that there is no overlap between input/output channel variables: (rewardChannel, laserChannel, rightPuffChannel, leftPuffChannel,rightRewardChannel, leftRewardChannel, newIterationChannel, newTrialChannel, etc.)
+ + + diff --git a/src/building/assets/GERBER/stage/IR-LED-circuit-for-optical-flow-sensor.zip b/src/building/assets/GERBER/stage/IR-LED-circuit-for-optical-flow-sensor.zip new file mode 100644 index 0000000..dcfb599 Binary files /dev/null and b/src/building/assets/GERBER/stage/IR-LED-circuit-for-optical-flow-sensor.zip differ diff --git a/src/building/assets/drawings/Training mini VR rig.step.zip b/src/building/assets/drawings/Training mini VR rig.step.zip new file mode 100644 index 0000000..870be73 Binary files /dev/null and b/src/building/assets/drawings/Training mini VR rig.step.zip differ diff --git a/src/software/assets/files/automation_gui/catgt_parameters_example.json.zip b/src/software/assets/files/automation_gui/catgt_parameters_example.json.zip new file mode 100644 index 0000000..373d577 Binary files /dev/null and b/src/software/assets/files/automation_gui/catgt_parameters_example.json.zip differ diff --git a/src/software/assets/files/automation_gui/kilosort_parameters_example.json.zip b/src/software/assets/files/automation_gui/kilosort_parameters_example.json.zip new file mode 100644 index 0000000..2bf976d Binary files /dev/null and b/src/software/assets/files/automation_gui/kilosort_parameters_example.json.zip differ