CINXE.COM
Dash Enterprise | Dash for Python Documentation | Plotly
<!DOCTYPE html><html><head> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Dash Enterprise | Dash for Python Documentation | Plotly</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content="Plotly Dash User Guide & Documentation"> <meta name="google-site-verification" content="EgLBLquJuqD_NR96F-pKLhTy9ZKQlWIoQlexW_OVKrM" /> <title>Dash Enterprise | Dash for Python Documentation | Plotly</title> <link rel="icon" type="image/x-icon" href="/assets/favicon.ico?m=1732036217.0"> <link href="https://esm.sh/@markprompt/css@0.18.0?css" rel="stylesheet" /> <link rel="stylesheet" href="/_dash-component-suites/dash_design_kit/ddk-all.v1_14_0m1732036307.css"> <link rel="stylesheet" href="/_dash-component-suites/dash_design_kit/bootstrap_build.v1_14_0m1732036307.css"> <link rel="stylesheet" href="/_dash-component-suites/dash_design_kit/fa-ddk.v1_14_0m1732036307.css"> <link rel="stylesheet" href="/assets/ag-grid-examples-css.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/azure.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/base.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/daq.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/dashbio.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/ddk.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/dosis.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/loading.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/local-css-example.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/markprompt_override.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/open-sans.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/override.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/percy.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/table.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/tabs-styled-with-classes.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/typography.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/dash-design-kit/docs.css?m=1732036334.0"> <link rel="stylesheet" href="/assets/dash-design-kit/gallery-style.css?m=1732036334.0"> <link rel="stylesheet" href="/assets/dash-design-kit/react-resizable.css?m=1732036334.0"> <link rel="stylesheet" href="/assets/dash-design-kit/report.css?m=1732036334.0"> <link rel="stylesheet" href="/assets/font-awesome/css/fontawesome.min.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/font-awesome/css/solid.min.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/highlight/styles/default.css?m=1732036217.0"> <link rel="stylesheet" href="/assets/highlight/styles/dm-mono.css?m=1732036217.0"> <!-- Google Tag Manager Tag --> <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-N6T2RXG');</script> <style type="text/css"> .placeholder-content{will-change:transform;animation:placeHolderShimmer 1s linear infinite forwards;-webkit-backface-visibility:hidden;background:#e6e6e6;background:linear-gradient(90deg,#eee 8%,#ddd 18%,#eee 33%);background-size:800px 104px;height:100%;position:relative}.placeholder-content *{color:transparent!important;opacity:0}@keyframes placeHolderShimmer{0%{-webkit-transform:translateZ(0);transform:translateZ(0);background-position:-468px 0;opacity:.7}45%{opacity:.8}75%{opacity:1}100%{-webkit-transform:translateZ(0);transform:translateZ(0);background-position:468px 0;opacity:.7}}@keyframes placeholderAnimate{0%{background-position:-650px 0}100%{background-position:650px 0}}.preload{position:fixed;top:0;left:0;right:0;bottom:0;transition:all ease .3s;z-index:99999;background-color:#fff}.preload *{box-sizing:border-box}.preload .pre-sidebar{position:absolute;top:0;left:0;bottom:0;width:300px;background-color:#fafafa}.preload .pre-content{position:absolute;top:0;left:300px;bottom:0;right:0;padding:0 0 0 90px;z-index:999;background-color:#fff}.preload .pre-brand{padding:35px 10px 20px 20px;display:flex;align-items:center;justify-content:space-between}.preload .pre-logo{width:100px;height:30px;flex-shrink:0;border-radius:6px}.preload .pre-switch{display:inline-flex !important;justify-content:flex-end;}.preload .pre-switch .pre-dot{flex-shrink:0;width:20px;height:20px;border-radius:20px;margin:0px !important;}.preload .pre-switch .pre-large{width:45px;height:20px;border-radius:20px;flex-shrink:0;margin:0 6px}.preload .pre-search{height:38px;width:223px;margin:10px 0 40px 36px;border-radius:30px}.preload .pre-line{width:100px;height:15px;margin:0 0 30px 30px;border-radius:3px}.preload .pre-line1{width:125px}.preload .pre-line2{width:135px}.preload .pre-line3{width:145px}.preload .pre-line4{width:245px}.preload .pre-line5{width:225px}.preload .pre-line6{width:235px}.preload .pre-line7{width:150px}.preload .pre-line8{width:180px}.preload .pre-line9{width:190px}.preload .pre-line10{width:120px}.preload .pre-menu{padding:20px 20px 0 0;text-align:right}.preload .pre-menu div{width:100px;display:inline-block;height:20px;border-radius:2px;margin:0 0 0 30px}.preload .pre-wrap{max-width:850px}.preload .pre-headline{height:30px;width:400px;margin:100px 0 70px 2px;border-radius:2px}.preload .pre-subhead{height:23px;width:180px;margin:0 0 28px 0;border-radius:2px}.preload .pre-subhead2{margin:70px 0 28px 0}.preload .pre-box-row{display:flex;flex-wrap:wrap;margin:0 -16px}.preload .pre-box-col{width:33.333%;margin:0 0 20px 0;padding:0 16px}.preload .pre-box{height:112px;width:100%;border-radius:2px} </style> </head> <body> <div class="preload"> <div class="pre-wrap"> <div class="pre-sidebar"> <div class="pre-brand"> <div class="pre-logo placeholder-content"> </div> </div> <div class="pre-search placeholder-content"> </div> <div class="pre-line pre-line1 placeholder-content"> </div> <div class="pre-line pre-line2 placeholder-content"> </div> <div class="pre-line pre-line3 placeholder-content"> </div> <div class="pre-line pre-line4 placeholder-content"> </div> <div class="pre-line pre-line5 placeholder-content"> </div> <div class="pre-line pre-line6 placeholder-content"> </div> <div class="pre-line pre-line7 placeholder-content"> </div> <div class="pre-line pre-line8 placeholder-content"> </div> <div class="pre-line pre-line9 placeholder-content"> </div> <div class="pre-line pre-line10 placeholder-content"> </div> </div> <div class="pre-content"> <div class="pre-menu"> <div class=" placeholder-content"> </div> <div class="pre-switch"> <div class="pre-dot placeholder-content"> </div> <div class="pre-large placeholder-content"> </div> <div class="pre-dot placeholder-content"> </div> </div> <div class=" placeholder-content"> </div> <div class=" placeholder-content"> </div> <div class=" placeholder-content"> </div> <div class=" placeholder-content"> </div> </div> <div class="pre-wrap"> <div class="pre-headline placeholder-content"> </div> <div class="pre-subhead placeholder-content"> </div> <div class="pre-box-row"> <div class="pre-box-col"> <div class="pre-box placeholder-content"> </div> </div> <div class="pre-box-col"> <div class="pre-box placeholder-content"> </div> </div> <div class="pre-box-col"> <div class="pre-box placeholder-content"> </div> </div> </div> <div class="pre-subhead pre-subhead2 placeholder-content"> </div> <div class="pre-box-row"> <div class="pre-box-col"> <div class="pre-box placeholder-content"> </div> </div> <div class="pre-box-col"> <div class="pre-box placeholder-content"> </div> </div> <div class="pre-box-col"> <div class="pre-box placeholder-content"> </div> </div> <div class="pre-box-col"> <div class="pre-box placeholder-content"> </div> </div> <div class="pre-box-col"> <div class="pre-box placeholder-content"> </div> </div> </div> </div> </div> </div> </div> <!-- Google Tag Manager Tag --> <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-N6T2RXG" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript> <div id="react-entry-point"> <div class="toc"> <h1>Dash Enterprise Guide </h1> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">What's Dash Enterprise? </h2> <div id="{'type': 'links-store', 'index': '0df34c3b8e19d8'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': '0df34c3b8e19d8'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> </div> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">Quickstart </h2> <div id="{'type': 'links-store', 'index': 'cb69ee83006903'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': 'cb69ee83006903'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> <div class="width-100 text-center"><button id="{'type': 'load-more-btn', 'index': 'cb69ee83006903'}" class="btn-show-more" n_clicks="false">show more </button> </div> </div> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">Installation </h2> <div id="{'type': 'links-store', 'index': '0426a23ecf737a'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': '0426a23ecf737a'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> </div> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">Administration </h2> <div id="{'type': 'links-store', 'index': '4bb32a07e018de'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': '4bb32a07e018de'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> <div class="width-100 text-center"><button id="{'type': 'load-more-btn', 'index': '4bb32a07e018de'}" class="btn-show-more" n_clicks="false">show more </button> </div> </div> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">App Configuration </h2> <div id="{'type': 'links-store', 'index': '274597f59f1bb6'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': '274597f59f1bb6'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> </div> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">User Interface </h2> <div id="{'type': 'links-store', 'index': 'fff0fc20e345b8'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': 'fff0fc20e345b8'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> <div class="width-100 text-center"><button id="{'type': 'load-more-btn', 'index': 'fff0fc20e345b8'}" class="btn-show-more" n_clicks="false">show more </button> </div> </div> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">Continuous Integration </h2> <div id="{'type': 'links-store', 'index': '2fe89b150cce83'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': '2fe89b150cce83'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> </div> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">Advanced </h2> <div id="{'type': 'links-store', 'index': '47397a72f203ea'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': '47397a72f203ea'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> </div> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">Troubleshooting </h2> <div id="{'type': 'links-store', 'index': '5e95551b2bb5a6'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': '5e95551b2bb5a6'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> </div> <div class="toc--section bottom64"> <h2 class="toc-title-border" style="marginTop:30px; paddingBottom:6px">Reference </h2> <div id="{'type': 'links-store', 'index': '92d0f4e03d8c39'}" class="ssr-dash-core-components-store" style="height:50px"> </div> <div id="{'type': 'links-show', 'index': '92d0f4e03d8c39'}" class="bottom16-ssr-dash-bootstrap-components-row" style="height:50px"> </div> </div> </div> </div> <footer> <script id="_dash-config" type="application/json">{"url_base_pathname":null,"requests_pathname_prefix":"\u002f","ui":false,"props_check":false,"show_undo_redo":false,"suppress_callback_exceptions":true,"update_title":null,"children_props":{"dash_core_components":{"Checklist":["options[].label"],"Clipboard":[],"ConfirmDialog":[],"ConfirmDialogProvider":[],"DatePickerRange":[],"DatePickerSingle":[],"Download":[],"Dropdown":["options[].label"],"Geolocation":[],"Graph":[],"Input":[],"Interval":[],"Link":[],"Loading":["custom_spinner"],"Location":[],"LogoutButton":[],"Markdown":[],"RadioItems":["options[].label"],"RangeSlider":[],"Slider":[],"Store":[],"Tab":[],"Tabs":[],"Textarea":[],"Tooltip":[],"Upload":[]},"dash_html_components":{"A":[],"Abbr":[],"Acronym":[],"Address":[],"Area":[],"Article":[],"Aside":[],"Audio":[],"B":[],"Base":[],"Basefont":[],"Bdi":[],"Bdo":[],"Big":[],"Blink":[],"Blockquote":[],"Br":[],"Button":[],"Canvas":[],"Caption":[],"Center":[],"Cite":[],"Code":[],"Col":[],"Colgroup":[],"Content":[],"Data":[],"Datalist":[],"Dd":[],"Del":[],"Details":[],"Dfn":[],"Dialog":[],"Div":[],"Dl":[],"Dt":[],"Em":[],"Embed":[],"Fieldset":[],"Figcaption":[],"Figure":[],"Font":[],"Footer":[],"Form":[],"Frame":[],"Frameset":[],"H1":[],"H2":[],"H3":[],"H4":[],"H5":[],"H6":[],"Header":[],"Hgroup":[],"Hr":[],"I":[],"Iframe":[],"Img":[],"Ins":[],"Kbd":[],"Keygen":[],"Label":[],"Legend":[],"Li":[],"Link":[],"Main":[],"MapEl":[],"Mark":[],"Marquee":[],"Meta":[],"Meter":[],"Nav":[],"Nobr":[],"Noscript":[],"ObjectEl":[],"Ol":[],"Optgroup":[],"Option":[],"Output":[],"P":[],"Param":[],"Picture":[],"Plaintext":[],"Pre":[],"Progress":[],"Q":[],"Rb":[],"Rp":[],"Rt":[],"Rtc":[],"Ruby":[],"S":[],"Samp":[],"Script":[],"Section":[],"Select":[],"Shadow":[],"Slot":[],"Small":[],"Source":[],"Spacer":[],"Span":[],"Strike":[],"Strong":[],"Sub":[],"Summary":[],"Sup":[],"Table":[],"Tbody":[],"Td":[],"Template":[],"Textarea":[],"Tfoot":[],"Th":[],"Thead":[],"Time":[],"Title":[],"Tr":[],"Track":[],"U":[],"Ul":[],"Var":[],"Video":[],"Wbr":[],"Xmp":[]},"dash_table":{"DataTable":[]},"dash_design_kit":{"App":[],"Block":[],"Card":[],"CardFooter":[],"CardHeader":[],"CollapsibleMenu":["title"],"ControlCard":[],"ControlItem":[],"ControlsHeader":["primary_controls","secondary_controls"],"DataCard":[],"DataTable":[],"Footer":["tags"],"FullScreen":["cardRef"],"Graph":["insights.title","insights_conversation[].answer"],"Header":[],"Hero":["tags"],"Icon":[],"Logo":[],"Menu":[],"Modal":["cardRef"],"Notification":[],"Page":[],"PageFooter":[],"PageHeader":[],"Report":[],"Row":[],"SectionTitle":[],"Sidebar":[],"SidebarCompanion":[],"Tag":[],"Title":[],"_Accordion":["control_groups[].children","action_button"],"_AccordionItem":[],"_ControlPanel":["control_groups[].children","action_button"],"_TabbedControls":["control_groups[].children","action_button"],"_Section":[],"_SectionHeading":[],"_CopyText":null},"dash_bootstrap_components":{"Accordion":[],"AccordionItem":[],"Alert":[],"Badge":[],"Breadcrumb":[],"Button":[],"ButtonGroup":[],"Card":[],"CardBody":[],"CardFooter":[],"CardGroup":[],"CardHeader":[],"CardImg":[],"CardImgOverlay":[],"CardLink":[],"Carousel":[],"Collapse":[],"DropdownMenu":["label"],"DropdownMenuItem":[],"Fade":[],"Form":[],"FormFeedback":[],"FormFloating":[],"FormText":[],"Label":[],"Checkbox":["label"],"Checklist":["options[].label"],"Input":[],"InputGroup":[],"InputGroupText":[],"RadioButton":["label"],"RadioItems":["options[].label"],"Select":[],"Switch":["label"],"Textarea":[],"Col":[],"Container":[],"Row":[],"Stack":[],"ListGroup":[],"ListGroupItem":[],"Modal":[],"ModalBody":[],"ModalFooter":[],"ModalHeader":[],"ModalTitle":[],"Nav":[],"NavItem":[],"NavLink":[],"Navbar":[],"NavbarBrand":[],"NavbarSimple":["brand"],"NavbarToggler":[],"Offcanvas":["title"],"Pagination":[],"Placeholder":[],"Popover":[],"PopoverBody":[],"PopoverHeader":[],"Progress":[],"Spinner":[],"Table":[],"Tab":[],"Tabs":[],"Toast":["header"],"Tooltip":[]},"dash_user_guide_components":{"PageMenu":[],"Sidebar":[]},"dash_enterprise_libraries":{"Chatbot":["chatbotButton"],"Header":[],"NavLinks":[],"QuickSettings":[],"ShareDialog":[]},"dash_bio":{"AlignmentChart":null,"Circos":null,"FornaContainer":null,"Ideogram":null,"Igv":null,"Jsme":null,"Molecule2dViewer":null,"Molecule3dViewer":null,"NeedlePlot":null,"NglMoleculeViewer":null,"OncoPrint":null,"Pileup":null,"SequenceViewer":null,"Speck":null},"dash_cytoscape":{"Cytoscape":null},"dash_embedded":{"ConsumerContext":[],"ConsumerFunction":[]},"dash_ag_grid":{"AgGrid":[]},"dash_mantine_components":{"Accordion":["chevron"],"AccordionControl":["chevron","icon"],"AccordionItem":[],"AccordionPanel":[],"Navbar":[],"NavbarSection":[],"AppShell":[],"Aside":[],"Footer":[],"Header":[],"Avatar":[],"AvatarGroup":[],"Button":["leftIcon","rightIcon"],"ButtonGroup":[],"Card":[],"CardSection":[],"Checkbox":["label","description","error"],"CheckboxGroup":["label","description","error"],"Chip":[],"ChipGroup":["label","description","error"],"ColorInput":["eyeDropperIcon","icon","rightSection","label","description","error"],"ColorPicker":[],"Col":[],"Grid":[],"HoverCard":[],"HoverCardDropdown":[],"HoverCardTarget":[],"BackgroundImage":[],"Image":["placeholder","caption"],"List":["icon"],"ListItem":["icon"],"Menu":[],"MenuDivider":[],"MenuDropdown":[],"MenuItem":["icon","rightSection"],"MenuLabel":[],"MenuTarget":[],"Popover":[],"PopoverDropdown":[],"PopoverTarget":[],"Radio":["label","description","error"],"RadioGroup":["label","description","error"],"Autocomplete":["icon","rightSection","label","description","error","nothingFound"],"MultiSelect":["icon","rightSection","label","description","error","nothingFound"],"Select":["icon","rightSection","label","description","error","nothingFound"],"RangeSlider":["marks[].label","label","thumbChildren"],"Slider":["marks[].label","label","thumbChildren"],"Stepper":["icon","completedIcon","progressIcon"],"StepperCompleted":[],"StepperStep":["icon","completedIcon","progressIcon","label","description"],"Tab":["rightSection","icon"],"Tabs":[],"TabsList":[],"TabsPanel":[],"JsonInput":["validationError","icon","rightSection","label","description","error"],"NumberInput":["icon","rightSection","label","description","error"],"PasswordInput":["icon","rightSection","label","description","error"],"PinInput":["icon","rightSection"],"TextInput":["icon","rightSection","label","description","error"],"Textarea":["icon","rightSection","label","description","error"],"Timeline":[],"TimelineItem":["title","bullet"],"FloatingTooltip":["label"],"Tooltip":["label"],"ActionIcon":[],"Affix":[],"Alert":["title","icon"],"Anchor":[],"AspectRatio":[],"Badge":["leftSection","rightSection"],"Blockquote":["icon","cite"],"Box":[],"Breadcrumbs":["separator"],"Burger":[],"Center":[],"Code":[],"Container":[],"Divider":["label"],"Drawer":["title","closeButtonProps.children"],"Flex":[],"Group":[],"Highlight":[],"Indicator":["label"],"InputWrapper":["label","description","error"],"Kbd":[],"Loader":[],"LoadingOverlay":["loader"],"Mark":[],"MediaQuery":[],"Modal":["title","closeButtonProps.children"],"NavLink":["label","description","icon","rightSection"],"Pagination":[],"Paper":[],"Progress":["sections[].tooltip"],"Rating":["emptySymbol","fullSymbol"],"RingProgress":["label","sections[].tooltip"],"ScrollArea":[],"SegmentedControl":[],"SimpleGrid":[],"Skeleton":[],"Space":[],"Spoiler":["hideLabel","showLabel"],"Stack":[],"Switch":["label","offLabel","onLabel","thumbIcon","description","error"],"Table":[],"Text":[],"ThemeIcon":[],"Title":[],"TransferList":[],"DateInput":["icon","rightSection","label","description","error","nextIcon","previousIcon","modalProps.title","modalProps.closeButtonProps.children"],"DatePicker":["nextIcon","previousIcon"],"DatePickerInput":["nextIcon","previousIcon","modalProps.title","modalProps.closeButtonProps.children","icon","rightSection","label","description","error"],"DatesProvider":[],"TimeInput":["icon","rightSection","label","description","error"],"Notification":["icon","title","message"],"Notifications":[],"Prism":[],"MantineProvider":[]},"dash_iconify":{"DashIconify":null},"dash_canvas":{"DashCanvas":null},"dash_player":{"DashPlayer":[]},"dash_vtk":{"Algorithm":null,"Calculator":null,"CellData":null,"DataArray":null,"FieldData":null,"GeometryRepresentation":null,"GlyphRepresentation":null,"ImageData":null,"Mesh":null,"PointCloudRepresentation":null,"PointData":null,"PolyData":null,"Reader":null,"ShareDataSet":null,"SliceRepresentation":null,"View":null,"Volume":null,"VolumeController":null,"VolumeDataRepresentation":null,"VolumeRepresentation":null},"dash_vega_components":{"Vega":[]}},"serve_locally":true}</script> <script src="/_dash-component-suites/dash/deps/polyfill@7.v2_18_0m1732036307.12.1.min.js"></script> <script src="/_dash-component-suites/dash/deps/react@16.v2_18_0m1732036307.14.0.min.js"></script> <script src="/_dash-component-suites/dash/deps/react-dom@16.v2_18_0m1732036307.14.0.min.js"></script> <script src="/_dash-component-suites/dash/deps/prop-types@15.v2_18_0m1732036307.8.1.min.js"></script> <script src="/_dash-component-suites/dash_design_kit/dash_design_kit.v1_14_0m1732036307.min.js"></script> <script src="/_dash-component-suites/dash_daq/dash_daq.v0_5_0m1732036323.min.js"></script> <script src="/_dash-component-suites/dash_bootstrap_components/_components/dash_bootstrap_components.v1_5_0m1732036316.min.js"></script> <script src="/_dash-component-suites/dash_user_guide_components/dash_user_guide_components.v0_0_8m1732036217.min.js"></script> <script src="/_dash-component-suites/dash_enterprise_libraries/dash_renderer/dash_renderer/dash_renderer.v1_4_1m1732036315.js"></script> <script src="/_dash-component-suites/dash_enterprise_libraries/components/dash_enterprise_libraries/dash_enterprise_libraries.v1_4_1m1732036315.js"></script> <script src="/_dash-component-suites/dash_bio/bundle.v1_0_2m1732036321.js"></script> <script src="/_dash-component-suites/dash_cytoscape/dash_cytoscape.v0_2_0m1732036323.min.js"></script> <script src="/_dash-component-suites/dash_embedded/dash_embedded.v2_17_0m1732036307.min.js"></script> <script src="/_dash-component-suites/dash_ag_grid/dash_ag_grid.v31_2_0m1732036316.min.js"></script> <script src="/_dash-component-suites/dash_mantine_components/dash_mantine_components.v0_13_0a3m1732036323.js"></script> <script src="/_dash-component-suites/dash_iconify/dash_iconify.v0_1_2m1732036323.min.js"></script> <script src="/_dash-component-suites/dash_canvas/dash_canvas.v0_1_0m1732036323.min.js"></script> <script src="/_dash-component-suites/dash_player/dash_player.v1_1_0m1732036324.min.js"></script> <script src="/_dash-component-suites/dash_vtk/dash_vtk.v0_0_9m1732036334.min.js"></script> <script src="/_dash-component-suites/dash_vega_components/dash_vega_components.v0_8_0devm1732036324.min.js"></script> <script src="/assets/clientside_example.js?m=1732036217.0"></script> <script src="/assets/dashAgGridClientsideCallbacks.js?m=1732036217.0"></script> <script src="/assets/dashAgGridComponentFunctions.js?m=1732036217.0"></script> <script src="/assets/dashAgGridFunctions.js?m=1732036217.0"></script> <script src="/assets/loading.js?m=1732036217.0"></script> <script src="/assets/tooltip.js?m=1732036217.0"></script> <script src="/assets/dash-design-kit/print-handler.js?m=1732036334.0"></script> <script src="/_dash-component-suites/dash/dash-renderer/build/dash_renderer.v2_18_0m1732036307.min.js"></script> <script src="/_dash-component-suites/dash/dcc/async-markdown.v2_14_2m1732036307.js"></script> <script src="/_dash-component-suites/dash/dcc/dash_core_components.v2_14_2m1732036307.js"></script> <script src="/_dash-component-suites/dash/dcc/dash_core_components-shared.v2_14_2m1732036307.js"></script> <script src="/_dash-component-suites/dash/html/dash_html_components.v2_0_19m1732036307.min.js"></script> <script src="/_dash-component-suites/dash/dash_table/bundle.v5_2_12m1732036307.js"></script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["d32110f6252871a225be1df6b3e25534d0e52613af4a444992b5f829410b333d"] = function(index, theme, presets) { if (index.every(x => x === undefined)) { return Array(2).fill(window.dash_clientside.no_update); } theme = theme.toLowerCase(); var idx = dash_clientside.callback_context.triggered_id["index"]; var active_preset = presets[`${theme}-style`]; active_preset["accent"] = presets[theme][idx]["accent"]; active_preset["user_color"] = presets[theme][idx]["user_color"]; return [ active_preset, [ active_preset["container_background"], active_preset["line_separator_color"], active_preset["header_title_color"], active_preset["header_subtitle_color"], active_preset["no_header_close_button_shadow_color"], active_preset["accent"], active_preset["user_color"], active_preset["assistant_background"], active_preset["assistant_color"], active_preset["response_action_button"], active_preset["chat_action_button_background_color"], active_preset["chat_action_button_color"], ] ]; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["4592cd5306724bf681848b1438defe041995bbcb3fc7bce5b825858eeb2474c6"] = function () { document.addEventListener('keydown', function(e) { if (e.ctrlKey && e.keyCode == 82) { // Simulate getting new data newData = JSON.stringify(new Date()) // Update dcc.Store with ID store-events dash_clientside.set_props("store-events", {data: newData}) event.preventDefault() event.stopPropagation() return dash_clientside.no_update; } }); return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["50355143269584b59943490dbf625504aa4fff023a27beb7e5987be9fb7afc14"] = function(){ console.log(dash_clientside.callback_context); const triggered_id = dash_clientside.callback_context.triggered_id; return "triggered id: " + triggered_id } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["bc59509db9dbc9ca67e47ed57998330f227754191c2f804ae1f6fcd668a433db"] = function () { var printContents = document.getElementById('grid-print-area').innerHTML; var originalContents = document.body.innerHTML; document.body.innerHTML = printContents; window.print(); document.body.innerHTML = originalContents; location.reload() return window.dash_clientside.no_update } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["f14be55984da1266fe5f898e53986abd85f025f85348fb5acb33d1d8b454a04b"] = function update_setpos_from_click(data, index, info) { if (data && data.points && data.points.length) { let point = data["points"][0]; let xyz = [point["x"], point["y"]]; let depth = info.offset[2] + index * info.stepsize[2]; xyz.splice(2 - info.axis, 0, depth); return xyz; } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e4d1e647de5956da1ab7b3802a76f21aaf4ac93984e55465aad63ae7b52addae"] = function update_slider_value(positions, cur_index, info) { for (let trigger of dash_clientside.callback_context.triggered) { if (!trigger.value) continue; let pos = trigger.value[2 - info.axis]; if (typeof pos !== 'number') continue; let index = Math.round((pos - info.offset[2]) / info.stepsize[2]); if (index == cur_index) continue; return Math.max(0, Math.min(info.size[2] - 1, index)); } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["8078f58cb18f4491159fcfb28ac8887d0579977a04cd0630b8df970cdf0c4cfc"] = function update_rate_limiting_info(index, relayoutData, n_intervals) { if (!window._slicer_slicer1) window._slicer_slicer1 = {}; let private_state = window._slicer_slicer1; let now = window.performance.now(); // Get whether the slider was moved, layout was changed, or timer ticked let slider_value_changed = false; let graph_layout_changed = false; let timer_ticked = false; for (let trigger of dash_clientside.callback_context.triggered) { if (trigger.prop_id.indexOf('slider') >= 0) slider_value_changed = true; if (trigger.prop_id.indexOf('timer') >= 0) timer_ticked = true; if (trigger.prop_id.indexOf('graph') >= 0) { for (let key in relayoutData) { if (key.startsWith("xaxis.range") || key.startsWith("yaxis.range")) { graph_layout_changed = true; } } } } // Set timeout and whether to disable the timer let disable_timer = false; if (slider_value_changed) { private_state.timeout = now + 200; } else if (graph_layout_changed) { private_state.timeout = now + 400; // need longer timeout for smooth scroll zoom } else if (!n_intervals) { private_state.timeout = now + 100; // initialize } else if (!private_state.timeout) { disable_timer = true; } return disable_timer; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["a11a47b742f0e458d9510f2aa8a55170d0d3335c66ec64d851c77c0f51420d84"] = function update_state(n_intervals, index, info, figure) { if (!window._slicer_slicer1) window._slicer_slicer1 = {}; let private_state = window._slicer_slicer1; let now = window.performance.now(); // Ready to apply and stop the timer, or return early? if (!(private_state.timeout && now >= private_state.timeout)) { return dash_clientside.no_update; } // Give the plot time to settle the initial axis ranges if (n_intervals < 5) { return dash_clientside.no_update; } // Disable the timer private_state.timeout = 0; // Calculate view range based on the volume let xrangeVol = [ info.offset[0] - 0.5 * info.stepsize[0], info.offset[0] + (info.size[0] - 0.5) * info.stepsize[0] ]; let yrangeVol = [ info.offset[1] - 0.5 * info.stepsize[1], info.offset[1] + (info.size[1] - 0.5) * info.stepsize[1] ]; // Get view range from the figure. We make range[0] < range[1] let xrangeFig = figure.layout.xaxis.range let yrangeFig = figure.layout.yaxis.range; xrangeFig = [Math.min(xrangeFig[0], xrangeFig[1]), Math.max(xrangeFig[0], xrangeFig[1])]; yrangeFig = [Math.min(yrangeFig[0], yrangeFig[1]), Math.max(yrangeFig[0], yrangeFig[1])]; // Add offset to avoid the corner-indicators for THIS slicer to only be half-visible let plotSize = [400, 400]; // This estimate results in ok results let graphDiv = document.getElementById('slicer1-graph'); let plotDiv = graphDiv.getElementsByClassName('js-plotly-plot')[0]; if (plotDiv && plotDiv._fullLayout) plotSize = [plotDiv._fullLayout.width, plotDiv._fullLayout.height]; xrangeFig[0] += 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; xrangeFig[1] -= 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; yrangeFig[0] += 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; yrangeFig[1] -= 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; // Combine the ranges let xrange = [Math.max(xrangeVol[0], xrangeFig[0]), Math.min(xrangeVol[1], xrangeFig[1])]; let yrange = [Math.max(yrangeVol[0], yrangeFig[0]), Math.min(yrangeVol[1], yrangeFig[1])]; // Create new state let new_state = { index: index, index_changed: false, xrange: xrange, yrange: yrange, zpos: info.offset[2] + index * info.stepsize[2], axis: info.axis, color: info.color, }; if (index != private_state.last_index || info.infoid != private_state.infoid) { private_state.last_index = index; new_state.index_changed = true; } private_state.infoid = info.infoid; // infoid changes on hot reload return new_state; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["280a79c61b994d44eda071bb0fff25c8f8881932997e8e3389ea3b02d5f84369"] = function update_image_traces(index, server_data, overlays, thumbnails, info, current_traces) { // Prepare traces let slice_trace = { type: 'image', x0: info.offset[0], y0: info.offset[1], dx: info.stepsize[0], dy: info.stepsize[1], hovertemplate: '(%{x:.2f}, %{y:.2f})<extra></extra>' }; let overlay_trace = {...slice_trace}; overlay_trace.hoverinfo = 'skip'; overlay_trace.source = overlays[index] || ''; overlay_trace.hovertemplate = ''; let new_traces = [slice_trace, overlay_trace]; // Use full data, or use thumbnails if (index == server_data.index) { slice_trace.source = server_data.slice; } else { slice_trace.source = thumbnails[index]; // Scale the image to take the exact same space as the full-res // version. Note that depending on how the low-res data is // created, the pixel centers may not be correctly aligned. slice_trace.dx *= info.size[0] / info.thumbnail_size[0]; slice_trace.dy *= info.size[1] / info.thumbnail_size[1]; slice_trace.x0 += 0.5 * slice_trace.dx - 0.5 * info.stepsize[0]; slice_trace.y0 += 0.5 * slice_trace.dy - 0.5 * info.stepsize[1]; } // Has the image data even changed? if (!current_traces.length) { current_traces = [{source:''}, {source:''}]; } if (new_traces[0].source == current_traces[0].source && new_traces[1].source == current_traces[1].source) { new_traces = dash_clientside.no_update; } return new_traces; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e8d2161e56a5d0a34e8bc130bcdbf21a309e3418cb2b6025569415bc563e7c91"] = function update_indicator_traces(states, info, thisState) { let traces = []; for (let state of states) { if (!state) continue; let zpos = [state.zpos, state.zpos]; let trace = null; if (info.axis == 0 && state.axis == 1) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 0 && state.axis == 2) { trace = {x: zpos, y: state.xrange}; } else if (info.axis == 1 && state.axis == 2) { trace = {x: zpos, y: state.yrange}; } else if (info.axis == 1 && state.axis == 0) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 2 && state.axis == 0) { trace = {x: state.yrange, y: zpos}; } else if (info.axis == 2 && state.axis == 1) { trace = {x: zpos, y: state.yrange}; } if (trace) { trace.line = {color: state.color, width: 1}; traces.push(trace); } } // Show our own color around the image, but only if there are other // slicers with the same scene id, on a different axis. We do some // math to make sure that these indicators are the same size (in // scene coordinates) for all slicers of the same data. if (thisState && info.color && traces.length) { let fraction = 0.1; let lengthx = info.size[0] * info.stepsize[0]; let lengthy = info.size[1] * info.stepsize[1]; let lengthz = info.size[2] * info.stepsize[2]; let dd = fraction * (lengthx + lengthy + lengthz) / 3; // average dd = Math.min(dd, 0.45 * Math.min(lengthx, lengthy, lengthz)); // failsafe let x1 = thisState.xrange[0]; let x2 = thisState.xrange[0] + dd; let x3 = thisState.xrange[1] - dd; let x4 = thisState.xrange[1]; let y1 = thisState.yrange[0]; let y2 = thisState.yrange[0] + dd; let y3 = thisState.yrange[1] - dd; let y4 = thisState.yrange[1]; traces.push({ x: [x1, x1, x2, null, x3, x4, x4, null, x4, x4, x3, null, x2, x1, x1], y: [y2, y1, y1, null, y1, y1, y2, null, y3, y4, y4, null, y4, y4, y3], line: {color: info.color, width: 4} }); } // Post-process the traces we created above for (let trace of traces) { trace.type = 'scatter'; trace.mode = 'lines'; trace.hoverinfo = 'skip'; trace.showlegend = false; } if (thisState) { return traces; } else { return dash_clientside.no_update; } } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["4f84255f8d1e848137904d58e835a8de8e5a9457ce7c3833e597b5b495f4f5d9"] = function update_figure(img_traces, indicator_traces, extra_traces, info, ori_figure) { // Collect traces let traces = []; for (let trace of img_traces) { traces.push(trace); } for (let trace of extra_traces) { traces.push(trace); } for (let trace of indicator_traces) { if (trace.line.color) traces.push(trace); } // Update figure let figure = {...ori_figure}; figure.data = traces; return figure; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["f14be55984da1266fe5f898e53986abd85f025f85348fb5acb33d1d8b454a04b"] = function update_setpos_from_click(data, index, info) { if (data && data.points && data.points.length) { let point = data["points"][0]; let xyz = [point["x"], point["y"]]; let depth = info.offset[2] + index * info.stepsize[2]; xyz.splice(2 - info.axis, 0, depth); return xyz; } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e4d1e647de5956da1ab7b3802a76f21aaf4ac93984e55465aad63ae7b52addae"] = function update_slider_value(positions, cur_index, info) { for (let trigger of dash_clientside.callback_context.triggered) { if (!trigger.value) continue; let pos = trigger.value[2 - info.axis]; if (typeof pos !== 'number') continue; let index = Math.round((pos - info.offset[2]) / info.stepsize[2]); if (index == cur_index) continue; return Math.max(0, Math.min(info.size[2] - 1, index)); } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["40992178b9d2d41a7d1a477d98a0199d1d7b93ec44e5b41a27fd9bf294164cf8"] = function update_rate_limiting_info(index, relayoutData, n_intervals) { if (!window._slicer_slicer2) window._slicer_slicer2 = {}; let private_state = window._slicer_slicer2; let now = window.performance.now(); // Get whether the slider was moved, layout was changed, or timer ticked let slider_value_changed = false; let graph_layout_changed = false; let timer_ticked = false; for (let trigger of dash_clientside.callback_context.triggered) { if (trigger.prop_id.indexOf('slider') >= 0) slider_value_changed = true; if (trigger.prop_id.indexOf('timer') >= 0) timer_ticked = true; if (trigger.prop_id.indexOf('graph') >= 0) { for (let key in relayoutData) { if (key.startsWith("xaxis.range") || key.startsWith("yaxis.range")) { graph_layout_changed = true; } } } } // Set timeout and whether to disable the timer let disable_timer = false; if (slider_value_changed) { private_state.timeout = now + 200; } else if (graph_layout_changed) { private_state.timeout = now + 400; // need longer timeout for smooth scroll zoom } else if (!n_intervals) { private_state.timeout = now + 100; // initialize } else if (!private_state.timeout) { disable_timer = true; } return disable_timer; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["a61252172c75869ceea1743840abf064b855132ef4c14e6eb799f1469a383637"] = function update_state(n_intervals, index, info, figure) { if (!window._slicer_slicer2) window._slicer_slicer2 = {}; let private_state = window._slicer_slicer2; let now = window.performance.now(); // Ready to apply and stop the timer, or return early? if (!(private_state.timeout && now >= private_state.timeout)) { return dash_clientside.no_update; } // Give the plot time to settle the initial axis ranges if (n_intervals < 5) { return dash_clientside.no_update; } // Disable the timer private_state.timeout = 0; // Calculate view range based on the volume let xrangeVol = [ info.offset[0] - 0.5 * info.stepsize[0], info.offset[0] + (info.size[0] - 0.5) * info.stepsize[0] ]; let yrangeVol = [ info.offset[1] - 0.5 * info.stepsize[1], info.offset[1] + (info.size[1] - 0.5) * info.stepsize[1] ]; // Get view range from the figure. We make range[0] < range[1] let xrangeFig = figure.layout.xaxis.range let yrangeFig = figure.layout.yaxis.range; xrangeFig = [Math.min(xrangeFig[0], xrangeFig[1]), Math.max(xrangeFig[0], xrangeFig[1])]; yrangeFig = [Math.min(yrangeFig[0], yrangeFig[1]), Math.max(yrangeFig[0], yrangeFig[1])]; // Add offset to avoid the corner-indicators for THIS slicer to only be half-visible let plotSize = [400, 400]; // This estimate results in ok results let graphDiv = document.getElementById('slicer2-graph'); let plotDiv = graphDiv.getElementsByClassName('js-plotly-plot')[0]; if (plotDiv && plotDiv._fullLayout) plotSize = [plotDiv._fullLayout.width, plotDiv._fullLayout.height]; xrangeFig[0] += 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; xrangeFig[1] -= 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; yrangeFig[0] += 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; yrangeFig[1] -= 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; // Combine the ranges let xrange = [Math.max(xrangeVol[0], xrangeFig[0]), Math.min(xrangeVol[1], xrangeFig[1])]; let yrange = [Math.max(yrangeVol[0], yrangeFig[0]), Math.min(yrangeVol[1], yrangeFig[1])]; // Create new state let new_state = { index: index, index_changed: false, xrange: xrange, yrange: yrange, zpos: info.offset[2] + index * info.stepsize[2], axis: info.axis, color: info.color, }; if (index != private_state.last_index || info.infoid != private_state.infoid) { private_state.last_index = index; new_state.index_changed = true; } private_state.infoid = info.infoid; // infoid changes on hot reload return new_state; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["280a79c61b994d44eda071bb0fff25c8f8881932997e8e3389ea3b02d5f84369"] = function update_image_traces(index, server_data, overlays, thumbnails, info, current_traces) { // Prepare traces let slice_trace = { type: 'image', x0: info.offset[0], y0: info.offset[1], dx: info.stepsize[0], dy: info.stepsize[1], hovertemplate: '(%{x:.2f}, %{y:.2f})<extra></extra>' }; let overlay_trace = {...slice_trace}; overlay_trace.hoverinfo = 'skip'; overlay_trace.source = overlays[index] || ''; overlay_trace.hovertemplate = ''; let new_traces = [slice_trace, overlay_trace]; // Use full data, or use thumbnails if (index == server_data.index) { slice_trace.source = server_data.slice; } else { slice_trace.source = thumbnails[index]; // Scale the image to take the exact same space as the full-res // version. Note that depending on how the low-res data is // created, the pixel centers may not be correctly aligned. slice_trace.dx *= info.size[0] / info.thumbnail_size[0]; slice_trace.dy *= info.size[1] / info.thumbnail_size[1]; slice_trace.x0 += 0.5 * slice_trace.dx - 0.5 * info.stepsize[0]; slice_trace.y0 += 0.5 * slice_trace.dy - 0.5 * info.stepsize[1]; } // Has the image data even changed? if (!current_traces.length) { current_traces = [{source:''}, {source:''}]; } if (new_traces[0].source == current_traces[0].source && new_traces[1].source == current_traces[1].source) { new_traces = dash_clientside.no_update; } return new_traces; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e8d2161e56a5d0a34e8bc130bcdbf21a309e3418cb2b6025569415bc563e7c91"] = function update_indicator_traces(states, info, thisState) { let traces = []; for (let state of states) { if (!state) continue; let zpos = [state.zpos, state.zpos]; let trace = null; if (info.axis == 0 && state.axis == 1) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 0 && state.axis == 2) { trace = {x: zpos, y: state.xrange}; } else if (info.axis == 1 && state.axis == 2) { trace = {x: zpos, y: state.yrange}; } else if (info.axis == 1 && state.axis == 0) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 2 && state.axis == 0) { trace = {x: state.yrange, y: zpos}; } else if (info.axis == 2 && state.axis == 1) { trace = {x: zpos, y: state.yrange}; } if (trace) { trace.line = {color: state.color, width: 1}; traces.push(trace); } } // Show our own color around the image, but only if there are other // slicers with the same scene id, on a different axis. We do some // math to make sure that these indicators are the same size (in // scene coordinates) for all slicers of the same data. if (thisState && info.color && traces.length) { let fraction = 0.1; let lengthx = info.size[0] * info.stepsize[0]; let lengthy = info.size[1] * info.stepsize[1]; let lengthz = info.size[2] * info.stepsize[2]; let dd = fraction * (lengthx + lengthy + lengthz) / 3; // average dd = Math.min(dd, 0.45 * Math.min(lengthx, lengthy, lengthz)); // failsafe let x1 = thisState.xrange[0]; let x2 = thisState.xrange[0] + dd; let x3 = thisState.xrange[1] - dd; let x4 = thisState.xrange[1]; let y1 = thisState.yrange[0]; let y2 = thisState.yrange[0] + dd; let y3 = thisState.yrange[1] - dd; let y4 = thisState.yrange[1]; traces.push({ x: [x1, x1, x2, null, x3, x4, x4, null, x4, x4, x3, null, x2, x1, x1], y: [y2, y1, y1, null, y1, y1, y2, null, y3, y4, y4, null, y4, y4, y3], line: {color: info.color, width: 4} }); } // Post-process the traces we created above for (let trace of traces) { trace.type = 'scatter'; trace.mode = 'lines'; trace.hoverinfo = 'skip'; trace.showlegend = false; } if (thisState) { return traces; } else { return dash_clientside.no_update; } } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["4f84255f8d1e848137904d58e835a8de8e5a9457ce7c3833e597b5b495f4f5d9"] = function update_figure(img_traces, indicator_traces, extra_traces, info, ori_figure) { // Collect traces let traces = []; for (let trace of img_traces) { traces.push(trace); } for (let trace of extra_traces) { traces.push(trace); } for (let trace of indicator_traces) { if (trace.line.color) traces.push(trace); } // Update figure let figure = {...ori_figure}; figure.data = traces; return figure; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["f14be55984da1266fe5f898e53986abd85f025f85348fb5acb33d1d8b454a04b"] = function update_setpos_from_click(data, index, info) { if (data && data.points && data.points.length) { let point = data["points"][0]; let xyz = [point["x"], point["y"]]; let depth = info.offset[2] + index * info.stepsize[2]; xyz.splice(2 - info.axis, 0, depth); return xyz; } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e4d1e647de5956da1ab7b3802a76f21aaf4ac93984e55465aad63ae7b52addae"] = function update_slider_value(positions, cur_index, info) { for (let trigger of dash_clientside.callback_context.triggered) { if (!trigger.value) continue; let pos = trigger.value[2 - info.axis]; if (typeof pos !== 'number') continue; let index = Math.round((pos - info.offset[2]) / info.stepsize[2]); if (index == cur_index) continue; return Math.max(0, Math.min(info.size[2] - 1, index)); } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["7de3589c516874862a6861efcb57d36c327f5b0850c8b3c12b0960050dd83dec"] = function update_rate_limiting_info(index, relayoutData, n_intervals) { if (!window._slicer_slicer3) window._slicer_slicer3 = {}; let private_state = window._slicer_slicer3; let now = window.performance.now(); // Get whether the slider was moved, layout was changed, or timer ticked let slider_value_changed = false; let graph_layout_changed = false; let timer_ticked = false; for (let trigger of dash_clientside.callback_context.triggered) { if (trigger.prop_id.indexOf('slider') >= 0) slider_value_changed = true; if (trigger.prop_id.indexOf('timer') >= 0) timer_ticked = true; if (trigger.prop_id.indexOf('graph') >= 0) { for (let key in relayoutData) { if (key.startsWith("xaxis.range") || key.startsWith("yaxis.range")) { graph_layout_changed = true; } } } } // Set timeout and whether to disable the timer let disable_timer = false; if (slider_value_changed) { private_state.timeout = now + 200; } else if (graph_layout_changed) { private_state.timeout = now + 400; // need longer timeout for smooth scroll zoom } else if (!n_intervals) { private_state.timeout = now + 100; // initialize } else if (!private_state.timeout) { disable_timer = true; } return disable_timer; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["693aa95458e86c7ce8ec6145c8dfed9da1f46ebbd655a462b6e08e8121eb2d55"] = function update_state(n_intervals, index, info, figure) { if (!window._slicer_slicer3) window._slicer_slicer3 = {}; let private_state = window._slicer_slicer3; let now = window.performance.now(); // Ready to apply and stop the timer, or return early? if (!(private_state.timeout && now >= private_state.timeout)) { return dash_clientside.no_update; } // Give the plot time to settle the initial axis ranges if (n_intervals < 5) { return dash_clientside.no_update; } // Disable the timer private_state.timeout = 0; // Calculate view range based on the volume let xrangeVol = [ info.offset[0] - 0.5 * info.stepsize[0], info.offset[0] + (info.size[0] - 0.5) * info.stepsize[0] ]; let yrangeVol = [ info.offset[1] - 0.5 * info.stepsize[1], info.offset[1] + (info.size[1] - 0.5) * info.stepsize[1] ]; // Get view range from the figure. We make range[0] < range[1] let xrangeFig = figure.layout.xaxis.range let yrangeFig = figure.layout.yaxis.range; xrangeFig = [Math.min(xrangeFig[0], xrangeFig[1]), Math.max(xrangeFig[0], xrangeFig[1])]; yrangeFig = [Math.min(yrangeFig[0], yrangeFig[1]), Math.max(yrangeFig[0], yrangeFig[1])]; // Add offset to avoid the corner-indicators for THIS slicer to only be half-visible let plotSize = [400, 400]; // This estimate results in ok results let graphDiv = document.getElementById('slicer3-graph'); let plotDiv = graphDiv.getElementsByClassName('js-plotly-plot')[0]; if (plotDiv && plotDiv._fullLayout) plotSize = [plotDiv._fullLayout.width, plotDiv._fullLayout.height]; xrangeFig[0] += 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; xrangeFig[1] -= 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; yrangeFig[0] += 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; yrangeFig[1] -= 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; // Combine the ranges let xrange = [Math.max(xrangeVol[0], xrangeFig[0]), Math.min(xrangeVol[1], xrangeFig[1])]; let yrange = [Math.max(yrangeVol[0], yrangeFig[0]), Math.min(yrangeVol[1], yrangeFig[1])]; // Create new state let new_state = { index: index, index_changed: false, xrange: xrange, yrange: yrange, zpos: info.offset[2] + index * info.stepsize[2], axis: info.axis, color: info.color, }; if (index != private_state.last_index || info.infoid != private_state.infoid) { private_state.last_index = index; new_state.index_changed = true; } private_state.infoid = info.infoid; // infoid changes on hot reload return new_state; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["280a79c61b994d44eda071bb0fff25c8f8881932997e8e3389ea3b02d5f84369"] = function update_image_traces(index, server_data, overlays, thumbnails, info, current_traces) { // Prepare traces let slice_trace = { type: 'image', x0: info.offset[0], y0: info.offset[1], dx: info.stepsize[0], dy: info.stepsize[1], hovertemplate: '(%{x:.2f}, %{y:.2f})<extra></extra>' }; let overlay_trace = {...slice_trace}; overlay_trace.hoverinfo = 'skip'; overlay_trace.source = overlays[index] || ''; overlay_trace.hovertemplate = ''; let new_traces = [slice_trace, overlay_trace]; // Use full data, or use thumbnails if (index == server_data.index) { slice_trace.source = server_data.slice; } else { slice_trace.source = thumbnails[index]; // Scale the image to take the exact same space as the full-res // version. Note that depending on how the low-res data is // created, the pixel centers may not be correctly aligned. slice_trace.dx *= info.size[0] / info.thumbnail_size[0]; slice_trace.dy *= info.size[1] / info.thumbnail_size[1]; slice_trace.x0 += 0.5 * slice_trace.dx - 0.5 * info.stepsize[0]; slice_trace.y0 += 0.5 * slice_trace.dy - 0.5 * info.stepsize[1]; } // Has the image data even changed? if (!current_traces.length) { current_traces = [{source:''}, {source:''}]; } if (new_traces[0].source == current_traces[0].source && new_traces[1].source == current_traces[1].source) { new_traces = dash_clientside.no_update; } return new_traces; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e8d2161e56a5d0a34e8bc130bcdbf21a309e3418cb2b6025569415bc563e7c91"] = function update_indicator_traces(states, info, thisState) { let traces = []; for (let state of states) { if (!state) continue; let zpos = [state.zpos, state.zpos]; let trace = null; if (info.axis == 0 && state.axis == 1) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 0 && state.axis == 2) { trace = {x: zpos, y: state.xrange}; } else if (info.axis == 1 && state.axis == 2) { trace = {x: zpos, y: state.yrange}; } else if (info.axis == 1 && state.axis == 0) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 2 && state.axis == 0) { trace = {x: state.yrange, y: zpos}; } else if (info.axis == 2 && state.axis == 1) { trace = {x: zpos, y: state.yrange}; } if (trace) { trace.line = {color: state.color, width: 1}; traces.push(trace); } } // Show our own color around the image, but only if there are other // slicers with the same scene id, on a different axis. We do some // math to make sure that these indicators are the same size (in // scene coordinates) for all slicers of the same data. if (thisState && info.color && traces.length) { let fraction = 0.1; let lengthx = info.size[0] * info.stepsize[0]; let lengthy = info.size[1] * info.stepsize[1]; let lengthz = info.size[2] * info.stepsize[2]; let dd = fraction * (lengthx + lengthy + lengthz) / 3; // average dd = Math.min(dd, 0.45 * Math.min(lengthx, lengthy, lengthz)); // failsafe let x1 = thisState.xrange[0]; let x2 = thisState.xrange[0] + dd; let x3 = thisState.xrange[1] - dd; let x4 = thisState.xrange[1]; let y1 = thisState.yrange[0]; let y2 = thisState.yrange[0] + dd; let y3 = thisState.yrange[1] - dd; let y4 = thisState.yrange[1]; traces.push({ x: [x1, x1, x2, null, x3, x4, x4, null, x4, x4, x3, null, x2, x1, x1], y: [y2, y1, y1, null, y1, y1, y2, null, y3, y4, y4, null, y4, y4, y3], line: {color: info.color, width: 4} }); } // Post-process the traces we created above for (let trace of traces) { trace.type = 'scatter'; trace.mode = 'lines'; trace.hoverinfo = 'skip'; trace.showlegend = false; } if (thisState) { return traces; } else { return dash_clientside.no_update; } } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["4f84255f8d1e848137904d58e835a8de8e5a9457ce7c3833e597b5b495f4f5d9"] = function update_figure(img_traces, indicator_traces, extra_traces, info, ori_figure) { // Collect traces let traces = []; for (let trace of img_traces) { traces.push(trace); } for (let trace of extra_traces) { traces.push(trace); } for (let trace of indicator_traces) { if (trace.line.color) traces.push(trace); } // Update figure let figure = {...ori_figure}; figure.data = traces; return figure; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["f14be55984da1266fe5f898e53986abd85f025f85348fb5acb33d1d8b454a04b"] = function update_setpos_from_click(data, index, info) { if (data && data.points && data.points.length) { let point = data["points"][0]; let xyz = [point["x"], point["y"]]; let depth = info.offset[2] + index * info.stepsize[2]; xyz.splice(2 - info.axis, 0, depth); return xyz; } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e4d1e647de5956da1ab7b3802a76f21aaf4ac93984e55465aad63ae7b52addae"] = function update_slider_value(positions, cur_index, info) { for (let trigger of dash_clientside.callback_context.triggered) { if (!trigger.value) continue; let pos = trigger.value[2 - info.axis]; if (typeof pos !== 'number') continue; let index = Math.round((pos - info.offset[2]) / info.stepsize[2]); if (index == cur_index) continue; return Math.max(0, Math.min(info.size[2] - 1, index)); } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["768dc844c7c5399a567952800bcc1cd7cdfd588ac2d09fc8d97679740c5f9439"] = function update_rate_limiting_info(index, relayoutData, n_intervals) { if (!window._slicer_slicer4) window._slicer_slicer4 = {}; let private_state = window._slicer_slicer4; let now = window.performance.now(); // Get whether the slider was moved, layout was changed, or timer ticked let slider_value_changed = false; let graph_layout_changed = false; let timer_ticked = false; for (let trigger of dash_clientside.callback_context.triggered) { if (trigger.prop_id.indexOf('slider') >= 0) slider_value_changed = true; if (trigger.prop_id.indexOf('timer') >= 0) timer_ticked = true; if (trigger.prop_id.indexOf('graph') >= 0) { for (let key in relayoutData) { if (key.startsWith("xaxis.range") || key.startsWith("yaxis.range")) { graph_layout_changed = true; } } } } // Set timeout and whether to disable the timer let disable_timer = false; if (slider_value_changed) { private_state.timeout = now + 200; } else if (graph_layout_changed) { private_state.timeout = now + 400; // need longer timeout for smooth scroll zoom } else if (!n_intervals) { private_state.timeout = now + 100; // initialize } else if (!private_state.timeout) { disable_timer = true; } return disable_timer; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["9cb7d6cf4a2c728d8ee89be5f2fe861daade77da9e6dedbdafd07d9c091917c0"] = function update_state(n_intervals, index, info, figure) { if (!window._slicer_slicer4) window._slicer_slicer4 = {}; let private_state = window._slicer_slicer4; let now = window.performance.now(); // Ready to apply and stop the timer, or return early? if (!(private_state.timeout && now >= private_state.timeout)) { return dash_clientside.no_update; } // Give the plot time to settle the initial axis ranges if (n_intervals < 5) { return dash_clientside.no_update; } // Disable the timer private_state.timeout = 0; // Calculate view range based on the volume let xrangeVol = [ info.offset[0] - 0.5 * info.stepsize[0], info.offset[0] + (info.size[0] - 0.5) * info.stepsize[0] ]; let yrangeVol = [ info.offset[1] - 0.5 * info.stepsize[1], info.offset[1] + (info.size[1] - 0.5) * info.stepsize[1] ]; // Get view range from the figure. We make range[0] < range[1] let xrangeFig = figure.layout.xaxis.range let yrangeFig = figure.layout.yaxis.range; xrangeFig = [Math.min(xrangeFig[0], xrangeFig[1]), Math.max(xrangeFig[0], xrangeFig[1])]; yrangeFig = [Math.min(yrangeFig[0], yrangeFig[1]), Math.max(yrangeFig[0], yrangeFig[1])]; // Add offset to avoid the corner-indicators for THIS slicer to only be half-visible let plotSize = [400, 400]; // This estimate results in ok results let graphDiv = document.getElementById('slicer4-graph'); let plotDiv = graphDiv.getElementsByClassName('js-plotly-plot')[0]; if (plotDiv && plotDiv._fullLayout) plotSize = [plotDiv._fullLayout.width, plotDiv._fullLayout.height]; xrangeFig[0] += 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; xrangeFig[1] -= 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; yrangeFig[0] += 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; yrangeFig[1] -= 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; // Combine the ranges let xrange = [Math.max(xrangeVol[0], xrangeFig[0]), Math.min(xrangeVol[1], xrangeFig[1])]; let yrange = [Math.max(yrangeVol[0], yrangeFig[0]), Math.min(yrangeVol[1], yrangeFig[1])]; // Create new state let new_state = { index: index, index_changed: false, xrange: xrange, yrange: yrange, zpos: info.offset[2] + index * info.stepsize[2], axis: info.axis, color: info.color, }; if (index != private_state.last_index || info.infoid != private_state.infoid) { private_state.last_index = index; new_state.index_changed = true; } private_state.infoid = info.infoid; // infoid changes on hot reload return new_state; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["280a79c61b994d44eda071bb0fff25c8f8881932997e8e3389ea3b02d5f84369"] = function update_image_traces(index, server_data, overlays, thumbnails, info, current_traces) { // Prepare traces let slice_trace = { type: 'image', x0: info.offset[0], y0: info.offset[1], dx: info.stepsize[0], dy: info.stepsize[1], hovertemplate: '(%{x:.2f}, %{y:.2f})<extra></extra>' }; let overlay_trace = {...slice_trace}; overlay_trace.hoverinfo = 'skip'; overlay_trace.source = overlays[index] || ''; overlay_trace.hovertemplate = ''; let new_traces = [slice_trace, overlay_trace]; // Use full data, or use thumbnails if (index == server_data.index) { slice_trace.source = server_data.slice; } else { slice_trace.source = thumbnails[index]; // Scale the image to take the exact same space as the full-res // version. Note that depending on how the low-res data is // created, the pixel centers may not be correctly aligned. slice_trace.dx *= info.size[0] / info.thumbnail_size[0]; slice_trace.dy *= info.size[1] / info.thumbnail_size[1]; slice_trace.x0 += 0.5 * slice_trace.dx - 0.5 * info.stepsize[0]; slice_trace.y0 += 0.5 * slice_trace.dy - 0.5 * info.stepsize[1]; } // Has the image data even changed? if (!current_traces.length) { current_traces = [{source:''}, {source:''}]; } if (new_traces[0].source == current_traces[0].source && new_traces[1].source == current_traces[1].source) { new_traces = dash_clientside.no_update; } return new_traces; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e8d2161e56a5d0a34e8bc130bcdbf21a309e3418cb2b6025569415bc563e7c91"] = function update_indicator_traces(states, info, thisState) { let traces = []; for (let state of states) { if (!state) continue; let zpos = [state.zpos, state.zpos]; let trace = null; if (info.axis == 0 && state.axis == 1) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 0 && state.axis == 2) { trace = {x: zpos, y: state.xrange}; } else if (info.axis == 1 && state.axis == 2) { trace = {x: zpos, y: state.yrange}; } else if (info.axis == 1 && state.axis == 0) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 2 && state.axis == 0) { trace = {x: state.yrange, y: zpos}; } else if (info.axis == 2 && state.axis == 1) { trace = {x: zpos, y: state.yrange}; } if (trace) { trace.line = {color: state.color, width: 1}; traces.push(trace); } } // Show our own color around the image, but only if there are other // slicers with the same scene id, on a different axis. We do some // math to make sure that these indicators are the same size (in // scene coordinates) for all slicers of the same data. if (thisState && info.color && traces.length) { let fraction = 0.1; let lengthx = info.size[0] * info.stepsize[0]; let lengthy = info.size[1] * info.stepsize[1]; let lengthz = info.size[2] * info.stepsize[2]; let dd = fraction * (lengthx + lengthy + lengthz) / 3; // average dd = Math.min(dd, 0.45 * Math.min(lengthx, lengthy, lengthz)); // failsafe let x1 = thisState.xrange[0]; let x2 = thisState.xrange[0] + dd; let x3 = thisState.xrange[1] - dd; let x4 = thisState.xrange[1]; let y1 = thisState.yrange[0]; let y2 = thisState.yrange[0] + dd; let y3 = thisState.yrange[1] - dd; let y4 = thisState.yrange[1]; traces.push({ x: [x1, x1, x2, null, x3, x4, x4, null, x4, x4, x3, null, x2, x1, x1], y: [y2, y1, y1, null, y1, y1, y2, null, y3, y4, y4, null, y4, y4, y3], line: {color: info.color, width: 4} }); } // Post-process the traces we created above for (let trace of traces) { trace.type = 'scatter'; trace.mode = 'lines'; trace.hoverinfo = 'skip'; trace.showlegend = false; } if (thisState) { return traces; } else { return dash_clientside.no_update; } } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["4f84255f8d1e848137904d58e835a8de8e5a9457ce7c3833e597b5b495f4f5d9"] = function update_figure(img_traces, indicator_traces, extra_traces, info, ori_figure) { // Collect traces let traces = []; for (let trace of img_traces) { traces.push(trace); } for (let trace of extra_traces) { traces.push(trace); } for (let trace of indicator_traces) { if (trace.line.color) traces.push(trace); } // Update figure let figure = {...ori_figure}; figure.data = traces; return figure; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["f14be55984da1266fe5f898e53986abd85f025f85348fb5acb33d1d8b454a04b"] = function update_setpos_from_click(data, index, info) { if (data && data.points && data.points.length) { let point = data["points"][0]; let xyz = [point["x"], point["y"]]; let depth = info.offset[2] + index * info.stepsize[2]; xyz.splice(2 - info.axis, 0, depth); return xyz; } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e4d1e647de5956da1ab7b3802a76f21aaf4ac93984e55465aad63ae7b52addae"] = function update_slider_value(positions, cur_index, info) { for (let trigger of dash_clientside.callback_context.triggered) { if (!trigger.value) continue; let pos = trigger.value[2 - info.axis]; if (typeof pos !== 'number') continue; let index = Math.round((pos - info.offset[2]) / info.stepsize[2]); if (index == cur_index) continue; return Math.max(0, Math.min(info.size[2] - 1, index)); } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["dc16b1349f75a0c2740f93c8ad1ad947f2a1f80e7b329a47118315987ee51bb8"] = function update_rate_limiting_info(index, relayoutData, n_intervals) { if (!window._slicer_slicer5) window._slicer_slicer5 = {}; let private_state = window._slicer_slicer5; let now = window.performance.now(); // Get whether the slider was moved, layout was changed, or timer ticked let slider_value_changed = false; let graph_layout_changed = false; let timer_ticked = false; for (let trigger of dash_clientside.callback_context.triggered) { if (trigger.prop_id.indexOf('slider') >= 0) slider_value_changed = true; if (trigger.prop_id.indexOf('timer') >= 0) timer_ticked = true; if (trigger.prop_id.indexOf('graph') >= 0) { for (let key in relayoutData) { if (key.startsWith("xaxis.range") || key.startsWith("yaxis.range")) { graph_layout_changed = true; } } } } // Set timeout and whether to disable the timer let disable_timer = false; if (slider_value_changed) { private_state.timeout = now + 200; } else if (graph_layout_changed) { private_state.timeout = now + 400; // need longer timeout for smooth scroll zoom } else if (!n_intervals) { private_state.timeout = now + 100; // initialize } else if (!private_state.timeout) { disable_timer = true; } return disable_timer; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["faa62306b98f3ce4cf7ce574db47a66efd11e38dc1c98fafdf1d9a9d6652afeb"] = function update_state(n_intervals, index, info, figure) { if (!window._slicer_slicer5) window._slicer_slicer5 = {}; let private_state = window._slicer_slicer5; let now = window.performance.now(); // Ready to apply and stop the timer, or return early? if (!(private_state.timeout && now >= private_state.timeout)) { return dash_clientside.no_update; } // Give the plot time to settle the initial axis ranges if (n_intervals < 5) { return dash_clientside.no_update; } // Disable the timer private_state.timeout = 0; // Calculate view range based on the volume let xrangeVol = [ info.offset[0] - 0.5 * info.stepsize[0], info.offset[0] + (info.size[0] - 0.5) * info.stepsize[0] ]; let yrangeVol = [ info.offset[1] - 0.5 * info.stepsize[1], info.offset[1] + (info.size[1] - 0.5) * info.stepsize[1] ]; // Get view range from the figure. We make range[0] < range[1] let xrangeFig = figure.layout.xaxis.range let yrangeFig = figure.layout.yaxis.range; xrangeFig = [Math.min(xrangeFig[0], xrangeFig[1]), Math.max(xrangeFig[0], xrangeFig[1])]; yrangeFig = [Math.min(yrangeFig[0], yrangeFig[1]), Math.max(yrangeFig[0], yrangeFig[1])]; // Add offset to avoid the corner-indicators for THIS slicer to only be half-visible let plotSize = [400, 400]; // This estimate results in ok results let graphDiv = document.getElementById('slicer5-graph'); let plotDiv = graphDiv.getElementsByClassName('js-plotly-plot')[0]; if (plotDiv && plotDiv._fullLayout) plotSize = [plotDiv._fullLayout.width, plotDiv._fullLayout.height]; xrangeFig[0] += 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; xrangeFig[1] -= 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; yrangeFig[0] += 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; yrangeFig[1] -= 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; // Combine the ranges let xrange = [Math.max(xrangeVol[0], xrangeFig[0]), Math.min(xrangeVol[1], xrangeFig[1])]; let yrange = [Math.max(yrangeVol[0], yrangeFig[0]), Math.min(yrangeVol[1], yrangeFig[1])]; // Create new state let new_state = { index: index, index_changed: false, xrange: xrange, yrange: yrange, zpos: info.offset[2] + index * info.stepsize[2], axis: info.axis, color: info.color, }; if (index != private_state.last_index || info.infoid != private_state.infoid) { private_state.last_index = index; new_state.index_changed = true; } private_state.infoid = info.infoid; // infoid changes on hot reload return new_state; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["280a79c61b994d44eda071bb0fff25c8f8881932997e8e3389ea3b02d5f84369"] = function update_image_traces(index, server_data, overlays, thumbnails, info, current_traces) { // Prepare traces let slice_trace = { type: 'image', x0: info.offset[0], y0: info.offset[1], dx: info.stepsize[0], dy: info.stepsize[1], hovertemplate: '(%{x:.2f}, %{y:.2f})<extra></extra>' }; let overlay_trace = {...slice_trace}; overlay_trace.hoverinfo = 'skip'; overlay_trace.source = overlays[index] || ''; overlay_trace.hovertemplate = ''; let new_traces = [slice_trace, overlay_trace]; // Use full data, or use thumbnails if (index == server_data.index) { slice_trace.source = server_data.slice; } else { slice_trace.source = thumbnails[index]; // Scale the image to take the exact same space as the full-res // version. Note that depending on how the low-res data is // created, the pixel centers may not be correctly aligned. slice_trace.dx *= info.size[0] / info.thumbnail_size[0]; slice_trace.dy *= info.size[1] / info.thumbnail_size[1]; slice_trace.x0 += 0.5 * slice_trace.dx - 0.5 * info.stepsize[0]; slice_trace.y0 += 0.5 * slice_trace.dy - 0.5 * info.stepsize[1]; } // Has the image data even changed? if (!current_traces.length) { current_traces = [{source:''}, {source:''}]; } if (new_traces[0].source == current_traces[0].source && new_traces[1].source == current_traces[1].source) { new_traces = dash_clientside.no_update; } return new_traces; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e8d2161e56a5d0a34e8bc130bcdbf21a309e3418cb2b6025569415bc563e7c91"] = function update_indicator_traces(states, info, thisState) { let traces = []; for (let state of states) { if (!state) continue; let zpos = [state.zpos, state.zpos]; let trace = null; if (info.axis == 0 && state.axis == 1) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 0 && state.axis == 2) { trace = {x: zpos, y: state.xrange}; } else if (info.axis == 1 && state.axis == 2) { trace = {x: zpos, y: state.yrange}; } else if (info.axis == 1 && state.axis == 0) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 2 && state.axis == 0) { trace = {x: state.yrange, y: zpos}; } else if (info.axis == 2 && state.axis == 1) { trace = {x: zpos, y: state.yrange}; } if (trace) { trace.line = {color: state.color, width: 1}; traces.push(trace); } } // Show our own color around the image, but only if there are other // slicers with the same scene id, on a different axis. We do some // math to make sure that these indicators are the same size (in // scene coordinates) for all slicers of the same data. if (thisState && info.color && traces.length) { let fraction = 0.1; let lengthx = info.size[0] * info.stepsize[0]; let lengthy = info.size[1] * info.stepsize[1]; let lengthz = info.size[2] * info.stepsize[2]; let dd = fraction * (lengthx + lengthy + lengthz) / 3; // average dd = Math.min(dd, 0.45 * Math.min(lengthx, lengthy, lengthz)); // failsafe let x1 = thisState.xrange[0]; let x2 = thisState.xrange[0] + dd; let x3 = thisState.xrange[1] - dd; let x4 = thisState.xrange[1]; let y1 = thisState.yrange[0]; let y2 = thisState.yrange[0] + dd; let y3 = thisState.yrange[1] - dd; let y4 = thisState.yrange[1]; traces.push({ x: [x1, x1, x2, null, x3, x4, x4, null, x4, x4, x3, null, x2, x1, x1], y: [y2, y1, y1, null, y1, y1, y2, null, y3, y4, y4, null, y4, y4, y3], line: {color: info.color, width: 4} }); } // Post-process the traces we created above for (let trace of traces) { trace.type = 'scatter'; trace.mode = 'lines'; trace.hoverinfo = 'skip'; trace.showlegend = false; } if (thisState) { return traces; } else { return dash_clientside.no_update; } } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["4f84255f8d1e848137904d58e835a8de8e5a9457ce7c3833e597b5b495f4f5d9"] = function update_figure(img_traces, indicator_traces, extra_traces, info, ori_figure) { // Collect traces let traces = []; for (let trace of img_traces) { traces.push(trace); } for (let trace of extra_traces) { traces.push(trace); } for (let trace of indicator_traces) { if (trace.line.color) traces.push(trace); } // Update figure let figure = {...ori_figure}; figure.data = traces; return figure; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["f14be55984da1266fe5f898e53986abd85f025f85348fb5acb33d1d8b454a04b"] = function update_setpos_from_click(data, index, info) { if (data && data.points && data.points.length) { let point = data["points"][0]; let xyz = [point["x"], point["y"]]; let depth = info.offset[2] + index * info.stepsize[2]; xyz.splice(2 - info.axis, 0, depth); return xyz; } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e4d1e647de5956da1ab7b3802a76f21aaf4ac93984e55465aad63ae7b52addae"] = function update_slider_value(positions, cur_index, info) { for (let trigger of dash_clientside.callback_context.triggered) { if (!trigger.value) continue; let pos = trigger.value[2 - info.axis]; if (typeof pos !== 'number') continue; let index = Math.round((pos - info.offset[2]) / info.stepsize[2]); if (index == cur_index) continue; return Math.max(0, Math.min(info.size[2] - 1, index)); } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["19f2edf701f8491ff2dc5feb950e36b929bfe7b61986f90a10df0542fb51b4c4"] = function update_rate_limiting_info(index, relayoutData, n_intervals) { if (!window._slicer_slicer6) window._slicer_slicer6 = {}; let private_state = window._slicer_slicer6; let now = window.performance.now(); // Get whether the slider was moved, layout was changed, or timer ticked let slider_value_changed = false; let graph_layout_changed = false; let timer_ticked = false; for (let trigger of dash_clientside.callback_context.triggered) { if (trigger.prop_id.indexOf('slider') >= 0) slider_value_changed = true; if (trigger.prop_id.indexOf('timer') >= 0) timer_ticked = true; if (trigger.prop_id.indexOf('graph') >= 0) { for (let key in relayoutData) { if (key.startsWith("xaxis.range") || key.startsWith("yaxis.range")) { graph_layout_changed = true; } } } } // Set timeout and whether to disable the timer let disable_timer = false; if (slider_value_changed) { private_state.timeout = now + 200; } else if (graph_layout_changed) { private_state.timeout = now + 400; // need longer timeout for smooth scroll zoom } else if (!n_intervals) { private_state.timeout = now + 100; // initialize } else if (!private_state.timeout) { disable_timer = true; } return disable_timer; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["f08409d656da94ba5d85185b81f78f10957b38eff5f375c28a578b38be26165e"] = function update_state(n_intervals, index, info, figure) { if (!window._slicer_slicer6) window._slicer_slicer6 = {}; let private_state = window._slicer_slicer6; let now = window.performance.now(); // Ready to apply and stop the timer, or return early? if (!(private_state.timeout && now >= private_state.timeout)) { return dash_clientside.no_update; } // Give the plot time to settle the initial axis ranges if (n_intervals < 5) { return dash_clientside.no_update; } // Disable the timer private_state.timeout = 0; // Calculate view range based on the volume let xrangeVol = [ info.offset[0] - 0.5 * info.stepsize[0], info.offset[0] + (info.size[0] - 0.5) * info.stepsize[0] ]; let yrangeVol = [ info.offset[1] - 0.5 * info.stepsize[1], info.offset[1] + (info.size[1] - 0.5) * info.stepsize[1] ]; // Get view range from the figure. We make range[0] < range[1] let xrangeFig = figure.layout.xaxis.range let yrangeFig = figure.layout.yaxis.range; xrangeFig = [Math.min(xrangeFig[0], xrangeFig[1]), Math.max(xrangeFig[0], xrangeFig[1])]; yrangeFig = [Math.min(yrangeFig[0], yrangeFig[1]), Math.max(yrangeFig[0], yrangeFig[1])]; // Add offset to avoid the corner-indicators for THIS slicer to only be half-visible let plotSize = [400, 400]; // This estimate results in ok results let graphDiv = document.getElementById('slicer6-graph'); let plotDiv = graphDiv.getElementsByClassName('js-plotly-plot')[0]; if (plotDiv && plotDiv._fullLayout) plotSize = [plotDiv._fullLayout.width, plotDiv._fullLayout.height]; xrangeFig[0] += 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; xrangeFig[1] -= 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; yrangeFig[0] += 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; yrangeFig[1] -= 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; // Combine the ranges let xrange = [Math.max(xrangeVol[0], xrangeFig[0]), Math.min(xrangeVol[1], xrangeFig[1])]; let yrange = [Math.max(yrangeVol[0], yrangeFig[0]), Math.min(yrangeVol[1], yrangeFig[1])]; // Create new state let new_state = { index: index, index_changed: false, xrange: xrange, yrange: yrange, zpos: info.offset[2] + index * info.stepsize[2], axis: info.axis, color: info.color, }; if (index != private_state.last_index || info.infoid != private_state.infoid) { private_state.last_index = index; new_state.index_changed = true; } private_state.infoid = info.infoid; // infoid changes on hot reload return new_state; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["280a79c61b994d44eda071bb0fff25c8f8881932997e8e3389ea3b02d5f84369"] = function update_image_traces(index, server_data, overlays, thumbnails, info, current_traces) { // Prepare traces let slice_trace = { type: 'image', x0: info.offset[0], y0: info.offset[1], dx: info.stepsize[0], dy: info.stepsize[1], hovertemplate: '(%{x:.2f}, %{y:.2f})<extra></extra>' }; let overlay_trace = {...slice_trace}; overlay_trace.hoverinfo = 'skip'; overlay_trace.source = overlays[index] || ''; overlay_trace.hovertemplate = ''; let new_traces = [slice_trace, overlay_trace]; // Use full data, or use thumbnails if (index == server_data.index) { slice_trace.source = server_data.slice; } else { slice_trace.source = thumbnails[index]; // Scale the image to take the exact same space as the full-res // version. Note that depending on how the low-res data is // created, the pixel centers may not be correctly aligned. slice_trace.dx *= info.size[0] / info.thumbnail_size[0]; slice_trace.dy *= info.size[1] / info.thumbnail_size[1]; slice_trace.x0 += 0.5 * slice_trace.dx - 0.5 * info.stepsize[0]; slice_trace.y0 += 0.5 * slice_trace.dy - 0.5 * info.stepsize[1]; } // Has the image data even changed? if (!current_traces.length) { current_traces = [{source:''}, {source:''}]; } if (new_traces[0].source == current_traces[0].source && new_traces[1].source == current_traces[1].source) { new_traces = dash_clientside.no_update; } return new_traces; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e8d2161e56a5d0a34e8bc130bcdbf21a309e3418cb2b6025569415bc563e7c91"] = function update_indicator_traces(states, info, thisState) { let traces = []; for (let state of states) { if (!state) continue; let zpos = [state.zpos, state.zpos]; let trace = null; if (info.axis == 0 && state.axis == 1) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 0 && state.axis == 2) { trace = {x: zpos, y: state.xrange}; } else if (info.axis == 1 && state.axis == 2) { trace = {x: zpos, y: state.yrange}; } else if (info.axis == 1 && state.axis == 0) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 2 && state.axis == 0) { trace = {x: state.yrange, y: zpos}; } else if (info.axis == 2 && state.axis == 1) { trace = {x: zpos, y: state.yrange}; } if (trace) { trace.line = {color: state.color, width: 1}; traces.push(trace); } } // Show our own color around the image, but only if there are other // slicers with the same scene id, on a different axis. We do some // math to make sure that these indicators are the same size (in // scene coordinates) for all slicers of the same data. if (thisState && info.color && traces.length) { let fraction = 0.1; let lengthx = info.size[0] * info.stepsize[0]; let lengthy = info.size[1] * info.stepsize[1]; let lengthz = info.size[2] * info.stepsize[2]; let dd = fraction * (lengthx + lengthy + lengthz) / 3; // average dd = Math.min(dd, 0.45 * Math.min(lengthx, lengthy, lengthz)); // failsafe let x1 = thisState.xrange[0]; let x2 = thisState.xrange[0] + dd; let x3 = thisState.xrange[1] - dd; let x4 = thisState.xrange[1]; let y1 = thisState.yrange[0]; let y2 = thisState.yrange[0] + dd; let y3 = thisState.yrange[1] - dd; let y4 = thisState.yrange[1]; traces.push({ x: [x1, x1, x2, null, x3, x4, x4, null, x4, x4, x3, null, x2, x1, x1], y: [y2, y1, y1, null, y1, y1, y2, null, y3, y4, y4, null, y4, y4, y3], line: {color: info.color, width: 4} }); } // Post-process the traces we created above for (let trace of traces) { trace.type = 'scatter'; trace.mode = 'lines'; trace.hoverinfo = 'skip'; trace.showlegend = false; } if (thisState) { return traces; } else { return dash_clientside.no_update; } } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["4f84255f8d1e848137904d58e835a8de8e5a9457ce7c3833e597b5b495f4f5d9"] = function update_figure(img_traces, indicator_traces, extra_traces, info, ori_figure) { // Collect traces let traces = []; for (let trace of img_traces) { traces.push(trace); } for (let trace of extra_traces) { traces.push(trace); } for (let trace of indicator_traces) { if (trace.line.color) traces.push(trace); } // Update figure let figure = {...ori_figure}; figure.data = traces; return figure; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["f14be55984da1266fe5f898e53986abd85f025f85348fb5acb33d1d8b454a04b"] = function update_setpos_from_click(data, index, info) { if (data && data.points && data.points.length) { let point = data["points"][0]; let xyz = [point["x"], point["y"]]; let depth = info.offset[2] + index * info.stepsize[2]; xyz.splice(2 - info.axis, 0, depth); return xyz; } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e4d1e647de5956da1ab7b3802a76f21aaf4ac93984e55465aad63ae7b52addae"] = function update_slider_value(positions, cur_index, info) { for (let trigger of dash_clientside.callback_context.triggered) { if (!trigger.value) continue; let pos = trigger.value[2 - info.axis]; if (typeof pos !== 'number') continue; let index = Math.round((pos - info.offset[2]) / info.stepsize[2]); if (index == cur_index) continue; return Math.max(0, Math.min(info.size[2] - 1, index)); } return dash_clientside.no_update; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["a32e2596a7fa7301f6ff4c011e4d28409fa5630e50299d6a3cf278575b42c8e2"] = function update_rate_limiting_info(index, relayoutData, n_intervals) { if (!window._slicer_slicer7) window._slicer_slicer7 = {}; let private_state = window._slicer_slicer7; let now = window.performance.now(); // Get whether the slider was moved, layout was changed, or timer ticked let slider_value_changed = false; let graph_layout_changed = false; let timer_ticked = false; for (let trigger of dash_clientside.callback_context.triggered) { if (trigger.prop_id.indexOf('slider') >= 0) slider_value_changed = true; if (trigger.prop_id.indexOf('timer') >= 0) timer_ticked = true; if (trigger.prop_id.indexOf('graph') >= 0) { for (let key in relayoutData) { if (key.startsWith("xaxis.range") || key.startsWith("yaxis.range")) { graph_layout_changed = true; } } } } // Set timeout and whether to disable the timer let disable_timer = false; if (slider_value_changed) { private_state.timeout = now + 200; } else if (graph_layout_changed) { private_state.timeout = now + 400; // need longer timeout for smooth scroll zoom } else if (!n_intervals) { private_state.timeout = now + 100; // initialize } else if (!private_state.timeout) { disable_timer = true; } return disable_timer; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["8a4b24b6271800153d3496e1b012557287b6d5aba4de636b3fc7fe6e5ce094e2"] = function update_state(n_intervals, index, info, figure) { if (!window._slicer_slicer7) window._slicer_slicer7 = {}; let private_state = window._slicer_slicer7; let now = window.performance.now(); // Ready to apply and stop the timer, or return early? if (!(private_state.timeout && now >= private_state.timeout)) { return dash_clientside.no_update; } // Give the plot time to settle the initial axis ranges if (n_intervals < 5) { return dash_clientside.no_update; } // Disable the timer private_state.timeout = 0; // Calculate view range based on the volume let xrangeVol = [ info.offset[0] - 0.5 * info.stepsize[0], info.offset[0] + (info.size[0] - 0.5) * info.stepsize[0] ]; let yrangeVol = [ info.offset[1] - 0.5 * info.stepsize[1], info.offset[1] + (info.size[1] - 0.5) * info.stepsize[1] ]; // Get view range from the figure. We make range[0] < range[1] let xrangeFig = figure.layout.xaxis.range let yrangeFig = figure.layout.yaxis.range; xrangeFig = [Math.min(xrangeFig[0], xrangeFig[1]), Math.max(xrangeFig[0], xrangeFig[1])]; yrangeFig = [Math.min(yrangeFig[0], yrangeFig[1]), Math.max(yrangeFig[0], yrangeFig[1])]; // Add offset to avoid the corner-indicators for THIS slicer to only be half-visible let plotSize = [400, 400]; // This estimate results in ok results let graphDiv = document.getElementById('slicer7-graph'); let plotDiv = graphDiv.getElementsByClassName('js-plotly-plot')[0]; if (plotDiv && plotDiv._fullLayout) plotSize = [plotDiv._fullLayout.width, plotDiv._fullLayout.height]; xrangeFig[0] += 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; xrangeFig[1] -= 2 * (xrangeFig[1] - xrangeFig[0]) / plotSize[0]; yrangeFig[0] += 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; yrangeFig[1] -= 2 * (yrangeFig[1] - yrangeFig[0]) / plotSize[1]; // Combine the ranges let xrange = [Math.max(xrangeVol[0], xrangeFig[0]), Math.min(xrangeVol[1], xrangeFig[1])]; let yrange = [Math.max(yrangeVol[0], yrangeFig[0]), Math.min(yrangeVol[1], yrangeFig[1])]; // Create new state let new_state = { index: index, index_changed: false, xrange: xrange, yrange: yrange, zpos: info.offset[2] + index * info.stepsize[2], axis: info.axis, color: info.color, }; if (index != private_state.last_index || info.infoid != private_state.infoid) { private_state.last_index = index; new_state.index_changed = true; } private_state.infoid = info.infoid; // infoid changes on hot reload return new_state; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["280a79c61b994d44eda071bb0fff25c8f8881932997e8e3389ea3b02d5f84369"] = function update_image_traces(index, server_data, overlays, thumbnails, info, current_traces) { // Prepare traces let slice_trace = { type: 'image', x0: info.offset[0], y0: info.offset[1], dx: info.stepsize[0], dy: info.stepsize[1], hovertemplate: '(%{x:.2f}, %{y:.2f})<extra></extra>' }; let overlay_trace = {...slice_trace}; overlay_trace.hoverinfo = 'skip'; overlay_trace.source = overlays[index] || ''; overlay_trace.hovertemplate = ''; let new_traces = [slice_trace, overlay_trace]; // Use full data, or use thumbnails if (index == server_data.index) { slice_trace.source = server_data.slice; } else { slice_trace.source = thumbnails[index]; // Scale the image to take the exact same space as the full-res // version. Note that depending on how the low-res data is // created, the pixel centers may not be correctly aligned. slice_trace.dx *= info.size[0] / info.thumbnail_size[0]; slice_trace.dy *= info.size[1] / info.thumbnail_size[1]; slice_trace.x0 += 0.5 * slice_trace.dx - 0.5 * info.stepsize[0]; slice_trace.y0 += 0.5 * slice_trace.dy - 0.5 * info.stepsize[1]; } // Has the image data even changed? if (!current_traces.length) { current_traces = [{source:''}, {source:''}]; } if (new_traces[0].source == current_traces[0].source && new_traces[1].source == current_traces[1].source) { new_traces = dash_clientside.no_update; } return new_traces; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e8d2161e56a5d0a34e8bc130bcdbf21a309e3418cb2b6025569415bc563e7c91"] = function update_indicator_traces(states, info, thisState) { let traces = []; for (let state of states) { if (!state) continue; let zpos = [state.zpos, state.zpos]; let trace = null; if (info.axis == 0 && state.axis == 1) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 0 && state.axis == 2) { trace = {x: zpos, y: state.xrange}; } else if (info.axis == 1 && state.axis == 2) { trace = {x: zpos, y: state.yrange}; } else if (info.axis == 1 && state.axis == 0) { trace = {x: state.xrange, y: zpos}; } else if (info.axis == 2 && state.axis == 0) { trace = {x: state.yrange, y: zpos}; } else if (info.axis == 2 && state.axis == 1) { trace = {x: zpos, y: state.yrange}; } if (trace) { trace.line = {color: state.color, width: 1}; traces.push(trace); } } // Show our own color around the image, but only if there are other // slicers with the same scene id, on a different axis. We do some // math to make sure that these indicators are the same size (in // scene coordinates) for all slicers of the same data. if (thisState && info.color && traces.length) { let fraction = 0.1; let lengthx = info.size[0] * info.stepsize[0]; let lengthy = info.size[1] * info.stepsize[1]; let lengthz = info.size[2] * info.stepsize[2]; let dd = fraction * (lengthx + lengthy + lengthz) / 3; // average dd = Math.min(dd, 0.45 * Math.min(lengthx, lengthy, lengthz)); // failsafe let x1 = thisState.xrange[0]; let x2 = thisState.xrange[0] + dd; let x3 = thisState.xrange[1] - dd; let x4 = thisState.xrange[1]; let y1 = thisState.yrange[0]; let y2 = thisState.yrange[0] + dd; let y3 = thisState.yrange[1] - dd; let y4 = thisState.yrange[1]; traces.push({ x: [x1, x1, x2, null, x3, x4, x4, null, x4, x4, x3, null, x2, x1, x1], y: [y2, y1, y1, null, y1, y1, y2, null, y3, y4, y4, null, y4, y4, y3], line: {color: info.color, width: 4} }); } // Post-process the traces we created above for (let trace of traces) { trace.type = 'scatter'; trace.mode = 'lines'; trace.hoverinfo = 'skip'; trace.showlegend = false; } if (thisState) { return traces; } else { return dash_clientside.no_update; } } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["4f84255f8d1e848137904d58e835a8de8e5a9457ce7c3833e597b5b495f4f5d9"] = function update_figure(img_traces, indicator_traces, extra_traces, info, ori_figure) { // Collect traces let traces = []; for (let trace of img_traces) { traces.push(trace); } for (let trace of extra_traces) { traces.push(trace); } for (let trace of indicator_traces) { if (trace.line.color) traces.push(trace); } // Update figure let figure = {...ori_figure}; figure.data = traces; return figure; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["fc976e3b81c06c46f9fa8c7e2f41f70fc8763587e0eea6fa6a9e06ac17931742"] = function(title, path, params, hash, refreshPage) { // trigger a pagemenu rerender and set the document title window.history.replaceState(null, null, path + params + hash); if (title) { document.title = title; } return ["", path, refreshPage]; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["737d4f9ccaa4fcfb4ff5f88585fe430b92cb9824fde4d834a87690af15d6478b"] = function(refreshPage) { if (refreshPage===true) { window.location.reload(); } return ""; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["d47d11591f64cc0536c7079a63dd9b2d097118ed962f5ad5a366ec5aaade92db"] = function(x) {return x}; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["d47d11591f64cc0536c7079a63dd9b2d097118ed962f5ad5a366ec5aaade92db"] = function(x) {return x}; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["d47d11591f64cc0536c7079a63dd9b2d097118ed962f5ad5a366ec5aaade92db"] = function(x) {return x}; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["3b87e7ea0a54697b84e2838b3ccf0a3ae2460cd236c5b482ca68d41bded2240b"] = function(data, scale) { return { 'data': data, 'layout': { 'yaxis': {'type': scale} } } } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["f4f0cd36bb54318092c4b9fa3b0fa966873777ffcf4c46e97ddf56c86e749487"] = function(figure, scale) { if(figure === undefined) { return {'data': [], 'layout': {}}; } const fig = Object.assign({}, figure, { 'layout': { ...figure.layout, 'yaxis': { ...figure.layout.yaxis, type: scale } } }); return fig; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["18eaf07bff6d0de1db46741289c67822cb8251e2eccffe8ed172f9848f28207c"] = async function(value) { const response = await fetch(value); const data = await response.json(); return data; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["e835da3fb0bc7a5c356464405f9f057074f1d4a072fbfd679318a47da93f0e07"] = function show_tooltip(hoverData) { if(!hoverData) { return [false, dash_clientside.no_update]; } var pt = hoverData.points[0]; return [true, pt.bbox]; } ; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["ca793bf738081d9de2e85fd6f8bafbb9e25a49585b0bc5ec28983f5aee6a9e40"] = async function (changedCell, forceRefresh) { gridApi = await dash_ag_grid.getApiAsync('styling-cells-other-col') forceRefresh.length != 0 && gridApi.refreshCells({force: true, columns: ['employee']}) return window.dash_clientside.no_update }; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["0364d7b663010e98e3f4c21ccf1b8310069f997bd9cb5f26dcdc8f0e91e51ae8"] = async (n) => { if (n) { const gridApi = await dash_ag_grid.getApiAsync("grid-flash-cells-custom") var rowCount = gridApi.getDisplayedRowCount(); // pick 20 cells at random to update for (var i = 0; i < 20; i++) { var row = Math.floor(Math.random() * rowCount); var rowNode = gridApi.getDisplayedRowAtIndex(row); var col = ['a', 'b', 'c', 'd', 'e', 'f'][i % 6]; rowNode.setDataValue(col, Math.floor(Math.random() * 10000)); } } return dash_clientside.no_update }; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["eaa5f2b260fecd837b412ac81b0a52d7d65cc761ab4d0cfef7f090848eb1d18a"] = async (n) => { if (n) { const gridApi = await dash_ag_grid.getApiAsync("grid-flash-cells-custom") // pick row 4 and 5 var rowNode1 = gridApi.getDisplayedRowAtIndex(4); var rowNode2 = gridApi.getDisplayedRowAtIndex(5); // flash whole row, so leave column selection out gridApi.flashCells({ rowNodes: [rowNode1, rowNode2], flashDuration: 3000, fadeDuration: 2000, }); } return dash_clientside.no_update }; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["2a5a740d1314d12016864e13bb871c2b68e5c83a407f893467fc7e93f63ea827"] = async (n) => { if (n) { const gridApi = await dash_ag_grid.getApiAsync("grid-flash-cells") var rowCount = gridApi.getDisplayedRowCount(); // pick 20 cells at random to update for (var i = 0; i < 20; i++) { var row = Math.floor(Math.random() * rowCount); var rowNode = gridApi.getDisplayedRowAtIndex(row); var col = ['a', 'b', 'c', 'd', 'e', 'f'][i % 6]; rowNode.setDataValue(col, Math.floor(Math.random() * 10000)); } } return dash_clientside.no_update }; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["532d86dc9909f47a550f38ae0f52bbdb8d440ef88b2c2d66a5893fc2f2a8b78f"] = async (n) => { if (n) { const gridApi = await dash_ag_grid.getApiAsync("grid-flash-cells") // flash row 4 col 'c' var rowNode = gridApi.getDisplayedRowAtIndex(4); gridApi.flashCells({ rowNodes: [rowNode], columns: ['c'] }); } return dash_clientside.no_update }; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["c801b5f91fea945fe19263bc62c3934f993433a09de833ee0a5ccc1d8979cd25"] = async (n) => { if (n) { const gridApi = await dash_ag_grid.getApiAsync("grid-flash-cells") // pick row 4 and 5 var rowNode1 = gridApi.getDisplayedRowAtIndex(4); var rowNode2 = gridApi.getDisplayedRowAtIndex(5); // flash whole row, so leave column selection out gridApi.flashCells({ rowNodes: [rowNode1, rowNode2] }); } return dash_clientside.no_update }; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["fb31606c398a49bfc46b5ebedc12f46cdbf059ac6118645b4758cb8534fbf117"] = async (n) => { if (n) { const gridApi = await dash_ag_grid.getApiAsync("grid-flash-cells"); gridApi.flashCells({ columns: ['c', 'd'] }); } return dash_clientside.no_update; }; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["d1b7448a7693c9d89d259fb2fa5f005c0f9a67054cab16421ca6f9c75995b191"] = function (rowId) { if (rowId) { grid = dash_ag_grid.getApi("grid-scroll-to-pagination") rowIndex = grid.getRowNode(rowId).rowIndex pageTarget = Math.floor(rowIndex / grid.paginationGetPageSize()) grid.paginationGoToPage(pageTarget) } return {"rowId": rowId.toString()} }; })(); </script> <script> (function() { var clientside = window.dash_clientside = window.dash_clientside || {}; var ns = clientside["_dashprivate_clientside_funcs"] = clientside["_dashprivate_clientside_funcs"] || {}; ns["02901b6011bc7cd27565dc26a63b94319df594ddf9a5c0c38512bb5a4e78654f"] = function (rowId) { if (rowId) { grid = dash_ag_grid.getApi("grid-scroll-to-group") grid.setRowNodeExpanded(grid.getRowNode(rowId), true, true) } return {"rowId": rowId.toString()} }; })(); </script> <script id="_dash-renderer" type="application/javascript">var renderer = new DashRenderer();</script> </footer> <div id="markprompt" /> <script type="module"> // References URL link formatter const getHref = (result) => { var path = result.file.path; // If the source is not plotly.com/python, then it should be a relative path if (!path.startsWith("https://plotly.com/python")) { var urlObject = new URL(path); path = urlObject.pathname; } if (result && result.meta && result.meta.leadHeading && result.meta.leadHeading.id) { path = (path + "#" + result.meta.leadHeading.id); } if (result && result.meta && result.meta.leadHeading && result.meta.leadHeading.value) { path = (path + "#" + result.meta.leadHeading.slug); } return path; }; const getLabel = (reference) => { var label = reference.meta?.leadHeading?.value || reference.file?.title; label = label.replace(/[^\x00-\x7F]/g, ""); while (label.includes("plotly-logomark")) { label = label.replace("plotly-logomark", ""); } return label; }; const setCookie = (name, value, days) => { const expires = new Date(); expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000); document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`; }; const getCookie = (name) => { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.startsWith(name + '=')) { return cookie.substring(name.length + 1); } } return null; }; const getUniqueID = () => { const storedID = getCookie("plotly-chatbot-cookie"); if (storedID) { return storedID; } else { const newID = generateUniqueID(); setCookie("plotly-chatbot-cookie", newID, 365); return newID; } }; const generateUniqueID = () => { return Date.now().toString(); }; window.markprompt = { projectKey: 'pk_0upevf7bcscej8JQMALYiqmXoWQkltw3', container: '#markprompt', options: { sticky: true, close: { hasIcon: true }, chat: { systemPrompt: "- You are an enthusiastic company representative from Plotly who loves to help people!\ - Never give code examples which are not provided in the docs, and don't give code examples in other languages than Python.", defaultView: { message: "Welcome to Plotly's AI Assistant", promptsHeading: 'Popular questions', prompts: [ 'How can I get started with Dash?', 'How can I customize the layout in Dash?', 'How can I change the color of graph labels?', 'How do I move the legend to the top of the graph?', ], }, conversationMetadata: { "userid": getUniqueID(), "source": "dash-docs", }, enabled: true, model: 'gpt-3.5-turbo', maxTokens: 2000, errorText: "Sorry, I'm having some connection issues. Please try again in a few minutes.", }, search: { enabled: false, getHref: getHref }, references: { heading: 'References', getHref: getHref, getLabel: getLabel }, feedback: { enabled: true }, trigger: { buttonLabel: 'Ask AI', iconSrc: '/assets/markprompt_chat.svg' }, branding: { type: 'text' } } } </script> <script type="module" src="https://esm.sh/@markprompt/web@0.24.0/init"></script> </body></html>