From 83c453d1f3b0c69321958b03134128cda5b3eb42 Mon Sep 17 00:00:00 2001 From: Alireza Date: Tue, 20 Jun 2023 10:26:05 -0400 Subject: [PATCH] chore(version): update cs3d version and add iframe documentation (#3474) --- .webpack/webpack.base.js | 9 - extensions/cornerstone-dicom-sr/package.json | 6 +- extensions/cornerstone/package.json | 10 +- extensions/measurement-tracking/package.json | 4 +- package.json | 2 +- platform/app/netlify.toml | 2 + platform/app/package.json | 2 +- platform/core/package.json | 2 +- .../docs/docs/assets/img/iframe-basic.png | Bin 0 -> 145099 bytes .../docs/docs/assets/img/iframe-headers.png | Bin 0 -> 219238 bytes .../docs/docs/deployment/authorization.md | 2 +- .../docs/deployment/build-for-production.md | 8 +- .../deployment/google-cloud-healthcare.md | 7 - platform/docs/docs/deployment/iframe.md | 163 +++++++ platform/docs/docs/deployment/index.md | 33 +- .../docs/deployment/user-account-control.md | 7 - platform/docs/docs/migration-guide.md | 2 +- .../docs/platform/environment-variables.md | 2 +- platform/docs/docusaurus.config.js | 56 ++- platform/docs/src/css/custom.css | 13 + platform/docs/src/pages/versions.md | 46 +- .../I-want-to/_category_.json | 0 .../I-want-to/add-a-logo-to-the-viewer.md | 0 .../I-want-to/add-a-tool-to-the-viewer.md | 0 .../Standalone-Installation-Instructions.md | 0 .../OHIF-Viewer/_category_.json | 0 .../OHIF-Viewer/environment-installations.md | 0 .../OHIF-Viewer/usage.md | 0 .../README.md | 0 .../LesionTracker/LT_Assessment_Progress.png | Bin .../LesionTracker/LT_Association_Dialog.png | Bin .../img/LesionTracker/LT_Audit_Trails.png | Bin .../assets/img/LesionTracker/LT_CINE.png | Bin .../img/LesionTracker/LT_Change_Password.png | Bin .../img/LesionTracker/LT_CompareMode.png | Bin .../img/LesionTracker/LT_Comparison.png | Bin .../LesionTracker/LT_Configuration_Menu.png | Bin .../LesionTracker/LT_Conformance_Check.png | Bin .../assets/img/LesionTracker/LT_Download.png | Bin .../assets/img/LesionTracker/LT_Ellipse.png | Bin .../assets/img/LesionTracker/LT_FlipH.png | Bin .../assets/img/LesionTracker/LT_FlipV.png | Bin .../img/LesionTracker/LT_Forgot_Password.png | Bin .../img/LesionTracker/LT_Generate_Report.png | Bin .../assets/img/LesionTracker/LT_HUD_Panel.png | Bin .../img/LesionTracker/LT_Image_Viewer.png | Bin .../LT_Installer_After_Prerequisites.png | Bin .../LT_Installer_Desktop_Shortcuts.png | Bin .../img/LesionTracker/LT_Installer_Final.png | Bin .../img/LesionTracker/LT_Installer_Finish.png | Bin .../LesionTracker/LT_Installer_Initial.png | Bin .../LT_Installer_Launch_Installation.png | Bin .../LT_Installer_Launch_Uninstall.png | Bin .../LT_Installer_License_Aggrement.png | Bin .../LT_Installer_Prerequisites.png | Bin .../LT_Installer_Select_Location.png | Bin .../LesionTracker/LT_Installer_Services.png | Bin .../LesionTracker/LT_Installer_Successful.png | Bin .../LesionTracker/LT_Installer_Uninstall.png | Bin .../assets/img/LesionTracker/LT_Invert.png | Bin .../img/LesionTracker/LT_Key_Timepoints.png | Bin .../LesionTracker/LT_Keyboard_Shortcuts.png | Bin .../assets/img/LesionTracker/LT_Login.png | Bin .../assets/img/LesionTracker/LT_Logout.png | Bin .../assets/img/LesionTracker/LT_Magnify.png | Bin .../img/LesionTracker/LT_Measurements.png | Bin .../img/LesionTracker/LT_Need_Account.png | Bin .../LT_NonTarget_Select_Location.png | Bin .../img/LesionTracker/LT_NonTarget_Tool.png | Bin .../LT_Orthanc_Delete_Select_Patient.png | Bin .../LT_Orthanc_Delete_Select_Study.png | Bin .../LesionTracker/LT_Orthanc_Delete_Study.png | Bin .../LT_Orthanc_Drag_and_Drop.png | Bin .../LesionTracker/LT_Orthanc_Start_Upload.png | Bin .../img/LesionTracker/LT_Orthanc_Upload.png | Bin .../LT_Orthanc_Upload_Result.png | Bin .../assets/img/LesionTracker/LT_Pan.png | Bin .../LesionTracker/LT_Quick_Switch_Tool.png | Bin .../img/LesionTracker/LT_Remove_Associate.png | Bin .../img/LesionTracker/LT_Report_PDF.png | Bin .../assets/img/LesionTracker/LT_Reset.png | Bin .../LesionTracker/LT_Response_Criteria.png | Bin .../img/LesionTracker/LT_Rotate_Right.png | Bin .../assets/img/LesionTracker/LT_Save1.png | Bin .../assets/img/LesionTracker/LT_Save2.png | Bin .../assets/img/LesionTracker/LT_Scroll.png | Bin .../img/LesionTracker/LT_Select_Associate.png | Bin .../img/LesionTracker/LT_Server_Info.png | Bin .../LesionTracker/LT_StackScroll_Multiple.png | Bin .../LesionTracker/LT_StackScroll_Single.png | Bin .../img/LesionTracker/LT_Studies_Panel.png | Bin .../assets/img/LesionTracker/LT_StudyList.png | Bin .../assets/img/LesionTracker/LT_Target.png | Bin .../assets/img/LesionTracker/LT_Target_CR.png | Bin .../img/LesionTracker/LT_Target_Delete.png | Bin .../img/LesionTracker/LT_Target_Label.png | Bin .../img/LesionTracker/LT_Target_Rename.png | Bin .../assets/img/LesionTracker/LT_Target_UN.png | Bin .../assets/img/LesionTracker/LT_Temp_Tool.png | Bin .../assets/img/LesionTracker/LT_Themes.png | Bin .../img/LesionTracker/LT_View_Lesion.png | Bin .../LesionTracker/LT_View_Series_Details.png | Bin .../img/LesionTracker/LT_View_Study.png | Bin .../assets/img/LesionTracker/LT_Viewer.png | Bin .../assets/img/LesionTracker/LT_WL.png | Bin .../img/LesionTracker/LT_WL_Presets.png | Bin .../assets/img/LesionTracker/LT_Zoom.png | Bin .../assets/img/lesionTracker.png | Bin .../assets/img/viewer.png | Bin .../assets/img/worklist.png | Bin .../_category_.json | 0 .../dcm4chee-with-docker.md | 0 .../connecting-to-image-archives/dicomweb.md | 0 .../connecting-to-image-archives/dimse.md | 0 .../google-cloud-healthcare.md | 0 .../connecting-to-image-archives/options.md | 0 .../orthanc-with-docker.md | 0 .../contributing.md | 0 .../data/_category_.json | 0 .../data/data-hierarchy.md | 0 .../data/image-viewport.md | 0 .../data/measurements-and-annotations.md | 0 .../data/tool-management.md | 0 .../deployment/_category_.json | 0 .../deployment/building-for-production.md | 0 .../deployment/security.md | 0 .../essentials/_category_.json | 0 .../essentials/architecture.md | 0 .../essentials/configuration.md | 0 .../essentials/installation.md | 0 .../essentials/meteor-packages.md | 0 .../essentials/troubleshooting.md | 0 .../example-applications/_category_.json | 0 .../example-applications/lesion-tracker.md | 0 .../example-applications/ohif-viewer.md | 0 .../example-applications/standalone-viewer.md | 0 .../faq/_category_.json | 0 .../faq/general.md | 0 .../faq/technical.md | 0 .../layout/_category_.json | 0 .../layout/hanging-protocols.md | 0 .../layout/layout-management.md | 0 .../lesion-tracker/_category_.json | 0 .../lesion-tracker/audit-trail.md | 0 .../lesion-tracker/installation-on-windows.md | 0 .../manage-studies-in-orthanc.md | 0 .../lesion-tracker/server-management.md | 0 .../study-and-timepoint-management.md | 0 .../lesion-tracker/user-accounts.md | 0 .../lesion-tracker/user-preferences.md | 0 .../lesion-tracker/using-the-viewer.md | 0 .../packages/_category_.json | 0 .../packages/measurements.md | 0 .../Architecture.md | 0 .../README.md | 0 .../assets/designs/architecture-diagram | Bin .../assets/designs/canny-full.fig | Bin .../assets/designs/cloud.svg | 0 .../assets/designs/embedded-viewer-diagram | Bin .../assets/designs/nginx-image-archive.fig | Bin .../assets/designs/npm-logo-red.svg | 0 .../assets/designs/scope-of-project.fig | Bin .../user-access-control-request-flow.fig | Bin .../assets/img/WORKFLOW_DEPLOY.png | Bin .../assets/img/WORKFLOW_PR_CHECKS.png | Bin .../WORKFLOW_PR_OPTIONAL_DOCKER_PUBLISH.png | Bin .../assets/img/WORKFLOW_RELEASE.png | Bin .../assets/img/architecture-diagram.png | Bin .../assets/img/cornerstone-tools-link.gif | Bin .../assets/img/dialog-example.gif | Bin .../assets/img/embedded-viewer-diagram.png | Bin .../assets/img/extensions-diagram.png | Bin .../assets/img/extensions-panel.gif | Bin .../assets/img/extensions-toolbar-nested.gif | Bin .../assets/img/extensions-toolbar.gif | Bin .../assets/img/extensions-viewport.png | Bin .../assets/img/homePage.png | Bin .../assets/img/jwt-explained.png | Bin .../assets/img/keycloak-default-theme.png | Bin .../assets/img/keycloak-ohif-theme.png | Bin .../assets/img/lesionTracker.png | Bin .../assets/img/locizeSponsor.svg | 0 .../assets/img/modal-example.gif | Bin .../assets/img/netlify-drop.gif | Bin .../assets/img/nginx-image-archive.png | Bin .../assets/img/notification-example.gif | Bin .../assets/img/open-graph.png | Bin .../assets/img/scope-of-project.png | Bin .../assets/img/services.png | Bin .../assets/img/surge-deploy.gif | Bin .../assets/img/ui-services.png | Bin .../img/user-access-control-request-flow.png | Bin .../assets/img/viewer.png | Bin .../assets/img/worklist.png | Bin .../configuring/_category_.json | 0 .../configuring/data-source.md | 0 .../configuring/index.md | 0 .../deployment/_category_.json | 0 .../deployment/index.md | 0 .../deployment/recipes/_category_.json | 0 .../recipes/build-for-production.md | 0 .../deployment/recipes/embedded-viewer.md | 0 .../recipes/google-cloud-healthcare.md | 0 .../recipes/nginx--image-archive.md | 0 .../deployment/recipes/static-assets.md | 0 .../recipes/user-account-control.md | 0 .../development/_category_.json | 0 .../development/continous-integration.md | 0 .../development/contributing.md | 0 .../development/getting-started.md | 0 .../development/testing.md | 0 .../extensions/_category_.json | 0 .../extensions/index.md | 0 .../extensions/lifecycle/_category_.json | 0 .../extensions/lifecycle/pre-registration.md | 0 .../extensions/modules/_category_.json | 0 .../extensions/modules/commands.md | 0 .../extensions/modules/panel.md | 0 .../extensions/modules/sop-class-handler.md | 0 .../extensions/modules/toolbar.md | 0 .../extensions/modules/viewport.md | 0 .../faq/_category_.json | 0 .../faq/browser-support.md | 0 .../faq/index.md | 0 .../faq/pwa-vs-packaged.md | 0 .../faq/scope-of-project.md | 0 .../help.md | 0 .../our-process.md | 0 .../services/_category_.json | 0 .../services/default.md | 0 .../services/index.md | 0 .../services/ui/_category_.json | 0 .../services/ui/index.md | 0 .../services/ui/ui-dialog-service.md | 0 .../services/ui/ui-modal-service.md | 0 .../services/ui/ui-notification-service.md | 0 .../viewer/_category_.json | 0 .../viewer/configuration.md | 0 .../viewer/environment-variables.md | 0 .../viewer/internationalization.md | 0 .../viewer/themeing.md | 0 .../docs/versioned_docs/version-3.0/README.md | 97 ----- .../assets/designs/architecture-diagram | Bin 27048 -> 0 bytes .../version-3.0/assets/designs/canny-full.fig | Bin 3963 -> 0 bytes .../version-3.0/assets/designs/cloud.svg | 14 - .../assets/designs/embedded-viewer-diagram | Bin 29766 -> 0 bytes .../assets/designs/nginx-image-archive.fig | Bin 46026 -> 0 bytes .../assets/designs/npm-logo-red.svg | 9 - .../assets/designs/scope-of-project.fig | Bin 147332 -> 0 bytes .../user-access-control-request-flow.fig | Bin 56115 -> 0 bytes .../version-3.0/assets/img/OHIF-Viewer.png | Bin 507051 -> 0 bytes .../assets/img/OHIF-e2e-test-studies.png | Bin 106170 -> 0 bytes .../version-3.0/assets/img/SR-exported.png | Bin 17704 -> 0 bytes .../assets/img/WORKFLOW_DEPLOY.png | Bin 7987 -> 0 bytes .../assets/img/WORKFLOW_PR_CHECKS.png | Bin 5813 -> 0 bytes .../WORKFLOW_PR_OPTIONAL_DOCKER_PUBLISH.png | Bin 4778 -> 0 bytes .../assets/img/WORKFLOW_RELEASE.png | Bin 6307 -> 0 bytes .../version-3.0/assets/img/add-extension.png | Bin 96813 -> 0 bytes .../version-3.0/assets/img/add-mode.png | Bin 101457 -> 0 bytes .../assets/img/cli-search-no-verbose.png | Bin 72858 -> 0 bytes .../assets/img/cli-search-with-verbose.png | Bin 118526 -> 0 bytes .../version-3.0/assets/img/clock-mode.png | Bin 99242 -> 0 bytes .../version-3.0/assets/img/clock-mode1.png | Bin 432541 -> 0 bytes .../assets/img/cornerstone-tools-link.gif | Bin 432282 -> 0 bytes .../assets/img/create-extension.png | Bin 143075 -> 0 bytes .../version-3.0/assets/img/create-mode.png | Bin 163590 -> 0 bytes .../version-3.0/assets/img/custom-logo.png | Bin 5239 -> 0 bytes .../assets/img/dicom-json-public.png | Bin 26323 -> 0 bytes .../version-3.0/assets/img/dicom-json.png | Bin 661443 -> 0 bytes .../version-3.0/assets/img/docker-pacs.png | Bin 88403 -> 0 bytes .../assets/img/e2e-cypress-final.png | Bin 202521 -> 0 bytes .../version-3.0/assets/img/e2e-cypress.png | Bin 99477 -> 0 bytes .../assets/img/embedded-viewer-diagram.png | Bin 22910 -> 0 bytes .../version-3.0/assets/img/jwt-explained.png | Bin 173115 -> 0 bytes .../assets/img/keycloak-default-theme.png | Bin 42441 -> 0 bytes .../assets/img/keycloak-ohif-theme.png | Bin 905557 -> 0 bytes .../version-3.0/assets/img/locizeSponsor.svg | 187 --------- .../version-3.0/assets/img/locked-sr.png | Bin 29504 -> 0 bytes .../assets/img/measurement-panel-1.png | Bin 195491 -> 0 bytes .../assets/img/measurement-panel-prompt.png | Bin 398428 -> 0 bytes .../assets/img/measurement-panel-tracked.png | Bin 464095 -> 0 bytes .../assets/img/measurement-temporary.png | Bin 371702 -> 0 bytes .../assets/img/measurements-prevNext.png | Bin 42047 -> 0 bytes .../version-3.0/assets/img/mode-archs.png | Bin 200248 -> 0 bytes .../version-3.0/assets/img/mode-clock.png | Bin 89818 -> 0 bytes .../version-3.0/assets/img/mode-template.png | Bin 21528 -> 0 bytes .../assets/img/nginx-image-archive.png | Bin 27211 -> 0 bytes .../version-3.0/assets/img/ohif-cli-list.png | Bin 68430 -> 0 bytes .../version-3.0/assets/img/open-graph.png | Bin 21751 -> 0 bytes .../version-3.0/assets/img/overview.png | Bin 661194 -> 0 bytes .../assets/img/panel-module-left-right.png | Bin 59087 -> 0 bytes .../assets/img/panel-module-v3.png | Bin 121894 -> 0 bytes .../assets/img/panelmodule-icon.png | Bin 21084 -> 0 bytes .../assets/img/restore-exported-sr.png | Bin 11310 -> 0 bytes .../assets/img/scope-of-project.png | Bin 61023 -> 0 bytes .../version-3.0/assets/img/services-data.png | Bin 54573 -> 0 bytes .../assets/img/services-measurements.png | Bin 81196 -> 0 bytes .../version-3.0/assets/img/services-ui.png | Bin 60742 -> 0 bytes .../version-3.0/assets/img/services.png | Bin 21893 -> 0 bytes .../version-3.0/assets/img/surge-deploy.gif | Bin 380156 -> 0 bytes .../assets/img/template-extension-files.png | Bin 21288 -> 0 bytes .../assets/img/template-mode-files.png | Bin 18732 -> 0 bytes .../assets/img/template-mode-ui.png | Bin 204247 -> 0 bytes .../version-3.0/assets/img/toolbar-module.png | Bin 49855 -> 0 bytes .../assets/img/toolbarModule-layout.png | Bin 5649 -> 0 bytes .../img/toolbarModule-nested-buttons.png | Bin 14210 -> 0 bytes .../assets/img/toolbarModule-zoom.png | Bin 5876 -> 0 bytes .../assets/img/tracked-not-tracked.png | Bin 61027 -> 0 bytes .../assets/img/tracking-workflow1.png | Bin 751832 -> 0 bytes .../assets/img/tracking-workflow2.png | Bin 170448 -> 0 bytes .../assets/img/tracking-workflow3.png | Bin 308525 -> 0 bytes .../version-3.0/assets/img/ui-modal.gif | Bin 478634 -> 0 bytes .../version-3.0/assets/img/ui-services.png | Bin 26824 -> 0 bytes .../img/user-access-control-request-flow.png | Bin 40904 -> 0 bytes .../assets/img/user-hotkeys-default.png | Bin 92452 -> 0 bytes .../version-3.0/assets/img/user-hotkeys.png | Bin 10789 -> 0 bytes .../assets/img/user-measurement-export.png | Bin 58868 -> 0 bytes .../assets/img/user-open-viewer.png | Bin 110526 -> 0 bytes .../assets/img/user-study-filter.png | Bin 278720 -> 0 bytes .../assets/img/user-study-list.png | Bin 343458 -> 0 bytes .../assets/img/user-study-next.png | Bin 145963 -> 0 bytes .../assets/img/user-study-panel.png | Bin 383503 -> 0 bytes .../assets/img/user-study-summary.png | Bin 114773 -> 0 bytes .../assets/img/user-studyist-modespecific.png | Bin 207914 -> 0 bytes .../assets/img/user-toolbar-download-icon.png | Bin 36455 -> 0 bytes .../assets/img/user-toolbar-extra.png | Bin 42284 -> 0 bytes .../assets/img/user-toolbar-preset.png | Bin 67428 -> 0 bytes .../assets/img/user-toolbarDownload.png | Bin 200463 -> 0 bytes .../assets/img/user-viewer-layout.png | Bin 98322 -> 0 bytes .../assets/img/user-viewer-main.png | Bin 277510 -> 0 bytes .../img/user-viewer-toolbar-measurements.png | Bin 379934 -> 0 bytes .../assets/img/user-viewer-toolbar.png | Bin 201278 -> 0 bytes .../version-3.0/assets/img/user-viewer.png | Bin 468814 -> 0 bytes .../assets/img/viewportModule-layout.png | Bin 335313 -> 0 bytes .../version-3.0/assets/img/viewportModule.png | Bin 229972 -> 0 bytes .../version-3.0/configuration/_category_.json | 4 - .../configuration/configuration.md | 83 ---- .../configuration/dataSources/_category_.json | 4 - .../configuration/dataSources/dicom-json.md | 155 ------- .../configuration/dataSources/dicom-web.md | 191 --------- .../configuration/dataSources/static-files.md | 45 -- .../version-3.0/configuration/index.md | 168 -------- .../version-3.0/deployment/_category_.json | 4 - .../deployment/build-for-production.md | 132 ------ .../deployment/google-cloud-healthcare.md | 7 - .../version-3.0/deployment/index.md | 335 --------------- .../deployment/nginx--image-archive.md | 273 ------------ .../version-3.0/deployment/static-assets.md | 160 ------- .../deployment/user-account-control.md | 7 - .../version-3.0/development/_category_.json | 4 - .../version-3.0/development/architecture.md | 203 --------- .../development/continous-integration.md | 90 ---- .../version-3.0/development/contributing.md | 152 ------- .../development/getting-started.md | 111 ----- .../version-3.0/development/ohif-cli.md | 291 ------------- .../version-3.0/development/our-process.md | 156 ------- .../version-3.0/development/testing.md | 217 ---------- .../docs/versioned_docs/version-3.0/faq.md | 81 ---- .../version-3.0/platform/_category_.json | 4 - .../version-3.0/platform/browser-support.md | 50 --- .../platform/environment-variables.md | 27 -- .../platform/extensions/_category_.json | 4 - .../platform/extensions/extension.md | 55 --- .../version-3.0/platform/extensions/index.md | 325 -------------- .../platform/extensions/installation.md | 12 - .../platform/extensions/lifecycle.md | 128 ------ .../extensions/modules/_category_.json | 4 - .../platform/extensions/modules/commands.md | 121 ------ .../extensions/modules/contextModule.md | 30 -- .../extensions/modules/data-source.md | 106 ----- .../platform/extensions/modules/hpModule.md | 58 --- .../extensions/modules/layout-template.md | 139 ------ .../platform/extensions/modules/panel.md | 115 ----- .../extensions/modules/sop-class-handler.md | 108 ----- .../platform/extensions/modules/toolbar.md | 250 ----------- .../platform/extensions/modules/viewport.md | 96 ----- .../platform/internationalization.md | 396 ------------------ .../platform/managers/_category_.json | 4 - .../version-3.0/platform/managers/commands.md | 180 -------- .../platform/managers/extension.md | 55 --- .../version-3.0/platform/managers/hotkeys.md | 79 ---- .../version-3.0/platform/managers/index.md | 76 ---- .../version-3.0/platform/managers/service.md | 162 ------- .../platform/modes/_category_.json | 4 - .../version-3.0/platform/modes/index.md | 383 ----------------- .../platform/modes/installation.md | 12 - .../version-3.0/platform/modes/lifecycle.md | 86 ---- .../version-3.0/platform/modes/routes.md | 315 -------------- .../version-3.0/platform/modes/validity.md | 37 -- .../version-3.0/platform/pwa-vs-packaged.md | 34 -- .../version-3.0/platform/scope-of-project.md | 69 --- .../platform/services/_category_.json | 4 - .../services/data/DicomMetadataStore.md | 112 ----- .../services/data/DisplaySetService.md | 88 ---- .../services/data/HangingProtocolService.md | 348 --------------- .../services/data/MeasurementService.md | 161 ------- .../platform/services/data/ToolbarService.md | 226 ---------- .../platform/services/data/_category_.json | 4 - .../platform/services/data/index.md | 53 --- .../version-3.0/platform/services/index.md | 173 -------- .../version-3.0/platform/services/pubsub.md | 120 ------ .../platform/services/ui/_category_.json | 4 - .../platform/services/ui/cine-service.md | 8 - .../version-3.0/platform/services/ui/index.md | 304 -------------- .../platform/services/ui/ui-dialog-service.md | 48 --- .../platform/services/ui/ui-modal-service.md | 56 --- .../services/ui/ui-notification-service.md | 55 --- .../services/ui/ui-viewport-dialog-service.md | 65 --- .../services/ui/viewport-grid-service.md | 51 --- .../version-3.0/platform/themeing.md | 168 -------- .../version-3.0/release-notes.md | 141 ------- .../versioned_docs/version-3.0/resources.md | 101 ----- .../version-3.0/user-guide/_category_.json | 4 - .../version-3.0/user-guide/index.md | 83 ---- .../version-3.0/user-guide/viewer/Language.md | 22 - .../user-guide/viewer/_category_.json | 4 - .../version-3.0/user-guide/viewer/hotkeys.md | 15 - .../version-3.0/user-guide/viewer/index.md | 29 -- .../user-guide/viewer/measurement-panel.md | 74 ---- .../user-guide/viewer/measurement-tracking.md | 124 ------ .../user-guide/viewer/study-panel.md | 32 -- .../version-3.0/user-guide/viewer/toolbar.md | 85 ---- .../version-3.0/user-guide/viewer/viewport.md | 39 -- ...n => version-1.0-deprecated-sidebars.json} | 0 ...n => version-2.0-deprecated-sidebars.json} | 0 .../version-3.0-sidebars.json | 8 - platform/docs/versions.json | 2 +- yarn.lock | 46 +- 428 files changed, 271 insertions(+), 9666 deletions(-) create mode 100644 platform/docs/docs/assets/img/iframe-basic.png create mode 100644 platform/docs/docs/assets/img/iframe-headers.png delete mode 100644 platform/docs/docs/deployment/google-cloud-healthcare.md create mode 100644 platform/docs/docs/deployment/iframe.md delete mode 100644 platform/docs/docs/deployment/user-account-control.md rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/I-want-to/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/I-want-to/add-a-logo-to-the-viewer.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/I-want-to/add-a-tool-to-the-viewer.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/OHIF-Viewer/Standalone-Installation-Instructions.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/OHIF-Viewer/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/OHIF-Viewer/environment-installations.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/OHIF-Viewer/usage.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/README.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Assessment_Progress.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Association_Dialog.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Audit_Trails.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_CINE.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Change_Password.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_CompareMode.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Comparison.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Configuration_Menu.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Conformance_Check.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Download.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Ellipse.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_FlipH.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_FlipV.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Forgot_Password.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Generate_Report.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_HUD_Panel.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Image_Viewer.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_After_Prerequisites.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Desktop_Shortcuts.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Final.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Finish.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Initial.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Launch_Installation.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Launch_Uninstall.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_License_Aggrement.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Prerequisites.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Select_Location.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Services.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Successful.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Installer_Uninstall.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Invert.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Key_Timepoints.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Keyboard_Shortcuts.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Login.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Logout.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Magnify.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Measurements.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Need_Account.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_NonTarget_Select_Location.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_NonTarget_Tool.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Orthanc_Delete_Select_Patient.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Orthanc_Delete_Select_Study.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Orthanc_Delete_Study.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Orthanc_Drag_and_Drop.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Orthanc_Start_Upload.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Orthanc_Upload.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Orthanc_Upload_Result.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Pan.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Quick_Switch_Tool.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Remove_Associate.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Report_PDF.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Reset.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Response_Criteria.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Rotate_Right.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Save1.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Save2.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Scroll.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Select_Associate.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Server_Info.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_StackScroll_Multiple.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_StackScroll_Single.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Studies_Panel.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_StudyList.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Target.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Target_CR.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Target_Delete.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Target_Label.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Target_Rename.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Target_UN.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Temp_Tool.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Themes.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_View_Lesion.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_View_Series_Details.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_View_Study.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Viewer.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_WL.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_WL_Presets.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/LesionTracker/LT_Zoom.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/lesionTracker.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/viewer.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/assets/img/worklist.png (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/connecting-to-image-archives/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/connecting-to-image-archives/dcm4chee-with-docker.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/connecting-to-image-archives/dicomweb.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/connecting-to-image-archives/dimse.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/connecting-to-image-archives/google-cloud-healthcare.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/connecting-to-image-archives/options.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/connecting-to-image-archives/orthanc-with-docker.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/contributing.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/data/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/data/data-hierarchy.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/data/image-viewport.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/data/measurements-and-annotations.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/data/tool-management.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/deployment/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/deployment/building-for-production.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/deployment/security.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/essentials/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/essentials/architecture.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/essentials/configuration.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/essentials/installation.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/essentials/meteor-packages.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/essentials/troubleshooting.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/example-applications/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/example-applications/lesion-tracker.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/example-applications/ohif-viewer.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/example-applications/standalone-viewer.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/faq/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/faq/general.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/faq/technical.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/layout/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/layout/hanging-protocols.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/layout/layout-management.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/lesion-tracker/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/lesion-tracker/audit-trail.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/lesion-tracker/installation-on-windows.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/lesion-tracker/manage-studies-in-orthanc.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/lesion-tracker/server-management.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/lesion-tracker/study-and-timepoint-management.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/lesion-tracker/user-accounts.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/lesion-tracker/user-preferences.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/lesion-tracker/using-the-viewer.md (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/packages/_category_.json (100%) rename platform/docs/versioned_docs/{version-1.0 => version-1.0-deprecated}/packages/measurements.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/Architecture.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/README.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/designs/architecture-diagram (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/designs/canny-full.fig (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/designs/cloud.svg (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/designs/embedded-viewer-diagram (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/designs/nginx-image-archive.fig (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/designs/npm-logo-red.svg (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/designs/scope-of-project.fig (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/designs/user-access-control-request-flow.fig (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/WORKFLOW_DEPLOY.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/WORKFLOW_PR_CHECKS.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/WORKFLOW_PR_OPTIONAL_DOCKER_PUBLISH.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/WORKFLOW_RELEASE.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/architecture-diagram.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/cornerstone-tools-link.gif (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/dialog-example.gif (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/embedded-viewer-diagram.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/extensions-diagram.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/extensions-panel.gif (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/extensions-toolbar-nested.gif (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/extensions-toolbar.gif (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/extensions-viewport.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/homePage.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/jwt-explained.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/keycloak-default-theme.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/keycloak-ohif-theme.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/lesionTracker.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/locizeSponsor.svg (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/modal-example.gif (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/netlify-drop.gif (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/nginx-image-archive.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/notification-example.gif (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/open-graph.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/scope-of-project.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/services.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/surge-deploy.gif (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/ui-services.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/user-access-control-request-flow.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/viewer.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/assets/img/worklist.png (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/configuring/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/configuring/data-source.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/configuring/index.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/deployment/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/deployment/index.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/deployment/recipes/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/deployment/recipes/build-for-production.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/deployment/recipes/embedded-viewer.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/deployment/recipes/google-cloud-healthcare.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/deployment/recipes/nginx--image-archive.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/deployment/recipes/static-assets.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/deployment/recipes/user-account-control.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/development/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/development/continous-integration.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/development/contributing.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/development/getting-started.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/development/testing.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/index.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/lifecycle/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/lifecycle/pre-registration.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/modules/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/modules/commands.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/modules/panel.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/modules/sop-class-handler.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/modules/toolbar.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/extensions/modules/viewport.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/faq/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/faq/browser-support.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/faq/index.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/faq/pwa-vs-packaged.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/faq/scope-of-project.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/help.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/our-process.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/services/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/services/default.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/services/index.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/services/ui/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/services/ui/index.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/services/ui/ui-dialog-service.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/services/ui/ui-modal-service.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/services/ui/ui-notification-service.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/viewer/_category_.json (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/viewer/configuration.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/viewer/environment-variables.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/viewer/internationalization.md (100%) rename platform/docs/versioned_docs/{version-2.0 => version-2.0-deprecated}/viewer/themeing.md (100%) delete mode 100644 platform/docs/versioned_docs/version-3.0/README.md delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/designs/architecture-diagram delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/designs/canny-full.fig delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/designs/cloud.svg delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/designs/embedded-viewer-diagram delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/designs/nginx-image-archive.fig delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/designs/npm-logo-red.svg delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/designs/scope-of-project.fig delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/designs/user-access-control-request-flow.fig delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/OHIF-Viewer.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/OHIF-e2e-test-studies.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/SR-exported.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/WORKFLOW_DEPLOY.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/WORKFLOW_PR_CHECKS.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/WORKFLOW_PR_OPTIONAL_DOCKER_PUBLISH.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/WORKFLOW_RELEASE.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/add-extension.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/add-mode.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/cli-search-no-verbose.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/cli-search-with-verbose.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/clock-mode.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/clock-mode1.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/cornerstone-tools-link.gif delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/create-extension.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/create-mode.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/custom-logo.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/dicom-json-public.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/dicom-json.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/docker-pacs.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/e2e-cypress-final.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/e2e-cypress.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/embedded-viewer-diagram.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/jwt-explained.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/keycloak-default-theme.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/keycloak-ohif-theme.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/locizeSponsor.svg delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/locked-sr.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/measurement-panel-1.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/measurement-panel-prompt.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/measurement-panel-tracked.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/measurement-temporary.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/measurements-prevNext.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/mode-archs.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/mode-clock.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/mode-template.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/nginx-image-archive.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/ohif-cli-list.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/open-graph.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/overview.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/panel-module-left-right.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/panel-module-v3.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/panelmodule-icon.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/restore-exported-sr.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/scope-of-project.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/services-data.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/services-measurements.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/services-ui.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/services.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/surge-deploy.gif delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/template-extension-files.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/template-mode-files.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/template-mode-ui.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/toolbar-module.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/toolbarModule-layout.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/toolbarModule-nested-buttons.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/toolbarModule-zoom.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/tracked-not-tracked.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/tracking-workflow1.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/tracking-workflow2.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/tracking-workflow3.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/ui-modal.gif delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/ui-services.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-access-control-request-flow.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-hotkeys-default.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-hotkeys.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-measurement-export.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-open-viewer.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-study-filter.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-study-list.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-study-next.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-study-panel.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-study-summary.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-studyist-modespecific.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-toolbar-download-icon.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-toolbar-extra.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-toolbar-preset.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-toolbarDownload.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-viewer-layout.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-viewer-main.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-viewer-toolbar-measurements.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-viewer-toolbar.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/user-viewer.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/viewportModule-layout.png delete mode 100644 platform/docs/versioned_docs/version-3.0/assets/img/viewportModule.png delete mode 100644 platform/docs/versioned_docs/version-3.0/configuration/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/configuration/configuration.md delete mode 100644 platform/docs/versioned_docs/version-3.0/configuration/dataSources/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/configuration/dataSources/dicom-json.md delete mode 100644 platform/docs/versioned_docs/version-3.0/configuration/dataSources/dicom-web.md delete mode 100644 platform/docs/versioned_docs/version-3.0/configuration/dataSources/static-files.md delete mode 100644 platform/docs/versioned_docs/version-3.0/configuration/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/deployment/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/deployment/build-for-production.md delete mode 100644 platform/docs/versioned_docs/version-3.0/deployment/google-cloud-healthcare.md delete mode 100644 platform/docs/versioned_docs/version-3.0/deployment/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/deployment/nginx--image-archive.md delete mode 100644 platform/docs/versioned_docs/version-3.0/deployment/static-assets.md delete mode 100644 platform/docs/versioned_docs/version-3.0/deployment/user-account-control.md delete mode 100644 platform/docs/versioned_docs/version-3.0/development/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/development/architecture.md delete mode 100644 platform/docs/versioned_docs/version-3.0/development/continous-integration.md delete mode 100644 platform/docs/versioned_docs/version-3.0/development/contributing.md delete mode 100644 platform/docs/versioned_docs/version-3.0/development/getting-started.md delete mode 100644 platform/docs/versioned_docs/version-3.0/development/ohif-cli.md delete mode 100644 platform/docs/versioned_docs/version-3.0/development/our-process.md delete mode 100644 platform/docs/versioned_docs/version-3.0/development/testing.md delete mode 100644 platform/docs/versioned_docs/version-3.0/faq.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/browser-support.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/environment-variables.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/extension.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/installation.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/lifecycle.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/commands.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/contextModule.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/data-source.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/hpModule.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/layout-template.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/panel.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/sop-class-handler.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/toolbar.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/extensions/modules/viewport.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/internationalization.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/managers/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/managers/commands.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/managers/extension.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/managers/hotkeys.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/managers/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/managers/service.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/modes/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/modes/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/modes/installation.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/modes/lifecycle.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/modes/routes.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/modes/validity.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/pwa-vs-packaged.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/scope-of-project.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/data/DicomMetadataStore.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/data/DisplaySetService.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/data/HangingProtocolService.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/data/MeasurementService.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/data/ToolbarService.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/data/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/data/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/pubsub.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/ui/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/ui/cine-service.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/ui/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-dialog-service.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-modal-service.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-notification-service.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-viewport-dialog-service.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/services/ui/viewport-grid-service.md delete mode 100644 platform/docs/versioned_docs/version-3.0/platform/themeing.md delete mode 100644 platform/docs/versioned_docs/version-3.0/release-notes.md delete mode 100644 platform/docs/versioned_docs/version-3.0/resources.md delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/viewer/Language.md delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/viewer/_category_.json delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/viewer/hotkeys.md delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/viewer/index.md delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/viewer/measurement-panel.md delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/viewer/measurement-tracking.md delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/viewer/study-panel.md delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/viewer/toolbar.md delete mode 100644 platform/docs/versioned_docs/version-3.0/user-guide/viewer/viewport.md rename platform/docs/versioned_sidebars/{version-1.0-sidebars.json => version-1.0-deprecated-sidebars.json} (100%) rename platform/docs/versioned_sidebars/{version-2.0-sidebars.json => version-2.0-deprecated-sidebars.json} (100%) delete mode 100644 platform/docs/versioned_sidebars/version-3.0-sidebars.json diff --git a/.webpack/webpack.base.js b/.webpack/webpack.base.js index ec8ec5291eb..e1b531461da 100644 --- a/.webpack/webpack.base.js +++ b/.webpack/webpack.base.js @@ -73,15 +73,6 @@ module.exports = (env, argv, { SRC_DIR, ENTRY }) => { children: false, warnings: true, }, - devServer: { - open: true, - port: 3000, - historyApiFallback: true, - headers: { - 'Cross-Origin-Embedder-Policy': 'require-corp', - 'Cross-Origin-Opener-Policy': 'same-origin', - }, - }, cache: { type: 'filesystem', }, diff --git a/extensions/cornerstone-dicom-sr/package.json b/extensions/cornerstone-dicom-sr/package.json index 0ab1e03d81e..c820986c34f 100644 --- a/extensions/cornerstone-dicom-sr/package.json +++ b/extensions/cornerstone-dicom-sr/package.json @@ -44,9 +44,9 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^1.1.8", - "@cornerstonejs/core": "^1.1.8", - "@cornerstonejs/tools": "^1.1.8", + "@cornerstonejs/adapters": "^1.2.4", + "@cornerstonejs/core": "^1.2.4", + "@cornerstonejs/tools": "^1.2.4", "classnames": "^2.3.2" } } diff --git a/extensions/cornerstone/package.json b/extensions/cornerstone/package.json index 92d5cb8d005..8240cf5982a 100644 --- a/extensions/cornerstone/package.json +++ b/extensions/cornerstone/package.json @@ -36,7 +36,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.1.8", + "@cornerstonejs/dicom-image-loader": "^1.2.4", "@ohif/core": "3.7.0-beta.11", "@ohif/ui": "3.7.0-beta.11", "dcmjs": "^0.29.6", @@ -52,10 +52,10 @@ }, "dependencies": { "@babel/runtime": "^7.20.13", - "@cornerstonejs/adapters": "^1.1.8", - "@cornerstonejs/core": "^1.1.8", - "@cornerstonejs/streaming-image-volume-loader": "^1.1.8", - "@cornerstonejs/tools": "^1.1.8", + "@cornerstonejs/adapters": "^1.2.4", + "@cornerstonejs/core": "^1.2.4", + "@cornerstonejs/streaming-image-volume-loader": "^1.2.4", + "@cornerstonejs/tools": "^1.2.4", "@kitware/vtk.js": "27.3.1", "html2canvas": "^1.4.1", "lodash.debounce": "4.0.8", diff --git a/extensions/measurement-tracking/package.json b/extensions/measurement-tracking/package.json index 53b9445432a..5302d7076f8 100644 --- a/extensions/measurement-tracking/package.json +++ b/extensions/measurement-tracking/package.json @@ -30,8 +30,8 @@ "start": "yarn run dev" }, "peerDependencies": { - "@cornerstonejs/core": "^1.1.8", - "@cornerstonejs/tools": "^1.1.8", + "@cornerstonejs/core": "^1.2.4", + "@cornerstonejs/tools": "^1.2.4", "@ohif/core": "3.7.0-beta.11", "@ohif/extension-cornerstone-dicom-sr": "3.7.0-beta.11", "@ohif/ui": "3.7.0-beta.11", diff --git a/package.json b/package.json index d710148376c..dd370c7c909 100644 --- a/package.json +++ b/package.json @@ -149,7 +149,7 @@ ] }, "resolutions": { - "@cornerstonejs/core": "^1.1.8", + "@cornerstonejs/core": "^1.2.4", "**/@babel/runtime": "^7.20.13", "commander": "8.3.0", "nth-check": "^2.1.1", diff --git a/platform/app/netlify.toml b/platform/app/netlify.toml index 4af3dd5977b..5942b9a58b7 100644 --- a/platform/app/netlify.toml +++ b/platform/app/netlify.toml @@ -43,3 +43,5 @@ # COMMENT: For sharedArrayBuffer, see https://developer.chrome.com/blog/enabling-shared-array-buffer/ Cross-Origin-Embedder-Policy = "require-corp" Cross-Origin-Opener-Policy = "same-origin" + # set CORP to cross-origin for anyone who wants to use the viewer in an iframe + Cross-Origin-Resource-Policy = "cross-origin" diff --git a/platform/app/package.json b/platform/app/package.json index 8a1f367f2e0..eeabf0a9c9a 100644 --- a/platform/app/package.json +++ b/platform/app/package.json @@ -51,7 +51,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.1.8", + "@cornerstonejs/dicom-image-loader": "^1.2.4", "@ohif/core": "3.7.0-beta.11", "@ohif/extension-cornerstone": "3.7.0-beta.11", "@ohif/extension-cornerstone-dicom-rt": "3.7.0-beta.11", diff --git a/platform/core/package.json b/platform/core/package.json index acaeebb2f2b..dcccdf99781 100644 --- a/platform/core/package.json +++ b/platform/core/package.json @@ -35,7 +35,7 @@ "@cornerstonejs/codec-libjpeg-turbo-8bit": "^1.2.2", "@cornerstonejs/codec-openjpeg": "^1.2.2", "@cornerstonejs/codec-openjph": "^2.4.2", - "@cornerstonejs/dicom-image-loader": "^1.1.8", + "@cornerstonejs/dicom-image-loader": "^1.2.4", "@ohif/ui": "3.7.0-beta.11", "cornerstone-math": "0.1.9", "dicom-parser": "^1.8.21" diff --git a/platform/docs/docs/assets/img/iframe-basic.png b/platform/docs/docs/assets/img/iframe-basic.png new file mode 100644 index 0000000000000000000000000000000000000000..25ea20708bf58092bfcaf7e2de21453bf7544a8d GIT binary patch literal 145099 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 N!G2@i{9le={5OPA(+&Ut literal 0 HcmV?d00001 diff --git a/platform/docs/docs/assets/img/iframe-headers.png b/platform/docs/docs/assets/img/iframe-headers.png new file mode 100644 index 0000000000000000000000000000000000000000..27d649d22f34884d016563b57c63579ac25485ec GIT binary patch literal 219238 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�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 z%0Die|NL<|2!hGg9wPGF|HhL4`P&xCUw9x0fK3hl_f9b(V5?EERX2RWkohm|$p3uA zf4#z6#0Us<0`_2$oG7gPUs>Egw=2jJX6SAgj43D>qyMIC0s}EILY-8c+Y5jh_TOfo z9cmG*|8k-5w2Kt{pxl@mx=R2a{V2*hu;!MLQ6PHi|K9{Lo)39-vmKOHPLol#Us1IG zAM9z zCwA4>lD8G+%hKL~OC(`8PZ`UoUks0iQ}bXmh+cZ8DTq@7lJ=$_otmnK2`qwTAV{%a z_0_E5RY;S+C%b%nd`uFRh&jo-vbo;UV~S^l-j+oZ&;Vo1fn& z|204V&DG7VSOOx%jTm3pydmBW|io3Ap& z1LE{dTwLmml<09@p{BEdVhIzIyuFYn1W95Gl}p+9agqUacnMvVPurxI2}Jklq2y!; zR|RKVXzk=o(_sbb%DJ<8vlR2vR%FN0v?oU=$6M{i_ULh**KM}ntkS`!bHJwu6 zt%|KB^@tNNyv4>s>}W)3vA4pw$uFQOi231RVO0miQTHK-70k>in{DPtDmbmc=7oQq zKF9H9P#?f7q@))670So!-s6bA^>(-Yy=Jhdfs+0sST={Tssg5u?KcX!?0m5OQ6Por z{o~VYZN6gOX`W$WY+-l))DGz>ia%h$IiB|qSS37TZS_@Vv*4Ko6xsl3 zlb;~weF)ztkKvVnE}kg`B(8WZK!eKvRoQ@qj5I#6CV!{7b#QP%_gLtcoZ(6%H9|!O zk}{;AvKZC9C8%Hv?n=PAg>Ua{pKm@{vhcYG=~{Koqfhj2i&mM%##O1-YqlVeMIH`6 z4pBive_|YicqE4gN&0K@Pxle;Z&l5Sd))Lw!vm7{KYo&azdQRS&(?i|Nkc=U`r!i% z_+^T3aaj8lRI7>`vA#p{1Qzhk%@xbrY;<`8w#OB?5xzQ!*e4eDhp_#R74t+M^idM* zNw%N&2)@=eNXY$I<9Mky*GSa_HTLIEjn#Vdh_^~!xMka<5JX5?Z0|>J*Q8)^VYowl zKXZt9NPb$BbO;lZc<62XS#!)F=x^94JN_nv zZ$%63^g#)@Bb6j(lujI%ejc@V>g+N_Gf8sTKlD0UJ&RP<_5<(J0eFR9!;Q9{}9!|{H;KC2ZYLKtU0Q6Os)w~uq2_nh& z#Ee7+oYso!LjS^EN&OGPU=JX82iR@?1c3J}u4Zq@XBF!_;-yX4EU2l+DZHXK~N&%uJIRJidF#pN?0^TW<0?5y= za~DRBb!!dgkR~PPfwiQ1btaJ8hG9UQ$9xL`zX#{YrZ^Oca24D|K+UOa%cML7d5=E! z+CzmH@PDGba|ji9iGYhS>~9gup|8giaD_|9;8Vc=YSAEr-qmE%9%su=hY4cm=r zpV$3ei-yAWsdAcN4jk{t zDPma=%@b)B1@zp`tdV47h#A?g4-edE-xn$oDe5 zCty}TkxSs~t+pzmrrISzFAuYe*u#_yx7}hDzqo+WM};scO!Y_dtu7J8$De8cL#8dp zBLe|_0OtCSL*9VP5$yGO^aVk3+ssi%_rNvPneOy}ojId~$V$;h`iP*t>0R0TMyR1o z@xSgGpgxQH4;89Xzz;y zi-y&ha3VgF??DF+i39#__)WsjvCys+u6=kmF1353JP$j4Jb+t$a#0Xg{*#vutznz9 zxSklKvVvFQ24TN#seY?tgHi&Cx66!%2u5FH^g*9411G22ou@Tk-5rsDYmu&MJ+@3U zSre@AnsukO(_yP~yfbkb*YsDJ++hADjwbnw1bOD@nnb|%*EH`&cdv4fau|uMmg-&7 z&^HX>{2^7FS>=kmc>X>0h8@zYofvKe8PWVFPVh7WLd)%nrl#j~vGbKRwtWO(&>V~m zsLlS0q%MB#42||LHSW3lVc&AL4m<4U#WU4kT(Rt3g5&> zh1Zj{)>^;KU^;Apx>U&XE9$X~#OXIMdER`Zx#FeHa{B*86{^*7kUTaUB}w4ZNkpUQuN~`NVjE=R2PkRTh3g1n%vtBv1jynVeXdqfUmn zMim!)#{483@SqpNiH=4Z)yjx$6}l}3v|K5~X5Nb6<`01%P|aaPe(b}$AFG|)B|XB3 zZ~Xp3VWjv$1+NG?a4YOZHiENHJ*D!vf>yf^=F!X8%pBFv9oBU=owykIp5LU5&08b`<==X;P~9gE@~EA;h!O9{h+?C$3RVAtbPqNWMidYpZeUH0+=RFldjnfjkFjU09Fk#sc+KQ9??p_i ztf$e51B;UxXIv||oPJ>$Wn*l0{9n)&YZiy-Q8Ceq8yDk0AA(c|n;5*CUeL+nmJKw_aQ0NKf9^s+d_WC(fMWV#63?BI_RP+g+fZB#7H z>*8yFj+N4qrw5t##R*bY%c13{&{I@@586U8lH=tu?Gt&}CPhNNfS{o2_6bm3O zLmv1k!rmw1Mc%s;`#C{bQ34$xkjFm21CkQ1ae)giO(HODi(rnzd!QnA|Ip@9P;&gm z*}xpCxMtylGQ%CKVHdUca>qOpt*rmkP2x)eJSPevw=8J#y#f!)3wSvx#I)T$dL4MV zBeeoI%d3d7$~Q+rdW!5Wq5q-n>M_jE+O8toW{vo2s}ECUK}j<=*iSav1FDCAmo&nD zqCiv!&F zAXp_tjq+IZi|jb(p=k0xS?o!Y{G8*t_&`WpVZ<+qivu4}h78z3Dh57~6Laq9jYkPH zk{yS=AuByAVr=-U!`2u+v;v9`M_<=|s(zV#8Y{0Rn9T|1 zGs(&mTlAR_3A5`An-GWCpd`8c#b1A(c9oETEOGn|k4^1K<)Q*m|O=~~TfSCa_zNlM8j^kOZwtQwz`(XS zluLs4c(5P?uwjxiP?(;`GM{t{b{KCbKS4Z;Q3lCudovUf%NiVE&sD%L3MZN&BGW4C zGz@F_ql-QFUGG(eS`qsrGSB$jfGwpb!S!e+?!NHGc|b_$OAtwPh8CkfVGmIeJD|I3 zBUv<2B-6}C*%e9R&+Wu`6kk!2cu@dM$&(``Z$%FqRl}2D_nD;7yz-U4N($aw&&|Xf zO7ts_7lFdF5|Hod@fN*g3qdl%1Db?m5$wqkPfRE-@mDHjn#MTsjkstI{y5?EXrY1< zN?HBzmtWQ4uOvvbew1z(LLWz8;hb%SJPls@6dn31V0bL5bB3U0k)LmLuW6`7gysVi z2)sB1NFjxRV3!-=n#p=3irM$+HTr^&SRH;88wEe#%-9#p9PFOnx|Qi?B8_Kpnfep| z1JW99Fm*8y&}M&B!o+ENWWk)I5PiF%RP}72zaHR%!+J!F2->OGt1nb6pdR-d3`!kG z&@c=n78DP^jDXJfAod{&RIebiIWblPbBGw{3&=nP{0mq@?*zcMY-I|hyCgB(;}$Y0 zc`~dT7TtvuA@jTHRV5cli!($NaG|!eg$SgVQTz->zVRwhn7y2Ibyfnb@B%fAOT}~< z6Rj9O727e)Fv6a?W#!9Pcr=HAbxGVAiC;^0;8({&(^AYsN2c6)um8McFSuFDz#vOw zs4S8K)bv58VXocH>S;gCn4W?{{5J`&J-+|_FVEBlmvz)|h#U^$X*sW)A1$-mx(yOT zoRUo>^prn(W&@njdfBW!L8@#unq=V~u=3dUt+5`_t_f(TNa=a+b0tzjGDOLKQe;(6 zs9CDCS5yFR=XkrJaSs&trZ%|1WaMF(Czc{{{N#mYRk{5L;WjP5M0kI4i$NY|)mOwb zRody}dyU(nX`em-ycY$jpG%N)eAiaAC)`|Nj%;+t7rMO>$ecDAV%hPCE}NzKy*cI~ zX!tBuwlF*|DCHrWO;mcUdk~T=C+ia)CMIQ|n@O18q4vZ#a;{@2;dJ77h#VrY2?DA1 zZ=Eo7>$w(G7B6!E&4^(guGj18KY-!Zt_F26v&N2Zw$tTwWPlk)*OUjLcT5`=vug!pK(0xhag2M}9PSb&BU_Vo(SO1ya4^&WML4;Y%8 zBcylU5=A+MIE6k%4Q+|N3-*ZMZ!%l}Xc8tvz8%tGlUg@gueHI88c>PU-~_r$XB~4n zhp$_|H-P8)l3xXQ{DprklpWmPJ*e^?G?y)CwJufCD~kBzYjiZ-ejjV5z|tks zBlZm&g#Hr`21t)*$$*kz#4v?(M^DBHjZDL~(}(4K*%NF~*AV&wKC6y}LAxAMVU&Pi zl}+O6sAS?)N|mxLvhIw*C*z}`NUYC)mN_y2w`|H^{*XwoJEn4Y_I(@1yE&KMK4cs7KPvrCOY%SSLn<;7Z#hZJgX)LqR zD1&?s=4&l(-t3hw^r;{k)7^{0y84a8J3gr z4mp*6Pl}2!TJoV-S~;6}H}~~Ml91CTOWg0?6x!xV<{Y0GD>q>M|FU9qq#-6s*_Vf5 zh@iK7{GZiM7OPpTFzfO0-@)edp~Z0c>l2VIW4W1y>JVEeTyXog4Z&V0WgN2dA;g&f z?FBHBM+)tPGNkGuow#d);w)~v^F{cpHWtLXIn);A17&P$YkWXL{5Z^mDQ2EUKfw_= z+e44VxgFzs0V|rEPs^45)s!=DPnvKn%&%>P;Hq*w8VOo7bXSbfJ-(}LWDokP91;Dv z9Q46QGkhoBXDi5$9(g~=&(GgN@8SbL!crO5+%92Pg3)-mv%(lQDg4q5(xniW3^aSk)(SN_$niDX(PGmhAMO!I8q?IyWJ$1m=Pf$>u?TND z;^)wQzTU%8{r09P*X@&iM+THK6lyLJIRWPToQ_0~e3NAP{U)JQHaD{963_~Xu2o$cdCAI-UvhGZkXrh8k}7bcvKmG=3` z#ps_JxWIY8_XD@H#|^g`ubd3{Yj&;xJgaFBhl7q8_necg=a+!{o#<4uz(;-5^Xy!~ zvKV9EQ`c8fx&=|f>*Q+B)q3W}0i^x4T*0o}TJ6A*&qp|EY)eKQTv6V>&Ne8Q?}gyEZ6T(IR&^OheyzSpW9ZgKxS>rgWd1($I)pW{KCM; zO|pkDfaQhU))+bFkZ4ak>%+bM2JhQD9g2p&XBCprVSrxc-{YhHK`D+n*B(0=_L3L* z2V@SlN!l1*9TWH)QEU>B2-kg+SccZXeEbvS`(d7;KqiTx#rnmCh1Kh7NSY!@^0w4X zzB^CS5i@(4>BdzI5b$(aRC@m`Z27j)I&O~;0eHF$l63sDPvrOlH~PhDu#zwEcWo~O z^jKc})S-yy%|_(5%JlYTl055*^QXHR$IeqNC4v3qJDo7pNj0n;9gg>uoMm%EWUz6O&W3%mjw5XvVo#?sKnM5`CUrH+R8^cZ=i0iXRuPP7*x9x#n=kb#5&$|V-U zUKYYnDUc*IO^XJ+F>xbAMt>xgoG-)JX7td~fDnP>{cOKzZk#XZ(E83}OP5Me*z%Yk z{q}zdy*d^N_C=C3vGu-OalNcu%>uu#uO6Mpxp=Y*;vP;-{@DK2c6Rx63YuTaP}z9P zku1%yA8d~QkP?En>`&O_eUMpdf4h!aVxzA6Ig!J%_Ls39VD-M)vhY^>^uE_|v>Nn@ zNV(Ii`?xqW1<&c$nUrGnnMLTQ=pVFH7oy&tt_L16<`ak8-wi6il6xO{)_9Z8{V#)# zv+k2MdHp3u@y=9x zF}~NnELHm6{3x7|S%MPkI<3CdU-WVJ{d#k<8&|uuU3%ATf6q6qkx@D+q@1C$*?%$W zL-RiN3e*5T*Svy6PsqklTbCPtur@uIouVI98NU<|w;c5B&%OsJ3*7Vdvdnl*H%0^N zhB)O@^qtZT;+C!60|f6HWtw}=a;KrPVFi&tuq#lF+;{2MV7^Vo3vp2Yq zqnMQE=iCS#=!|8FWnzv&^1Ct~7zRgb2=TV6UIJ}&$dyxakZjx)RpUJS12MJ%D9{Z_ z?Ef)E3fhmPs}5(w`f%P}f4?L)2NQ_u2|6V(Pg;hZZFU%`VD`cc*aQ8TS0r(|I`8cD z3>l!66C!n{;q;frqEoVek-3W3H>#}Zuw7GFQK|2q=?S5WfVDT68ehSETSy z(Kc|Ax|RaYUH>ZQli3l{4SD&3V{{xebIF8GeAg!*WxO-7c{v{rzvT(&R0p8uIE#CQ zN$bB5l9Fzh1A6)5Hab?1)g3hkLX^{5dKQ~uH>+Tug4b7}&>ph5lwM}x@Em@NtvE0qB|*wY{Di;lf!@xY{A@65XeRyEzK42X=ozbyzSL((H~; zd;Zk^Zm!JV{Bq70u;`dVe4F8Ue=1_&OJ{|VxF+9{_5BO%Zu5ICLrXp< z36v8!YCULfIeHhknHWuTBK39k|KY&4)qap;bjA)}B^>bRy2Ca@fB({nhfaJug*7qy ze!yax$->7f6L^r!$@PSH>e|OmIa=GMP^sK;^<=Z!39{DT%D~EBs+G|>G23$kk0iz>+Sj*h^uv@qN?X@b^k>)%Me%B{*v?Y zyWIqC?Q+d@tuIKR7uYP!PGtP+6s_pL5ZQ#cF38EDn`(H%E;yGo@NvQzs6GWV;i$Ge zMi+#aZVS(VoCkXgWe(XcW~k502zA*HVL;BhjVROW%By{h2ugwHBZoSN*-9+WUAHfS zxp=UV4^r-F@Y`Sr42*$B1-kl;hm^+0tzv$S2qdL3hknRcE#(tDM+GTYxB3hZM%4Vl z`gOBnFm^=JZXeC|CWVJ zZE5W~6P>`psy$*86g0YRV3}xM+B6t(x>;=)t6*bGGw`rn@n1S6nre*`DQ9l{nRMzx zk9zJq8aHJMbY14C4lE0NyIGo;81K#PAQ0VNgV&_<%Ojn;;oU-JYcdgdchXjnJm#q4 z(K0M=o{9m60*a^KhB5Z7HXkh>*M_ksF6m-7W(K4_rTu?YoqIgf{r~@+M>3@%4RfVZ zA##}WkTP9DSFVyAyBy0g=DY(|RymB2TI{?kzb*Sx}>XmOg+9(_Cm{Hry-TM-lq5H1| zO;;=-2!JX`V@uz?&*A>=U%xIHS!VcK`>P>`w zLX5?}Q%O8NxiglJdXFc(mh*eb^R9^ucUx-wo`p6WYo=LCa*R6lXfgJbWuU59Y<|3h zZO2)uus6#mU}&Dux~~Az{6(@WCJJZ}BIW>3DNlmbP%9!SIR*OK)6@qYou901fU%M! ze$4~;gRxCN?C~J~bk96$S!!c}ewmZnI#CphmDbZ%Bz0smRdu77zNo?DjQrYOfWR1U zQ-p&qzE!k^tkzLzseJ{j=uyeNNNwd6ndHw$Xaki|Kuhh~vYn{-mO|6Tf{*kl3}BW$ zRrk+EzWf1Gr-2eF?xME>vJ*ac!#;@Ykvi1&5xqLu^>#SM>$XAT``8|NJc_ZlTWC=@dvFQ+=TBvcK3$jG|at0Lo{1K16&$-*?wPg0(+ONqMWJ z+XRn!^5f55<&kBL(%HMUTkkqbi}rIG`-Lo zID53SGur>bHL>mw0RTAEF1=y%Xmi%g)v>W{8#JhJ80s9(xAt{A{tD&^D;0>|pf>hK z?;!Q}(ez#p!rS~zc%Xc_rdo$6JB{3H?rpUa|47(fSpn=n_^SEr!P$Cvz&&McyU_NJ zfcp9^DX++jsrFwR4(0)Gb=RJ-MB^F%fV%ao=O$z-!$yOqMp7lg_h!R?K6cGjs(y;x zGZ*4R`ExG0=xSlsLD2X|#FkQcGJ33KD{#Nb9awcUKg>PyUw17778ZPT@V%(NA|m7k z>#(#RGUfHD)whA%!HHCzv?3wr7x@Nwo`Q}g#KrnL@z3+n_~u!BD}GZsM*5`u7=J&1 z(5>H8*+_#>Drw%6H!3x##y?$19mKL$rwcD7`%JZ>vV42AuNXkow zoK+6n=z)L0JWthe@S~{!H)Ne7PCW{1!+@pAC~=~8ffX|5TQ+|t;yb5Wd5cujC?iHL zpXSEBR;le~&33vOvA62`-#~Qi!&W}V&6yrPyIXUsu`)(kmqgTe&=BkGXKK;%C!Sqc za$@_KY+rBs=XehSBl_K%k@JjaW2si1QoYauQ=kRFY4V2vK-a~PQ9un#PIDu%7>t*y zFp;NaB_65! zeXv~rfRDXUQ);`=Lhwz9o^5NSYE`xLK3X0^SIFwL`{Z6+?(P}0mMEVw8dzDjv&*X5 zwHVGTKk}bY#}kiakOTEjh_tB?a(-Gnvb5UIjj6PcHQIY^VHqn@SshW+u7hUfl zldqC!^2&;{KIzM+tC1arC0@*>JruFdx1KX2VHbZ0F|XTk434fqcs0-T6zO`~Hf?R3 z>N)9n@WgYk%(*&X^sBP1%=7j&GBNL4K2rVZWtP$V>gLU^vR~+iDzAnO8P}cr){6MU zq4fV;yQh)-61I8k+Y^I7Q$MHpkI(K`rG9a}JewJ?G>CSPSZ2X;9b(usIMj4q(b4jK zC4>3zR+IC8U#*_?v(jE12megHgu4=>bntU@?qHac1{wZ)?Tl?(1`ULFXF5)HZI<<3 z+xXNwG~W1tVQ?^EIW<_}mMbeO!8n$1Do^<3NC4y4379O{GzeiK-O-#mr6!gKiJP0xX_bK?uYq14;=Hctbw`brhi;AnoBBJfpdjU4 z@G(SIZRT^CIZm($0&7dh#`C+?V=@wtZcWeZ|4Z*zf%n@cWuy)A6ve%Wo!Wa+~-=i$8D z)_X+{Hkpo7smP;!jm77V84qTek+X5HsSTAfT;9x#FSvS+bN=PJlCSg^82A2kvZ@^G zXrCS4bF{wm75bZB!qKJ}KKE$UF?a-JYyD15NyXB>Yghl*&~D6qJbDwg7@zLDA?iZR zSF&M09dR7g`X8{Ya}nK`oxStTdd;WqG2Shb)d`rkLRaQu{+p(p zo#k08ZbpT#6gc^FHoz{nE2C)CE~_y1KfU*@?MI>p`Ie)C37-w^v_Xdz-}2YF1nhbI zxT~_KqR*#)=Br^zofd4VoKO)gBPM;!{4ExC1t8V~G$fIgWv!d`=YlouSCY+51Tu|9 z1JxP1gqS-K0$H@PF~+AFk`I2p(qV^hu1SYIcaI9Bv($W?&$pdjz*N18@8A;^(W~Mr zJ!L-xj6Wsgu+aU{>rR>Wb?D{?LkXtehj0B-cFr#k7U+NApnjV*jeF%?V|D@N!=4w8 z3aTcbdIzkk`BN%=kOg&^+Bu%3ICb3{?99PF3hf?h`9vi8@;0yYy(RbHIeV~n!O@lN zZ;V$cfZ`-0L#O$zDC^6PQQ0V27)^DG&SF(=8ypTQC!M#pH?XIrGK%!*9b8zcI?god z;QVemuxQ0(0f5?-ACqUF6{I!UTD-V3^v=#zr3+u=(oMeH>ul@!hkke8BNG{2H^mT0 z#?x>_7>hpY&1&1;3fc3yxu-j_>Xmc^CNC9XMEXD#eFSf}@s9j<_{=7> zdoB3N*d68*U*Y+J=sm=tnrkUbwKNIGw6J-)UZ#}zj0irO1_nN`Lyl~*4tA9cSX-&R z?{0}J4I&QTy55^HoesC&oElA8tqv)kao^mUFGdv3j)#^skVbSA`i@hGoA07yH}G+U_#HZM`?b?Ps*gJ9oJ!^-JievyKAyn|oSg6zz(dSgU1QJqntKYWo0u z;HXVLn>mQSRy`Z!X_GSxTyy$e-7*vSdpl|3WZz0(I7&^9q{h{hn%bKV9yR7$e6Mjt zI`XT$P1D%0aW6>W)|y;I2t)1fjdep|8st_}KKl7iJPV^SY1jwyPg@%n=Hz4K;j2r$zmv_f@c-V4v|# zU5dhn>~d7IqeD?Mtt#3r%cV#P-lf@_52aW66TwZhtfKnEPi5<>!_e1T^}_=S$|yp4 z4}Eh?^3Nr}Y^7&9L!r3Bj!CcW%Qt=>&ZO?oj*E33v=<*e+|?tQA#Lm*kJ^%wosS$R)-O&a zGxOO$$pvp!f>NHju5cvbQ^LW>4fS;c>R0=zVoT)wJRo(f`RKqk6}kK5K+}#nxb;yK zS%BLg!9f2CIwBpq=IhT*OiKMi_{<&bAK2&ok0a;Ak3NyEsrFSzg?YZ=j-5!oeHFyHU0rm0Q$0C{H@4^BuhIBI}n`i;G8a&GWwCVxEd<<=7=y(wbeiL`; zu&=qXCZpkkR!3rBv^}X);7oab_{Zy67v|5)RS~f4uAXxr_1V-10LD+(5+hb6kr(Wl z2ZD@>sM8baU(5*B17|C~i1Ih}weS|{)d64ZKb)d|0_X;+tSJp0Mh}ElwFTIDEFMXf z1=Q@WBzDH4pEP&RTL{NbH91;8%xSW{L^{xbp|+P@%i~5BCG7m~hhKTddZX+xXZuUO z7q`z$dvXpk=afEsDeU3%Nphm1fr7rz`tWM~voM@9KL<(zb4O=>dGAaxLwg>bdT?37 zKJ30}J>s;I-~4^+R1QT?M+&9;HrqGrDI6O!Zzx;e+sbtBT76?+e-}6&TD|p?^=55q zO*wPMad|=3?iqQmm%F|pC**jqaAkeE7G`v%=YRO(*-0K5*U~5AF5w2n~*CBAl$hwPfS-&H|5A*fxC zjoBY?ocYLI{HrXQ;VB2du6#ArB>4%)5sFwqG$_ab3j<{0%)LDfC_OyO?0e}cK zjVZNq30)#X%6ayVcTgmK8M;?166|*5RliZSDD23%k=r@uEra_VIAlY5Rle2S#}yV8WC$1Z#jD2pGXFfJ`9^c@ecrga=KgHBLkec z7JR_^S#CkjHRpkU1{+~0Ia`JYQHIh`g%=&-U zrTfB!-^nyKe=pD4^CHk9_rZ$!hqO&m-R~2t+Lpcsv__joqwS4Nyp~zu4gk$E&VZed z7?}BEK(2Ir8WY|dm;?@bsivi~Il2OTCZO~q)ltKvhag;eHEF-QZi~{8Wx*kKvs!}e7c-*TZC$^eVg&h+_M4OuU zj#m9D_&ejo)!`$S&=R5_XCUuo_`(GfuU9|~b^ z1*OsmEw5+3$Yzj(A6bNR$)tkvz!6vu1j((p)72*`mN@B$e8Ju%Vtiayu)WuaRv??n zHh{9ua(Smb)}nML?{?Cp$cI?8Ni9t8?W3n(I))n_g>O{4KcC&{=NDJW?@OOJ$w&nm zFV%-ar6`)4O4D<1pIWg!qf+ZMACylMLAL=ta z$N~mP>d>DHE*UN!c?!^PGMff??v+EXb<$gN;*B@j-0s2D>mjc6PF(wUzt z=UlZ=H~LiJ?X5M-#QnuDjnELf*B9sfpQoH70c%malgK@(L~8ij`B|g?p$Iy{eOcls zNW$>NDR0f~ska#1-i5OgFU^E1+J>v&M|oZ$)Y{!$FEN~W%msy;`ekw9+bgEH#!o!I z#I1oS6I&Q2m>A!U4TcE%BPdyW7cYFqZcgo;o7I%$3Ga4u>bv1QiH$Z$6RF-+DrsS# zsjdzs!rq>4N$-nQ&_=Gv4i=sV+$7FDB)vHrVmHPm)t$~-kAQAoSA9^o;;vcIaW3MU zsCttX0|3LT*7L#aTdOBN#GeEkO0dGbUN_M>mEe$^+!$L8kaxvjx#<%IJ{a>1ty1Yv zp~3e60oD9{-zLuVZ5krvcNQiu)*vv=RFMTI)N=VaZyycd0*i~$GMw6s1!zN}sO9t9ky|c(=0@CmPVA~;f7{U|cLE)DV zY$$U(YdIR~P31b6;8oUI$nMp7ZW7Mr(D6l7%g(l>>DYO^Fe0SZl^3hG+t;t)jZq0= zmToMM6*p}4K!9Nn<$Q~Zz2A)(qU(Be-|dKhR@>(Bd_E>VVRgE4)^}UM6n3%w-axz;(t$csddi82}M{ zGJMSx!18U}8AU}DiHdGSdASk_&7-E>oD%RsAQ6H#f>4JdXgdh~q6sV4#tGhy#sYm$ z9K^Y2@rPs85=B!pt~-l=#hw+ej{B2-Ge*>&>zu#0Vyo`f5Lb}9F}#N{49?U8Smdb5 zFgjvk9mRd0CW);{WmjIx$mCxQd`F&3{(O{;wFKIK&<(2tVSLq>rLDlO-!u~&oL@FD z*OUuMx8x1o(>2+YC|vEYpt!cLX#}@)?*|sT8xn0{jNTrembn0n$R|eGvS#`S^NTX zM2R>80hX^shuc}F4%yn9^-n#WN4n3FEt^LlstIgF!6yIVtzhJ6G*NEDyi4(AJ1;Cy zJ(*stwoYM3Pl$d+&M;2EacA6EGHbW11tUUD6^-iDZL`)rG*c}7{#j}vL5|pnvGI+R z-!K{|&~)v5=2O~Ya1`_;QRjbZ$Q*d0J;npM$MZOH!xZh>Wf{*KS=?eJMiI_Bb#_YX za=s|q@NL97#*#JlX&aYVo~VzL7(%#X2g66^@nm-kWy#w6;jo94NTAG#ilmt60qOe~?sz05#jT|>mp6?Ce{1IwpxdMvrCePy1VnwBzgZGKIb*0pW)@ef) z@w>^5C$!6G(J(h^@=Cuz$6eS&Psnl9KF$&HGh~Qgl+GIOez!1r@VC##)!sdio>ckInX-)oQ0(A~To-V_PfcVo=TijB+3v>QDWMR%F8)W0X z*eg7-N>C8WpZYT&T3IMO3S8rTq*@ROH-g2dM{3T%t=963lQk}Qa@XHf*6ZrhqTCoH zOizB2N&m3-Tchf8n+KgiftdkVBuU*KB2gD_=Cx{g&LwU~IM%bE)WoybAV#?=WZqK1 z!LQsx!2QAE`h`H1Fiv>q7({o0|A*lJpA#G4!KL#*c=-5*IQv+c=7dYq$?hFhTkh+e zH^(PiV02Dn?GMkB_?;M<`GD#dV6vtHxR4pUW5k zZUFsBABYwxvBuboaH6^G`ajN*21D@x2QLc&nZ3EOsh>ow4Aoh#&Yd^1FBrx z1Q(`uQf&=`fbt|B&neYj#o<|-O7>Q7we96mp^EiLO}n*J)igu2S9Z~07+=$kYRV~ z4sgu~7^E6y*xcVuBf9%J^j)2m1}p0n1yrfs{I4ziAGL;)Pgx6tHotGQs)lFwr2)+i zv&^|%0@F`(m)VslT~2AyKl-izRIcPL-?W%csBpqsy$7BAhfu~vSFT{cwhunekJaR4 zCEmI7{&5+Gt%k5ih&S`~mU1n8c*0ow-Hwb&?!$YGE?PS-enKj{^hu62(1SucI5X+} zmhw%BJt>d_{rx<(YCOUYE7?*LC)734jayHqjT8eZr}P^uH1ILI)M$6T^^=Vhl`f2f zi%3t*%+Tdw106RhMp?h{j{O;6cWY9gWF+Q#P}E?&bYG*miZ!ESU6B18wG=eN3lu6W zuABNXk%_7yZ3I}#=2sG3~vHYD+R+te9BlWnatM2p{obHu*f_wLUQRTI) zHZR1AVk+eYZcT&Wy<4C}Olx91!KUZgr{~Qvy4;GpC{sw5R?vfn$}h z4}2{Uu`RE=dN2^teCbhPcbuN}%Zls(Ia zL9Vj+rdefw$Xap5J2*m2DO?SxuXC+Wu`#K90{QDh$XEJlmEJ^Jeo>!a8r{j!0AB&F7#}81ubLI7rUWw^Cz$Zh5F`T>0<#{Z0 zUM{`Kfqoq9?PV;`Nc?_{mD2t9fV-RAs;tQm&D=P#H16sQt~4KBxXRw6mWJzlZm?_+ z_?HANb!BJ46Brsx$kp-a3l9|1$CH%(ThOE@NsQ<)cADi?*d-}f?YTGGaYhDK%gZip zAFW4qw`9(0T^>B!brV4Swe3NP>o7{joKp@DJ~98-y;>BD$eZAv+48Ls<9WDZhW+wrz3iJGcp*We2CEB;Qdv7-{1rP0Z^z4=z zgc=iM&C54t8et>Rtw=?0Xg$zmkY^;O4wFGt^X;ttFDCd`6%uk@QI=8JEq+?K!ChcB z_&mj2R@8Aq;O18OXoyhJl*!{i4W$vavS14jfza{ig73)P{PR6LPvH{?hPZA6>0-p7 zz^!-#d*X`+q#|i0sf|?#pCsBPU(`1eB7I|-rWz!yJRb?bLOm7}-R)T9k;2DG2b)`apK4k;gEMeM{J3u}F9R#|F_808#WOUqh68Uus zu@VUg$F@?X#Y`iPp7e%!_-HzQZ8}a*yk#;9P`3dvPo2{i1cFC?cYyJ5$_lkz=Y<0} z!=ZNXnq*l;??k2yYmw$0_Ox8QCzAIHf~n607XD0+4^&bcg~ZpnCAy(ll=Bd%DSeJ@Uwvs3&n#%y1pWD4Cx1KgF5wF@fant#;lzGSoRB zLWX=FH+Sy9gKaDiS#uh-b;{DQtOIG6&lX8{{+EdV>$FHh6%mFH?l|E25P2SVT8YLxvNc=h zmPkk_{eh)i40#bB!TEYfEMxWRCWRdl+!{2_%*(l}z*J|3R( zW8I#kV$FP=lfLcWp?%7Q1ZkSE8;=KGAWelg#2Re&NebCx)s}5q*nNoi(v^dcUo*8% zzuVlt556u?6JbEr_KfB2V*t>q`Ai-iby@(DeNm743f)VK;Kifc=SZbFupFs3)KtBW zn*u189;U7iJ61k0tcAEd)EbH15fQO(Ge)nDa??A`qC%o2^vic2rvBXFgi7c9Re{dN z#hG4#ua4K*Shj+}yAdEA?U`0yM?;^a`(V*FEFvUih&Pk>dm@W{|I zERZ8R^CRi(6#ktnmpecC-?G{Nz>g3+CE4u$B`3Ei{RbCIBvg301EQV=8r9cz`t$Ac zxN0dm6-8b>ahlhtv}L5aGRjj6a|JHM=C8{!zYCUOBq~rltvBcbde?M z#P{Ai-7m~Exhz4Ad`BBx?aJ9d&q@Iuh|<^mvLgZK%G#2ktJLn8;|E;&Qrg;(Xupw( zvrR#u%vb}}3HU5aBvg6R`(3$_oEpRkCm+V9lXGO6^c%x*Q6%}r5&;<*&R(vNlIC6N z_4ve=y0xOIh50j0aye^$OM1fZeACv-(|6gJqwQrvrORE*08mz5pD(9A#)V3#G`0cT zIX_sk_L2qA+J5ek`Ki?=+3mvdwrVWqc|2c_%cB5NG=NPxd+6Ul;Zp_HR?0MKV5CXR z+Q6!o@2b-zV;^WN<29}+SyrX6=2>)uE>Fl^PR7zzFEgbISFD7`ce zRh>lfiQ8p-#keRVgE=0yJa9xFoliY?jN0dZF~8G;OSe5JmvGcQP%b^LKM^++*ZlvQ zw|D!BPHl=#nUZ(jtAF7ijzDj5dlw=Kgs7^z-Rd04l%Q;X$OUQn(`P*+B^tccr%3Kp+@3nIlsMM# zFXvo(m6|gc?{rA}#+bgVvn6*xyYGn!^=aBp9I8X|z-+hE>Snj(RL7lEo-Esv&5BTg zj1a2(VNw74$l%c*Qc&V8gA#|!@`LA`^p82R3zUGKq}tF|`N5yNyMq$$NYKU3)l5>( z*!Ts!i~=|L93yC=)H|+V6*>pCD3-xB>zls(y2EE&%;io2YsudV9HnbME^u{9^)5$Q zNXDnOd@JYH3H1PBSfbK&*FL(8h^)ls_%n4Ey@}8uw0YLLS~dv%e`C9My^0CuFP*~N z5)5rru2D|&3H$NSGXz^w%AX9n-EidbbybJR^~k0luVC>FaB~+0sY?5kUP&Z~z9qjH z4H3)s1hBd)m;}wbH8mMk66wm`XP%7Mk!Zf+F1yc7f~O72ytHCL*M_cX_fZ3CiALZo zh@hd2F2Tssw~kUS^b_1jPUu9@X=$H9q8vfrpn$0^RY8eGdw~Jp6(GROu4PG9OFRe% z2-*o*`lsv=yz#aN9lFl4fViNt^Z7#Q1OqQ%>N*9=OE2;SRz(bIp;YQcFh}X=C0{l& zOnSwqDSeJD&+s5}yLM+pE7+i=;zG!1jq!9(EO@PFXUuVKvOtaTgAk&RO2J%M-XY36A6K65fAlM$Drl`d>lUEG zMnXz(E_5#QK*KV8p+z%ZstRW9-2;E^P5F{JKsh+(AhV_p6^g^;j9+38eg9M{nHF-+ z*mn47sContDjW*Pb&Axn&JSz7Ox=7K^uN{7|B(f7stLZrE@~+eVJ2JrO+sJ!e;Ya# zn3pIBnro-Wcp35${JaIaTFtTx=RWc1XH9M$@`WT~H0^1(FcKv;5&7UER4s}zSxLrU z|9}Hxv>oU-FthdYTV_fwlDrOLdRk(k6F&)U!zP6Xug&hC0wUnle@p)4SJ7Esmx=Bx zA2};03eT!DF630Ms9I=;-In&Ij;IX`t;RSo&X)680&zg7=zLOHV(F6?yd=K4-gH`} zWKZ=0BfE0qoDd0Mu>ItMy7WNC6YlL~Rwtd>C7`0x?C7GZw5SQ{x?E3hAv|GIL+Bb611hxXBS5rYVfQ$hgZ+INl|`bs z@hDV}SpBqruhPNbMNiE`c=A@L9^Gj(LI(h)1G9TWNJ;wV60W=Y#74);YYeV_<)~AV z!UW)$&Hsqj|8pz>cz(X$QC{4YhM^`2BClE=WGgcM7MH?!webHGJHb9yuqgC0;9ZV> zq{cM$=Ot51r)!i?^Q22g5z>Na)geiMeFcWfc{4va*xv|AC6X5Pg@Gv*^X|^ZMRhmD zTa38|q78M!aH=`we+fcuCMkUKwU~Dlmw;cg-<7qryNm*+nteRkG&cji3y^Iso-oJ< ztVkvlap6R!oaKNx^i)mAFLMBr8h8J^99~*#5sH)s4T+yaNG~mHs}2aAx}@Ha$i~Dg zZELlgdgx?m5ArNM;8Yp!25#$Ok1w(BI_aw{6X^4te0Yw#<7>PG_`Zcb2%)!>mLJUZ zU6h#^bOms0QffMTF(9P&R=`?eH3WP~-ZR#Jr!N|WTwqHl08$aJ?r3L{wZA*SOJ|)^ zsM9{LEa*f5(HU8inWp~_<$SeSdbP=XBsi?fB)|Wi;jnv;Wj;&*3VgE=LXd~0-HDL5 z@i{XSZt1Hy`lbtJoTVY!kKEgHDW9j4xZayn_#|*dF4b6!!+((bInEIkRC{)o{=d#A zghz?QWq4vmpGU$TPCTx0l1n(7EbMVgtCxRJmRr+~%R1^5LMtjrNYH`C&*P@UPkkZZ zRr!pIFp||`oo+15-6#^sS_L7LRgOFRhLnxgeE!vs+odAKfz+;!DP^=+781&2PuZo5-ElTsZ+{ zuOyHjrgJ?IgZI+9mH5(j0UPBfBYEk!neC@HYPpRy8@7D}bl!N|LGCo&-+gJ=k&iphYUAHB%KRX& z-}M(3gM|d@QF4?RJ(Cx=asiKa`C7$UN?#!vOX&P3vOVF73^^ zws6CI(K$-AG6zH>Lyi~eZ~t@@tr!?Oqf81qFNJla?vRzp8z%J2wrzTyEU1XfCOd=WM3T8hZH0jmbjD?~D8C&qp6MRR z@BL(6sWPtwE-1bFRf)EtsJwHOT#3A`0rZV3)Fqn(e-+kZGN?D?B!!XP7E#}3$fss1 zFkaW_6MBpwDT8#e6P!eQ2+-9w)oY6E^|AxzQDU<0%y$fm`~k6oKq2kAyWf?av8QTF zCDIse+>B^V?a2eN5jk$v3julm#$Rc+<@18fyGy#wGRGd+dRH#V3&+`fW}cR+p)e9@ zS9qIF%>C?uF+|R0EVI*m2`Ovy!dxhXbrF~%FFK@)O1<9244K_~p?PjYp`heO{S#xK zQPs5*2rL+wNY<%ILkurO8;jf3CGwL@+4gvsSk9}-5AZ7wx>Xbgbc?N=D3y^R0Ep=h z9`t$nvE?PXA&JI_rmKI?X+?F4OT z{eSM=GMk^Tgy(OgB78>X$q>hwy+$sAavh=b7&U>f-k-Z7nPhWU(McpL?j}TD=*_UG zHQ3I3B3ZDBf1lm~l5Y59HqzZMu0^>B7kaa(-Bm&^dHl?j2QQ@uSiAy~he|5T%+_c7 ztTRCPT`p<=>^v}XO8rhL76rIWHbd792{q-#`8d=x{P`gJ8=tO zb$HK1*o|RwUz)f|a36Exkgt2Ixctys%j{+92^4S*Y3=699EYn>j& z!DOy)F$pPcWBIck4wetPII^z__gH^+*#O9sKIE?FBgY*g8Dj^YX~TJKV6J#e3eQOS zeAApggP$oF$?il%i~xMa0I`m}F$c z-jyBK3?UtU=ImqA2`;cvO}2G&-A})#LrR7t_#pq}Q-;FHM1D)%M}bDw5%!?FsXws3 zvXPDbMj_pCCq=Rt$G41qt+)W6K}mM9mdfx05m;O$Xprrvuy6|w+Yq2!vYUP>q>;H2qOTC4SIzw0Ntan}j7Q@?<3DYt^4 zfCfr5AdJBxF&kpJKTk2rI0`mYX{IlG26FDov|pRZ#x}uVUh;}JR@2?4B{ybiWL*#y zsZ{4WljdN#9mc78di4AC9T83=5UQ!nf2zk zRX4Lt>S*@Sk9`e8SIv7;9i-vhwCX~@zk<7?#Wog0^)R&W>h)WWK<@4COI3^G>@ zS(w=oIM^8I{e?ZrQd!i$(dfUKaMd&B*%SAqf-@93>$HM#K4_>%MK14FGVz=y5+M3z zX7V}^DdxahOq_XV&IF*#3UK~x6JF|Wt)wR)*E#aHtUG*t^4Z4!4aze4vt)$@|KTs; zaRMO;8-B8W;$6qy@Mn04jq7q5DvZBf8;drvH_XV^Jz$Yua1^C*vGLYZaQE#TrF0RU z)-w?>K%frU-HO-WkXO_|uc8}cRwN=6Mo@p(bjJrGwvYpGAtzmTV=q)2zqz6}950}( z4*wwhC{Xoc&6_=4JLJxY>yNzKi=1rU6QD&M>U5iE&|uY_%#)DuN6_Tut6-@jm@*L% zD2XGlCg#h`7z1D+?FgxKh&u3DpFCvCCu3P}SzE+C@2KXC8{!@Vmt57BUam-zbq|`U z=|J~CIlL})=V9QD^gV=Q~2=yMo2?h@A5aO9lnW4;xZR+Ch1X& zl2CHx#V%}&%%M{YzW)T16)B}ZNj+x3t!vkm8W)wZeu4EX@%j}rI2YARoqEAwE7rW{ zop%U{2U2;($hqx=4$_Zu&dwViA#p%lh5+>t^u*3fRAcu5PECc1bm)IuDHo*CG>(Bz zRFLhDeBl&8pd4(KdG28Vf`mI?%Pa12}F{IK6pQVwvA1&i0<6_H{d?Cs1to8X2P z%G-x^)G5OuIol7<=^?tiCSjLm=tMKTs>AB~3jusq#uv>uH#!d~G9e|wjN!I5^9ejpTrG)A?bu}&6&jAwVJYd!lXO)u16Qq#vS{Etr^9EjYs=k0ZHdzx<|#jPpjE!4DVIP~Wwy->)-9!AdgS!>~4&%4DUN(k=|9;2!Vhj<7G)YLin!FnM_ zs1b5NbOg&tN`#tk*4?&oBFyGO{kneuEhlP>751(Pfh1~Jv2k}^6?H_sRiuwTPp)iJ z10qNH12?G2&H!~uiL93Br-bW`#!`WBF$e$oc98VJxT(D)&Zzz=PNaK8)Y7KaDxL0x z41Qy*y17&OSnc=Ds4eaoPEcy0BvGRL4e>wl+l6!J^Tq5K)Dqi|wAs*RcIYyDjTBJrIKxF+n)~3Hve}Pz{2E(19lfdP&P@125X>m;(gUZet$aKHePd5>brUr3x|q; z0iCFWjIv9g6^20~lCo>bRfr&$(nwxORdN|`)9`k=0~eBdp+U9dlbL-p^^+W{AhpLY zPSoCma@E`(8+JehHKEuaG^d9|i(+~e>+cNvQo#qzMFr*RPlFzY>(|RW(_zNDNs;pV zK>%$zb{@WVXK69b*4O^6Z78DlVAQr}Gydo==Jw`*$Is%>LEYYCryfYZ8J-)^u4c1A zb7`M^KWbPj70<3^F6Q~7tL;KYwTJ1Ai*n%0srG)4nLDB=yC_YO8-;er_Ql0;tjvUO zR-zA?R*6HFP5aL*n3T7)I``NbY!Un|ky&htD6(PDy`*FYYqrP)Eu(R`rN)Otgk zT-k(QgJ4V?d3t{{yyqDV^>IZdsI_KmOSAclq7~k?c`bgb*U{3TJY#ESp2fP-=aDhI zEld`6*x4#$p$i1~ECMr1mUD0@Ec`e!4qDFY}%fAX6Nx_+iWXd zA)^QX*R=@WeEl2h2>Fq$1GL=7?qt{WZfF zI==d}u;j||xa(0~oB_HU@2b;t{gYx5IEd?i)}j4M7kRr+XODQ+ure=W*N z`u-!g_A@}qHrGLj@$K4D7jPN&iX)7j5F3rFda)|T((9mCBfty1Y9+z)8j>E#29;Bx(b`;zB z)E!2nrdD@AEuQiY#Nyx=9JvRUpB*W|7_ZSQmbu_l-Vbrj3|wV{4Vn(l--PJRN^)Dv z<}`4ST*?`1yV3%VI$?2Qr)2Mza@b!J@L_Y?`hFWuh#(^>ESSwd-BOs*ve&fN=s%#n zoGgdaE6YIcP83dTs0KW2S&6uj@GV2ch{rLMhvfxSF)ev*LcK}@FvxP_5)VBkB6trL zE}2S1w7rVuTc7+8qpD*R0y!OG%B2h!I_$1~Y^W*dvC~~%s{*9^rO>!n8Ew21Tsi#y z@SJY5s7gsqZF;+?GE;9yTGao5l0sfd74^CEPcDg^J}6<|k*}XnnkNFS=dKnhuwq2# zm*GED&)PIkkDsfb9`Bf18gv_QzCQss88F@AbkTp!X&;cwS@B!CBmB-e&AohBkdao~ z8{8lG#DwEMlsy@^%I5}Gx6QQ;_}R+PbO^&M8;5o+Jg;{6*;4nM7UP4Nq%ZXNjpD4p z{%{X!3=|kXva=oN3U7HwOTpQc?A5$O>D&Z2Tx3zLkfVan21t)E1{o9?C@~SrHAm{o zm2l{xKMAoyT|CiLMaYYjao~~GC5q?^`q2LXpu9dnPaiMpJ``WPi@H4B`2*rH*V&q% zD?Pw76PH0&9QJke-8S!W+v)h;j@GG0Y{=nPtLwGPSE{DoCN=N1`L8cG4f!5XtD8AH zqpYiN{|-c$@_WHtJ-=0j0bYjv-Y1anKHA?i2zII6`qe8FttK|}Nj_}sG5)IAPv2qO z!Su<+Ujc`z$l$bU2RXZshjfySeAdJGqhDjTN2>D=F7G3LtGRAVG?%a$6yLYj&HEfq zN0xVFKGoiM?x>#eZ+{+ws^EAz9I=%tJGYYgmZIqdZjTiTI`n%y+6-*Ax0 z*us(uM@GMKTAqf3FU%v}J#!mUnRZt<^=I8~eu{M*3?py%c6YK%0<{^ur&hTgoErP_ z_7dd%p6@Z&yv;4YV0|qM4RS*|l*6ik4ynQ7XO)Bn?`-`B0W^I`j4PHKJbbrX22mMam8hM;36mS3!mFD4V9a`J#9%E`~stuK;Lba?|e&2|!Lr!4|{w4_%U*zK1 zIjp(K(5m2`oN0(GUsvsYd-1K^2Wh9yYfXi_6G=={NB`JnkO)w0g-lf6F8Y_+X!B*w zm~?@?CXs2a)@}lR%;&X(qVvWanHi4p9!la$wKRzi^5>QjzNWH6Gu318u`WP624@n; z=n&fDMX8KEWb@&3%`kSMG-EkJO4`vl38m@As0(!OyV2MtTz#c7@~x$|lxk6d{-`jd z1(y{8jqssRxWV7W>EE$F)D?lT8Y1zp83}@)zuaYdsR9D~cWEN#^DEofWQ z43DYFX$b=i{ZObAlnHb654=Ju z9*webTldFJnxM6JeyXDSD|<-Zv9Q+l#MRxmn8W;7d)Gz(*0Cmst*!z3mdw{di~-{= z5&~cOGWhpw$fAbpk@fFM;4@NjB{_QWJ?ryL;IoREfc?zHdaU$cOT{t6q(UjACEqmC z9hqi(P&F8r){<&KFFpKY*tA2k&L$rm zC3?r#7V`@K ze=>~`_rNH|erP~;oG4)t>ym>kk!hk>rP6bT^ZUlif?9?xEJEJ2Rk3~uINDN%EufE_ z1%N*3!28kDN)n#@S)+n_;zh+t+1pV&qd-ZNcXzQP@r(t%NWl+nU-J8=Z$lS9W#uNo zbpw9gVFT{>P4Kd3F0T~Bg$!s_@LxzAap@bgb;l^gtIhsfuwfC7;lP;{+x<%*xpe1<~GHas2d!OAvYEyi_Tt@dN;SN~{PF*vYc-bX6; z$u=CE0$)`qtebQiE?F!`AAH-IS4Mk|AHt?e5&Ddp#f~qyn&&u-@TO^~qTi~JLGk7* zn~&_}^tp!v25am7`wO9;=L$M13fv;A@Zb-xbR^Lk#- z>)Pj!yQ8O6YPPk=bx;%DZ?LwluiR*%KmC4@I{64QxzK&X$U?sKE*Ku1mb!=1d_vH5 zf0}aay6)Na`!}b>3AXHbAvu1}Z~CK)pWgL7-jLRE=lR+pzRH z{qFK#o_q-x_|7)eD3))w2vv_Uj_?4sv&X|aIMKJvnq0>3#Ab5Kf=>Halxv4bS~78J zv0dYN-?p`uz|>wW;8yLLlvwBgHj}Y}*qT`e8(QC9I~Qau z4Oo!p;9upbBVR^(YKXHE+_h>Vesi|jK=U0PDqf0SF4=&;9U3VuJ2=b&^eGn=1AuGg zE2#Z^0u)(!q?&vHb#r9IlD&sL{pO)l!)8m~-s|vNgBZs>ax8bGX~+m^I*bRi7py7> znK#OpQ=S((66kE!Y{F(IHr}+vBm|d>(@gDA%8%zf@36XhO!(+bar0o#iO%yQ)1sQe z`*z4~pL55yB*jzHnv~&>{!O#kuTaP1SuA;gS*2lMXI|_cRA2Q=BI-zuH@&)Qd+o!r z6yJK|-k?N%^L2wkC6~|aJ$KWE69;9juErm)J{)Y=9!P%Zxg!!c5XBQYJ{kzvZ@H>z zH6Bs5o5`8(EwX$h{ZvvsApMVFsY2?Nwbiqr>d&$5GJJqOs7?9=RcxKG7z(J@VW9Y| z_ke7hz)1@laTdmH1ODc>Q$O`0%@8}`{*iTD%ecZx1YR>%G#^mxU#dFFn{_q*W!+y3 z$sMiUGN}lzk(-_T-(wEf>z;h(Lv98GOdJU!qRI&4bH57rK9^0FE3D;j+82%>M8lkT zoZC!%XKi?-B!yvzhw+3H%=;6U*}Fq=l?o#zt0)q>17)F<)!5xCuI>Kf`ibC7voUJ9 zvgoBX@#?oTzvxoDTsu4Rq3-EB1*j=ozH!t($sTT@r#c-{rqw8M6qM?DOY~^asDmN- z%K>{loLv=N#|z!plO2v49x{-O z=B9yUk|x1(8&dI$Gff97|pvv_zdd-bUTWO$raoYeT09?7%Ft0S5$uw`b-J{6Sq zE2h20dZLOlRiw=9YVHqr@eieDKNP1#JetdHPA=?uL@N)IpAAgDFTtRXDbvvr{E1Er zk1=*GV;R$qR<=c6{}ICB^DV#MN)-tQ>jNE1=H?a3*UGFdlbI!3!hLJuxeUJL?^lFbOypSqv> z)BD9W^z^sL%=v{82GnjPcFC3ZEg^hu?OYbSjH!dnR#W9;FKscG%|EQE-Mv-TjAyM+A z?&fo0n*$$QIg!uwTl4aZ5>HVSLUAs2!%h}@6xq0vjLA=X2QL3TytUpfJj!zgTC(lb zN8ap-ZMIBmF?o`R?5t!=%6=35+PC$qaGXbZ9qYSX4b`~Zm9fb%9*|xVS;%Mrge$>zMM!wFP$L42*9Zcj~s@k>4-R6UMC203U*V zNTE~yI-F@42tIr2iWrIOxQFZU`H~!enYNNk!2k;^2$R8z)1_SISM$ouvi!}l+)uAr zavw4uLe%>!ajEceC4?s?FN~5pA{)I9qWll7(vQ%v!|AfwNaZSe`EoqB|M7PEm_kwF z?80^U2-BM;94vMRe|N7>;^VrX>G&9u98=MRmfQr=KSZ73wLxM;`g>c#VA6 zVG!5U#n-%0QJ)6CF`l7J-j_m8?U_}g_$~^yad51YF8<8Z1$d2+ugyvaety;SjrPE( zt~GK*CQIBNQ)h?FIR4Ey>BeeeK)K6@9Ogp}3e)B~O-~|Wka=O=IW4k7!f?0r2TE?R z=S<0kC#_Q*QQP~~k>`%B(n`Umy%7%ES^x0;Vw&&z8DM03Tl9f7hT)l0(CLqoJ&&M} zjE)*st{<;1h)hk3E>!**3h)4^BA>&i{?3{$_*2S?zGp`<*tB>QDyb3;o)HjSqsa1E zL%zzY(2WgfmsE-kOY$IX&OOm6h+>FFRP}hmK8ixNc}(9N8lvf$ly3&wtGpp+-$6Ez z*#S}H!c=ZG>R>3)TMZ@>q2Ku7&4jhk8m%e6xU8G7$T!+zNq{l>-*(yA)nE`sNIFB4 zzc1pO`(`0JGP@nx5HEy%&FJqw5AcT{?rn`UPEAb~Z{bw;2Dn!W=MT{SnTHlficd-& zH=2|a>KcV4^^8ToV|!xV{8OpikY=@dmwN8rmDJo5IEwhddb*hp?0x_G-y;X=B-$^p z0Pas*D*bIDc~tk9J~l-#EcWuAXwz4%NfMaS%o^*)x<6K29LoR3r3cG)s2DK3>j=Ga zP$_>LRn~nj{kpzzy&Lvq52jRlSkED%1GWIZyYU#aK3cZyqYviMP^+K^W@5^%s>V=thg#LGp zykVXy^R|iDBYE|=iypD@vYc`E4g%ET9x%;}y_+)Ql4Ilj+8I@MC4q_4GM1f(9O%)& zE>gr?tn_N2?1g!9tlynM#{ucSsCwaKpQ{4R!U~z089Fy#gzsgVLdFVs$8_T;gYfu%~_VDW3>SgN`g2NK7 zEkX?%h23PP_x!S1fhT*oQKPtrC00(Gj2PRwCTkrX)5-bH&2L>?+Hmg?6PNp>lR)c# zCY^3V1!-&V{m16s=>D--wp_2om9`#dfKasQY^WLv_ntPUg*V&tI*W~Z9~m-OXo9|d zc=fm?s(=5Se-6-p+LbGEsj(k&{8-ZqL94iXwPuuR0;Cv*1_PfAiKvuOf9bf9ET~Ug zjhQ)oF|Nh@VRoLzo{OxQ zmJnbqVKgq#XO7S(k|-c*hK7t*Hosl=x)?s}P+I3Hd>T|hTD#-?W%lVWA`3c6vR_hM zi9urY(~uR$z^#e5@pN6IR7*J3r~eqhYNjFq(D406F&#y<{-6LR^ zL#>DQ)(t#Hw+q*pNV)YJhCt5AXHLaaGlxg3KdSXb!iy}9+a!O+43V;&*7MPvD@88` zC)}D)1ofe8;@UsE*u#~DWBp4>g`l zSU)z$oygDUerfIJS2dN{Ere+wXH9tA5`vw0&kFtaa%2O zb)+>;gm;8noGh17KUpP5f{S4Bs43OGZ|z1F3R%u+s2S}wB9>8ExUP{_mbyo4R=wLK zN4XPS-y!5rHTgXZhFm|HE%tZZbt`YTdO=FDNF8-b^8QR=lt7oh@03>9#G5V;Y>bO7 zd%FE&JMk>x(q+cJDeVfb7(0%jGydber|fwDJN1%HmlMM#A^+i+=6jPlmDINIBH*iT zwA%eIS=~O&Y@i?!W;R96mY29^PsuZqT|>X@!z>78=Y-hg7&EIE!`S~SZx12wy#G5E zAf(u*;Y7yW1rlwtWA>%uWve%3JlXq3X+g51Y!u4oAE_G7$-afF&DT5j*>PMK0Uwdb zHXR{B$Q(&n<@locwyjAJ%8RChFDG*1u$ibO5&{5|B{BiT1&X2eY{F&u(%Y{+<$|xz zo`$(sZ;~fwm3JBiO93EGZu60gCB>BzhtoEzc;FOr*R4e(^46{_it43f(vg%wkAg;} zKm}{QqXbU1i5cjjc^2SYX6^%V^9)M@fgR?pI|_EfWt42%)L*u~P9>cF!_$NDmCIJg z$iJY6-Tss>f9;?!a`kB0t@h57wpd@}-4!;ajMU=UboU2S84a{vOW(o3mg<>V^&zr` zk=x+g41G{gB+sUwTfjQK|L!!GX8n%1&rEhoWy_^#`3l6TU8<4izxO-M#FT+#$LK>@EZR^@YE|4Hl?d_)misy7b>3T=-QiOx-NohWmb7+~`-%alPie zdp$ok9duL(#i}PBwOl%FP$+YM@vLssG>~vG+6py4J|IPXD_n8+=49L)IgGhytHM=c zZeqmtVPDrR)N8*31x!)n7-wd@tMBc->r<+j%`iXo!Dqo{o=l@9l0hY-JvmBA{6OPVxi=MEZ3lhW!dN2nC z;94XcDbyca7uoK9)s2HPhca=dQ`_0^lY0UBmJa|8G%zUHmN_&SG=!7XP3rer)(np? zYw*24UD_2|8$XF;Tll+HJz#Mr(0I{ks|HYGOc#OQDhecFK$FU_Q#KvuiFVP_&>h>cdahQ^!Ie3<; zO}Ro9P!M?L*3UDX^KQ&-(_6@3ZaE*UwB{s6)WACTy%3IiVQ4b{3QZtuvM}`H2W2f@ zWHdI!^IsdIko~WXf9u58Y01H|e~o~~D7&|=_A`IN);3PG-lV_qzxIdAbz<24i|b}H zzk=dnaPd|uO#+oThU`ZUX&RyOxNV2{RQE%VsY{EVh&iv9ywh!k^LU~@M@n0N{>{u% z5ps1A8*Gb2LIeC%&gU^q-?&7Pl|sr$A5*E}SBUWzqSpWlB4FY5LsK(dc>m3t0s@`c z%%?su8zjas0n)c{n2vvl_JQ$$>P!wm$KGxpl&YV{CfwQHvo?k+O0Ao}Ztc{7=589N zo-;$e+DHyl?0kaCTrN@Fb9@(NZf#aOP56cOi(SbWYV^))s;3mV5>Vi&{a0T6X^M^q z2(RFfJAIDVM5@gcYFDvM_JEPc2FJ5tl))7R55AWUM3*(|n7k#UT53Z$q4mT*YS(4C z`I}k8xKEQVuxbC#`i7VB*b{E?(h;!<1TA=Ly>Vq~zNB&2G3r5th5e38=O2GQh8@6H zXL^{sU6^&6VT0M|r9rVX)>HW7Ov0*S|03)=ObL8{*LB?{6-jvFP*=q`vfEhXt$4K3 z%-?%^zxgeSoch*Q*`dyo&L+Jq{pCCUgIPVPDKH##s)o%tNC5v4cTW-j(d=HjWk>^Q z*+5dq1X1^BLWT1_h&+5IGgkq_a)){DkKmVuJavPdgZy&be_XUd;z9i1(R~-n2~FNngajTVMfZckpCK4uD@L$d&2pJy#vXD z;sO2jQ<<{`eGM@*J!BBGZpilNrcMbKe}-VUgV~~@mdV@fnYl6&*?v2%-|;>r#$G)5 zeN$k1Ft^p__U~wRe(-hrl7^K^W^leJd^IaFUEW(>?oD~-eH*LrG{+}93;|!baCxn` zQ5LHpsSzeGO=EHC0mLq87k^erPn4&)!T2_>F^MM2Sw;92I1;9ht_^!!No5}uZxdmy z4E@tRE@HCW?G7|XS zb;{@RVtxQ{%ceHuTY6KUNDrEa6b75>mk>4c|IB|$sZM| z2xZv@D%xT$v>NKOoX?8Q<3BF_1+~iIN<+d0^wb2>?rXXn-mEiH`aYX@OtInh8l89h z+V;iX)HBsx{B@E_R5x8{zR^5C9YvQrGPmw3Q#<-DnjW0;cvR=a1)pM_d8wk&X(mpi zqDw@#{G|f=j)rj0naII|u(zRiKAw2RPrOX>B3`}opE3hSd(3v;nY%5Rx;+GAT0C4H z(!h{?AVI<^!sUi*KcIl^pyrEMw3QB z@<3twRZAF+6r9f(2iR-ZN0s??tbJ%5Yp_h-HIClnJe4BMk#MpAXR(v>O0Hfg*9}hD zunk^;sqwpx1}?MiZ1kq?7*7%vI1?UlJD~xt}3ePWHOJCwj zSM5>$bD`h&@w0kePBGS7Qx)*<*_?0szC`fB4D+hTjfv6fqEwoY>7g*#&30zYM1MGF z(ha9yA0m=Y&gTKBdbfOp`5-p~fc-?~+S280D>s>2D(!ESx95q6FE0p`8oA-((-_3~ zzmqY7UE*;<&%!Qjxznlo25pR?p`U<1`WxSQBEXy;R@{B+Jwr(9xKT=<2QwV(_6bH+ z*ye7(b=R?1JR^r6PZIigx|i_rw4ay)3lne!KCV@>y&9$XrbKU32>KT=oiU$JZBAD? z-2B$+Uv5abqh!0-Zk!8U6zcr0Lkw-#O^ z0^gnIHQ3t8kQF*ytccnP)?;Bw^9P zQGFcw9gA1E`mudc=sKWE|H0cg(8Zy3ZvpEPNqi{V;3lLGy$cOu!ta%{|S z3VIWxJGx_w4>pCIKkGot2A7{BAkSAMb;$28KKAYw zYT#BFFX=2)7u>kBxwf5XlV!hjHyx+{(~c?+Ff^<}0Eby7T2y6OhdYUl zPm`tPUa|1W`~8_85w(6u5|*H8@Hx!Q=V^xi?v6{rR?w*J{we08W9yOGX#H3Is#dZY z%B9>Cr5xhjBbaxWZCSqCqqJZir9OT@#&*$sGaL^f0ZO_2gv9h!sY?nC0jgPjEzHdM zV;!i(qBwkvPtkO5*D&)^FK9JNzAb(ok-j?%z-ns@Rk~D9$QvhCuet=^X4Qp^l-9B2 zQ#hlF8I3tJj7Y4f*|G*%7bB?A9F*DnX2so^A@av2^T;PniK0YVI}$owAJ z9=PERVslr#1QM~)3w2{f@pJ{z*HabGX^X#>gIwBrY&eVjqi6u_idW-4bVl_U0JYLf zsba26wUU;rL8`Tw))S-*iDe}Vtpi)0gh+#_X8U;D$fvXYR9{r|%lO#Alwv z)ob1q*Uo9S9@hkX;z7}#P(Rz+s6yv~oRGEq@-j0sl>{{OW%#*OGV^bZleJxIJbAE` zwxPV9ubT2a-nPFaRevR#wZan`sMgx)69=hg+2<1Nz-m&+oo!tl-SLmq$MNwYPJ>cy z#3OxQ(%<*@d6=MLVBV}G1o*^G>g5~tDj-;YzUid#{=g>%&T(B9mO_?pDm!_KMTwrI z>d41V$eqeBV5*wk!(tbc0r0y=+vz9c!XCq~?%H0lypkY(3RM4~d&jd*U?N|m#mA0J zlvYuud4~*g%DOIc8;;|Jl?EQh zs(1~2@XYz#qm|@C8#1(8w`N1sQ`wk1Ludn3-2LC5oZOIYX z^(jTF1Il4ZzP>WJZG5teY(1Wcwov-vaMO2>+pG1)RBtj{6649MV|y%jrh-S`YL)AE zbops?%>0i;=BZa=d^OH|G?FnQg*vx76M#$20<zEVvdL=B3~Nh?F@Rp(F|o27EVifGk&nyM(B-&t=1=KM!FVaU+9MJKf|UsCnv9 zujh`pPnLgu-as&ExxHUdg2cqi9e)onvLuLQd zR{{j@l)01{j`#qE$ks-4@Y88oCp<&8K{=U2SR)0*SY zha6qbdTXBaR3WC;?y44Bv9BhfW}Q{>^qcEkU=^Agm(!AbY-2G~zWCvk%Zeq8*Nw4X zZbq^-3|>j-1Nd0^gHTLI#ut0y$##VOy0i73hnuZKIhe*ADN1?7zy5_ihP0cP?DSGW zuj-Mclp~qj^f$a#e&jP;XtDA2pY@(QkR?T2l$_Fc6~DqAojMgC-U(-LIx6>;N~z~4 zAWGJ?gYPV^(g*Q78|e^SRy3fm+Hei5>cN%PZ@_nw`D3!7EJ#8HohRFJ2~xr3*bp)` z%xMEjnPwyW22g_IALW}#v7)DZ!=>L29svteF8ltfJp2}Kf%4v)2Kv_w0(soq0GJQV zD#$hlNGv?Aq6cg~@d@U<94On*Q?barU^8fE@#{as8^V_PjeDTDB>np*=H4!=+a1{b z5wNCo-}(PrTS;u|Ujs5eORi!hUY!U97qlnkOF9=kra{~}99c{75T0*tdU(g`NkgO4 z7fHGfke3*_FZpksL1&H$-@7ldf+8R)DQOVSWrSf$F7qDZ_v{n?qQ`B|FnsVQX|ppQ zHL`Cic`crq8F*$Vb&0Knt%C6pz64-0yIn&R8`ISOC!XeuwB(TVlB3AQh&x#6chzzp zg%gH2hNRQoat(GBwXh3bD^c`3)F_%9iAja(d-e}R4ZP6z8=`T;mw1$}e+&WCtuN6Y z3OPP!mHh{6?1h#I(KG$T3raj_A4>Cn_1t9W_bmu{m2Kp3eiZv0bKuslWBOR7;*!sI z$LRc(itaZL5-XmLRg9RxnYefF2_8lp*}f2Z67;6sQy;#ZbJL`m1IIs7yGuQJWgW$- zQr8*F2&ujXiRF(2O1S7;{9kD$?)P|KTW=mJjPb zZBYlnZo;Rk&qv?-W#Ha0{2vK!VngTmJ?DGAF-|jnM96yl*J2V>xfO~F52e0S{&W;- zA>ckNCnjCRgc)Y@CS+YWFx`tmA}FNG^6%l*XOVcv@q$-5=5{bcd-7)>k=2qV^K)6swd7G}L5L8CzYVWy zS5t(-gmJ16s|uj`${^d|Gsj?z=T0xn*`BBD`yAc3_{8eZ5JQgZ%J{A;(wnY+ zAmfh@Hm3Y`ep#%oN@ql^G15`o{e=S!{B8#_&l9I@`?&l@1kC-O!@Afm+Z@56Ptu&2 z>^fk`eW&jb;z~ie9=C*7vkp_3UbgmoavCl&EOwr%Z?boNK*IQ~K7b4nq2#KV*fxox zPSEdwr1KQ>_2~|7fGh=k@kUK1QbN)#+9@k+sKV5gT<%tpg&pM+$~@|wM%db{a@4XF zH;fi-jRxnF*V|vWQ1L%6yOTnIx&U|u5ca}j-X7fBAG6@_Ai#&B-FIv4jKw;U-41Q< zBDUSkUQ_wBeluW-Lzg97oY~J)j>Jk{(P;L#d4~KEAQo@t(vG-Y{D>Lo9I3L^_D;Vc zlD-+`-;l?3c6Dd8@f}mGM65quUNl6NDp);KyW@_$7@xZNsGGTwm26~wP2JE2y=msN z`c}GzlrG=={>fmYxO-0NgW7n0-w%NF_Nt13bybiORAKbl-`90vUtS;VvR)a z7suJyyw=G&L9kRX`7Gb(>y2~Q>QHoS2K)Yn*BU;2@}NXf1t;~U&5P?~ zk9c-!8gJf7HRK=*aQ)|dEbLluHR;i#0Zx1h878wQdk9_7e794X)-&OD7t8O{va~Ps`dvty9-8yr0ZJSXk6wLsr!R zeMM1E_OS65L~}~qoqE40lz((Pnf1uq0#aGufXr*KXnAXFbnM~bNgV20E;{!2U(I$L z`nL;o64)M>gno*7E2B{3^6l|i$fF?nv_IA?zqLuAwmWurHs?SHF$jR;ZC8K~Pb7y8 zH|FsI=_6}y!3!D0+nGNm(-$GXiVI|Wd(`y3V`ip$xn;+kF46 zvl{ji7fr2;tYCZIOYDl8BzeWlaPHJH+>Q8P0(RI0dv4eZn;2FZc@#Bb4N_f5uzH6v zdb-Cbshu_&_low8{8v8(cW%++8jZ77sL>eWbvrSeV(i0{^ICYcocu%Iaby@ z!eab(h($pl0)Ni;l>aKIVLeXaVabt$hbWsf?E~iT_s$?ioV_Q7J|S$yoNV_YZa|^D zW8;04@J_%BBd;s<9K7l*xy7mp4j@lTeZ7$g4Lm{b_I2VU#Y!4k&sLw#?K@t_9+w~d ze%k8hf3UIxl+c;Yns=9x3S&zv+HZ=RAlMfSu2r3w*0~S*zhs0GrWZj5eRuEF`9o>K z511F-{f}qkCVpDi?(Uu(c2D>SIrR&l6p7m>#)&jOs($JG1@28kO=S8uR3%qi^4cca z$8{<##?AjR_k64H-f1MEfa{+1ac^otF020hD!-YQZ&Rcj~;)q4m!Z#`S06<^$N=cO~#Gb3+r ziByTN#a_))H_Yez7h`YC#-s$WW(%iq^6I%OUL%+@#u6)aL0}zB?jo0YrOSar?v;#m zhQZDyy}E#D#@gLk7d_b&{Uu(Mj+_%0{ee#`4VmTL!!2Z`i~>=V;1~RlUy}Zzo0qJY z2wsFj{j82l@|Q>ri=21O5n9=j^fDtpvJf1!oPAZxd)&EoK>LEQn#~nNnmg9CV{;1=NfvAkh4Q3s&<4JX~CwL z@~^kJy9o@7pd%3iWUfj5p&ArbVXlP2F<~z#NDZ!RsWi+4vqCfUC^fC(px)^heEv9h z-2F5Dl<&cL;>ZydDkf;E`R7Ag<$yrM_>@sYAv^|`bp>(cK4j$Av$s=CR7=lk6~~&r z>FutD%zPC8xxUTK7REfLsld1Uj@vKSlhZguV=-s?stx@kc37R>p~u$m+LbB{*1eN0DWdu58jIo4XsPOW5YA1 z>M}1n-E^^1hEj*QURA|?*AdMxXWuw`R2SCu`%J_ENV_AL&VWpoV18jmN?Zs}et zmbGJumY{I`h9mPPZBfW}$3*UYWreH0k~>72Ki>c3U}CA&uV@nbdj3Mah92$BUY5DV zWGWTo3$4^i^>AWvSqUlUNo3=5mSPHGzOUa}E~+7(pE*uj5W;PTgf`({mHhWj11Eqm zM8{aFEyT{BZF6?~-FoRsylbWz=o}B=<@&U{i3}qvt=b z+r;PkCYtGc5a-^YC=leLL`Uy5Z-U^BGF&{B!@z)Lm!*ViW-*ARelRJ2J7DzH;gIVw zydmw)Ors2`=Vj*hU^S+4w}UZOl8>R^$F7=WPZ2xWT-lyepB@=}d1fi`OOEQRufuLk zT*Mv3%1ms_9cYNspIFcHV`&fOeQ#p6<^_eG`LLg%3C0)4mGBd-Y3*vb{?h%0ZWo>Gx)8IhJOJeYC-}h? zpj&MA-g2LX4Gq_O6~~5k8Q_r~M!rlvfB6@U_zZw^_4U@Zuie7w2zW2!1Np@uYj6{9 zI;XPjZ#N4ZTU*XvE9`g^;VX{Cq&9$SOj9KSA83<8h2DR+`hMKm^_jyhil?dt{B^!RgXML zwbXZ}pPc%-lMLOU%;&5(N;Vrf9r3wm%=1o0(dc1I>-p<|o_Wt};V`+TY!5WJjHPSf zTbzD8Z0l)MfrnHD>4}AJYP+!TQWr!2t&@^l?z_r@~g@KKXQ@X6s|X|nc8dZlh-K6K|tr7)@^ z8e;(a-d8+UBzl=McJVyWM@&+;as8*ga_fDxP2A9rg$qr6z!}p1TsCyDk-m1|83ni6 zaf)+!oGhPxQ0>{^3i+7*S5Y#pS9Nwj*Mx2J+D@qkkk%$Dsd;Z?n8kwtIIO{Cd|8%kuSwqP^1BiBg zd+!r}R|aw(w4C)cwa%rmK<-zlO5oOV7^gsM%l$L(m^a?#Hq}D~Tc&!I<=TuA*29SK7qea2Y;~!7<6n_HvCJPFRrsGPI}Blj>C{wz`Kz>t%@|a zUV_+>nMwMNyYUihY^h|oS77;3m_9PABQGaqpW)|FIrdY|RxK2oj5x6XNVPf9EuC+vmF<(Y@|F)GYCPi4M`+j@gbHgOZAA zmq>l9(*}Uf2i>vmiQ6!9))!*?JaY5b$KU9N;nT^Yvs_wSS1e4{aJ(Y8f8MkI3GI!9 z#HCPy>YK=A{5U7Yg!vjg9@WV{-<+5)z}Ir$=C~ zc7EvXp8El8Csxz zMM@TJ|8XimZ@Uhp^>ULqka`@gT#O?)MUv)gV`^&LuZHetGK3U8USFa zj+ge>z4Fv#wsn2ZlK1rF+r-m&V!*`aat6kq;jYHB5tF@Yix;el5WdJs^!FS6Y3yCrC;YXU^hqADy*5wG-IkrB8; zY7Yb7W>CPkAeP{}=nqY}>j-&rYi8TrB_2Hx?;g*=szcpKo+sDL7k15XUdzj^O97HG z`4CBvxPEeuO;)R-^9C+Tc3GM7NdmwQ)nkDxN^X(j(gVWvKibH?*-E(jdz1r4Vu(`G z={%8_8`9oRcbrazAVH&ie}7~pe?1{bXr%X@P%Wg~*(?g&wh004;g*ryAAl+poO9vd zFq!hK(CvCgWTl7iYN_U0jN$RHSnO=!XUQKpo4<`5x%w;FR=QO|{srZjuF}PfC^o%D zBj2*_j@7ao5otaHk7BYy7XQB&fOpy1zguo&S31=#miR_UVUa`|{dY_8$hw8c{N|c~ zk&DHT|0XIYq~Nnt=tY6DR8XidSj!u>u zFk~z;#uTOEJ`Aing{mvS1p8?z?tHsZ^|3K`XjSXEfNkTf9q-=An${pSlu0M<&&1BFXhWjc-JFDWLgJvR59 zPp^9sejCIsvi+yBPM|}&?`W4%Gn&?2EM4M~pIwdjTkTP@E}!vT?`BM@PWGfaA97CI zVBf3qU7swLU0)F*#H4d!eSG$YX6^^vfgRPZN1k_d>S3(Uk~dlbcNXj-@Pni@<|N*8 z=pfb$k~p@&Sv>QSvLfg|o{)UGmAK+%0m=cZiXDEDlUoyCsf3sZp}D~1cGriZIN-gZ zL<2ElEC>J@*BO%ELy(LFcs}Gm2l2+(J>VVAnD>$E)tH^a^&qZW--}J#_c-DB6yztPQ7?58aZ-K?d@#iM zu~*XKQ2%AH&` zb=f`l$KprFV4Xw|p^TkpNWxOhyx8a(pnp$@)vhRaT3lXN3B;pPi*Dt0krHd=;+#1( znu&+bBo|6($P?b<;nPiT9zQAlzlG_i4^!Y1w9#ZS|JDj$N*0$~>t$sT#SJ_7mq3So zADIJnL1aOTr9>Z2Ml=COFBkHG{*tp=>M+wh`BCper%;3Jg`D>>kA;D}$I2b{ z#)NXo^`+dVyN9KkU0$I&O1>n)nwDZ8+mMr3bsZBxL$6=Hgx50#$7p>CMqf35^y2O} zi{~pBd{zOF?Z0I|V7oXNAJUQ>BC9jR7#Q{eJw{cH&NeTKBTParr@Kw|{g_eX2jTldCS`trM|x z+&jPS>Cl8Mzq`Si{^DD;IqQwvYv9yL;mzEb`uMeNx-W7N`PB9$Dn=~^_a`pEGF&@! z=!3 z@udg^>Y6qX0XdHc#cMF5>7eub1jT}Tf;VCwshBL`yr*%_XX6$F7M29zkgJJeiLt-A zU}hjO?@>qgP*vDW#!MmpE0{TkSE>tA;MU$}6$mKdp7wtlt^a;CNaYA7|)H$w$fne}p4X1iVLv(U6Yppp|(mq|?^1M9QK z%fqa9bO3aPL86kiy(dV4`o8xlr2&>2T4wx-}K&t2hl&YE4+jtVY*} z0_-GrJuw-E^&JR2@QiozdgVFdfB4;Zi(|zzISyuGv{Td_s$}^www-JLJ#Sf-U zh4s>8af!h*f5S*JERL>-QAh%`5d;V>Z(1T?89Gc@91=Ko227nxhAQDbHDK@w? zbAY_(qAR62(@uYSmtMu?cItOR50lRaqpA>4`jKhMN3*&rZ z9CVk}d?>f5IU>)8Q}wuuYiF=Q@-(S0 z1YX!c5{0&@1m4)q0@f}Hm96ZWmtQ8JG!4HAdR9%L4&Jp!xMOlIT6VYdanp|AhOia> zzC54^A({)By~(Gtrc!$4iO(ypxtq(9=dLKen_{i^oAfo_D>(n%+r#@r*zE4XNu9p1 z&mY82%%rE=KHEO?guy5AlJ(FB-k+Fjiy+>Tm_^nJ=^@~^>s{#zPiWULgl(tPzEmHo zX1(gUM+CPC&J;8<5lXa+0>0%?! zmTMZ-Wl6s!y?NULHH7tQw0Q%7pR4_sx`Rsb7E)20`X`~D1xMg#5qf`cjKjTy8|h$(9D-O^RHo{x!A5vx(2~#6eA_R@J=#f1iN1(zsYTF5qfWC z6i_1R*K@LTAzfq2#%kw;40*ZkdLKakqlS*a1~=A_?oMuBh&5_`abCPGUr@g3VjqfEK7@v<~wqau-V({(J}3LWz^ded+yp(8%y4i;QHNaPN@5c z_u8pRg4Vud_vv;do;NL83{g;o=0O<%1^RjW`Msa*S&& zm^An7Oy79A@JZBs^dGmop}zS^G%~G-WIJz9?<%eVq-j{}B>Co4hWyiRwM#Pdd{ZAH zb^N%E6Le5FOh*VpED6o8rj1W6BgT=2yfikK$AljBroc3-r82jq@^g{^ zk$pl|vw)ho`?zaE|GZo+!~fz8bpA)v^-tpB-FU@7(`0%^A&Y66tjiN3NhX>dxm>fD zkYMYgL@d(`Q(;h8kVKltDVM|)`PN+U($$lfYN4zua&pfP^29zv2_pk&D&XjmKh=$w zmei_6#-_2M0{|(Ub2%yvv&_7w@h?e=F_Y|nk(r=Z9&^p4&2mg=Wv;$;$Ax2uq5-vs*d6IJR-YQ@i8a)0ZX}`uSEB! zdx1;&#V6EveZ%LKP7enU$NltY7fp5PQKkRt*0dPNws(8B-_ZL2MwXd;y+`&fN}YbD z@7Gh!Ym3WIVO3QURjsJz@iQ_KRF)RibF@jGM&v*bm$fwF^|Me&KCgG=D3bO74?-bfGpd@wq|z1!)06vuKvR*dlGP(69m|R6 zwn?De;qGCRvtOWdDvVI|MJ0CC7ysJ-J@)05q=6#WOgIf!jW1oaj^ZxeDy^eSCl4&BW>0H$}*KupP6-X8aUR4c}hLwLZUTP~{ z>PA_%gy5)}P{D@y9Em_5)7M?@FJG8va4qFgBH&g(zA+<)KDCGiJh+y0Z+ACq zQBc{jz>W3ezrAH0EphP|)%^RJVN+uqD|xbB>l3bD^;BffM`9_EEWh3I*I7a{0nINh z(zOIg+>xbpa#TI=$2?WGg4%5>cD)>Ik?m z!C#Z{h~Q2d>2Y5g`w0dgVo}h|rI}S#fw?i3`Kc@X{BFr{xn5IRxpF2ED|wU=0*9_D z{??8CW7`XIqFt2t|L!U|=_TeztwyMqgK7My)HAozKsN9ClAEVn_dVqf#LNsJ!C|@=aH#+*{$U zwcSgmO_KD4ChUOMkN?2A1KLVvU`9J6kK$8VvbP1?G$g9gYc}uhd<5*x1P!JnrPsTgjWSf4Zh~o_h}?Wnf%rwW0@fcI_1sM#VzH|Iz$!cay}P`r|MM)x zz&b48@vX4iLx|wW1Q5^E>Y>K;HLw-Bc-|l|uv$r^sK4spy;^{VxLPK^>jQ_8k zZVCbPU#sXvT%-?)49Z5+s+V6SAS;@;nr5BLu*S0WyxiY*)F&L?w5quYD}u=7yP*m_ zR|d`1nFI-h3{&nQxoedl^F0Whn|I0Hig1JM%l1n&Kl79W*g2v^2h&1?EVKCd==bI1 z`|a<)*+$#M^zB94KM4Og2h_K-xq1}A*@DU4p+fqRNLP4DKx$mEkKzsC*;epJp+tPO zZViv_9Wb&$4(D04?;91G|BEP2P0U_Mzh7`|<*~Z8|IG8AtrTpCJ&WWT9%twB+$QYy!EzfK{Tb^4b~dYiQ9GKS z-%)0}T-+++CgSUJqiG!P)})0W@e5(xOYn#zwktYKU64KMT0t{Fz9u`!ChrFWRu$g= zNlXp)nE(W8!NijUq0@RYlSRSZQaxYT8N{r&cW84^cfpaPjSXKEFMpTC`H$?Z+00M) z`A!V~>sP6?<$QbZk_nPIxt0;Y6K0I^2n=P~zKP|q^`5v(`4vYKOq{^R#g6ub&W%3PY$!??3}aJY)EV;d&6)kt!`nuLo<>(jIn*r>SP2Yb@**~c5X6}G z8%-3xT5HQPDozoXXQ2Pme`TS0gv-9 z?XypYlXOCZRTbK0=i_tKH|lnW`6L}B0;%JI&9g+Qz|hKWr+*ui4`Kj)utNvUw(HPu z39b`4Sw6b5M~mXuL|}6sMZgoEuciP$yhh1|9WI9n+eHtLF;Q^>!uQ7-T3Ja2Cdzm|5Cc zGbicn>(!8oDoBpXR54T;|L)>)BCN^I@$qkgxi%;-f-wTH?@Mr*%-w~Q-^@gka58|+WW-^D}ko@6Eq6$^D4g3~9M z0phvoUL)t*=cm>yc*!H0*~8^$HulnNjsW1@LOl+RvQdLt;AKaQKW^Ce_kUJCPdrm%}yG{Gb=C zwC0*SKXz?YohjbvgZuLCe<2r(9nR`4`+KO{5*euQ7C4)jE$JS-QQ`kW@(wqRbWS*_wJarOeGuTwY0l4N(%3Kh_cpbcP&jp z0m>lao4zBAQq4_ji~@a)5*P#`c zog7CHIV04qmi%+@``=P=H7h?H-Qu&OPkHZc{ZA^NK>MbjR)6TKLG$7@q$xU@ zt|wBsi(4vsipqjrHwrn*78#t_+#MT8;(|Vkd)0*zCp}Nm5iIv99n{Pal=HS4ddk3c zvUKgvmrVj{x8GnVYH{qwk1L)?8@Lb>X;|dRzH^5KaYX#IIt54`?na-GI`V&xKCrfz zh~6LjrEsjpDbWdqjgG2&Ew|9!H&96F5|sM@4juBKK9rbwqRBzxU24WJUU^RofUZVw z#nKzct_4E?_sRQG0G=RpF(J0?)A@l3X4qOa(yd{#SU^OYO!>EyqGqu?xCfucvo_gX zpZj;D4~DOy<{KgnCx|o~aqMiCFiS-~RD(_Pj1)Qu~McucBVNQKnDj z(x#@<^=W^q-gTt?Jb5D`FY=g(i+!UOJYo$0xL}f%;w=-+w9Q;Ny-R&IZ-9wO5R8Gw zw#8p+deE8r+%2mE?aZkAu2+JWrkMD#R_2$Rdjx_ncyJBQW5PCXOlyb}V}o3Qv#A{X zp2Y@(>og7DRIvqJ0lwJK{%^2|XS_twV=%$zhB&JLeCJIlQZ#9|zse2yDmSFV*UBvaO+>d8vn9 zriVDDOJ%NbST=1Oh`XOnA40WOXnJ1TuH3Z9W?ai{GVA=| zNmNkk|MZ>}s_8KJcBPvyUnN`eF#8e&WWMh8hI+2XEecpc-uT_*e8^9xjRlfxfIR}r zQ|=M=1tI^`uCPbOjE-s1;_|r&Peg@zr?`CfU1?QfQ;#kAQ4j5}<+_eBs%Sq?t8L{k zCBH2fcU_5x8Qz|&xbc@_fS${^K(x-bjr-E(bU6c|I}gVjXJ+uNjRH_lZF;n?@0=ig30Tz&=|@5?fMA!1K>|P{R{1Z}%V$su#3W`|oU)-%$zHb^K@1xFzcM ztvfRS#z0Xwp$j@bc>QO{ujcJmBYl6LFx2;BGrjBUU6}`|#o58T7Z7XxA9J;mq-COh z(k9R%b>Hav&}QpqcLUq=K`b4}U1=xZ1KwwV-h&!@;Xn3yVKqZrgii71H~6z{DGtFq zty+ZeR23hC`7zk!MHy`STIG18Puw715Ha8P-rPU>&(=6L)R*O&1!{ae=U0*k)e}5x z7)bN65|OJSrc@yAnpu|(z482*C`#F*t02BR_+bL0xGVaz6#U&f0{IA7MKyd6Ro@;< z{7>*OQcVD95YN9pd_?M&#j!R6qZAo(v#Fb7TvCH$(r&3{TPY}SJVrnWjEgy-l-b1Y zti(tSemXJJy5smV+$6Il3m+BPbijrl}s5SR7n+cwdf_Hr^Jb$nXV^+pPC z+bQ0r{>+lLTnBCr4TNFevl+1Qo@ND~dd66B*ww1m3qkp2DxYm{VkrF<~G; z5lxHF>$%W19qZ2lt#Mx^80Xg+Qy0_DYSbbgJDLsj#5qPOQtWmgq!BaGw~jtXibrX2 zPTG$^j|;@O;V#U)*9FzTXR~3H({mn!OKIz9r}J~Jq*Yd4XTL2`lz6L)VR=< z_{_p~A11M&t&r&o`*JbXgb7HKR{JCF$andKFwhRI!!D;C1o347$R}*92BP%4Xw4!nn)()V~k@^MS{{yvMYFz3t z1*Sb!aAi7wIhfrMdDCzGbUQ2zmCoQVsCWYhvqHOgIaS$d5gHWUpSRlGE3Gg7zsBXI zjT8C-2J&5qQ=@} zDJW;B>%L1i613)n=`+pn0rj5*EV&}b;J0!)JV%nfe_c!xrw+lZ0=RI^fE`Bc2K@1Q zME>G6CexLD`u*fD;F`NeVPoQPGjje z0_4m8$jHA@qe5B3#VAe@8vevAnli;d(vv@~Mdh$dzpN$R!MF?u2CdNyD>sNx9=7Xw z&A{|5_xLNrwGt`)I)@62KSB|?K1+EmJwU%FReEfi&7^C0WL{amJ++-4@~(PBT!&Q- zKd|PJSkue&K`{$Xjr^;zWE!Qyyur zCa%a`!9WZ=V`cG{+QKZ_&6XPewJ>lBT6N~tt3sMZA1dvTmmo)TFl4y(UA%2WDk=Li zR0P@vzsYws^6Md0(Bk#udFjyzU^T{@#v_{#&T_J)CIw+#*?AvCzyNzeyGsJfP5)5Vh9!VO-mMB zs8$&6XRZZ`-zBiNpQ};V$k+WKOHEUW2Q**aPbUk1`_ zrI00~XjsR0lta?^7ZVLd17a0@l~ZwHI^SYSD5vG`F;3HA@||w^OtXyKZlA9Y=jHT! z7wwo&5mcvBoBKU~QqY_E7)4u!UPkvn>i3PpvJn13cd|8+y4-}pkrZ%*IugY zVml_D)d^?DOJhNluldT*F?Y@gSJ49Yr15#|LHzn?NdzT0QhQw=WXw_--peNyy#1LBQ zdBHa`f(jUi^wCWPwjphCzX|CU={GWpJ_%P{VFN0<{aw>e;(~zXv$>@&P{764K7}(t z9*NvW?(y>;c@`1EyP$4^7abm&k?}Blu8W98yN&x!?03lXKSLX zLgm@_I8j3-eXT*5_?z2LX;FE$6;!8}UNUvx!K-N=NKwZVwTzdDN&Q2zL9|gJ6at~e z!Rs2C#)DG3n>&%~H|4ZnS_$je>v?5=jbLs4rB8&vQ+WCcBVAsQh(Ru~MsrH!?E+7j z2ypK;%P<5J7dxg`Gr^T~Taj5`q3&rgUp2TZBqe<`hC4T%HKH*Tw372TI3cz{;RV(L z)Png~-WPKjm=VA-%HFS^nKkU zZagw_tU~sWbrLS}HXtZ*97SnWi9O@N`lB{Yy!} zK~Ig^6~%e}d+>DuZIJ6Cqo&}sy(yqRZ>eKqj03eJk1l*w!nM?_Jr$SH=av~J=R?fx z7N$Ozyr%QK>hEO~_s7%CDA<;n`mGHsD?VY;&fYNLweeyA^Z%l93A zleTt$Jcqv@LfKDHgOr9}KxON%d+$M!MISc~*N!Q97;w(Tn0g)tLCA{S5?YKIlm7N* zvmbbjSX=wU<)X*~V+L?1qN)mCl9?>GMP`_P^YH-ibB_ z%JmO<0vwV!-PXRuhK?x6pes~a=gF^l?~sX~{d5e_U4=gTG(1z2UtpEvEL0}kWmitV z0B?ftBUQc{*^4hUC+Gs|yT0inHF?g87NYfDCAA_2kMpg_db#qU42J=J+u0%b|J$&V zxc4kkX6GQ+9JIvjbI?SV%AUB4W|K+g{^~#XOno{HfVYb?e{`#2B=`g>V7#N|C5xMYp6T(eu+i9T_D!;B6zp3aD z4jHBf&Z}<|Qn#(9*Cga2@Q<|)WJCQnFUS#5(S4xfF4IWWPIHy85=^ zHk`^m{rsx;f^)dNC$5M()Amdveaas$t|k=P+?)R6ub%ajbcs|IANxA*=gIFW9LEug zG;Y(Eh}%<`e%Yflh@CVa`F8*+y^fnCFmh!t)gc+-7Xz<%;yeg*US)Tprk!8BxayD) z5A6(>sNQ=Z3VF9OY^AoVof4fD&hO69YuBqZwNCg>$SWBiAw@t0lD~^OXrdejp$~Iw z3%4blN~FnhC{hGmpXlvcE`ck#ER*XFfId0)3~<&L5lt)c9xX8_+m1ez_5Mvm>3q|d zN=T~(xhqDJh&=OKyt+!@34;fD|0xsWqt(vqAF%IG0JF8MFd zHCQ2Qf5$At=^QOBVo;v{vFr*l7epAay0@n)SS;()@g`%ve+d_Sxj+9`p7)^KJ+}3G zHiR7vPVLzwx|f=>$4wq@tfw6eX-c#D{UyJdSaUhxiWIbuTW7xh zs4Chp?8RuBoLtpwE9NT>P+mpC_w6#VY)AQ}zE>0KdS-_KYSyR|N9J6MBp6?1inkw8 znEcI~`eYuf0ev#si0_3}^Y*IV=-=v!BNpymEz{gP3Ki1K!7x+uPkHJ=wP zIH9L_j%dNgRUq>bgQFgzTIGDhUw$EuH=BR~`{Tyg;E8HC6~fV{!nn^eH0@x_$W4kq zzG(EX!f%#?{)?YfKvhz^(6Q3!6~X2gbOOiOG9$8XA|Skwt-^^4?^=;CZ7U@|DE~nkOX8cjra0;Y7D3v0;#GJi9K5^7%kTa3?)bdf!Xr_iA}>2|pQh>SSsXU)XNM&{R`uIiZj3@u4`O)w!C!fCReXDjUcL<5R zTK}|dgWgC7NWlyQjh5`QV%6<0b2%~cSRp&;#)pe_WUdsm0!38L@8(PNajjh&eUIx^ zgvc~ewoFx&3-W-pj-E5aMuK`24c0q-CGA4c+i}e>BBf0W%Ksn2=ITOUW2k{OG3g*M zrE~f1Y`(WElR4@Xqkx{n=?Fx?*GG*j+*K;Ccq9%+Et=Xay};I`?RY< zq>H{=B}PVL4zzn}n*vBv44Kp>$YBEXiOvPjt#?sORq_g>_HF~5Q5N%1nqnBlSCblZ zW}JuEKKa|EbU0I6a0y-iSUrqG1vBdUuKM5~R^(;c({N&yvLG49;4I|uF~#I_hlMH~ zuJV7dj)QL~AMQM#=(8d5vWG(sCS=8GDIcbo3(F5{FV;pWOqD32u0tLEWp7Yc34YW36N9HseiZekuO_Ii>Fv@#AZu zl9m7XOHsve8*^jT>YmW^4UeyF^j@UnCVZ=VdNQU>xrz(41|aR zK?XI#b~{S%$E$tMkR+A4EGB^yd?1N6DwF=o zN?Box^j_~bN!tLq)b(duZuJnD^dN_Y$P9|4K2mf^%u5yI4j%%NnpO$UwvnaR0jE~; zL-;+`(`vzME10Zn@V)CvD3tXi8nGT-MWdC9gLy1xNV(SlX<@EJH*9n@&d6-=D~36f z{Bd4{lOpj9-9{5F9L`5BTEbt%90xM73M$d=#a*~PUm{MHOynsKde%t)PU>#axg5dv zy?e_-cRw{6n0G#)diVN|6FpsGsnDgMy;w+dx2V!LP`1cbA1Q`bJ^rR!mN|6*y>{VD zpj)*#F){D*ePVFX)~2kwg5Q8gfqSS4xz8+X_z|puUVLQ4<3t2z)Z>c18d1+Uy!MWqZ9^M<+GXe_zF{i8~%8EGxc*T*>x-|!bf zH~Fd-4HEF2q#;{d2!c$IH^u{31kZ@+XCA`-O_vNAhL|yYREZKf27&*%8$S=l)b3@q zf=K;eBCxM~%J_%%Rm7n-n(spuh*#gn6}QxSk)Owp9R`i|3h7r^oF&SgAQy9DNUTx# zrk)6o(7##t5`@#c&yFj`PD{clCC-9M$yaUt7#P_K7sj6+#3-UZUdj{d2*kVQ_;I_O zY)yR=0dK7?M0&BLvVoH;XMl1#y&jX9|MNaHUdP>(Fa_zq3Wh{=Wd6PS%O(%3-d>+O zxF2r2vbOin$=9SS8zA=-c#kg`E`?%Xg9OrtLHJA58)t$e#03$Ga?49;Qk{*G+{T=9 zaOZ64LGB(}vB0S-14{BFc?Eblb+}mE4Cvo3d%`E17bsJ$A*jT#`jOS@CeA<~RRS~9`*14qu^rqsU7zWaMWi(W@owjo?TTxaVDx4xwApec%H z1$v(7(eG&byV}Hvh0?+&co{OB@V0`76So)+z*SPYw`v(U2YAXa?KaT|WA02nD4b1JwpP6^4Z6QMylR%Q5y{zrbB6~JW!UVXA&?4zi6TB9|Aa> z8VPbc_&N*LF#MlmbT9OXmYR;&<`?LDtIXqZH$Ii{TzqaP&i?|o zJ5hPHVK?EEt3;e2<(r9Wp5F6mjffVsiZlY+dnIzBCtTUnVO)-)HQ(2rZwZhF@D{bH zar;s~>vYeL0XKYmADLkgr~h@6Fa}?)&uB&CJTSY|{KovDdKdUxGDo*%? zrp*s{oG!zZ8iOZ)SQ)!z6D~CKg$});%6nGcqh(Ls*l2fE%EcoSTk4PdZUQ=fJfQb- zKkt%Ds`ZWC_&=_f)-^!nU53t#NL;A|DJuclq|`(Sx9tw#eMl?Fxd^Z?05V{FT&q37Z=%c{QatTC5AYQjmXJ`2?F z={}49*Tw|*4U$-sfP_-4N?fFV23sth)jiV1nwu9h3^xT!T&%r^~+cR6YNwY_xc z>lmr{)uM2ex=K6yK$A0ePUL7#z!geIos=UAnJGnW{Igtrn!s8gZB#J2+63tkFE0=6 z?Ps+%Whe22jfX~GV{Dst zPvNfXJHP%Cf8(u}Pu~aaNyv1WP0oxu_)ywdGqkrsf;ap?2tP5u#-F94mcAMkRbYkeu53v_fc8N5hF*!ftq;@qP)vz$Y*m zUK^|Zhj)}gKM^KpO~p5^U;9oQpX6Y;>WCa`p$9}s58fwvRSrp$yTnaKJ3) zRq!hmc1UF`1VGI`iGQL`qhT>yjGj3WSdMR#krQRjYv?K|S8V9p?nuSmQSy6|DXGHK z+v+t%y%5-VURNpE*K&vo{dB(3MJY$z%BvVk+gFI9-e=?KclXWYf8P$c!?t+u$3L3M zYnDPzeIh2ROm-dbks=jB>f>P!D-j=6FX`fHEhTC}q2#Xw2z zW}FRc>x^sdfHNk2mR3N+{+_`b=j z>@y>9^RqHs4Q@%44Ww`3$(lEB{MZj0?P3U8mf%QW33LjJ?7JTRppv@c9dMeF0ZUW= zboIf=&+H@EMHt2uw!VBay@rQA`V zwxYtMa6zR*gzRA7q6#j*#plrGEa&@9hBA3Q#pfvChZ)ZaWG%POvw&}kK3)nIXPZBe ze}!Lp!6Vcx^iF(IcjIvTs};{|5^eF8{}!x2gWfdN3m8=Eg!s} z|ND91(f?2-Y}IFjfnquDB)dlXj8=(htG_`wF}Jtvd;!F;uFs3`w*eo(HeG}bZ955< z84ttAOM>g1HN>)A$|r=G2{zdU_3Yd?o)y5?6qgGIqB!2NC5&)h`v2u zN=cu4KP5#(P#HPuP39*N_7CK~_~U1#15%9m8#JEjz9BJv2|ls=(53Owt=}cjt8$pe zE=IF%=Xq!P@r2$=QT~RmvE1@Ksu!LQJj8Iy1mF15tt?-{x{j?}i#SsdV1ri!)z9%I z3nW~xwnE1x*6@iB|E?tkqhDB+_J*93$ihBULo_XHs^6BnJ0FL~2H8f?%8w=gb7 zqHi<2oY8v;zZZ95WQ1ii`v#sSlmXT?ndBb#BAZ4LXTO-d8}KOa@9(wb;~+~WWX$qS z@d3O8-21f2Q(_oIek5Rtu|hsOEo9lP|K%{Yvwl;^Ea37=zp|AX%oY{JBmjY$EkxVC z7RN)#eVJS{veX7x6=QWiZ>f^gdY| zU8MCQebmb>k0hd8L6eFvjyiHVfY!SeKkr_7^2@}%?wQK_3&cFNXLTtjbQYUSHj9iC zKn4Z-_^8TsuH6Sl({*=`Msy8(?^l8EK+OR>qD+-XfA6J0GKm?ceZpykM^o5;aG9Oy*@3g%?>y3 z{{BUF(+^@_6?T0eDL!Q0-kNj?1t0&GRaHYdg-ErtOu1fYW}gT%RU4e4l zLhxs7*8C9L-xocg(^Kpeg}dKtph>{Ri<<*%BM%%l4S%T?Po?A6_n|1Y-1&^n?T7qz(bzUAQo*Fe{p&WlN6F(`UJHP|kO@nd8%=9`$ZH{Ro*) z4Di?e3ND3S`O2s%OY4S+$WiE=!)+z9d~8iXM5H%4F+QY7feM*eryXUwJ{ZMfGX5tL zFEjR?c`Cb-#6L&4zVvS^lKUaEW#eyXSQ3YUf!-#nGbJ=uCY(^^jb5ADTa$W+fE-W< zem!%-l5W@9T+#jZv0uciO+YTb;3hsL47613*8=88fFw7Dw|`>;Nt|8)xd$<%fmla$ z8Iw)U+ah3#KE}NFBN2^h?ym)cd|dn{)znlps??k566*$Vrw52~Uo$7%eWs(>H`s*>qO`)RA;pcJz<~WLcrjK$GptaI6s@8aOH5 z%pyBgMW0`BRuw<-56NLJa~{*DqCzvKo}%uGtCqFV!q2N@FBsGJ zX*Mh>c%>4MqZEt*a)Oj0y>ckK9w+xZz3J#~N%ys%ciDAA=;}L_r^qbWk)7@%r+-2< zEOKP+?b)})!#zAgcWW&<||sxnIL;_VVv=!VYd zT&W-@*|W70aesR{_M@pDZ9^tUSZm?Z)MBQEZV(X@LIKN~16BY$`Pf{aJqnaH;6%(O zNl&IUkL=6bdA0Tbu>c0>saB!qS6`?4;lS~A1V0W;maIorJE!@`2duzQsLg{!bnQGx z4k_y-*@R>E9|=(uAajLM6gFqA0-F>M(qovscsdo(y#L=bldSsfwqr=U)oZb5w`?}M zKr%iIz#FcqLKnj9{lKIeH&Q-8xvf6ZN~^h+lPz^njPU&T&x}I%VhivcGK2M|j74Q% zRGUIA^RRW`o`5=b?Uo=x_WWSRi)<5rc@weotgPst zeIuq_V)-tcol!fwO$~+OjIRVkv}8l?rIXo*tf>})#dH1GuK&TPsTKlfz6&5x7zhdB z%MkhokRZy_I_omB>;=Z&58Pk+mM-L}O*MdT9rI~F(>Foq zb%O3KF0~t^LU%Hs+sXr0y=IHfYq#!EcbNU2%ZaY!noYUDeh05-C3L?)rdU~^^K5wgT6 zj?nQ!sgb(ZmGG{7v8te+5645FqYoDa<(DH7r;+pdv5pUgr6li7LWw}T)qNVD3a_iI zRE(O>x zifmX6*L&}l{9E>_!Jqm?di^rmBgt+iziTz>VSe0#v?aA`ZBGl(Cx3$#nA!O~zg>Jf z2OKkAzrh?85-KzU@tH7dIns-Tg@S5C1RZus7ny53#TnyYhAzGC%U@9%W50pGsSVsO zoTs*{|M{CHgu8GqhWAJc-gZUY$Q&q9Nc?C^PDgE})mb0iR{(~r;$HPZ1t4+Z7MUeh zU(%wD)(g6JklPlE@O$Y}=W)%(ix}QE=ZyQ)lW11i9#sUI)nGS?UiK{f;Opv>PplD1 zQkSFd;5&qs3|bU#zU%U$=DL`K9RK-Z{iTDR_esbRCye$^4GyIFJ-mnX%3#nivQ!ul z3?YI-4+Fg!f@{9w4d87)y=D>-qZRW_B?c5IYDBY8meQ)#foX?~$PMg8F6nCWWus1W za|_(AVsb$!c_yq-5^QR{5O!lhmv!hBNDsw1aOS(G&yAmY@pKTyvP`^ed~sO0jg1+(@&5pi?^g%;Ib4*)E`WpxUT?=_UqP4=eWP4;}qd3*hfDtCKElaOTD z|E}}2DKt4Y43l?M!eSZ^^e$F?G!jRx>1@30j=0Rg?_zB@vFbcDylllt`ncjA@$f~a3ON5=ePRm zLeVt2VALrrPygIJVPaj48lL=_m9wRrdH>HB@4t6s@zQ@f6$JXy+@2Wo?~%TXO&uef z|1^~OdH)@d#Rf0N)Xf5a@1p0wI}3WnTYnn_ey#8G=tMH0dhTC9kC%jEc;w-?C zaIcac`V6R%MpYF}v_D#^{C605_Yh~3+xH%jt_Ha9jhmFi(n)VKhz^F(YW^_t2&8w@ zk0{Zhw>{$H1l13yr2rf;X)a$SC#x)sloW3;EPH?U%Jb#}*rxz?i%OKTZ<6_(;=RcI ztx_i=RNS_}iTsSi)zl`(!OVMQskMQalGlLkn6j>gMaB-+FY=8VQ5NufEX8kViBV7Q zQS3x^D5`O~^6<6@S&D$BrIN#GRHZh)Xa81@wyNfCT~}q7}aL=XL;Ve5}RukwDxh9 z3NfDwZ0*0r)|7qfaxm$TH+4HZ*4!U#NA~G-X+KqUJ0~MaE z=i|lk_b}pB!r~2VtP6J<;x;QLhEr$#rYkC&cI-bR7zr&@)EQRGbqg~)}D6o zEl<@TK{tzp`)`N$NHrAJE*n@AFC^*T(D~TXo>$iu{BImQL-F|kZyZzy(%V2mkwGHB zY?jFCzNlJN{BxB-f(LhnYQ|_$o9eVSaBWMD88_)=qyHv+3a9K=${xT?zPs`yLVV?y zGap(oghqNc%T-&AcT0twQhD2IxZ{iBpLp{@^pMJ$_#ErlrT z@iGi~SZ=(}_CtMIf3j9c`P%jw+lT*E^idEd^juPiMbHs|@0TBo?7C-YY`z&T)7w?3 zh*6w^K(8GlY@6Y@)PUFM>=BMXc!+gu!F!AcRHIO{4YH#6=lhouO2puD5sMwqX_|qU zopQBJQ`8IBy^ACm}HLCY1P{iS6VKy0==l?#YG&^t(P9$60i zMQ;wFD|wiS*VvWLu%(s6WPRoO$wC=fw2%va@p`Ln&7R%#AO!h`K(jE=m@2yeSkRsP zIjLw12xHz}F96IeDIHa|j!2@qZR*+1V)Yk53f?QPMr8w z_nyMX#?wYtQ^pThbtjJmIHjfvr1dwm6ZN6Pw zcqdx<$q8&XhZp2h_8C~0`J*~IS#(8}@9U1DKri$~NanX8|CYj~@>Y_|`{01In^3LY zcwGV!q;&W$9G%oxL`b59GPeuLElqo{uui8F-b?PPI3`)QE0NJX8E)af)Hz}ap0le8 zCmJvFhgX{|Wx=|az>Kdbl1~K^(kDRjpFNnFhVIHsNJ~qfWIo9Y3og4+wmr%mh0jb4 zTi(5=6u4d`=qlEFKWPgbz%>n>*jn4+8>#c0Wa+G=J(kye>%a3W z+*&-?1|*@QuuHtYf)X4&i~o1y5dpAEzkl+Ph^nqEshI&$QxPV^MT7n*T`c=^R1Fo3l`IlG7ay` z-m}i^qPb@9Y&cv2zNk{b&p_u6eJOgY<-?2XDyR=nkpc3K`>}nzGwU521k;!2?+E@7 z52t5#GlM#n)OQKxymwu{>@44)(cpYE2n8ahQKU3wPqpVI6Vr-4L}nY6`wThf-f4P> zhjU`K`h>&$&E6LH& z;H4SPp$1)eT~zkx@^^2ug$1Px@`fjSQ(_;oMe{5E!wODbPyg}Xu>a9|SA1#^G9hK& zihDQq^zXAKeK|#E7^R(cv02Mr@k=Ks9rnz_o<^Wmq*VqEq!tt3)3xD zs5P6Y$T$2G5w#2^=ZBvcxvH)u-ExTGsVg2MzkPm7I2!zsP45ZqC09qsgc6%b)hFf> zg+f9A9tz#hvp@0Yf0p+BMq_6WLs9Lm?tg*@C*!H=7l(>}KY4#Uu)0~ddxs#@>lvL# z_iAZyWOw-U6&g8_`DOE=H!-8!;g?l%CzI`eq>i(49Z$fIile56m6}XF%f;t2Z_P(t zw6XX1p9&t&2%Tizc}>LfcUNB_zTFzulCNN0@^)9OJoZLYkZust zgOJS(B|;=OEcEDWE!FY%Dy$egaqH_Jzvo7h?x@aifmO$STS$cSKf28+Wbg+yS%ktP zdd9REvU;!`6J|5Zwdc}8nd0L5au#c19r3hs7P?0RU+%C~WO{0zzy zM(UbPK*Xce+Pw5ZLjqrAb`*+rEmu2C{Ew1dd>nh6`ix)T*Sq_M=n?uw)!c<=k@IoF zODbs%eoN?;^8Img{h zC%!mV(>>!q$pi?Bzqar#)HEV~s&1$4L6n*3n>op46cqBD##!X=Man4kf=KU0Y6M0o zk4`WL!fbqt`RUKmcuM!2{3Z$gI58=suq2yv@2w9k5wJ;E<@(T_@7dCCKCU!>5+Z-G z^llp9QgTfv`)dhBmM8&!z7PbXQE!#sJsP=fA0-@M|7SRI6BktG)YIO3{o%k= zn}UQBV2_E03gRd968F~Cts8^=L`pr(K96hD#@R>*yeu{og)cOHljF*ng);EdTFki= zGm)d>c?|^nkb%HLjOsQ^U3cFYgcBFRKoG*N^h2J?7Xkw^)_yWm&7i$nA%bLq9^Rqt zY=M26T>V=SyHr+dva|-Re?yf%Z;J~gASzs&dFPh~#&6UMAT-l_+}>GWTFa^eKuPrE zz9>10=c$Te=|Iwh6lVGsPYd5#Tvj%*)bCwWIn$yi z`0f9|OnYV6M#o659Mee7RN<m_MXvevju=OU(>?bB& z(o1p|=F4CoCv(4<93CO(7JO?-eo4|tk6qKvgp(uG-58XF^%4Ej9c|5RyN_zA(wu4+8CHp=>2?sdO-sAK-c_ay(a&4*CbLcT4 zJW|#+=;3}%IyX69f!(Lp?}^DSbo0CFME6Kb7nj;TYfK++p876>rruUl*8$TKa(Y6w zz{iyd8y`|cU63WqQy2Q`eDpcj&S!Kc;cHaMme;>JNA3i)qDIG09rnVO6-4WxzVjK% zfd#`v7u=)%oI4FQ0++f#jiJli+}OMs0cp=p1~NheU+UBXi9`~=F!IPwUR!;o5pkfe4HMl(d9o4s?d@Bs0;W4})&=C!NnkhGvbGJP*U`<14_prcpB!#C z_byqBs26K>ljYAR>NKMxu~3azE}kra=To}~mRp>$=SsJP8(0Oiq;8zCFXn$kiw-A~ zM#ojqah8dnGCN+wtT?+4rRsC{v{{uNq~-i=F&%@Y-dxg z=oVg9`(1+L?6l|j3SfZbKQxQl#Fi|HF9PDpwG+ut1fgpH@dht|0->k(FqLPh&^_14VYD<Y-uV|D=@Ce#FeN+Isy-*bHHK%vcax`sNe9<<1f=vb`epN{D zkj~zfi6=#)!cgn;jpq=+ZeF)d8|f7$FJc_~yzdjl{4L-*I_I$G^D4Va2B5ikq3B~T z(|EPEnBqdJ29v3LNI8WJ^n0GBWp*DGIDEJyl5HYda4@l$BLP zch**YjR~Kt_2}e0(TG8PRq9x^PW^s?%e49dx)nHnWLv&7ktghs2;YtUBY=5+%&w#A zf@%G1uXW!Ig5R5+hd#KbV3^A8UCor;O1vM*X37HJ;1_;c6Wz?NdRipkPImK z?w55b!S~%|=Y7A(LneAhRTHEe|MxrO2w1+ib_VDCNn>ATkT2xDk=5a_=JuGhx(V2p z>+??_!kj#4r`7mrg)NH_l;=32C78Hd99+gR{cC!gj2B_^*-k+o^$utH2TG{a=`1=IS?PQjd=7D@VbMB-y2T7;DYv6v=P&!zy&+6%kCtBIsWt;uiohqA za2|KmKvzNiS3s{C<$oK0lg9JIdL#!Q+{o!2ZSRlj8-D0QeU3g&@?B_!4eD)b3?v$A znnr1~3Po7h&^`caFt-Wv{9189`)!yK0kEE3sAU?BCS7!oz85%~0j#0lcKdB$=d$8_ z=mzo*_ymSw2~sFiL&~=Yw}Fa_aRz40!u_@&j%JO`kikzCU4Bw(3ommFowGGkA0QAt z*T!FQ2#7|BtZ-_l>a6!jy}pnI58_#X%Y-MV*^JVCc_6(otKTV>u|0|tau-;ASPLtz ziDtJPG_=@ko8S^86V8-M+=s0<`YzQAOND+0d$GaD+09tRr^iG^v(jHjj9Mh*@>mr( zud|l6T3j(YlsH+y?z7M~9Y;asuyKdQ*hfP5D)o&p)p<(v|-*TOEeoo%xJT0i#E-Vvt0dLy@R^Di@O=!fWjC(?zSJgAd7 z`@5xjg(akI$=Zq>$<;E(T3KYWqD3DgO+M{9Pbf!F$5s|Pvda)7?9_IW(1 zC~WSR(ovx$K6?EHVBM*Eay8o{;Qw9^j_bZ+#w*fx1E-eS76_aZk|3Bdfy+xy4ld_+ zj=B)%1W0kN_-lMa8f%)0J$gMhpGr1s@%#IHd2&uIIYAY|W}1Pa|LPiyL|>IVzt|Z< zs$>d;fhe7kvuBn8pJfN8NU%LA;q^+L(zi*4s$H|i2vk=T#5CdhfRs!pFcF>`%sGPM z57mv+CmjAaW1M4*e*&p;b-S3NF^ewZ&} zv{ZsnF0saj`&nApJocn$;zc2HYAup21HDe6{-@8hy~c|H!^e5dHnVM>&Ss6~j6IV` zh83`(RFT|KqY{zw84aRI9jpnc0fhT9Kl$2b&+^U z@C@lXFqCA77cUqxqUDY_ z=EXp2cxc<-3Ku@%PRx)4=3?l_lDBpNQmPT&o3)PJ-bYT+ahkqm;uw|+HX@wahdBsW z5RJoZ1it&_ar1P|p}ytf>UR%2`-Y!DMvGi^(~ca}8Bdj1I}|Y#>sEknk0EOxI*dPB zBDWQ?rY#gFh;puzlYH1vZtWf}Zn|+!?^+fLUnG5#z%k?M6zgJ9O?a_x+#Q+5fF#gv zUfa%KO+}1a!=)OR<-$r}Lz$sw&?hV?5wl1qQ zAau#V1~xb4_Q@=y@eAyNw9HlY$5|5C*=Qvju>t^VOEyre@n78hB;)TO>M%Q!izoU2 zaeU+-p@H7%O<@F~Boj{J#mse0RoNKv#=S1JkAFDx(*2Zw&CFh}E(oWjg~Wg6tW6z; z?a=QS2oQ~O;1ew748BeK-T)uhnP7hHCPuFBBj{A4Z_jcB+Y7&Cl%rl0mpATa08{I= zp}IDYc-pNiOT{eki8(2Hk`%M}ky}{5QuhaCklQ~G>t?S=gErU7+~B$RYfO@2u|X3R zE^Z(%wAHK#;bbLzsa+XY3Goa?Gbcfz{=;=_4g1=@(XSZ1(-Bk$oKZ-y4+b7om{m-T>&mf=lnYHr|^uG2nWu9=z$j6NN>GJCt1zcfCV2Y~xm-wcX+&x6T5xRc7q^ z%yMoharK%9u++T$Y@-`NExb&)Y$D;O=FDPVH0YzwW!$jMjD(6Q)-a5g-+4aB$;$N`E<%LHJwMSkM z78aHGk*aibp#w$&{~>A~>{$jiDB``<8aVI_4d@GFKlt5wyH%tnNUN3>wJ{lfkpCs7 zdiJ$AgrxWCsmVs`0`y9}k+jF+ulTl@y;MHCcBH=2}g&c)2?akY^hBH*^U*Ns%Tx1G zP<{NAhjL|wT!9SN94R6c2OmFYNzT&qA#=apeUqvm;}LJ1ZbAJp1N$Rzh06L!?i@MN zF}5{nb2HU_TmA;0WI;3`+-7#$=n;_bv*3iRy<8{j2lXkj+kMA=X{%IF6&W#sSDPuoQNwgFMsSn;n|@4AO@b~ zv?dt11Sg_4vJT`({Ts7VwykqqiV95&Kdl9t;#3+96tT-P0gu7pW9NQqC17Pf&ci84 zRG8g$B_C{BZSKfxcK#}eTLrk5DDjDb98LA`?|+{fs2U|7e{{S1nn<1sQ9OjtE=Cs@ z+Lluuvu4ZEF4{^i9hlKCeL=LW9m$VdOM0S;Y6azUl4rd2tF;jrop4HlRY4q01@lbv zPD(P@4u{+1c#*xf$f&2{n};gTJ2tInnrB@`%>o>dT0izgl5(fDQ=E;1M{Bf>st0D1 zW|pj{$1wA4GO(>X;qK6hA3?!yjz|8zagTo8#>^P{_s&Sm1^=Gg7;8~)nEY1<>`z2Y z8Yl%oPM?!>NOzq5sTF2aLoY$ZCJz`4ji4i(9F@AQlz1Cdt)k@wV7icexic^$fr|qE zm~(EW{mwt!8HO#VhxuReJERwqqY%D8&?HhK_ zo4O!ApepqH&%oJ)G!oy%K$B$RDa!z$sFUPq-*$fgoRQsn0SX`@Og5tpr}3omvBsh= zw3>y}UUbIzRp@u+O!e&*)Xs? z8aRSW_MPs^3Rb-_wFFt!R@k`y?({7tdY^3R=j!iu2k*eN2Fs)7ME#aNicAIRgHK3b zBsydd9EV;6B2(;Fji4;N#17Ow&D;M9Q4`c~)}Mg256495v1s-ka9)a+ zUV?fTZ&;palZb4ji_O6P)W0U^=}E8Mgsu6kGk;)lGW)(v zFpEL>`6}joL?A_)`Aa`fezEGslQH`}M$M5^YaF{uG~nx_7o*FMy3FzAw#Mf9AHp{<3HYOPew;tXJdRc9;92#dyK#wBOhE}T0=i# zk;d@X>c{uO6L|Keow+1HEO9-hE3hS!?{&EzW9meEeiGi+RmbDul6D9mqY^#t7q-+a zlJ=dMbYD}XjKb~vQX^6~tK8Qc3ypS)Qa$p0^4w6U5aTx6W7tROxxcu?nY;Pq+xYxY zE70HjGc$~W;96LyneU%t8u!b6$FNjTYpM)j_XtOpO)GZ;c^xCs(}AN&tA+w<^orKg zW#tGH^Ofeh_)u}OeqFO3w!aL2gYUt7ILrvDvw6L_-26k z&eP9d#j&jP1$FACczh@=D*1hKC{_^vRJq<@X^dl(o>v&qb6E04gU(vB#{&O?j$ zUS`U901`ZH;b0RXeQC5DKv}gguLD!J!GZ{di~T!97pI@>;5|gJGk5SKY>DRBLkCty z`z>Wi2^-*SqdYL?x9^*O_qIZBoP>tOOqFsslI8`6tUZW+-5Hq%UI@I6AMhpt6iq^ndn3}yAa_!A*xsezwxIpNNL00aU# zipi}SrViH5%N2B<6Ye(#r2=+mGi(hEyX+Y$7R-ON$xkI|+Y%`n6$e!g z2UWScGI<|)grvSN+%D7AZYwzhB}sNv*Jq$A3`>ZnIlZ#=+v0 z>d7|b@z@5OOI~|3Y~PHbC2LYNIpU|u0K{8R*2CG(~^9hOBahjkIx!!!+Wr5YhB((-BON?mw^2o z|C@1b_g}i7R^~1`@xr1;k9rI43gaH}vWBlb0bT7w8F{|cSf_pBhDk^KUNdnqJWyMJ zp&ffTEP*@~hT0{cYI>);#XE+o zeroE`@jfpy+i94E7Fr|{j@jj&fL>yDs?@B;pC-lHgkg-Dks?lJBsS`=WdMD#JbbOr z@;Xk%{K`#V_M8dJav=<5avT=@LRX}=Lm&!YN?xjI%zhb$_X zB79VCb);nca#Yc0X;KlG6I`&zJ*l{F6X#!A$As`>e4mZkfIV;Q;LfFN{_msaJ0{~e zC!>1b@)$2jyO7*i)Zkf%A|`uOTO$HwfLli2Wf zh0FJPkCM9gbEE)YY=nB$bs!Y$d(@dTWX1Jeiy0D#gP4aCPVc>giMss+0%cpvpZ%aAtC|ii`dXzNiSij{7zmZYMpYw;V*e%pr0TSG9R2F zOPW%%$WgeD-NUeC=Ywf$jFfb#a;0-``WC6Pi^BDrIooF zy+{3m?KEti+N-oL^}R&i`jCF=HIO=fDwJ=Mmq6ooE7j^A<8N>xeRYx!D3*l*phwR@ zRtv4KnKC1Inj0BF(BE%Y1T<}|FoWmRj)}J-?XGf&PEG@S>|ei4VS#q(o)BH+__RME zUoda85#{J|$!p)XJ_T;3Z@$uRT1oXlid7RjXTs zg%Pc~ErOqo^5tB0gPgku8j924c!*-q#l$J?$z5G}4vzYE|CFacpm!#C8k~FTcP4(` zRoAh^UK|I=(dP(A_fJr-hZf{po_l)uEu1uqaKg*SMZdv+>0@_r`L}MC*@SmxC~>w^ zJXpF)ajj~#5#_8YTeASj0I}3K-0jZ$=B;JH@ULNM(-x%@x!rw$GU^a>|9Jjd*QJ@Y zNPaLWhCf$wv`eV@E6($(29H5JV1223H7;qIx}*N!`j~=t>*m%9Wk!e@`SI6j4XyVOm?DG z=Clj%nIc&(vD&Q!0Ow|5ivJY*WU4$LTW}OmlbqU)7_cFTJKd8BNU7EvAP^6{`DDg5 zWsF#^sQn3^7vM=v{3%6Uzb2}~5uag#?=Z&_R*G^aoC7qQYS)adSc z?@@nl{LWu2CPWb_1|Ado>KMlpdLxMW{I*2?3vVLN(akPk0h;9=%bf|%zj{7Ion0yV zS%LuH%8(yy?0JOWPsPBb$xk*LK*ZegwJaCr3$L8wat`Kmi0H~6I8O>Iw5cl^Dn{d4 zYd>MYa^J4(b_zO7WrrW{Z%^@~OGk)dhii%@iEZsaUyV5i6hXqLeU9>VUNhFOzROx- z;AGZQ+eh{r~FO4a`eO06aQ4G;T^{yI`UkkZ2ua^0~+_fRv%x81qtu!XVS zL%?k^9G5XBP<t7ekN;pu>>6aTk~3ADEgbCWR-mV~i4)tzYQBy~X8|B#g)2)q-Jt zWDZL-m>G2s-l}?dx zx;^l1?UmtF+Shrvf|sz{5Y`OM?$&QVUXy|9BmbUfeQkr6)kZ`E9A^u@^de247hTVJ z*7iW>Z3!NxEw(-Tb+xrb1oVVWTm!;0nb-7;S0>t`4Ib~rlA_973!Ho(qw3c z)|0cJL$56obQN8Z$R$6aK6e&%V}|VDkkhESGe%!IS3LOOnbT8HMDE19ChU=KEzHWQ zEOr1RH^Vg^cB{s*6jvXD;K5XVmbdwBIb(_EUHHQ@qjmlsGR@GmmMJpK=Yg3F`G*Db zQJzPX)&!9!A%VQo@u^Soo@S-fk?IQ(xfO42)+=kl|5i;Fg!Eo6pB|SUb-vYHh&?Tm z4kSN8&ub_68{+0~=Y%fITq7h0WPSeRfelD+UKUnR)o%7rxLA6c!7IF5OEjFBHJ@Q& z8@jfCn_R-Sn5&-SSje10hSfKk#t702gQz&8o|@P()yhZMm1ruY{-+$2hc;Eywsy>m z<%95jv$DdREd1hevJe~`O0lHCGl7Ejw0OM#!_QRW=|4}xyNa@voubU_)>(UqdB)Fv z7=^DO1n)x^wFh=QEk24R_h{*`Bfz~H`GXd0Tr{!g=MRPn&`vuA#N&~%99blvh~ zq+^A46FgFrS{AWBq}Tu$`r^>|Odjp^c}+k3^Taa$$xjeydrZ8#e9(jTRjn@xpl}J> zYT;7IQTW)hPa;~NM@T=?$H^Pw26=@C`LgqAToH0DcU1m+_=>cc)tJ#OPO80s)%Sko zt?sBBb1>f<#(yEeU>MxWv9`q2YP|hBuleAGKK?B^|Lx4qq|TRb!xOB%;5-86@TD?O zh5KUd>%EO)$w~#o9t?!yKteW`n?Y8mR2+{NK?Fs+)D1MvXC3P4)iD#WX)8@CcTIag zNbvA!%iZ$axc|t%Y1~Doqojq}=>2CvxEbZxSR&Py4Qx5d-q@<(a=zb&s~S$U4Q{`Q zCl6XM3)wJkS!#@J2Y{tyo;EC$z-so8d74DFp%}9V+&aBPUo9=Az7MBgUL<&~L>sr8 zfqMN`+OlF8y4l2InY6%AC@{CbBkgU{KT;uZ0`XI6e?t0020b`dVUN}LSDOVU;R~}b zNl~40fs4<@cUX4s*8|rP-PQZEUT%4%_Sj&`%UvjZ-0OgdCAcRBp8U9~~8I!#*rC7#uC z45Gel8FJI|uFMOgm9OiJ%ib}QBlLNGN1X(OPHH)q(nu~=(sLM3n5fn`Lv4N5{J8tQ z39Hx67&_%Kn9W7gxT0eSwjHNqy%~fw+p<>?kbPlccgmjgcZh+`bHGyVlr0Q32ML{W3TiLhLJ5_)G zx1Qyli{PC8Mlc+8hL}H^Te{(U+jvMC#~<2yttk56H$Rf3RWRKDBMc~wTW7o8_^_;b z?S7goH9TOu)zHZITQcCtPZV~Q5F=+l`|O_+@vUvnaSbcAFE*wW4U@Xcpl8f{t_-tY zM@SQ{x};=AWaz8d=gWW!kGFa)h zl>962jdtIpiEL<1W8;I9IX|(oufvH8aQ4eHHw1b}FMJ!+<}qAt9}p zlPKx+F%9fD;9)CQqfuQ&x4z|LEKcgJwBant76Nyu za(tC4e&|z`i&tK^!odP^$yQ=lChfgTfQ>m(D}hU+ z6?!!$^+R3++)Ga$A~V`eRGu!Dm$cHu$0Gz$#i=k-Ii8f zyB7M&C)x0!X9nv-OH*@~4x@A(=-Mg%yRAyQZFQj&HwIKx*GJG^Qxok==N*QYCx~;2 zNw?xOD^H7@edVs|a%Uqe?lLWkFf5L)s#C5$1?^GKHfJ=XxglRJS;G+*^r6e#cK#-c z1n>$dN-OFDGTGFUM7$?l&sqb#$z(?}t&2c6FQR4|fA*?&LnGog1{G(zU#o>v>IETO z7+Z6k_};G=VI-I-@rC^En_|ZyJ)3Y+B=EWRQPK-cH3zP1jv#L$7T@GNx#zR@ZID7) zi3>U^qyB_Z?%6DMl{Sq=C7HpI=LL~>y3VSjK{HIfytHm zRV6bJ@J-xr;8sP%6?hRI!ekn&AH|q|8xr4MPiZEl8&h77%tk8mH{s?&$>|+9B)Gs~ z)QaG~YFo#ak7TQRy>M5-Hvsf5_k@=BtO~lcNt|l>D~ck7Va? ztnV^7$-P^8IfW-(X+fHfl+mQqzH;a$0KPcf? zu2P+D(^MyAIU?`=r9vZTyRwSXn!aVDHO|TFY9qv0d!kfGGg=V4!qqP8s-{irhM1&O zs08_qUzD<{@@y&fN{~%IA-bKVdtI}K6jd7ZDgN%v7#5mGA^>XbQ3AC|q-r}wKy$k*B6>PyZc0r$7I3BeB)o^ZO z9>neb89iF~lRHu!LX|L|myz2pN{Wf~x#}x7)b?N~MOiH6s~9vdMxw*7r>Zq2_h1n_ z#`0r4ou1UuB?ud|SfOuPg` zo%A1p*@$t;1#jJf5=5Mq^jxqjkwdNHw91r!F8u=dLXQ2it-pylqZMyZ^Mhiiv>#j2 z!wY>E2pal-$f8Z+x;bN~B!_rgXmeRGg1f)IJ@YugYUpAi+Be;SYOL@=2By6`;x}Rs zA1cN4_0+76aj#o+69XsSeRcrFQAsKawTZF}w{n}F8eu*uf@?bGt9M6t__D8nQdiN@ zN2;Iap|EV*SyhRd;s~SL2BUJVa@M3k+T&_^2&_lNipesaOb-7Ck zAbnJ2hGJWH^QlBcjZusUvB)1E0eyJ-iq0_dU|}7k$)jzD+oY`J&UyqnfK!C}S`e}}*PCq4Syduln8}Ils>71^uxcKwlNq#i{10V~XJt3zJbS}W} zBJ4bQ$vOCXC!ANZoU4u3F4^}~KO~qG8Q6dpFzCS1*4*nMt9 zO%y~pmS;+eM#(^h<&GsJJ`X$fRTDu7i-?*OE@*`HhxMBQ8 zQA>f$JC;=ExPJ9?wRpMoN%A*_p&p^ofe$ovM1=%cX!@fDSe*Gk0O^4=;K-<{h@o&u z@=8Y7zO!0w)m?+`2<7db7WKY@1EN-l*wIjioE)plIDq+bi0@}P#C&6WYA0tl^Im}| zEhQ;0!;QLrKGLdI{wmdkGjQut%jv?TCkAF6tENr2Wh&1%ps&Vx@37mI`?>9GxnuNm zbB}37t0npYZo+>&6cu+kQY4Q)0iX?%U^lMkF_yC}*u4?UWITooANai7Y7b!Mc@cr& zGY_s9FOv#X6L$Z!7Xa5TWwyeIYChm+-hZ!qN#=mcG|6vOWVYgNwzLeiyCvF4B?BP= z*01YcDR6bYSvs0~7XiYqTo(NH04REx0&LJ9ynppixKzQRZps zxRj=cT?4NLE4c2@)Xd<+M56ujiM0z~(IG?MOwR+S41+s!d8bsv%eb^BBmA+c-FOnP zp74FR2%m@u>D%&kb~N(rd^s{ba1JIP3DKzEUHPt>a5oB`g58|Vx?6Mi@&8Pgjz-jItN;p{?BC$l^<~ogF@9OIMXfgXnrLC>ZajvH} zw!04F>sS4=M*pRZ1_5BoSufWm2OB}<(y1_B!uhN1#l|^B%M>d;zu38NZ^5|T?oU%J zJ-5PI%eU?f&H?4=_q_Y*OFeCIDRny|3Z-VPy!Axa!z0(N$;Mmhfj5*@s$&fe)cD%p)|FZz(QVT_eNgYf7E$rog>}{R1qdUn& z%1j~Ol$c>UW%F22U7wS-T(+X^om^L+$0&?a3OefiqNXyDo0SQkWpHf=-%9{`fEFe8 zhhB}}3}(`+s`1F(j2WcV#@36VfrlL}%TV);^AHE+hg4fMlJ z`Tf{^W(c#iYFjYH*>u0NiE?>w|2(-XODDU{qjKVtM}MCr?n5**{UASlhfQ+@;d4bD za#6HvWV2^~akRPEW-sxm!RF*|Y4y|L?r`eiM)yo(eZzK!tJkfDdv*VNM!OGlysbuj zRH0^QB)}ELBmI~mzmC7{kDoQZ7$hQ7q*b0pfou4>-g2%OjJl051(%(xc*+dn+?M1z z&-Jl43_!41*T(&wA_||gbQ)x0972G4! z!)r%>TJkC5PTB9#E59NIL6z?vU<-&?QyjCp|FDT#(rVC;wIhDYU6h!CaHMlBlbsWa zuT_Y#+@){G;Qn1^(G+ZaAi?UmtaUz7Xh?_aYUstMPaKe;C6JPlK(EG)yDadoB4kdP z;mUB}K4MeO@o=b?ryrNpbOof!tU3EaS>se`c3k(1F{+tJh`>8~l3X5tYm8PoiprX0 zEe4c1&+s|q1Y^rOQsjp9cjA+W9)zU%IpqPg?bnPvvn4dm4Ft*OG>cR`pBDOuO2gv@ z;Z25RcSIr7<@1o_L&1Mlq??CNZ}w-LjLB{fRVg`2kRGY9tUbqgM%&eMQVTh!(^cuJ z(oEnt?XiK<~Mss32-p+L%6~Y?eEG(PPH366Tnb zOBI0+;(lxfAmql}69DjkeGN$oIVbHKzlrrIugWBV?)OO8fcTK!V-}AxKTvS{Am_7; z!bbxpBM^2&v2Wk{<9jlM0@Yxw(K1UAHnT1`&kENgU#2NwFl7E}+x}1o_*Z8(hQP)M z8enF}tVr&vD7HKDl;?dM!1;Nq!jRk&(Q z6lc~`dmNl!WPmDf#o5}JFR0fpC!=u-V`tCWwmd5Hz21O5D%RaxAT|xXgW`H*PH16H zsiR;1E8g1D2WvzOl-@5dKrl)xS3OR9icY4Fo^G7zH3=MI}&0E)%nPTuaozDX~uPI+?Yz!XHzzg9O}OTShl+NWA%_4{Y?jemnT(K>|Ci zu4ZD{Mx>H~K+7y|V}2e&G8P7%!Hqg%)+qqz9k2lh^}* zbX6VP&Sf36OZxHi?GSE7+rIIu*t;b@5s&75t~`WXq}S=xzjs?(O^8UKcwf>eqwaX) zR2psis=e$_zVVwu93=g)Ejv}EUjL9bz~Mn={$asp%0K93wYtV7&CTVP3U=y8dLVH& zKT+epV7G^V-@ZyT`Id7%O!L{-*6~X6EyaxRiSP5~?h?Vwx#~xjIwRMJXbzZ6`hins z0v>)fSs>P4lN4;|YjeZ@3BhBDV{ip!8MON+$fwDmNW+nvj{#KoVqW?IljDw5PLSn- z9=YBkG!vcV`nEZt_P)D;yaV`Td(9N*G;IsoKF#hAG zCiHxyt^?2e96;{Tn(L~^Mb}&$X1CW2@88EMR)jJBuZI5aU=K@(xWqyZ)62xTU_HoI?L4y4WWHE$2ISdkbkHxbMITH!jGwP)LmI-b1dDcq}5$ zNO&vp-~YYa5-i+1`#8FobRh zS${qE%l^dB4bYXZ=yZy4Q>EM|wdD^|G`1)FCjCh0+ymPerFig0=aSaR{>Fd2FRg}b zGZNGOyP1Hf#%S`Be?2vYdL_%sB6%GXZ%!7oS}dRnE&%}68g%`Q-AW~J*!>q!#jF{RY$ZM`xL5Zr9TLYkb@@?u85ck)H6Ietu3yp5Yd6FBUy-wwyKYSO^EIAJuclUJXf(~fy_mqyqUL(RunBe-!k!#w zmhg!?U|oSzm(o0|2q*^KB$<6)Op zm_gvst%$-!h{%e%n*CLwXbd?Gto9~RS7=CqIfr5rwk}upyzp*LxkrKzqzPu7OmVec zVSqb9!BIJE`-U>vR~d&*iE4@OC8w2d#zK0ftb$CtY%_%X4PREk#C1!Uh5UI&02A%S z$S6xGQiy~Grf zl$4;^W~6?-v;e%24T8NX{q+t?groL-+YHV68;WI8j_WX{in|jYn~znf9jEAgmG2S) zo;H6KlKuYa3(JKl#(>J*6Qqs8NfPBt#Evo8)%HR=at?t%+P2=)o3H;tLe+~n4BhK+ zfY`UQTuK*QP0++se_alwaj}L!7v|48eL!4F2o08927F0ZT9#EcXky&jA}@g#KHFRi zPQM!Z`Oh)Rb2sVB-$YKQj;Fru1b{)(?869{=ZgQ|m(|lklP5oBdN^S7xeVlVml4il zt`K_U7R0Cw4Ej$&>;5;{8v&q2qj{(EWf_81z09w4L%TVqp-ZWTQ+4&y=mfi3EVN6{ z`}z{2%u;f|T!4F7SELpW?Sp{>?uW3*5`^}a10k#lH%*0?V)&i%zY%|$QWhg~k>=rk zr!@OUs>Jw*es#&3LxkshUR71O{Y*huqU#fdMJwm{WqMyFp+q?IW-eHYBq+lqX`LbH zY|H?2=$u}@5{{H`5Do3xgec0H3LDD<{~YhMMGGg_=nEEQ5lpTP@iX7m3NcFVDUosf zy2Kq7O%@;SlT>@s4@F)R zy%`Jeg6_Jv&~;kM-~Potla{X;C73I-xtL}l@iJLTI$O3jXR}@4ue*0Mmjy#LuZ<4Y zcpu*j+SLrQv>sF2wL~_(JqYY~8Le)t)ZE(#2JJGElphniiu#H7$2cpe!e@@En)UzA z#zE~54u98pmpJKxk7BdzmyqRJ^cUbFrM$BrfVT4)%_JSC+!lDZPq5v*-3FU5m+dD& zN*K^Ax_Ca~U}*O)k`f6Hu(b8l-(9h6srQH^B+UTTZ@lkSL@c=d2^2j_H0>))pv8m5 zW*|2+2}Z@bD6%N-i~8;Uu|u}#>?YbbkGZH8`?j}5t&IaqBfuuXk*(Ao^$x%z@GDky zw=u0o5rmIm4HME=cpp5J{`y< zegtlwFw$u;j^s8z47l|(R@DC#{q)odE3MFr@D6r*<-S{fOb*%_CfPa+n|U|XVrP}} zOw;4UHL!(Ba3~IBd&_zU=9bfCQ_1iP2e7rEkIF>$oUj9n?s3R{y7u=enect_+A2#R z(#b$VxRd=7I;WYakdhIPqTHlM3ZMJ}LL`|B*ewPloxTtIGc&h2CVZ}GTKAfEIP7#V z))aq-YA{_pC7uxwZJW+dy#P*Cr0TW2MW!0I!UyZrC(^I&Tit0jLw>ClAMKM=)vc>e z_Jyb5%;QX3yYDev2_tvSn$b=-8hRSGSaY|=P38r2RoMc5#wCH_3#onlT<5NG;7_%e zd#s(ZCcoRCJqW_KY%ranyhyQ+d^rDTm~c>5UM~D~{(eY|k%NFgMfj5+sX+-|Vr7GA zJX7@hC`u4HUw(s+mW=zJ4AFSMTj!G;93iSYajmf=QW@tC4q|lNI5YV$BE@uVqu|d? z=zwdl>_J0Z)ibt3j`NVyiDCz0^^d$4`BQ!Tp}q>mE!`Voce3B^1~9icIgs_D-qS7} zM~cYOOf->Cv_W=!5f8Xn5gKP6@{^qSE6;kOCXMW=>05Si&vU2UdUY>{PS#8>%T|le zlcD3v7%ycQom?pUr7Jo)%cr^S=ZBOrU;x+6a;}A>X%;tTw=4IY9!_d+ubu)^bZ{ta zCn|VcCBU7l$bUXX{^N~_mNXL6dRC71K!Ga;*m&F$hxTC z8xeu4ZZi49{3@oobT`sMafggQyJ) zVwla@>`FQ)RieVkyO#?tB{Lwk6w&WL)$61k5@D(@`YUY&+C$0Hgd01!na3e}Pe&053j~Xd{wTaTw)~2-urBW@@NzG6cMeQAgC{@I&ReQ9wRBWvg2}RJ_YS$)q z5Jaqh`W(meI`6)@kL$j#>pIWR`QUQrnI2bjgnCbQZ_NO8@NfRjbu8m?z)usJKtB>W z@#fT`K{GmjFo1x0oNHfI@{6X&SVTwcwBD(<(!$KT1J2TVaHZ)>|3IlG8bL4vy3z-c zRLM`Yjxgg}iIK{&^2>YSL{-c;WxoB@vS^X}QtN6~&uo&5}VQ%mBr{k== z1zsEXfz{D4JC5Qz+_ynj@?+R+fa0`(*#YJ_me8@ug5E&a25(=Qid~K^;fR7**$9(* zYWCGh`#5J8LsvVp0{6l0cdU~q+*DpVJUciYIux?M3GipkK7}@I%!UOWlXh*Av*ONN zfTsy>j-k1KXMztLQm!;KyWzqc&8O|EO)Bt>zF%!`u3@=8eZp{dJYwL=kmGNpbX%99C?hB{Gmr+g^mDe}TW)Tv;vR<`ktR#p= ziCdf7YESwJ6(az1Goi1&Kv?2eL{!b<7Zv`&o>%$w`D1~u@Ap+~dkFerJ-ZBU*@Eo7 zlXsR&di^J>)U@%pt!w*ks{3({SLK)sH+xJN#|zWO!?R$+Z?k*u5GU@VGzce2VV#JZB&!zCI>aAx%HOg;HxMUv@9 ztzk-J1m~Syg)D#gZ#JJy+e~?3G?gR>&!=S-9{A&q!Jxe)x2a=4WDacM%5gmVoPfH$ zwI8x|kP)l^40+ODrv^X&{+V{g@?b5->)7Y+L=UH{)zcLcqcF*t?N?A;nihu@0&I~l zZFMJsJo% z`74JVX*Pwa?v}pU(mnDYYdLByd7y55mGSREh5sltcWyvVid8?(g!?&bvBWIve?{$c za&q$8akrwQin{Pr`p@LRJ~Ofw{{oxqP9s=kGTH{~D(b}<>8`67BmrihD9kHmWYhYk zdECa+%v3&7U>=r?{g1rTLcj}2WtOj{#Y{iFm7*k69F{HE^;TWB+?blOV|klU;dPBF z$0u*D2t`Rno+f4wQ>6!O+ht3+shIhg6HJ1Gem{;Wveh6jMXH*vEEZACWZ!M7qbsNd zx58LJ#_^$brfJ2{+WaeLom)7*hDR*l)PMc0l%Co!J=tu5u=OzAnx{ZSzQ>?7Lzv@pCf6(f}VO?5=|#`TyU!#RM^?Z#__X@#e56ml$*{9?sBF?nNQ>< z&EDPZ?&pGD3f2cz9~|F|Ame^SJyeDD&3jRH{829RGAw1er4r5?JWEuXG1+RSD@^{I zi2Yyl$Q~iFjS5;11L9v9-tgLZ9U4uN_ra*CX|PSzf74n&RweF~mSxX)yAP&=P9wfF zZWegX$9fj=7!^Fs#FUv%(|x$unmzwE37_i@XnT6d4mcKDhtM5cPifbPWX{EsH{Ta| z&I@@!#+_oN7CnB4{!r$Vv^K!|`}7Zpe!mWvhBOhW^MtJZm;tW>DBZ@*UDV>>s{3D|Jl8>-;nf`%PLy;Nrh%ez6LF~5+8^HNn zn4Jo56>Ut`+)GBMR&n%DpHmUVaX(8g?NAIH#uf*=Q79VlpXb|%#)ube`f;@PUX@U& zNJ*ndAtx3y5mvnrJ?`J<*fH77Kd3iJ9Wfdo-*5cm;qy=bQ!KUHSt!uj?*7bt+02)+ zS#Nuv??3(b;mN!Oyyl(JitUdSU#-91Sxk!1X8mvR#G>`U;-EyN#1 z+TmMwTdkMBFgl*?^~%l$<@}N}%;sc|@1O~(7LijOzM>sgE%FZS!8<~~@#h;V7C{HZ zi=K^~_XYZ=rOreF$Zc*{IUHlRzpSc}FO`5)X?qs42TXm2+}PiHD`Ap`i*toQ%oW7| zHR*u1iMjkG=9W+*_PFv!Pr&>DYIp6a5FF$?4*b5{q$J*#oxoox=GW0h7q6RR=Fk;B zqZY7u76^`&R2cwbpzKhZCr*w{Bag-JWT>$>Z~LMIc7Dl<9Ae)f@w!@JU;9+oBUBiL zV2@G_yqIw;LRVXfi5f#(UiaS&3I-N(?G*(tSzBozj-*6nmABinkLpA7dsf&HCDVH& zsK8IMq;Rr`8b?!dQ4rY#k|%Oo9XvHYJ}yqHy5iZCI&ky5Yf0?RLgo&Au+UlqeH4A# z59|x60sP|W+kF>p1OOxRm(rrnB?i z6QI<`YqdW^3u1))fW#7a5-=1$zg^YE2w9;IorY?7qo{?y_U10~@y7||_$ohVKF8~7 z`aKNR;4tK@lrZJ~##S%HI1P^7f?gazQ8@vRj;C7Brbc&&H3w`;zp4Es>ltMyVt)-2 zk<-1g(ogiy*TVk`gXhrsP#KR+4)AqrumY?e8~2Yt2M1`AhaG2Es(#1z`k#{2{T5by z<=h6c$$dJmZ|!=<3qbkO4riy?EXD${JM?PG#<$;^)a%`C4Ye!EZg(r+tF@IJ=g{!@ z#tw=CfdgGXfF=M2R<|F}{QkcKETa@qJFIcIbG|t1^8~RrkNHP9%n@UMdk+$NaJ3Uz zlO{12$4M(_*CEnvSDD=39W%H>c^P0k0;oGbBDxYieNO*d(mET~G6K+=qgv${|DJ98 z`(F?M7XvwgE15Iyr=9MnZKPKUG<(KcQrGZC5xkwQ3OkU$nZ=ag_v0VeZK{F}=Gs4V z-xT*(bCB;y$`8)<=$D=qv4Dd3Ux(ji993NF;&=iy4um5+t0?*>7BdjexKX3S35rJe+>^BWN zA2wP3-7LE=tpf}|%v1KH-G#c{f-72cPIA720qp{RAMNb-S|3&iX$|eGQv#vXw3vw5 z{(l3zbBDwN^RqCjKg4G3FDIG>-F+psUSt{)DAvF9DEN5&H6^xdPaxCV$hx~CbgNM; zZ^;DR=z)6(rLf4aj*S0AKS42Bo%jsI=?SQ%)6*QUZVunHqS+$<^iro@o1+VZh}V`IRGVj$4|1B=lh%xun|m4RClL=n4N|Kq`i+AWYGr z1KsRDklw{e*jbGW2^rnfo;C0nIh9MhtqGpa7A^e~4S_9i-AP;={knE(X+T+B2gh}G zHFimk~1jE-w(-A*K?+G`r57L9FWG%m-*!YK0 zu-e8bU1+i&vfy`Bf^x{9othRO(?9^z2W{kuIHoPH^2Q){&LqoTfS0t26nqiHvQR0z z+2iki@#Y9ugve9-&k$;~yK%B0Da5ucK0baVdIrR`jD|qeXM+Si z63(}G&MWpcD{A`G%7hz)4>O}<%3p!6&9rIlZQ+b7rTe^%Af(IoGn5%eQkY*<^DrYt z5kiaswX;Mh9?B`*IIAuq3|$YRO-B>gf|h$y7tgRf!7G*m%<=oHsf%2PNC5CSm~c)4ivR`x}8(6%JL#$ zk|1`7@*6*or(?wFO(}yo8_14~YZ7Ev&-1Z>Q$6-j8e%NxhhG9D`C z9UF$2_u-hf$dGa?tG_^OlQc~6+OT5Q~vg(y#$gfq2n`XLFJ%f>_TdJ z>-7tjxxX}A#z0pyla-8Drnv75t;F!pCxbjIY)tT56rDFF)yI*4e>ed7Bx57L+B+ z-Dss_UIk;K!&|%WUqRhuXWzdA&bzBwW;8uc^2WyR^TeWnTiHJd?}sG-LLSjFu!q)L zC2^^2oN~0;BKe@dUlZQw(81ym&hu$Xbvh>vMyiCghUQOy8^X@U!p?q#;@<|oE~n#O z>-C|^$+sh>O(%&}FJ#LkJ*TGG7YKZ&&)%J}f#;vhDRYsUyd|;kfhz*|K!i`pzuMkS zzlH!P$4YjUa8K5i`8d?XlN5(XTR7!Fv*8DHX58dnm` z2yj2}q5!SOg8O-LH`O0ZMI~=>NuKB;sk83Zhr{*+T4H4m4`dJHD?Tnx4B++G)rW){ z?~P5P=4{kS^bu&M#2u#SMglGB4Vhk(T;2jBU90Dv@qzNG-v@4(JLa`CRVkoe&{7Aa zUiTPjD43k2|831|*j{28I;jSE!mTZ--Rea&=#*J|`VvB!Cxam&%TQ^oLZO>}y@@n}2pcqw0JH6n_gN^*;r1>@c)O?q zI*A7CWh6`)OSz0`^;09^B6q{8kz9!e8pyZZA1lmM1{Gs9Vp-jcwz(6r;1W(uL98HE zzRX#1FWj0jU8zSZaWAFC+IuMX+^ZO0P5W{3$5&_;Eh;m zw*?F~wvXXydw4>~rd>|0e883qw5h7_W_L-jy&MaV!Uqf!O`(8&j7H;jdWr=Zd^A#3 zX`uO?UZy)&$zZ)qH*7h{*-pmEd08dz7ANRZmCX=+HpiF={Qp>9#Ct&jkghq`vllz5jxQB z9w%#P2PZ3$8mcu49NUp9%`lJS80?!{f$;bN)L7d9^|&gLUl;{lKYOZng@C(4bN5Nc7rW+f?$Em71$L|k!s_LZnd1k zEF>(2?hdZT#TWM-^InNY0mgX<-=^rIWSs?O3L3~mX~x0d7seh7p_=!4zUmg-Q>C=A zx=v+Q$o1>^94ht6kwN5{+)j}MntDdhv6If9Xoi9O5Q@ahbC1mIFj5m*0@lW8*zZea@kJ2=1w5QD$>j3W%)=r zV;_Zg`m6*=&9%in{o|ax0bV(;4Mz%75OflGp>V@(pNKd2vzgQ!bT}k_*1>{sF*s4I zo;$VZpfg#x1Y4(s^tnRelcvovmpstQ2IOlU(BGyDoS;2$l@GOleq5L9>*8{OPa^iJ zMz}AeknzoL-;2bdvCVtZ!1^1Qs)cI>)Ggd^NpNr{KV#Rz(2smBfzKBdO?-{bGe!tu zG$a0c{ll=y8fXuFjEe3$pR)C}Qm)BKPajngrmL52=I>hn_T}WGUs2n;$551IZ$y(c zkN2GfGmc(OSh6&;AFTrk&5P!Fl!`$#1D(8#(yp(rt3;b>f^UX=rQpZ==2Y?(Z(j>>Is;S(3OmuFF%{M8E?wrX~PEr4{FEsyTiYg3`=h7=UsXR)Tu6{fi+b0j-w< za~%jeH;Pc4#G7gc{aUGdzW!FY$w$FDP~=deKC(|j%kI}>t7YV5yEI=bMSdd$We~#m zlIkA+u_3Bx>za!=MsA-__RAwyu-y*dpK-#=jyT?1EIK>y9SeMjgWv>4&)bzxI~Q<; z(Vn&(b(&T!{hrI(=_QD-`iZrrg`2YD>+_NB$}b4{{Vth%bjAZwohn>}AqOOvRW7TB z<`J79R&epzEF;5-#nhTsi9S`do2?eHBPo0=!c5)nppj04dptXfU}(Wo*xVMQWJgb! zPtZ`Q!%70p51&Ca{mNAJQ)aM(zl*r+-?Aq2XtQ@G!MyGpFJ}U~#mvOodlpM26LN=d z?ycPayHu733vntlUV479-i-iS8?=o4en};xAk42@bEwTHSYVJVkE5OB>$2DGU%Qo) z$x3%`?E^)$ng7;^RpN^-y)J?o?Cgn-3X=_hO%c^sDL4&P zKw^k@ofn#3)02HXJmm0i$<&3}iGPhFTLkxJoG%lFy;~EJC)`sh(X%FGer+{5RF_u0 zT+5wnK*EP9&fKDslA=JO1lHC%d}|Xn+sPMtV;3dxd!0#Xziu%;7w)i4Sjd2Yj+e+^IUO9A zcxgI2{Hz06`5bXHzfph#EO@@U)b_ioqP%`w%uj8~qLKsgi%H&Qz1#7>c?NV*TV?3_ z)4Z=^fpro4KbaJYoxJ-BYM!osbgB5_JJs45p81p7n6c|_p#`z?8UW9!S>W#5)qT3h zF`{};_SKcHmw%%GQ-fFB@Kt)i`JOwLK9_NeOydWI@j*T#ZEdPH0#X4Z4wBi9Q`Pir zn(;DY3>E|k{7>0`f(mB>SsgFJj@TWUr6qfx27>E5I5bK2u+F(`T8F`+3i+?Se_n`O zqVq(mdOq~mg?z_^4DLao`gqj{x=>mU-wlpgLY7o<&cgY$8APO98g`&Jsl7V zT$0j`>K4t6J^iFPK|5Kx$~59zArxqYR`W>QU1F5YChAxz-Lt6ux?zs4_km{8%_Thn z3j2!FHrYx!rKJfe3DD{Y)axfk^>y@_-3TO5kU1R-Ojg{kq+b#?T!hC!E`$L$#N(Kq z=X8@fho?4*%iglW&NOF=EnvbS-8Yoah>ACFoTHvex^IT%C@Cj}=-yBbw3~~qlqW1U zERuZ@9hr^z{xh!x`1!otE4OJzxbT6r_~5*-v`lzNxDzVt4h4k3&7No*<4Vcba!@dQ zbG=b}WrEeq2!cFd`N(6CzwvI7aG2}q6<@%|aR#L}Qk*HYbLC^`FtiCiA>kqzG8b+C z#zU_)6u#R|tq~b~TBUROZ(UH&HJH432t5(dY8UX5aew^|0_gDw5@P2p*C;qHB45;t z;M3ZJx$E1jW3R+Yus>qWDmkY_oQIjSb?QZVe64+&?tO{(Zmd=x<6_5vTn1$%|ITiq zxpg!N@t+N@Uu7|l+?ZOj8<*F?AB`-q4>+LaH8tj;ouas{K6_&5j8Q85MCOcfqv<^< z{{7xto=o`r+?JCpcbV!{8cHkk3sB;L0Wi4?WLt?)i0POr7&qv*fOqFEnDpSRt$9?9 zspOp>F=Rl0xjJ4epWo}j7u}K5!J&SeW1Kejj?%-6WY7Gr?}QjJ2kH{xNkZgs`3>nO`v=+cp?v!xWr2 z?&jh$$b)uX_y1UdmAmu3S%4uPX?snvd9P89na%&|7H-H>P?P zjGk(7Y#Q%ge)l`GT;pJ^Fh4%$23cOF@l#H|j20YJl;PYcUla5LP}myBU|Zg1eQ z{9_y;z-t$!Bk)M=uUYF#7B6macBGJf~K|2C_2NZpQqakAIkhF-tHMh)e|#} z^ku^$cC^#KY2i0D{b!%fzPJq2Zwf+A)^O}1HhFI|_z4TqR3O)DCXj2ot>j4B(r5|J zpixEr)%Dka4;!>jDe`}s7p6MIohA7mA|5YmXF~OT@kO`auv3GR2W=i9|8WVHdTEk4 zf-g>HFT7*FXjHXH9Msy$si?;BxA(5u4)F0Yh%d)oDk>J%{Stp@R(u$^vufW;{3QF_ zt}Ecnj@^&ArMEoRFW3a5qf^HGR*0%&eU6tH@jT!N(BM__gJ>01&a*-uK^~izVZ@~B zl$EN3x_FUDOo^D#s^y^O7L}uY-*h;#&B%0qIeRe7O@))v7gtRBBDgUex?)z0gtuuQ zAD<8UPeq;W{d&{1y%H<1cvga3d|^iCeV2Gsg~gG)Hm2JYYMPd#L{5SG&BwYl;|4_q za$Hm7fAU3W9mLH>umT2LJ--Qsw#WCcm(0HZC&~{IPgR;pV}i$<_Z z(AzLo%&T*jox?C*1b) zc_)RkC{NWWuxpaGVL%1ihE2{GW;BHItZL$}>ijLs5<->}Cyk?t$h2Y0({8qB^L4>8(U5Xa{Ram$GZuxBaYk$Ag6Sk@)X!m+w412o>9aDdo@=(?CIgL4Egj6m>e#$M9m|Ndy zf7)n7EwFGWN=42ou82W7H$T=+Ebpn^U^{!q{9xz!gv9csfgq5@5Lw#sA!yx0PSZ1G zj8ZH_8Gq&2$HS5q@peS_`978nT1J*g5L3{LM~N*OyU&Fsgk+4hti)049goL=Gk!wH z5~#^n)Lb+9rjrb{)a#$6%}2*f9%SzHI>|bBncOE91JLuLgsZrrS%)c<;;toCAYORqf7{!BcPgkc9ddL#z6!@8e*f0=*IkHJFE5w|1sSZ7pM zv!AwRc~3f*j7pEOW+r4Pm}^_y#_wD~1>Ex=yvOsl+0RvQd|MSWfe$NBpB|Rzy9{ox zGvzqf3O=IQFnzuZI0ai=atlPL89#gDz~HkY8v%bn7gYkkPZx9los(f)!tU8S@y;Vj zdGyuN{7&A-qN3q9cy%6d=-tz?@$s;ybX}}*A|f}WKP6n8Zw~Kl&3jG#t$*zv*4i@Z z-LD#qqBQFpn+KXMJ2m~syI0U%Ksw4S7}(b3zQl~AlRq5VQq;z@LyX|O*9fLM2rm~g zS{WD&6b=bUUEVPf5LvZ%92!*>Vyhsvme@|x3;Y2SKc{=S+VnHrDZSaXgrU!Po9;S( z9fNgGhz3m>^0?Wsyr3z<6$3-)A|}_wy5m36f3DWf)!smmKkgHshJ<4MSQzY<*ADE5 z+}&X8W(9>>jbW4fSJ7?|B)arsJ&$>ObkQ=mQAq4~>O(?adeM98-SCe;)beKc>4Vh! zTFlJQZT%lojDawuEmt=4?)BEmyE~E<-wXG|-K~NV+FXhzqeFSF)tjro^Gq4F8GJTr z+znrrS(LZQq{N`ImUh*CBGtEENJO7r;%+fq!3{HzY*0CeRhfs?j9DK??%)+T>_qB4 z=G(p&8QfB9XMy$YpMjRU%Vs;x>Z%tC4PK+lQI^ggKWbmrGM5MMw4l<)Oz2|wJYvyH zV#gKtCO4;lCbmF#vbT%PuKYQ_&2oB08WVOby(wpq+|8GfHYx&($lH}%nqI0qQG{0g zxDb_m|BZ7cfk2NkLf_76B$NKTNJ5&bp3@+@k*qNBShvbw2*;z~MuIZ=bu27!@(|cc zPUtCfTd&>KEqf39)=|yyGV7h?7;OqNSta;T6G#huh(a!w{e# zCHoWcPsVU114P0C#LFT$FjR6%kjhPJ=|}&acK6#bVeTsu4D%Uq3W*AHib;z+wcP0m z*Diekkp~n00HpFL3Qt4|1QaM|o#sVrpiG4o%;(%>3au@9T!WD_!_4VG`)~207c5&> zn`j~omooC_O;4qjJwaVvi2{^SW-U%c92-RimvW}zg^U`Ri=3Bb+x*N$C831%>ZzjH zBSgGxsM<k5ex91&O5rU+Y2JLo%1DPz&bN9{JKt`g-hM^=s^zLD;YuY|Om;HL!^2%! z04G0J0vFu0ajo;Isj8Fi3yAGgvtT#pyp5taDNw%4SRUtq)AzY{0V3Anx`%v~;@em* zi4J*C6CcieD#YE~2KDZZ64eE}1+$A2yheQ+6(A{^Di z&$H2G{d;%Nu|H++Un~ccHLOEl-Bmhr1+G2sJcbIBA9jd4xSm>u0k}JWxZzpbNDU2~ ze9ljv!?U2#->tZ%JbSD&TGtd%ax8Ztp4A^y^^?P=y^K{Os)Llst7}E6E`|>*Mj za_NQ|FQtRkCK3;Cjm=7ONqs;nE18Nrj3Nl1k;S8NhmO~zJq`(~())aa=E^-50 zlZ!iTbYJqkUG~`MG!wvU=&*2A85Rus$_kagys&?o)Zg<|Uz5T9ss@ujPWjy_Fus{%o=n8G!mh|-IrNh@uGmV03q+jVwppn^+|X4+y}wNO0F5jKs^ax z3HVE>K>3i#cZa7Y7;xBD)KeeBf!kJ^0<%tL+Ov1b2}ZNM`4+k76{w1M)<{FAJ;i3S z_<}mQ;G7aE6)J>0F!H@7lyLh%vLwuLKuk6xKcP#Opbr9eOCptLVf&FV4J8nD?8sUG zrOvdgl;9eO2xw*aFxl76`4N= zxyLa2%3KyT%$;H*drTqEHrLbn_*Um!i& zx;Y-c;~+gJuI}3}exjW?O_IsP4YCLNh=FG&v+Gqp^O#}1HJr78`s-M*$>jEnz*QfQ zxP-nT!c-!;R@Gs1#__Xx)eDwdts>j-A+1-x^!gYn()x9n)W!KxYpc=H>6ONOc;}Ec zogo|%!==qlxiB?d^8K*%JR=VML*X4$v*(AG5;5(`e_7YzwhYF5i7oJM2E*`ze4`Mm z(R|}XS`T_u!M~K|JNfkb$CY`_sE{oe-vLrP@VpW!#NW+D!ytTUF*%NFiHioF>jol48fF2hvF;DS z)-lAha#j&KA=2&y&PZEV|8)A=2OW+O4Tpwm$HosB0|H&j9PweL z3E1^Vzw}O6?j;v$YAr)=oXf}_lfTD8oNnX6jW%)CV8xY z#CrB2sZUus3SX*mW@A~YuP*3P7J#rCxh~CRw2rWQ$)aJ8p#vFfHHvyhML(D{M1KD% zFAAO7bX&jYQz$T%F`zIQW%v{G5Mk#`7-#~Sl z`4Kf$FEWh6=VG-cMDRQ-Fu^k2Xg&Dm{(L~=Umw&sxBXTYW=qdM$99eSJ#_-rfH02w zwYGq^$@m>w6F5HwY7A$mqVE%r0UdmSj5ZoxWA0(sBo1IH*}a+p2W3zzTCgNyBxx?i zvTL%qPyaVfyFGR94o}(@CmP<+mu(0C*rz&o-z-D`&VTK!ycuR&pC-~@W@gx=r#m%o z)Q;>=x;c0Mc-&YG1QfciNGsY%?6&`kjUl`427_(}6jCh(GyYVVEjrt>%fmP2TW6khj&2C&S z{q!)gg|+7(Yr2G}Q}%RBIjN{Q?{|IUUFd2J!+qF8tZQ1HC3b=3_C|Z z4_;cRT3hW&(RG~tKrun+eg({Rh{+yp&aoTbP5LzRbOw>S3SqJ~6i@l#-3!(~E>UBh z{>e^|+Tyez^fq^DcaD#*X3)|6KMPj+N|jZ)ft%# zS0*$LDZ$oj4Tk@W<6e8HB^t3e9XbpHqvoPRmPE(9We&yn%lX?@(;G(+dBU5HJN%4* zQM(~VV5W~(9M3DP$EtYT5b||w^50UkxgA?-(90*oKgFano)Qe8kl8>>ECQDZ)DF9evdE;aovmZKyvK|!BMIrC8WUfK?6UrA zvN^|}GOq90iV4=Qw(s6sg(XM@C0>meo@6`v*GWFNWq6-622_{e#@qa=C0vyr!f6Knnqk)25z^&ialR<{g)bk!}_REN1R)KyXQ2O zU+}VMALAvXM6;FPe}PH-u&kAT#c__!J)m7Lo{IYhje+)}ITIPKO!eP0s!_WH&3e!k zn%m6lOU!@Z*$UJ~b35druG~}QmNg^V*%kSirLi&%KFA|oKGchQ72b_Ez^(Nk67TV| zrO-Dw7PszG2Z#QIdeQbr#xlo{GGNNV0vFn+gPuzogc3#u!1<4pm3Vk0^cIhT%@ci1 z<~TZL8o_g!%Q|)rat5ht{~V=6Dt?sO1MmZ~d8CrwUJC8aa3>@S|_EU5f|_X(0z^et%&Gs@~8z zn+^3lHZdlyFVcjxt!9+BvunE2IF3j_8~sYt(Xe}sF%0OtfMAs&3AA2VS@3weR9DEtzIZ~2 zzr|qhDgGr&Tui&NS3a+BFh#%4sb9(I`q!*qTnIvnir;sZ~J+a|e9O`0Eq@g3= z6M3o&JmlrvaBGJwEE7c`k)W{>%k3N>5r$-8Rs_U;Vfdm5!Kf)7ol}-44C}Qvvl!~m zPhqAcxfwK(O6;6{v|+J^YxbYch}YXytu+XYe+JUO4Mc1;8Qf~_>D6^E*>~M55)0{0 zjW*3aB!mSR%B~)Izxo~ci?-Ih`^K5=*vlH{!F3lo>A%wNz8D_;j*H1|XkL~cb$xTL zw)xLXr1oP#+)L@3GBq`Z$`$@Wo9Yo+b^fx281=j7kF{xVG%X((v*G$S`oi!k`-wWv z%0y-iRbdc3eXc7q_V#K-_GP}FP)hX_YTiplm1BX&XLGpsG>~k^-1vU1`Eo((rgs@nEg5UF+9pg^f$OOhonsSpx9f7e_vV?l`JGm&YvJK0qmBs%y}{ zsixLuRd4&&CmdF{zhpJyl1!#d_qJ@O+p6E+hl|Zs4I;kHafe(MtV${n44ka4$NEd( zei@dQ3V7TnJu8#RJ}-1<$kCN7@*cGYQ95(EwHLz0B@{B`h|2bL5XvT8L07m>k^mQD z2|`_{k?5s+JgY-FVnLA~bcYC(AJ2*_F*j(>?g}x7rf2$1%Q<|u zN?O~XEh05}>MZP3$q6e%62w)_GeFaWT-(;8LjW8qP-4w||8a%p_iq%@u!% z(3<=t69`j7mpA(j#ejy~PWf)Si zw3!x@>rS-XRBVZf2&&5>`)dEuY+`yOpS)^J3To+m%X6Ra#x1V=&#{@ukTCLa>TExf zB~c?p{o-`rWzw@t$P_CFFJrgima8z_g4AFV%`tkEr{O-gArriKx0ghvwP44rkj)}T z`T?h|zeHl=U)p{6FiQHEr&gqFneOURDHzQxbc|(#!GixG(tM8%jDI%J3m>l6T!$y` zWLNZ{NQc+yMqW@xR zSy_gWxU_j~X{hV>)}c~p$>H*I&x7~DwPSS+)sLFyxo1W`vAgBBDjE1AAwrvl%|3^p z6T(Y&{4)Yf{@Np%KW8Fs1tPcv+NK)9)X%40V6I7BT;AANgjt4JJvX8IEGuEu8s$v- zFc{q-NBU-7wbszLyS{Py=wd}e2{hEj18ST(oO)g^s*Z-BnTJSmV-LFZmwF|_6gn7p zOZ$~y#W@OQ-A}LhCKmzSg>32A_mtGMXmoizJEdN2j`|{~xm&_&H7;3v=Hfc{yiUeA zMYbhj0tU==(rWqXR;gp5pQ%JAsTAq|uzIb0sOyi0=#1e_^OScFIkzOJU>^LUo4Ard8lVfjuMm>ZfCwEhM0FQUqLCDC^wMuPnx zY=POvNV7+YQj1@)1ib7prPF!y_mBZ7?m!Z{SWrLgn=i4;%4*W&q{{sMybm5{7%b^k z@nhv9);3zmBoFC;5efKlRzFpyftH>rj(1-zwaW`R;8?> z@-%eJ@=DTGrcT4$z>4Mwe5=9?1)sZDZdD{$?0n632)o(3@HhY*FKj-f`N%_d;VC&I z^i%7;)>-ddNB;FC(6|<)u|>iEudm})!jGK?V#)|=Sl_{Ds$@@OPkBWj$@1U~{2((~ zIN34c{ztoIF(wS|qI1 zpI!u*x!Ea1zM0JMn>1~@67G`%P@KPF$-F(#evQkOdEQsXq)<#?7!oKDm{~cDw&74u z{KR_Vq!`*bFj{9Ld)WT4b(-g=iS>oo_KCHtD%Tg=9>eBa!^6ydYh}Xqof1T&kPN_j z5&6?ODsM03lw20yUkq)hI}LD4Dw<_r#NmoL*cKD)Zy^ZJ_~@r_l~ddR(>n~Lg zL^QBW!Ag;|gbrTAkBqZ1wyz5~PKQ12Ic8GN;sXDPE}Qc5^4UXH)o1ydDdd@Nh!dqG zt}<7W@Vl$Q+H*IPb{3?h5O-(ucXgiUFP&Vb>h0p8HlleZLR|{iXH=R=(dn|kMQcf; zGDIbJIhmaV=hdc-LxxvrVrU)&uo7A4nvGxTngE$12t$Z-AF(pZEVR-blaByilHtVc z*JvEi19n}M2s+OmB0ufkM8DJ0Noc{Q!5^Td%iKs+I=p$;^TPP(uyp6^MTHL^s-oza z-ms5fz{x%zWyNg@6YN0lV$d8SM=hWIX>aSPON-?xZ+!r2CdDOa`+Eu?-!G+R5=L=@ zj!WnVZ^mlY!wcJD%XJ)fi333FOIitqD!`a z{GnXUDgpXQ#OojgQTgoF$+)h09uZp?LS@$4U=D5_Sv|f59cum5ff@-HHbcMKdnZef z)OeWYH(T?#!6!r=L9fvx@Mt0>c&l#g57aS2b#k%0>A4ic_1q@{n~5nwIs49}xq<{Q zlc&L#goFxfLbmsNQWmG>&+wFSE9^hd>>Y8`RsAe61Zox!i{Q(}3}+hErdui77pMyK6VZj zmYZ0d2d*y)5R--Ts?x<1vJH9p{4qj}9eE?&dGo;L6$oYAA=0yVZ@GF51Vc|Trzlv@ zcZt`G#DmXpx#&qaesfx%QSI>N^0;=6Go!kiyInz_c@a{Q-1o{V$u6@@gsSBq5vk(A z@yXvKbc6AdM_q8J=nz>1a)E5NEzylISxmCS9KI;>pTS*k3NAwRJ4NEO&j|GI8LY&T zp)!xk#N7VANE<;Dl9zB5)SXA-)2g?J@`o*fBWS7<_h9L)%f|`fAE~s-4(V1V32Z(D z%*z1D7yE8PytcONhx^lnYwS$Vw?T+eZ9By_x>Wl4gmH>Gu)R<`Fy3l%FjpQW=F>xbOA7;Af_pjvv9 zwC<*piw#qRn}6`#1~tb}Wt&6e#_K&r-#I0?dl-YbiXBn1YluGo@$*5{##(=hgpepC z%$xe`t@8sZ%;u=W>8pW)kYeRE6^~o%Z zbrY(5Juw#Ll^lxvPG%IG&S@eutE9h8cKvIyxbd@_P0^pWyYDS~A0#VtxEHYaa@3e5}+o^BG240vsA-w6Ns~Du2XJeXwAylM#r1 z&oD=oGVE2!=~5%;PRhSy+{iERITrLK?BhGbi?=sVbz0L{!p=sT{B6 z7TnePcY^z0<>0E+uKkq%TnGpwwIBHAf7vsiY?P)th0}OwQwxVPB+`hcLqh}4?l5!R zWblHEVi>Zi40=)+pV1d%E?uU%K6k}~Q3)gXE=d+R=NKaonsY?a(&$k0Rw}+baAUPs z=to&HecYu{AO|drl$zOONZIUt2qWCoNy_qhvweCKQPl0W0)^2sKOtQL-tm}Au^-1R zIWjA-YU6HSU8LP_C6A)ksn!U4-mAIV^Q%(~^h^vSLN<>2jFgjYdcQMi5 z%vsnICyc)O0nyI^Ko7|6M;=hq)}Vv1(;G)-%{}|f|D)+W{HgHY|NmnhgpMeZajXs^ zvup=RlAWx~j3leAipbuwIkqF&FFOZEcFs8tj{QBoKfm8!aL&1%=ei!( z<8i;5pUA!FDq6Ta{vNDqi(FRVaO^)iqDNcHp=n zFa&0GYq73Zs!f{CI8E6}W#h#WYcxotUaC;RjLT}XP5xa?YYDV(Gir=vw?3-ow6j@(6h%zdy| z+8sCb{Wx2IOxzx-*wHi-O|_yu*IE!P92aMuk%_%k__I#5#sf}5YR8d0&rFv79y!5z zz#-}eMcMU9qz z97n}}Kqb`bc*6XJ{+2I!?koL)!%%pl*bnL&4*5a&K6bD z;`xsTZwxg@KlTC#W_kHXgBHKCLVH|1mYjBm5L%4A%(xBP<$T%4E_`)SV zFJO53M)9>GqrG#aEw7ttlPn$vF({~yZI1%N0);!_|m$0QfpEPTqwGf&uKfE zn(STi=`H{gOGccS!kB^By2*9jBsk{leT1lwL$8ydgWy;q9+T?DOSt?6&7uL>p|$>HiJR;CW3n-^yehgb=A(XLaLjlb2mQlQN47L z&d@er;UV-~~p-*VO# z5HNE{1ntS~kdJ#wBW8OYm%q2x2@Ao;Q9-*h0dE*(lBY)W2JT42=Ay0$=5ldzERlPK zr6H^9{jfeM4#zIKW)~S%ex#VYiCiE7HzyFBskoEky^|ti(Dtnwyi_|4QO17cASo}X zk59h1Jvn7&YaK%OqO6B;g+f%n_14uW-K)DskOIG@bCG&(;`R6hCZ+m*!5CUoQ(g-S z#(v#`__TO%OcXAiccNkj`Frklu1|2pd_q{Zd7mS4kkz-b!LbQ}eI4)js@7Gylu_Cn zJ`<`tZEH=yuRX7(<&pi$o;i~sjh(4W$sy@6cG=6;JRMZ|N?yE?=ArR4R77of#oqKu z4z##(Wh&~x_#H^qZ8AO)Mq07a=jr%L| zvLr0dje<@R2P>bN9v93{P=T!L-y=vXe*&Fj@%uV-L5oU%al*uG05q8>*8Z2r#WQ1L}rK7 zM`y)uR6_HF8|eXppA!%Rd{L9i$2kME%rx@hAVEF5B4tS`akYnPl!l4h1&kOLNjeW| zaW(oXQPB02Jx@xBhY5N$)|N^*(2r2PEV2BmRdNVy|~?d=&3ze_fLn< zvOiESoN=kwqN%E#>ga{Q-`q&E?9QOj)QE9;NM2$*mqr}}s z^cb=DtN*|H_rI0)c7*iT{UUPRTTtUL%%St@wi1 zHWJP<#>nm=-EPXii6?TZUY<461_z?>t@hwO&Yf1BAI&eVS4c^xIbO0<^aMuov!z4s z*skV3Dce=i!zSlavy8inJ!aCpi4`5C5j&($iX=rbOb7Pl{&iNJzds0e)UAUmxgo`t z&2>>jNKb@TMT5Wr3b<<&6|~6@HH>c%j)||3^>W9WXKM+qSG{ADJ-V~8yp}SoOZW^k zjcO(g^N?PRcd=y^uq(Od##*VG=@zve{ch1WO&3hkPxUgrawpAi%qVm7g#h>uKk2a$ ztH$Zy7SG}RHi>FBSfp09ty`jN4{*y!$c+`b{3S+l(#d`p&U+ZUYZW!%TjoC3^YQ~? z&VBF3^P5ZL=UOvc)fQ6)jvj7c>zxBF8tGzz3dIdHAwEdFjZztx8(h{RyAnJFEOSA* z4uMSuO8r8yBl1PGZdK_1O8Q9KMbr(#z~c|80lDj3R)Qx5>p=(fuab12zq|xjHFxqbIiEF}wfT?`9|umS`fMBQuelP= zWEYS$e%0j7yLecQ+exI~N*g)3NW1FP3sRWVY*0+Nc z(Hrota37H3{ugGt5 zIu8Oq0X?#+G~ZhPbuc_|C8v{OvkLVasDs;_C%MsqS}{T)K^TL2o^?lF-(aFQy%6?oga%}4G0B%ib8G5fUqRoRvGc=W!>g?`$kx`FgKTV?9O_R}BAhXO5I zb} z{1_U;7`Rw|3aY*E7yS}i37~JpP}~A)hx3DXS?#Dlg(cbnm=z)2YCzt!)$>h* z?Gm$NSAmGrv!6d|u;w%?hz%>-`gP8;f({`Wmy;%Fc5qoclbLQ3!QmLq4`p77aGcp^ zKeBfJ$`0lc75!U=UhZ~$oeAIKBX@W!6bHMJZ722gFP#9ir8&d`Aw5jaNm?5HOhOIh zYf660S;tw^fcV9*EW{A=&Y_{qoqAW#eAA4)ng4U9fRDkg zLni&R1mF{?@+g&5ReTsx_3R|)UUd}yUHcOtBPvR(gK4?9JIbqUkAFR`)=Y?FOEO*K zYBo*~^5Ii*^$!teu+=9Uv@5Lzpp8hSanaq=i+!B)Td)8 zolXYHq?us&3>40`e7UN;#YP`=g1$3UFxpKCsj<8noj)++5nko1{3p+vcj{U4=I1IM zKAeRxCwefWJQwQ79vS%v<@PP@drQo(@bLqD40s1pacfPBipP&TxdwO#nCT#|6YaN~ zA=lMDzcKkS{O*&}arig(Rt(LQD*We7NI($CfU%6^o+G~Rq}uEHR5Q?tweI%KXU-kv zXh^`dvQdsP)rPMv-c(!-bkKy#GKvOS7p0a?{syU=5h91hV7B5V-je@4?9@UyC63fe z$H$#_7bh5#$_sGKRq;{V`N%=)4NZ3IXF>|c&moKpt0YB>lOjY}Jb%CN`eDOX%l)FE zRk`tvYc?0iF#5}AE*Du}f`#Zy(uaUh)#nxucoYs@L>C9DMI@}7>_E2u`p$@=Sb}b0 zRr<}&huY|p5Ys@FnDUJ{vs*2lHe?0hb4+Hv%s z;d(X8iZv)vWJypm`$gel6023Bfspizio@zePr2tQtMwJk=PBKL&b^zS!7HlD)r7#u zFP%P_&Aqspj*Y3cGbKW_6lB}CO28&O@(d$0OUAICL-Z@8;@X&zqKf;QL_J;VslDu! zL0@baKad>PepX(;4a zXUwg`^Zcn0Dh;~O3-Q_Kb7~eIX&4_cL+D#@f4;XV3*{2~VnBRVy0x|TD#X;%u2vU& zZ~GE1#%oS}OYO=A0O*L}r<0lx9VLqYD6)kh0MY6>oE=3PfN>^UN$Q0@9o*~8k7S`f zD?_*MniiK46)@~W5Q`f?Ax|QdGAmpXRa$h$ZVP*RcW*G+Om4Ci(M;&!lACnx7{%}Y zEMA@SoNFk;l2k9@x8V>5i+DibE;S}Io9@K^qBK0|&Z*OC8LUmK5H}cZs~97{<}}3e zMw&XBgJ_Inu#!@qN|wcKAb@3|X8r>A)!HL*1|ncnVm zN5InAxm;g!wcPQvW6JRku6d&O#ef!0VS0M!I1*Y|2F(hHWb8i^A-z{6tk!O}{K6AL z`j_)*FQ=yQbB4sucy{m;>+wl4FFW_SDfHpb4$N0Qm1w3cX3M!QC z^EBn#)j;~E8}_&36qyPcFSs}xSGFVC@`O4SxVdkUZ&=+QYT;MZ--QZLP<3dW^;UP< z81lZ7>SQM2jM`TU!B2QoFt@`(rLlAu$5{@(zXQ$Iond;-1iIWj+h$ZMiryM)`?mM% z*Y4J>9}W%g9!uC9fBfVJYC&TTqAfeikOHW(O!UVstMF51E5^+tmecmO`Z!Mk!T zAELccsv;S+)C~rE9#+xf*-820&`18#q#t1nAp$X~FIfZ?zxTgR{x>_|1Tu?@)(s>L z+Ee*Xj9~^GS!`ws;^sZt%1^3N3{0iEz?RsDBQtjtYoq+ud?lvUG86|<&b`dpx;4e* z_I#;d9|Aj9XS>k#AEfSFx!D{-(v1)PyJ>S|Z|v0b5TW-Z%R%i?dqZ%*H+NG}mli!Z zWVAl`nBeh7OY7u2QrEmld3K;ZWO4TCDI*|7VCl!N$q}}HxBg2CI4z#){E6!Lbk?>% z3~HWN8EK#ZtD=r?f31NnXuT(mTv{qp^>M-N=MFy|@Q2aG`?w;=MOz1!I32V$**bRVvFr)(V9Go)K2$h+h37v!Grr#l6A8 ziLB&;lU17@N_T#t)SESJ+FU)G6ey3DWYCvi+dxUO)UQG&-IP!I;QhM`LkUdo4Ytkjyc zI^XbAZtCK8RFUEA254#z@^2=K0}x&kO^7;u$+0~pm7G5nV^}LHD*6UAQb^sDGLD)N zi#LHfsyQW51L+oyuU|^zQT;NFJ{4TK55t+92C=1Q#u+FPZkvVCEHLanIWfkuvzpCr@4RwiF~*+sY#g%WproIO_oqZC-5Q#Wu*8WG3d{Qiop zs~82(>hW$Wu}O|}imVOr3mNo`M>cq}eXgKkY&|$;{C%JY*AKy}!k&jrNF=rw$1@PT zb0_-oI5RldY0n(Yq-{ov4&`0@c6$UWP4p&Y@9zyB2*+={T$!NagtB%No%+ptnoS6p z*;G9Y9{h!6vPzVI-x>Gw`$Ee#(*Vn4DD0iyWZ;}+SRZ&ng;WS2wZJ|*`GRuJ59cfO zv7PLG_0b%-A+3sNa_!WCVw{fGYyHpBM6!waG}nt*pfx`5LI^fymIHRhF*ss*yopi~ z?+vWwjY8bkZoT3h|4ju_u9`EnXza?I> zVutP_#leqW*J>9PsqDJkzbN@6a3TZ}a;RKzB?-@$$6D#McI%(i1`Bme$M4L(2gy&f zPjsw+0%qc4Nk3qRDe+viEiXs@LQ+qWx0~3;CpB%<8-lC~?Mt|%4;(5rw&t@t%Ay${ z*tF>s+_>4fBi_1Mp#krCw#84I+iVQHC>kla8uj}ut<2)!DqD&%R(vt9 zk9Pnw`0#4Fq(<9^OL4NBsp3!f_Ml9Y4U?prk!?FgVrZoD$yk^&%7{|JU5h>g>&j}4 zRp=W6?nJOy%}!`#G6Gbb%sSKy8bl0o2s){9%Ef)IA+l)7P2<1mC&4GBi1N!#&p6hs zeTM$cel+GS&yugMK8*L{x4nNd0IX^xMxtim$Ct@f^V!KTvp~f5g{xQU-acRH%X3D& z{+dvrS*mT(z6L!J#DiJ(loW%qt3Dff=4d}H3U%xO)$;|7#xNcQL+|iNYDdtT;`}*v zS&J|Vq`Zjj9{JX<;H1A>inv2sK;9UzR_)H43S;dp`Tbfqt~jKesY+dC8xU%DL#K- z^#MNfBxHPV!I=D_a-(mr;^=sEQgX(8T2rp_yva*%CrNtzMe51I(qOCvI-&?Yq0y`u zp8jhsF(s&5L!U_B5roq$JdytL00Gl#svD`+o84IFY8c5iL&(3}_Hd)|)*YYg;l&BR zTWV_FJr)lxv26K9%h{b)GmDFZgcXD%}! z6)IhfT`152($=dT3rJu&O@Ss`U()Q}iTR2c*fu|MMh)-&ShP`fL|+|04nQZ0et0UB zU7x7jFT3e8QUZ~G6tdf;6W2Bznkd%nB4m#oD5L*Z|37*jDzP1Z_N(X1Dp7|2AlT(` z^IaXFjKMqon#c~e3N@|Ig|WfG*Tp~D1TfsWfTRoK7yp3 zmGCH!^Lz$ey5aWzWO`Pxu1Wqp7?TZL$*-;Ef8yE1q zQG^LoX#&1s{!MBmT+r^=3VlpY|48IK%x8yVS{;(15ByG8lxi8^b-8U=XJnKX)Js=Y z_Dd~P?T4jjOTGRti$Uyt)u2!OYZ+^|Y6O&;u2#?ne=ORSDQ0Vl3vbiCL!h<9X=WgL zqr&gvttKQB*4KzeozsCRPNGp1 zy|dI;S8{>C%U1QIynG<~ex#!(p*!|Da~Gb1rBkx;tw7N4{TwsfsWU(39(w-aE(!w1eaMZXzEiavM%zNqwlr*L%5n0l=wuuk zbS0?Hgflyz+KPmoV0V}KVd>7gb4vo*0SxmolJly#diXEERm}Eg>EUL?>~<-K749}X zrQ<+bv5P%d=XtJYi31FN96k`BA-T$e67Vdm>z|MnFxfTitU$2xcz9(+k%JR< z|MoFlrJzWB(`1Q7RPVpr>j4K}-ZQY9wn`}sdALw5F?jTglQzGKd(Aw#jF3W;@n?S~ z`|4DODSIhv(FSurqOLy==btR1qpwX@=Kq z@1~UrV7B}Gb2*+qfJA-yfV76c76!bOdWBIs(>^Z1`>U7b#ehWf#X@YW?dKJlSMp&t z+*J>9n4s^loNkG^paKSaTsPMyQI7fNgjdkGK{F~wmh;tEFZOMb#*vgJg{(?l1VSe* z+3YELo4blXjNf`P{m?9Px3Rm&F-cjLMRLq+5nYCfuL@;V}k5}D8sr19p* z;Kk1rzTD=?ilnz&PZkgDDG=%n-tFNSb+kMr>gri<=M9NVqS3nZS%>p81oGF)huG{M zBMDB6%{+Z5edc6u(Xp!a?q+1#;zqCMHI)f*>4ZTcB+DBiDhPfgAeyg7d7Lp4i=;Xl zV3ryD!G75(*1GcnEZ(dCYnEB{JgfV)S3xc3j`y#Z#pJReOt@P9|n@FkkmQf{B$cJ_xqnrygT22bo@&fn$8fPu|$&&xBy}%K7 zgYVwB*1@%i*Kqsmk1sJAC#4tN&a)`^Jlr;eycT;AZb-yXRJa6T_CJW8!Z~yG52!dO zmnl(T#D*Kq*DCpd=c&Fm3R=T0nigcO1$|){h!{WncUwQ5V`!l}qJmQNl?-6<3y zD#veE`?|M8v5JB#AT*Nm#|`;*+tmd%=~6q&m*Fg7S*WYL1ZoD-6*@*BjmloobjzJ8 zdLYbO1FlAwMxp#V!9Hu`P{&c_1NV@nbUc}_627<+2^3+LQAF#NkO?b|$w z&9)DjH>8jrPD2Gmd^BsK77YiTj8f#x@W)69$lE0eFJW13jv+(3z%_2zgd&7fa#6%R z^PZ)MYv{yPsvh*~4zugY_c5X%)N2cQmSdmkt4`lsIk}_)b;TE#Z}3RtGC#2iYCG(a zi~A4;h7H$-j{Eqv!JgdXB;`ibI*Bp2b_AZ$K}aMedkviD7@)X2-W)eiw|RWMBHvvk z`<_k0#>#AT)L?PVhC$!J$z(0+I0!^*D#H()*V%12Fc5YvVd=tMw z*CDTZR2)SzW!HmTDz}qJF%`ddy{#uJmCp-Abgs6PbT`3fT>1M&i94N${6{AVvF9_l zgO7ONSs?Ol-ErYin*ldIy-c-pUg}?wI5Pl8(A&e{AN7b57bPRxswc`V+Q|4BKaW5f zuj7vuOWF(b_5ZJC4{wWR zj$l!v6kIt2tS{M+Jn!=+(%uUlA{+Y&=xzEIA2qR8wOf7FoT+L9BlJ2{YHHN8nG4nQ ziefI1iGmp3UZsQ1@hhA)Ww`3_D3~JU{fN5;qZU>`AWjFw zy$#^EJ;^F>vCXoqZYAyS+(#Nh`1{a#^oxl8-FhaVs(lu|Mmma7o|)_Y+c{U?9OW7& z8>aDDG$7g9&c`RTt?G&5VoFNn(z`%xCv7!{FzGddwvrb=^P?;H$NVTVLT{DL3pw zeOjgGhRjLno-&hCQ~Xwb15xOFK`OYQvQJ_*Vwk7_AC_uwT04DOo9bWcJ|k109HLHI zn@v_f{5AMvd5vM5=ncu=amtdrQvenND*^x+DppECkxVe))1rta7oB)^bRP5 zl7H=ZtER?EzUD{96pbO}RVZU=i_r2Snp=9KTXpkcWLoe*B_-M(i!GL@mw=4ON;)TUb$fwVK}kWlwvCl6CK;Vo!9yXQ;Fy4LqmS&g~_d2lhaD z4sy-2*rM{LzByNdj#96Ky~JneogTlPxEVn|@>vD{b>C6-ysu3|c_-{!K)`2h@C4|< z7H*(A8TDy?XToz90!O#!_P38Gja0O6O9ks6ePmhEAPwlW@(wq75fgImNf(GB^|IqO z?c;G{7J+bXO(+8Kj!3mhGTJH^S_7pQ%eXjpO%)(}FQ2AKThHt24wv{PAK}KO)f@9N zF;6lF@^a;AWUKt^eJujN-;L{aiBtLP%Bs+G#eIY_)0e+rFI7elGNkMdEp!d7bdY=A zK_mYokCLu28th9nI#`e}ruYzgt&{nuf?N|NFW^b2R>lo^N+4Oi0Z_-=X(p_)f45=> z%m0f5TB+LY+%G3btNq^mBUI!?^LW72l60w{>I@2wx4xgyKi$mnXjI<<0jqsj)b23! z#6eFsP)Fn(-j%Ak$ND)7l}pmG`4)D6EIV1Bvof4bOc+7?g_zW+jUc`|G_;V%$C1NW zeac`|tn?xMGir9Uyuqm88%)&Mgp{q2W#`A2BX=lFj}|~NGG|^Yj)hy#>6AsZFVf8dQ_5d@9fR( z#;WSW+PP`!@WybShJgYGH)i&mk|?eqoF^xD9c{?C?h}&cUBp!hj9~hitu7yA`H~~+ zwJ{C|bg~D=2cVnG-}Cr{@>NN(LVWCX6fwp^+}PUO<`g(aiCW>#|IY%rpnYBDFy%8~ zXYS^Ayq0D*yTVJT)8yC%CF+b|YW+rwR=mfq#fdssX2;F;-G{{R5W^}R$H=jJWa1!~ zXe1Hj$3bI1LG+i^aEqML1y3wlb2ixfANuB2qZjVfzsUKC$7v{6bZiJ6_MUDvhI>|J zUliC@gM(*lxs_@v!8|x?rE^bFR{8f!k+hpd9~cRSwrn;vxMe(dhCBKScylYC_MMJSD=VX%@{Tlrn7h0f8$k9G2}M8 zqFNJaC5D!k+h_FUq{mQ+BCC*%1c0~Q(*Zz77fSyI@H37gfwK`qXGif+ZF$hRllhJF zgGV`by;?DNa}ReHqSDgwFGW0?4o&A|@l^svGC;i(601uk5~1$*?R%tvgx0 zPSFzF$%&vwYL0OVe&&?v|1;_5Va|gisN~#A$4Ft(I?(R;1hw~-`wSOrFGoUXIAo8{ zrg-R0sg2gYqgNvcZHjqf%9zUW1Z^&a*i13X62%hGwYOn!_iQ_Nn&vt#6hV*K_>{%) zj0G?&;I*OS-+D;+>b)jfwvQHkipJy%1*RfP;@f6ALt{TBnatU?ml{)w1)?22)n1J= zM54rJCdgkZSqwnS2vBBR2Axsc5NTzr!aVnbFZzUz^P-~|Z7?5ic9%wHK3HKbeHtgf z^5MBNx8#kmtwFVzkQhr$Vvv&9HssDm2~)r_J5T#AtgK8v(tS=87@j>x=|4axE}sgi zFtkyca*>YWa!>R8N_$9>O%I@dgeE=JsJ58z_zW8ASI4eX zRqj6T-f|-(4u9L`ZAIl)?g=EFFd$^SsQ$=oB%@LN*p9KSTHlG~ zk{8V0M-NS8ZG|&l-2FgAK>7 z*!YDk!>2eJk`^$Z16Oo_VvKlpWEK!X&Qtt6zsaM#t}rr-jpnLp<8gPYP{;3-x17%QTp{>+{Gq;x*ZHYt!B!r|*b?#+ip9I=K$Ch-CS$ z9HxT~T$O-TbsAXJtL*BurpifO+xE&WoYOiXCFPG|BLu5mB&u+@l0h?H9(aHLzV*dG z#-J;q_BP~;=`bNkW_AvE{mVw#uKMUq%R9`EyQZ5#g4_IvEb`+SZ3Y zI@~tgDV|+ZAJyGG?#;0YTYJ3J#p?QUh&OM1RZLv{GxO?%4dcmg`IY5(X13+c) z7Qn=OwhRi9uR5XsPOq!{Ug{>5BjBc5;K$wzG_S#u&E*L>q@a3EydtJXKMFAQrEpQZ zUenbF;l-gp$!=Ao+1+l&J#q9V|a&?tM4~m_;7GNXloi>d~fAt7>3Hn-Ah)WHVO4?~R*;b>_>ID92J$ z-%{T!(agc8NGTkBNNn&&m0fqjKxoXClQ$>#vBCn%L9@UdB3t?K6A66i4Sy6}M#{J* z>QyLx@^9pQhMVNlt8Ot~VHQS?GIM-VCS!tE?NQJB{nK7yFekNm=<4_UxDrtcKpf^1 z<00*>tW`1ysbZ-cFH^8|_D4>XMENz8SJH%?Qa+p#DNhc?kttI17S7owp6@*J05?Nh zq$m|RJHK)o7Nj-P2!;#G=|`A^x^AVH)hO@O;pn!c>^@**!#G2Pwy=V}n;%C&M-$oVwtrPYADjK}m zI*C*hgi8<_QP}xnzz#^&76>yhMj{BCF*r>FmtWV~jH9G+-H}oHRn*WbrcaW`-^9b> z_TYRqxYciFtNIEFzNGf#Svmcl|*!F5v6#)mvOehdqgt`xIM zsN_LnIqoGDwW5+{DEG3Yms__hTArQt(#E$DwpK^{FZQxcpxHCX^O=u4=tJMbE9ti9 zEE7a}(AQco9s~#M`IuW5AZ~7>?+=+i<(+MJ*Nx44Fh52%(=kut7(K59YQMvIrEnYM zwsMQi@;r=3)dv1GiJOhjUeNf~5_vej;|)KMo3^k;m5K#BKV|LMuKI>-h*ql833&l_ zudjZur!=88OPzbTIyP-j+h3huH$#_u@mHBJo1!`|VL1y=&N?5gGP6-Q5J}TE3GB55 z>VW_9@J4^(kE+-b87YSldn@%fVIP%Y6)k>Z)-`p7+Up_X8wCg#6Pu=iIRm-%@zUR= zP6}pMK}~1Zfup&g+UlCEsF1B`NOf`>jB}|zQ46U0UULqL#-7yV#=^_`ctq~7M#|Xp z_sf~;EA7_34mNNq6Rw_)ZhJZPs{1bBI)FCeioDlZb#?U>wp1z3(a*02y|gQ>C_n~| z3!`E2(-om{u3bjdD%iG_8ic!=d*czW|GlWNANqdblhq1rU2RB%N;rN#Jv4($pWm^?(LxKd84ZSo|^UQnk zH}5=ba;2}OViXB;?G||!d9{ELb=dg!f3SGlXa-$uCu8-^rP`$4D;DiS*|y}C)<~tO zFI>RYc%bv4F2>~P&F+!SW%fJ_rE=|$u^Vw5x)W(UC|ap2Vu?9zgIrQ^Q-dqlK~;4I zN^Gh04EU?z#cv*3_Nw~ucT?TPUq|?M%inaMVL}AZI{?73Jp`{l1ydgEl1jQVhu_SZ}j+QzaQ}_s728T-%9{a;bo4kC&)QMe6Pq0DNDoRC_PaNhGGY3RK z_S1R8FL!95IZ8JI+e*$`iO*6kLT>dRJ=DQ5<0$OH*+K!&vNGNKsU)cl!xcJLqgf@d zJ#O7HsVwPy;l~MRJ6+u4f$cbeIsfH9x1V8=xo6mS#>aoI1+9tNT6AP~(^D{G9)XVs zw6-3CvddV!b`>CG!x9C&`Q&C9s(f$npZ58Zq46!lBU0_&W4gbKJ&QjVTUlW(Uv6XA z?$H4gR!JQyxqpITTA;HKqw z!YnVQocgT+IzlIycpmgC2ja61-eTkgO)Ah3=;-m=jW1U}=hG9JMApm%a)p*>fvIL2 zaJ*`}>J22oa&2QkB%Y3jkG+oN+Kf`~f~!ssqJ?tg<=3;kx88L-d^1pe?*?^WdB4Mm z*mwv&ncbio>H$Sx>k*e6dU>BmH|)0L`@g2CpXrKPD6VsTYYAi4HRAbo0;G{{d_dB3 zM9CnzBp+Gbw#|ta0%gx!87rQvI4ilTG8_GC%gz~T;+QU&7++_gu-liZ+`xW0Iv*iv zUbr~-jWONrp?|O}a&HFS{pV&imF3u7s;-$L>10*6v{U-CclkcmgjeR#+-Y~Wfg5q& z@pb+lGKP*ahkn`EYSz=)nP(loySQ5Kit@H#q;v&^mmU|=H85$Em z@gGl3BFkksIWPC%CvQ>URvR#MBuO?ULSp@=mNT2Js9J*PAoLW zK4OP5MAcc}@+!++o??@_k^4-}a@^RG)e^-DXZju8Mnt_RoJrZ8rDUs>JFSj)mH&v( ziOMG*sOw2O;>AdM#V>K2=L=+dj`y2?6hEO78=BX3FW4{(5EUQ4Q2Pgca&Nh)fZ06e zpYKu7by8H#gjT8N7fE?orP&0zv_UGU08f9F>Omj3ia)`;cu-^jO)k00OVcV zvm1D!_TCUTyuX~v`kT&b3}13+S8NiOoPO8`y<0Y3?&)<#QK7lYF2t1cIokd)QJV)Ldet#a59Iqpn{x%@cckW$Z;R13>;^j3^=M8h-{{}*t{iug9 zK%T(;hFwG|XXFQwWF#mC^TEM9-9*C%R9i!*FI<_WeH|$upRC?y`z^ed?1~>%56o;# z=ALxlci`d?tET!XC>qqIy1o_m*5?HnU*R`OWy9Bs4$dA_n|#O`UQZ0opDSdN9Booe z^g_oRB(ZVhiaD!k=P};r$@$2$fk{(oJE8L)7;vy#QEmL<+Zxs7&Wa5(SRi;UqnatR zDeem`SQxx2E^09w!+jtn>t6;&Mi8%g6~x#g|70W;adD7gv6*(ygmMbjPi9(VoBS#y zl5!B0Bkp1@MT2@rK7;|5kcVlis^*AvFOTWUS)FsY?@R%^^&;mJa9hr=wsXR&(wk3! zfle8vsVSAQ0SSbFg88iZ?FoAUWED~Kg~Co%_iGL?w^^F&>aEd4v9$>{ z-}SkCA!3(xnVsGvc{^*vNq=J)J zGC6yHPNU!bXYi&?%0ky=BXpX6Klw<-ek)mlASUSO2CwT@}q8K$fbbmq{q*5k#2z+3Y@;f`M@B#--Mob-Q6-=Y4$xNjdCOxeb+5S1-Uc7`M*R6e0BV+(zdu@A-`vTqeW_7sVXeP3qm zA`G%6hOvx&Ff^vYJ$>)%{^7pfe}L=aT*rBx=kq+CAN_Lu{Ab&OGC)#;t94ruA{0(E z4d)0sznX_*&l*Gj*JN1VgFv zni9|>kCFAw;U$hF`69wEp0GZMLmZmPgOJ7?MzUjHTCn0U&URk@xpJjOXNBQBKQc{y z`F>xeLQ#q~3~-;Bv^IHVI_-LCnv1C5eMVpdTgo@{CS8%F81vOPSy*J89U(@0D-vyH zOPWIeO__#FC#BjcTfImHpQ~HEXGdEh;X&UY*t~CLTbRucBc=I-?9>=EXm|kk%A*l8 z^uq3-KW<)3kQ36!J|0Z^?#BuPHBV7sm-~%^=nA{-WA8r>A7|4{X3_qzE(dV$Ns8~; zYK@rPiO(LtArR?~=jXGpm0FzT?do)qOYX>*gy#D_8f~Z>*na*ZYVu6Q$JcfU)-{!7 zE=SFiI%)JzXL)$`TmVm<13o2t_zzqxK0fxTgyJv(+GUFmEijB`#1dpHuI#1de6pDa zwXsV$4o$fz9K0qB0+pL(CHNaOdJVAe$$F$s>uo7e#?EQd$sAtK!efm*SO2rrPW}E^ z-tV7io~`l#SbH~&H*;&6yc z-oGXGRc!Z5Mb($+TlNxZKx22CPkv)kL|5-zn6yDb8rDG;OUV~BcXDv{41jl<#I{rYk>W$R@Qw6LfwfaWVz z2B*6G(edZ|>wgoN3g<7;Eua<_7RIU0-jJ6CJ1(`#k&IyjCoB&c6u(`g0`*U~e5Eg^ z?^{))y$)EE79RcbV@q3r9bA1eq?1a${M1e_kzLIaAMDLks(t6%xwEVw-|!Lmx!z=) z&Ye}kUKi4gxleDxOE+x)i2BlUiA-*a2vLIibgh+9gqY&_NNUjaXg(Ne&G@(b()`ca zA;DSNCe{)AY;}`$!!dhpRvwWCvJLHq#&s#kpN6V1TiGA}4;&sZzP+j2O z^ELG~tBwhx?%}cP47*z3*{AsBcg3k;hAw`O3w=YMLU%F`4b^6z*`{oMEg)=%czpVf zNYXqV{h`!{KN)Se`mH3IWlDP}_aO-jICXx( z5%m(3XQ_?ONY7JjxZr2WsmP zIP^_!V6+%iDah5N{t?@)FTDii&s~)o`?Og&k8i~nde}P}hdZgvBqZCWKK{t3k&bh0 zuDLU>3d9otA_$m&g60s1D(|d!1kH6x9Xb}XNY(hYPCNJQ%pq_jt^L6fu4%!?xZ@>_ zpu*b&_h)&@=0UX$$_l*ZAR)S_yqRR3>OM6SB^L3A>okvwHhPA)N?iZG#p@$nT3Yo?A04OKyC!XvZc1FPL)771cHvxq(q5o4+j3SABq9q z?16s5WtD2TlgPBdUkiw}we{peq}kitF<+b9qaEL-VAqK0cr8FmnK zU|#lyjj9sST>iK?vuXgyqZlmspGIJ=!b>05{8bd^0|7#Y_e_4^4`{nQN>XpGin4&V z%F&!rCao`L@ZMLGO41_n%N@LX+C$1h;w^Z`p+X+zCe`Eed>$nxTMb(_p%WobiT1JN$n#aloCTzhzt44vZd>^LHk3HZUsPZ5Ekr}qJ9Oo{Zn&M2Q5HZ`P`5h>S5?^YPGXv7r zvb8sxNJIG$Fgvet_=T;0twA&&(78v=%LX!3$!+~ehC{j}2(r+H7((_pK(D=gnA ziSX6aYeBEz9gj6hNd5u%uj|Qwwcq2)gOFWsvF@lu+vG}JV2y}&Zm=uLy zDrR*2T7@=tGmVuTX#f@q9cOZ96|B=&zO^VHwjvlh0wSJXsrI;|ijARyaiRGikQ`l) z%%;ahG&3==pg#md6~7k{-}^x?x+s(PwS8Q6j)y6<##N;1nzWZ}<*)ux5Iyy7OY^02 zE2r-6@I0_+~IwQ3B&^5}cANn7Z-S@oY>n$>_WE>*tST_p$F7#_Pi6avG9;?!Js1u zygYQi;804mHd2>5I4OHs^b&g$6X6`UTVvhVqB9@F!5S}S{a!jAEKT!9g>*A< zq~eMAH3}c38;S;baVTp?i(q@k6ZWeIL<)A$M`{S86Hdv1Fo2w+pyn;|hn}*3#mq89 z&18>s;RGS!>+vF8(cq;^Tovu$GrT-j3%o$xqb-duki=3jcP$VKWgl0DH;lm5zpQ zC0_WKJJXIJIfMRHs;PD_^!^AUD+(*C58Dj$PUNbw*l7s%GYIDY>~T<3#@s=qaC`EB z30SUXbaOyY{%L{*ymkfv=@0E;YlW)P@QnNqu-SCH3vh&fu<1+v!()iR^}7{cEL#apZuVy@ptZ!LL$EEuE@(o|10m;w4 zkt2+SLh4PHv#PT@#|?e&e@Kzb*g@oD!tV z3U99KHX_2QlRi{C6?s{*h;ONPUv(O)p-mFmpaQisAZN>oV=KTujT6Vr@fE<(CbyaY zrYm}gGqT{}$?ENJeef6sI=1sm4dH5%a_U6E_pO z7e(a#RVv&@WylaoeAiN2B!0Tils}Okyg__rlboADK0jd4OC^@2W;nI}a6#*c2=M33 z*dNn6rOI8$UAu3A>M6GiKdyRrBJgS|)T?hHhMrZk<=iEy!;~5DY{cwHM?fokn8yc; z5?gTVmpA}S+Wm4&Mi<~mcu+jt#Arc2nJiE=SrGiaeFHKwg^A7 zPx9L>bz1<3Kbaboh)Gc4ffpWSoK>J5E8-P+zBk$m`>5S%N{M#8z1kFK?D26N)M0(u zSb?*}7KmaL$w$ASWnt~aK3riOrL(F6yR|jK6NaKP$o`+Q&HHn-zsn4)mg%X#F|E%9 z_D5HdH~2`ivFH6$vk{6Q55M=`(VQ~P9_ybwyoVNG>~c2BXS*2r=}Veq)h3nmS3a|Z zZ9(nEm%d-Qe)c4HVdcA)6(kAF)AE`*$P;4mqCaoS$i^*P#!WGDu0lh|{9O^sihvyE z+H+#!`|oP1f3PEz1Pbwi*@N{;Nx8wgTQOfJBnz-l93{87+noi67%Xzj+(t5!4D5*@ z*|Q-)Tt_g>e(<9gel^b{J~~Mbo?G(|kuCKEwp}3$5i#&Ct0S+M^g9Gg>5@Sx)p8YSuuz)i+NoxL;WN zZ1>a#p)t^=77wjue_mWDZ#x(-#;4SWGztPy(^be0+Q{pDgC=43QQ5rj+BjHIDk?VB zTIs$&J)4eAslnNc7y}Wl?y9!?d9grs940P(;7U)~uRn`7MJQN+0gw0LFQNU4t%14h z*LG)zDQZ3bRp0GkFRmmke~8(z_>anz6P}52By$Um*d6$C`UY2~!*e&tzbqf7jQr2|ime6!jt>W?eexFeu)<$#3nKQT8vP8*Hq! z9LK52N9q$-!DEp6-0g|zZVkv#Tu+RIZH6RbS;PbJC1At(Ee!W-mXOI)fGQE{`2ELB zy+_jaL*iJTWQ|IrqrOP6o#g|fu9>rn@Os&SlFR(&+c2MB33eaocW>G!J>9}%YP2YX z<~=@#57PrVQ#zN2ghx20S!*dK^Yr$i&y`(S}6IP^~Bp|QqwBWT$z{>79sHT@#3DN zIlC$B;sN$yGMsU@nTlpt|I7rC?au2M2xnwrP1WtYt>q#;?sz$=*H(UM&^vC>ss8W& zWxoP?_HXFO#6Tt^$6qv3sO|RIe)t8aY(QS5m%uT&3tvQf<{kU3+*d-D345@XO}|{t zC$`vKVvxmG84RxbUsV@;rack8eKh=v=iXeK{v)s|u((D5COhhp-O-YLtK~-9qeJ?e zQ9LofT4!smL%=5fvekr|r_DYiDYlelf9ZHm7<24wyHlrx>M|Wb?n24IF%ZDi9zh4C zdrUDz4Sq5EzvbM;#PFSmi^Qbt?zF#?VP>Djb48q;dc)4-c_3NP{P=fmR!8MZEes9C zOCGG&kr@05heAB66HutqDM0%*)K{>uudsN)mB2>s8JHo+5F&Qvc-*IqU&%arqgU&; z_U@y&@EHkJGF-MCU)W&S9hk0P+3gzNMz|M99)IRX&x54M+YmQwMy}sKq6ZZ`C^d`k zFTclyK#rN2LDzZ#5c%pEx!7NAf)5Z_!qm);Qf#`V!OZ-$2k2+yR zklpERlq~GSAo-tQ)3LwGiuvDxea(+ zZ0wfpmsG^6*q!uw*TT@?0pSpjeNV3t>;2c9ruf~KjROCgxVi&=p65w{^}u*9+-;q} zMqVThz&4bxC<-u26|`%NRMljt+_9NERpa-oU)sxzNA%u<;r1Hs3zA#x>)cO90nPTc ziUJ|EYmQsINsT1tM*K=4urX2c&on@A;lzISvr`C>_yUJuY270F?m3R092-ae)E5ZL z4Iqi@?{yYmpY`}eeNWnde;FZEXWb|b3&^w2vu#^H62i{jhF-hk%U%F^l%)?M@PMU9 zYrU_t2!((_cuBhmJ)vN?&*m$}1Ue=WSd3gXMIVu_P1^9>e_%e6Q3B~uO<*h6vAP=)36hriEoor@*FR?FC4 zTLQ1xnP^ zmz?&j~T6*9JT7S(Otx1X#^Kl+cj~pF&3XCU7Nb+G#puxq% zvkEpqk~;cBe;0f|4v0Z zkq8yM*8XnA%Yt$Q%$4&Gppe#DORP>@mt!ve-x71x6Z6dMj9H8m;Dap!u@EI8J>!S;e;MaXas`AACPNw00_hF@7(4Nd+7m(H>t?*c)FqqpEVKM2wtPI|qY&gk`aRpa^KUY|N!Zx_(lHk5gVi zL?zY(>)BpWF5MWKy0`(~UHIQav+@ets;QPE%bwFx6^=r09XL`j*PzjsVAboN3mtcH zTH+DLVxwn+5OJLdE>#jKmY9x0eKK=oR-KAmv#wVgNQDEs4!nO@zOxj?u11r@2pLam zl2!Hc%c7^HUkw5tCO#=Bc$_L1Gm41d(Ka)-uAc!5*Szb5mq17*POXf3230`En}Pdi5*3apuwWh3 zqhT8v?%{1DI?Tyqgc=-zWcK`?UASQbPAI#l5Jq%L8AqPtTJ`OYjEXIfGE9#g1^D_%m3^wvqH8O9&(Qf3_q25HXgJevShvS>#tMy zUy$=a#i`k=r75(RU5|1XrWCA#pz@psE7{mXeDhNV>A{-oX)WzojE_^fwBQ$ddW-l1 z!O58t>MEmK(hrz~6>Vz7GPKopyWlm>(7$mJ!?VkAVRI2D<5N5>vmJCIE$AC3_6ioG zGOgrenKMjdq;8xL6NJ1OSG8iJm7gtuS98IwOXb%XkT;}eyY^{L*>5e7nUI}!1{;bb z@vxC*LL?lO+QJO6I>gP@oYnef3X&rS3`Tp}d`b9AAeeK~F>aE;em~MctCL52{?z-n zUs`q=-oac$kNEicToMa%|LMh;$TDK znTw)IMVQX*K5bi@xevgW#8RhD6k|q*TI0-K)XoY^S>knT=Pa`7URQOL>+l>la;ZfW z@BCYKP_`41=^KJzv7l7S!AYEkNw+*IJpMjppWnG!kVdJ|oAJ?A?)uQ%I0p&uhE%_Z zRO3DQYJ%xk`ON8B?bV#WJ&f#4#gDn(z*5VZP~9x8@UU=EE0%f+gGR@&i`8RFN|yDMgj2Wdb{eR1D!A*$9{s+##_bdt{)d|zKCXl8 zA~8N+LfxYxImfDqgG|au-Q|3lxjMen*NikRuY<0Zrhb>Po05qgk87z~Y*zwfl*31k z<1-&f-@Z6-*9cyH5$9a2p>%Pcy610tLI-H)1Nr(rr5+{RG^@EPb*^K3 zf1@2c#8Om0tXvSwAhywb?1=|+ymur$t{K|L$o_ZfIV(qAU;qZTk*~M%v8w&>TX5M( z$T69yF_TdAzqJSNQ+khKx~i4CBcqxe-y0ie5sCj9mb?14kZSd`BlByXZXjrFS_tc+ zBUPt><*)^bbS;~B}GCawJ)yo^&+)lB~HLIR0aKhgT(n2?QGx#edHqV}?czuSlAr)^ zNP2PnV4gbIywb>+vWC^pQh$Nx2X*`2bkMGXbW z2*Al+c!E}FB2NCJfYU3x@;XZ*ZAD?QuYon$IgAMeZ&d-H`T_(i6fJhXr3JA+1#63LR-qEJ7j4Xu%_qMf zq@=0@UsZfI0#3YHQ2RZPVV~D#CwFx9mRra>{#VT&7|t_Q*XW8Ty_)OwAH2@?MpxJY z=i?G}H4=f4{TlOK*wpzake0f#9KmA&Jz>=UbI~PldAATW`n_2HMY@5Adi4zlsjj0( ze_qI*QN#19yq>BK(A$3NlEwz{C+^8CI!6WusV~zn6#cG%^W}~Qyh41}J^H#-HN@94 zSR@myC_((Bb={}i6>$veK&4%8RhlOEe8O*JzdEfRXV%RBKwITjIT4tYih4bY+8I8s zmRYTgE|KBIM#Lrh@>t!bPWDoSq(R2l%LALY>5k>GK-uP^z@zUfzhh%#zhF>|uCmO6 zq%vy6Z)+NkMG!1BH1n6~X&LwHSJW^a>i~{!S#n6I&CQ3w?N(CiHN}3L5!I)O_j!CZ zH*sQBdAb++oF;klOJexn?>Q5tw^Tt?O%&r7Hl2_TFf?egM07)V9}g)qvL>2 z_4I}1w>8h3Sxx9z~MeZ|g1 zLl*SWtXc?b_fGDzgHGf9s@cP3aQms5FPFI zwKGO1O1dv-9`PsmhThGR##~zxxM0be9R@v0vLL(^L>a9tSp9^T)Z+i?92OnwFDd(P z^Pl3}TgIm}`#nb@Rfj~$&o`)c@1m|q|C&oTcDz*{7gcRz`b+Wpu4>l-?(DvLlW z;>q;S6ixj+Q+O}9JpCN@=5rza7@HwYI=zdn?|0OdI?2wmQDd6-z^uPMlt4&A(Nz`+NnYNwU;eT0E0KtQH(sCB|GYO1*lw3I;f9btt zK$mkVcw-YeYO^Nd*knJHp-re|f$<20pKU`eTQ)6iu_f-xwYOsI2pQiO)++{Gldvl6 ze7}?U`0BR}!eD$|gVEu^DC>M6V^fEE2wVsUy_l-`D(K2?Wq(M75=-+t!vZ(S(0((4d^gKM zox%s?&tlPG_M89Yw;;1G&d6JZVEpzZblf7!Y-xNePT(!BF|Ce0rJnKK-vHJ=`;Dm| z3%>%FI@ARM9c`)^L}X87?elKyc{{v+*y7fQfh{yvPCe+A9<`E5bzr&i)(o-2c_(cd zv0xII{#cq&bd!Yr$ElfB4y<}VRnjv`9L#2_FA^xo5O)TiOlbaJi?)(sV@7cW!sZq$ zKOt$VRRZ!>MZs<%0V5W+aBgM(pMlGMtSO+!Q|QclhA{UleC*02S%y;tQSaKg+~lT- zzeU@rboGkEn1=G!*7|;|b$78Rl8v)V==6SJEf#gSXMl=_aD7Am+WjN5Qq9GTJ9^OJgM;s2rP3h zlWA4Qclc{#W#G{PF68Q~y!d_12Gr7oXgBL_nmKdEWd>$5AK>;qozuVLlR@$J98$Oy)=@1lHNCEqz!nsNXYkYk&AEUE;+b1N2#k!RBmps%`7t*t&Vfe&?50JCTHnmb=s*-IRa-8yK;1>0* zx-z*v6hV3R#Muj|wvD$Bc|Dr{sl|8Wr1N*j{*P39@5a6U3fwA#ZC--t?PVQ4LA?g@ zaFK029~gJVidj^eS-$eTdo!Z$su=8G@L&5%L7=HLp*gzOP^gWDIgjBg*=LsIK+TH5 z32fWZIA^l5r#$i}RUkGiSm;Pq_KA(O?_rqU@i$oI^9ga1lQi7JI3~FuD82w?5|0`ncJ1FhC>h7w!uiYZe7Lv^_!`NOf zo_kZk`MEB5R3VKMvT!vUiB*}J+wO@&;a)*RK6RzWz6YyFX*WM;eRRgN^a&5SSl-Jr z)|8Px9cC)nN1OBbt+bKk6^f07b7Ni*ILdnOZxI1wW$1i{D{?&ASaGPMKxpqBN5S*= zn$GA#tBS$^qKp3R@VycF$2s`uRB)uRdx!jW<6Cj*tW`&%;zF2rY32e zWrK;!{5K1dO*i{ja(JKJH3}!FP7i42)_*i^!9Nv3czjv17~#CGTr4Df+&EjLuGDq> z)$51k9d>nm(Y&3;?=$%U%YTw8f<%QQKyn_mLd3yW=5lDudbJaxmQZ%8Go1mH$Q&1x z+S&5r)mB;lPWt4SUFP+(g-6p+NN{6n7zzyxc);ss^(U_Yr#sdDH#M9{eh0QXmRdId7Gr*{(mOs^-anqiIpil=5#4=0aTyZxyO?5Jp>?%1XT zUp{L&_*_&j*FG$Dc*E&M4Ooy*qr=bXo@smh4-)?_cJMPV?(MjLLBIfvp~(qG^2rNO zQoQ(~#^lsKUX+Cw-yL11t4Pc0B)Cn6KQg8+LktWSOXBu8p7|XxB+q0ne68{9Iy*Vu zlSPN@FalEprUdpxncDgfCVk2wl{}ihD%zhHROR zCi+fpz-YhiZ+a(m&z*uo7#rA6^5#RI{_uzy%g8uLj%K+rug&k{D;h-?vmXz8N4xi& z(DvWF=B8%iNdkWV(kYgQ+{qQejfp4o@QX7zUOI*qe?{#tFoCp}uO&89&rb7Lx5Rf7 zd1SZ#N{wF!dNTON4 zWcs83#{xj0Zrb4_e=mmYCvYZ3Nd~W)bwr7}ST~{+JW)9pw9U~%HJ4L@abI=LMnRE$;Rr3x{UJUo zMKiyE5fc1CW5zTQ#)F%hBM!GmgJq9XJl6~FmZdc00Pr`k=p2B8y zhe?xPcyODgNN=Tm#XZt>vFC2^H&oZ_$5Fwn$nBOs!4t=nnrH2sncJGGo}@8~LwI_A zCuYK+!&iw|vq??+YYxZQ2l=e@&@tz`EcUc~)I3!T^7+jVdWPwd?C420_#^1PT^0|z z&69O@Xz{~Dgwq*7uX4IGxun?*)^bTqf=#qQi3%Ii=g%*5nVn+5VG&5{#@FG9aiFyj zo9x;6HFv)xXl`)GxiK2Z>%Y9jo6aJ%o3Gs#^OgXzC>((fG@^QvE&a(jk;-#rN^Td? z8K`}npe4L>stfn6g4oboCddvTt_|3exj*)RAnm5lqtTZudCAOKF;Nx;c}$4yen3?K zRevPkOM*rnbT(>e@pv)t38&s+lDF^w79`I;np12jM zPcC$9M9SAgAdl^J`Igy3P|Dn`5b)<4TRx9@UK_g1`Uyw!cpS2Q{c9Pi)Z#bviFcxH zcW)r+T;0n{h3%TPxi`%wj}6`t(S+KMg*P{DOPOK~dWFd*InO)W16Lj`=-}i_`M*r|jVVNh%xLNx7 za(uYnr2Ml}oldS--qVTD!YA*q?kUL0oX|o&bmz z@x7f$vsq!HYbm5X^+~v0(iU=*Gd2Y+=CIy~eX!e{2kC$2v2P@97LMgZIxCBeF#0aE zl(`6IW@+UtIak*JgBTWx=(1q-J7wdMSu)sXZQARIohy|eOd<`0o)asCWowyA>0~!R zxdOKu=>Y%1$5W*VujQK8RJW4#5sdX@{*W``3_x=ZAE&t@eC%vF#aBoI)DKlb7G=&u zLYz!Mq{$T5Q2Z??hxVz1AirXhV!ifFBs3w6Z@B)*l2mN2y2E|O0qu4joyAEK(Kwln zVnyaZ3b_Me*9P(d>@{7tIfniOb{^#~{>8J9{rApK0@}Cu35yjGy#q&-OI!daM!TXl zs@L{Pk8Vp^uj)#+4aGKZs;#20ny-?kpK-8{@}GNE`RJoUUXGF#XOBG&*d=8q<`nr4 zn}WiDw*wZu2mW0U%+a}&1e6e_25`$&wT`pZ{wgr1N!nzyY^( z?cs(WwHG7zDuf?68x)s$Um(4YBR$BpZjqF86 zC$t32I>cStn|0q`y`P9!QB=*6AxgdEDoJO9WGJ+LPu2(}a)S;x{6ys+5mk7U&oI;M z0IQl}$tS(p?(Xs_E6?K_?jl>J)8}T>pdBmo24$TZMk4*F?)Unao!rWL(JlSBA(_|=pwj z*bgST9;(GIS>Y1*OTz2Nr)T85KBNZychE5NzT48E3!@c!%g>2@i?fTN@Ei^_n@?tg zU-!&eI-!4-(2~5#sRp)#FAs{Q=;tCscipx8?UoNdW2wivQz6tx>XHVP#1U*DWLk2V!A4AIzXE$V;7M=*PgN_wy7ji%e6%sQoh z4M9Sm-Ef2@C7W9^7|I5)YBe{M^y%Jq1M9M*#JaaMBk997@&l_lLI(DpzTG)C(b>0J;cU%t4ovI2Ns1nmpuG|}D=op6RR(wUP$-dj zyu#;)Dse#bK{EK^qEaG&e!9k0p44#CnMiOrWm3fbLj@aTdGZF%7-Ga{6Mpe?DFmcN zd1SKQ(du;M1acJHjSna2$-(q3NamnLl}ChZs02scvyqx2I*V{kStNdY2&k@St>BXW zjr6h5*Gz|+ZNPoU< z&2Nb>!JWL;qk`5Jy7hPRy--=5@NPiopbpqCDf~#9+>}~H$YfM(|L`nS=N&da9DDoz ziE=ykseH<6Wa>jc%ME*id#a_=C)->$Ik+W(=X?rXE)oo<%8lrkWq|{P|HS4AMJZuP zagx+msQ|>wJn3Z1`9%>0)3g+84w+vxSEXvy0pF3wJ(Aiya$5zj#S7(s#9C_RZ1)>E zZ1ZTHsyeOzsQnPBe(tC5MgEvpxTsi~o;jlIB%)Q~DV)v+#kj)9tGY~}s=JdSq4iw1 zqpkWqu5J9qyLnxl{YI)omS1xQ4~T?Q-kf(_Y;SxSQ^h4MS}&2O$;D-VGd0;4m>+3S zR}Tnka@N;Ghed(2A+xY2B7M$-tOLJ9`+J5I3}br?dBILDk68N_^_eQ=eFg?&@;Fa) zUx4WX<5ZtBvN!YcZ!ke+X;|lMrNH+_yYpF8)#B&sTz_{GV&p2{BiNe%_U6qQ8f&vn zDAvgKr^??+!kYiGl2nwle6;FS|Ek@TJ~oy{TikW>Rv+C8jd$z^IT2A=!qvo znaC#jY-iKKvL7M0PAFpI;-nU%Ixc($9rml1qqCFohqF2Xa_i?S5) zrx5u4jxSJl*Le^z?J|ls0m0^SO9;KP2WgV|gfE5KC(dG-onbGA&Ht2eANH0We1%Zf z6*_Cn2TJ5;*m?5t-)f=?=%(|kNwne0g!x%T!4qth!NnG5f*t;we294}08Zl99{$Nu zkXH-*foeH0BU_qaKF=!uo0@B_i2^P0N#QDlQxBdU zLIil#Cro)1q|~M@HMA8$gB5b2KQ#;{g)2{!wBeoitygUhtpa~}vkPkl1ERqL(a--D zw$^@-*^d^eqI##-m9p@wi{~dzzZa?Gj+sa*S6DBEdV*jP?yF&E!e-?$7q}F<{TeLT zOw$Xq^>eIGdZ^{(QwbyFT^9SX{>z<|*G6bNLaBML$nWv;@iy~ajibo|egI|xOEq-q z1Yr7)Ggz(KVE~bKaia;*6I7EkIul5U8YqJ^cy4fL zP@U|C92u;xv_?>(_*$obB$UOFgX@4x(77q{Xv(X?dOwj+zw9O6PRd#A|^KLS{>ymhr$JrxgGnqXpI!5DYIx1Sd zH7;`z>tmY5u}!_LuIsGg?wBlg)@ThJwIet>`J%4{oX?qsPq&5c?fQ@67?T(|67TZh zlaP0niOCS_M@haOQ<>7FiK>V!9b?i^B1ChJK#x>&F)y>t&!Yj^PtD=EcH`FHNs@=@ zxcQY46Lo@7vLn6(KZ8_0V5p}bb63E|8KWogr60X)0Arlm!|C(8spU=kzm2f+9xSQvBv=w3&%G*KutT?nxrAM`Qe$9-32KdS75{jOH9 zvVrGZ>iD#+1pDx5k%temMu~s--`h4-8LXYd_*`>J*H>I+V{^ zaX}~3MMtw_*?Gu)_5ZKGbgCDQWj3?OULR3psA;od+hn`_YXnoO&GJ>Xm?@Xh5~d24 znyoPQxF(UdQ*<*u#(3u{JFOg{=?xuZu{Unzo~k%4j~AAv1gWh5;bWJ!TYN~~PvU_y z%=xbI!;fjYP$Mz^f?#HocKi`4`j?dPXx{@j;{X&J8{1PpnNs||UcDPA%Su{3o_)M0 zceOxzwG^P5|7RI=XeFKjUpn4s+uC+93hR61W?g>}%%tv&0SL2{tbUgd+v$TA_{_qh z_sVb>3nb`lgN4~CQ3YXGE!eYRC8BaNDCxjZ*T`iC$)@i|q=&OH=wx!<2x5Y6eY(wcVBQ zkRR-9^@tDM&Ce>Gjn`|{9JLcL2d~3C-tIoPy8S+(MG9grVntXN`<1Qd7)-*m2nXLC zpvKf>MVN`iNR!7mm(I^g2H$>6vS^{!))hh~RWz-{t1&EAbFF4&M6P(R3dG!;k$kO~QR5?f{am z2;u2PT4V_7fD)8ZI2GPCBDL#wlgPI?UVY<%rC;gyQW1Da`%UtVe%;XiN(=V!LiuNd zIZq3E4G&E6ET$`&{vx*)BLTuz`N)AiUVbOnDLNi&S;M^g#E3@Te*|-8>V49&sy19- zOSggADPpk$B;L=7$zjU<`ybpG=gsfZMgDL8{A*|a`}JGU)2%V=S8d)*Vf^7p8!{7o z5UKNA^IA=2ks&iGic{dDkTlgdvS?T9qI)+N3q_>eqZhI7Wt$gg!G9=WlQ~GhLTEeh zS*Ll?N|+UizZ3<+hl(ukpwOu*lv}H5T-JDW1p`y)@g=Jbw~AqRAvf%pn(*@V#MQ|_ zIdN-ZhBJ!@7V}BWh(pj(QfY^ZOYS#OffMut)Jv@EvDfP0DJg>=?a;39+Sw@A+~C^c zbnk`%fFSI?B&nyaPcsv_9y+d|a)3mNYx}<5 zlU|SL1M$}8Le`be(Hld`e&a>1JE8vJtW}|;3uW8&tFZb0TI1F7}0mbJI zZ!LdUbw!}lgp$++PCff=I&gS^-R&Cl<8L41Qz7MCt#F0d!yD?c2H^^6V6(BX={l+- zArM#j{jMp@qF3sa9^CO?-QwFcW4;ilNHdB-*ynL9Xp_s!jSq-pkOhjR{NVFC*Fk$x z=v6mPVEloH{Y?>ddcO-yn z!tzg9o8zax{r7_=x+&YY_lm(3Fk--%?;Rsg%KbE~s3)c`CK9d4W16EY&&!@G-*V%& za{sq-d2!E6WptpDRYd+z-)7d!mG44Eo3&!; zojR({__0Lt>OPk2%=|o?D2FnBxa_-|HGYFG@b*@Q&SwL&od^p@efik)XL;iWR|?;l z5Yh!6W2LbSsks(#2HYkT=?BV^bP{LfF>1dgHWUF6s$agYS5TEEzJxgX-oPffkS@cL z_}Zj4ktfJ!hrZaHD(!HpYZ_WCR~tp`ltANOW@y(MyNLfTs2#r_sH~9iN%}q}#yLqd z9@!gAs$SO9;zN6M&aL}{AU4j|q5}q$k>zjbsq8E%^3^P-ngSULTp`Y`FUVc*T8N+N zMFP}7Ecd%+wWOSFbeStoCu{X&D??wP)l|gWvwxPtCcI1hR~jKk%-=`23T@!OiH-uO zwsL-{ZGcKHN2Uf(YA%?^C~2sc(XPvCtz5>5Hml}xkF}o~6Cyy1?+t(VvPe4Xd>`FKV}gmFsmtb`HQuBBmv7iJy*6c@5t>h#C`8?P z=+2W1MOecte`9W|gO>WvH(I)@alp2?uaW__5~Iz!DZs*m{$(x}C54{SqM9jer@B)j zgizJ|lMHu1qS)hB55`O*hL1efnMw9!RTB@@`GjsUJ~C<|l*T2M$K^JGM#hm^>5%eV zXfbi}v)5;ij6tWH$P7tZY28Mz=ZH|lY!nz3d_JY5@5(eT;&0tSzP+H=D!BCtuS{r^;wM5n!@9tN>8?c$s_@C;Dbn7{q_gBl` z?zFe*ylX%yiVl#@jh$gwk}iqN5YZRvr(dBUJO$*pXw|U`U+JN=v#=n1+MHn z3@aSF!@`G#D{`0188mct(P8_@O8fX>Q{ffX1bN;}owLNC>u1~AIU>aA@d%zWg5YH8{lFDep+8tn$ z%}W2iEq-nW!!oP(Q1dsN4@u$k+z6eoB=-@~q*kKnmh!JTsg@mbLLGY$(M}r}?=`$M-Ry!<1kn_W2PLb8Cqu!cq?1LxcbD7U7gd3O2iJ&& zygcZdqS-+9eLR$i(-!`0FUV(gGPFC>p|CN^1p5m4o*OQ89QDuyKzhY8P+UaNLX!Fb z-8u$IX{r0hT_bk_N^2r0C2^LS(Ji1AReYnbqw9quuKjA)vU=PcIcBqaK3 z=6hXl6={D^o2q_lazdbBQOBby1o=akP1M>v$R3wc;18kgY2N|iRWlxZ#a%W2mryu} ze0R3GzJ3sHyHI9dot#2ztg`ub$u?y7@g7K?f2_Yya$u-sCC^9Mag|5dpYgHWiWkM; zvJBJ42sii%b72-6yk{s995R-@x`I&Sn7sGDhg4&t=j2=DTSLYhd7mXHVRX4L3MV$9 zB>rDgNdS?zE3}?;9X5M~hUy~9O1>H^3{h=83qb^x91vbI0b`f^#%APZ(7<>HVB>Me zFI{)8_DEE>kbK?A6|-+bUaZ~v*9cM)Y*jA|MHMnx!$jU@m`01#u>P14Q9J||{g{8g zUH#lodcWuLfu+yQTt^>#VoGlow|+hiOUH{eLiXB=F3gwWU>zW7|0Tdie?5>q3SE-4 zI~~3y9-0Xzo12HlG6Gy|SwqS}x)Z%A{ZuO7l+Vg`^L`1$DATS}fX=|vsV{`-{FO4}`JC~YPZujJYEj6(h5boJ0n2xC z@lPFsE`8q-tq@R<4Ft1}KRSZ_TY%Gn`sdm(R(Q`;RFtXC%K$p#n*>U16_a|mKgN`W-8%a4DID8gQ- zqs#7^4Q@ID1yCE1-8BQgb5x98$4a3$hIy>MYqPjMDv6&|FRXw|8fO-0N#W|+WVyh- z*PtT0+~@TBXW{NDe^^|E4g;8z1C&#is`BCd`P9U1`Lc+#;5O46*Xr9OEuMNX#?@c^ zEb1l-=1qs;QkNBPX;L^obxlo?uIvlykK%!HQTv#=n2=pAl?IvdpUKmr{}j${D)K}s z>T~3eJGKNVivSt!z)tgGp`di18HO)Z#cP^3WQ(o|>-(@1#3is|1TIzm8@OpM^^Ubo zL81sB?pOO|SKAADYfdN1S^>cm(HDrj+7StknUp5V_{x$fSq4@%jgx-pNqQ(#whphq z!P@dm!iP$hPq$9`tGLazBxVoW#wrw*tLZ*WH!NT%mC5!wddZA_$)L$T=>ayyWr}b) zPJ2S#pI`0f;9IEj2(;)v_6KFuMP~R}Ri9p_*ib;G;B75-Ms*>EJP|mX*$I|Ky}nRK zMn(SDK(5!&Kb9PNsTMTLgVzRpoll8#LdvVxq3cEG=tDS;!Q{wZB7*2)O2E&A?tkqfOR@~Zggz+AoI56a z4D{D>pZd!;5@OWDzibrk$QS>-Vyh-n7Niw^cm-;|zh&K#7U+2Y87z7nGnnOx&_aHM zD|Z|!gZ9Y3W!_YY8W~eKvTT_s-8NAvq+$?GA&xU zjyyUdw*a4HyG~Y?$Qg&7_inx=r={#^lk<+hc+%#DJAG%p)+YJrLT zAk+Wt49J(R>3fQ4Z;FNLJE_nTmg87g~nhV*~6#=&*8m;j45^G0y`yZRzJTCr%L8^;b9uHh) zZp8hY$+$|f=aab6$j22t5ic9!s1@iM75CNj+7^B;x(8v0z6lhN9Qa~tmISndWXipU zt%+9ozU{`}?L76|nVg{G=dA0Q;IgSwWJv~gR-~C1LOkuIq(Tkwv)645#}sL^TYsKK z@d@fAdv&BiFHV-eTX`slhDTw#T)Z(V28P%oX zuc7N&evvL7ST$69suD?I1E08P_0p-i-i_ou?}K4gC7*c?xKo+=MWpR!*4R<0B7C`7 zkKJpR(A#guu{$u*vYn(1`;7t&H>>5UXT+KNEl<^}!#%Bg%2)trh~2>|BPe_}%8^FU zlYVY%_FX0A=0a=0XD96>Z^CXq*cmnbG~U<2&POlcQ#nq$EnXImACxaRMqtyr&~Zgt z&s5^AF7ZRYXJLdbsxeB=0@7wJb&(fkniy!6K`E5myrn=A5zPf5`Mef(st|`!epE*R z7jS_3P_E|^f8?8$TW(7Q^72fL#yXcZC`mu{O2YA_vdrJ z;AG% zzOT6nuxR9g9t&J5>d1**?G^iKQ+jSP(WOtdQ$J_Oactf&07WteyuwHC>}VLQ7^JP0 zvjmT|yfPHZe`Q9NOCGytAKb$M9p|B@3JxI!j1Z zZo$Tl7f_Vt>22ZuMX&I8s0>;X476eWEj@;uVL0)8>EKE(5OEM_iJGfY6tv&r zINPda=~$+_zcVCX)YLytkPdBlYK&rGR`2)+3sd8H33Yy+GOLwJas1f7YFdU`yg1Zv z{Pzg4eHe?kx5OTyvH`l zFwEXDE=l)Yn`N|0j<6{!!KqBY&S8Kark`_7*Nl))6iM{xlBSeZM@Pzr7*MDaeQSUx zx#X3^ouyJ?|E}s7mlIJvr)v{WG$_(i9f6opp-1o)4$h(1v8K>a(F7EG*B|zO4ET9- z?ZQvlIsFKU5eRgQi~K7-pQp+pr0m;PPFIqc7Z6|4)YtBqB?kCx5o9+-D^-XDcM6jQ zq}fw#^4C4nh~cTNB5$oI1BJoMp}4?Rfpbhs%0f~_uD7n*_s%g2PR7ESWNW|euS29K7bsQAwaA3vsVkoAXECL7#97>8%lbHp97@WRo8 zg8HH4rJSGsf=TZOPKG!SdkemH$cuX*H1nm?8CXK;Z6x`;Klz4be?1c~d+Oa+m6AFt zeZHAnG@?i%46~|zW1m}>Ki_6CvpaGfmYfv_@88|C-x>XpTpnj~uDG|E)VZ0pucJ+& zJy`1K-KV$J!>jzMCy7iY7s?GjUUB0)$B)o{UvRi2h0(WPk`{2gsCCu6XBb+V^d1)^HslA#fUiHEoh4g6k${ZLsR)<_f>VPlD9 z=_Xk`$hck7upG}fwFWj}HoPUmzQ(>?@*Wr18~ZC?bxf4W*5zi5li8bF4mXug8x7U* zlw|3)K{5@WobBqt#JcTGa^lal%B&}ZAyJ@1#5p*;apL3dhx|g@4 zu!qlCI%<}CIwppyO_n+Yc<~{C{TvM;_eK`LxJ!Oa{?USE(_$}EhimESztZ=uUo9;yZA;fqBYUAj6@C-qSV+p=4UsxfxSKJyQj5GQG_8E8Gfk6bhCq0th6Yj| z4;TRlc^C!P$#Vf^%qgAe$X6GX#`R>4KlB8qDgfbeFQuc%@D} zx}6^M7MC?Lccf!_QyIu_rxh{hxh`1{Dx}uKBS1z+6sM*r^PKV@Ch-Ri(+J2ZDd5KW zQ<$fC*!xYY^t{e`YjJ=Am0hy#ZW6V@&!j?AmD1hIz^zgtDVJfQW`oJE{2>`1|ii)2xOf zq1(Mf!zxk=!DVg8Cc+!-y#M-&9qS8m)Rn9?s)7spP)gYO5yuO|eNUS_)LnfpxL<)1MN=N_FV53h&<(Fg$T&IyPAbP9neZMe^haQ*EZ@(vCw9} zYB)#mIcb_~Wja6$OYSDqbe=9@d@S_|*HimN6WZ&ESu+EJrr={9<&e;4_m?ZE9Ak?_ z9=`E((CuIrl(ol;53vi5WQ+VHl`-gbOJ%r0c2Wc`MsyPV*5u8HUbRZSf2=3gCe#gs zO%=%~{N98n1^8eX)ToQ=rw1*tcX$W5nB?sDR~JGl*z>i84I&1v$lNCF4(Az8hS|~l z`Ww(JvxWilcuGp1M8g`R#o?w3vW3vfv(V!`GQ{$v^b68nH+_CMs_SrQouB^feo7b8y%ckL)K>>dO@iYz>nd0nT$- z!fbaER~)`iwba^$NDg0~U`~5u`>+y20bDOgixIEmu*Y1ye6POF0LHdb94%E;XaDDJ z`p?fhl@w9!Z#8{nDXvE{s^29{0OdAzwE|zU~p}pUiLLYG)4uEN*_gt z1${vV;jI0b%~V@OMvqV8*uzb(r3_~7%cmN&r8GPp`;Z%(&j)w3&P@MCvFLOkf8Xx# zn|vtTE9$C%$|GQBy)41U=_Vi?{`Hde4_PlA!rM<-b@~C?*_(a(LH&@mU=)$pzFu!< z&<9-@AWz4~_TAFDFM8KUpgMLZL-fXcMS7C(pY5ic+~^uSgL~8 z4fa3LQtmQ}_#7Lk#D9TpTsG$edAhm4=28?%PFLKQX&Bqq>0Y1J1T%be&F7k1mh+y% zs=gx7q&JuFz%8V%!Ts;CYv{t>wr?VFIIKDWHz&}X0|bq$|&BVv_FxrQz$_J+>WbSKR^mL)K^ z3Dly)Vo^&bVcjRlFKz?@&n5j0#no|^7fO;xP}N#M>V1~m6`gLjS4N2hWInfIb4Fyr zL*gWkurbs$Vel~7Z&j?VRmPV@qzw2-UIro5?bs;2h8VSZ^WH)ZLuMjGhxshUaOkci zrctp#>i&*UmKIuJl0S&)m37IoJea$DkS9d1j|#?al~jZF_-jV1%X0l@`f99t${zWcfh` zYeP<{_l~ig=VGNwNJ1PLE-)o~I2LLTJVuxjDO^xasOY$I@84^5BoeRUs>{fTa6Mm*utL$DB_7xv>=gd9NiFFueJjC8nTM~IDD`AP`rWIflk)is z`Lb@Q5lq%+DQ2*EO!(H*GCWpIkmF!ELE6F^4I(%qd{ZOjlm-X-X`$Axr7=K|2jOU3 z818}FT^^vC<TIyl*VLz{G)UlKw<3P1RVQB6Bf1scTB9o4 zE6MqsuJ}&)$C}swHr#(3Z;KBUNm9|zqUx_$mdL)yO{TA*8BZ1EqI8LBio2rOa>GWW zChhG5oNNNM?0&r)*>q(=DMWLvuM`xq!ihrL~NNhDK5kqjy( zc3je^%9OA<#r_F5@kYn#C0fMcMnvXSl?;2t>$n;b6*kja!}sFFl;Q%B({^Em8AFT* zn^WM#@~{@$+*(cwbkBfw z_irA^woOf!g!UL{_a|4CNTR2Z5v&?Y`Q%7*V z4r}A6@L3&|LZkz1y%qc+BGaicg~y^r`uT}^7K>m0{QrUNYYkAYGT0G%mpTqmzN<;z zFmVPX;vv2#{>KPwV~(_k0I-Nx8`!-LSb%TPW#O6aP@00l;(IIoi>4Cc0$<%uCi|VA-xZ-I_Jry00z=+Tx zNY!zs&yySF2R;Vmu7)5wliNerfij>M6`La?7mX-0VsA#N&C&C2iBPlgosr(}=6iRw zirwIF<+#*0gG|M6z6yoRm?|6OWO~E`f-y>!5bTO}*Wc-Twn=m%mr8mh7$E6Trk%iQ zDH=|6F5~)SaevNZ{aLn>KqUE1|6&P$?;yqmvI&54|Bxicrql2e|4(3!;E})j9_rV; z8X^iP<0l9kk?(96S8tbD*MFIF|5x~%#gmscP46nX=sX9owv;q!;OI(`;pMbY(rW;2 zz}-@5d352;yaD@Ht;d!#CE6SGuh6>91|C@=J1y?e~5o{DaD9+ z%mxoD=yNMr*2${b1Sh$^D)ZT_0&=$jkmiTRnID-wSH)iex;HBpt&b*=aSwr&pL;fP zm!-Dq9L`7VYSn*{wruo>599ucAjHw0_UPET?fqDt*tWHo%Cxw92N-es)z0kINW>wN z(W7$6;NI>Q&1h2;m3xj(d1tu}BCWFie^nIyt0f!DS*aQq9Pky$Md;aH!MIzA~zq%I|^Se;Q z3_I?5GP88s6wH}?%Hv3%t7a*%x>%8F^Nq%OJvz9pQNk(J#+@w7va(PVI}?KJ4-v~3 zTbYa-vnOLJl_BYhp&4o&aa=G{U%^gp)$^m#7A%na_VwGs%0c*tK)L!VdeA=+IWH>< zX?4Dfx%}5M>+kNh2kNe&AhL`WvoI3@oe#ZP)9)3+a6(K9TzxAU&{OS6JHOtEXnms+ zlwpt|^vL=EBz>9j(mkatGTR2=)<$*{Vs=3si&7 zwI5p=rhdW{85S#dRPtJuzL2O>MaBTJqU8vnOs&DDwx9uWEt+x7h*A`Lvx?e8h${a6 z?~9`)(!XO$mt96iGw8y#7r$_g0Fyn!z38l$A-4wEb(B2Gd=10rZ^T-QRDHdS&{7Xh zyV9tcFG@2Zf}sSIe?iB0=MIr&fy+g90mNbBwburB_jQ1X`pPPiWG5l_liNinVv1_1 z%}?)deuWIUWa=D=O4rox=Y9<<{rp*!v z1+$oy8X{uEhw4d$D{1?Y`2yU5j!0$C-wTJ+pZ3D*lhvN*&hQOho_1eO{MGRtZE|@s zdrn|cV^q(DfCj`F(cNq_g7 z)X{GSoR1;CPrFc};7Z}(KBUU0IZ3DQMg3PoT1FLvzdi*NQvhr%`Gs-=OfGPvd6Fkz zLH_F1tL(-XC`zti_{c_NTo%)c3Gh%~pfxP{mF)@D;TK;br5MbWY=@F&0L#`oYOt)` zpgNUmM5X9m^gm@T8j2Th^D!0-)y=_Z)fS6!^DRh_cp2d2$cNc8`q^HZpZRyv;7M5n zF;cFyOTPFwF*W3MxK%3ZIm5UsxOs2SFpUsXro6F!-6Ad-+o=@lzG{U_WWGg+Jd=-` z*BXmt3}A2g-*wdAwUqsBrnSd66ZF}x`mo(ZeR9$g5(a;Iag!(Gsy=t6@otyr>R21g z@8}pnveQE!86L9kQ{QI;Z1AGT`hk}ndzT;bVMGhfDXzz`1Q%moB3pkD+v8)Y!HO1l zo9I$0zx>tmg-viMQ-sN63w^^t|C^I{#@%o3`<0iuiJ0b@hM{Dm4`b*nwwWK81QiU< z8VwfE;;3L0gB|A2p50ks+!Qi7(@u9`>m1u*cP_j+>h6)7QaBY zm~lLVoTH%Ue0**FRq_e8$`-XD!#erBGHBi6-#_;5ys{NgJ!F$nX-FFtd1w^v!MMp* zurhT6T0Sb1d3`%gklWwDY>F=sw6lLzhT+QCvQl_gp_3Fur?)2C%B!_JoNKcNn#*Ed zt6Zw?MwKRiXF5!|A9A}k`DS6dX;dG(9hrhs1Jeg8eB&S;+fOlZg-ptvHd|g<;lfjz z5UVkCe~!MIZ5_35eW?1-Q5fD{{4IV$=(_C?lC$&fk5?gE9I(7v1@DG`v^Ygq?|Q?T zX(1i>p7$W-Kopi{317(1S<;&pCv!+4r9J}mIbNH3rmZIs3U_1y*tszWQ6`S;u%>Z7 z^6EVLzQm-w@Ss?U7|VEK-c6d~;0ozyU+_Uym$35`xUXxUSZA|+rbV}9A{A!+n~bbbPNn;M~Fvq+B0;BauwCFg8r<> zM?QI4vXmv5sb-L>!(x!BVMCBb{VVQpEzgktOyxZbgDU4s1~knt$^a0}AsY>(WOs@- zf%AfGA?D$Rbwom{iUE3y(;y?(G;?)GFtAUp{7SQmg5kgTt55?G5&Mw6&cL4>-EeWY zxA|@i_xwOX!}^cj2}TeivnO#s-eikYcPQPYI3mVW3gZ&bNFZeMip&rT|4FI)K}i4b zgyvd$V`=&M>3Br=`5kEmDJ!&i&;mJtHh9`DB5c>OKbeM6_RxVB zzoOa0H&C^L#x3|qc6@DYrgamQMzsvGLP)<#k-2>10*Uc3hxV<44Ls zPhuZe2RV=LU6%&*e3i@g@b&a$D|@k~Zqh$%eO#UC6S^$e>{erQ+*z!$+P(pKoy+$M zHwx(o2*jYM_)}AaTNTxh@dW4kA*oorUd8f?YI1WBMXkIBi*yVA)+%MHS_TUAW=JME zg$C4C=Iw+3RzYP%*GZMQ=i)*?I>|CDG(-UMZ7IFeQN2=8T7mY=6OB4>>|mc=LH*lq-;K zU+%BjTcLwqXD?v>8a4iJC7Ux{ea)c>%jDjm+!6VQErln41pgQ3UCqAm=aoa?q^OU2 z&KAebT740R3=OeX4ef)c8Pw3aH58@7ZJ?K#DMMzu+nT=mz4gnDIpMatNEo6QmdPHP@mP)gD-LCL3Y*&& zkGAQ6Lk?_OLy7Vk8k>6{6(cQCy2F%=B-ySOv0ZIZhrVL@EXJRAID>6IqkOTS2@c%A=r)Wv^pRF9;*S7H3C=nWQF&^0hj3p|g?o)mK{*QsMnvqun%{?4S7E;PLG^ssE+@g)Mrz z>$s_tiWyWwi_c`BOX$B=>vnZ)cgpHM`B`#R#DUV=fU3a0v6WpqK~s?~r_IG_ALX49T-PP}+!ITKNh#gy@xK${eI|88r_`$|b6p@7sMQM!N?oTYS+0&K2)y}+0 zH<2cog}`#1&teF}dbUBOc0^n(mDH@-vW7An_faMXq{k4MDHSRz@e*TzR-3(ID3W=AJP-q_a^Bpf{}NQ z?TL2+i1fw2SKMnhiJnW}#0C2Ln$sEVwx}u#@9#?xz{n(MspJ_(bm?h3@gs{}8586TZs2`vS%*pU zYV0cqE;#**w1a73$&aZ_zRnQ|27aYo`jFUZZrx%JE6u)Wxh4Fra`%PNR9ruQk~d-@ zynVMS)FUSqbJql@QevK@Z8=gVxjVa>&A0};FMfjMV*VsiAEAD)6Q;0i2tBeNayH35 zPf~>I2>!fm2n70sa7=ZbAaAp2yuOx5N%zq0QM6#9en!o8zTmr)-8Ah0hTw z+>ce=)f!wXfvY`tRL15$urEzA{W^)xu)obGUK@N;;;oQj(~UCu6J@}0sCQ}ZZU114 zdiNUszl!_S)x6}8&feHLhv?!jzN_#&i~PuZi@mNtzkdGxO2W2wR(n|2-sb7&{|lo9 zarq+Fznjn+id~8=Z{_v4J1Tf<)c~`Cy7^(xnl@a0Wqx&(b@9qOk|64h*(=Y1^(xs zo>u}PeO49uJb8l1eirH2L2)GS#y( z1ow@hzxEj&KcR(_RMt2reT})hIbf*&vcx zd{@_O%#BR-qe0zG_d7(a)1r3d3EyDPJ@9xW+QYIB8t$lIdp)(5M z1@{d*+z(N=L^;U{ge@}_yBZRsWS$TuuIdN^y7-+Q*r}ePiWc8&*uDyxSz#UbA%kTh z+j;^=4%>o)Bn@-m9D2GkxX!SvA$YhciZ$rxCX45|{qLIDm@cgEU6%t|X}V_rr~=K2 zU~zAx#(z~$*wws7nBV;(qYvdEbFpcDC3e@W0OqA6TjCp~_grUSvPNot4U$?NAhsz+ zBpc=-(O#db7aQ{{NAo|r_kpjs>`N*Dq{nI#+OmOopSRdM8C)6$J>nf(<6rE6 zq+pSRooFQz67UMU{Bqf7rSVisE}0N%GA03tQ7pYA2>B@ZuJATZb$T|~fu8FLdV<$% zwPTVX39#o!j4lIJ@&&-#Sh40m802Gw&vD{BIsAQ&U%Rmp)`Na7%v?O(fA(RVF1GyO z?a!QiIa!2G1kpe}3^q*IE7C^G$7aOJG8ZZJIZrZoZ^3R2xz=7c{zr8S8CwZTKDh~y z8qx&7h3h4L57X#1`kLhyzR!&rMUPX6doF7R${~4PlhT-H@`LL$8Z}wsZ9REENZRx7 z7@a;hv9A8ubo?a6uCeKk7ie$5aNw#SjZbnrhzQ4(2=8VRoLMy;hm>Wn17%ZN!BUtitVeQ?5OC)3 zxzZ#(O~LVGu|Ffca{04-T)&XNtBXjk!OS3rk2*h`dVr^%oW?+ekfMs*LB};>xp=}- z(@o$7B%dfOYw?D)1I>HR*Ilz537`|0;l8ZX$m*<6yP$zLY9~p*s}PB*HDCpP$XH_NnE|D|E6f_`He5R`cas4Sr;U1r$u)m} zrXoZB8+c_+mQPo|r1w|G4KZsUz=A=~YxdKg6+BLrZ$0{Ix&I-q&;3ckb(KhQz`&i? zPDP6CT>PfUg_DGdI6Y5Lo0$^m&ui>oHfn`rNULv!FY4bFeI|;Rzy_he z{+XySabJzELHGI%5x%XKkMm9Sk@8W+y(Oh12Fe7@r{ z`ZR0nRX$8Z?P)Kc3_1t|LI69y(1T>&pcfF%-N$Wg8-pH!&te?2W1` zFT<@Hglm(A`iifx&lNf2OFd~4!#6R{_MK4eE;MHci5wS136}99$)Xg*i_SO8v)83; zR(YUX2K5fN(Jxq>U00=-)BOssvScXz7wgakjHcHBsY~Ix2Dze z-b<#PA$)t%tM3M;ps!p^)A-Ro*epZ~Q2uvOUgsCfdWJM;Gw2xV`Vu9NRkA!j;;p4S zbzU5%&vIvfp5-?5cHzss(?aax+oA?3UtJK=j1$3;l!dZfzV3$xiTnZ=vGMX#k6q(E zd6-5OWzv1uJ%6Y>9IRrNf-BA{PiBuA*D+Yb-KYEDb8kOdrZTzVzIrI^AL~`eVUp=< z2&unp{Pt=}j4tgFcx5dzApo(W@2ll-Hy{`TeT`>8V3HnRKX}9CZ{4?81zu}>gs&lO zUuHL3&)UZETqOAV)wX;~Jc9LpZO;DpFYyArnyfgtEq&4i-hGzu`Q1lY@*@r@e!fb@ zf~^V-#^yj!IbMYIqU00dN(cq*?I9@*8kRQ8ZxWF7xNtOg$YV|ywxxk9ABW0nLXM`g za!F1?lB(ras{o}f75iwJok>_v*6zLGpY;L(gUr>oSU||MnVpwb$Z=*BoRI<`w1=-3>4Qit%z%2d|EO*R!MDnIxn81i2Xz; zjf!*Z1XGm4+da@7a#AAPnp!=BTU5IsN@H2UYQjUV9K0jco_NEsaZSfz_xGwhb=rMq z0_Ol#Pc?VZvyf-K1^1m;3mo}K-#H_EdKiz`YqqC(b0e1sf4+K6gWVq`f9kd)?-i-FN8m0cvmw1ezI60IN7-1C`y()>y-y7pn}g6S0iYHF5?1pH7!H7 z^Vut;_4YIHB7Tr1m*c@4k>GgI)=W?ZO4TAuJQ$;^g=98GhC0OogKNq`O+F9pu4xGb zkp10SeN7ir2I+e3$?~D~2F||UvN!plJ5sB0Mj1?=26m*MBNN4KC)eQw=c?|rQ`r=k z1D;E>uRaB{@o#H5L#A2B)1!*uPQ`<^< z9nb!Xz@X^2I^ocv@08A>`Z>0e`UX(~rLQ*5rD=MCo3a$>=&@8&(aHZP_n-oLUX_0_ z=`Z`kJ!foo9wZ*0!@D@zeyW7~|-d=IVKfHX%zY?uHdJ?;%Rp1sC+f5&cU)w@pI)zzsZpE#_P- zWY;y&_D-RVIotEEV%X6prOXDUx`1kOMiEz7orFKS!uyC;`tkNIB{-&nXuQN6^)^kJ2ncv@MHZ&HKc;50S)PJ3IZ-EijjRe7+`^zHdA$=XN8&{g7b zRj1$imt~*zk0SWKhuGQ#=<5Q84e=V%7hN(w|Cbj9bJ(jj*li;c7{;FkYBKw6aUP=_ z()VT4D_Uj^%3KjZCb)j77j6y#2x8YmA|cOp5ikfy}X-?NAx_ksCSx!SLq)PT?A$S5EV7IlL~mIOhz z+mZ5Mw7$28z&gTAHnr3D#tjXn)3Jg3TLWHAS@tuJj!Yfq2dp}~R>xFdr(p6w`{=OP zZnX@=XjCaE#VPxn=HRZ71-j=eQDncc^!$|WQ|+C|U&+wvlTY-6lGgZ{!}u`hD$n@G z&vn67m9n32rEeeU*P>@NEW2vh!GHAh`)m z$pUJf1~L*D1K|e+iOE|Tg&&FKUE%is*a3%ePEvhZb$2z`z2vmZ%0E;+EDO=338+qa z%d}V}S(S{gm=e74z<-@Q z@+ow<>ZIkd;vpmmNNBLn97o|k<~{hMMXxt1NmX!_-G_Y>q$-B>{U}x=U*Bo_wlng} z)U@@YS;UF6Ix{U&2RyfxUjn|o{-35MFu=ufU`Q3_uH{vl;@Y(q0 z`6ou@JU@gfm#h<#PVn%n8n_HFmSINUv|_Wx#=KHFJ_!11we*d&(J>)u%WoSq z!6N>kXRzwYT3t65gL$yZVblGhkCGfY&FNjUIZ+Bdwe4?Ei5g@7m)_fOYh-=j@sisv zgET16Ih~K=w_;zz;rsHto+7tEXrSI5iYsmL^(1_qss$$MG5;7_p~T_i&%A;jjSiKv zD&}cw6ZxS*1z|**D`ZCZ19PCO3i|WGJxS%ZgEFg7=lfZbes3I{bBsQRg*`u%R`Ooe z2Tg=ak@u72yrwPlUE4Z3DF5#`Q6=G%o}43beGwmRS~#`#?6nRYo%w-EvYLvJU6DD0 zZf~vreU0C)0_WPcVF(=mVxdTN;Nyk;+XaibR|>l#o>*dkCm6O(Us>OoEuQf>Y?qh- zY$Ox~kjnHV50dj~)I!$iGBdxzC`|Aqp&O?dIFQloiEsJmAcf#M<%$_(_^-lwtNy3= zKbSC+@zJw*-r}uH!yk3xR12ccTbmOoF*N)9<8_spw(shzF{!g}gAte<#`h*Hr0+mm zyl}9o_>p~Ld~iL*Oa+8kSf0IS-MV@GGA2j&vB3Y&6Sb#DxX03@t}k}JlMW*OMdY=k zqn7&nt^@li#>!E@aAS=E^Q_JL$4w858-^^?R&iWGV_9^;BurXlQb-t#{{HtSJ-Z+_ z7fpqS8hjE7(2FN~D$ZmF7X{X;Anq6+i zXFl)Ar%%WjQ48T4G2)tlMi%uG+(ET>Sk>8@IMgkq-sc+loS-*xkHRw)JQ%K0Ss3sH zW_*;ua=^gt%W0E^isI@(F&Q1CXWKSzBV(Z!FL|p8iTwGQ1mi%tOaM%2NNiI18NRnO z7~ezx%;Zl-0Lbd=ou3Z`JM(gmHHjk^M$5czB; z2azeQ;x$V3L-EQ1J?b;{+F|G0Y3#-kMAz)WERzVo3CYuxn`aY_l=>-~I%g)pO(avv zD;%TM;ao;&h@mJh5t?w0(ax$|(S3&GuyqBQA++`$m(Dm5=`XF_W0=qIOlk(mz9?mrD8YvR{-8}X$bfp- zJn6WKzyxUoxH$>q(p~{Nhct6ls7V|Y>}>3&>_i#=t5P!5GuHffm0Y6>ofJm*GrXPS z&0m8;JYF95ON`W#0ZC${IfSQfq^?i@k6FcWNCV^4jd&IJn)-D}rD5yF;fQL8Cg0Bj z`YbrRpC_1;6qtvpa`dZ}jp#Na?SHg0jv7+ad#tW9=Mw;;8y;H2H7dWRdC` z67NEp^RDuj(wJ&S{!Rbc>HNJ^4dpH!b!axhzUA%N4`hW#TmS8r_)PwqHOd@dHhz7H zj?c5);SPouqI;=`CoW?P67rE^zzn;+QwJq{+QRM%V7@kpq8EM;|KBpiKP)o z)bD3fzf6~ClV0o$&m@(^D3L_FA1mPXGpZIL@t5drdza`e4-+4KAI(Vpbef1F#d_dk zM$AH==SX4^{>4rvQ+HEVbblBxkrEFuSmFMsniXEKm zj=r2WU$x$A>P2`qmCd(2Du|K0U&(_KgLR!Na(c>b7CWO0tpRt?kZu zlS{0E1&>}SPw0$*jY{&JupYTaq$7{VQI^ZQZT#q+CG@~AQPM#&@a?~MCaTevne@s% zY7i)y?wtFVaA}yC9kn&DuyWeHCHLS8V|rcqa?n(j?bIraJ$kY?Q zpOg=6Zyu1M)WgXP!*Q6_lfJk!ao0QVY1Ih*5`HD46j&fq2YSpn>spq=o2K7;Umf}J z+`|0#@8z|hQ*7K{O4kWK8ZQm!HqD`R#1FBuddmXwY%YFdCt%M#K0lrC^EaMeZhM)f zyc&nf52AtR1tGs$Q@ly#=6R?67yh*&Hn1z5PqfGRAHl1CEnlZ!e{a})(xY578x=nF zvw%(}odU=PCK~M#c6_V^^eakpT#=$v=jI2_~ zJjytP?CsbiWs{LjNcJAtWaro`+re?H<2c7Y+|#|k-@`xP!8xDL`~4cv7x`-oZp)zd zL56@IV#qRyVUP?~+OpmO2y9#TsjDT6WAh+2v~+_MWIVO+3IKX#)ti2`Y0 zuz78sn5=hu-*l<^StLH%)iDGqtF?QwkQ{{O?OK$Z5|nRcF84@P>?gIl%=z$^1#06D zz7L+}U22~b7>t94XMzCS-FygTOk1yfu-?GQW`kJ|v{>@L0Z)_Pg-UM0%8D|c7F z!?q-H>}X9oj%JP|YUtD4oDOH-#;WP@!!vKiKHLu9*pRK%PkZAQRF~xRNLYQ1i9J@C ze$rWrVgme+;1!LJue@pnepvR#^233Zd=8pA;Ke zJcmUU>`hJ*Lr!WE;6R*l3{CP;zHordthY;ylelYxMI0S2`Bz`1>w`NE)!eiA_*UOu zomJiYQ11yP>=#`R#Q3apagKxYIIa1?ba?%RJG+_zr#!D?2o>QdR*Nbi(e#NGv+R?~ zPG*yKr%|?MXjx+to+}`-v~~zrRdy-RL{X3{+wlABrq=%VxormV=QK^=)Be`4Dnr2NIDg6{>4= znBX4c52e4?s_0%hAJP{o?vEO)(<{HMK`Yx%o)E}Hit~<*ORN!AkLZ4J>pF~rn&%nP z-)#>_E;Y^Gr%8L_w*NA~3#NaRveWo9>t`|e0!!^Tn@8oep_EAO1eHf{;?YdmljeaJ z`p_{wef`Eq#azjp1?~qE3UoxFW@8R_$uAY?rmu?}-sAV30*g`j{Y|q&Uqhdp%axVu zCYlu9Fib9!jayW>Ci;@s8xqe&qN9u1KO?LVB@nR6$9`Mnp z5NX%E0`mZO2X;d9FN$+CYu0!mGl<4~O2EWj zrPy}Ji=T&M?Mv+<9c7$*v~-Pn2)Vm5?OftuR|JBx+qO75b|9qzp{%LL{~J6#t_s`V zdB(CZYAd&)2B~;gzxP&YaQQR)MrYG|W`{1Aw{tn2*G zK3mmB>SL>SMAhra>7RYKS_jCOUAw;QIS|n2e6zM&#vrL5Aio(YDLWx@W?a6eZy3M~ z1)rN*ZoAO4?S3Pt#0bCRF%ekWM0(Q`8T!YYlQJUVHAc&Ydb&CW>ParQNsGD72(?DV zOLvL*pj|wXU)s8cCAPS{X7C}ZfXQsTsv-a`wAPp5+mOX)ouSR1jM293@~^Gp0)*nv7Bn-gw?rk1Br@ck!l^@9N97n2AyXk&DxtKRKw=|gF`@xzD> zyPHQ>HgrH&$}0*Xr>3=ta!6~M+u}+mcdAoBpmiOG51?`6J9#`2 z=eOiMb+*{8_ywpfvcx)1#$wHG)4?BDGMd#P)VzFR^VSpr@JDsnLv@(cYW)+-&)`ep z1f|u3%v!iz!mS9?OlQVAr}^A>DUygjA#y4i1ANpsr$m!gisV;EtG!9I}UGO9SC`wL;SexLW6_J^?Un=N&gc|@XZW>!qtepWil@_Vb0qy?hEN8D zfa1H5ER9-9pKDLo_hfonX+Sx4Zg;K4wu6Ur4?nGa(Fmb9-@M-@C01GLJQlNoaL{uS z7g_OeD-yuA`+kQw0!jGM=W?S)FCpC>vM!|PAKA(edr@S9cQb*aaZmZsLHD65kPG)1 z0DhHk^CS&O06KpY$^?7=7Q6Q&xV|BTQ+nCi(mqn*!IRWVnmvmy%Js5I?F;+hs!R9V zJT+)$YzkszrKBnnrEv+_3!&MRPI-1@&&h-EC4%h!@`XYm2PV!Ht2@Nhs$Lx z`SvZdQ1|{pxBZ7agy_}RHJx;QMbZ68QZHXi6ZCIscA0j}j!}q}8RLl)nu`Ds1s;dzTP9yUFFsj?xClhnDqh->EBx~AySK9kf zRD+3=eUcv|>>TBKU`7xn1n+`%9cvEUeg$OR7kvrmT|$_Ad#zCJkXTu6h56%>sMW2# zxUD^Q=ynfL5-A#9R)gw+P? zutVu?5Rpvt?|PaIxainj9@yF+vZoCiGTT&X#FKV7yJ#5&zOW~!g59QaMHzy9vItZ3 z3fCv+SC_w;A&cyK{+%BPSN$h&|1F7(*WYNILSs7O%zIX&Dff^oA42n5Si}4s-s|C? zL%5u|xz3k*UT}~%%Y?Z!9g)eYDe!vN$G8aExT`}E!R2APvXM^inkjSXz7>2>kF4p! zm9@In9?uXO*}T%WcAS7N;R(aeAr&HJ5>}!t`sc+R4OrdI*S2}hz8AW|`tHa-yROK* zX{V^RBpT0b5OGY%t*RigbL10m0fp0Xdg|3DIl|ow^%qsv{i1q(4Q}whX-g7^c@|w% zexx+?yrSMPqM~}EURlXV{=}^YkP^4+Px$u<6C0gH&g;k>OqoMM149O@UqhufUK;Ab z>w6^qqGJ(V1GVHjA?Bz~-DkSlQlefF_KET^yEs~{*UTJJ(f5~k;O44BoCjMcdP7Z4R9JgTS=tbuo@6E-PtT zD8eUaUA0rda6V6CpacK6LsHG&<#-GyJxAgE0}4k8>q{Tmd`YCN8}y2$m4S%<%Kozb8(_CY)L5QTkpXUsf~o$+B=bN zR)&sfl4LkgYi1T)mq1d7QeCvmixuwB__lq@6E^+~N z)BUL=H&%TTWm7wmy%i~tyv7#d4(A>LpS36m^xU~vQ2b6yZ@?gVoJ_%EDiK5>bg=%! zq5t|-$OqeQ0T0q+Wb!B}UZ&z;I*)mi_N3C;P%Wj!T!%Dy-DJ`}+%U+RlfDSt(S$5;en{!{+!^Pw$jyjOdx?Afx%~IZMO0$~ zA&ghmyO>P`haI>Lv#p%;P`deY{Of)RiiC zum@Blm3k$WPVkn$G(C)_tWgXZY$`lS|L$hIZu((+)?wcv+n$Tbhggw+CxnuL^#GU9 z!%Hxo(|efIJ}XDw7WkZGktm{@sBm1dY?F_4`II!ZMm^xQN(o~Oq^<2iMW`hWj3y`# zuh3)1J!5o*R5vIt2cpw^g@lWubPorSrl%cLV%DnQ-)$-TY@&rP~RdC!h&@DKy@%Z1q#0$Z)V zT;`}H?xB^H9n&RRLA;8)>+#8d@fzT?-{z|n1*Q?+%#99>Ncxc)AZrG*u6vyB z3>lHae$wV+R>icw?f{B+n=z~3?BOAKEkipYQ~=vx_KmFN)D(or5Ws(pN;r*z4&%Kw z*Gs?-*&I5%(pW~iJQ`1}7AXOA-8YDBF|S&K$`=Y7@2wE^APr6C);M;>eYDDXkSK+G%vFc5TT#%R;tRW83GjJggezhD3gvWF0iMRs0=Pvu7xxMKNoG1S zYhhBI7aq?CLz@qB*hBp>h(YTgV24ZLYRRa554)pB77UjOasJ=S`^47Xajg(|<=gmI z#;uF)Z8QwTDXs*pq|^Tr%Q}wK9;BB_bH+_esDzE>6uk`bycq?NNjzL+j@{OHcQ#)i%kEX;l2C%S={849Jime z+k3+*`kxUnOj$PwiCR~VN)%uRL48eO9)2|{@ zTKYKrEo}FyAD8l5{F#|@QNOT|a}U4IvHrzu!RgNj_NZmThDY6rG(WAEAae3%m75Y# zbu^bE;jqSH7C#HhO3=;{v-A_RPl2?b7K$`Ij+D$?<9{AWd8?Opx)9FmZQldVH|&z! z2x^}Tf(9MwR34-@xL==dH(DHhfn2SN!xpd+d8=Y_*w%+!Mv)4E$f#E5WcbIygCMR& z5P7n-gkKBB;l-^;@Lc7EbB^5X*{?u2yW@`W{Ev%;H+`Cw9|2Xx@-32m$S=YJTy<0B z10}3CJz_aRla*)6>2<^An?^StT7w^=0z@NHJFYf232P#bbUy=Dp>}Isq1{28KN(X4 zUO0S-sg{)LKWV8uqepMX5K=x(cvcqzKCvD~d|!dtEG{%Gh;p2Woc*Qzq$BC&QCwiF z_8oG{P@S1;Ma9*w@3Ud^y?<9;Bz+i#@XuXGxY7a*h#wFGLsr?naT`bkvuVZ;V{40i zC)XT}2FebwR>NjGde;!d=oYJ&IrVB78zAfy+lhQtUg3$%;{ifz4vftxZ@djwJTh%) z+0+0^rDSA+tijLE=s244;s~%}5|OiqR7RU?BnlUiSr-BEfBkF!{58L4AgjIf{=?C? z!fB?eHD1?znMm-yu*G`_TjkFLwe`C@U-pn2WSk4TN&eZAQnxmPChAv%!oV=!ub+Dk zJ!CM{(>{r-L7v9~b+{c(1Ko5?vJDTrF{D$Y>J#U?P=ITqQ9AA#o$GW}05}VR4@d+C ze!0y4(?biP9WC0(HUdGJMiB}95u~JU+8<9cb7_nny7Qtl9e7IT2dJH(`$%0A-xpkn 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 eTpkpU!~%kTczu!mM0o>z$w(?*9RfuQ8GU literal 0 HcmV?d00001 diff --git a/platform/docs/docs/deployment/authorization.md b/platform/docs/docs/deployment/authorization.md index daba7454e7b..6de334c7c3b 100644 --- a/platform/docs/docs/deployment/authorization.md +++ b/platform/docs/docs/deployment/authorization.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 7 sidebar_label: Authorization --- diff --git a/platform/docs/docs/deployment/build-for-production.md b/platform/docs/docs/deployment/build-for-production.md index b1fa6999ccc..7c061a89eb9 100644 --- a/platform/docs/docs/deployment/build-for-production.md +++ b/platform/docs/docs/deployment/build-for-production.md @@ -70,7 +70,7 @@ and registered extension's features, are configured using this file. The easiest way to apply your own configuration is to modify the `default.js` file. For more advanced configuration options, check out our -[configuration essentials guide](../configuration/index.md). +[configuration essentials guide](../configuration/configurationFiles.md). ## Next Steps @@ -108,6 +108,10 @@ yarn global add http-server npx http-server ./dist ``` +:::caution +In the video below notice that there is `platform/viewer` which has been renamed to `platform/app` in the latest version +::: +
@@ -127,6 +131,6 @@ web application. For a starting point, check out this repository's own use of: [circleci]: https://circleci.com/gh/OHIF/Viewers [circleci-config]: https://github.com/OHIF/Viewers/blob/master/.circleci/config.yml [netlify]: https://app.netlify.com/sites/ohif/deploys -[netlify.toml]: https://github.com/OHIF/Viewers/blob/master/netlify.toml +[netlify.toml]: https://github.com/OHIF/Viewers/blob/master/platform/app/netlify.toml [build-deploy-preview.sh]: https://github.com/OHIF/Viewers/blob/master/.netlify/build-deploy-preview.sh diff --git a/platform/docs/docs/deployment/google-cloud-healthcare.md b/platform/docs/docs/deployment/google-cloud-healthcare.md deleted file mode 100644 index 0484bbdfb7a..00000000000 --- a/platform/docs/docs/deployment/google-cloud-healthcare.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -sidebar_position: 7 ---- - -# Google Cloud Healthcare - -> Coming soon - We are working on bringing Google Cloud Healthcare to OHIF-v3 diff --git a/platform/docs/docs/deployment/iframe.md b/platform/docs/docs/deployment/iframe.md new file mode 100644 index 00000000000..4aef3b96d46 --- /dev/null +++ b/platform/docs/docs/deployment/iframe.md @@ -0,0 +1,163 @@ +--- +sidebar_position: 7 +sidebar_label: iframe +--- + +# iframe + +With the transition to more advanced visualization, loading, and rendering techniques using WebWorkers, WASM, and WebGL, the script tag usage of the OHIF viewer v3 has been deprecated. +An alternative option for script tag usage is to employ an iframe. You can utilize the iframe element to load the OHIF viewer and establish communication with it using the postMessage API if needed. + +We recommend utilizing modern development practices and incorporating OHIF viewer within your application using a more modular and integrated approach, such as leveraging bundlers, other UI +components, and frameworks. + +## Static Build + +You can use the iframe element to load the OHIF viewer as a child element of your application if you need the +viewer to be embedded within your application. The iframe element can be used as follows (use your own custom styles) + +```html + - - -[dcm4chee]: https://github.com/dcm4che/dcm4chee-arc-light -[dcm4chee-docker]: - https://github.com/dcm4che/dcm4chee-arc-light/wiki/Running-on-Docker -[orthanc]: https://www.orthanc-server.com/ -[orthanc-docker]: http://book.orthanc-server.com/users/docker.html -[dicomcloud]: https://github.com/DICOMcloud/DICOMcloud -[dicomcloud-install]: https://github.com/DICOMcloud/DICOMcloud#running-the-code -[osirix]: http://www.osirix-viewer.com/ -[horos]: https://www.horosproject.org/ -[default-config]: - https://github.com/OHIF/Viewers/blob/master/platform/viewer/public/config/default.js -[html-templates]: - https://github.com/OHIF/Viewers/tree/master/platform/viewer/public/html-templates -[config-files]: - https://github.com/OHIF/Viewers/tree/master/platform/viewer/public/config diff --git a/platform/docs/versioned_docs/version-3.0/configuration/dataSources/static-files.md b/platform/docs/versioned_docs/version-3.0/configuration/dataSources/static-files.md deleted file mode 100644 index 62c53d69b93..00000000000 --- a/platform/docs/versioned_docs/version-3.0/configuration/dataSources/static-files.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: Static Files ---- - -# Static Files - -There is a binary DICOM to static file generator, which provides easily served -binary files. The files are all compressed in order to reduce space -significantly, and are pre-computed for the files required for OHIF, so that the -performance of serving the files is just the read from disk/write to http stream -time, without any extra processing time. - -The project for the static wado files is located here: [static-wado]: -https://github.com/wayfarer3130/static-wado - -It can be compiled with Java and Gradle, and then run against a set of dicom, in -the example located in /dicom/study1 outputting to /dicomweb, and then a server -run against that data, like this: - -``` -git clone https://github.com/wayfarer3130/static-wado.git -cd static-wado -./gradlew installDist -StaticWado/build/install/StaticWado/bin/StaticWado -d /dicomweb /dicom/study1 -cd /dicomweb -npx http-server -p 5000 --cors -g -``` - -There is then a dev environment in the platform/viewer directory which can be -run against those files, like this: - -``` -cd platform/viewer -yarn dev:static -``` - -Additional studies can be added to the dicomweb by re-running the StaticWado -command. It will create a single studies.gz index file (JSON DICOM file, -compressed) containing an index of all studies created. There is then a small -extension to OHIF which performs client side indexing. - -The StaticWado command also knows how to deploy a client and dicomweb directory -to Amazon s3, which can then server files up directly. There is another build -setup build:aws in the viewer package.json to create such a deployment. diff --git a/platform/docs/versioned_docs/version-3.0/configuration/index.md b/platform/docs/versioned_docs/version-3.0/configuration/index.md deleted file mode 100644 index f51abd3d3ac..00000000000 --- a/platform/docs/versioned_docs/version-3.0/configuration/index.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Overview ---- - -# Overview - -After following the steps outlined in -[Getting Started](./../development/getting-started.md), you'll notice that the -OHIF Viewer has data for several studies and their images. You didn't add this -data, so where is it coming from? - -By default, the viewer is configured to connect to a remote server hosted by the -nice folks over at [dcmjs.org][dcmjs-org]. While convenient for getting started, -the time may come when you want to develop using your own data either locally or -remotely. - -## Configuration Files - -The configuration for our viewer is in the `platform/viewer/public/config` -directory. Our build process knows which configuration file to use based on the -`APP_CONFIG` environment variable. By default, its value is -[`config/default.js`][default-config]. The majority of the viewer's features, -and registered extension's features, are configured using this file. - -The simplest way is to update the existing default config: - -```js title="platform/viewer/public/config/default.js" -window.config = { - routerBasename: '/', - extensions: [], - modes: [], - showStudyList: true, - dataSources: [ - { - friendlyName: 'dcmjs DICOMWeb Server', - namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', - sourceName: 'dicomweb', - configuration: { - name: 'DCM4CHEE', - wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado', - qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs', - wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs', - qidoSupportsIncludeField: true, - supportsReject: true, - imageRendering: 'wadors', - thumbnailRendering: 'wadors', - enableStudyLazyLoad: true, - supportsFuzzyMatching: true, - supportsWildcard: true, - }, - }, - ], - defaultDataSourceName: 'dicomweb', -}; -``` - -> As you can see a new change in `OHIF-v3` is the addition of `dataSources`. You -> can build your own datasource and map it to the internal data structure of -> OHIF’s > metadata and enjoy using other peoples developed mode on your own -> data! -> -> You can read more about data sources at -> [Data Source section in Modes](../platform/modes/index.md) - -The configuration can also be written as a JS Function in case you need to -inject dependencies like external services: - -```js -window.config = ({ servicesManager } = {}) => { - const { UIDialogService } = servicesManager.services; - return { - cornerstoneExtensionConfig: { - tools: { - ArrowAnnotate: { - configuration: { - getTextCallback: (callback, eventDetails) => UIDialogService.create({... - } - } - }, - }, - routerBasename: '/', - dataSources: [ - { - friendlyName: 'dcmjs DICOMWeb Server', - namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', - sourceName: 'dicomweb', - configuration: { - name: 'DCM4CHEE', - wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado', - qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs', - wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs', - qidoSupportsIncludeField: true, - supportsReject: true, - imageRendering: 'wadors', - thumbnailRendering: 'wadors', - enableStudyLazyLoad: true, - supportsFuzzyMatching: true, - supportsWildcard: true, - }, - }, - ], - defaultDataSourceName: 'dicomweb', - }; -}; -``` - - - -## Environment Variables - -We use environment variables at build and dev time to change the Viewer's -behavior. We can update the `HTML_TEMPLATE` to easily change which extensions -are registered, and specify a different `APP_CONFIG` to connect to an -alternative data source (or even specify different default hotkeys). - -| Environment Variable | Description | Default | -| -------------------- | -------------------------------------------------------------------------------------------------- | ------------------- | -| `HTML_TEMPLATE` | Which [HTML template][html-templates] to use as our web app's entry point. Specific to PWA builds. | `index.html` | -| `PUBLIC_URL` | The route relative to the host that the app will be served from. Specific to PWA builds. | `/` | -| `APP_CONFIG` | Which [configuration file][config-file] to copy to output as `app-config.js` | `config/default.js` | -| `PROXY_TARGET` | When developing, proxy requests that match this pattern to `PROXY_DOMAIN` | `undefined` | -| `PROXY_DOMAIN` | When developing, proxy requests from `PROXY_TARGET` to `PROXY_DOMAIN` | `undefined` | - -You can also create a new config file and specify its path relative to the build -output's root by setting the `APP_CONFIG` environment variable. You can set the -value of this environment variable a few different ways: - -- ~[Add a temporary environment variable in your shell](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#adding-temporary-environment-variables-in-your-shell)~ - - Previous `react-scripts` functionality that we need to duplicate with - `dotenv-webpack` -- ~[Add environment specific variables in `.env` file(s)](https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#adding-development-environment-variables-in-env)~ - - Previous `react-scripts` functionality that we need to duplicate with - `dotenv-webpack` -- Using the `cross-env` package in a npm script: - - `"build": "cross-env APP_CONFIG=config/my-config.js react-scripts build"` - -After updating the configuration, `yarn run build` to generate updated build -output. - - - - -[dcmjs-org]: https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado -[dicom-web]: https://en.wikipedia.org/wiki/DICOMweb -[storescu]: https://support.dcmtk.org/docs/storescu.html -[webpack-proxy]: https://webpack.js.org/configuration/dev-server/#devserverproxy -[orthanc-docker-compose]: https://github.com/OHIF/Viewers/tree/master/.docker/Nginx-Orthanc - -[dcm4chee]: https://github.com/dcm4che/dcm4chee-arc-light -[dcm4chee-docker]: https://github.com/dcm4che/dcm4chee-arc-light/wiki/Running-on-Docker -[orthanc]: https://www.orthanc-server.com/ -[orthanc-docker]: https://book.orthanc-server.com/users/docker.html -[dicomcloud]: https://github.com/DICOMcloud/DICOMcloud -[dicomcloud-install]: https://github.com/DICOMcloud/DICOMcloud#running-the-code -[osirix]: https://www.osirix-viewer.com/ -[horos]: https://www.horosproject.org/ -[default-config]: https://github.com/OHIF/Viewers/blob/master/platform/viewer/public/config/default.js -[html-templates]: https://github.com/OHIF/Viewers/tree/master/platform/viewer/public/html-templates -[config-files]: https://github.com/OHIF/Viewers/tree/master/platform/viewer/public/config - diff --git a/platform/docs/versioned_docs/version-3.0/deployment/_category_.json b/platform/docs/versioned_docs/version-3.0/deployment/_category_.json deleted file mode 100644 index 534be1dfb6d..00000000000 --- a/platform/docs/versioned_docs/version-3.0/deployment/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Deployment", - "position": 3 -} diff --git a/platform/docs/versioned_docs/version-3.0/deployment/build-for-production.md b/platform/docs/versioned_docs/version-3.0/deployment/build-for-production.md deleted file mode 100644 index b23463237a4..00000000000 --- a/platform/docs/versioned_docs/version-3.0/deployment/build-for-production.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Build for Production - -### Build Machine Requirements - -- [Node.js & NPM](https://nodejs.org/en/download/) -- [Yarn](https://yarnpkg.com/lang/en/docs/install/) -- [Git](https://www.atlassian.com/git/tutorials/install-git) - -### Getting the Code - -_With Git:_ - -```bash -# Clone the remote repository to your local machine -git clone https://github.com/OHIF/Viewers.git -``` - -More on: _[`git clone`](https://git-scm.com/docs/git-clone), -[`git checkout`](https://git-scm.com/docs/git-checkout)_ - -_From .zip:_ - -[OHIF/Viewers: master.zip](https://github.com/OHIF/Viewers/archive/master.zip) - -### Restore Dependencies & Build - -Open your terminal, and navigate to the directory containing the source files. -Next run these commands: - -```bash -# If you haven't already, enable yarn workspaces -yarn config set workspaces-experimental true - -# Restore dependencies -yarn install - -# Build source code for production -yarn run build -``` - -If everything worked as expected, you should have a new `dist/` directory in the -`platform/viewer/dist` folder. It should roughly resemble the following: - -```bash title="platform/viewer/dist/" -β”œβ”€β”€ app-config.js -β”œβ”€β”€ app.bundle.js -β”œβ”€β”€ app.css -β”œβ”€β”€ index.html -β”œβ”€β”€ manifest.json -β”œβ”€β”€ service-worker.js -└── ... -``` - -By default, the build output will connect to OHIF's publicly accessible PACS. If -this is your first time setting up the OHIF Viewer, it is recommended that you -test with these default settings. After testing, you can find instructions on -how to configure the project for your own imaging archive below. - -### Configuration - -The configuration for our viewer is in the `platform/viewer/public/config` -directory. Our build process knows which configuration file to use based on the -`APP_CONFIG` environment variable. By default, its value is -[`config/default.js`][default-config]. The majority of the viewer's features, -and registered extension's features, are configured using this file. - -The easiest way to apply your own configuration is to modify the `default.js` -file. For more advanced configuration options, check out our -[configuration essentials guide](../configuration/index.md). - -## Next Steps - -### Deploying Build Output - -_Drag-n-drop_ - -- [Netlify: Drop](./static-assets#netlify-drop) - -_Easy_ - -- [Surge.sh](./static-assets#surgesh) -- [GitHub Pages](./static-assets#github-pages) - -_Advanced_ - -- [AWS S3 + Cloudfront](./static-assets#aws-s3--cloudfront) -- [GCP + Cloudflare](./static-assets#gcp--cloudflare) -- [Azure](./static-assets#azure) - -### Testing Build Output Locally - -A quick way to test your build output locally is to spin up a small webserver. -You can do this by running the following commands in the `dist/` output -directory: - -```bash -# Install http-server as a globally available package -yarn global add http-server - -# Change the directory to the platform/viewer - -# Serve the files in our current directory -# Accessible at: `http://localhost:8080` -npx http-server ./dist -``` - -
- -
- -### Automating Builds and Deployments - -If you found setting up your environment and running all of these steps to be a -bit tedious, then you are in good company. Thankfully, there are a large number -of tools available to assist with automating tasks like building and deploying -web application. For a starting point, check out this repository's own use of: - -- [CircleCI][circleci]: [config.yaml][circleci-config] -- [Netlify][netlify]: [netlify.toml][netlify.toml] | - [build-deploy-preview.sh][build-deploy-preview.sh] - - -[circleci]: https://circleci.com/gh/OHIF/Viewers -[circleci-config]: https://github.com/OHIF/Viewers/blob/master/.circleci/config.yml -[netlify]: https://app.netlify.com/sites/ohif/deploys -[netlify.toml]: https://github.com/OHIF/Viewers/blob/master/netlify.toml -[build-deploy-preview.sh]: https://github.com/OHIF/Viewers/blob/master/.netlify/build-deploy-preview.sh - diff --git a/platform/docs/versioned_docs/version-3.0/deployment/google-cloud-healthcare.md b/platform/docs/versioned_docs/version-3.0/deployment/google-cloud-healthcare.md deleted file mode 100644 index 532bf4cc636..00000000000 --- a/platform/docs/versioned_docs/version-3.0/deployment/google-cloud-healthcare.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -sidebar_position: 6 ---- - -# Google Cloud Healthcare - -> Coming soon - We are working on bringing Google Cloud Healthcare to OHIF-v3 diff --git a/platform/docs/versioned_docs/version-3.0/deployment/index.md b/platform/docs/versioned_docs/version-3.0/deployment/index.md deleted file mode 100644 index 384aefc777d..00000000000 --- a/platform/docs/versioned_docs/version-3.0/deployment/index.md +++ /dev/null @@ -1,335 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Overview ---- - -# Deployment - -The OHIF Viewer can be embedded in other web applications via it's [packaged -script source][viewer-npm], or served up as a stand-alone PWA ([progressive web -application][pwa-url]) by building and hosting a collection of static assets. In -either case, you will need to configure your instance of the Viewer so that it -can connect to your data source (the database or PACS that provides the data -your Viewer will display). - -## Overview - -Our goal is to make deployment as simple and painless as possible; however, -there is an inherent amount of complexity in configuring and deploying web -applications. If you find yourself a little lost, please don't hesitate to -[reach out for help](/help) - -## Deployment Scenarios - -### Embedded Viewer (deprecated) - -`OHIF-v3` has deprecated deploying the viewer as an embedded viewer the number -of underlying libraries that run web workers are increasing for OHIF. An example -of these libraries is OHIF's 3D rendering functionality that is provided by -`vtk-js`. - -### Stand-alone Viewer - -Deploying the OHIF Viewer as a stand-alone web application provides many -benefits, but comes at the cost of time and complexity. Some benefits include: - -_Today:_ - -- Leverage [extensions](../platform/extensions/index.md) and - [modes](../platform/modes/index.md) to drop-in powerful new features -- Add routes and customize the viewer's workflow -- Finer control over styling and whitelabeling - -_In the future:_ - -- The ability to package the viewer for [App Store distribution][app-store] -- Leverage `service-workers` for offline support and speed benefits from caching - -#### Hosted Static Assets - -At the end of the day, a production OHIF Viewer instance is a collection of -HTML, CSS, JS, Font Files, and Images. We "build" those files from our -`source code` with configuration specific to our project. We then make those -files publicly accessible by hosting them on a Web Server. - -If you have not deployed a web application before, this may be a good time to -[reach out for help](/help), as these steps assume prior web development and -deployment experience. - -##### Part 1 - Build Production Assets - -"Building", or creating, the files you will need is the same regardless of the -web host you choose. You can find detailed instructions on how to configure and -build the OHIF Viewer in our -["Build for Production" guide](./build-for-production.md). - -##### Part 2 - Host Your App - -There are a lot of [benefits to hosting static assets][host-static-assets] over -dynamic content. You can find instructions on how to host your build's output -via one of these guides: - -_Drag-n-drop_ - -- [Netlify: Drop](./static-assets.md#netlify-drop) - -_Easy_ - -- [Surge.sh](./static-assets.md#surgesh) -- [GitHub Pages](./static-assets.md#github-pages) - -_Advanced_ - -- [AWS S3 + Cloudfront](./static-assets.md#aws-s3--cloudfront) -- [GCP + Cloudflare](./static-assets.md#gcp--cloudflare) -- [Azure](./static-assets.md#azure) - -## Data - -The OHIF Viewer is able to connect to any data source that implements the [DICOM -Web Standard][dicom-web-standard]. [DICOM Web][dicom-web] refers to RESTful -DICOM Services -- a recently standardized set of guidelines for exchanging -medical images and imaging metadata over the internet. Not all archives fully -support it yet, but it is gaining wider adoption. - -### Configure Connection - -If you have an existing archive and intend to host the OHIF Viewer at the same -domain name as your archive, then connecting the two is as simple as following -the steps layed out in our -[Configuration Essentials Guide](./../configuration/index.md). - -#### What if I don't have an imaging archive? - -We provide some guidance on configuring a local image archive in our -[Data Source Essentials](./../configuration/index.md#set-up-a-local-DICOM-server) -guide. Hosting an archive remotely is a little trickier. You can check out some -of our [advanced recipes](#recipes) for modeled setups that may work for you. - -#### What if I intend to host the OHIF Viewer at a different domain? - -There are two important steps to making sure this setup works: - -1. Your Image Archive needs to be exposed, in some way, to the open web. This - can be directly, or through a `reverse proxy`, but the Viewer needs _some - way_ to request its data. -2. \* Your Image Archive needs to have appropriate CORS (Cross-Origin Resource - Sharing) Headers - -> \* Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional -> HTTP headers to tell a browser to let a web application running at one origin -> (domain) have permission to access selected resources from a server at a -> different origin. - [MDN Web Docs: Web - Http - CORS][cors] - -Most image archives do not provide either of these features "out of the box". -It's common to use IIS, Nginx, or Apache to route incoming requests and append -appropriate headers. You can find an example of this setup in our -[Nginx + Image Archive Deployment Recipe](./nginx--image-archive.md). - -#### What if my archive doesn't support DicomWeb? - -It's possible to supply all Study data via JSON format, in the event you do not -have a DicomWeb endpoint. You can host all of the relevant files on any web -accessible server (Amazon S3, Azure Blob Storage, Local file server etc.) - -This JSON is supplied via the '?url=' query parameter. It should reference an -endpoint that returns **application/json** formatted text. - -If you do not have an API, you can simply return a text file containing the JSON -from any web server. - -You tell the OHIF viewer to use JSON by using the `dicomjson` datasource and -appending `'?url='` query to your mode's route: - -e.g. -`https://my-test-ohif-server/myMode/dicomjson?url=https://my-json-server/study-uid.json` - -The returned JSON object must contain a single root object with a 'studies' -array. - -You can read more about using different data sources for mode's routes -[here](../platform/modes/routes.md#route-path) - -_Sample JSON format:_ - -```json -{ - "studies": [ - { - "StudyInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.78", - "StudyDescription": "BRAIN SELLA", - "StudyDate": "20010108", - "StudyTime": "120022", - "PatientName": "MISTER^MR", - "PatientId": "832040", - "series": [ - { - "SeriesDescription": "SAG T-1", - "SeriesInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.121", - "SeriesNumber": 2, - "SeriesDate": "20010108", - "SeriesTime": "120318", - "Modality": "MR", - "instances": [ - { - "metadata": { - "Columns": 512, - "Rows": 512, - "InstanceNumber": 3, - "AcquisitionNumber": 0, - "PhotometricInterpretation": "MONOCHROME2", - "BitsAllocated": 16, - "BitsStored": 16, - "PixelRepresentation": 1, - "SamplesPerPixel": 1, - "PixelSpacing": [0.390625, 0.390625], - "HighBit": 15, - "ImageOrientationPatient": [0, 1, 0, 0, 0, -1], - "ImagePositionPatient": [11.6, -92.5, 98.099998], - "FrameOfReferenceUID": "1.2.840.113619.2.5.1762583153.223134.978956938.470", - "ImageType": ["ORIGINAL", "PRIMARY", "OTHER"], - "Modality": "MR", - "SOPInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.124", - "SeriesInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.121", - "StudyInstanceUID": "1.2.840.113619.2.5.1762583153.215519.978957063.78" - }, - "url": "dicomweb://s3.amazonaws.com/lury/MRStudy/1.2.840.113619.2.5.1762583153.215519.978957063.124.dcm" - } - ] - } - ] - } - ] -} -``` - -More info on this JSON format can be found here -[Issue #1500](https://github.com/OHIF/Viewers/issues/1500) - -**Implementation Notes:** - - - -1. For each instance url (dicom object) in the returned JSON, you must prefix - the `url` with `dicomjson:` in order for the cornerstone image loader to - retrieve it correctly. eg. `https://image-server/my-image.dcm` ---> - `dicomjson:https://image-server/my-image.dcm` -2. The JSON format above is compatible with >= v3.7.8 of the application in `V2` - version. Older versions of the viewer used a different JSON format. As of - 20/04/20 the public [https://viewer.ohif.org/] is a pre 3.0 version that does - not support this format yet. -3. The JSON format is case-sensitive. Please ensure you have matched casing with - the naturalised Dicom format referenced in - [Issue #1500](https://github.com/OHIF/Viewers/issues/1500). - -_CORS Issues (Cross-Origin Resource Sharing)_ - -If you host a JSON API or Images on a different domain from the app itself, -you will likely have CORS issues. This will also happen when testing from -Localhost and reaching out to remote servers. Even if the domain is the same, -different ports, subdomains or protocols (https vs http) will also cause CORS -errors. You will to need add a configuration on each server hosting these assets -to allow your App server origin. - -For example: - -Let's assume your application is hosted on `https://my-ohif-server.com`. - -Your JSON API is hosted on `https://my-json-api.aws.com` - -And your images are stored on Amazon S3 at `https://my-s3-bucket.aws.com` - -When you first start your application, browsing to -`https://my-ohif-server.com/myMode/dicomjson?url=https://my-json-api.aws.com/api/my-json-study-info.json`, -you will likely get a CORS error in the browser console as it tries to connect -to `https://my-json-api.aws.com`. - -Adding a setting on the JSON server to allow the CORS origin = -`https://my-ohif-server.com` should solve this. - -Next, you will likely get a similar CORS error, as the browser tries to go to -`https://my-s3-bucket.aws.com`. You will need to go to the S3 bucket -configuration, and add a CORS setting to allow origin = -`https://my-ohif-server.com`. - -Essentially, whenever the application connects to a remote resource, you will -need to add the applications url to the allowed CORS Origins on that resource. -Adding an origin similar to https://localhost:3000 will also allow for local -testing. - -### Securing Your Data - -Coming soon - - - -### Recipes - -We've included a few recipes for common deployment scenarios. There are many, -many possible configurations, so please don't feel limited to these setups. -Please feel free to suggest or contribute your own recipes. - -- [Build for Production](./build-for-production.md) -- [Static](./static-assets.md) -- [Nginx + Image Archive](./nginx--image-archive.md) -- [User Account Control](./user-account-control.md) - - - - -[viewer-npm]: https://www.npmjs.com/package/@ohif/viewer -[pwa-url]: https://developers.google.com/web/progressive-web-apps/ -[static-assets-url]: https://www.maxcdn.com/one/visual-glossary/static-content/ -[app-store]: https://medium.freecodecamp.org/i-built-a-pwa-and-published-it-in-3-app-stores-heres-what-i-learned-7cb3f56daf9b -[dicom-web-standard]: https://www.dicomstandard.org/dicomweb/ -[dicom-web]: https://en.wikipedia.org/wiki/DICOMweb -[host-static-assets]: https://www.netlify.com/blog/2016/05/18/9-reasons-your-site-should-be-static/ -[cors]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS -[code-flows]: https://medium.com/@darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660 -[code-sandbox]: https://codesandbox.io/s/viewer-script-tag-tprch - diff --git a/platform/docs/versioned_docs/version-3.0/deployment/nginx--image-archive.md b/platform/docs/versioned_docs/version-3.0/deployment/nginx--image-archive.md deleted file mode 100644 index 79f729d2fb5..00000000000 --- a/platform/docs/versioned_docs/version-3.0/deployment/nginx--image-archive.md +++ /dev/null @@ -1,273 +0,0 @@ ---- -sidebar_position: 4 ---- - -# Nginx + Image Archive - -> DISCLAIMER! We make no claims or guarantees of this approach's security. If in -> doubt, enlist the help of an expert and conduct proper audits. - -At a certain point, you may want others to have access to your instance of the -OHIF Viewer and its medical imaging data. This post covers one of many potential -setups that accomplish that. Please note, noticeably absent is user account -control. - -Do not use this recipe to host sensitive medical data on the open web. Depending -on your company's policies, this may be an appropriate setup on an internal -network when protected with a server's basic authentication. For a more robust -setup, check out our [user account control recipe](./user-account-control) -that builds on the lessons learned here. - -## Overview - -Our two biggest hurdles when hosting our image archive and web client are: - -- Risks related to exposing our PACS to the network -- Cross-Origin Resource Sharing (CORS) requests - -### Handling Web Requests - -We mitigate our first issue by allowing [Nginx][nginx] to handle incoming web -requests. Nginx is open source software for web serving, reverse proxying, -caching, and more. It's designed for maximum performance and stability -- -allowing us to more reliably serve content than Orthanc's built-in server can. - -More specifically, we accomplish this by using a -[`reverse proxy`](https://en.wikipedia.org/wiki/Reverse_proxy) to retrieve -resources from our image archive (Orthanc), and when accessing its web admin. - -> A reverse proxy is a type of proxy server that retrieves resources on behalf -> of a client from one or more servers. These resources are then returned to the -> client, appearing as if they originated from the proxy server itself. - -### CORS Issues - -Cross-Origin Resource Sharing (CORS) is a mechanism that uses HTTP headers to -tell a browser which web applications have permission to access selected -resources from a server at a different origin (domain, protocol, port). IE. By -default, a Web App located at `http://my-website.com` can't access resources -hosted at `http://not-my-website.com` - -We can solve this one of two ways: - -1. Have our Image Archive located at the same domain as our Web App -2. Add appropriate `Access-Control-Allow-*` HTTP headers - -**This solution uses the first approach.** - -You can read more about CORS in this Medium article: [Understanding -CORS][understanding-cors] - -### Diagram - -This setup allows us to create a setup similar to the one pictured below: - - -![nginX](../assets/img/nginx-image-archive.png) - - -- All web requests are routed through `nginx` on our `OpenResty` image -- `/pacs` is a reverse proxy for `orthanc`'s `DICOM Web` endpoints -- `/pacs-admin` is a reverse proxy for `orthanc`'s Web Admin -- All static resources for OHIF Viewer are served up by `nginx` when a matching - route for that resource is requested - -## Getting Started - -### Requirements - -- Docker - - [Docker for Mac](https://docs.docker.com/docker-for-mac/) - - [Docker for Windows](https://docs.docker.com/docker-for-windows/) - -_Not sure if you have `docker` installed already? Try running `docker --version` -in command prompt or terminal_ - -### Setup - -- Navigate to `viewer` folder inside `platform` -- then: `cd .recipes/OpenResty-Orthanc` -- run: `docker-compose up --build` -- Navigate to `127.0.0.1` for the viewer -- Navigate to `127.0.0.1/pacs-admin` for uploading studies - - -You can see the overview of the mentioned steps: - - - -
- -
- - - -### Troubleshooting - -_Exit code 137_ - -This means Docker ran out of memory. Open Docker Desktop, go to the `advanced` -tab, and increase the amount of Memory available. - -_Cannot create container for service X_ - -Use this one with caution: `docker system prune` - -_X is already running_ - -Stop running all containers: - -- Win: `docker ps -a -q | ForEach { docker stop $_ }` -- Linux: `docker stop $(docker ps -a -q)` - - -_Traceback (most recent call last):_ - _File "urllib3/connectionpool.py", line 670, in urlopen_ - _...._ - -Are you sure your docker is running? see explanation [here](https://github.com/docker/compose/issues/7896) - - -### Configuration - -After verifying that everything runs with default configuration values, you will -likely want to update: - -- The domain: `http://127.0.0.1` - -#### OHIF Viewer - -The OHIF Viewer's configuration is imported from a static `.js` file. The -configuration we use is set to a specific file when we build the viewer, and -determined by the env variable: `APP_CONFIG`. You can see where we set its value -in the `dockerfile` for this solution: - -`ENV APP_CONFIG=config/docker_openresty-orthanc.js` - -You can find the configuration we're using here: -`/public/config/docker_openresty-orthanc.js` - -To rebuild the `webapp` image created by our `dockerfile` after updating the -Viewer's configuration, you can run: - -- `docker-compose build` OR -- `docker-compose up --build` - -#### Other - -All other files are found in: `/docker/OpenResty-Orthanc/` - -| Service | Configuration | Docs | -| ----------------- | --------------------------------- | ------------------------------------------- | -| OHIF Viewer | [dockerfile][dockerfile] | You're reading them now! | -| OpenResty (Nginx) | [`/nginx.conf`][config-nginx] | [lua-resty-openidc][lua-resty-openidc-docs] | -| Orthanc | [`/orthanc.json`][config-orthanc] | [Here][orthanc-docs] | - -## Next Steps - -### Deploying to Production - -While these configuration and docker-compose files model an environment suitable -for production, they are not easy to deploy "as is". You can either: - -- Manually recreate this environment and deploy built application files **OR** -- Deploy to a cloud kubernetes provider like - [Digital Ocean](https://www.digitalocean.com/products/kubernetes/) **OR** - - [See a full list of cloud providers here](https://landscape.cncf.io/category=cloud&format=card-mode&grouping=category) -- Find and follow your preferred provider's guide on setting up - [swarms and stacks](https://docs.docker.com/get-started/) - -### Adding SSL - -Adding SSL registration and renewal for your domain with Let's Encrypt that -terminates at Nginx is an incredibly important step toward securing your data. -Here are some resources, specific to this setup, that may be helpful: - -- [lua-resty-auto-ssl](https://github.com/GUI/lua-resty-auto-ssl) -- [Let's Encrypt + Nginx](https://www.nginx.com/blog/using-free-ssltls-certificates-from-lets-encrypt-with-nginx/) - -While we terminate SSL at Nginx, it may be worth using self-signed certificates -for communication between services. - -- [SSL Termination for TCP Upstream Servers](https://docs.nginx.com/nginx/admin-guide/security-controls/terminating-ssl-tcp/) - -### Use PostgresSQL w/ Orthanc - -Orthanc can handle a large amount of data and requests, but if you find that -requests start to slow as you add more and more studies, you may want to -configure your Orthanc instance to use PostgresSQL. Instructions on how to do -that can be found in the -[`Orthanc Server Book`](http://book.orthanc-server.com/users/docker.html), under -"PostgreSQL and Orthanc inside Docker" - -### Improving This Guide - -Here are some improvements this guide would benefit from, and that we would be -more than happy to accept Pull Requests for: - -- SSL Support -- Complete configuration with `.env` file (or something similar) -- Any security issues -- One-click deploy to a cloud provider - -## Resources - -### Misc. Helpful Commands - -_Check if `nginx.conf` is valid:_ - -```bash -docker run --rm -t -a stdout --name my-openresty -v $PWD/config/:/usr/local/openresty/nginx/conf/:ro openresty/openresty:alpine-fat openresty -c /usr/local/openresty/nginx/conf/nginx.conf -t -``` - -_Interact w/ running container:_ - -`docker exec -it CONTAINER_NAME bash` - -_List running containers:_ - -`docker ps` - -### Referenced Articles - -For more documentation on the software we've chosen to use, you may find the -following resources helpful: - -- [Orthanc for Docker](http://book.orthanc-server.com/users/docker.html) -- [OpenResty Guide](http://www.staticshin.com/programming/definitely-an-open-resty-guide/) -- [Lua Ngx API](https://openresty-reference.readthedocs.io/en/latest/Lua_Nginx_API/) - -For a different take on this setup, check out the repositories our community -members put together: - -- [mjstealey/ohif-orthanc-dimse-docker](https://github.com/mjstealey/ohif-orthanc-dimse-docker) -- [trypag/ohif-orthanc-postgres-docker](https://github.com/trypag/ohif-orthanc-postgres-docker) - - - - - -[nginx]: https://www.nginx.com/resources/glossary/nginx/ -[understanding-cors]: https://medium.com/@baphemot/understanding-cors-18ad6b478e2b -[orthanc-docs]: http://book.orthanc-server.com/users/configuration.html#configuration -[lua-resty-openidc-docs]: https://github.com/zmartzone/lua-resty-openidc - -[dockerfile]: https://github.com/OHIF/Viewers/blob/master/platform/viewer/.recipes/OpenResty-Orthanc/dockerfile -[config-nginx]: https://github.com/OHIF/Viewers/blob/master/platform/viewer/.recipes/OpenResty-Orthanc/config/nginx.conf -[config-orthanc]: https://github.com/OHIF/Viewers/blob/master/platform/viewer/.recipes/OpenResty-Orthanc/config/orthanc.json - diff --git a/platform/docs/versioned_docs/version-3.0/deployment/static-assets.md b/platform/docs/versioned_docs/version-3.0/deployment/static-assets.md deleted file mode 100644 index 767ad692802..00000000000 --- a/platform/docs/versioned_docs/version-3.0/deployment/static-assets.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Deploy Static Assets - -> WARNING! All of these solutions stand-up a publicly accessible web viewer. Do -> not hook your hosted viewer up to a sensitive source of data without -> implementing authentication. - -There are a lot of options for deploying static assets. Some services, like -`netlify` and `surge.sh`, specialize in static websites. You'll notice that -deploying with them requires much less time and effort, but comes at the cost of -less product offerings. - -While not required, it can simplify things to host your Web Viewer alongside -your image archive. Services with more robust product offerings, like -`Google Cloud`, `Microsoft's Azure`, and `Amazon Web Services (AWS)`, are able -to accommodate this setup. - -_Drag-n-drop_ - -- [Netlify: Drop](#netlify-drop) - -_Easy_ - -- [Surge.sh](#surgesh) -- [GitHub Pages](#github-pages) - -_Advanced_ - -- [Deploy Static Assets](#deploy-static-assets) - - [Drag-n-drop](#drag-n-drop) - - [Netlify Drop](#netlify-drop) - - [Easy](#easy) - - [Surge.sh](#surgesh) - - [GitHub Pages](#github-pages) - - [Advanced](#advanced) - - [AWS S3 + Cloudfront](#aws-s3--cloudfront) - - [GCP + Cloudflare](#gcp--cloudflare) - - [Azure](#azure) - -## Drag-n-drop - -### Netlify Drop - - -
- -
- - -_GIF demonstrating deployment with Netlify Drop_ - -1. https://app.netlify.com/drop -2. Drag your `build/` folder on to the drop target -3. ... -4. _annnd you're done_ - -**Features:** - -- Custom domains & HTTPS -- Instant Git integration -- Continuous deployment -- Deploy previews -- Access to add-ons - -(Non-free tiers include identity, FaaS, Forms, etc.) - -Learn more about [Netlify on their website](https://www.netlify.com/) - -## Easy - -### Surge.sh - -> Static web publishing for Front-End Developers. Simple, single-command web -> publishing. Publish HTML, CSS, and JS for free, without leaving the command -> line. - -![surge.sh deploy example](../assets/img/surge-deploy.gif) - -_GIF demonstrating deployment with surge_ - -```shell -# Add surge command -yarn global add surge - -# In the build directory -surge -``` - -**Features:** - -- Free custom domain support -- Free SSL for surge.sh subdomains -- pushState support for single page apps -- Custom 404.html pages -- Barrier-free deployment through the CLI -- Easy integration into your Grunt toolchain -- Cross-origin resource support -- And more… - -Learn more about [surge.sh on their website](https://surge.sh/) - -### GitHub Pages - -> WARNING! While great for project sites and light use, it is not advised to use -> GitHub Pages for production workloads. Please consider using a different -> service for mission critical applications. - -> Websites for you and your projects. Hosted directly from your GitHub -> repository. Just edit, push, and your changes are live. - -This deployment strategy makes more sense if you intend to maintain your project in -a GitHub repository. It allows you to specify a `branch` or `folder` as the -target for a GitHub Page's website. As you push code changes, the hosted content -updates to reflect those changes. - -1. Head over to GitHub.com and create a new repository, or go to an existing - one. Click on the Settings tab. -2. Scroll down to the GitHub Pages section. Choose the `branch` or `folder` you - would like as the "root" of your website. -3. Fire up a browser and go to `http://username.github.io/repository` - -Configuring Your Site: - -- [Setting up a custom domain](https://help.github.com/en/articles/using-a-custom-domain-with-github-pages) -- [Setting up SSL](https://help.github.com/en/articles/securing-your-github-pages-site-with-https) - -Learn more about [GitHub Pages on its website](https://pages.github.com/) - -## Advanced - -All of these options, while using providers with more service offerings, -demonstrate how to host the viewer with their respective file storage and CDN -offerings. While you can serve your static assets this way, if you're going -through the trouble of using AWS/GCP/Azure, it's more likely you're doing so to -avoid using a proxy or to simplify authentication. - -If that is the case, check out some of our more advanced `docker` deployments -that target these providers from the left-hand sidepanel. - -These guides can be a bit longer and an update more frequently. To provide -accurate documentation, we will link to each provider's own recommended steps: - -### AWS S3 + Cloudfront - -- [Host a Static Website](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html) -- [Speed Up Your Website with Cloudfront](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-cloudfront-walkthrough.html) - -### GCP + Cloudflare - -- [Things to Know Before Getting Started](https://code.luasoftware.com/tutorials/google-cloud-storage/things-to-know-before-hosting-static-website-on-google-cloud-storage/) -- [Hosting a Static Website on GCP](https://cloud.google.com/storage/docs/hosting-static-website) - -### Azure - -- [Host a Static Website](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website) -- [Add SSL Support](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-https-custom-domain-cdn) -- [Configure a Custom Domain](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-custom-domain-name) diff --git a/platform/docs/versioned_docs/version-3.0/deployment/user-account-control.md b/platform/docs/versioned_docs/version-3.0/deployment/user-account-control.md deleted file mode 100644 index e411cc7d535..00000000000 --- a/platform/docs/versioned_docs/version-3.0/deployment/user-account-control.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -sidebar_position: 5 ---- - -# User Account Control - -> Coming soon - We are working on bringing the User Account Control to OHIF-v3 diff --git a/platform/docs/versioned_docs/version-3.0/development/_category_.json b/platform/docs/versioned_docs/version-3.0/development/_category_.json deleted file mode 100644 index 8627cac4920..00000000000 --- a/platform/docs/versioned_docs/version-3.0/development/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Development", - "position": 5 -} diff --git a/platform/docs/versioned_docs/version-3.0/development/architecture.md b/platform/docs/versioned_docs/version-3.0/development/architecture.md deleted file mode 100644 index 4bcebb0175e..00000000000 --- a/platform/docs/versioned_docs/version-3.0/development/architecture.md +++ /dev/null @@ -1,203 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: Architecture ---- - -# Architecture - -In order to achieve a platform that can support various workflows and be -extensible for the foreseeable future we went through extensive planning of -possible use cases and decided to significantly change and improve the -architecture. - -Below, we aim to demystify that complexity by providing insight into how -`OHIF Platform` is architected, and the role each of its dependent libraries -plays. - -## Overview - -The [OHIF Medical Image Viewing Platform][viewers-project] is maintained as a -[`monorepo`][monorepo]. This means that this repository, instead of containing a -single project, contains many projects. If you explore our project structure, -you'll see the following: - -```bash -β”‚ -β”œβ”€β”€ extensions -β”‚ β”œβ”€β”€ _example # Skeleton of example extension -β”‚ β”œβ”€β”€ default # default functionalities -β”‚ β”œβ”€β”€ cornerstone # 2D images w/ Cornerstone.js -β”‚ β”œβ”€β”€ measurement-tracking # measurement tracking -β”‚ β”œβ”€β”€ dicom-sr # Structured reports -β”‚ └── dicom-pdf # View DICOM wrapped PDFs in viewport -β”‚ -β”œβ”€β”€ modes -β”‚ └── longitudinal # longitudinal measurement tracking mode -β”‚ -β”œβ”€β”€ platform -β”‚ β”œβ”€β”€ core # Business Logic -β”‚ β”œβ”€β”€ i18n # Internationalization Support -β”‚ β”œβ”€β”€ ui # React component library -β”‚ └── viewer # Connects platform and extension projects -β”‚ -β”œβ”€β”€ ... # misc. shared configuration -β”œβ”€β”€ lerna.json # MonoRepo (Lerna) settings -β”œβ”€β”€ package.json # Shared devDependencies and commands -└── README.md -``` - -OHIF v3 is composed of the following components, described in detail in further -sections: - -- `@ohif/viewer`: The core framework that controls extension registration, mode - composition and routing. -- `@ohif/core`: A library of useful and reusable medical imaging functionality - for the web. -- `@ohif/ui`: A library of reusable components to build OHIF-styled applications - with. -- `Extensions`: A set of building blocks for building applications. The OHIF org - maintains a few core libraries. -- `Modes`: Configuration objects that tell @ohif/viewer how to compose - extensions to build applications on different routes of the platform. - -## Extensions - -The `extensions` directory contains many packages that provide essential -functionalities such as rendering, study/series browsers, measurement tracking -that modes can consume to enable a certain workflow. Extensions have had their -behavior changed in `OHIF-v3` and their api is expanded. In summary: - -> In `OHIF-v3`, extensions no longer automatically hook themselves to the app. -> Now, registering an extension makes its component available to `modes` that -> wish to use them. Basically, extensions in `OHIF-v3` are **building blocks** -> for building applications. - -OHIF team maintains several high value and commonly used functionalities in its -own extensions. For a list of extensions maintained by OHIF, -[check out this helpful table](../platform/extensions/index.md#maintained-extensions). -As an example `default` extension provides a default viewer layout, a -study/series browser and a datasource that maps to a DICOMWeb compliant backend. - -[Click here to read more about extensions!](../platform/extensions/index.md) - -## Modes - -The `modes` directory contains workflows that can be registered with OHIF within -certain `routes`. The mode will get used once the user opens the viewer on the -registered route. - -OHIF extensions were designed to provide certain core functionalities for -building your viewer. However, often in medical imaging we face a specific use -case in which we are using some core functionalities, adding our specific UI, -and use it in our workflows. Previously, to achieve this you had to create an -extension to add have such feature. `OHIF-v3` introduces `Modes` to enable -building such workflows by re-using the core functionalities from the -extensions. - -Some common workflows may include: - -- Measurement tracking for lesions -- Segmentation of brain abnormalities -- AI probe mode for detecting prostate cancer - -In the mentioned modes above, they will share the same core rendering module -that the `default` extension provides. However, segmentation mode will require -segmentation tools which is not needed for the other two. As you can see, modes -are a layer on top of extensions, that you can configure in order to achieve -certain workflows. - -To summarize the difference between extensions and modes in `OHIF-v3` and -extensions in `OHIF-v2` - -> - `Modes` are configuration objects that tell _@ohif/viewer_ how to compose -> extensions to build applications on different routes of the platform. -> - In v2 extensions are β€œplugins” that add functionality to a core viewer. -> - In v3 extensions are building blocks that a mode uses to build an entire -> viewer layout. - -[Click here to read more about modes!](../platform/modes/index.md) - -## Platform - -### `@ohif/viewer` - -This library is the core library which consumes modes and extensions and builds -an application. Extensions can be passed in as app configuration and will be -consumed and initialized at the appropriate time by the application. Upon -initialization the viewer will consume extensions and modes and build up the -route desired, these can then be accessed via the study list, or directly via -url parameters. - -Upon release modes will also be plugged into the app via configuration, but this -is still an area which is under development/discussion, and they are currently -pulled from the window in beta. - -Future ideas for this framework involve only adding modes and fetching the -required extension versions at either runtime or build time, but this decision -is still up for discussion. - -### `@ohif/core` - -OHIF core is a carefully maintained and tested set of web-based medical imaging -functions and classes. This library includes managers and services used from -within the viewer app. - -OHIF core is largely similar to the @ohif/core library in v2, however a lot of -logic has been moved to extensions: however all logic about DICOMWeb and other -data fetching mechanisms have been pulled out, as these now live in extensions, -described later. - -### `@ohif/ui` - -Firstly, a large time-consumer/barrier for entry we discovered was building new -UI in a timely manner that fit OHIF’s theme. For this reason we have built a new -UI component library which contains all the components one needs to build their -own viewer. - -These components are presentational only, so you can reuse them with whatever -logic you desire. As the components are presentational, you may swap out -@ohif/ui for a custom UI library with conforming API if you wish to white label -the viewer. The UI library is here to make development easier and quicker, but -it is not mandatory for extension components to use. - -[Check out our component library!](https://react.ohif.org/) - -## Overview of the architecture - -OHIF-v3 architecture can be seen in the following figure. We will explore each -piece in more detail. - -![mode-archs](../assets/img/mode-archs.png) - -## Common Questions - -> Can I create my own Viewer using Vue.js or Angular.js? - -You can, but you will not be able to leverage as much of the existing code and -components. `@ohif/core` could still be used for business logic, and to provide -a model for extensions. `@ohif/ui` would then become a guide for the components -you would need to recreate. - -> When I want to implement a functionality, should it be in the mode or in an -> extension? - -This is a great question. Modes are designed to consume extensions, so you -should implement your functionality in one of the modules of your new extension, -and let the mode consume it. This way, in the future, if you needed another mode -that utilizes the same functionality, you can easily hook the extension to the -new mode as well. - - - - -[monorepo]: https://github.com/OHIF/Viewers/issues/768 -[viewers-project]: https://github.com/OHIF/Viewers -[viewer-npm]: https://www.npmjs.com/package/@ohif/viewer -[pwa]: https://developers.google.com/web/progressive-web-apps/ -[configuration]: ../configuration/index.md -[extensions]: ../platform/extensions/index.md -[core-github]: https://github.com/OHIF/viewers/platform/core -[ui-github]: https://github.com/OHIF/Viewers/tree/master/platform/ui - diff --git a/platform/docs/versioned_docs/version-3.0/development/continous-integration.md b/platform/docs/versioned_docs/version-3.0/development/continous-integration.md deleted file mode 100644 index 3c3124af83b..00000000000 --- a/platform/docs/versioned_docs/version-3.0/development/continous-integration.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -sidebar_position: 7 -sidebar_label: Continous Integration ---- - -# Continous Integration (CI) - -This repository uses `CircleCI` and `Netlify` for continous integration. - -## Deploy Previews - -[Netlify Deploy previews][deploy-previews] are generated for every pull request. -They allow pull request authors and reviewers to "Preview" the OHIF Viewer as if -the changes had been merged. - -Deploy previews can be configured by modifying the `netlify.toml` file in the -root of the repository. Some additional scripts/assets for netlify are included -in the root `.netlify` directory. - -## Workflows - -[CircleCI Workflows][circleci-workflows] are a set of rules for defining a -collection of jobs and their run order. They are self-documenting and their -configuration can be found in our CircleCI configuration file: -`.circleci/config.yml`. - -### Workflow: PR_CHECKS - -The PR_CHECKS workflow (Pull Request Checks) runs our automated unit and -end-to-end tests for every code check-in. These tests must all pass before code -can be merged to our `master` branch. - -![PR_CHECKS](../assets/img/WORKFLOW_PR_CHECKS.png) - -### Workflow: PR_OPTIONAL_DOCKER_PUBLISH - -The PR_OPTIONAL_DOCKER_PUBLISH workflow allows for "manual approval" to publish -the pull request as a tagged docker image. This is helpful when changes need to -be tested with the Google Adapter before merging to `master`. - -![PR_Workflow](../assets/img/WORKFLOW_PR_OPTIONAL_DOCKER_PUBLISH.png) - -> NOTE: This workflow will fail unless it's for a branch on our `upstream` -> repository. If you need this functionality, but the branch is from a fork, -> merge the changes to a short-lived `feature/` branch on `upstream` - -### Workflow: DEPLOY - -The DEPLOY workflow deploys the OHIF Viewer when changes are merged to master. -It uses the Netlify CLI to deploy assets created as part of the repository's PWA -Build process (`yarn run build`). The workflow allows for "Manual Approval" to -promote the build to `STAGING` and `PRODUCTION` environments. - -![WORKFLOW_DEPLOY](../assets/img/WORKFLOW_DEPLOY.png) - -| Environment | Description | URL | -| ----------- | ---------------------------------------------------------------------------------- | --------------------------------------------- | -| Development | Always reflects latest changes on `master` branch. | [Netlify][netlify-dev] / [OHIF][ohif-dev] | -| Staging | For manual testing before promotion to prod. Keeps development workflow unblocked. | [Netlify][netlify-stage] / [OHIF][ohif-stage] | -| Production | Stable, tested, updated less frequently. | [Netlify][netlify-prod] / [OHIF][ohif-prod] | - -### Workflow: RELEASE - -The RELEASE workflow publishes our `npm` packages, updated documentation, and -`docker` image when changes are merged to master. `Lerna` and "Semantic Commit -Syntax" are used to independently version and publish the many packages in our -monorepository. If a new version is cut/released, a Docker image is created. -Documentation is generated with `gitbook` and pushed to our `gh-pages` branch. -GitHub hosts the `gh-pages` branch with GitHub Pages. - -- Platform Packages: https://github.com/ohif/viewers/#platform -- Extension Packages: https://github.com/ohif/viewers/#extensions -- Documentation: https://docs.ohif.org/ - -![WORKFLOW_RELEASE](../assets/img/WORKFLOW_RELEASE.png) - - - - -[deploy-previews]: https://www.netlify.com/blog/2016/07/20/introducing-deploy-previews-in-netlify/ -[circleci-workflows]: https://circleci.com/docs/2.0/workflows/ -[netlify-dev]: https://ohif-dev.netlify.com -[netlify-stage]: https://ohif-stage.netlify.com -[netlify-prod]: https://ohif-prod.netlify.com -[ohif-dev]: https://viewer-dev.ohif.org -[ohif-stage]: https://viewer-stage.ohif.org -[ohif-prod]: https://viewer-prod.ohif.org - diff --git a/platform/docs/versioned_docs/version-3.0/development/contributing.md b/platform/docs/versioned_docs/version-3.0/development/contributing.md deleted file mode 100644 index 763be20dd08..00000000000 --- a/platform/docs/versioned_docs/version-3.0/development/contributing.md +++ /dev/null @@ -1,152 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: Contributing ---- - -# Contributing - -## How can I help? - -Fork the repository, make your change and submit a pull request. If you would -like to discuss the changes you intend to make to clarify where or how they -should be implemented, please don't hesitate to create a new issue. At a -minimum, you may want to read the following documentation: - -- [Getting Started](/development/getting-started.md) -- [Architecture](./architecture.md) - -Pull requests that are: - -- Small -- [Well tested](./testing.md) -- Decoupled - -Are much more likely to get reviewed and merged in a timely manner. - -## When changes impact multiple repositories - -While this can be tricky, we've tried to reduce how often this situation crops -up this with our [recent switch to a monorepo][monorepo]. Our maintained -extensions, ui components, internationalization library, and business logic can -all be developed by simply running `yarn run dev` from the repository root. - -Testing the viewer with locally developed, unpublished package changes from a -package outside of the monorepo is most common with extension development. Let's -demonstrate how to accomplish this with two commonly forked extension -dependencies: - -### `cornerstone-tools` - -On your local file system: - -```bash title="/my-projects/" -β”œβ”€β”€ cornerstonejs/cornerstone-tools -└── ohif/viewers -``` - -- Open a terminal/shell -- Navigate to `cornerstonejs/cornerstone-tools` - - `yarn install` - - [`yarn link`](https://yarnpkg.com/en/docs/cli/link) - - `yarn run dev` - -* Open a new terminal/shell -* Navigate to `ohif/viewers` (the root of ohif project) - - `yarn install` - - [`yarn link cornerstone-tools`](https://yarnpkg.com/en/docs/cli/link) - - `yarn run dev` - -As you make changed to `cornerstone-tools`, and it's output is rebuilt, you -should see the following behavior: - -![tools](..//assets/img/cornerstone-tools-link.gif) - -If you wish to stop using your local package, run the following commands in the -`ohif/viewers` repository root: - -- `yarn unlink cornerstone-tools` -- `yarn install --force` - - - -#### Other linkage notes - -We're still working out some of the kinks with local package development as -there are a lot of factors that can influence the behavior of our development -server and bundler. If you encounter issues not addressed here, please don't -hesitate to reach out on GitHub. - -Sometimes you might encounter a situation where the linking doesn't work as -expected. This might happen when there are multiple linked packages with the -same name. You can [remove][unlink] the linked packages inside yarn and try -again. - -## Any guidance on submitting changes? - -While we do appreciate code contributions, triaging and integrating contributed -code changes can be very time consuming. Please consider the following tips when -working on your pull requests: - -- Functionality is appropriate for the repository. Consider creating a GitHub - issue to discuss your suggested changes. -- The scope of the pull request is not too large. Please consider separate pull - requests for each feature as big pull requests are very time consuming to - understand. - -We will provide feedback on your pull requests as soon as possible. Following -the tips above will help ensure your changes are reviewed. - - - - - - -[example-url]: https://deploy-preview-237--ohif.netlify.com/viewer/?url=https://s3.eu-central-1.amazonaws.com/ohif-viewer/sampleDICOM.json -[pr-237]: https://github.com/OHIF/Viewers/pull/237 -[monorepo]: https://github.com/OHIF/Viewers/issues/768 -[unlink]: https://stackoverflow.com/questions/58459698/is-there-a-command-to-unlink-all-yarn-packages-yarn-unlink-all - diff --git a/platform/docs/versioned_docs/version-3.0/development/getting-started.md b/platform/docs/versioned_docs/version-3.0/development/getting-started.md deleted file mode 100644 index b9b3bc5d51a..00000000000 --- a/platform/docs/versioned_docs/version-3.0/development/getting-started.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Getting Started ---- - -# Getting Started - -## Setup - -### Fork & Clone - -If you intend to contribute back changes, or if you would like to pull updates -we make to the OHIF Viewer, then follow these steps: - -- [Fork][fork-a-repo] the [OHIF/Viewers][ohif-viewers-repo] repository -- [Create a local clone][clone-a-repo] of your fork - - `git clone https://github.com/YOUR-USERNAME/Viewers` -- Add OHIF/Viewers as a [remote repository][add-remote-repo] labeled `upstream` - - Navigate to the cloned project's directory - - `git remote add upstream https://github.com/OHIF/Viewers.git` - -With this setup, you can now [sync your fork][sync-changes] to keep it -up-to-date with the upstream (original) repository. This is called a "Triangular -Workflow" and is common for Open Source projects. The GitHub blog has a [good -graphic that illustrates this setup][triangular-workflow]. - -### Private - -Alternatively, if you intend to use the OHIF Viewer as a starting point, and you -aren't as concerned with syncing updates, then follow these steps: - -1. Navigate to the [OHIF/Viewers][ohif-viewers] repository -2. Click `Clone or download`, and then `Download ZIP` -3. Use the contents of the `.zip` file as a starting point for your viewer - -> NOTE: It is still possible to sync changes using this approach. However, -> submitting pull requests for fixes and features are best done with the -> separate, forked repository setup described in "Fork & Clone" - -## Developing - -### Requirements - -- [Node.js & NPM](https://nodejs.org/en/) -- [Yarn](https://yarnpkg.com/en/) -- Yarn workspaces should be enabled: - - `yarn config set workspaces-experimental true` - -### Kick the tires - -Navigate to the root of the project's directory in your terminal and run the -following commands: - -```bash -# Switch to the v3 branch -git switch v3-stable - -# Restore dependencies -yarn install - -# Start local development server -yarn run dev -``` - -You should see the following output: - -```bash -@ohif/viewer: i ο½’wdsο½£: Project is running at http://localhost:3000/ -@ohif/viewer: i ο½’wdsο½£: webpack output is served from / -@ohif/viewer: i ο½’wdsο½£: Content not from webpack is served from D:\code\ohif\Viewers\platform\viewer -@ohif/viewer: i ο½’wdsο½£: 404s will fallback to /index.html - -# And a list of all generated files -``` - -### πŸŽ‰ Celebrate πŸŽ‰ - -
- -
- -### Building for Production - -> More comprehensive guides for building and publishing can be found in our -> [deployment docs](./../deployment/index.md) - -```bash -# Build static assets to host a PWA -yarn run build -``` - -## Troubleshooting - -- If you receive a _"No Studies Found"_ message and do not see your studies, try - changing the Study Date filters to a wider range. -- If you see a 'Loading' message which never resolves, check your browser's - JavaScript console inside the Developer Tools to identify any errors. - - - - -[fork-a-repo]: https://help.github.com/en/articles/fork-a-repo -[clone-a-repo]: https://help.github.com/en/articles/fork-a-repo#step-2-create-a-local-clone-of-your-fork -[add-remote-repo]: https://help.github.com/en/articles/fork-a-repo#step-3-configure-git-to-sync-your-fork-with-the-original-spoon-knife-repository -[sync-changes]: https://help.github.com/en/articles/syncing-a-fork -[triangular-workflow]: https://github.blog/2015-07-29-git-2-5-including-multiple-worktrees-and-triangular-workflows/#improved-support-for-triangular-workflows -[ohif-viewers-repo]: https://github.com/OHIF/Viewers -[ohif-viewers]: https://github.com/OHIF/Viewers - diff --git a/platform/docs/versioned_docs/version-3.0/development/ohif-cli.md b/platform/docs/versioned_docs/version-3.0/development/ohif-cli.md deleted file mode 100644 index cf8af80f581..00000000000 --- a/platform/docs/versioned_docs/version-3.0/development/ohif-cli.md +++ /dev/null @@ -1,291 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: OHIF CLI ---- - -# OHIF Command Line Interface - -OHIF-v3 architecture has been re-designed to enable building applications that -are easily extensible to various use cases (Modes) that behind the scene would -utilize desired functionalities (Extensions) to reach the goal of the use case. -Now, the question is _how to create/remove/install/uninstall an extension and/or -mode?_ - -You can use the `cli` script that comes with the OHIF monorepo to achieve these -goals. - -:::note Info -In the long-term, we envision our `cli` tool to be a separate installable -package that you can invoke anywhere on your local system to achieve the same -goals. In the meantime, `cli` will remain as part of the OHIF monorepo and needs -to be invoked using the `yarn` command. -::: - - -## CLI Installation - -You don't need to install the `cli` currently. You can use `yarn` to invoke its -commands. - -## Commands - -:::note Important -All commands should run from the root of the monorepo. -::: - - -There are various commands that can be used to interact with the OHIF-v3 CLI. If -you run the following command, you will see a list of available commands. - -``` -yarn run cli --help -``` - -which will output - -``` -OHIF CLI - -Options: - -V, --version output the version number - -h, --help display help for command - -Commands: - create-extension Create a new template extension - create-mode Create a new template Mode - add-extension [version] Adds an ohif extension - remove-extension removes an ohif extension - add-mode [version] Removes an ohif mode - remove-mode Removes an ohif mode - link-extension Links a local OHIF extension to the Viewer to be used for development - unlink-extension Unlinks a local OHIF extension from the Viewer - link-mode Links a local OHIF mode to the Viewer to be used for development - unlink-mode Unlinks a local OHIF mode from the Viewer - list List Added Extensions and Modes - search [options] Search NPM for the list of Modes and Extensions - help [command] display help for command -``` - -As seen there are commands for you such as: `create-extension`, `create-mode`, -`add-extension`, `remove-extension`, `add-mode`, `remove-mode`, -`link-extension`, `unlink-extension`, `link-mode`, `unlink-mode`, `list`, -`search`, and `help`. Here we will go through each of the commands and describe -them. - -### create-mode - -If you need to create a new mode, you can use the `create-mode` command. This -command will create a new mode template in the directory that you specify. -The command will ask you couple of information/questions in order -to properly create the mode metadata in the `package.json` file. - -```bash -yarn run cli create-mode -``` - -
- -![image](../assets/img/create-mode.png) - - -
- -Note 1: Some questions have a default answer, which is indicated inside the -parenthesis. If you don't want to answer the question, just hit enter. It will -use the default answer. - -Note 2: As you see in the questions, you can initiate a git repository for the -new mode right away by answering `Y` (default) to the question. - -Note 3: Finally, as indicated by the green lines at the end, `create-mode` command only -create the mode template. You will need to link the mode to the Viewer in order -to use it. See the [`link-mode`](#link-mode) command. - -If we take a look at the directory that we created, we will see the following -files: - -
- -![image](../assets/img/mode-template.png) - -
- - -### create-extension - -Similar to the `create-extension` command, you can use the `create-extension` -command to create a new extension template. This command will create a new -extension template in the directory that you specify the path. - -```bash -yarn run cli create-extension -``` - - -Note: again similar to the `create-extension` command, you need to manually link -the extension to the Viewer in order to use it. See the -[`link-mode`](#link-mode) command. - - -### link-extension - -`link-extension` command will link a local OHIF extension to the Viewer. This -command will utilize `yarn link` to achieve so. - -```bash -yarn run cli link-extension -``` - -### unlink-extension - -There might be situations where you want to unlink an extension from the Viewer -after some developments. `unlink-extension` command will do so. - -```bash -ohif-cli unlink-extension -``` - - - -### link-mode - -Similar to the `link-extension` command, `link-mode` command will link a local -OHIF mode to the Viewer. - -```bash -yarn run cli link-mode -``` - -### unlink-mode - -Similar to the `unlink-extension` command, `unlink-mode` command will unlink a -local OHIF mode from the Viewer. - -```bash -ohif-cli unlink-mode -``` - -### add-mode - -OHIF is a modular viewer. This means that you can install (add) different modes -to the viewer if they are published online . `add-mode` command will add a new mode to -the viewer. It will look for the mode in the NPM registry and installs it. This -command will also add the extension dependencies that the mode relies on to the -Viewer (if specified in the peerDependencies section of the package.json). - -:::note Important -`cli` will validate the npm package before adding it to the Viewer. An OHIF mode -should have `ohif-mode` as one of its keywords. -::: - -Note: If you don't specify the version, the latest version will be used. - -```bash -yarn run cli add-mode [version] -``` - -For instance `@ohif-test/mode-clock` is an example OHIF mode that we have -published to NPM. This mode basically has a panel that shows the clock :) - -We can add this mode to the Viewer by running the following command: - -```bash -yarn run cli add-mode @ohif-test/mode-clock -``` - -After installation, the Viewer has a new mode! - - -![image](../assets/img/add-mode.png) - - -Note: If the mode has an extension peerDependency (in this case @ohif-test/extension-clock), -`cli` will automatically add the extension to the Viewer too. - -The result - -![image](../assets/img/clock-mode.png) -![image](../assets/img/clock-mode1.png) - -### add-extension - -This command will add an OHIF extension to the Viewer. It will look for the -extension in the NPM registry and install it. - -```bash -yarn run cli add-extension [version] -``` - - -### remove-mode - -This command will remove the mode from the Viewer and also remove the extension -dependencies that the mode relies on from the Viewer. - -```bash -yarn run cli remove-mode -``` - - -### remove-extension - -Similar to the `remove-mode` command, this command will remove the extension -from the Viewer. - -```bash -yarn run cli remove-extension -``` - -### list - -`list` command will list all the installed extensions and modes in -the Viewer. It uses the `PluginConfig.json` file to list the installed -extensions and modes. - -```bash -yarn run cli list -``` - -an output would look like this: - -
- -![image](../assets/img/ohif-cli-list.png) - -
- -### search - -Using `search` command, you can search for OHIF extensions and modes -in the NPM registry. This tool can accept a `--verbose` flag to show more -information about the results. - -```bash -yarn run cli search [--verbose] -``` - -
- -![image](../assets/img/cli-search-no-verbose.png) - -
- -with the verbose flag `ohif-cli search --verbose` you will achieve the following -output: - -
- -![image](../assets/img/cli-search-with-verbose.png) - -
- - -## PluginConfig.json - -To make all the above commands work, we have created a new file called `PluginConfig.json` which contains the -information needed to run the commands. You **don't need to (and should not)** -edit/update/modify this file as it is automatically generated by the CLI. You -can take a look at what this file contains by going to -`platform/viewer/PluginConfig.json` in your project's root directory. In short, -this file tracks and stores all the extensions/modes and the their version that -are currently being used by the viewer. diff --git a/platform/docs/versioned_docs/version-3.0/development/our-process.md b/platform/docs/versioned_docs/version-3.0/development/our-process.md deleted file mode 100644 index d8b8ed86217..00000000000 --- a/platform/docs/versioned_docs/version-3.0/development/our-process.md +++ /dev/null @@ -1,156 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: Issue & PR Triage Process ---- - -# Our Process - -Our process is a living, breathing thing. We strive to have regular -[retrospectives][retrospective] that help us shape and adapt our process to our -team's current needs. This document attempts to capture the broad strokes of -that process in an effort to: - -- Strengthen community member involvement and understanding -- Welcome feedback and helpful suggestions - -## Issue Triage - -[GitHub issues][gh-issues] are the best way to provide feedback, ask questions, -and suggest changes to the OHIF Viewer's core team. Community issues generally -fall into one of three categories, and are marked with a `triage` label when -created. - -| Issue Template Name | Description | -| ---------------------- | ---------------------------------------------------------------------------------------- | -| Community: Report πŸ› | Describe a new issue; Provide steps to reproduce; Expected versus actual result? | -| Community: Request βœ‹ | Describe a proposed new feature. Why should it be implemented? What is the impact/value? | -| Community: Question ❓ | Seek clarification or assistance relevant to the repository. | - -_table 1. issue template names and descriptions_ - -Issues that require `triage` are akin to support tickets. As this is often our -first contact with would-be adopters and contributors, it's important that we -strive for timely responses and satisfactory resolutions. We attempt to -accomplish this by: - -1. Responding to issue requiring `triage` at least once a week -2. Create new "official issues" from "community issues" -3. Provide clear guidance and next steps (when applicable) -4. Regularly clean up old (stale) issues - -> πŸ–‹ Less obviously, patterns in the issues being reported can highlight areas -> that need improvement. For example, users often have difficulty navigating -> CORS issues when deploying the OHIF Viewer -- how do we best reduce our ticket -> volume for this issue? - -### Backlogged Issues - -Community issues serve as vehicles of discussion that lead us to "backlogged -issues". Backlogged issues are the distilled and actionable information -extracted from community issues. They contain the scope and requirements -necessary for hand-off to a core-team (or community) contributor ^\_^ - -| Category | Description | Labels | -| -------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | -| Bugs | An issue with steps that produce a bug (an unexpected result). | [Bug: Verified πŸ›][label-bug] | -| Stories | A feature/enhancement with a clear benefit, boundaries, and requirements. | [Story πŸ™Œ][label-story] | -| Tasks | Changes that improve [UX], [DX], or test coverage; but don't impact application behavior | [Task: CI/Tooling πŸ€–][label-tooling], [Task: Docs πŸ“–][label-docs], [Task: Refactor πŸ› ][label-refactor], [Task: Tests πŸ”¬][label-tests] | - -_table 2. backlogged issue types ([full list of labels][gh-labels])_ - -## Issue Curation (["backlog grooming"][groom-backlog]) - -If a [GitHub issue][gh-issues] has a `bug`, `story`, or `task` label; it's on -our backlog. If an issue is on our backlog, it means we are, at the very least, -committed to reviewing any community drafted Pull Requests to complete the -issue. If you're interested in seeing an issue completed but don't know where to -start, please don't hesitate to leave a comment! - -While we don't yet have a long-term or quarterly road map, we do regularly add -items to our ["Active Development" GitHub Project Board][gh-board]. Items on -this project board are either in active development by Core Team members, or -queued up for development as in-progress items are completed. - -> πŸ–‹ Want to contribute but not sure where to start? Check out [Up for -> grabs][label-grabs] issues and our [Contributing -> documentation][contributing-docs] - -## Contributions (Pull Requests) - -Incoming Pull Requests (PRs) are triaged using the following labels. Code review -is performed on all PRs where the bug fix or added functionality is deemed -appropriate: - -| Labels | Description | -| ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -| **Classification** | | -| [PR: Bug Fix][label-bug] | Filed to address a Bug. | -| [PR: Draft][draft] | Filed to gather early feedback from the core team, but which is not intended for merging in the short term. | -| **Review Workflow** | | -| [PR: Awaiting Response πŸ’¬][awaiting-response] | The core team is waiting for additional information from the author. | -| [PR: Awaiting Review πŸ‘€][awaiting-review] | The core team has not yet performed a code review. | -| [PR: Awaiting Revisions πŸ–Š][awaiting-revisions] | Following code review, this label is applied until the author has made sufficient changes. | -| **QA** | | -| [PR: Awaiting User Cases πŸ’ƒ][awaiting-stories] | The PR code changes need common language descriptions of impact to end users before the review can start | -| [PR: No UX Impact πŸ™ƒ][no-ux-impact] | The PR code changes do not impact the user's experience | - -We rely on GitHub Checks and integrations with third party services to evaluate -changes in code quality and test coverage. Tests must pass and User cases must -be present (when applicable) before a PR can be merged to master, and code -quality and test coverage must not be changed by a significant margin. For some -repositories, visual screenshot-based tests are also included, and video -recordings of end-to-end tests are stored for later review. - -[You can read more about our continous integration efforts here](/development/continous-integration.md) - -## Releases - -Releases are made automatically based on the type of commits which have been -merged (major.minor.patch). Releases are automatically pushed to NPM. Release -notes are automatically generated. Users can subscribe to GitHub and NPM -releases. - -We host development, staging, and production environments for the Progressive -Web Application version of the OHIF Viewer. [Development][ohif-dev] always -reflects the latest changes on our master branch. [Staging][ohif-stage] is used -to regression test a release before a bi-weekly deploy to our [Production -environment][ohif-prod]. - -Important announcements are made on GitHub, tagged as Announcement, and pinned -so that they remain at the top of the Issue page. - -The Core team occasionally performs full manual testing to begin the process of -releasing a Stable version. Once testing is complete, the known issues are -addressed and a Stable version is released. - - - - -[groom-backlog]: https://www.agilealliance.org/glossary/backlog-grooming -[retrospective]: https://www.atlassian.com/team-playbook/plays/retrospective -[gh-issues]: https://github.com/OHIF/Viewers/issues/new/choose -[gh-labels]: https://github.com/OHIF/Viewers/labels - -[label-story]: https://github.com/OHIF/Viewers/labels/Story%20%3Araised_hands%3A -[label-tooling]: https://github.com/OHIF/Viewers/labels/Task%3A%20CI%2FTooling%20%3Arobot%3A -[label-docs]: https://github.com/OHIF/Viewers/labels/Task%3A%20Docs%20%3Abook%3A -[label-refactor]: https://github.com/OHIF/Viewers/labels/Task%3A%20Refactor%20%3Ahammer_and_wrench%3A -[label-tests]: https://github.com/OHIF/Viewers/labels/Task%3A%20Tests%20%3Amicroscope%3A -[label-bug]: https://github.com/OHIF/Viewers/labels/Bug%3A%20Verified%20%3Abug%3A - -[draft]: https://github.com/OHIF/Viewers/labels/PR%3A%20Draft -[awaiting-response]: https://github.com/OHIF/Viewers/labels/PR%3A%20Awaiting%20Response%20%3Aspeech_balloon%3A -[awaiting-review]: https://github.com/OHIF/Viewers/labels/PR%3A%20Awaiting%20Review%20%3Aeyes%3A -[awaiting-stories]: https://github.com/OHIF/Viewers/labels/PR%3A%20Awaiting%20UX%20Stories%20%3Adancer%3A -[awaiting-revisions]: https://github.com/OHIF/Viewers/labels/PR%3A%20Awaiting%20Revisions%20%3Apen%3A -[no-ux-impact]: https://github.com/OHIF/Viewers/labels/PR%3A%20No%20UX%20Impact%20%3Aupside_down_face%3A - -[ohif-dev]: https://viewer-dev.ohif.org -[ohif-stage]: https://viewer-stage.ohif.org -[ohif-prod]: https://viewer.ohif.org -[gh-board]: https://github.com/OHIF/Viewers/projects/4 -[label-grabs]: https://github.com/OHIF/Viewers/issues?q=is%3Aissue+is%3Aopen+label%3A%22Up+For+Grabs+%3Araising_hand_woman%3A%22 -[contributing-docs]: ./development/contributing.md - diff --git a/platform/docs/versioned_docs/version-3.0/development/testing.md b/platform/docs/versioned_docs/version-3.0/development/testing.md deleted file mode 100644 index c7c846aaa3d..00000000000 --- a/platform/docs/versioned_docs/version-3.0/development/testing.md +++ /dev/null @@ -1,217 +0,0 @@ ---- -sidebar_position: 6 -sidebar_label: Testing ---- - -# Running Tests for OHIF - -We introduce here various test types that is available for OHIF, and how to run -each test in order to make sure your contribution hasn't broken any existing -functionalities. Idea and philosophy of each testing category is discussed in -the second part of this page. - -## Unit test - -To run the unit test: - -```bash -yarn run test:unit:ci -``` - -Note: You should have already installed all the packages with `yarn install`. - -Running unit test will generate a report at the end showing the successful and -unsuccessful tests with detailed explanations. - -## End-to-end test -For running the OHIF e2e test you need to run the following steps: - -- Open a new terminal, and from the root of the OHIF mono repo, run the following command: - - ```bash - yarn test:data - ``` - - This will download the required data to run the e2e tests (it might take a while). - The `test:data` only needs to be run once and checks the data out. Read more about - test data [below](#test-data). - -- Run the viewer with e2e config - - ```bash - APP_CONFIG=config/e2e.js yarn start - ``` - - You should be able to see test studies in the study list - - ![OHIF-e2e-test-studies](../assets/img/OHIF-e2e-test-studies.png) - -- Open a new terminal inside the OHIF project, and run the e2e cypress test - - ```bash - yarn test:e2e - ``` - - You should be able to see the cypress window open - - ![e2e-cypress](../assets/img/e2e-cypress.png) - - Run the tests by clicking on the `Run #number integration tests` . - - A new window will open, and you will see e2e tests being executed one after - each other. - - ![e2e-cypress-final](../assets/img/e2e-cypress-final.png) - - ## Test Data - The testing data is stored in two OHIF repositories. The first contains the - binary DICOM data, at [viewer-testdata](https://github.com/OHIF/viewer-testdata.git) - while the second module contains data in the DICOMweb format, installed as a submodule - into OHIF in the `testdata` directory. This is retrieved via the command - ```bash - yarn test:data - ``` - or the equivalent command `git submodule update --init` - When adding new data, run: - ``` - npm install -g dicomp10-to-dicomweb - mkdicomweb -d dicomweb dcm - ``` - to update the local dicomweb submodule in viewer-testdata. Then, commit - that data and update the submodules used in OHIF and in the viewer-testdata - parent modules. - - All data MUST be fully anonymized and allowed to be used for open access. - Any attributions should be included in the DCM directory. - -## Testing Philosophy - -> Testing is an opinionated topic. Here is a rough overview of our testing -> philosophy. See something you want to discuss or think should be changed? Open -> a PR and let's discuss. - -You're an engineer. You know how to write code, and writing tests isn't all that -different. But do you know why we write tests? Do you know when to write one, or -what kind of test to write? How do you know if a test is a _"good"_ test? This -document's goal is to give you the tools you need to make those determinations. - -Okay. So why do we write tests? To increase our... **CONFIDENCE** - -- If I do a large refactor, does everything still work? -- If I changed some critical piece of code, is it safe to push to production? - -Gaining the confidence we need to answer these questions after every change is -costly. Good tests allow us to answer them without manual regression testing. -What and how we choose to test to increase that confidence is nuanced. - -## Further Reading: Kinds of Tests - -Test's buy us confidence, but not all tests are created equal. Each kind of test -has a different cost to write and maintain. An expensive test is worth it if it -gives us confidence that a payment is processed, but it may not be the best -choice for asserting an element's border color. - -| Test Type | Example | Speed | Cost | -| ----------- | ------------------------------------------------------------------------ | ---------------- | ------------------------------------------------------------------------ | -| Static | `addNums(1, '2')` called with `string`, expected `int`. | :rocket: Instant | :money_with_wings: | -| Unit | `addNums(1, 2)` returns expected result `3` | :airplane: Fast | :money_with_wings::money_with_wings: | -| Integration | Clicking "Sign In", navigates to the dashboard (mocked network requests) | :running: Okay | :money_with_wings::money_with_wings::money_with_wings: | -| End-to-end | Clicking "Sign In", navigates to the dashboard (no mocks) | :turtle: Slow | :money_with_wings::money_with_wings::money_with_wings::money_with_wings: | - -- :rocket: Speed: How quickly tests run -- :money_with_wings: Cost: Time to write, and to debug when broken (more points - of failure) - -### Static Code Analysis - -Modern tooling gives us this "for free". It can catch invalid regular -expressions, unused variables, and guarantee we're calling methods/functions -with the expected parameter types. - -Example Tooling: - -- [ESLint][eslint-rules] -- [TypeScript][typescript-docs] or [Flow][flow-org] - -### Unit Tests - -The building blocks of our libraries and applications. For these, you'll often -be testing a single function or method. Conceptually, this equates to: - -_Pure Function Test:_ - -- If I call `sum(2, 2)`, I expect the output to be `4` - -_Side Effect Test:_ - -- If I call `resetViewport(viewport)`, I expect `cornerstone.reset` to be called - with `viewport` - -#### When to use - -Anything that is exposed as public API should have unit tests. - -#### When to avoid - -You're actually testing implementation details. You're testing implementation -details if: - -- Your test does something that the consumer of your code would never do. - - IE. Using a private function -- A refactor can break your tests - -### Integration Tests - -We write integration tests to gain confidence that several units work together. -Generally, we want to mock as little as possible for these tests. In practice, -this means only mocking network requests. - -### End-to-End Tests - -These are the most expensive tests to write and maintain. Largely because, when -they fail, they have the largest number of potential points of failure. So why -do we write them? Because they also buy us the most confidence. - -#### When to use - -Mission critical features and functionality, or to cover a large breadth of -functionality until unit tests catch up. Unsure if we should have a test for -feature `X` or scenario `Y`? Open an issue and let's discuss. - -### General - -- [Assert(js) Conf 2018 Talks][assert-js-talks] - - [Write tests. Not too many. Mostly integration.][kent-talk] - Kent C. Dodds - - [I see your point, but…][gleb-talk] - Gleb Bahmutov -- [Static vs Unit vs Integration vs E2E Testing][kent-blog] - Kent C. Dodds - (Blog) - -### End-to-end Testing w/ Cypress - -- [Getting Started](https://docs.cypress.io/guides/overview/why-cypress.html) - - Be sure to check out `Getting Started` and `Core Concepts` -- [Best Practices](https://docs.cypress.io/guides/references/best-practices.html) -- [Example Recipes](https://docs.cypress.io/examples/examples/recipes.html) - - - - -[eslint-rules]: https://eslint.org/docs/rules/ -[mini-pacs]: https://github.com/OHIF/viewer-testdata -[typescript-docs]: https://www.typescriptlang.org/docs/home.html -[flow-org]: https://flow.org/ - -[assert-js-talks]: https://www.youtube.com/playlist?list=PLZ66c9_z3umNSrKSb5cmpxdXZcIPNvKGw -[kent-talk]: https://www.youtube.com/watch?v=Fha2bVoC8SE -[gleb-talk]: https://www.youtube.com/watch?v=5FnalKRjpZk -[kent-blog]: https://kentcdodds.com/blog/unit-vs-integration-vs-e2e-tests - -[testing-trophy]: https://twitter.com/kentcdodds/status/960723172591992832?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E960723172591992832&ref_url=https%3A%2F%2Fkentcdodds.com%2Fblog%2Fwrite-tests -[aaron-square]: https://twitter.com/Carofine247/status/966727489274961920 -[gleb-pyramid]: https://twitter.com/Carofine247/status/966764532046684160/photo/3 -[testing-pyramid]: https://dojo.ministryoftesting.com/dojo/lessons/the-mobile-test-pyramid -[testing-dorito]: https://twitter.com/denvercoder/status/960752578198843392 -[testing-dorito-img]: https://pbs.twimg.com/media/DVVHXycUMAAcN-F?format=jpg&name=4096x4096 - diff --git a/platform/docs/versioned_docs/version-3.0/faq.md b/platform/docs/versioned_docs/version-3.0/faq.md deleted file mode 100644 index 67b7d30b2e8..00000000000 --- a/platform/docs/versioned_docs/version-3.0/faq.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -sidebar_position: 8 -sidebar_label: FAQ ---- - -# Frequently Asked Questions - -## Index - -- [Report a bug][report-bug] -- [Request a feature][new-feature] -- [Commercial Support & Consulting][commercial-support] -- [Academic collaborations][academic] -- [FDA Clearance or CE Marking][fda-clearance] -- [HIPAA Compliance][hipaa] - -### How do I report a bug? - -Navigate to our [GitHub Repository][new-issue], and submit a new bug report. -Follow the steps outlined in the [Bug Report Template][bug-report-template]. - -### How can I request a new feature? - -At the moment we are in the process of defining our roadmap and will do our best -to communicate this to the community. If your requested feature is on the -roadmap, then it will most likely be built at some point. If it is not, you are -welcome to build it yourself and [contribute it](development/contributing.md). -If you have resources and would like to fund the development of a feature, -please [contact us](https://www.ohif.org) or work with community members that -offer [consulting services][commercial-support]. - -### Who should I contact about Academic Collaborations? - -[Gordon J. Harris](https://www.dfhcc.harvard.edu/insider/member-detail/member/gordon-j-harris-phd/) -at Massachusetts General Hospital is the primary contact for any academic -collaborators. We are always happy to hear about new groups interested in using -the OHIF framework, and may be able to provide development support if the -proposed collaboration has an impact on cancer research. - -### Does OHIF offer commercial support? - -The Open Health Imaging Foundation does not offer commercial support, however, -some community members do offer consulting services. You can search our -[Community Forum](https://community.ohif.org/) for more information. - -### Does The OHIF Viewer have [510(k) Clearance][501k-clearance] from the U.S. F.D.A or [CE Marking][ce-marking] from the European Commission? - -**NO.** The OHIF Viewer is **NOT** F.D.A. cleared or CE Marked. It is the users' -responsibility to ensure compliance with applicable rules and regulations. The -[License](https://github.com/OHIF/Viewers/blob/master/LICENSE) for the OHIF -Platform does not prevent your company or group from seeking F.D.A. clearance -for a product built using the platform. - -If you have gone this route (or are going there), please let us know because we -would be interested to hear about your experience. - -### Is The OHIF Viewer [HIPAA][hipaa-def] Compliant? - -**NO.** The OHIF Viewer **DOES NOT** fulfill all of the criteria to become HIPAA -Compliant. It is the users' responsibility to ensure compliance with applicable -rules and regulations. - - - - - -[report-bug]: #how-do-i-report-a-bug -[new-feature]: #how-can-i-request-a-new-feature -[commercial-support]: #does-ohif-offer-commercial-support -[academic]: #who-should-i-contact-about-academic-collaborations -[fda-clearance]: #does-the-ohif-viewer-have-510k-clearance-from-the-us-fda-or-ce-marking-from-the-european-commission -[hipaa]: #is-the-ohif-viewer-hipaa-compliant - -[501k-clearance]: https://www.fda.gov/MedicalDevices/DeviceRegulationandGuidance/HowtoMarketYourDevice/PremarketSubmissions/PremarketNotification510k/ -[ce-marking]: https://ec.europa.eu/growth/single-market/ce-marking_en -[hipaa-def]: https://en.wikipedia.org/wiki/Health_Insurance_Portability_and_Accountability_Act -[new-issue]: https://github.com/OHIF/Viewers/issues/new/choose -[bug-report-template]: https://github.com/OHIF/Viewers/issues/new?assignees=&labels=Bug+Report+%3Abug%3A&template=---bug-report.md&title= - diff --git a/platform/docs/versioned_docs/version-3.0/platform/_category_.json b/platform/docs/versioned_docs/version-3.0/platform/_category_.json deleted file mode 100644 index 842e4abf4a1..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Platform", - "position": 6 -} diff --git a/platform/docs/versioned_docs/version-3.0/platform/browser-support.md b/platform/docs/versioned_docs/version-3.0/platform/browser-support.md deleted file mode 100644 index f717432aedc..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/browser-support.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -sidebar_position: 2 ---- -# Browser Support - -The browsers that we support are specified in the `.browserlistrc` file located -in the `platform/viewer` project. While we leverage the latest language features -when writing code, we rely on `babel` to _transpile_ our code so that it can run -in the browsers that we support. - -## In Practice - -The OHIF Viewer is capable of _running_ on: - -- IE 11 -- FireFox -- Chrome -- Safari -- Edge - -However, we do not have the resources to adequately test and maintain bug free -functionality across all of these. In order to push web based medical imaging -forward, we focus our development efforts on recent version of modern evergreen -browsers. - -Our support of older browsers equates to our willingness to review PRs for bug -fixes, and target their minimum JS support whenever possible. - -### Polyfills - -> A polyfill, or polyfiller, is a piece of code (or plugin) that provides the -> technology that you, the developer, expect the browser to provide natively. - -An example of a polyfill is that you expect `Array.prototype.filter` to exist, -but for some reason, the browser that's being used has not implemented that -language feature yet. Our earlier transpilation will rectify _syntax_ -discrepancies, but unimplemented features require a "temporary" implementation. -That's where polyfills step in. - -You can utilize a service like [polyfill.io](https://polyfill.io/v3/) to -auto-detect and apply polyfills as needed, or you can update the PWA build to -include polyfill's in your bundle by incorporating [core-js][core-js] - - - - -[core-js]: https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md - diff --git a/platform/docs/versioned_docs/version-3.0/platform/environment-variables.md b/platform/docs/versioned_docs/version-3.0/platform/environment-variables.md deleted file mode 100644 index 4fd2691a4aa..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/environment-variables.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: Environment Variables ---- -# Environment Variables - -There are a number of environment variables we use at build time to influence the output application's behavior. - -```bash -# Application -NODE_ENV=< production | development > -DEBUG=< true | false > -APP_CONFIG=< relative path to application configuration file > -PUBLIC_URL=<> -VERSION_NUMBER= -BUILD_NUM= -# i18n -USE_LOCIZE= -LOCIZE_PROJECTID= -LOCIZE_API_KEY= -``` - -## Setting Environment Variables - -- `npx cross-env` -- `.env` files -- env variables on build machine, or for terminal session diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/_category_.json b/platform/docs/versioned_docs/version-3.0/platform/extensions/_category_.json deleted file mode 100644 index b7a30d960fb..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Extensions", - "position": 9 -} diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/extension.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/extension.md deleted file mode 100644 index 148b82a9faf..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/extension.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: Extension Manager ---- - -# Extension Manager - -## Overview - -The `ExtensionManager` is a class made available to us via the `@ohif/core` -project (platform/core). Our application instantiates a single instance of it, -and provides a `ServicesManager` and `CommandsManager` along with the -application's configuration through the appConfig key (optional). - -```js -const commandsManager = new CommandsManager(); -const servicesManager = new ServicesManager(); -const extensionManager = new ExtensionManager({ - commandsManager, - servicesManager, - appConfig, -}); -``` - -The `ExtensionManager` only has a few public members: - -- `setActiveDataSource` - Sets the active data source for the application -- `getDataSources` - Returns the registered data sources -- `getActiveDataSource` - Returns the currently active data source -- `getModuleEntry` - Returns the module entry by the give id. - -## Accessing Modules - -We use `getModuleEntry` in our `ViewerLayout` logic to find the panels based on -the provided IDs in the mode's configuration. - -For instance: -`extensionManager.getModuleEntry("@ohif/extension-measurement-tracking.panelModule.seriesList")` -accesses the `seriesList` panel from `panelModule` of the -`@ohif/extension-measurement-tracking` extension. - -```js -const getPanelData = id => { - const entry = extensionManager.getModuleEntry(id); - const content = entry.component; - - return { - iconName: entry.iconName, - iconLabel: entry.iconLabel, - label: entry.label, - name: entry.name, - content, - }; -}; -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/index.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/index.md deleted file mode 100644 index b1920b52104..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/index.md +++ /dev/null @@ -1,325 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Introduction ---- - -# Introduction - -We have re-designed the architecture of the `OHIF-v3` to enable building -applications that are easily extensible to various use cases (modes) that behind -the scene would utilize desired functionalities (extensions) to reach the goal -of the use case. - -Previously, extensions were β€œadditive” and could not easily be mixed and matched -within the same viewer for different use cases. Previous `OHIF-v2` architecture -meant that any minor extension alteration usually would require the user to hard -fork. E.g. removing some tools from the toolbar of the cornerstone -extension meant you had to hard fork it, which was frustrating if the -implementation was otherwise the same as master. - -> - Developers should make packages of _reusable_ functionality as extensions, -> and can consume publicly available extensions. -> - Any conceivable radiological workflow or viewer setup will be able to be -> built with the platform through _modes_. - -Practical examples of extensions include: - -- A set of segmentation tools that build on top of the `cornerstone` viewport -- A set of rendering functionalities to volume render the data -- [See our maintained extensions for more examples of what's possible](#maintained-extensions) - -**Diagram showing how extensions are configured and accessed.** - - - -## Extension Skeleton - -An extension is a plain JavaScript object that has `id` and `version` properties, and one or -more [modules](#modules) and/or [lifecycle hooks](#lifecycle-hooks). - -```js -// prettier-ignore -export default { - /** - * Required properties. Should be a unique value across all extensions. - */ - id, - - // Lifecyle - preRegistration() { /* */ }, - onModeEnter() { /* */ }, - onModeExit() { /* */ }, - // Modules - getLayoutTemplateModule() { /* */ }, - getDataSourcesModule() { /* */ }, - getSopClassHandlerModule() { /* */ }, - getPanelModule() { /* */ }, - getViewportModule() { /* */ }, - getCommandsModule() { /* */ }, - getContextModule() { /* */ }, - getToolbarModule() { /* */ }, - getHangingProtocolModule() { /* */ }, -} -``` - -## OHIF-Maintained Extensions - -A small number of powerful extensions for popular use cases are maintained by -OHIF. They're co-located in the [`OHIF/Viewers`][viewers-repo] repository, in -the top level [`extensions/`][ext-source] directory. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ExtensionDescriptionModules
- - Default - - - Default extension provides default viewer layout, a study/series - browser, and a datasource that maps to a DICOMWeb compliant backend - commandsModule, ContextModule, DataSourceModule, HangingProtocolModule, LayoutTemplateModule, PanelModule, SOPClassHandlerModule, ToolbarModule
- - Cornerstone - - - Provides rendering functionalities for 2D images. - ViewportModule, CommandsModule
- DICOM PDF - - Renders PDFs for a specific SopClassUID. - Viewport, SopClassHandler
- DICOM SR - - Maintained extensions for cornerstone and visualization of DICOM Structured Reports - ViewportModule, CommandsModule, SOPClassHandlerModule
- Measurement tracking - - Tracking measurements in the measurement panel - ContextModule,PanelModule,ViewportModule,CommandsModule
- -## Registering of Extensions - -`viewer` starts by registering all the extensions specified inside the -`pluginConfig.json`, by default we register all extensions in the repo. - - -```js title=platform/viewer/pluginConfig.json -// Simplified version of the `pluginConfig.json` file -{ - "extensions": [ - { - "packageName": "@ohif/extension-cornerstone", - "version": "3.0.0" - }, - { - "packageName": "@ohif/extension-measurement-tracking", - "version": "3.0.0" - }, - // ... - ], - "modes": [ - { - "packageName": "@ohif/mode-longitudinal", - "version": "0.0.1" - } - ] -} -``` - -:::note Important -You SHOULD NOT directly register extensions in the `pluginConfig.json` file. -Use the provided `cli` to add/remove/install/uninstall extensions. Read more [here](../../development/ohif-cli.md) -::: - -The final registration and import of the extensions happen inside a non-tracked file `pluginImport.js` (this file is also for internal use only). - -After an extension gets registered withing the `viewer`, -each [module](#modules) defined by the extension becomes available to the modes -via the `ExtensionManager` by requesting it via its id. -[Read more about Extension Manager](#extension-manager) - -## Lifecycle Hooks - -Currently, there are three lifecycle hook for extensions: - -[`preRegistration`](./lifecycle/#preRegistration) This hook is called once on -initialization of the entire viewer application, used to initialize the -extensions state, and consume user defined extension configuration. If an -extension defines the [`preRegistration`](./lifecycle/#preRegistration) -lifecycle hook, it is called before any modules are registered in the -`ExtensionManager`. It's most commonly used to wire up extensions to -[services](./../services/index.md) and [commands](./modules/commands.md), and to -bootstrap 3rd party libraries. - -[`onModeEnter`](./lifecycle#onModeEnter): This hook is called whenever a new -mode is entered, or a mode’s data or datasource is switched. This hook can be -used to initialize data. - -[`onModeExit`](./lifecycle#onModeExit): Similarly to onModeEnter, this hook is -called when navigating away from a mode, or before a mode’s data or datasource -is changed. This can be used to clean up data (e.g. remove annotations that do -not need to be persisted) - -## Modules - -Modules are the meat of extensions, the `blocks` that we have been talking about -a lot. They provide "definitions", components, and filtering/mapping logic that -are then made available to modes and services. - -Each module type has a special purpose, and is consumed by our viewer -differently. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Types - Description
- - LayoutTemplate (NEW) - - Control Layout of a route
- - DataSource (NEW) - - Control the mapping from DICOM metadata to OHIF-metadata
- - SOPClassHandler - - Determines how retrieved study data is split into "DisplaySets"
- - Panel - - Adds left or right hand side panels
- - Viewport - - Adds a component responsible for rendering a "DisplaySet"
- - Commands - - Adds named commands, scoped to a context, to the CommandsManager
- - Toolbar - - Adds buttons or custom components to the toolbar
- - Context - - Shared state for a workflow or set of extension module definitions
- - HangingProtocol - - Adds hanging protocol rules
- -Tbl. Module types -with abridged descriptions and examples. Each module links to a dedicated -documentation page. - -### Contexts - -The `@ohif/viewer` tracks "active contexts" that extensions can use to scope -their functionality. Some example contexts being: - -- Route: `ROUTE:VIEWER`, `ROUTE:STUDY_LIST` -- Active Viewport: `ACTIVE_VIEWPORT:CORNERSTONE`, `ACTIVE_VIEWPORT:VTK` - -An extension module can use these to say "Only show this Toolbar Button if the -active viewport is a Cornerstone viewport." This helps us use the appropriate UI -and behaviors depending on the current contexts. - -For example, if we have hotkey that "rotates the active viewport", each Viewport -module that supports this behavior can add a command with the same name, scoped -to the appropriate context. When the `command` is fired, the "active contexts" -are used to determine the appropriate implementation of the rotation behavior. - - - - -[viewers-repo]: https://github.com/OHIF/Viewers -[ext-source]: https://github.com/OHIF/Viewers/tree/master/extensions -[module-types]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/extensions/MODULE_TYPES.js - diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/installation.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/installation.md deleted file mode 100644 index 2e5fb81c2a1..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/installation.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: Installation ---- - -# Extension: Installation - -OHIF-v3 provides the ability to utilize external extensions. - - -You can use ohif `cli` tool to install both local and publicly published -extensions on NPM. You can read more [here](../../development/ohif-cli.md) diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/lifecycle.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/lifecycle.md deleted file mode 100644 index 422bce794cd..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/lifecycle.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: Lifecycle Hooks ---- - -# Extensions: Lifecycle Hooks - -## Overview - -Extensions can implement specific lifecycle methods. - -- preRegistration -- onModeEnter -- onModeExit - -## preRegistration - -If an extension defines the `preRegistration` lifecycle hook, it is called -before any modules are registered in the `ExtensionManager`. This hook can be -used to: - -- initialize 3rd party libraries -- register event listeners -- add or call services -- add or call commands - -The `preRegistration` hook receives an object containing the -`ExtensionManager`'s associated `ServicesManager`, `CommandsManager`, and any -`configuration` that was provided with the extension at time of registration. - -Example `preRegistration` implementation that register a new service and make it -available in the app. We will talk more in details for creating a new service -for `OHIF-v3`. - -```js -// new service inside new extension -import MyNewService from './MyNewService'; - -export default function MyNewServiceWithServices(serviceManager) { - return { - name: 'MyNewService', - create: ({ configuration = {} }) => { - return new MyNewService(serviceManager); - }, - }; -} -``` - -and - -```js -import MyNewService from './MyNewService' - -export default { - id, - - /** - * @param {object} params - * @param {object} params.configuration - * @param {ServicesManager} params.servicesManager - * @param {CommandsManager} params.commandsManager - * @returns void - */ - preRegistration({ servicesManager, commandsManager, configuration }) { - console.log('Wiring up important stuff.'); - - window.importantStuff = () => { - console.log(configuration); - }; - - console.log('Important stuff has been wired.'); - window.importantStuff(); - - // Registering new services - servicesManager.registerService(MyNewService(servicesManager)); - }, - }, -}; -``` - -## onModeEnter - -If an extension defines the `onModeEnter` lifecycle hook, it is called when a -new mode is enters, or a mode's data or datasource is switched. - -For instance, in DICOM structured report extension (`dicom-sr`), we are using -`onModeEnter` to re-create the displaySets after a new mode is entered. - -_Example `onModeEnter` hook implementation_ - -```js -export default { - id: '@ohif/extension-cornerstone-dicom-sr', - - onModeEnter({ servicesManager }) { - const { DisplaySetService } = servicesManager.services; - const displaySetCache = DisplaySetService.getDisplaySetCache(); - - const srDisplaySets = displaySetCache.filter( - ds => ds.SOPClassHandlerId === SOPClassHandlerId - ); - - srDisplaySets.forEach(ds => { - // New mode route, allow SRs to be hydrated again - ds.isHydrated = false; - }); - }, -}; -``` - -## onModeExit - -If an extension defines the `onModeExit` lifecycle hook, it is called when -navigating away from a mode. This hook can be used to clean up data tasks such -as unregistering services, removing annotations that do not need to be -persisted. - -_Example `onModeExit` hook implementation_ - -```js -export default { - id: 'myExampleExtension', - - onModeExit({ servicesManager, commandsManager }) { - myCacheService.purge(); - }, -}; -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/_category_.json b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/_category_.json deleted file mode 100644 index c131ccdd7e3..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Modules", - "position": 3 -} diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/commands.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/commands.md deleted file mode 100644 index b37202bf61e..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/commands.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: Commands ---- -# Module: Commands - - -## Overview -`CommandsModule` includes list of arbitrary functions. These may activate tools, communicate with a server, open a modal, etc. -The significant difference between `OHIF-v3` and `OHIF-v2` is that in `v3` a `mode` defines -its toolbar, and which commands each tool call is inside in its toolDefinition - -An extension can register a Commands Module by defining a `getCommandsModule` -method. The Commands Module allows us to register one or more commands scoped to -specific [contexts](./../index.md#contexts). Commands have several unique -characteristics that make them tremendously powerful: - -- Multiple implementations for the same command can be defined -- Only the correct command's implementation will be run, dependent on the - application's "context" -- Commands are used by hotkeys, toolbar buttons and render settings - -Here is a simple example commands module: - -```js -const getCommandsModule = () => ({ - definitions: { - exampleActionDef: { - commandFn: ({ param1 }) => { - console.log(`param1's value is: ${param1}`); - }, - // storeContexts: ['viewports'], - options: { param1: 'param1' }, - context: 'VIEWER', // optional - }, - }, - defaultContext: 'ACTIVE_VIEWPORT::DICOMSR', -}); -``` - - -Each definition returned by the Commands Module is registered to the -`ExtensionManager`'s `CommandsManager`. - -> `storeContexts` has been removed in `OHIF-v3` and now modules have access to all commands and services. This change enables support for user-registered services. - -## Command Definitions - -The command definition consists of a named command (`exampleActionDef` below) and a -`commandFn`. The command name is used to call the command, and the `commandFn` -is the "command" that is actioned. - -```js -exampleActionDef: { - commandFn: ({ param1, options }) => { }, - options: { param1: 'measurement' }, - context: 'DEFAULT', -} -``` - -| Property | Type | Description | -| --------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | -| `commandFn` | func | The function to call when command is run. Receives `options` and `storeContexts`. | -| `options` | object | (optional) Arguments to pass at the time of calling to the `commandFn` | -| `context` | string[] or string | (optional) Overrides the `defaultContext`. Let's us know if command is currently "available" to be run. | - -## Command Behavior - - - -**If there are multiple valid commands for the application's active contexts** - -- What happens: all commands are run -- When to use: A `clearData` command that cleans up state for multiple - extensions - -**If no commands are valid for the application's active contexts** - -- What happens: a warning is printed to the console -- When to use: a `hotkey` (like "invert") that doesn't make sense for the - current viewport (PDF or HTML) - -## `CommandsManager` Public API - -If you would like to run a command in the consuming app or an extension, you can -use `CommandsManager.runCommand(commandName, options = {}, contextName)` - - -```js -// Returns all commands for a given context -commandsManager.getContext('string'); - -// Run a command, it will run all the `speak` commands in all contexts -commandsManager.runCommand('speak', { command: 'hello' }); - -// Run command, from Default context -commandsManager.runCommand('speak', { command: 'hello' }, ['DEFAULT']); -``` - -The `ExtensionManager` handles registering commands and creating contexts, so -most consumer's won't need these methods. If you find yourself using these, ask -yourself "why can't I register these commands via an extension?" - -```js -// Used by the `ExtensionManager` to register new commands -commandsManager.registerCommand('context', 'name', commandDefinition); - -// Creates a new context; clears the context if it already exists -commandsManager.createContext('string'); -``` - -### Contexts - -It is up to the consuming application to define what contexts are possible, and -which ones are currently active. As extensions depend heavily on these, we will -likely publish guidance around creating contexts, and ways to override extension -defined contexts in the near future. If you would like to discuss potential -changes to how contexts work, please don't hesitate to create a new GitHub -issue. - -[Some additional information on Contexts can be found here.](./../index.md#contexts) diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/contextModule.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/contextModule.md deleted file mode 100644 index 35de381a3da..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/contextModule.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -sidebar_position: 9 -sidebar_label: Context ---- -# Module: Context - -## Overview -This new module type allows you to connect components via a shared context. You can create a context that two components, e.g. a viewport and a panel can use to synchronize and communicate. An extensive example of this can be seen in the longitudinal mode’s custom extensions. - - - -```jsx -const ExampleContext = React.createContext(); - -function ExampleContextProvider({ children }) { - return ( - - {children} - - ); -} - -const getContextModule = () => [ - { - name: 'ExampleContext', - context: ExampleContext, - provider: ExampleContextProvider, - }, -]; -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/data-source.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/data-source.md deleted file mode 100644 index 381d7ea7e1e..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/data-source.md +++ /dev/null @@ -1,106 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: Data Source ---- - -# Module: Data Source - -## Overview - -The internal data structure of OHIF’s metadata follows naturalized DICOM JSON, A -format pioneered by `dcmjs`. In short DICOM metadata headers with DICOM Keywords -instead of tags and sequences as arrays, for easy development and clear code. - -We have built a standard for fetching and mapping data into OHIF’s native -format, which we call DataSources, and have provided one implementation of this -standard. - -You can make another datasource implementation which communicates to your -backend and maps to OHIF’s native format, then use any existing mode on your -platform. Your data doesn’t even need to be DICOM if you can map some -proprietary data to the correct format. - -The DataSource is also a place to add easy helper methods that platform-specific -extensions can call in order to interact with the backend, meaning proprietary -data interactions can be wrapped in extensions. - -```js -const getDataSourcesModule = () => [ - { - name: 'exampleDataSource', - type: 'webApi', // 'webApi' | 'local' | 'other' - createDataSource: dataSourceConfig => { - return IWebApiDataSource.create(/* */); - }, - }, -]; -``` - -Default extension provides two main data sources that are commonly used: -`dicomweb` and `dicomjson` - -```js -import { createDicomWebApi } from './DicomWebDataSource/index.js'; -import { createDicomJSONApi } from './DicomJSONDataSource/index.js'; - -function getDataSourcesModule() { - return [ - { - name: 'dicomweb', - type: 'webApi', - createDataSource: createDicomWebApi, - }, - { - name: 'dicomjson', - type: 'jsonApi', - createDataSource: createDicomJSONApi, - }, - ]; -} -``` - -## Custom DataSource - -You can add your custom datasource by creating the implementation using -`IWebApiDataSource.create` from `@ohif/core`. This factory function creates a -new "Web API" data source that fetches data over HTTP. - -You need to make sure, you implement the following functions for the data -source. - -```js title="platform/core/src/DataSources/IWebApiDataSource.js" -function create({ - query, - retrieve, - store, - reject, - parseRouteParams, - deleteStudyMetadataPromise, - getImageIdsForDisplaySet, - getImageIdsForInstance, -}) { - /* */ -} -``` - -You can take a look at `dicomweb` data source implementation to get an idea -`extensions/default/src/DicomWebDataSource/index.js` - -## Static WADO Client - -If the configuration for the data source has the value staticWado set, then it -is assumed that queries for the studies return a super-set of the studies, as it -is assumed to be returning a static list. The StaticWadoClient performs the -search functionality manually, by interpreting the query parameters and then -applying them to the returned response. This functionality may be useful for -other types of DICOMweb back ends, where they are capable of performing queries, -but don't allow for querying certain types of fields. However, that only works -as long as the size of the studies list isn't too large that client side -selection isn't too expensive. - -## DicomMetadataStore - -In `OHIF-v3` we have a central location for the metadata of studies, and they are -located in `DicomMetadataStore`. Your custom datasource can communicate with -`DicomMetadataStore` to store, and fetch Study/Series/Instance metadata. We will -learn more about `DicomMetadataStore` in services. diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/hpModule.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/hpModule.md deleted file mode 100644 index 649d6644eec..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/hpModule.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -sidebar_position: 8 -sidebar_label: Hanging Protocol ---- -# Module: Hanging Protocol - -## Overview -`hangingProtocolModule` provides the protocols for hanging the displaySets in the viewer. -This module can be as simple as loading a list of pre-defined protocols, or it can be more complex -and `fetch` the protocols from a server. - -You can read more about hanging protocols in HangingProtocolService. - -```js -const deafultProtocol = { - id: 'defaultProtocol', - locked: true, - hasUpdatedPriorsInformation: false, - name: 'Default', - createdDate: '2021-02-23T19:22:08.894Z', - modifiedDate: '2021-02-23T19:22:08.894Z', - availableTo: {}, - editableBy: {}, - protocolMatchingRules: [], - stages: [ - { - id: 'nwzau7jDkEkL8djfr', - name: 'oneByOne', - viewportStructure: { - type: 'grid', - properties: { - rows: 1, - columns: 1, - }, - }, - viewports: [ - { - viewportSettings: [], - imageMatchingRules: [], - seriesMatchingRules: [], - studyMatchingRules: [], - }, - ], - createdDate: '2021-02-23T19:22:08.894Z', - }, - ], - numberOfPriorsReferenced: -1, -}; - -function getHangingProtocolModule() { - return [ - { - name: hangingProtocolName, - protocols: [deafultProtocol], - }, - ]; -} -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/layout-template.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/layout-template.md deleted file mode 100644 index 66c839dae1b..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/layout-template.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -sidebar_position: 7 -sidebar_label: Layout Template ---- - -# Module: Layout Template - -## Overview - -`LayoutTemplates` are a new concept in v3 that modes use to control the layout -of a route. A layout template is a React component that is given a set of -managers that define apis to access toolbar state, commands, and hotkeys, as -well as props defined by the layout template. - -For instance the default LayoutTemplate takes in leftPanels, rightPanels and -viewports as props, which it uses to build its view. - -In addition, `layout template` has complete control over the structure of the -application. You could have tools down the left side, or a strict guided -workflow with tools set programmatically, the choice is yours for your use case. - -```jsx -const getLayoutTemplateModule = (/* ... */) => [ - { - id: 'exampleLayout', - name: 'exampleLayout', - component: ExampleLayoutComponent, - }, -]; -``` - -The `props` that are passed to `layoutTemplate` are managers and service, along -with the defined mode left/right panels, mode's defined viewports and OHIF -`ViewportGridComp`. LayoutTemplate leverages extensionManager to grab typed -extension module entries: `*.getModuleEntry(id)` - -A simplified code for `Default extension`'s layout template is: - -```jsx title="extensions/default/src/ViewerLayout/index.jsx" -import React from 'react'; -import { SidePanel } from '@ohif/ui'; - -function Toolbar({ servicesManager }) { - const { ToolBarService } = servicesManager.services; - - return ( - <> - // ToolBarService.getButtonSection('primary') to get toolbarButtons - {toolbarButtons.map((toolDef, index) => { - const { id, Component, componentProps } = toolDef; - return ( - ToolBarService.recordInteraction(args)} - /> - ); - })} - - ); -} - -function ViewerLayout({ - // From Extension Module Params - extensionManager, - servicesManager, - hotkeysManager, - commandsManager, - // From Modes - leftPanels, - rightPanels, - viewports, - ViewportGridComp, -}) { - const getPanelData = id => { - const entry = extensionManager.getModuleEntry(id); - const content = entry.component; - - return { - iconName: entry.iconName, - iconLabel: entry.iconLabel, - label: entry.label, - name: entry.name, - content, - }; - }; - - const getViewportComponentData = viewportComponent => { - const entry = extensionManager.getModuleEntry(viewportComponent.namespace); - - return { - component: entry.component, - displaySetsToDisplay: viewportComponent.displaySetsToDisplay, - }; - }; - - const leftPanelComponents = leftPanels.map(getPanelData); - const rightPanelComponents = rightPanels.map(getPanelData); - const viewportComponents = viewports.map(getViewportComponentData); - - return ( -
- - -
- {/* LEFT SIDEPANELS */} - - - {/* TOOLBAR + GRID */} - - - {/* Rigth SIDEPANELS */} - -
-
- ); -} -``` - -## Overview Video - -
- -
diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/panel.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/panel.md deleted file mode 100644 index 1ad0d8c0813..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/panel.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -sidebar_position: 6 -sidebar_label: Panel ---- - -# Module: Panel - -## Overview - -The default LayoutTemplate has panels on the left and right sides, however one -could make a template with panels at the top or bottom and make extensions with -panels intended for such slots. - -An extension can register a Panel Module by defining a `getPanelModule` method. -The panel module provides the ability to define `menuOptions` and `components` -that can be used by the consuming application. `components` are React Components -that can be displayed in the consuming application's "Panel" Component. - -![panel-module-v3](../../../assets/img/panel-module-v3.png) - -The `menuOptions`'s `target` key, points to a registered `components`'s `id`. A -`defaultContext` is applied to all `menuOption`s; however, each `menuOption` can -optionally provide its own `context` value. - -The `getPanelModule` receives an object containing the `ExtensionManager`'s -associated `ServicesManager` and `CommandsManager`. - -```jsx -import PanelMeasurementTable from './PanelMeasurementTable.js'; - -function getPanelModule({ - commandsManager, - extensionManager, - servicesManager, -}) { - const wrappedMeasurementPanel = () => { - return ( - - ); - }; - - return [ - { - name: 'measure', - iconName: 'list-bullets', - iconLabel: 'Measure', - label: 'Measurements', - isDisabled: studies => {}, // optional - component: wrappedMeasurementPanel, - }, - ]; -} -``` - -## Consuming Panels Inside Modes - -As explained earlier, extensions make the functionalities and components -available and `modes` utilize them to build an app. So, as seen above, we are -not actually defining which side the panel should be opened. Our extension is -providing the component with its. - -New: You can easily add multiple panels to the left/right side of the viewer -using the mode configuration. As seen below, the `leftPanels` and `rightPanels` -accept an `Array` of the `IDs`. - -```js - -const extensionDependencies = { - '@ohif/extension-default': '^3.0.0', - '@ohif/extension-cornerstone': '^3.0.0', - '@ohif/extension-measurement-tracking': '^3.0.0', - '@ohif/extension-cornerstone-dicom-sr': '^3.0.0', -}; - -const id = 'viewer' -const version = '3.0.0 - -function modeFactory({ modeConfiguration }) { - return { - id, - routes: [ - { - path: 'longitudinal', - layoutTemplate: ({ location, servicesManager }) => { - return { - id, - props: { - leftPanels: [ - '@ohif/extension-measurement-tracking.panelModule.seriesList', - ], - rightPanels: [ - '@ohif/extension-measurement-tracking.panelModule.trackedMeasurements', - ], - viewports, - }, - }; - }, - }, - ], - extensions: extensionDependencies - }; -} - -const mode = { - id, - modeFactory, - extensionDependencies, -}; - -export default mode; - -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/sop-class-handler.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/sop-class-handler.md deleted file mode 100644 index eb1b7a46410..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/sop-class-handler.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: SOP Class Handler ---- -# Module: SOP Class Handler - -## Overview -This module defines how a specific DICOM SOP class should be processed to make a displaySet, something that can be hung in a viewport. An extension can register a [SOP Class][sop-class-link] Handler Module by defining a `getSopClassHandlerModule` method. The [SOP Class][sop-class-link]. - -The mode chooses what SOPClassHandlers to use, so you could process a series in a different way depending on mode within the same application. - - -SOPClassHandler is a bit different from the other modules, as it doesn't provide a `1:1` -schema for UI or provide its own components. It instead defines: - -- `sopClassUIDs`: an array of string SOP Class UIDs that the - `getDisplaySetFromSeries` method should be applied to. -- `getDisplaySetFromSeries`: a method that maps series and study metadata to a - display set - -A `displaySet` has the following shape: - -```js -return { - Modality: 'MR', - displaySetInstanceUIDD - SeriesDate, - SeriesTime, - SeriesInstanceUID, - StudyInstanceUID, - SeriesNumber, - FrameRate, - SeriesDescription, - isMultiFrame, - numImageFrames, - SOPClassHandlerId, -} -``` - -## Example SOP Class Handler Module - -```js -import ImageSet from '@ohif/core/src/classes/ImageSet'; - - -const sopClassDictionary = { - CTImageStorage: "1.2.840.10008.5.1.4.1.1.2", - MRImageStorage: "1.2.840.10008.5.1.4.1.1.4", -}; - - -// It is important to note that the used SOPClassUIDs in the modes are in the order that is specified in the array. -const sopClassUids = [ - sopClassDictionary.CTImageStorage, - sopClassDictionary.MRImageStorage, -; - -const makeDisplaySet = (instances) => { - const instance = instances[0]; - const imageSet = new ImageSet(instances); - - imageSet.setAttributes({ - displaySetInstanceUID: imageSet.uid, - SeriesDate: instance.SeriesDate, - SeriesTime: instance.SeriesTime, - SeriesInstanceUID: instance.SeriesInstanceUID, - StudyInstanceUID: instance.StudyInstanceUID, - SeriesNumber: instance.SeriesNumber, - FrameRate: instance.FrameTime, - SeriesDescription: instance.SeriesDescription, - Modality: instance.Modality, - isMultiFrame: isMultiFrame(instance), - numImageFrames: instances.length, - SOPClassHandlerId: `${id}.sopClassHandlerModule.${sopClassHandlerName}`, - }); - - return imageSet; -}; - -getSopClassHandlerModule = () => { - return [ - { - name: 'stack, - sopClassUids, - getDisplaySetsFromSeries: makeDisplaySet, - }, - ]; -}; - -``` - -### More examples : -You can find another example for this mapping between raw metadata and displaySet for -`DICOM-SR` extension. - -## `@ohif/viewer` usage - -We use the `sopClassHandlerModule`s in `DisplaySetService` where we -transform instances from the raw metadata format to a OHIF displaySet format. -You can read more about DisplaySetService here. - - -[sop-class-link]: http://dicom.nema.org/dicom/2013/output/chtml/part04/sect_B.5.html -[dicom-html-sop]: https://github.com/OHIF/Viewers/blob/master/extensions/dicom-html/src/OHIFDicomHtmlSopClassHandler.js#L4-L12 -[dicom-pdf-sop]: https://github.com/OHIF/Viewers/blob/master/extensions/dicom-pdf/src/OHIFDicomPDFSopClassHandler.js#L4-L6 -[dicom-micro-sop]: https://github.com/OHIF/Viewers/blob/master/extensions/dicom-microscopy/src/DicomMicroscopySopClassHandler.js#L5-L7 -[dicom-seg-sop]: https://github.com/OHIF/Viewers/blob/master/extensions/dicom-segmentation/src/OHIFDicomSegSopClassHandler.js#L5-L7 - diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/toolbar.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/toolbar.md deleted file mode 100644 index 98e0d91a7a2..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/toolbar.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Toolbar ---- - -# Module: Toolbar - -An extension can register a Toolbar Module by defining a `getToolbarModule` -method. `OHIF-v3`'s `default` extension (`"@ohif/extension-default"`) provides 5 main -toolbar button types: - -![toolbarModule](../../../assets/img/toolbar-module.png) - -## Example Toolbar Module - -The Toolbar Module should return an array of `objects`. There are currently a -few different variations of definitions, each one is detailed further down. - -```js -export default function getToolbarModule({ commandsManager, servicesManager }) { - return [ - { - name: 'ohif.divider', - defaultComponent: ToolbarDivider, - clickHandler: () => {}, - }, - { - name: 'ohif.action', - defaultComponent: ToolbarButton, - clickHandler: () => {}, - }, - { - name: 'ohif.radioGroup', - defaultComponent: ToolbarButton, - clickHandler: () => {}, - }, - { - name: 'ohif.splitButton', - defaultComponent: ToolbarSplitButton, - clickHandler: () => {}, - }, - { - name: 'ohif.layoutSelector', - defaultComponent: ToolbarLayoutSelector, - clickHandler: (evt, clickedBtn, btnSectionName) => {}, - }, - ]; -} -``` - -## Toolbar buttons consumed in modes - -Below we can see a simplified version of the `longitudinal` mode that shows how -a mode can add buttons to the toolbar by calling -`ToolBarService.addButtons(toolbarButtons)`. `toolbarButtons` is an array of -`toolDefinitions` which we will learn next. - -```js -function modeFactory({ modeConfiguration }) { - return { - id: 'viewer', - displayName: 'Basic Viewer', - - onModeEnter: ({ servicesManager, extensionManager }) => { - const { ToolBarService } = servicesManager.services; - - ToolBarService.init(extensionManager); - ToolBarService.addButtons(toolbarButtons); - }, - routes: [ - { - path: 'longitudinal', - layoutTemplate: ({ location, servicesManager }) => { - return { - /* */ - }; - }, - }, - ], - }; -} -``` - -## Button Definitions - -The simplest toolbarButtons definition has the following properties: - -![toolbarModule-zoom](../../../assets/img/toolbarModule-zoom.png) - -```js -{ - id: 'Zoom', - type: 'ohif.radioGroup', - props: { - type: 'tool', - icon: 'tool-zoom', - label: 'Zoom', - commandOptions: { toolName: 'Zoom' }, - }, -}, -``` - -| property | description | values | -| ---------------- | ----------------------------------------------------------------- | ------------------------------------------- | -| `id` | Unique string identifier for the definition | \* | -| `label` | User/display friendly to show in UI | \* | -| `icon` | A string name for an icon supported by the consuming application. | \* | -| `type` | Used to determine the button's behaviour | "tool", "toggle", "action" | -| `commandName` | (optional) The command to run when the button is used. | Any command registered by a `CommandModule` | -| `commandOptions` | (optional) Options to pass the target `commandName` | \* | - -There are three main types of toolbar buttons: - -- `tool`: buttons that enable a tool by running the `setToolActive` command with - the `commandOptions` -- `toggle`: buttons that acts as a toggle: e.g., linking viewports -- `action`: buttons that executes an action: e.g., capture button to save - screenshot - -## Nested Buttons - -You can use the `ohif.splitButton` type to build a button with extra tools in -the dropdown. - -- First you need to give your `primary` tool definition to the split button -- the `secondary` properties can be a simple arrow down (`chevron-down` icon) -- For adding the extra tools add them to the `items` list. - -You can see below how `longitudinal` mode is using the available toolbarModule -to create `MeasurementTools` nested button - -![toolbarModule-nested-buttons](../../../assets/img/toolbarModule-nested-buttons.png) - -```js title="modes/longitudinal/src/toolbarButtons.js" -{ - id: 'MeasurementTools', - type: 'ohif.splitButton', - props: { - groupId: 'MeasurementTools', - isRadio: true, - primary: { - id: 'Length', - icon: 'tool-length', - label: 'Length', - type: 'tool', - commandOptions: { - toolName: 'Length', - } - }, - secondary: { - icon: 'chevron-down', - label: '', - isActive: true, - tooltip: 'More Measure Tools', - }, - items: [ - // Length tool - { - id: 'Length', - icon: 'tool-length', - label: 'Length', - type: 'tool', - commandOptions: { - toolName: 'Length', - } - }, - // Bidirectional tool - { - id: 'Bidirectional', - icon: 'tool-bidirectional', - label: 'Length', - type: 'tool', - commandOptions: { - toolName: 'Bidirectional', - } - }, - // Ellipse tool - { - id: 'EllipticalRoi', - icon: 'tool-elipse', - label: 'Ellipse', - type: 'tool', - commandOptions: { - toolName: 'EllipticalRoi', - } - }, - // Circle tool - { - id: 'CircleROI', - icon: 'tool-circle', - label: 'Circle', - type: 'tool', - commandOptions: { - toolName: 'CircleROI', - } - }, - ], - }, -} -``` - -
- -
- -## Layout Template - -Layout selector button and logic is also provided by the OHIF-v3 `default` -extension. To use it, you can just add the following definition to the list of -`toolDefinitions` - -![toolbarModule-layout](../../../assets/img/toolbarModule-layout.png) - -```js -{ - id: 'Layout', - type: 'ohif.layoutSelector', -} -``` - -
- -
- -## Custom Button - -You can also create your own extension, and add your new custom tool appearance -(e.g., split horizontally instead of vertically for split tool). Simply add -`getToolbarModule` to your extension, and pass your tool react component to its -`defaultComponent` property in the returned object. You can use `@ohif/ui` -components such as `IconButton, Icon, Tooltip, ToolbarButton` to build your own -component. - -```js -import myToolComponent from './myToolComponent'; - -export default function getToolbarModule({ commandsManager, servicesManager }) { - return [ - { - name: 'new-tool-type', - defaultComponent: myToolComponent, - clickHandler: () => {}, - }, - ]; -} -``` - -## Custom tool - -**I want to create a new tool** diff --git a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/viewport.md b/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/viewport.md deleted file mode 100644 index c3e07aa3464..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/extensions/modules/viewport.md +++ /dev/null @@ -1,96 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: Viewport ---- - -# Module: Viewport - -## Overview - -Viewports consume a displaySet and display/allow the user to interact with data. -An extension can register a Viewport Module by defining a `getViewportModule` -method that returns a React component. Currently, we use viewport components to -add support for: - -- 2D Medical Image Viewing (cornerstone ext.) -- Structured Reports as SR (DICOM SR ext.) -- Structured Reports as HTML (DICOM html ext.) -- Encapsulated PDFs as PDFs (DICOM pdf ext.) -- Whole Slide Microscopy Viewing (whole slide ext.) -- etc. - -The general pattern is that a mode can define which `Viewport` to use for which -specific `SOPClassHandlerUID`, so if you want to fork just a single Viewport -component for a specialized mode, this is possible. - -```jsx -// displaySet, viewportIndex, dataSource -const getViewportModule = () => { - const wrappedViewport = props => { - return ( - { - commandsManager.runCommand('commandName', data); - }} - /> - ); - }; - - return [{ name: 'example', component: wrappedViewport }]; -}; -``` - -## Example Viewport Component - -A simplified version of the tracked CornerstoneViewport is shown below, which -creates a cornerstone viewport and action bar on top of it. - -```jsx -function TrackedCornerstoneViewport({ - children, - dataSource, - displaySet, - viewportIndex, - servicesManager, - extensionManager, - commandsManager, -}) { - const renderViewport = () => { - const { component: Component } = extensionManager.getModuleEntry( - '@ohif/extension-cornerstone.viewportModule.cornerstone' - ); - return ( - - ); - }; - - return ( - <> - -
- {renderViewport()} -
- - ); -} -``` - -![viewportModule](../../../assets/img/viewportModule.png) - -### `@ohif/viewer` - -Viewport components are managed by the `ViewportGrid` Component. Which Viewport -component is used depends on: - -- Hanging Protocols -- The Layout Configuration -- Registered SopClassHandlers - -![viewportModule-layout](../../../assets/img/viewportModule-layout.png) - -
An example of three cornerstone Viewports
diff --git a/platform/docs/versioned_docs/version-3.0/platform/internationalization.md b/platform/docs/versioned_docs/version-3.0/platform/internationalization.md deleted file mode 100644 index 1bb32de5ba5..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/internationalization.md +++ /dev/null @@ -1,396 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: Internationalization ---- - -# Viewer: Internationalization - -OHIF supports internationalization using [i18next](https://www.i18next.com/) -through the npm package [@ohif/i18n](https://www.npmjs.com/package/@ohif/i18n), -where is the main instance of i18n containing several languages and tools. - -
- -## How to change language for the viewer? - -You can take a look into user manuals to see how to change the viewer's -language. In summary, you can change the language: - -- In the preference modals -- Using the language query in the URL: `lng=Test-LNG` - -## Installing - -```bash -yarn add @ohif/i18n - -# OR - -npm install --save @ohif/i18n -``` - -## How it works - -After installing `@ohif/i18n` npm package, the translation function -[t](https://www.i18next.com/overview/api#t) can be used [with](#with-react) or -[without](#without-react) React. - -A translation will occur every time a text match happens in a -[t](https://www.i18next.com/overview/api#t) function. - -The [t](https://www.i18next.com/overview/api#t) function is responsible for -getting translations using all the power of i18next. - -E.g. - -Before: - -```html -
my translated text
-``` - -After: - -```html -
{t('my translated text')}
-``` - -If the translation.json file contains a key that matches the HTML content e.g. -`my translated text`, it will be replaced automatically by the -[t](https://www.i18next.com/overview/api#t) function. - ---- - -### With React - -This section will introduce you to [react-i18next](https://react.i18next.com/) -basics and show how to implement the [t](https://www.i18next.com/overview/api#t) -function easily. - -#### Using Hooks - -You can use `useTranslation` hooks that is provided by `react-i18next` - -You can read more about this -[here](https://react.i18next.com/latest/usetranslation-hook). - -```js -import React from 'react'; -import { useTranslation } from 'react-i18next'; - -function MyComponent() { - const { t } = useTranslation(); - - return

{t('my translated text')}

; -} -``` - -### Using outside of OHIF viewer - -OHIF Viewer already sets a main -[I18nextProvider](https://react.i18next.com/latest/i18nextprovider) connected to -the shared i18n instance from `@ohif/i18n`, all extensions inside OHIF Viewer -will share this same provider at the end, you don't need to set new providers at -all. - -But, if you need to use it completely outside of OHIF viewer, you can set the -I18nextProvider this way: - -```jsx -import i18n from '@ohif/i18n'; -import { I18nextProvider } from 'react-i18next'; -import App from './App'; - - - -; -``` - -After setting `I18nextProvider` in your React App, all translations from -`@ohif/i18n` should be available following the basic [With React](#with-react) -usage. - ---- - -### Without React - -When needed, you can also use available translations _without React_. - -E.g. - -```js -import { T } from '@ohif/i18n'; -console.log(T('my translated text')); -console.log(T('$t(Common:Play) my translated text')); -``` - ---- - -## Main Concepts While Translating - -## Namespaces - -Namespaces are being used to organize translations in smaller portions, combined -semantically or by use. Each `.json` file inside `@ohif/i18n` npm package -becomes a new namespace automatically. - -- Buttons: All buttons translations -- CineDialog: Translations for the tool tips inside the Cine Player Dialog -- Common: all common jargons that can be reused like `t('$t(common:image)')` -- Header: translations related to OHIF's Header Top Bar -- MeasurementTable - Translations for the `@ohif/ui` Measurement Table -- UserPreferencesModal - Translations for the `@ohif/ui` Preferences Modal -- Modals - Translations available for other modals -- PatientInfo - Translations for patients info hover -- SidePanel - Translations for side panels -- ToolTip - Translations for tool tips - -### How to use another NameSpace inside the current NameSpace? - -i18next provides a parsing feature able to get translations strings from any -NameSpace, like this following example getting data from `Common` NameSpace: - -``` -$t('Common:Reset') -``` - -## Extending Languages in @ohif/i18n - -Sometimes, even using the same language, some nouns or jargons can change -according to the country, states or even from Hospital to Hospital. - -In this cases, you don't need to set an entire language again, you can extend -languages creating a new folder inside a pre existent language folder and -@ohif/i18n will do the hard work. - -This new folder must to be called with a double character name, like the `UK` in -the following file tree: - -```bash - |-- src - |-- locales - index.js - |-- en - |-- Buttons.json - index.js - | UK - |-- Buttons.js - indes.js - | US - |-- Buttons.js - index.js - ... -``` - -All properties inside a Namespace will be merged in the new sub language, e.g -`en-US` and `en-UK` will merge the props with `en`, using i18next's fallback -languages tool. - -You will need to export all Json files in your `index.js` file, mounting an -object like this: - -```js - { - en: { - NameSpace: { - keyWord1: 'keyWord1Translation', - keyWord2: 'keyWord2Translation', - keyWord3: 'keyWord3Translation', - } - }, - 'en-UK': { - NameSpace: { - keyWord1: 'keyWord1DifferentTranslation', - } - } - } -``` - -Please check the `index.js` files inside locales folder for an example of this -exporting structure. - -### Extending languages dynamically - -You have access to the i18next instance, so you can use the -[addResourceBundle](https://www.i18next.com/how-to/add-or-load-translations#add-after-init) -method to add and change language resources as needed. - -E.g. - -```js -import { i18n } from '@ohif/i18n'; -i18next.addResourceBundle('pt-BR', 'Buttons', { - Angle: 'Γ‚ngulo', -}); -``` - ---- - -### How to set a whole new language - -To set a brand new language you can do it in two different ways: - -- Opening a pull request for `@ohif/i18n` and sharing the translation with the - community. 😍 Please see [Contributing](#contributing-with-new-languages) - section for further information. - -- Setting it only in your project or extension: - -You'll need a final object like the following, what is setting French as -language, and send it to `addLocales` method. - -```js -const newLanguage = - { - fr: { - Commons: { - "Reset": "RΓ©initialiser", - "Previous": "PrΓ©cΓ©dent", - }, - Buttons: { - "Rectangle": "Rectangle", - "Circle": "Cercle", - } - } -``` - -To make it easier to translate, you can copy the .json files in the /locales -folder and theirs index.js exporters, keeping same keys and NameSpaces. -Importing the main index.js file, will provide you an Object as expected by the -method `addlocales`; - -E.g. of `addLocales` usage - -```js -import { addLocales } from '@ohif/i18n'; -import locales from './locales/index.js'; -addLocales(locales); -``` - -You can also set them manually, one by one, using this -[method](#extending-languages-dynamically). - ---- - -## Test Language - -We have created a test language that its translations can be seen in the locales -folder. You can copy paste the folder and its `.json` namespaces and add your -custom language translations. - -> If you apply the test-LNG you can see all the elements get appended with 'Test -> {}'. For instance `Study list` becomes `Test Study list`. - -## Language Detections - -@ohif/i18n uses -[i18next-browser-languageDetector](https://github.com/i18next/i18next-browser-languageDetector) -to manage detections, also exports a method called initI18n that accepts a new -detector config as parameter. - -### Changing the language - -OHIF Viewer accepts a query param called `lng` in the url to change the -language. - -E.g. - -``` -https://docs.ohif.org/demo/?lng=es-MX -``` - -### Language Persistence - -The user's language preference is kept automatically by the detector and stored -at a cookie called 'i18next', and in a localstorage key called 'i18nextLng'. -These names can be changed with a new -[Detector Config](https://github.com/i18next/i18next-browser-languageDetector). - -## Debugging translations - -There is an environment variable responsible for debugging the translations, -called `REACT_APP_I18N_DEBUG`. - -Run the project as following to get full debug information: - -```bash -REACT_APP_I18N_DEBUG=true yarn run dev -``` - -## Contributing with new languages - -We have integrated `i18next` into the OHIF Viewer and hooked it up with Locize -for translation management. Now we need your help to get the app translated into -as many languages as possible, and ensure that we haven't missed pieces of the -app that need translation. Locize has graciously offered to provide us with free -usage of their product. - -Once each crowd-sourcing project is completed, we can approve it and merge the -changes into the main project. At that point, the language will be immediately -available on https://viewer.ohif.org/ for testing, and can be used in any OHIF -project. We will support usage through both the Locize CDN and by copying the -language directly into the `@ohif/i18n` package, so that end users can serve the -content from their own domains. - -Here are a couple examples: - -Spanish: -https://viewer.ohif.org/viewer/1.2.840.113619.2.5.1762583153.215519.978957063.78?lng=es - -Chinese: -https://viewer.ohif.org/viewer/1.2.840.113619.2.5.1762583153.215519.978957063.78?lng=zh - -Portugese: -https://viewer.ohif.org/viewer/1.2.840.113619.2.5.1762583153.215519.978957063.78?lng=pt-BR - -Here are some links you can use to sign up to help translate. All you have to do -is sign up, translate the strings, and click Save. On our side, we have a -dashboard to see how many strings are translated and by whom. - -This is a pretty random set of languages, so please post below if you'd like a -new language link to be added: - -Languages: - -[French](https://www.locize.io/register?invitation=Nj8jRPaFKYwtIfNZ6Y5GVOJOpeiXNAdVuSiOg9ceaiveP6uF6y1wVXM9lgfKoYZX) - -[German](https://www.locize.io/register?invitation=gChNiVi66YINTPpbKESVAVYPapwg3DkpvMSSomLTvVqBJTXrdmPvxi0WZYHER11q) - -[Dutch](https://www.locize.io/register?invitation=2PGe7I184aN0cazM4GXMhzeLtGTf9Zen5uyOEFhHQ8vYkfKHkgR0mJ8dwbNlIeCG) - -[Turkish](https://www.locize.io/register?invitation=NOMIXsfneqPbFDqjce5wI7Z6p2swXSjc0rHOH4KLcM6qXSNA4LGyJaLxS7nqWAe3) - -[Chinese](https://www.locize.io/register?invitation=lrcUbt7DvV4aJmQeEA4SMAj5xNWr3rltOcaZW1cFc6eod0nvzSPFU4V383tDHGGn) - -[Japanese](https://www.locize.io/register?invitation=AaRq2S22o5FsxArwgVuw1gZcQjoe2ffyxarqlAXOpN7JnR2sf2mfamc5qV6LG1Mn) - -[Arabic](https://www.locize.io/register?invitation=BiqI6fOm1sC84N3YJLbImXmaOCk8Hc3TMGpXg7NH2R0b0OKuPCp9wlCHLoqMRpfQ) - -[Hindi](https://www.locize.io/register?invitation=ph7JmOGTV95DF3EFaI1kvK5Hx98dV9w2wj9h9UhUCWnkBNAwWEdWMcyjnF94zkWb) - -[Malay](https://www.locize.io/register?invitation=HsV9F5mKZyeUZYrC3XFRzNI2l0EsIh6hK0MUIKP8IYZA3GxuzfgkvWBLCFwCpDik) - -[Russian](https://www.locize.io/register?invitation=da4V9Q8DVO3M1FIlvfT50ZiS8NDNgvC0dE5hHUEAp47FXy6pLXmf1cp2lgLBfLmb) - -[Swedish](https://www.locize.io/register?invitation=uR4kzBZC1vhJe6jyMwYXgGPj84QDMulQRlt2s6rONU6ljUh5dgwuUyhJEtZ4REA3) - -[Italian](https://www.locize.io/register?invitation=viAS1NC5q342OxtuIv3JFX9DJ3KoR4SmGoElkBlRMphsDKt4hy9bW8JfBjHlfnd7) - -[Spanish](https://www.locize.io/register?invitation=ZikXW3KI4w4eo5Cf6L1aQMWaR69XAQ0a9Va3NGorH7mAPvEPXp8w8NLkPNLs5nG8) - -[Ukrainian](https://www.locize.io/register?invitation=TY0s6onqH3Asl05Bh1qB44SNSABL2pTYoturwxAmcNKRnzBZFK7bGfn7kVi23Vpg) - -[Vietnamese](https://www.locize.io/register?invitation=eqfHDm0vaqxGfQ5TGt6SeV0dx9b2dCp1RrMRdIRavqzOCOAfD3IElzUsyIT689cK) - -[Portugese-Brazil](https://www.locize.io/register?invitation=Qc5Dq449xbblQqLTpWeMfsyFiu3gACcgpj0EIucQjjs9Ph9pzPLpq3MnZupF9t6N) - -Don't see your language in the above list? Add a request -[here](https://github.com/OHIF/Viewers/issues/618) so that we can create the -language for your translation contribution. diff --git a/platform/docs/versioned_docs/version-3.0/platform/managers/_category_.json b/platform/docs/versioned_docs/version-3.0/platform/managers/_category_.json deleted file mode 100644 index 30940779278..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/managers/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Managers", - "position": 11 -} diff --git a/platform/docs/versioned_docs/version-3.0/platform/managers/commands.md b/platform/docs/versioned_docs/version-3.0/platform/managers/commands.md deleted file mode 100644 index fab666dacad..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/managers/commands.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: Commands Manager ---- -# Commands Manager - -## Overview - - -The `CommandsManager` is a class defined in the `@ohif/core` project. The Commands Manager tracks named commands (or functions) that are scoped to -a context. When we attempt to run a command with a given name, we look for it -in our active contexts. If found, we run the command, passing in any application -or call specific data specified in the command's definition. - -> Note: A single instance of `CommandsManager` should be defined in the consuming application, and it is used when constructing the `ExtensionManager`. - -A `simplified skeleton` of the `CommandsManager` is shown below: - -```js -export class CommandsManager { - constructor({ getActiveContexts } = {}) { - this.contexts = {}; - this._getActiveContexts = getActiveContexts; - } - - getContext(contextName) { - const context = this.contexts[contextName]; - return context; - } - - /**...**/ - - createContext(contextName) { - /** ... **/ - this.contexts[contextName] = {}; - } - - - registerCommand(contextName, commandName, definition) { - /**...**/ - const context = this.getContext(contextName); - /**...**/ - context[commandName] = definition; - } - - runCommand(commandName, options = {}, contextName) { - const definition = this.getCommand(commandName, contextName); - /**...**/ - const { commandFn } = definition; - const commandParams = Object.assign( - {}, - definition.options, // "Command configuration" - options // "Time of call" info - ); - /**...**/ - return commandFn(commandParams); - } - /**...**/ -} -``` - - - - -### Instantiating - -When we instantiate the `CommandsManager`, we are passing two methods: - -- `getAppState` - Should return the application's state when called (Not implemented in `v3`) -- `getActiveContexts` - Should return the application's active contexts when - called - -These methods are used internally to help determine which commands are currently -valid, and how to provide them with any state they may need at the time they are -called. - -```js title="platform/viewer/src/appInit.js" -const commandsManagerConfig = { - getAppState: () => {}, - /** Used by commands to determine active context */ - getActiveContexts: () => [ - 'VIEWER', - 'DEFAULT', - 'ACTIVE_VIEWPORT::CORNERSTONE', - ], -}; - -const commandsManager = new CommandsManager(commandsManagerConfig); -``` - - -## Commands/Context Registration -The `ExtensionManager` handles registering commands and creating contexts, so you don't need to register all your commands manually. Simply, create a `commandsModule` in your extension, and it will get automatically registered in the `context` provided. - -A *simplified version* of this registration is shown below to give an idea about the process. - - -```js -export default class ExtensionManager { - constructor({ commandsManager }) { - this._commandsManager = commandsManager - } - /** ... **/ - registerExtension = (extension, configuration = {}, dataSources = []) => { - let extensionId = extension.id - /** ... **/ - - // Register Modules provided by the extension - moduleTypeNames.forEach((moduleType) => { - const extensionModule = this._getExtensionModule( - moduleType, - extension, - extensionId, - configuration - ) - - if (moduleType === 'commandsModule') { - this._initCommandsModule(extensionModule) - } - /** registering other modules **/ - }) - } - - _initCommandsModule = (extensionModule) => { - let { definitions, defaultContext } = extensionModule - defaultContext = defaultContext || 'VIEWER' - - if (!this._commandsManager.getContext(defaultContext)) { - this._commandsManager.createContext(defaultContext) - } - - Object.keys(definitions).forEach((commandName) => { - const commandDefinition = definitions[commandName] - const commandHasContextThatDoesNotExist = - commandDefinition.context && - !this._commandsManager.getContext(commandDefinition.context) - - if (commandHasContextThatDoesNotExist) { - this._commandsManager.createContext(commandDefinition.context) - } - - this._commandsManager.registerCommand( - commandDefinition.context || defaultContext, - commandName, - commandDefinition - ) - }) - } -} - -``` - - -If you find yourself in a situation where you want to register a command/context manually, ask -yourself "why can't I register these commands via an extension?", but if you insist, you can use the `CommandsManager` API to do so: - -```js -// Command Registration -commandsManager.registerCommand('context', 'name', commandDefinition); - -// Context Creation -commandsManager.createContext('string'); -``` - -## `CommandsManager` Public API - -If you would like to run a command in the consuming app or an extension, you can -use `runCommand(commandName, options = {}, contextName)`. - - -```js -// Run a command, it will run all the `speak` commands in all contexts -commandsManager.runCommand('speak', { command: 'hello' }); - -// Run command, from Default context -commandsManager.runCommand('speak', { command: 'hello' }, ['DEFAULT']); - -// Returns all commands for a given context -commandsManager.getContext('string'); -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/managers/extension.md b/platform/docs/versioned_docs/version-3.0/platform/managers/extension.md deleted file mode 100644 index 9fb5196f840..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/managers/extension.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: Extension Manager ---- - -# Extension Manager - -## Overview - -The `ExtensionManager` is a class made available to us via the `@ohif/core` -project (platform/core). Our application instantiates a single instance of it, -and provides a `ServicesManager` and `CommandsManager` along with the -application's configuration through the appConfig key (optional). - -```js -const commandsManager = new CommandsManager(); -const servicesManager = new ServicesManager(); -const extensionManager = new ExtensionManager({ - commandsManager, - servicesManager, - appConfig, -}); -``` - -The `ExtensionManager` only has a few public members: - -- `setActiveDataSource` - Sets the active data source for the application -- `getDataSources` - Returns the registered data sources -- `getActiveDataSource` - Returns the currently active data source -- `getModuleEntry` - Returns the module entry by the give id. - -## Accessing Modules - -We use `getModuleEntry` in our `ViewerLayout` logic to find the panels based on -the provided IDs in the mode's configuration. - -For instance: -`extensionManager.getModuleEntry("@ohif/extension-measurement-tracking.panelModule.seriesList")` -accesses the `seriesList` panel from `panelModule` of the -`@ohif/extension-measurement-tracking` extension. - -```js -const getPanelData = id => { - const entry = extensionManager.getModuleEntry(id); - const content = entry.component; - - return { - iconName: entry.iconName, - iconLabel: entry.iconLabel, - label: entry.label, - name: entry.name, - content, - }; -}; -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/managers/hotkeys.md b/platform/docs/versioned_docs/version-3.0/platform/managers/hotkeys.md deleted file mode 100644 index ebdd2bd1334..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/managers/hotkeys.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: Hotkeys Manager ---- -# Hotkeys Managers - -## Overview -`HotkeysManager` handles all the logics for adding, setting and enabling/disabling -the hotkeys. - - - -## Instantiation -`HotkeysManager` is instantiated in the `appInit` similar to the other managers. - -```js -const commandsManager = new CommandsManager(commandsManagerConfig); -const servicesManager = new ServicesManager(commandsManager); -const hotkeysManager = new HotkeysManager(commandsManager, servicesManager); -const extensionManager = new ExtensionManager({ - commandsManager, - servicesManager, - hotkeysManager, - appConfig, -}); -``` - - - - -## Hotkeys Manager API - -- `setHotkeys`: The most important method in the `HotkeysManager` which binds the keys with commands. -- `setDefaultHotKeys`: set the defaultHotkeys **property**. Note that, this method **does not** bind the provided hotkeys; however, when `restoreDefaultBindings` -is called, the provided defaultHotkeys will get bound. -- `destroy`: reset the HotkeysManager, and remove the set hotkeys and empty out the `defaultHotkeys` - - - -## Structure of a Hotkey Definition -A hotkey definition should have the following properties: - -- `commandName`: name of the registered command -- `commandOptions`: extra arguments to the commands -- `keys`: an array defining the key to get bound to the command -- `label`: label to be shown in the hotkeys preference panel -- `isEditable`: whether the key can be edited by the user in the hotkey panel - - -### Default hotkeysBindings -The default key bindings can be find in `hotkeyBindings.js` - -```js -// platform/core/src/defaults/hotkeyBindings.js - -export default [ - /**..**/ - { - commandName: 'setToolActive', - commandOptions: { toolName: 'Zoom' }, - label: 'Zoom', - keys: ['z'], - isEditable: true, - }, - - { - commandName: 'flipViewportHorizontal', - label: 'Flip Vertically', - keys: ['v'], - isEditable: true, - }, - /**..**/ -] -``` - - -## Behind the Scene -When you `setHotkeys`, the `commandName` gets registered with the `commandsManager` and -get run after the key is pressed. diff --git a/platform/docs/versioned_docs/version-3.0/platform/managers/index.md b/platform/docs/versioned_docs/version-3.0/platform/managers/index.md deleted file mode 100644 index ee6d6b2fc8c..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/managers/index.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Introduction ---- - -# Managers - -## Overview - -`OHIF` uses `Managers` to accomplish various purposes such as registering new -services, dependency injection, and aggregating and exposing `extension` -features. - -`OHIF-v3` provides the following managers which we will discuss in depth. - - - - - - - - - - - - - - - - - - - - - - - - - - -
ManagerDescription
- - Extension Manager - - - Aggregating and exposing modules and features through out the app -
- - Services Manager - - - Single point of registration for all internal and external services -
- - Commands Manager - - - Register commands with specific context and run commands in the app -
- - Hotkeys Manager - - - For keyboard keys assignment to commands -
- - - - - -[core-services]: https://github.com/OHIF/Viewers/tree/master/platform/core/src/services -[services-manager]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/services/ServicesManager.js -[cross-cutting-concerns]: https://en.wikipedia.org/wiki/Cross-cutting_concern - diff --git a/platform/docs/versioned_docs/version-3.0/platform/managers/service.md b/platform/docs/versioned_docs/version-3.0/platform/managers/service.md deleted file mode 100644 index 2cacda412e8..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/managers/service.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: Service Manager ---- - -# Services Manager - -## Overview - -Services manager is the single point of service registration. Each service needs -to implement a `create` method which gets called inside `ServicesManager` to -instantiate the service. In the app, you can get access to a registered service -via the `services` property of the `ServicesManager`. - -## Skeleton - -_Simplified_ skeleton of `ServicesManager` is shown below. There are two public -methods: - -- `registerService`: registering a new service with/without a configuration -- `registerServices`: registering batch of services - -```js -export default class ServicesManager { - constructor(commandsManager) { - this._commandsManager = commandsManager; - this.services = {}; - this.registeredServiceNames = []; - } - - registerService(service, configuration = {}) { - /** validation checks **/ - this.services[service.name] = service.create({ - configuration, - commandsManager: this._commandsManager, - }); - - /* Track service registration */ - this.registeredServiceNames.push(service.name); - } - - registerServices(services) { - /** ... **/ - } -} -``` - -## Default Registered Services - -By default, `OHIF-v3` registers the following services in the `appInit`. - -```js title="platform/viewer/src/appInit.js" -servicesManager.registerServices([ - UINotificationService, - UIModalService, - UIDialogService, - UIViewportDialogService, - MeasurementService, - DisplaySetService, - ToolBarService, - ViewportGridService, - HangingProtocolService, - CineService, -]); -``` - -## Service Architecture - -If you take a look at the folder of each service implementation above, you will -find out that services need to be exported as an object with `name` and `create` -method. - -For instance, `ToolBarService` is exported as: - -```js title="platform/core/src/services/ToolBarService/index.js" -import ToolBarService from './ToolBarService'; - -export default { - name: 'ToolBarService', - create: ({ configuration = {}, commandsManager }) => { - return new ToolBarService(commandsManager); - }, -}; -``` - -and the implementation of `ToolBarService` lies in the same folder at -`./ToolbarSerivce.js`. - -> Note, the create method is critical for any custom service that you write and -> want to add to the list of services - -## Accessing Services - -Throughout the app you can use `services` property of the service manager to -access the desired service. - -For instance in the `PanelMeasurementTableTracking` which is the right panel in -the `longitudinal` mode, we have the _simplified code below_ for downloading the -drawn measurements. - -```js -function PanelMeasurementTableTracking({ servicesManager }) { - const { MeasurementService } = servicesManager.services; - /** ... **/ - - async function exportReport() { - const measurements = MeasurementService.getMeasurements(); - /** ... **/ - downloadCSVReport(measurements, MeasurementService); - } - - /** ... **/ - return <> /** ... **/ ; -} -``` - -## Registering Custom Services - -You might need to write you own custom service in an extension. -`preRegistration` hook inside your extension is the place for registering your -custom service. - -```js title="extensions/customExtension/src/index.js" -import WrappedBackEndService from './services/backEndService'; - -export default { - // ID of the extension - id: 'myExtension', - preRegistration({ servicesManager }) { - servicesManager.registerService(WrappedBackEndService(servicesManager)); - }, -}; -``` - -and the logic for your service shall be - -```js title="extensions/customExtension/src/services/backEndService/index.js" -import backEndService from './backEndService'; - -export default function WrappedBackEndService(serviceManager) { - return { - name: 'myService', - create: ({ configuration = {} }) => { - return new backEndService(serviceManager); - }, - }; -} -``` - -with implementation of - -```js -export default class backEndService { - constructor(serviceManager) { - this.serviceManager = serviceManager; - } - - putAnnotations() { - return post(/*...*/); - } -} -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/modes/_category_.json b/platform/docs/versioned_docs/version-3.0/platform/modes/_category_.json deleted file mode 100644 index 80702b9e54e..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/modes/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Modes", - "position": 10 -} diff --git a/platform/docs/versioned_docs/version-3.0/platform/modes/index.md b/platform/docs/versioned_docs/version-3.0/platform/modes/index.md deleted file mode 100644 index b01049b0f19..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/modes/index.md +++ /dev/null @@ -1,383 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Introduction ---- - -# Modes - -## Overview - -A mode can be thought of as a viewer app configured to perform a specific task, -such as tracking measurements over time, 3D segmentation, a guided radiological -workflow, etc. Addition of modes enables _application_ with many _applications_ -as each mode become a mini _app configuration_ behind the scene. - -Upon initialization the viewer will consume extensions and modes and build up -the route desired, these can then be accessed via the study list, or directly -via url parameters. - - - -OHIF-v3 architecture can be seen in the following: - -![mode-archs](../../assets/img/mode-archs.png) - -> Note: Templates are now a part of β€œextensions” Routes are configured by modes -> and/or app - -As mentioned, modes are tied to a specific route in the viewer, and multiple -modes/routes can be present within a single application. This allows for -tremendously more flexibility than before you can now: - -- Simultaneously host multiple viewers with for different use cases from within - the same app deploy. -- Make radiological viewers for specific purposes/workflows, e.g.: - - Tracking the size of lesions over time. - - PET/CT fusion workflows. - - Guided review workflows optimized for a specific clinical trial. -- Still host one single feature-rich viewer if you desire. - -## Anatomy - -A mode configuration has a `route` name which is dynamically transformed into a -viewer route on initialization of the application. Modes that are available to a -study will appear in the study list. - -![user-study-summary](../../assets/img/user-study-summary.png) - -The mode configuration specifies which `extensions` the mode requires, which -`LayoutTemplate` to use, and what props to pass to the template. For the default -template this defines which `side panels` will be available, as well as what -`viewports` and which `displaySets` they may hang. - -Mode's config is composed of three elements: -- `id`: the mode `id` -- `modeFactory`: the function that returns the mode specific configuration -- `extensionDependencies`: the list of extensions that the mode requires - - -that return a config object with certain -properties, the high-level view of this config object is: - -```js title="modes/example/src/index.js" -function modeFactory() { - return { - id: '', - version: '', - displayName: '', - onModeEnter: () => {}, - onModeExit: () => {}, - validationTags: {}, - isValidMode: () => {}, - routes: [ - { - path: '', - init: () => {}, - layoutTemplate: () => {}, - }, - ], - extensions: extensionDependencies, - hangingProtocol: [], - sopClassHandlers: [], - hotkeys: [], - }; -} - -const mode = { - id, - modeFactory, - extensionDependencies, -}; - -export default mode; -``` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PropertyDescription
- id - unique mode id used to refer to the mode
- displayName - actual name of the mode being displayed for each study in the study summary panel
- - onModeEnter - - hook is called when the mode is entered by the specified route
- - onModeExit - - hook is called when the mode exited
- - validationTags - - validationTags
- - isValidMode - - Checks if the mode is valid for a study
- - routes - - route config which defines the route address, and the layout for it
- - extensionDependencies - - extensions needed by the mode
- - hanging protocol - - list of hanging protocols that the mode should have access to
- - sopClassHandlers - - list of SOPClass modules needed by the mode
- - hotkeys - - hotkeys
- -### Consuming Extensions - -As mentioned in the [Extensions](../extensions/index.md) section, in `OHIF-v3` -developers write their extensions to create re-usable functionalities that later -can be used by `modes`. Now, it is time to describe how the registered -extensions will get utilized for a workflow mode via its `id`. - -Each `mode` has a list of its `extensions dependencies` which are the -the `extension` name and version number. In addition, to use a module element you can use the -`${extensionId}.${moduleType}.${element.name}` schema. For instance, if a mode -requires the left panel with name of `AIPanel` that is added by the -`myAIExtension` via the following `getPanelModule` code, it should address it as -`myAIExtension.panelModule.AIPanel` inside the mode configuration file. In the -background `OHIF` will handle grabbing the correct panel via `ExtensionManager`. - -```js title="extensions/myAIExtension/getPanelModule.js" -import PanelAI from './PanelAI.js'; - -function getPanelModule({ - commandsManager, - extensionManager, - servicesManager, -}) { - const wrappedAIPanel = () => { - return ( - - ); - }; - - return [ - { - name: 'AIPanel', - iconName: 'list-bullets', - iconLabel: '', - label: 'AI Panel', - isDisabled: studies => {}, // optional - component: wrappedAIPanel, - }, - ]; -} -``` - -Now, let's look at a simplified code of the `basic viewer` mode which consumes various functionalities -from different extensions. - -```js - -const extensionDependencies = { - '@ohif/extension-default': '^3.0.0', - '@ohif/extension-cornerstone': '^3.0.0', - '@ohif/extension-measurement-tracking': '^3.0.0', -}; - -const id = 'viewer'; -const version = '3.0.0'; - -function modeFactory({ modeConfiguration }) { - return { - id, - // ... - routes: [ - { - // ... - layoutTemplate: ({ location, servicesManager }) => { - return { - id: ohif.layout, - props: { - leftPanels: ['@ohif/extension-measurement-tracking.panelModule.seriesList'], - rightPanels: ['@ohif/extension-measurement-tracking.panelModule.trackedMeasurements'], - viewports: [ - { - namespace: '@ohif/extension-measurement-tracking.viewportModule.cornerstone-tracked', - displaySetsToDisplay: ['@ohif/extension-default.sopClassHandlerModule.stack'], - }, - ], - }, - }; - }, - }, - ], - extensions: extensionDependencies, - hangingProtocol: ['@ohif/extension-default.hangingProtocolModule.petCT'], - sopClassHandlers: ['@ohif/extension-default.sopClassHandlerModule.stack'], - // ... - }; -} - -const mode = { - id, - modeFactory, - extensionDependencies, -} - -export default mode -``` - -### Routes - -routes config is an array of route settings, and the overall look and behavior -of the viewer at the designated route is defined by the `layoutTemplate` and -`init` functions for the route. We will learn more about each of the above -properties inside the [route documentation](./routes.md) - - -### HangingProtocols - -Currently, you can pass your defined hanging protocols inside the -`hangingProtocols` property of the mode's config. This will get registered -inside `HangingProtocolService`. - -### SopClassHandlers - -Mode's configuration also accepts the `sopClassHandler` modules that have been -added by the extensions. This information will get used to initialize `DisplaySetService` with the provided SOPClass modules which -handles creation of the displaySets. - - -### Hotkeys - -`hotkeys` is another property in the configuration of a mode that can be defined -to add the specific hotkeys to the viewer at all routes. - -```js -// default hotkeys -import { utils } from '@ohif/ui'; - -const { hotkeys } = utils; - -const myHotkeys = [ - { - commandName: 'setToolActive', - commandOptions: { toolName: 'Zoom' }, - label: 'Zoom', - keys: ['z'], - isEditable: true, - }, - { - commandName: 'scaleUpViewport', - label: 'Zoom In', - keys: ['+'], - isEditable: true, - }, -] - -function modeFactory() { - return { - id: '', - id: '', - displayName: '', - /* - ... - */ - hotkeys: [..hotkeys.defaults.hotkeyBindings, ...myHotkeys], - } -} - -// exports -``` - -## Registration - -Similar to extension registration, `viewer` will look inside the `pluginConfig.json` to -find the `modes` to register. - - -```js title=platform/viewer/pluginConfig.json -// Simplified version of the `pluginConfig.json` file -{ - "extensions": [ - { - "packageName": "@ohif/extension-cornerstone", - "version": "3.0.0" - }, - // ... - ], - "modes": [ - { - "packageName": "@ohif/mode-longitudinal", - "version": "0.0.1" - } - ] -} -``` - -:::note Important -You SHOULD NOT directly register modes in the `pluginConfig.json` file. -Use the provided `cli` to add/remove/install/uninstall modes. Read more [here](../../development/ohif-cli.md) -::: - -The final registration and import of the modes happen inside a non-tracked file `pluginImport.js` (this file is also for internal use only). diff --git a/platform/docs/versioned_docs/version-3.0/platform/modes/installation.md b/platform/docs/versioned_docs/version-3.0/platform/modes/installation.md deleted file mode 100644 index 08c456d29e1..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/modes/installation.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: Installation ---- - -# Modes: Installation - -OHIF-v3 provides the ability to utilize external modes. - - -You can use ohif `cli` tool to install both local and publicly published -modes on NPM. You can read more [here](../../development/ohif-cli.md) diff --git a/platform/docs/versioned_docs/version-3.0/platform/modes/lifecycle.md b/platform/docs/versioned_docs/version-3.0/platform/modes/lifecycle.md deleted file mode 100644 index 32ea77cb352..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/modes/lifecycle.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: Lifecycle Hooks ---- - -# Modes: Lifecycle Hooks - -## Overview - -Currently, there are two hooks that are called for modes: - -- onModeEnter -- onModeExit - -## onModeEnter - -This hook gets run after the defined route has been entered by the mode. This -hook can be used to initialize the data, services and appearance of the viewer -upon the first render. - -For instance, in `longitudinal` mode we are using this hook to initialize the -`ToolBarService` and set the window level/width tool to be active and add -buttons to the toolbar. - -```js -function modeFactory() { - return { - id: '', - version: '', - displayName: '', - onModeEnter: ({ servicesManager, extensionManager }) => { - const { ToolBarService } = servicesManager.services; - - const interaction = { - groupId: 'primary', - itemId: 'WindowLevel', - interactionType: 'tool', - commandOptions: undefined, - }; - - ToolBarService.recordInteraction(interaction); - - ToolBarService.init(extensionManager); - ToolBarService.addButtons(toolbarButtons); - ToolBarService.createButtonSection('primary', [ - 'MeasurementTools', - 'Zoom', - 'WindowLevel', - 'Pan', - 'Capture', - 'Layout', - 'MoreTools', - ]); - }, - /* - ... - */ - }; -} -``` - -## onModeExit - -This hook is called when the viewer navigate away from the route in the url. -This is the place for cleaning up data, and services by unsubscribing to the -events. - -For instance, it can be used to reset the `ToolBarService` which reset the -toggled buttons. - -```js -function modeFactory() { - return { - id: '', - displayName: '', - onModeExit: ({ servicesManager, extensionManager }) => { - // Turn of the toggled states on exit - const { ToolBarService } = servicesManager.services; - ToolBarService.reset(); - }, - /* - ... - */ - }; -} -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/modes/routes.md b/platform/docs/versioned_docs/version-3.0/platform/modes/routes.md deleted file mode 100644 index 2204bd77ae7..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/modes/routes.md +++ /dev/null @@ -1,315 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: Routes ---- - -# Mode: Routes - -## Overview - -Modes are tied to a specific route in the viewer, and multiple modes/routes can -be present within a single application. This makes `routes` config, THE most -important part of the mode configuration. - -## Route - -`@ohif/viewer` **compose** extensions to build applications on different routes -for the platform. - -Below, you can see a simplified version of the `longitudinal` mode and the -`routes` section which has defined one `route`. Each route has three different -configuration: - -- **route path**: defines the route path to access the built application for - that route -- **route init**: hook that runs when application enters the defined route path, - if not defined the default init function will run for the mode. -- **route layout**: defines the layout of the application for the specified - route (panels, viewports) - -```js -function modeFactory() { - return { - id: 'viewer', - version: '3.0.0', - displayName: '', - routes: [ - { - path: 'longitudinal', - /*init: ({ servicesManager, extensionManager }) => { - //defaultViewerRouteInit - },*/ - layoutTemplate: ({ location, servicesManager }) => { - return { - id: ohif.layout, - props: { - leftPanels: [ - '@ohif/extension-measurement-tracking.panelModule.seriesList', - ], - rightPanels: [ - '@ohif/extension-measurement-tracking.panelModule.trackedMeasurements', - ], - viewports: [ - { - namespace: - '@ohif/extension-measurement-tracking.viewportModule.cornerstone-tracked', - displaySetsToDisplay: [ - '@ohif/extension-default.sopClassHandlerModule.stack', - ], - }, - { - namespace: '@ohif/extension-cornerstone-dicom-sr.viewportModule.dicom-sr', - displaySetsToDisplay: [ - '@ohif/extension-cornerstone-dicom-sr.sopClassHandlerModule.dicom-sr', - ], - }, - ], - }, - }; - }, - }, - ], - /* - ... - */ - }; -} -``` - -### Route: path - -Upon initialization the viewer will consume extensions and modes and build up -the route desired, these can then be accessed via the study list, or directly -via url parameters. - -> Note: Currently, only one route is built for each mode, but we will enhance -> route creation to create separate routes based on the `path` config for each -> `route` object. - -There are two types of `routes` that are created by the mode. - -- Routes with dataSourceName `/${mode.id}/${dataSourceName}` -- Routes without dataSourceName `/${mode.id}` - -Therefore, navigating to -`http://localhost:3000/viewer/?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1` -will run the app with the layout and functionalities of the `viewer` mode using -the `defaultDataSourceName` which is defined in the -[App Config](../../configuration/index.md) - -You can use the same exact mode using a different registered data source (e.g., -`dicomjson`) by navigating to -`http://localhost:3000/viewer/dicomjson/?StudyInstanceUIDs=1.3.6.1.4.1.25403.345050719074.3824.20170125113417.1` - -### Route: init - -The mode also has an init hook, which initializes the mode. If you don't define -an `init` function the `default init` function will get run (logic is located -inside `Mode.jsx`). However, you can define you own init function following -certain steps which we will discuss next. - -#### Default init - -Default init function will: - -- `retriveSeriesMetaData` for the `studyInstanceUIDs` that are defined in the - URL. -- Subscribe to `instanceAdded` event, to make display sets after a series have - finished retrieving its instances' metadata. -- Subscribe to `seriesAdded` event, to run the `HangingProtocolService` on the - retrieves series from the study. - -A _simplified_ "pseudocode" for the `defaultRouteInit` is: - -```jsx -async function defaultRouteInit({ - servicesManager, - studyInstanceUIDs, - dataSource, -}) { - const { - DisplaySetService, - HangingProtocolService, - } = servicesManager.services; - - // subscribe to run the function after the event happens - DicomMetadataStore.subscribe( - 'instancesAdded', - ({ StudyInstanceUID, SeriesInstanceUID }) => { - const seriesMetadata = DicomMetadataStore.getSeries( - StudyInstanceUID, - SeriesInstanceUID - ); - DisplaySetService.makeDisplaySets(seriesMetadata.instances); - } - ); - - studyInstanceUIDs.forEach(StudyInstanceUID => { - dataSource.retrieve.series.metadata({ StudyInstanceUID }); - }); - - DicomMetadataStore.subscribe('seriesAdded', ({ StudyInstanceUID }) => { - const studyMetadata = DicomMetadataStore.getStudy(StudyInstanceUID); - HangingProtocolService.run(studyMetadata); - }); - - return unsubscriptions; -} -``` - -#### Writing a custom init - -You can add your custom init function to enhance the default initialization for: - -- Fetching annotations from a server for the current study -- Changing the initial image index of the series to be displayed at first -- Caching the next study in the work list -- Adding a custom sort for the series to be displayed on the study browser panel - -and lots of other modifications. - -You just need to make sure, the mode `dataSource.retrieve.series.metadata`, -`makeDisplaySets` and `run` the HangingProtocols at some point. There are -various `events` that you can subscribe to and add your custom logic. **point to -events** - -For instance for jumping to the slice where a measurement is located at the -initial render, you need to follow a pattern similar to the following: - -```jsx -init: async ({ - servicesManager, - extensionManager, - hotkeysManager, - dataSource, - studyInstanceUIDs, -}) => { - const { DisplaySetService } = servicesManager.services; - - /** - ... - **/ - - const onDisplaySetsAdded = ({ displaySetsAdded, options }) => { - const displaySet = displaySetsAdded[0]; - const { SeriesInstanceUID } = displaySet; - - const toolData = myServer.fetchMeasurements(SeriesInstanceUID); - - if (!toolData.length) { - return; - } - - toolData.forEach(tool => { - const instance = displaySet.images.find( - image => image.SOPInstanceUID === tool.SOPInstanceUID - ); - }); - - MeasurementService.addMeasurement(/**...**/); - }; - - // subscription to the DISPLAY_SETS_ADDED - const { unsubscribe } = DisplaySetService.subscribe( - DisplaySetService.EVENTS.DISPLAY_SETS_ADDED, - onDisplaySetsAdded - ); - - /** - ... - **/ - - return unsubscriptions; -}; -``` - -### Route: layoutTemplate - -`layoutTemplate` is the last configuration for a certain route in a `mode`. -`layoutTemplate` is a function that returns an object that configures the -overall layout of the application. The returned object has two properties: - -- `id`: the id of the `layoutTemplate` being used (it should have been - registered via an extension) -- `props`: the required properties to be passed to the `layoutTemplate`. - -For instance `default extension` provides a layoutTemplate that builds the app -using left/right panels and viewports. Therefore, the `props` include -`leftPanels`, `rightPanels` and `viewports` sections. Note that the -`layoutTemplate` defines the properties it is expecting. So, if you write a -`layoutTemplate-2` that accepts a footer section, its logic should be written in -the extension, and any mode that is interested in using `layoutTemplate-2` -**should** provide the `id` for the footer component. - -**What module should the footer be registered?** - -```js -/* -... -*/ -layoutTemplate: ({ location, servicesManager }) => { - return { - id: '@ohif/extension-default.layoutTemplateModule.viewerLayout', - props: { - leftPanels: [ - 'myExtension.panelModule.leftPanel1', - 'myExtension.panelModule.leftPanel2', - ], - rightPanels: ['myExtension.panelModule.rightPanel'], - viewports: [ - { - namespace: 'myExtension.viewportModule.viewport1', - displaySetsToDisplay: ['myExtension.sopClassHandlerModule.sop1'], - }, - { - namespace: 'myExtension.viewportModule.viewport2', - displaySetsToDisplay: ['myExtension.sopClassHandlerModule.sop2'], - }, - ], - }, - }; -}; -/* -... -*/ -``` - -## FAQ - -> What is the difference between `onModeEnter` and `route.init` - -`onModeEnter` gets run first than `route.init`; however, each route can have -their own `init`, but they share the `onModeEnter`. - -> How can I change the `workList` appearance or add a new login page? - -This is where `OHIF-v3` shines! Since the default `layoutTemplate` is written -for the viewer part, you can simply add a new `layoutTemplate` and use the -component you have written for that route. `Mode` handle showing the correct -component for the specified route. - -```js -function modeFactory() { - return { - id: 'viewer', - displayName: '', - routes: [ - { - path: 'worklist', - init, - layoutTemplate: ({ location, servicesManager }) => { - return { - id: 'worklistLayout', - props: { - component: 'myNewWorkList', - }, - }; - }, - }, - ], - /* - ... - */ - }; -} -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/modes/validity.md b/platform/docs/versioned_docs/version-3.0/platform/modes/validity.md deleted file mode 100644 index e3f70af7668..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/modes/validity.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: Validity ---- -# Mode: Validity - - -## Overview -There are two mechanism for checking the validity of a mode for a study. - -- `isValidMode`: which is called on a selected study in the workList. -- `validTags` - - - -## isValidMode -This hook can be used to define a function that return a `boolean` which decided the -validity of the mode based on `StudyInstanceUID` and `modalities` that are in the study. - -For instance, for pet-ct mode, both `PT` and 'CT' modalities should be available inside the study. - -```js -function modeFactory() { - return { - id: '', - displayName: '', - isValidMode: ({ modalities, StudyInstanceUID }) => { - const modalities_list = modalities.split('\\'); - const validMode = ['CT', 'PT'].every(modality => modalities_list.includes(modality)); - return validMode; - }, - /* - ... - */ - } -} -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/pwa-vs-packaged.md b/platform/docs/versioned_docs/version-3.0/platform/pwa-vs-packaged.md deleted file mode 100644 index bdc411e6cb1..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/pwa-vs-packaged.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -sidebar_position: 3 ---- - -# PWA vs Packaged - -It's important to know that the OHIF Viewer project provides two different build -processes: - -```bash -# Static Asset output: For deploying PWAs -yarn run build -``` - -## Progressive Web Application (PWA) - -> [Progressive Web Apps][pwa] are a new breed of web applications that meet the -> [following requirements][pwa-checklist]. Notably, targeting a PWA allows us -> provide a reliable, fast, and engaging experience across different devices and -> network conditions. - -The OHIF Viewer is maintained as a [monorepo][monorepo]. We use WebPack to build -the many small static assets that comprise our application. Also generated is an -`index.html` that will serve as an entry point for loading configuration and the -application, as well as a `service-worker` that can intelligently cache files so -that subsequent requests are from the local file system instead of over the -network. - -You can read more about this particular strategy in our -[Build for Production Deployment Guide](./../deployment/build-for-production.md) - -## Commonjs Bundle (Packaged Script) - -We are not supporting `Commonjs` bundling inside `OHIF-v3`. diff --git a/platform/docs/versioned_docs/version-3.0/platform/scope-of-project.md b/platform/docs/versioned_docs/version-3.0/platform/scope-of-project.md deleted file mode 100644 index 4ac68daa60e..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/scope-of-project.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -sidebar_position: 1 ---- -# Scope of Project - -The OHIF Viewer is a web based medical imaging viewer. This allows it to be used -on almost any device, anywhere. The OHIF Viewer is what is commonly referred to -as a ["Dumb Client"][simplicable] - -> A dumb client is software that fully depends on a connection to a server or -> cloud service for its functionality. Without a network connection, the -> software offers nothing useful. - [simplicable.com][simplicable] - -While the Viewer persists some data, it's scope is limited to caching things -like user preferences and previous query parameters. Because of this, the Viewer -has been built to be highly configurable to work with almost any web accessible -data source. - -![scope-of-project diagram](./../assets/img/scope-of-project.png) - -To be more specific, the OHIF Viewer is a collection of HTML, JS, and CSS files. -These can be delivered to your end users however you would like: - -- From the local network -- From a remote web server -- From a CDN (content delivery network) -- From a service-worker's cache -- etc. - -These "static asset" files are referred to collectively as a "Progressive Web -Application" (PWA), and have the same capabilities and limitations that all PWAs -have. - -All studies, series, images, imageframes, metadata, and the images themselves -must come from an external source. There are many, many ways to provide this -information, the OHIF Viewer's scope **DOES NOT** encompass providing _any_ -data; only the configuration necessary to interface with one or more of these -many data sources. The OHIF Viewer's scope **DOES** include configuration and -support for services that are protected with OpenID-Connect. - -In an effort to aid our users and contributors, we attempt to provide several -[deployment and hosting recipes](./deployment/index.md) as potential starting -points. These are not meant to be rock solid, production ready, solutions; like -most recipes, they should be augmented to best fit you and your organization's -taste, preferences, etc. - -## FAQ - -_Am I able to cache studies for offline viewing?_ - -Not currently. A web page's offline cache capabilities are limited and somewhat -volatile (mostly imposed at the browser vendor level). For more robust offline -caching, you may want to consider a server on the local network, or packaging -the OHIF Viewer as a desktop application. - -_Does the OHIF Viewer work with the local filesystem?_ - -It is possible to accomplish this through extensions; however, for a user -experience that accommodates a large number of studies, you would likely need to -package the OHIF Viewer as an [Electron app][electron]. - - - - -[simplicable]: https://simplicable.com/new/dumb-client -[electron]: https://electronjs.org/ - diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/_category_.json b/platform/docs/versioned_docs/version-3.0/platform/services/_category_.json deleted file mode 100644 index 8b57449b24d..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Services", - "position": 12 -} diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/data/DicomMetadataStore.md b/platform/docs/versioned_docs/version-3.0/platform/services/data/DicomMetadataStore.md deleted file mode 100644 index 927b8b8e541..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/data/DicomMetadataStore.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: DICOM Metadata Store ---- -# DICOM Metadata Store - - -## Overview -`DicomMetaDataStore` is the central location that stores the metadata in `OHIF-v3`. There -are several APIs to add study/series/instance metadata and also for getting from the store. -DataSource utilize the `DicomMetaDataStore` to add the retrieved metadata to `OHIF Viewer`. - -> In `OHIF-v3` we have significantly changed the architecture of the metadata storage to -> provide a much cleaner way of handling metadata-related tasks and services. Classes such as -> `OHIFInstanceMetadata`, `OHIFSeriesMetadata` and `OHIFStudyMetadata` has been removed and -> replaced with `DicomMetaDataStore`. -> - - -## Events -There are two events that get publish in `DicomMetaDataStore`: - - -| Event | Description | -|-----------------|------------------------------------------------------------------------------------------------| -| SERIES_ADDED | Fires when all series of one study have added their summary metadata to the `DicomMetaDataStore` | -| INSTANCES_ADDED | Fires when all instances of one series have added their metadata to the `DicomMetaDataStore` | - - -## API -Let's find out about the public API for `DicomMetaDataStore` service. - -- `EVENTS`: Object including the events mentioned above. You can subscribe to these events - by calling DicomMetaDataStore.subscribe(EVENTS.SERIES_ADDED, myFunction). [Read more about pub/sub pattern here](../pubsub.md) - -- `addInstances(instances, madeInClient = false)`: adds the instances' metadata to the store. madeInClient is explained in detail below. After - adding to the store it fires the EVENTS.INSTANCES_ADDED. - -- `addSeriesMetadata(seriesSummaryMetadata, madeInClient = false)`: adds series summary metadata. After adding it fires EVENTS.SERIES_ADDED - -- `addStudy(study)`: creates and add study-level metadata to the store. - -- `getStudy(StudyInstanceUID)`: returns the study metadata from the store. It includes all the series and instance metadata in the requested study - -- `getSeries(StudyInstanceUID, SeriesInstanceUID`: returns the series-level metadata for the requested study and series UIDs. - -- `getInstance(StudyInstanceUID, SeriesInstanceUID, SOPInstanceUID)`: returns the instance metadata based on the study, series and sop instanceUIDs. - -- `geteInstanceFromImageId`: returns the instance metadata based on the requested imageId. It searches the store for the instance that has the same imageId. - - - -### madeInClient - -Since upon adding the metadata to the store, the relevant events are fired, and there are -other services that are subscribed to these events (`HangingProtocolService` or `DisplaySetService`), sometimes -we want to add instance metadata but don't want the events to get fired. For instance, when -you are caching the data for the next study in advance, you probably don't want to trigger hanging protocol -logic, so you set `madeInClient=true` to not fire events. - - -## Storage -As discussed before, there are several API that enables getting metadata from the store and adding to the store. -However, it is good to have an understanding of where they get -stored and in what format and hierarchy. `_model` is a private variable in the store -which holds all the metadata for all studies, series, and instances, and it looks like: - - -```js title="platform/core/src/services/DicomMetadataStore/DicomMetadataStore.js" -const _model = { - studies: [ - { - /** Study Metadata **/ - seriesLists: [ - { - // Series in study from dicom web server 1 (or different backend 1) - series: [ - { - // Series 1 Metadata - instances: [ - { - // Instance 1 metadata of Series 1 - }, - { - // Instance 2 metadata of Series 1 - }, - /** Other instances metadata **/ - ], - }, - { - // Series 2 Metadata - instances: [ - { - // Instance 1 metadata of Series 2 - }, - { - // Instance 2 metadata of Series 1 - }, - /** Other instances metadata **/ - ], - }, - ], - }, - { - // Series in study from dicom web server 2 (or different backend 2) - /** ... **/ - }, - ], - }, - ], -} -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/data/DisplaySetService.md b/platform/docs/versioned_docs/version-3.0/platform/services/data/DisplaySetService.md deleted file mode 100644 index defc022c610..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/data/DisplaySetService.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: DisplaySet Service ---- -# DisplaySet Service - - -## Overview -`DisplaySetService` handles converting the `instanceMetadata` into `DisplaySet` that `OHIF` uses for the visualization. `DisplaySetService` gets initialized in the `Mode.jsx`. During the initialization `SOPClassHandlerIds` of the `modes` gets registered with the `DisplaySetService`. - -> Based on the instanceMetadata's `SOPClassHandlerId`, the correct module from the registered extensions is found by `OHIF` and its `getDisplaySetsFromSeries` runs to create a DisplaySet for the Series. - - -```js title="platform/core/src/services/DisplaySetService/DisplaySetService.js" -init(extensionManager, SOPClassHandlerIds) { - this.extensionManager = extensionManager; - this.SOPClassHandlerIds = SOPClassHandlerIds; - this.activeDisplaySets = []; -} -``` - -in `Mode.jsx` - -```js title="platform/viewer/src/routes/Mode/Mode.jsx" -export default function ModeRoute(/** ... **/) { - /** ... **/ - const { DisplaySetService } = servicesManager.services - const { sopClassHandlers } = mode - /** ... **/ - useEffect( - () => { - /** ... **/ - - // Add SOPClassHandlers to a new SOPClassManager. - DisplaySetService.init(extensionManager, sopClassHandlers) - - /** ... **/ - } - /** ... **/ - ) - /** ... **/ - return <> /** ... **/ -} -``` - - - - -## Events -There are three events that get broadcasted in `DisplaySetService`: - - - -| Event | Description | -| -------------------- | ---------------------------------------------------- | -| DISPLAY_SETS_ADDED | Fires a displayset is added to the displaysets cache | -| DISPLAY_SETS_CHANGED | Fires when a displayset is changed | -| DISPLAY_SETS_REMOVED | Fires when a displayset is removed | - - - -## API -Let's find out about the public API for `DisplaySetService`. - -- `EVENTS`: Object including the events mentioned above. You can subscribe to these events - by calling DisplaySetService.subscribe(EVENTS.DISPLAY_SETS_CHANGED, myFunction). [Read more about pub/sub pattern here](../pubsub.md) - -- `makeDisplaySets(input, { batch, madeInClient, settings } = {}`): Creates displaySet for the provided - array of instances metadata. Each display set gets a random UID assigned. - - - `input`: Array of instances Metadata - - `batch = false`: If you need to pass array of arrays of instances metadata to have a batch creation - - `madeInClient = false`: Disables the events firing - - `settings = {}`: Hanging protocol viewport or rendering settings. For instance, setting the initial `voi`, or activating a tool upon - displaySet rendering. [Read more about hanging protocols settings here](./HangingProtocolService.md#Settings) - - -- `getDisplaySetByUID`: Returns the displaySet based on the DisplaySetUID. - -- `getDisplaySetForSOPInstanceUID`: Returns the displaySet that includes an image with the provided SOPInstanceUID - -- `getActiveDisplaySets`: Returns the active displaySets - -- `deleteDisplaySet`: Deletes the displaySets from the displaySets cache - -- `holdChangeEvents`: Prevents firing change events (currently only works on add event). - -- `fireHoldChangeEvents`: Causes the change event to be fired IF there were any changes. No longer holds events. diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/data/HangingProtocolService.md b/platform/docs/versioned_docs/version-3.0/platform/services/data/HangingProtocolService.md deleted file mode 100644 index 006a5571218..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/data/HangingProtocolService.md +++ /dev/null @@ -1,348 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: Hanging Protocol Service ---- - -# Hanging Protocol Service - -## Overview - -`HangingProtocolService` is a migration of the `OHIF-v1` hanging protocol -engine. This service handles the arrangement of the images in the viewport. In -short, the registered protocols will get matched with the DisplaySets that are -available for the study. Each protocol gets a score, and they are ranked. The -winning protocol gets applied and its settings run for the viewports. - -You can read more about hanging protocols -[here](http://dicom.nema.org/dicom/Conf-2005/Day-2_Selected_Papers/B305_Morgan_HangProto_v1.pdf). -In short with `OHIF-v3` hanging protocols you can: - -- Define what layout of the viewport should the viewer starts with (eg 2x2 layout) -- Define which series gets displayed in which position of the layout -- Apply certain initial viewport settings; e.g., inverting the contrast -- Enable certain tools based on what series are displayed: link prostate T2 and - ADC MRI. -- Apply synchronization settings between different viewports or between setting and viewports -- Register custom synchronization settings for viewports -- Register custom attribute extractors -- Select "next display set" from the matching display sets, both on navigation and initial view - -## Skeleton of A Hanging Protocol - -You can find the skeleton of the hanging protocols here: - -```js -const defaultProtocol = { - id: 'test', - locked: true, - hasUpdatedPriorsInformation: false, - name: 'Default', - createdDate: '2021-02-23T19:22:08.894Z', - modifiedDate: '2021-02-23T19:22:08.894Z', - availableTo: {}, - editableBy: {}, - toolGroupIds: [ - 'ctToolGroup', - 'ptToolGroup', - ], - imageLoadStrategy: 'interleaveTopToBottom', // "default" , "interleaveTopToBottom", "interleaveCenter" - protocolMatchingRules: [ - { - id: 'wauZK2QNEfDPwcAQo', - weight: 1, - attribute: 'StudyDescription', - constraint: { - contains: { - value: 'PETCT', - }, - }, - required: false, - }, - ], - stages: [ - { - id: 'hYbmMy3b7pz7GLiaT', - name: 'default', - viewportStructure: { - layoutType: 'grid', - properties: { - rows: 1, - columns: 1, - }, - }, - displaySets: [ - { - id: 'displaySet', - seriesMatchingRules: [ - { - id: 'GPEYqFLv2dwzCM322', - weight: 1, - attribute: 'Modality', - constraint: { - equals: 'CT', - }, - required: true, - }, - { - id: 'vSjk7NCYjtdS3XZAw', - weight: 1, - attribute: 'numImageFrames', - constraint: { - greaterThan: 10, - }, - }, - ], - studyMatchingRules: [], - }, - ], - viewports: [ - { - viewportOptions: { - viewportId: 'ctAXIAL', - viewportType: 'volume', - orientation: 'axial', - toolGroupId: 'ctToolGroup', - initialImageOptions: { - // index: 5, - preset: 'first', // 'first', 'last', 'middle' - }, - syncGroups: [ - { - type: 'cameraPosition', - id: 'axialSync', - source: true, - target: true, - }, - ], - }, - displaySets: [ - { - id: 'displaySet', - }, - ], - }, - ], - }, - ], - numberOfPriorsReferenced: -1, -} -``` - -Let's discuss each property in depth. - -- `id`: unique identifier for the protocol -- `name`: Name displayed to the user to select this protocol - -- `protocolMatchingRules`: A list of criteria for the protocol along with the - provided points for ranking. - - - `weight`: weight for the matching rule. Eventually, all the registered - protocols get sorted based on the weights, and the winning protocol gets - applied to the viewer. - - `attribute`: tag that needs to be matched against. This can be either - Study-level metadata or a custom attribute. - [Learn more about custom attribute matching](#custom-attribute) - - - `constraint`: the constraint that needs to be satisfied for the attribute. It accepts a `validator` which can be - [`equals`, `doesNotEqual`, `contains`, `doesNotContain`, `startsWith`, `endsWidth`] - - A sample of the matching rule is: - - ```js - { - weight: 1, - attribute: 'StudyInstanceUID', - constraint: { - equals: '1.3.6.1.4.1.25403.345050719074.3824.20170125112931.11', - }, - required: true, - } - ``` - - -- `stages`: Each protocol can define one or more stages. Each stage defines a certain layout and viewport rules. - Therefore, the `stages` property is array of objects, each object being one stage. - - - `displaySets`: Defines the matching rules for which display sets to use. - - `viewportStructure`: Defines the layout of the viewer. You can define the - number of `rows` and `columns`. - - `viewports` defines the actual viewports to display. There should be `rows * columns` number of - these `viewports` property, ordered rows first, then columns. - - - ```js - stages: [ - { - id: 'hYbmMy3b7pz7GLiaT', - name: 'oneByTwo', - viewportStructure: { - type: 'grid', - properties: { - rows: 1, - columns: 3, - }, - }, - viewports: [ - // viewport 1 - { - viewportOptions: { - viewportId: 'ctAXIAL', - viewportType: 'volume', - orientation: 'axial', - toolGroupId: 'ctToolGroup', - initialImageOptions: { - // index: 5, - preset: 'first', // 'first', 'last', 'middle' - }, - syncGroups: [ - { - type: 'cameraPosition', - id: 'axialSync', - source: true, - target: true, - }, - ], - }, - displaySets: [ - { - id: 'displaySet', - }, - ], - }, - ]; - ``` - -## Events - -There are two events that get publish in `HangingProtocolService`: - -| Event | Description | -| ------------ | -------------------------------------------------------------------- | -| NEW_LAYOUT | Fires when a new layout is requested by the `HangingProtocolService` | -| STAGE_CHANGE | Fires when the the stage is changed in the hanging protocols | - -## API - -- `getState`: returns an array: `[matchDetails, hpAlreadyApplied]`: - - - `matchDetails`: matching details for the series - - `hpAlreadyApplied`: An array which tracks whether HPServices has been - applied on each viewport. - -- `addProtocols`: adds provided protocols to the list of registered protocols - for matching - -- `run({ studies, displaySets }, protocol)`: runs the HPService with the provided - list of studies, display sets and optional protocol. - If protocol is not given, HP Matching - engine will search all the registered protocols for the best matching one - based on the constraints. - -- `addCustomAttribute`: adding a custom attribute for matching. (see below) - -Default initialization of the modes handles running the `HangingProtocolService` - -## Custom Attribute -In some situations, you might want to match based on a custom attribute and not the DICOM tags. For instance, -if you have assigned a `timepointId` to each study, and you want to match based on it. -Good news is that, in `OHIF-v3` you can define you custom attribute and use it for matching. - -In some situations, you might want to match based on a custom attribute and not -the DICOM tags. For instance, if you have assigned a `timepointId` to each study -and you want to match based on it. Good news is that, in `OHIF-v3` you can -define you custom attribute and use it for matching. - -There are various ways that you can let `HangingProtocolService` know of you -custom attribute. We will show how to add it inside the an extension. This extension -also shows how to register a sync group service which can be referenced -in the sync group settings. - -```js -const myCustomProtocol = { - id: 'myCustomProtocol', - /** ... **/ - protocolMatchingRules: [ - { - id: 'vSjk7NCYjtdS3XZAw', - attribute: 'timepointId', - constraint: { - equals: 'first', - }, - required: false, - }, - ], -... - -// Custom function for custom attribute -const getTimePointUID = metaData => { - // requesting the timePoint Id - return myBackEndAPI(metaData); -}; - - preRegistration: ({ - servicesManager, - }) => { - const { HangingProtocolService, SyncGroupService } = servicesManager.services; - HangingProtocolService.addCustomAttribute('timepointId', 'TimePoint ID', getTimePointUID); - SyncGroupService.setSynchronizer('initialzoompan', initialZoomPan); - } -``` - -## Viewport Settings - -You can define custom settings to be applied to each viewport. There are two -types of settings: - -- `viewport settings`: Currently we support two viewport settings - - - `voi`: applying an initial `voi` by setting the windowWidth and windowCenter - - `inverted`: inverting the viewport color (e.g., for PET images) - -- `props settings`: Running commands after the first render; e.g., enabling the - link tool - -Examples of each settings are : - -```js -viewportSettings: [ - { - options: { - itemId: 'SyncScroll', - interactionType: 'toggle', - commandName: 'toggleSynchronizer', - commandOptions: { toggledState: true }, - }, - commandName: 'setToolActive', - type: 'props', - }, -]; -``` - -and - -```js -viewportSettings: [ - { - options: { - voi: { - windowWidth: 400, - windowCenter: 40, - }, - }, - commandName: '', - type: 'viewport', - }, -]; -``` - -## Sync Groups -The sync groups are listeners to events that synchronize viewport settings to -some other settings. There are three default/provided sync groups: `zoomPan`, -`cameraPosition` and `voi`. These are defined in the `syncGroups` array. -Additionally, other synchronization types can be created and registered on the -`SyncGroupService.setSynchronizer`, by registering a new id, and a creator method. - -The sync group service is specific to the `cornerstone-extension` because the -actual behaviour of the synchronizers is dependent on the specific viewport. -Different viewport types could redifine the same synchronizer names in -different ways appropriate to that viewport. diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/data/MeasurementService.md b/platform/docs/versioned_docs/version-3.0/platform/services/data/MeasurementService.md deleted file mode 100644 index 74605bce1c5..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/data/MeasurementService.md +++ /dev/null @@ -1,161 +0,0 @@ ---- -sidebar_position: 6 -sidebar_label: Measurement Service ---- - -# Measurement Service - -## Overview - -`MeasurementService` handles the internal measurement representation inside -`OHIF` platform. Developers can add their custom `sources` with `mappers` to -enable adding measurements inside OHIF. Currently, we are maintaining -`CornerstoneTools` annotations and corresponding mappers can be found inside the -`cornerstone` extension. However, `MeasurementService` can be configured to work -with any custom tools given that its `mappers` is added to the -`MeasurementService`. We can see the overall architecture of the -`MeasurementService` below: - -![services-measurements](../../../assets/img/services-measurements.png) - -## Events - -There are seven events that get publish in `MeasurementService`: - -| Event | Description | -| --------------------- | ------------------------------------------------------ | -| MEASUREMENT_UPDATED | Fires when a measurement is updated | -| MEASUREMENT_ADDED | Fires when a new measurement is added | -| RAW_MEASUREMENT_ADDED | Fires when a raw measurement is added (e.g., dicom-sr) | -| MEASUREMENT_REMOVED | Fires when a measurement is removed | -| MEASUREMENTS_CLEARED | Fires when all measurements are deleted | -| JUMP_TO_MEASUREMENT | Fires when a measurement is requested to be jump to | - -## API - -- `getMeasurements`: returns array of measurements - -- `getMeasurement(id)`: returns the corresponding measurement based on the - provided Id. - -- `remove(id, source)`: removes a measurement and broadcasts the - `MEASUREMENT_REMOVED` event. - -- `clearMeasurements`: removes all measurements and broadcasts - `MEASUREMENTS_CLEARED` event. - -- `createSource(name, version)`: creates a new measurement source, generates a - uid and adds it to the `sources` property of the service. - -- `addMapping(source, definition, matchingCriteria, toSourceSchema, toMeasurementSchema)`: - adds a new measurement matching criteria along with mapping functions. We will - learn more about [source/mappers below](#source--mappers) - -- `update`: updates the measurement details and fires `MEASUREMENT_UPDATED` - -- `addRawMeasurement(source,definition,data,toMeasurementSchema,dataSource = {}` - : adds a raw measurement into a source so that it may be converted to/from - annotation in the same way. E.g. import serialized data of the same form as - the measurement source. Fires `MEASUREMENT_UPDATED` or `MEASUREMENT_ADDED`. - Note that, `MeasurementService` handles finding the correct mapper upon new - measurements; however, `addRawMeasurement` provides more flexibility. You can - take a look into its usage in `dicom-sr` extension. - - - `source`: The measurement source instance. - - `definition`: The source definition you want to add the measurement to. - - `data`: The data you wish to add to the source. - - `toMeasurementSchema`: A function to get the `data` into the same shape as - the source definition. - -- `jumpToMeasurement(viewportIndex, id)`: calls the listeners who have - subscribed to `JUMP_TO_MEASUREMENT`. - -## Source / Mappers - -To create a custom measurement source and relevant mappers for each tool, you -can take a look at the `init.js` inside the `cornerstone` extension. In which we -are registering our `CornerstoneTools-v4` measurement source to -MeasurementService. Let's take a peek at the _simplified_ implementation -together. To achieve this, for each tool, we need to provide three mappers: - -- `matchingCriteria`: criteria used for finding the correct mapper for the drawn - tool. -- `toAnnotation`: tbd -- `toMeasurement`: a function that converts the tool data to OHIF internal - representation of measurement data. - -```js title="extensions/cornerstone/src/utils/measurementServiceMappings/Length.js" -function toMeasurement( - csToolsAnnotation, - DisplaySetService, - getValueTypeFromToolType -) { - const { element, measurementData } = csToolsAnnotation; - - /** ... **/ - - const { - SOPInstanceUID, - FrameOfReferenceUID, - SeriesInstanceUID, - StudyInstanceUID, - } = getSOPInstanceAttributes(element); - - const displaySet = DisplaySetService.getDisplaySetForSOPInstanceUID( - SOPInstanceUID, - SeriesInstanceUID - ); - - /** ... **/ - return { - id: measurementData.id, - SOPInstanceUID, - FrameOfReferenceUID, - referenceSeriesUID: SeriesInstanceUID, - referenceStudyUID: StudyInstanceUID, - displaySetInstanceUID: displaySet.displaySetInstanceUID, - label: measurementData.label, - description: measurementData.description, - unit: measurementData.unit, - length: measurementData.length, - type: getValueTypeFromToolType(tool), - points: getPointsFromHandles(measurementData.handles), - }; -} - -////////////////////////////////////////// - -// extensions/cornerstone/src/init.js - -const Length = { - toAnnotation, - toMeasurement, - matchingCriteria: [ - { - valueType: MeasurementService.VALUE_TYPES.POLYLINE, - points: 2, - }, - ], -}; - -const _initMeasurementService = (MeasurementService, DisplaySetService) => { - /** ... **/ - - const csToolsVer4MeasurementSource = MeasurementService.createSource( - 'CornerstoneTools', - '4' - ); - - /* Mappings */ - MeasurementService.addMapping( - csToolsVer4MeasurementSource, - 'Length', - Length.matchingCriteria, - toAnnotation, - toMeasurement - ); - - /** Other tools **/ - return csToolsVer4MeasurementSource; -}; -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/data/ToolbarService.md b/platform/docs/versioned_docs/version-3.0/platform/services/data/ToolbarService.md deleted file mode 100644 index 92ab50048b2..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/data/ToolbarService.md +++ /dev/null @@ -1,226 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: Toolbar Service ---- - -# Toolbar Service - -## Overview - -`ToolBarService` handles the toolbar section buttons, and what happens when a -button is clicked by the user. - -
- -
- -## Events - -| Event | Description | -| ----------------------- | ---------------------------------------------------------------------- | -| TOOL_BAR_MODIFIED | Fires when a button is added/removed to the toolbar | -| TOOL_BAR_STATE_MODIFIED | Fires when an interaction happens and ToolBarService state is modified | - -## API - -- `recordInteraction(interaction)`: executes the provided interaction which is - an object providing the following properties to the ToolBarService: - - - `interactionType`: can be `tool`, `toggle` and `action`. We will discuss - more each type below. - - `itemId`: tool name - - `groupId`: the Id for the tool button group; e.g., `Wwwc` which holds - presets. - - `commandName`: if tool has a command attached to run - - `commandOptions`: arguments for the command. - -- `reset`: reset the state of the toolbarService, set the primary tool to be - `Wwwc` and unsubscribe tools that have registered their functions. - -- `addButtons`: add the button definition to the service. - [See below for button definition](#button-definitions). - -- `setButtons`: sets the buttons defined in the service. It overrides all the - previous buttons - -- `getActiveTools`: returns the active tool + all the toggled-on tools - -## State - -ToolBarService has an internal state that gets updated per tool interaction and -tracks the active toolId, state of the buttons that have toggled state, and the -group buttons and which tool in each group is active. - -```js -state = { - primaryToolId: 'Wwwc', - toggles: { - /* id: true/false */ - }, - groups: { - /* track most recent click per group...*/ - }, -}; -``` - -## Interaction type - -There are three main types that a tool can have which is defined in the -interaction object. - -- `tool`: setting a tool to be active; e.g., measurement tools -- `toggle`: toggling state of a tool; e.g., viewport link (sync) -- `action`: performs a registered action outside of the ToolBarService; e.g., - capture - -A _simplified_ implementation of the ToolBarService is: - -```js -export default class ToolBarService { - /** ... **/ - recordInteraction(interaction) { - /** ... **/ - switch (interactionType) { - case 'action': { - break; - } - case 'tool': { - this.state.primaryToolId = itemId; - - commandsManager.runCommand('setToolActive', interaction.commandOptions); - break; - } - case 'toggle': { - this.state.toggles[itemId] = - this.state.toggles[itemId] === undefined - ? true - : !this.state.toggles[itemId]; - interaction.commandOptions.toggledState = this.state.toggles[itemId]; - break; - } - default: - throw new Error(`Invalid interaction type: ${interactionType}`); - } - /** ... **/ - } - /** ... **/ -} -``` - -## Button Definitions - -The simplest toolbarButtons definition has the following properties: - -![toolbarModule-zoom](../../../assets/img/toolbarModule-zoom.png) - -```js -{ - id: 'Zoom', - type: 'ohif.radioGroup', - props: { - type: 'tool', - icon: 'tool-zoom', - label: 'Zoom', - commandOptions: { toolName: 'Zoom' }, - }, -}, -``` - -| property | description | values | -| ---------------- | ----------------------------------------------------------------- | ------------------------------------------- | -| `id` | Unique string identifier for the definition | \* | -| `label` | User/display friendly to show in UI | \* | -| `icon` | A string name for an icon supported by the consuming application. | \* | -| `type` | Used to determine the button's behaviour | "tool", "toggle", "action" | -| `commandName` | (optional) The command to run when the button is used. | Any command registered by a `CommandModule` | -| `commandOptions` | (optional) Options to pass the target `commandName` | \* | - -There are three main types of toolbar buttons: - -- `tool`: buttons that enable a tool by running the `setToolActive` command with - the `commandOptions` -- `toggle`: buttons that acts as a toggle: e.g., linking viewports -- `action`: buttons that executes an action: e.g., capture button to save - screenshot - -## Nested Buttons - -You can use the `ohif.splitButton` type to build a button with extra tools in -the dropdown. - -- First you need to give your `primary` tool definition to the split button -- the `secondary` properties can be a simple arrow down (`chevron-down` icon) -- For adding the extra tools add them to the `items` list. - -You can see below how `longitudinal` mode is using the available toolbarModule -to create `MeasurementTools` nested button - -![toolbarModule-nested-buttons](../../../assets/img/toolbarModule-nested-buttons.png) - -```js title="modes/longitudinal/src/toolbarButtons.js" -{ - id: 'MeasurementTools', - type: 'ohif.splitButton', - props: { - groupId: 'MeasurementTools', - isRadio: true, - primary: { - id: 'Length', - icon: 'tool-length', - label: 'Length', - type: 'tool', - commandOptions: { - toolName: 'Length', - } - }, - secondary: { - icon: 'chevron-down', - label: '', - isActive: true, - tooltip: 'More Measure Tools', - }, - items: [ - // Length tool - { - id: 'Length', - icon: 'tool-length', - label: 'Length', - type: 'tool', - commandOptions: { - toolName: 'Length', - } - }, - // Bidirectional tool - { - id: 'Bidirectional', - icon: 'tool-bidirectional', - label: 'Length', - type: 'tool', - commandOptions: { - toolName: 'Bidirectional', - } - }, - // Ellipse tool - { - id: 'EllipticalRoi', - icon: 'tool-elipse', - label: 'Ellipse', - type: 'tool', - commandOptions: { - toolName: 'EllipticalRoi', - } - }, - // Circle tool - { - id: 'CircleROI', - icon: 'tool-circle', - label: 'Circle', - type: 'tool', - commandOptions: { - toolName: 'CircleROI', - } - }, - ], - }, -} -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/data/_category_.json b/platform/docs/versioned_docs/version-3.0/platform/services/data/_category_.json deleted file mode 100644 index 984ac9a4208..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/data/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Data Services", - "position": 2 -} diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/data/index.md b/platform/docs/versioned_docs/version-3.0/platform/services/data/index.md deleted file mode 100644 index fa9128ae4da..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/data/index.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Overview ---- - -# Overview - -Data services are the first category of services which deal with handling non-ui -related state Each service have their own internal state which they handle. - -> We have replaced the _redux_ store. Instead, we have introduced various -> services and a pub/sub pattern to subscribe and run, which makes the `OHIF-v3` -> architecture nice and clean. - -We maintain the following non-ui Services: - -- [DicomMetadata Store](./../data/DicomMetadataStore.md) -- [DisplaySet Service](./../data/DisplaySetService.md) -- [Hanging Protocol Service](../data/HangingProtocolService.md) -- [Toolbar Service](../data/ToolBarService.md) -- [Measurement Service](../data/MeasurementService.md) - -## Service Architecture - -![services-data](../../../assets/img/services-data.png) - -> We have explained services and how to create a custom service in the -> [`ServiceManager`](../../managers/service.md) section of the docs - -To recap: The simplest service return a new object that has a `name` property, -and `Create` method which instantiate the service class. The "Factory Function" -that creates the service is provided with the implementation (this is slightly -different for UI Services). - -```js -// extensions/customExtension/src/services/backEndService/index.js -import backEndService from './backEndService'; - -export default function WrappedBackEndService(serviceManager) { - return { - name: 'myService', - create: ({ configuration = {} }) => { - return new backEndService(serviceManager); - }, - }; -} -``` - -A service, once created, can be registered with the `ServicesManager` to make it -accessible to extensions. Similarly, the application code can access named -services from the `ServicesManager`. - -[Read more of how to design a new custom service and register it](../../managers/service.md) diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/index.md b/platform/docs/versioned_docs/version-3.0/platform/services/index.md deleted file mode 100644 index 87d88e7ad2b..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/index.md +++ /dev/null @@ -1,173 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Introduction ---- - -# Services - -## Overview - -Services are "concern-specific" code modules that can be consumed across layers. -Services provide a set of operations, often tied to some shared state, and are -made available to through out the app via the `ServicesManager`. Services are -particularly well suited to address [cross-cutting -concerns][cross-cutting-concerns]. - -Each service should be: - -- self-contained -- able to fail and/or be removed without breaking the application -- completely interchangeable with another module implementing the same interface - -> In `OHIF-v3` we have added multiple non-UI services and have introduced -> **pub/sub** pattern to reduce coupling between layers. -> -> [Read more about Pub/Sub](./pubsub.md) - -## Services - -The following services is available in the `OHIF-v3`. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ServiceTypeDescription
- - DicomMetadataStore (NEW) - - Data Service - DicomMetadataStore -
- - DisplaySetService (NEW) - - Data Service - DisplaySetService -
- - HangingProtocolService (NEW) - - Data Service - HangingProtocolService -
- - MeasurementService (MODIFIED) - - Data Service - MeasurementService -
- - ToolBarService (NEW) - - Data Service - ToolBarService -
- - ViewportGridService (NEW) - - UI Service - ViewportGridService -
- - Cine Service (NEW) - - UI Service - cine -
- - UIDialogService - - UI Service - UIDialogService -
- - UIModalService - - UI Service - UIModalService -
- - UINotificationService - - UI Service - UINotificationService -
- - UIViewportDialogService (NEW) - - UI Service - UIViewportDialogService -
- - - - - -[core-services]: https://github.com/OHIF/Viewers/tree/master/platform/core/src/services -[services-manager]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/services/ServicesManager.js -[cross-cutting-concerns]: https://en.wikipedia.org/wiki/Cross-cutting_concern - diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/pubsub.md b/platform/docs/versioned_docs/version-3.0/platform/services/pubsub.md deleted file mode 100644 index fae6978e6a8..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/pubsub.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: Pub Sub ---- - -# Pub sub - -## Overview - -Publish–subscribe pattern is a messaging pattern that is one of the fundamentals -patterns used in reusable software components. - -In short, services that implement this pattern, can have listeners subscribed -to their broadcasted events. After the event is fired, the corresponding -listener will execute the function that is registered. - -You can read more about this design pattern -[here](https://cloud.google.com/pubsub/docs/overview). - -## Example: Default Initialization - -In `Mode.jsx` we have a default initialization that demonstrates a series of -subscriptions to various events. - -```js -async function defaultRouteInit({ - servicesManager, - studyInstanceUIDs, - dataSource, -}) { - const { - DisplaySetService, - HangingProtocolService, - } = servicesManager.services; - - const unsubscriptions = []; - - const { - unsubscribe: instanceAddedUnsubscribe, - } = DicomMetadataStore.subscribe( - DicomMetadataStore.EVENTS.INSTANCES_ADDED, - ({ StudyInstanceUID, SeriesInstanceUID, madeInClient = false }) => { - const seriesMetadata = DicomMetadataStore.getSeries( - StudyInstanceUID, - SeriesInstanceUID - ); - - DisplaySetService.makeDisplaySets(seriesMetadata.instances, madeInClient); - } - ); - - unsubscriptions.push(instanceAddedUnsubscribe); - - studyInstanceUIDs.forEach(StudyInstanceUID => { - dataSource.retrieve.series.metadata({ StudyInstanceUID }); - }); - - const { unsubscribe: seriesAddedUnsubscribe } = DicomMetadataStore.subscribe( - DicomMetadataStore.EVENTS.SERIES_ADDED, - ({ StudyInstanceUID }) => { - const studyMetadata = DicomMetadataStore.getStudy(StudyInstanceUID); - HangingProtocolService.run(studyMetadata, DisplaySetService.getActiveDisplaySets()); - } - ); - unsubscriptions.push(seriesAddedUnsubscribe); - - return unsubscriptions; -} -``` - -## Unsubscription - -You need to be careful if you are adding custom subscriptions to the app. Each -subscription will return an unsubscription function that needs to be executed on -component destruction to avoid adding multiple subscriptions to the same -observer. - -Below, we can see `simplified` `Mode.jsx` and the corresponding `useEffect` -where the unsubscription functions are executed upon destruction. - -```js title="platform/viewer/src/routes/Mode/Mode.jsx" -export default function ModeRoute(/**..**/) { - /**...**/ - useEffect(() => { - /**...**/ - - DisplaySetService.init(extensionManager, sopClassHandlers); - - extensionManager.onModeEnter(); - mode?.onModeEnter({ servicesManager, extensionManager }); - - hangingProtocols.forEach(extentionProtocols => { - const { protocols } = extensionManager.getModuleEntry(extentionProtocols); - HangingProtocolService.addProtocols(protocols); - }); - - const setupRouteInit = async () => { - if (route.init) { - return await route.init(/**...**/); - } - - return await defaultRouteInit(/**...**/); - }; - - let unsubscriptions; - setupRouteInit().then(unsubs => { - unsubscriptions = unsubs; - }); - - return () => { - extensionManager.onModeExit(); - mode?.onModeExit({ servicesManager, extensionManager }); - unsubscriptions.forEach(unsub => { - unsub(); - }); - }; - }); - return <> /**...**/ ; -} -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/ui/_category_.json b/platform/docs/versioned_docs/version-3.0/platform/services/ui/_category_.json deleted file mode 100644 index 9c012134eb0..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/ui/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "UI Services", - "position": 3 -} diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/ui/cine-service.md b/platform/docs/versioned_docs/version-3.0/platform/services/ui/cine-service.md deleted file mode 100644 index 707b5d97f7f..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/ui/cine-service.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -sidebar_position: 7 -sidebar_label: CINE Service ---- - -# CINE Service - -TODO... diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/ui/index.md b/platform/docs/versioned_docs/version-3.0/platform/services/ui/index.md deleted file mode 100644 index 5ba4a539057..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/ui/index.md +++ /dev/null @@ -1,304 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Overview ---- - -# Overview - - - -A typical web application will have components and state for common UI like -modals, notifications, dialogs, etc. A UI service makes it possible to leverage -these components from an extension. - -We maintain the following UI Services: - -- [UI Notification Service](ui-notification-service.md) -- [UI Modal Service](ui-modal-service.md) -- [UI Dialog Service](ui-dialog-service.md) -- [UI Viewport Dialog Service](ui-viewport-dialog-service.md) -- [CINE Service](cine-service.md) -- [Viewport Grid Service](viewport-grid-service.md) - - - -![UIService](../../../assets/img/ui-services.png) - - - -## Providers for UI services - -**There are several context providers that wraps the application routes. This -makes the context values exposed in the app, and service's `setImplementation` -can get run to override the implementation of the service.** - -```js title="platform/viewer/src/App.jsx" -function App({ config, defaultExtensions }) { - /**...**/ - /**...**/ - return ( - /**...**/ - - - - - - - {appRoutes} - - - - - - - /**...**/ - ); -} -``` - -## Example - -For instance `UIModalService` has the following Public API: - -```js title="platform/core/src/services/UIModalService/index.js" -const publicAPI = { - name, - hide: _hide, - show: _show, - setServiceImplementation, -}; - -function setServiceImplementation({ - hide: hideImplementation, - show: showImplementation, -}) { - /** ... **/ - serviceImplementation._hide = hideImplementation; - serviceImplementation._show = showImplementation; - /** ... **/ -} - -export default { - name: 'UIModalService', - create: ({ configuration = {} }) => { - return publicAPI; - }, -}; -``` - -`UIModalService` implementation can be set (override) in its context provider. -For instance in `ModalProvider` we have: - -```js title="platform/ui/src/contextProviders/ModalProvider.jsx" -import { Modal } from '@ohif/ui'; - -const ModalContext = createContext(null); -const { Provider } = ModalContext; - -export const useModal = () => useContext(ModalContext); - -const ModalProvider = ({ children, modal: Modal, service }) => { - const DEFAULT_OPTIONS = { - content: null, - contentProps: null, - shouldCloseOnEsc: true, - isOpen: true, - closeButton: true, - title: null, - customClassName: '', - }; - - const show = useCallback(props => setOptions({ ...options, ...props }), [ - options, - ]); - - const hide = useCallback(() => setOptions(DEFAULT_OPTIONS), [ - DEFAULT_OPTIONS, - ]); - - useEffect(() => { - if (service) { - service.setServiceImplementation({ hide, show }); - } - }, [hide, service, show]); - - const { - content: ModalContent, - contentProps, - isOpen, - title, - customClassName, - shouldCloseOnEsc, - closeButton, - } = options; - - return ( - - {ModalContent && ( - - - - )} - {children} - - ); -}; - -export default ModalProvider; - -export const ModalConsumer = ModalContext.Consumer; -``` - -Therefore, anywhere in the app that we have access to react context we can use -it by calling the `useModal` from `@ohif/ui`. As a matter of fact, we are -utilizing the modal for the preference window which shows the hotkeys after -clicking on the gear button on the right side of the header. - -A `simplified` code for our worklist is: - -```js title="platform/viewer/src/routes/WorkList/WorkList.jsx" -import { useModal, Header } from '@ohif/ui'; - -function WorkList({ - history, - data: studies, - dataTotal: studiesTotal, - isLoadingData, - dataSource, - hotkeysManager, -}) { - const { show, hide } = useModal(); - - /** ... **/ - - const menuOptions = [ - { - title: t('Header:About'), - icon: 'info', - onClick: () => show({ content: AboutModal, title: 'About OHIF Viewer' }), - }, - { - title: t('Header:Preferences'), - icon: 'settings', - onClick: () => - show({ - title: t('UserPreferencesModal:User Preferences'), - content: UserPreferences, - contentProps: { - hotkeyDefaults: hotkeysManager.getValidHotkeyDefinitions( - hotkeyDefaults - ), - hotkeyDefinitions, - onCancel: hide, - currentLanguage: currentLanguage(), - availableLanguages, - defaultLanguage, - onSubmit: state => { - i18n.changeLanguage(state.language.value); - hotkeysManager.setHotkeys(state.hotkeyDefinitions); - hide(); - }, - onReset: () => hotkeysManager.restoreDefaultBindings(), - }, - }), - }, - ]; - /** ... **/ - return ( -
- /** ... **/ -
- /** ... **/ -
- ); -} -``` - - - - - - - -## Tips & Tricks - -It's important to remember that all we're doing is making it possible to control -bits of the application's UI from an extension. Here are a few non-obvious -takeaways worth mentioning: - -- Your application code should continue to use React context - (consumers/providers) as it normally would -- You can substitute our "out of the box" UI implementations with your own -- You can create and register your own UI services -- You can choose not to register a service or provide a service implementation -- In extensions, you can provide fallback/alternative behavior if an expected - service is not registered - - No `UIModalService`? Use the `UINotificationService` to notify users. -- You can technically register a service in an extension and expose it to the - core application - -> Note: These are recommended patterns, not hard and fast rules. Following them -> will help reduce confusion and interoperability with the larger OHIF -> community, but they're not silver bullets. Please speak up, create an issue, -> if you would like to discuss new services or improvements to this pattern. diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-dialog-service.md b/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-dialog-service.md deleted file mode 100644 index 152841ae625..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-dialog-service.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -sidebar_position: 4 -sidebar_label: UI Dialog Service ---- -# UI Dialog Service - -Dialogs have similar characteristics to that of Modals, but often with a -streamlined focus. They can be helpful when: - -- We need to grab the user's attention -- We need user input -- We need to show additional information - -If you're curious about the DOs and DON'Ts of dialogs and modals, check out this -article: ["Best Practices for Modals / Overlays / Dialog Windows"][ux-article] - - - -## Interface - -For a more detailed look on the options and return values each of these methods -is expected to support, [check out it's interface in `@ohif/core`][interface] - -| API Member | Description | -| -------------- | ------------------------------------------------------ | -| `create()` | Creates a new Dialog that is displayed until dismissed | -| `dismiss()` | Dismisses the specified dialog | -| `dismissAll()` | Dismisses all dialogs | - -## Implementations - -| Implementation | Consumer | -| ------------------------------------ | -------------------------- | -| [Dialog Provider][dialog-provider]\* | Baked into Dialog Provider | - -`*` - Denotes maintained by OHIF - -> 3rd Party implementers may be added to this table via pull requests. - - - - -[interface]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/services/UIDialogService/index.js -[dialog-provider]: https://github.com/OHIF/Viewers/blob/master/platform/ui/src/contextProviders/DialogProvider.js -[ux-article]: https://uxplanet.org/best-practices-for-modals-overlays-dialog-windows-c00c66cddd8c - diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-modal-service.md b/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-modal-service.md deleted file mode 100644 index cb36d7e6cf6..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-modal-service.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -sidebar_position: 3 -sidebar_label: UI Modal Service ---- -# UI Modal Service - -Modals have similar characteristics to that of Dialogs, but are often larger, -and only allow for a single instance to be viewable at once. They also tend to -be centered, and not draggable. They're commonly used when: - -- We need to grab the user's attention -- We need user input -- We need to show additional information - -If you're curious about the DOs and DON'Ts of dialogs and modals, check out this -article: ["Best Practices for Modals / Overlays / Dialog Windows"][ux-article] - - -
- -
- -## Interface - -For a more detailed look on the options and return values each of these methods -is expected to support, [check out it's interface in `@ohif/core`][interface] - -| API Member | Description | -| ---------- | ------------------------------------- | -| `hide()` | Hides the open modal | -| `show()` | Shows the provided content in a modal | - -## Implementations - -| Implementation | Consumer | -| ---------------------------------- | --------- | -| [Modal Provider][modal-provider]\* | Modal.jsx | - -`*` - Denotes maintained by OHIF - - - - - -> 3rd Party implementers may be added to this table via pull requests. - - - - -[interface]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/services/UIModalService/index.js -[modal-provider]: https://github.com/OHIF/Viewers/blob/master/platform/ui/src/contextProviders/ModalProvider.js -[modal-consumer]: https://github.com/OHIF/Viewers/tree/master/platform/ui/src/components/ohifModal -[ux-article]: https://uxplanet.org/best-practices-for-modals-overlays-dialog-windows-c00c66cddd8c - diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-notification-service.md b/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-notification-service.md deleted file mode 100644 index 96185943482..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-notification-service.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: UI Notification Service ---- -# UI Notification Service - -Notifications can be annoying and disruptive. They can also deliver timely -helpful information, or expedite the user's workflow. Here is some high level -guidance on when and how to use them: - -- Notifications should be non-interfering (timely, relevant, important) -- We should only show small/brief notifications -- Notifications should be contextual to current behavior/actions -- Notifications can serve warnings (acting as a confirmation) - -If you're curious about the DOs and DON'Ts of notifications, check out this -article: ["How To Design Notifications For Better UX"][ux-article] - - - -
- -
- - -## Interface - -For a more detailed look on the options and return values each of these methods -is expected to support, [check out it's interface in `@ohif/core`][interface] - -| API Member | Description | -| ---------- | --------------------------------------- | -| `hide()` | Hides the specified notification | -| `show()` | Creates and displays a new notification | - -## Implementations - -| Implementation | Consumer | -| ---------------------------------------- | ----------------------------------------- | -| [Snackbar Provider][snackbar-provider]\* | [SnackbarContainer][snackbar-container]\* | - -`*` - Denotes maintained by OHIF - -> 3rd Party implementers may be added to this table via pull requests. - - - - -[interface]: https://github.com/OHIF/Viewers/blob/master/platform/core/src/services/UINotificationService/index.js -[snackbar-provider]: https://github.com/OHIF/Viewers/blob/master/platform/ui/src/contextProviders/SnackbarProvider.js -[snackbar-container]: https://github.com/OHIF/Viewers/blob/master/platform/ui/src/components/snackbar/SnackbarContainer.js -[ux-article]: https://uxplanet.org/how-to-design-notifications-for-better-ux-6fb0711be54d - diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-viewport-dialog-service.md b/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-viewport-dialog-service.md deleted file mode 100644 index 7370428459d..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/ui/ui-viewport-dialog-service.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -sidebar_position: 5 -sidebar_label: UI Viewport Dialog Service ---- - -# UI Viewport Dialog Service - -## Overview -This is a new UI service, that creates a modal inside the viewport. - -Dialogs have similar characteristics to that of Modals, but often with a -streamlined focus. They can be helpful when: - -- We need to grab the user's attention -- We need user input -- We need to show additional information - -If you're curious about the DOs and DON'Ts of dialogs and modals, check out this -article: ["Best Practices for Modals / Overlays / Dialog Windows"][ux-article] - - - -
- -
- -## Interface - -For a more detailed look on the options and return values each of these methods -is expected to support, [check out it's interface in `@ohif/core`][interface] - -| API Member | Description | -| -------------- | ------------------------------------------------------ | -| `create()` | Creates a new Dialog that is displayed until dismissed | -| `dismiss()` | Dismisses the specified dialog | -| `dismissAll()` | Dismisses all dialogs | - -## Implementations - -| Implementation | Consumer | -| ------------------------ | -------------------------- | -| [ViewportDialogProvider] | Baked into Dialog Provider | - -`*` - Denotes maintained by OHIF - - -## State - -```js -const DEFAULT_STATE = { - viewportIndex: null, - message: undefined, - type: 'info', // "error" | "warning" | "info" | "success" - actions: undefined, // array of { type, text, value } - onSubmit: () => { - console.log('btn value?'); - }, - onOutsideClick: () => { - console.warn('default: onOutsideClick') - }, - onDismiss: () => { - console.log('dismiss? -1'); - }, -}; -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/services/ui/viewport-grid-service.md b/platform/docs/versioned_docs/version-3.0/platform/services/ui/viewport-grid-service.md deleted file mode 100644 index 39e2378a327..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/services/ui/viewport-grid-service.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -sidebar_position: 6 -sidebar_label: Viewport Grid Service ---- - -# Viewport Grid Service - -## Overview - -This is a new UI service, that handles the grid layout of the viewer. - -## Interface - -For a more detailed look on the options and return values each of these methods -is expected to support, [check out it's interface in `@ohif/core`][interface] - -| API Member | Description | -| --------------------------------------------------------------------- | --------------------------------------------------- | -| `setActiveViewportIndex(index)` | Sets the active viewport index in the app | -| `getState()` | Gets the states of the viewport (see below) | -| `setDisplaySetsForViewport({ viewportIndex, displaySetInstanceUID })` | Sets displaySet for viewport based on displaySet Id | -| `setLayout({numCols, numRows, keepExtraViewports})` | Sets rows and columns. When the total number of viewports decreases, optionally keep the extra/offscreen viewports. | -| `reset()` | Resets the default states | -| `getNumViewportPanes()` | Gets the number of visible viewport panes | - -## Implementations - -| Implementation | Consumer | -| ---------------------- | -------------------------- | -| [ViewportGridProvider] | Baked into Dialog Provider | - -`*` - Denotes maintained by OHIF - -## State - -```js -const DEFAULT_STATE = { - // starting from null, hanging - // protocol will defined number of rows and cols - numRows: null, - numCols: null, - viewports: [ - /* - * { - * displaySetInstanceUID: string, - * } - */ - ], - activeViewportIndex: 0, -}; -``` diff --git a/platform/docs/versioned_docs/version-3.0/platform/themeing.md b/platform/docs/versioned_docs/version-3.0/platform/themeing.md deleted file mode 100644 index 852c5d3982c..00000000000 --- a/platform/docs/versioned_docs/version-3.0/platform/themeing.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: Theming ---- - -# Viewer: Theming - -`OHIF-v3` has introduced the -[`LayoutTemplateModule`](./extensions/modules/layout-template.md) which enables -addition of custom layouts. You can easily design your custom components inside -an extension and consume it via the layoutTemplate module you write. - -## Tailwind CSS - -[Tailwind CSS](https://tailwindcss.com/) is a utility-first CSS framework for -creating custom user interfaces. - -Below you can see a compiled version of the tailwind configs. Each section can -be edited accordingly. For instance screen size break points, primary and -secondary colors, etc. - -```js -module.exports = { - prefix: '', - important: false, - separator: ':', - theme: { - screens: { - sm: '640px', - md: '768px', - lg: '1024px', - xl: '1280px', - }, - colors: { - overlay: 'rgba(0, 0, 0, 0.8)', - transparent: 'transparent', - black: '#000', - white: '#fff', - initial: 'initial', - inherit: 'inherit', - - indigo: { - dark: '#0b1a42', - }, - aqua: { - pale: '#7bb2ce', - }, - - primary: { - light: '#5acce6', - main: '#0944b3', - dark: '#090c29', - active: '#348cfd', - }, - - secondary: { - light: '#3a3f99', - main: '#2b166b', - dark: '#041c4a', - active: '#1f1f27', - }, - - common: { - bright: '#e1e1e1', - light: '#a19fad', - main: '#fff', - dark: '#726f7e', - active: '#2c3074', - }, - - customgreen: { - 100: '#05D97C', - }, - - customblue: { - 100: '#c4fdff', - 200: '#38daff', - }, - }, - }, -}; -``` - -You can also use the color variable like before. For instance: - -```js -primary: { - default: β€˜var(--default-color)β€˜, - light: β€˜#5ACCE6’, - main: β€˜#0944B3’, - dark: β€˜#090C29’, - active: β€˜#348CFD’, -} -``` - -## White Labeling - -A white-label product is a product or service produced by one company (the -producer) that other companies (the marketers) rebrand to make it appear as if -they had made it - -[Wikipedia: White-Label Product](https://en.wikipedia.org/wiki/White-label_product) - -Current white-labeling options are limited. We expose the ability to replace the -"Logo" section of the application with a custom "Logo" component. You can do -this by adding a whiteLabeling key to your configuration file. - -```js -window.config = { - /** .. **/ - whiteLabeling: { - createLogoComponentFn: function(React) { - return React.createElement( - 'a', - { - target: '_blank', - rel: 'noopener noreferrer', - className: 'text-white underline', - href: 'http://radicalimaging.com', - }, - React.createElement('h5', {}, 'RADICAL IMAGING') - ); - }, - }, - /** .. **/ -}; -``` - -> You can simply use the stylings from tailwind CSS in the whiteLabeling - -In addition to text, you can also add your custom logo. You can put them -inside the platform/viewer/public/assets folder and use them in the -whiteLabeling section. - -```js -window.config = { - /** .. **/ - whiteLabeling: { - createLogoComponentFn: function(React) { - return React.createElement( - 'a', - { - target: '_self', - rel: 'noopener noreferrer', - className: 'text-purple-600 line-through', - href: '/', - }, - React.createElement('img', { - src: './assets/customLogo.svg', - // className: 'w-8 h-8', - }) - ); - }, - }, - /** .. **/ -}; -``` - -The output will look like - -![custom-logo](../assets/img/custom-logo.png) - - - - -[wikipedia]: https://en.wikipedia.org/wiki/White-label_product - diff --git a/platform/docs/versioned_docs/version-3.0/release-notes.md b/platform/docs/versioned_docs/version-3.0/release-notes.md deleted file mode 100644 index 242221bd7d9..00000000000 --- a/platform/docs/versioned_docs/version-3.0/release-notes.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: Release Notes ---- - -# Release Notes - -> New `OHIF-v3` architecture has made OHIF a general purpose extensible medical -> imaging **platform**, as opposed to a configurable viewer. - -## What's new in `OHIF-v3` - -`OHIF-v3` is our second try for a React-based viewer, and is the third version -of our medical image web viewers from the start. The summary of changes includes: - -- Addition of workflow modes - - Often, medical imaging use cases involves lots of specific workflows that - re-use functionalities. We have added the capability of workflow modes, that - enable people to customize user interface and configure application for - specific workflow. - - The idea is to re-use the functionalities that extensions provide and create - a workflow. Brain segmentation workflow is different from prostate - segmentation in UI for sure; however, they share the segmentation tools that - can be re-used. - - Our vision is that technical people focus of developing extensions which - provides core functionalities, and experts to build modes by picking the - appropriate functionalities from each extension. - -* UI has been completely redesigned with modularity and workflow modes in mind. -* New UI components have been built with Tailwind CSS -* Redux store has been removed from the viewer in favour of services backed by - React's Context API - -Below, you can find the gap analysis between the `OHIF-v2` and `OHIF-v3`: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
OHIF-v2 functionalitiesOHIF-v3Comment
Rendering of 2D images via Cornerstoneβœ…
Study Listβœ…
Series Browserβœ…
DICOM JSONβœ…
2D Tools via CornerstoneToolsβœ…
OpenID Connect standard authentication flow for connecting to identity providersβœ…
Internationalizationβœ…
Drag/drop DICOM data into the viewer (see https://viewer.ohif.org/local)βœ…
White-labelling: Easily replace the OHIF Logo with your logoβœ…
DICOM Whole-slide imaging viewportπŸ”œIn Progress
IHE Invoke Image Display - Standard-compliant launching of the viewer (e.g. from PACS or RIS)πŸ”œNot Started
DICOM PDF supportπŸ”œNot Started
Displaying non-renderable DICOM as HTMLπŸ”œNot Started
Segmentation supportπŸ”œNot Started
RT STRUCT supportπŸ”œNot Started
DICOM upload to PACSπŸ”œNot Started
Google Cloud adapterπŸ”œNot Started
VTK Extension + MIP / MPR layout❌Other plans that involves amazing news soon!
UMD Build (Embedded Viewer). ❌The problem is that this breaks a bunch of extensions that rely on third party scripts (e.g. VTK) which have their own web worker loaders.
diff --git a/platform/docs/versioned_docs/version-3.0/resources.md b/platform/docs/versioned_docs/version-3.0/resources.md deleted file mode 100644 index be7b10ed756..00000000000 --- a/platform/docs/versioned_docs/version-3.0/resources.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -sidebar_position: 9 -sidebar_label: Resources ---- - -# Resources - -Throughout the development of the OHIF Viewer, we have participated in various -conferences and "hackathons". In this page, we will provide the presentations -and other resources that we have provided to the community in the past: - -## 2022 - -### [NA-MIC Project Week 36th 2022 - Remote](https://github.com/NA-MIC/ProjectWeek/blob/master/PW36_2022_Virtual/README.md) - -The Project Week is a week-long hackathon of hands-on activity in which medical -image computing researchers. OHIF team participated and gave a talk on OHIF and -Cornerstone in the 36th Project Week: -[[Slides]](https://docs.google.com/presentation/d/1-GtOKmr2cQi-r3OFyseSmgLeurtB3KXUkGMx2pVLh1I/edit?usp=sharing) -[[Video]](https://vimeo.com/668339696/63a2c48de8) - -## 2021 - -### [NA-MIC Project Week 35th 2021 - Remote](https://github.com/NA-MIC/ProjectWeek/tree/master/PW35_2021_Virtual) - -The Project Week is a week-long hackathon of hands-on activity in which medical -image computing researchers. OHIF team participated in the 35th Project Week -in 2021. -[[Slides]](https://docs.google.com/presentation/d/1KYNjuiI8lT1foQ4P9TGNV0lBhM6H-5KBs0wkYj4JJbk/edit?usp=sharing) - -### Chan Zuckerberg Initiative (CZI) - -Project presentations and demonstrations of Essential Open Source Software for -Science (EOSS) grantees -[[Slides]](https://docs.google.com/presentation/d/1_CLtG2hsL3ZxOtV2olVnzBOzq-TMLrHLomOy3FiU4NE/edit?usp=sharing) -[[Video]](https://youtu.be/0FjKkTJO0Rc?t=3737) - -### Google Cloud Tech - -Healthcare Imaging with Cloud Healthcare API -[[Video]](https://www.youtube.com/watch?v=2MiX9ScHFhY) - -## 2020 - -### OHIF ITCR Pitch - -OHIF pitch for Informatics Technology for Cancer Research (ITCR) -[[Slides]](https://docs.google.com/presentation/d/1MZXnZrVAnjmhVIWqC-aRSvJOoMMRLhLddACdCa1TybM/edit?usp=sharing) -[[Video]](https://vimeo.com/678769373/625bdb8793) - -## 2019 - -### OHIF and VTK.js Training Course - -OHIF and Kitware collaboration to create a training course for OHIF and VTK.js -developers. Funding for this work was provided by Kitware (NIH NINDS -R44NS081792, NIH NINDS R42NS086295, NIH NIBIB and NIGMS R01EB021396, NIH NIBIB -R01EB014955), Isomics (NIH P41 EB015902), and Massachusetts General Hospital -(NIH U24 CA199460). - -1. Introduction to VTK.js and OHIF - [[Slides]](https://docs.google.com/presentation/d/1NCJxpfx_qUGJI_2DhbECzaOg0k-Z6b65QlUptCofN-A/edit#slide=id.p) - [[Video]](https://vimeo.com/375520781) -2. Developing with VTK.js - [[Slides]](https://docs.google.com/presentation/d/17TCS6EhFi6SWFIrcAJ-DFdFzFFL-WD9BBTv-owmMdDU/edit#slide=id.p) - [[Video]](https://vimeo.com/375521036) -3. VTK.js Architecture and Tooling - [[Slides]](https://docs.google.com/presentation/d/1Sr1OGxMSw0oCt46koKQbmwSIE11Kqq8MGtyW3W0ASpk/edit?usp=gmail_thread) - [[Video]](https://vimeo.com/375521810) -4. OHIF + VTK.js Integration - [[Slides]](https://docs.google.com/presentation/d/1Iwg-u01HGVf1CgC6NbcBD3gm3uHN9WhjU59FSz55TN8/edit?ts=5d9c9ce4#slide=id.g59aa99cda4_0_131) - [[Video]](https://vimeo.com/375521206) - -## 2017 - -### Lesion Tracker - -LesionTracker: Extensible Open-Source Zero-Footprint Web Viewer for Cancer -Imaging Research and Clinical Trials. This project was supported in part by -grant U24 CA199460 from the National Cancer Institute (NCI) Informatics -Technology for Cancer Research (ITCR) Program. -[[Video]](https://www.youtube.com/watch?v=gUIPtoSBL-Q) - -### OHIF Community Meeting - June - -[[Slides]](https://docs.google.com/presentation/d/1K9Y6eP5DYTXoDlfwCZE6GkCUp83AK4_40YQS0dlzVBo/edit?usp=sharing) - -## 2016 - -### Imaging Community Call - -Open Source Oncology Web Viewer; Presentation by Gordon J. Harris -[[Slides]](https://www.slideshare.net/imgcommcall/lesiontracker) - -### OHIF Community Meeting - June - -[[Slides]](https://docs.google.com/presentation/d/1Ai25mBG0ZWUPhaadp3VnbCVmkYs9K51sQ8osMixrvJ0/edit?usp=sharing) - -### OHIF Community Meeting - September - -[[Slides]](https://docs.google.com/presentation/d/1iYZoU7v7KHSLHiKwH1_9_wweAkG7RGnyxrWeeHva4zQ/edit?usp=sharing) diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/_category_.json b/platform/docs/versioned_docs/version-3.0/user-guide/_category_.json deleted file mode 100644 index 68ea78e7844..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "User Guide", - "position": 2 -} diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/index.md b/platform/docs/versioned_docs/version-3.0/user-guide/index.md deleted file mode 100644 index 52f44bad8cb..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/index.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -sidebar_position: 2 -sidebar_label: Study List ---- - -# Study List - -## Overview - -The first page you will see when the viewer is loaded is the `Study List`. In -this page you can explore all the studies that are stored on the configured -server for the `OHIF Viewer`. - -![user-study-list](../assets/img/user-study-list.png) - -## Sorting - -When the Study List is opened, the application queries the PACS for 101 studies -by default. If there are greater than 100 studies returned, the default sort for -the study list is dictated by the image archive that hosts these studies for the -viewer and study list sorting will be disabled. If there are less than or equal -to 100 studies returned, they will be sorted by study date (most recent to -oldest) and study list sorting will be enabled. Whenever a query returns greater -than 100 studies, use filters to narrow results below 100 studies to enable -Study List sorting. - -## Filters - -There are certain filters that can be used to limit the study list to the -desired criteria. - -- Patient Name: Searches between patients names -- MRN: Searches between patients Medical Record Number -- Study Date: Filters the date of the acquisition -- Description: Searches between study descriptions -- Modality: Filters the modalities -- Accession: Searches between patients accession number - -An example of using study list filter is shown below: - -![user-study-filter](../assets/img/user-study-filter.png) - -Below the study list are pagination options for 25, 50, or 100 studies per page. - -![user-study-next](../assets/img/user-study-next.png) - -## Study Summary - -Click on a study to expand the study summary panel. - -![user-study-summary](../assets/img/user-study-summary.png) - -A summary of series available in the study is shown, which contains the series -description, series number, modality of the series, instances in the series, and -buttons to launch viewer modes to display the study. - -## Study Specific Modes - -All available modes are seen in the study expanded view. Modes can be enabled or -disabled for a study based on the modalities contained within the study. - -In the screenshot below, there are two modes shown for the selected study - -- Basic Viewer: Default mode that enables rendering and measurement tracking - -- PET/CT Fusion: Mode for visualizing the PET CT study in a 3x3 format. - -Based on the mode configurations (e.g., available modalities), PET/CT mode is -disabled for studies that do not contain PET AND CT images. - - - -![user-studyist-modespecific](../assets/img/user-studyist-modespecific.png) - -The previous screenshot shows a study containing PET and CT images and both -Basic Viewer and PET/CT Mode are available. - -## View Study - -The `Basic Viewer` mode is available for all studies by default. Click on the -mode button to launch the viewer. - -![user-open-viewer](../assets/img/user-open-viewer.png) diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/Language.md b/platform/docs/versioned_docs/version-3.0/user-guide/viewer/Language.md deleted file mode 100644 index 9032ecc5f62..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/Language.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -sidebar_position: 8 ---- - -# Language - -OHIF supports internationalization capabilities and setting the general language -of the Viewer. - -It should be noted that we don't have complete translations for all the components -and all the languages; however, you can easily add the key value translation pairs -following developer guides. - -Summary of language changing usage can be seen below: - - - -## Overview Video - -
- -
diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/_category_.json b/platform/docs/versioned_docs/version-3.0/user-guide/viewer/_category_.json deleted file mode 100644 index 417861dba3d..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Basic Viewer", - "position": 2 -} diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/hotkeys.md b/platform/docs/versioned_docs/version-3.0/user-guide/viewer/hotkeys.md deleted file mode 100644 index 5d8aac1fb47..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/hotkeys.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -sidebar_position: 7 ---- - -# Hotkeys - -To open the hotkey assignment panel, you can click on the Preferences gear on the -top right side of the viewer. - - -Below, you can see the default hotkeys key bindings: - -![user-hotkeys-default](../../assets/img/user-hotkeys-default.png) - -Hotkeys can be assigned to custom bindings that persist for the duration of the browser session. diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/index.md b/platform/docs/versioned_docs/version-3.0/user-guide/viewer/index.md deleted file mode 100644 index 6918ce3b1b8..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -sidebar_position: 1 -sidebar_label: Overview ---- - - -# Overview -When you open a mode, viewport, toolbar and panels of the mode get shown. -It is important to note that each mode has a different UI, which serves its purpose. -Here we explain various components of `Basic Viewer` mode which includes measurement -tracking functionalities. - -Basic viewer mode (longitudinal): - -![user-viewer](../../assets/img/user-viewer.png) - -Let's break different aspects of the viewer to the main components: - -- Left Panel (study panel): displays series thumbnails with series details -- Viewport: renders the image and displays annotations -- Right Panel (measurements): displays annotations details -- Toolbar: displays tools and logo - -![user-viewer-components](../../assets/img/overview.png) - - - - -Now, we explain each component and its sub-elements in detail. diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/measurement-panel.md b/platform/docs/versioned_docs/version-3.0/user-guide/viewer/measurement-panel.md deleted file mode 100644 index b760bf37e46..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/measurement-panel.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -sidebar_position: 3 ---- - -# Measurement Panel - -## Introduction -In `Basic Viewer` mode, the right panel is the `Measurement Panel`. The Measurement Panel can be expanded or hidden by clicking on the arrow to the left of `Measurements`. - -Select a measurement tool and mark an image to initiate measurement tracking. A pop-up will ask if you want to track measurements for the series on which the annotation was drawn. - -![user-measurement-panel-modal](../../assets/img/measurement-panel-prompt.png) - - - - - -If you select `Yes`, the series becomes a `tracked series`, and the current drawn measurement and next measurements are shown on the measurement panel on the right. - -![user-measurement-panel-tracked](../../assets/img/measurement-panel-tracked.png) - -If you select `No`, the measurement becomes temporary. The next annotation made will repeat the measurement tracking prompt. - -If you select `No, do not ask again`, all annotations made on the study will be temporary. - -![measurement-temporary](../../assets/img/measurement-temporary.png) - - -## Labeling Measurements -You can edit the measurement name by hovering over the measurement and selecting the edit icon. You can also label or relabel a measurement by right-clicking on it in the viewport. - -![user-measurement-edit](../../assets/img/measurement-panel-1.png) - - - -## Deleting a Measurement -A measurement can be deleting by dragging it outside the image in the viewport or by right-clicking on the measurement in the viewport and selecting 'Delete'. - - -## Jumping to a Measurement -Measurement navigation inside the top viewport can be used to move to previous and next measurement. - - -![measurements-prevNext](../../assets/img/measurements-prevNext.png) - -If a series containing a measurement is currently being displayed in a viewport, you can jump to display the measurement in the viewport by clicking on it in the Measurement Panel. - -## Export Measurements - -You can export the measurements by clicking on the `Export`. A CSV file will get downloaded to your local computer containing the drawn measurements. - - -![user-measurement-export](../../assets/img/user-measurement-export.png) - - -If you have set up your DICOM server to be able to store instances from the viewer, then you are able to create a report by clicking on the `Create Report`. -This will create a DICOM Structured Report (SR) from the measurements and push it -to the server. - -For instance, running the Viewer on a local DCM4CHEE: - - - -
- -
- -## Overview Video -An overview of measurement drawing and exporting can be seen below: - - -
- -
diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/measurement-tracking.md b/platform/docs/versioned_docs/version-3.0/user-guide/viewer/measurement-tracking.md deleted file mode 100644 index a15f7e5dfb6..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/measurement-tracking.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -sidebar_position: 4 ---- - -# Measurement Tracking - -## Introduction -OHIF-V3's `Basic Viewer` implements a `Measurement Tracking` workflow. Measurement -tracking allows you to: - -- Draw annotations and have them shown in the measurement panel -- Create a report from the tracked measurement and export them as DICOM SR -- Use already exported DICOM SR to re-hydrate the measurements in the viewer - - -## Status Icon -Each viewport has a left icon indicating whether the series within the viewport -contains: - -- tracked measurement OR -- untracked measurement OR -- Structured Report OR -- Locked (uneditable) Structured Report - -In the following, we will discuss each category. - -### Tracked vs Untracked Measurements - -`OHIF-v3` implements a workflow for measurement tracking that can be seen below. - -![user-measurement-panel-modal](../../assets/img/tracking-workflow1.png) - -In summary, when you create an annotation, a prompt will be shown whether to start tracking or not. If you start the tracking, the annotation style will change to a solid line, and annotation details get displayed on the measurement panel. -On the other hand, if you decline the tracking prompt, the measurement will be considered "temporary," and annotation style remains as a dashed line and not shown on the right panel, and cannot be exported. - - -Below, you can see different icons that appear for a tracked vs. untracked series in -`OHIF-v3`. - -![tracked-not-tracked](../../assets/img/tracked-not-tracked.png) - - - -#### Overview video for starting the tracking for measurements: - - -
- -
- - -

- -#### Overview video for not starting tracking for measurements: - - -
- -
- - -### Reading and Writing DICOM SR - -`OHIF-v3` provides full support for reading, writing and mapping the DICOM Structured -Report (SR) to interactable `Cornerstone Tools`. When you load an already exported -DICOM SR into the viewer, you will be prompted whether to track the measurements -for the series or not. - -![SR-exported](../../assets/img/SR-exported.png) - -If you click Yes, DICOM SR measurements gets re-hydrated into the viewer and -the series become a tracked series. However, If you say no and later decide to say track the measurements, you can always click on the SR button that will prompt you -with the same message again. - -![restore-exported-sr](../../assets/img/restore-exported-sr.png) - -The full workflow for saving measurements to SR and loading SR into the viewer is shown below. - -![user-measurement-panel-modal](../../assets/img/tracking-workflow2.png) -![user-measurement-panel-modal](../../assets/img/tracking-workflow3.png) - - -#### Overview video for loading DICOM SR and making a tracked series: - - -
- -
- -

- -#### Overview video for loading DICOM SR and not making a tracked series: - - -
- -
- -

- -
- -
- -### Loading DICOM SR into an Already Tracked Series - -If you have an already tracked series and try to load a DICOM SR measurements, -you will be shown the following lock icon. This means that, you can review the -DICOM SR measurement, manipulate image and draw "temporary" measurements; however, -you cannot edit the DICOM SR measurement. - - -![locked-sr](../../assets/img/locked-sr.png) - -

- - -#### Overview video for loading DICOM SR inside an already tracked series: - - - -
- -
diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/study-panel.md b/platform/docs/versioned_docs/version-3.0/user-guide/viewer/study-panel.md deleted file mode 100644 index 1b5190ffaeb..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/study-panel.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Study Panel - -In `Basic Viewer` mode, the left panel includes Studies related to the current -patient. You can see three main type of studies below - -- Primary: The opened study from the study list. This study is always expanded - by default. -- Recent: All studies for the patient that contain study dates within 1 year of - the primary study -- All: All studies available for the patient contained within the source - repository - -The `Study Panel` displays the measurement tracking status of each series within -a study. As you can see in the first picture, the dashed circle on the left side -of each series demonstrates whether the series is being tracked for measurement -or not. - - - -![user-study-panel](../../assets/img/user-study-panel.png) - -Studies can be expanded or collapsed by clicking on the study information in the -Study Panel. If a series is being tracking within a study, the Measurement Panel -will display this information while the study is collapsed. - - - - diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/toolbar.md b/platform/docs/versioned_docs/version-3.0/user-guide/viewer/toolbar.md deleted file mode 100644 index cb982ce25b8..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/toolbar.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -sidebar_position: 6 ---- - - -# Toolbar - -The four main components of the toolbar are: - -- Navigation back to the [Study List](../index.md) -- Logo and white labelling -- [Tools](#tools) -- [Preferences](#preferences) - -![user-viewer-toolbar](../../assets/img/user-viewer-toolbar.png) - - -## Tools -This section displays all the available tools inside the mode. -## Measurement tools -The basic viewer comes with the following default measurement tools: - -- Length Tool: Calculates the linear distance between two points in *mm* -- Bidirectional Tool: Creates a measurement of the longest diameter (LD) and longest perpendicular diameter (LPD) in *mm* -- Annotation: Used to create a qualitative marker with a freetext label -- Ellipse: Measures an elliptical area in *mm2* and Hounsfield Units (HU) -- Calibration Tool: Calibrate (or override) the Pixel Spacing Attribute (Physical distance in the patient between the center of each pixel, specified by a numeric pair - adjacent row spacing (delimiter) adjacent column spacing in mm) - -When a measurement tool is selected from the toolbar, it becomes the `active` tool. Use the caret to expand the measurement tools and select another tool. - - -![user-viewer-toolbar-measurements](../../assets/img/user-viewer-toolbar-measurements.png) - - -## Window/Level -The `Window/Level` tool enables manipulating the window level and window width of the rendered image. Click on the tool to enable freeform adjustment, then click and drag on the viewport to freely adjust the window/level. - -Click on the caret to expand the tool and choose from predefined W/L settings for common imaging scenarios. - - -![user-toolbar-preset](../../assets/img/user-toolbar-preset.png) - - -## Pan and Zoom -With the Zoom tool selected, click and drag the cursor on an image to adjust the zoom. The magnification level is displayed in the viewport. - -With the Pan tool selected, click and drag the cursor on an image to adjust the image position. - -## Image Capture -Click on the Camera icon to download a high quality image capture using common image formats (png, jpg) - -![user-toolbar-download-icon](../../assets/img/user-toolbar-download-icon.png) - -In the opened modal, the filename, image's width and height, and filetype and can be configured before downloading the image to your local computer. - -![user-toolbarDownload](../../assets/img/user-toolbarDownload.png) - - - -## Layout Selector -Please see the `Viewport` section for details. - - -## More Tools Menu -- Reset View: Resets all image manipulation such as position, zoom, and W/L -- Rotate Right: Flips the image 90 degrees clockwise -- Flip Horizontally: Flips the image 180 degrees horizontally -- Stack Scroll: Links all viewports containing images to scroll together -- Magnify: Click on an image to magnify a particular area of interest -- Invert: Inverts the color scale -- Cine: Toggles the Cine player control in the currently selected viewport. Click the `x` on the Cine player or click the tool again to toggle off. -- Angle: Measures an adjustable angle on an image -- Probe: Drag the probe to see pixel values -- Rectangle: Measures a rectangular area in mm^2 and HU - -When a tool is selected from the `More Tools` menu, it becomes the active tool until it is replaced by clicking on a different tool in the More Tools menu or main toolbar. - - -## Overview Video -An overview of tool usage can been seen below: - - -
- -
diff --git a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/viewport.md b/platform/docs/versioned_docs/version-3.0/user-guide/viewer/viewport.md deleted file mode 100644 index 173728ca153..00000000000 --- a/platform/docs/versioned_docs/version-3.0/user-guide/viewer/viewport.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -sidebar_position: 5 ---- - -# Viewport - -Image visualization happens at the viewport which contains canvas or canvases that -renders series. - -![user-viewer-main](../../assets/img/user-viewer-main.png) - - -By default, you can modify: - -- Zoom: right click dragging up or down -- Contrast/brightness: left click dragging up/down to change contrast, and left/right for changing brightness -- Pan: middle click dragging - - -## Changing Series for display -To change the displayed series, you can drag and drop the desired series from the left panel. Start, by dragging the thumbnail of the series, and drop it on the viewport. - -## Changing Layout -If you click on the layout icon on the toolbar, you can use the layout selector UI. After changing the layout, you can select studies for each new viewport by dragging and dropping in to the viewport. - -After changing the layout from 1x1, you will see each viewport gets tagged by a letter, -which matches its series section in the study list. - - -![user-viewer-layout](../../assets/img/user-viewer-layout.png) - - -## Overview Video -An overview of viewport layout change, and manipulation can be seen below: - - -
- -
diff --git a/platform/docs/versioned_sidebars/version-1.0-sidebars.json b/platform/docs/versioned_sidebars/version-1.0-deprecated-sidebars.json similarity index 100% rename from platform/docs/versioned_sidebars/version-1.0-sidebars.json rename to platform/docs/versioned_sidebars/version-1.0-deprecated-sidebars.json diff --git a/platform/docs/versioned_sidebars/version-2.0-sidebars.json b/platform/docs/versioned_sidebars/version-2.0-deprecated-sidebars.json similarity index 100% rename from platform/docs/versioned_sidebars/version-2.0-sidebars.json rename to platform/docs/versioned_sidebars/version-2.0-deprecated-sidebars.json diff --git a/platform/docs/versioned_sidebars/version-3.0-sidebars.json b/platform/docs/versioned_sidebars/version-3.0-sidebars.json deleted file mode 100644 index caea0c03ba6..00000000000 --- a/platform/docs/versioned_sidebars/version-3.0-sidebars.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "tutorialSidebar": [ - { - "type": "autogenerated", - "dirName": "." - } - ] -} diff --git a/platform/docs/versions.json b/platform/docs/versions.json index 8858c6ab305..fe701e38475 100644 --- a/platform/docs/versions.json +++ b/platform/docs/versions.json @@ -1 +1 @@ -["2.0"] +["2.0-deprecated", "1.0-deprecated"] diff --git a/yarn.lock b/yarn.lock index 09ee9082529..1e36f10b442 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1589,10 +1589,10 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@cornerstonejs/adapters@^1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@cornerstonejs/adapters/-/adapters-1.1.8.tgz#0d3ffc5befa543fe69beec9f2a66bd75d564a4c9" - integrity sha512-NOq1FTO9IY1XmjY8wE0UpBYMKiX6XFQb4Hyh7M56jRZRh5knpzReI+eIf+N4P1rYMt+I6aUqMJDQhn3QiXTvAQ== +"@cornerstonejs/adapters@^1.2.4": + version "1.2.4" + resolved "https://registry.npmjs.org/@cornerstonejs/adapters/-/adapters-1.2.4.tgz#9920ca4cae2acf064ba3165cde6da67123fbc25e" + integrity sha512-d2wl49d45QdjM9F5ATkO1g8/PoTqTSehk7wYdgEfFXmXbl8FVfaat/PAMDiyRZ65CBctmWcGcgyoFS14U9KvHQ== dependencies: "@babel/runtime-corejs2" "^7.17.8" dcmjs "^0.29.5" @@ -1640,43 +1640,43 @@ resolved "https://registry.yarnpkg.com/@cornerstonejs/codec-openjph/-/codec-openjph-2.4.2.tgz#e96721d56f6ec96f7f95c16321d88cc8467d8d81" integrity sha512-lgdvBvvNezleY+4pIe2ceUsJzlZe/0PipdeubQ3vZZOz3xxtHHMR1XFCl4fgd8gosR8COHuD7h6q+MwgrwBsng== -"@cornerstonejs/core@^1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@cornerstonejs/core/-/core-1.1.8.tgz#8040055e45fc74d91b1f6b32b8974947b696e4fc" - integrity sha512-2dcSBYhhKoHaiN7+pQkKNmH5JzymXThx+JzLzG4F5BDGYfHOL2A1bxhVsYGhnbZNIfbxBOPQuIchXJjnfwuFeg== +"@cornerstonejs/core@^1.2.4": + version "1.2.4" + resolved "https://registry.npmjs.org/@cornerstonejs/core/-/core-1.2.4.tgz#98c480f0db3cc98477f1160b47e8c686357e794b" + integrity sha512-CRrpn744m8e6damEdJaE6spF1C7/qS/h2OZiaHQnobDkJHdnSU8JHcPeP4NuMI0eRjk8NL/nGadVF4YXDOSppg== dependencies: "@kitware/vtk.js" "27.3.1" detect-gpu "^5.0.22" gl-matrix "^3.4.3" lodash.clonedeep "4.5.0" -"@cornerstonejs/dicom-image-loader@^1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.1.8.tgz#3202f5a1bb3c443620582535ca85fb2c5a50d779" - integrity sha512-Dltl8VSeaODZ8+T1n1vE7j0+wgCD/TJnLN/C6BnnlssH2wD6SrZyq2m3VMR9mLr104rnuegdXr1GeH0BPJ/ojw== +"@cornerstonejs/dicom-image-loader@^1.2.4": + version "1.2.4" + resolved "https://registry.npmjs.org/@cornerstonejs/dicom-image-loader/-/dicom-image-loader-1.2.4.tgz#d917768788d222918c0c5e7e29d7968922fbaf5c" + integrity sha512-b1FHjqc+j4QaWUtEw8JeQGmTsejYfbDwdIBP5GKh7EuHjrURA0N+JThau2fYHL7oNjYmDvNx9OW9A4dYswI0mg== dependencies: "@cornerstonejs/codec-charls" "^1.2.3" "@cornerstonejs/codec-libjpeg-turbo-8bit" "^1.2.2" "@cornerstonejs/codec-openjpeg" "^1.2.2" "@cornerstonejs/codec-openjph" "^2.4.2" - "@cornerstonejs/core" "^1.1.8" + "@cornerstonejs/core" "^1.2.4" dicom-parser "^1.8.9" pako "^2.0.4" uuid "^9.0.0" -"@cornerstonejs/streaming-image-volume-loader@^1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.1.8.tgz#1db9b675670d40a58c1d76120e506c4b044d1dd1" - integrity sha512-TkN7gAcGEO3JaDCyJCHcNO5EyLQLA+ndmsRIHkbaePO91Y+wY3vTsir7alBXs6PIxaM4gRNJmAdHNEKXJixMxw== +"@cornerstonejs/streaming-image-volume-loader@^1.2.4": + version "1.2.4" + resolved "https://registry.npmjs.org/@cornerstonejs/streaming-image-volume-loader/-/streaming-image-volume-loader-1.2.4.tgz#cf5c55a44cb736b220b2a7e02a4e3ffc6fc09353" + integrity sha512-MfMz6rvI+Buhd+6OSJRqGHO/8Ol2HSAcSjltXaJ0Sc5YQ6tnzNEYGqnADY/E8mLCFIj/d2l6sT3Uy76USn+ODQ== dependencies: - "@cornerstonejs/core" "^1.1.8" + "@cornerstonejs/core" "^1.2.4" -"@cornerstonejs/tools@^1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@cornerstonejs/tools/-/tools-1.1.8.tgz#dc3f73c6e9b1355d592397536a4435a2fb17cce8" - integrity sha512-uc8f2ck0mZZ5TcCw6Erz87sRM9nezpNKGELMRlBO1QR/podEUBjAxhIWnHkJf4nRSB5BGQ9+xaYKC4jZ1q54jg== +"@cornerstonejs/tools@^1.2.4": + version "1.2.4" + resolved "https://registry.npmjs.org/@cornerstonejs/tools/-/tools-1.2.4.tgz#292cc0782158811ab623ee96fb2ba9d7e2fd22e6" + integrity sha512-EM2wf1unzMZ5RPj5hCZP5SDarOO8P1uK9ORZ3aEKL0q+d0xdirKTzazp38cC+Deavda460Q9KmaHCPTtSHfE1g== dependencies: - "@cornerstonejs/core" "^1.1.8" + "@cornerstonejs/core" "^1.2.4" lodash.clonedeep "4.5.0" lodash.get "^4.4.2"
-

Our translation management is powered by - Locize - through their generous support of open source.

- - Locize Translation Management Logo - -