@aics/vole-app 3.2.3 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/aics-image-viewer/components/App/index.js +8 -3
- package/es/aics-image-viewer/components/AxisClipSliders/index.js +2 -1
- package/es/aics-image-viewer/components/ErrorAlert/index.js +16 -6
- package/es/aics-image-viewer/components/ErrorAlert/styles.css +8 -4
- package/es/aics-image-viewer/components/StyleProvider/index.js +25 -7
- package/es/aics-image-viewer/components/Toolbar/index.js +38 -1
- package/es/aics-image-viewer/components/Toolbar/styles.css +21 -0
- package/es/aics-image-viewer/components/useVolume.js +42 -40
- package/es/aics-image-viewer/shared/constants.js +2 -0
- package/es/aics-image-viewer/shared/utils/sceneStore.js +18 -7
- package/es/aics-image-viewer/shared/utils/test/urlParsing.test.js +10 -2
- package/es/aics-image-viewer/shared/utils/urlParsing.js +17 -3
- package/es/aics-image-viewer/state/store.js +24 -6
- package/es/aics-image-viewer/state/subscribers.js +22 -1
- package/es/aics-image-viewer/state/test/reset.test.js +3 -1
- package/package.json +2 -2
- package/type-declarations/aics-image-viewer/components/Toolbar/index.d.ts +3 -0
- package/type-declarations/aics-image-viewer/components/useVolume.d.ts +2 -2
- package/type-declarations/aics-image-viewer/shared/utils/sceneStore.d.ts +1 -1
- package/type-declarations/aics-image-viewer/shared/utils/urlParsing.d.ts +7 -1
- package/type-declarations/aics-image-viewer/state/store.d.ts +2 -0
- package/type-declarations/aics-image-viewer/state/types.d.ts +2 -0
|
@@ -113,6 +113,7 @@ var App = function App(props) {
|
|
|
113
113
|
var time = useViewerState(select("time"));
|
|
114
114
|
var showAxes = useViewerState(select("showAxes"));
|
|
115
115
|
var channelSettings = useViewerState(select("channelSettings"));
|
|
116
|
+
var changeViewerSetting = useViewerState(select("changeViewerSetting"));
|
|
116
117
|
var changeChannelSetting = useViewerState(select("changeChannelSetting"));
|
|
117
118
|
var applyColorPresets = useViewerState(select("applyColorPresets"));
|
|
118
119
|
var resetToSavedState = useViewerState(select("resetToSavedViewerState"));
|
|
@@ -264,10 +265,12 @@ var App = function App(props) {
|
|
|
264
265
|
_useState2 = _slicedToArray(_useState, 2),
|
|
265
266
|
loadedScene = _useState2[0],
|
|
266
267
|
setLoadedScene = _useState2[1];
|
|
267
|
-
var onChangeScene = useCallback(function (image, sceneIndex) {
|
|
268
|
+
var onChangeScene = useCallback(function (image, sceneIndex, loadSpec) {
|
|
269
|
+
changeViewerSetting("time", loadSpec.time);
|
|
268
270
|
onImageTitleChange === null || onImageTitleChange === void 0 || onImageTitleChange(image.imageInfo.imageInfo.name);
|
|
269
271
|
setLoadedScene(sceneIndex);
|
|
270
|
-
|
|
272
|
+
changeViewerSetting("scaleLevelIndex", image.imageInfo.multiscaleLevel);
|
|
273
|
+
}, [onImageTitleChange, changeViewerSetting]);
|
|
271
274
|
var onChannelLoaded = useCallback(function (image, channelIndex, isInitialLoad) {
|
|
272
275
|
// TODO this was once a search by name - is that still necessary or will
|
|
273
276
|
// the index always be correct?
|
|
@@ -585,7 +588,9 @@ var App = function App(props) {
|
|
|
585
588
|
resetCamera: resetCamera,
|
|
586
589
|
downloadScreenshot: saveScreenshot,
|
|
587
590
|
resetToSavedViewerState: resetToSavedViewerState,
|
|
588
|
-
visibleControls: visibleControls
|
|
591
|
+
visibleControls: visibleControls,
|
|
592
|
+
multiscaleDims: image === null || image === void 0 ? void 0 : image.imageInfo.imageInfo.multiscaleLevelDims,
|
|
593
|
+
multiscaleIndex: image === null || image === void 0 ? void 0 : image.imageInfo.multiscaleLevel
|
|
589
594
|
}), /*#__PURE__*/React.createElement(CellViewerCanvasWrapper, {
|
|
590
595
|
view3d: view3d,
|
|
591
596
|
image: image,
|
|
@@ -287,7 +287,8 @@ var AxisClipSliders = function AxisClipSliders(props) {
|
|
|
287
287
|
onChange: function onChange(_ref6) {
|
|
288
288
|
var _ref7 = _slicedToArray(_ref6, 1),
|
|
289
289
|
scene = _ref7[0];
|
|
290
|
-
|
|
290
|
+
props.changeViewerSetting("scene", scene);
|
|
291
|
+
props.changeViewerSetting("useExactScaleLevel", false);
|
|
291
292
|
}
|
|
292
293
|
})))));
|
|
293
294
|
};
|
|
@@ -17,6 +17,7 @@ import { RightOutlined } from "@ant-design/icons";
|
|
|
17
17
|
import { Alert, Button } from "antd";
|
|
18
18
|
import React from "react";
|
|
19
19
|
import { useConstructor } from "../../shared/utils/hooks";
|
|
20
|
+
import { useViewerState } from "../../state/store";
|
|
20
21
|
import "./styles.css";
|
|
21
22
|
var IssueLink = function IssueLink(_ref) {
|
|
22
23
|
var bug = _ref.bug,
|
|
@@ -32,7 +33,7 @@ var UNKNOWN_ERROR_DESCRIPTION = /*#__PURE__*/React.createElement(React.Fragment,
|
|
|
32
33
|
}, "send us a bug report here"), ".");
|
|
33
34
|
var ERROR_TYPE_DESCRIPTIONS = _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty({}, VolumeLoadErrorType.UNKNOWN, /*#__PURE__*/React.createElement(React.Fragment, null, "An unknown error occurred while loading volume data. Check the browser console (F12) for more details. If this looks like a bug, ", /*#__PURE__*/React.createElement(IssueLink, {
|
|
34
35
|
bug: true
|
|
35
|
-
}, "send us a bug report here"), ".")), VolumeLoadErrorType.NOT_FOUND, /*#__PURE__*/React.createElement(React.Fragment, null, "The viewer was unable to find any volume data at the specified location. Check that the provided URL is correct and try again.")), VolumeLoadErrorType.TOO_LARGE, /*#__PURE__*/React.createElement(React.Fragment, null, "No
|
|
36
|
+
}, "send us a bug report here"), ".")), VolumeLoadErrorType.NOT_FOUND, /*#__PURE__*/React.createElement(React.Fragment, null, "The viewer was unable to find any volume data at the specified location. Check that the provided URL is correct and try again.")), VolumeLoadErrorType.TOO_LARGE, /*#__PURE__*/React.createElement(React.Fragment, null, "No resolution level is available for this volume which fits within our maximum memory footprint. This maximum is tuned to ensure compatibility with the majority of browsers. If you're trying to load your own OME-Zarr dataset, you may be able to open this volume by including a lower resolution level.")), VolumeLoadErrorType.LOAD_DATA_FAILED, /*#__PURE__*/React.createElement(React.Fragment, null, "The viewer was able to find a source of volume data at the specified location, but encountered an error while trying to load it. Check that your dataset is complete and properly formatted. You can also check the browser console (F12) for more details about this error. If it looks like a problem on our end,", " ", /*#__PURE__*/React.createElement(IssueLink, {
|
|
36
37
|
bug: true
|
|
37
38
|
}, "start a bug report here"), ".")), VolumeLoadErrorType.INVALID_METADATA, /*#__PURE__*/React.createElement(React.Fragment, null, "The viewer was unable to read all necessary information from this volume's metadata. Check that your dataset's metadata is complete and properly formatted. If you believe your data is valid and should be supported by our viewer, let us know by ", /*#__PURE__*/React.createElement(IssueLink, null, "opening a GitHub issue"), ".")), VolumeLoadErrorType.INVALID_MULTI_SOURCE_ZARR, /*#__PURE__*/React.createElement(React.Fragment, null, "The viewer is currently configured to consolidate multiple OME-Zarr datasets into a single volume, but the provided datasets can't all be matched up. Ensure that all dataset URLs are correct and that at least one equivalently-sized scale level exists in all datasets."));
|
|
38
39
|
var getErrorTitle = function getErrorTitle(error) {
|
|
@@ -45,6 +46,9 @@ var getErrorDescription = function getErrorDescription(error) {
|
|
|
45
46
|
if (!type) {
|
|
46
47
|
return _typeof(error) === "object" && error !== null && error.description || UNKNOWN_ERROR_DESCRIPTION;
|
|
47
48
|
}
|
|
49
|
+
if (type === VolumeLoadErrorType.TOO_LARGE && useViewerState.getState().useExactScaleLevel) {
|
|
50
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, "The viewer cannot load this resolution level within memory limits. Try again with a smaller resolution level.");
|
|
51
|
+
}
|
|
48
52
|
return (_ERROR_TYPE_DESCRIPTI2 = ERROR_TYPE_DESCRIPTIONS[type]) !== null && _ERROR_TYPE_DESCRIPTI2 !== void 0 ? _ERROR_TYPE_DESCRIPTI2 : UNKNOWN_ERROR_DESCRIPTION;
|
|
49
53
|
};
|
|
50
54
|
var ErrorAlert = function ErrorAlert(_ref2) {
|
|
@@ -62,16 +66,22 @@ var ErrorAlert = function ErrorAlert(_ref2) {
|
|
|
62
66
|
errorsSeenCount = _React$useState4[0],
|
|
63
67
|
setErrorsSeenCount = _React$useState4[1];
|
|
64
68
|
var error = Array.isArray(errors) ? errors[0] : errors;
|
|
65
|
-
var
|
|
69
|
+
var infoStyle = {
|
|
70
|
+
display: showDetails ? undefined : "none"
|
|
71
|
+
};
|
|
72
|
+
var errorMessage = /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
73
|
+
className: "error-title"
|
|
74
|
+
}, getErrorTitle(error) + (firstErrorCount > 1 ? " (".concat(firstErrorCount, ")") : ""), " ", /*#__PURE__*/React.createElement(Button, {
|
|
66
75
|
type: "text",
|
|
67
76
|
onClick: function onClick() {
|
|
68
77
|
return setShowDetails(!showDetails);
|
|
69
78
|
}
|
|
70
79
|
}, showDetails ? "Show less info" : "Show more info")), /*#__PURE__*/React.createElement("div", {
|
|
71
|
-
style:
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
style: infoStyle
|
|
81
|
+
}, getErrorDescription(error)), error.cause !== undefined && /*#__PURE__*/React.createElement("div", {
|
|
82
|
+
className: "error-cause",
|
|
83
|
+
style: infoStyle
|
|
84
|
+
}, "Caused by ", getErrorTitle(error.cause)));
|
|
75
85
|
var skipErrorButton = Array.isArray(errors) && errors.length > 1 && /*#__PURE__*/React.createElement(Button, {
|
|
76
86
|
type: "text",
|
|
77
87
|
onClick: function onClick() {
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
z-index:5000;
|
|
8
8
|
border-color:#dc4446;
|
|
9
9
|
padding:12px 30px;
|
|
10
|
+
color:var(--color-text-section);
|
|
10
11
|
}
|
|
11
12
|
.load-error-alert .ant-alert-icon,
|
|
12
13
|
.load-error-alert .ant-alert-close-icon,
|
|
@@ -19,7 +20,10 @@
|
|
|
19
20
|
.load-error-alert .ant-btn-text:hover{
|
|
20
21
|
color:#25affe !important;
|
|
21
22
|
}
|
|
22
|
-
.load-error-alert .ant-alert-message div
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
.load-error-alert .ant-alert-message > div.error-title{
|
|
24
|
+
font-weight:600;
|
|
25
|
+
}
|
|
26
|
+
.load-error-alert .ant-alert-message > div.error-cause{
|
|
27
|
+
font-style:italic;
|
|
28
|
+
color:var(--color-text-body);
|
|
29
|
+
}
|
|
@@ -19,9 +19,13 @@ var palette = {
|
|
|
19
19
|
veryDarkPurple: "#5f369f",
|
|
20
20
|
veryLtPurple: "#e7e4f2",
|
|
21
21
|
brightRed: "#ff4d4d",
|
|
22
|
+
brightYellow: "#e39b0d",
|
|
22
23
|
brightGreen: "#61d900",
|
|
23
24
|
veryBrightGreen: "#61ff00",
|
|
24
|
-
brightBlue: "#0099ff"
|
|
25
|
+
brightBlue: "#0099ff",
|
|
26
|
+
veryBrightBlue: "#0dc4d9",
|
|
27
|
+
darkBlue: "#29484c",
|
|
28
|
+
darkYellow: "#4c3c29"
|
|
25
29
|
};
|
|
26
30
|
var theme = {
|
|
27
31
|
colors: {
|
|
@@ -31,7 +35,7 @@ var theme = {
|
|
|
31
35
|
primaryDk: palette.darkPurple,
|
|
32
36
|
success: palette.brightGreen,
|
|
33
37
|
error: palette.brightRed,
|
|
34
|
-
warning: palette.
|
|
38
|
+
warning: palette.brightYellow,
|
|
35
39
|
info: palette.brightBlue
|
|
36
40
|
},
|
|
37
41
|
text: {
|
|
@@ -121,6 +125,16 @@ var theme = {
|
|
|
121
125
|
selectedBg: palette.medGrey,
|
|
122
126
|
textPlaceholder: palette.ltPurple
|
|
123
127
|
},
|
|
128
|
+
alert: {
|
|
129
|
+
warning: {
|
|
130
|
+
text: palette.brightYellow,
|
|
131
|
+
bg: palette.darkYellow
|
|
132
|
+
},
|
|
133
|
+
info: {
|
|
134
|
+
text: palette.veryBrightBlue,
|
|
135
|
+
bg: palette.darkBlue
|
|
136
|
+
}
|
|
137
|
+
},
|
|
124
138
|
tooltip: {
|
|
125
139
|
bg: palette.black
|
|
126
140
|
},
|
|
@@ -138,7 +152,7 @@ var theme = {
|
|
|
138
152
|
/** Makes theme styling available to child components via CSS variables. */
|
|
139
153
|
var CssProvider = styled.div(_templateObject || (_templateObject = _taggedTemplateLiteral(["\n width: 100%;\n height: 100%;\n\n ", "\n\n h1, h2, h3, h4, p {\n font-family: var(--font-family);\n }\n\n h1 {\n color: var(--color-text-header);\n font-size: 28px;\n font-weight: 400;\n }\n\n h2 {\n color: var(--color-text-section);\n font-size: 19px;\n font-weight: 400;\n }\n\n h3 {\n color: var(--color-text-header);\n font-size: 16px;\n font-weight: 600;\n }\n\n h4 {\n color: var(--color-text-header);\n font-size: 14px;\n font-weight: 400;\n }\n\n p {\n color: var(--color-text-body);\n font-size: 14px;\n font-weight: 400;\n }\n\n a {\n color: var(--color-text-link);\n }\n\n & *::selection {\n background-color: var(--color-text-selection-bg);\n color: var(--color-text-selection-text);\n }\n\n /** TODO: Go through these styles and see if we can use Ant ConfigProvider for them instead. */\n .ant-btn-link,\n .ant-btn-text,\n .ant-btn-primary,\n .ant-btn-icon-only {\n box-shadow: none;\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: var(--color-button-primary-hover-bg);\n border-color: var(--color-button-primary-hover-bg);\n color: var(--color-button-primary-text);\n }\n\n &:active:not(:disabled) {\n background-color: var(--color-button-primary-hover-bg);\n border: 1px solid var(--color-button-primary-active-outline);\n color: var(--color-button-primary-text);\n }\n }\n\n /* Let us use buttons with type=\"text\" as purely semantic containers - don't bring any styling! */\n .ant-btn-text {\n width: unset;\n height: unset;\n padding: unset;\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: unset;\n border-color: transparent;\n }\n }\n\n .ant-btn-icon-only:disabled {\n color: var(--color-button-icon-disabled-text);\n }\n\n .ant-btn-link:not(:disabled) {\n // Change from default blue link text\n color: var(--color-button-link-text);\n }\n\n /**\n * Tertiary style buttons. Grey outline by default, turns to light\n * purple outline on hover.\n */\n .ant-btn-default:not(.ant-btn-icon-only) {\n background-color: var(--color-button-tertiary-bg);\n color: var(--color-button-tertiary-text);\n border-color: var(--color-button-tertiary-outline);\n\n &:hover:not(:disabled),\n &:focus-visible:not(:disabled) {\n background-color: transparent;\n border-color: var(--color-button-tertiary-hover-bg);\n color: var(--color-button-tertiary-hover-text);\n }\n\n &:active:not(:disabled) {\n background-color: transparent;\n border-color: var(--color-button-tertiary-active-outline);\n color: var(--color-button-tertiary-active-text);\n }\n }\n\n // Overrides for checkbox styling\n & .ant-checkbox-input {\n &:hover,\n &:focus-visible {\n border: 1px solid white;\n }\n }\n\n & .ant-checkbox.ant-checkbox-checked {\n background-color: var(--color-checkbox-bg);\n }\n\n .ant-checkbox-inner {\n background-color: transparent !important;\n }\n\n // Add outlines to modals and dropdowns\n & .ant-select-dropdown,\n & .ant-dropdown-menu,\n & .ant-modal-content {\n border: 1px solid var(--color-modal-border);\n }\n\n // Force active/hovered text to be white instead of grey for better contrast\n & .ant-dropdown-menu-item-active {\n color: var(--color-menu-hover-text);\n }\n\n // Remove padding in dropdown menus and make items reactangular + flush with the edge\n & .ant-dropdown-menu,\n & .ant-select-dropdown {\n padding: 0;\n overflow: hidden;\n\n & .ant-dropdown-menu-item,\n & .ant-select-item {\n border-radius: 0;\n }\n }\n"])), function (_ref) {
|
|
140
154
|
var $theme = _ref.$theme;
|
|
141
|
-
return css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n /* Component and color variables. */\n // TODO: Fix inconsistent use of border vs. outline\n // TODO: Remove variables that aren't used in other CSS files. These should be set directly\n // from the $theme object to reduce unnecessary variables.\n --color-text-link: ", ";\n --color-text-header: ", ";\n --color-text-section: ", ";\n --color-text-body: ", ";\n --color-text-error: ", ";\n\n --color-text-selection-bg: ", ";\n --color-text-selection-text: ", ";\n\n --color-header-title: ", ";\n --color-header-hover-title: ", ";\n --color-header-bg: ", ";\n --color-header-border: ", ";\n\n --color-button-primary-bg: ", ";\n --color-button-primary-text: ", ";\n --color-button-primary-hover-bg: ", ";\n --color-button-primary-active-bg: ", ";\n --color-button-primary-active-outline: ", ";\n --color-button-primary-disabled-bg: ", ";\n\n --color-button-link-text: ", ";\n\n --color-button-secondary-bg: ", ";\n --color-button-secondary-text: ", ";\n --color-button-secondary-outline: ", ";\n\n --color-button-tertiary-bg: transparent;\n --color-button-tertiary-text: ", ";\n --color-button-tertiary-outline: ", ";\n --color-button-tertiary-hover-outline: ", ";\n --color-button-tertiary-hover-text: ", ";\n --color-button-tertiary-active-outline: ", ";\n --color-button-tertiary-active-text: ", ";\n\n --color-button-icon-disabled-text: ", ";\n --color-button-icon-
|
|
155
|
+
return css(_templateObject2 || (_templateObject2 = _taggedTemplateLiteral(["\n /* Component and color variables. */\n // TODO: Fix inconsistent use of border vs. outline\n // TODO: Remove variables that aren't used in other CSS files. These should be set directly\n // from the $theme object to reduce unnecessary variables.\n --color-text-link: ", ";\n --color-text-header: ", ";\n --color-text-section: ", ";\n --color-text-body: ", ";\n --color-text-error: ", ";\n\n --color-text-selection-bg: ", ";\n --color-text-selection-text: ", ";\n\n --color-header-title: ", ";\n --color-header-hover-title: ", ";\n --color-header-bg: ", ";\n --color-header-border: ", ";\n\n --color-button-primary-bg: ", ";\n --color-button-primary-text: ", ";\n --color-button-primary-hover-bg: ", ";\n --color-button-primary-active-bg: ", ";\n --color-button-primary-active-outline: ", ";\n --color-button-primary-disabled-bg: ", ";\n\n --color-button-link-text: ", ";\n\n --color-button-secondary-bg: ", ";\n --color-button-secondary-text: ", ";\n --color-button-secondary-outline: ", ";\n\n --color-button-tertiary-bg: transparent;\n --color-button-tertiary-text: ", ";\n --color-button-tertiary-outline: ", ";\n --color-button-tertiary-hover-outline: ", ";\n --color-button-tertiary-hover-text: ", ";\n --color-button-tertiary-active-outline: ", ";\n --color-button-tertiary-active-text: ", ";\n\n --color-button-icon-disabled-text: ", ";\n --color-button-icon-activated-text: ", ";\n --color-button-icon-activated-bg: ", ";\n --color-button-icon-activated-outline: ", ";\n\n --color-toolbar-button-bg: ", ";\n\n --color-controlpanel-bg: ", ";\n --color-controlpanel-border: ", ";\n --color-controlpanel-section-text: ", ";\n --color-controlpanel-text: ", ";\n --color-controlpanel-section-bg: ", ";\n --color-controlpanel-drawer-bg: ", ";\n --color-controlpanel-ramp-slider: ", ";\n --color-controlpanel-isovalue-slider: ", ";\n\n --color-landingpage-bg: ", ";\n --color-landingpage-bg-alt: ", ";\n --color-landingpage-text: ", ";\n --color-landingpage-banner-highlight-bg: ", ";\n\n --color-statusflag-border: ", ";\n --color-statusflag-text: ", ";\n\n --color-alert-warning-text: ", ";\n --color-alert-warning-bg: ", ";\n --color-alert-info-text: ", ";\n --color-alert-info-bg: ", ";\n\n --color-layout-dividers: ", ";\n\n --color-modal-border: ", ";\n\n --color-menu-hover-text: ", ";\n --color-menu-selected-text: ", ";\n\n --color-checkbox-bg: ", ";\n\n --font-family: ", ";\n "])), $theme.colors.text.link, $theme.colors.text.header, $theme.colors.text.section, $theme.colors.text.body, $theme.colors.text.error, $theme.colors.text.selectionBg, $theme.colors.text.selectionText, $theme.colors.header.title, $theme.colors.header.hoverTitle, $theme.colors.header.bg, $theme.colors.header.border, $theme.colors.button.primary.bg, $theme.colors.button.primary.text, $theme.colors.button.primary.hoverBg, $theme.colors.button.primary.hoverBg, $theme.colors.button.primary.activeOutline, $theme.colors.button.primary.disabledBg, $theme.colors.button.link.text, $theme.colors.button.secondary.bg, $theme.colors.button.secondary.text, $theme.colors.button.secondary.outline, $theme.colors.button.tertiary.text, $theme.colors.button.tertiary.outline, $theme.colors.button.tertiary.hoverOutline, $theme.colors.button.tertiary.hoverText, $theme.colors.button.tertiary.activeOutline, $theme.colors.button.tertiary.hoverText, $theme.colors.button.tertiary.disabledText, $theme.colors.button.tertiary.activatedText, $theme.colors.button.tertiary.activatedBg, $theme.colors.button.tertiary.activatedOutline, $theme.colors.toolbar.buttonBg, $theme.colors.controlPanel.bg, $theme.colors.controlPanel.border, $theme.colors.controlPanel.sectionText, $theme.colors.controlPanel.text, $theme.colors.controlPanel.sectionBg, $theme.colors.controlPanel.drawerBg, $theme.colors.controlPanel.rampSlider, $theme.colors.controlPanel.isovalueSlider, $theme.colors.landingPage.bg, $theme.colors.landingPage.bgAlt, $theme.colors.landingPage.text, $theme.colors.landingPage.bannerBg, $theme.colors.statusFlag.border, $theme.colors.statusFlag.text, $theme.colors.alert.warning.text, $theme.colors.alert.warning.bg, $theme.colors.alert.info.text, $theme.colors.alert.info.bg, $theme.colors.layout.dividers, $theme.colors.modal.border, $theme.colors.menu.hoverText, $theme.colors.menu.selectedText, $theme.colors.checkbox.bg, $theme.fonts.family);
|
|
142
156
|
});
|
|
143
157
|
|
|
144
158
|
/**
|
|
@@ -157,6 +171,14 @@ export default function StyleProvider(props) {
|
|
|
157
171
|
colorBgContainer: "transparent",
|
|
158
172
|
colorSplit: theme.colors.layout.split,
|
|
159
173
|
colorPrimaryTextHover: theme.colors.text.selectionText,
|
|
174
|
+
colorWarning: theme.colors.alert.warning.text,
|
|
175
|
+
colorWarningBg: theme.colors.alert.warning.bg,
|
|
176
|
+
colorWarningBorder: theme.colors.alert.warning.text,
|
|
177
|
+
colorWarningText: theme.colors.alert.warning.text,
|
|
178
|
+
colorInfo: theme.colors.alert.info.text,
|
|
179
|
+
colorInfoBg: theme.colors.alert.info.bg,
|
|
180
|
+
colorInfoBorder: theme.colors.alert.info.text,
|
|
181
|
+
colorInfoText: theme.colors.alert.info.text,
|
|
160
182
|
fontWeightStrong: 400,
|
|
161
183
|
colorBgElevated: palette.darkGrey,
|
|
162
184
|
controlItemBgHover: theme.colors.menu.hoverBg,
|
|
@@ -172,10 +194,6 @@ export default function StyleProvider(props) {
|
|
|
172
194
|
defaultActiveBg: theme.colors.button.secondary.bg,
|
|
173
195
|
defaultActiveBorderColor: theme.colors.button.tertiary.activeOutline
|
|
174
196
|
},
|
|
175
|
-
Card: {
|
|
176
|
-
borderRadiusLG: 0,
|
|
177
|
-
headerHeight: 48
|
|
178
|
-
},
|
|
179
197
|
Collapse: {
|
|
180
198
|
borderRadiusLG: 0,
|
|
181
199
|
colorTextHeading: theme.colors.text.section
|
|
@@ -4,6 +4,8 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
|
|
|
4
4
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
5
5
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
6
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
7
|
+
// TODO this really ought to be exported at the top level...
|
|
8
|
+
|
|
7
9
|
import { ReloadOutlined } from "@ant-design/icons";
|
|
8
10
|
import { Button, Radio, Select, Tooltip } from "antd";
|
|
9
11
|
import { debounce } from "lodash";
|
|
@@ -27,6 +29,7 @@ var visuallyHiddenStyle = {
|
|
|
27
29
|
borderWidth: "0"
|
|
28
30
|
};
|
|
29
31
|
var Toolbar = function Toolbar(props) {
|
|
32
|
+
var _props$multiscaleInde;
|
|
30
33
|
var containerRef = React.useRef(null);
|
|
31
34
|
var barRef = React.useRef(null);
|
|
32
35
|
var leftRef = React.useRef(null);
|
|
@@ -50,6 +53,8 @@ var Toolbar = function Toolbar(props) {
|
|
|
50
53
|
var autorotate = useViewerState(select("autorotate"));
|
|
51
54
|
var showAxes = useViewerState(select("showAxes"));
|
|
52
55
|
var showBoundingBox = useViewerState(select("showBoundingBox"));
|
|
56
|
+
var useExactScaleLevel = useViewerState(select("useExactScaleLevel"));
|
|
57
|
+
var scaleLevelIndex = useViewerState(select("scaleLevelIndex"));
|
|
53
58
|
var changeViewerSetting = useViewerState(select("changeViewerSetting"));
|
|
54
59
|
|
|
55
60
|
// Scroll buttons are only visible when toolbar can be scrolled in that direction.
|
|
@@ -244,7 +249,39 @@ var Toolbar = function Toolbar(props) {
|
|
|
244
249
|
onClick: toggleBoundingBox
|
|
245
250
|
}, /*#__PURE__*/React.createElement(ViewerIcon, {
|
|
246
251
|
type: "boundingBox"
|
|
247
|
-
}))))
|
|
252
|
+
})))), props.multiscaleDims !== undefined && props.multiscaleDims.length > 1 && /*#__PURE__*/React.createElement("div", {
|
|
253
|
+
className: "viewer-toolbar-group"
|
|
254
|
+
}, /*#__PURE__*/React.createElement("span", null, "Resolution"), /*#__PURE__*/React.createElement(Radio.Group, {
|
|
255
|
+
value: useExactScaleLevel,
|
|
256
|
+
onChange: function onChange(e) {
|
|
257
|
+
return changeViewerSetting("useExactScaleLevel", e.target.value);
|
|
258
|
+
}
|
|
259
|
+
}, /*#__PURE__*/React.createElement(Radio.Button, {
|
|
260
|
+
value: false
|
|
261
|
+
}, "Auto"), /*#__PURE__*/React.createElement(Radio.Button, {
|
|
262
|
+
value: true
|
|
263
|
+
}, "Manual")), /*#__PURE__*/React.createElement(Select, {
|
|
264
|
+
className: "select-render-setting",
|
|
265
|
+
style: {
|
|
266
|
+
minWidth: 150
|
|
267
|
+
},
|
|
268
|
+
value: useExactScaleLevel ? scaleLevelIndex : (_props$multiscaleInde = props.multiscaleIndex) !== null && _props$multiscaleInde !== void 0 ? _props$multiscaleInde : scaleLevelIndex,
|
|
269
|
+
onChange: function onChange(value) {
|
|
270
|
+
return changeViewerSetting("scaleLevelIndex", value);
|
|
271
|
+
},
|
|
272
|
+
disabled: !useExactScaleLevel
|
|
273
|
+
}, props.multiscaleDims.map(function (dims, idx) {
|
|
274
|
+
var _dims$shape = _slicedToArray(dims.shape, 5),
|
|
275
|
+
_t = _dims$shape[0],
|
|
276
|
+
_c = _dims$shape[1],
|
|
277
|
+
z = _dims$shape[2],
|
|
278
|
+
y = _dims$shape[3],
|
|
279
|
+
x = _dims$shape[4];
|
|
280
|
+
return /*#__PURE__*/React.createElement(Select.Option, {
|
|
281
|
+
key: idx,
|
|
282
|
+
value: idx
|
|
283
|
+
}, x, " x ", y, " x ", z);
|
|
284
|
+
})))), /*#__PURE__*/React.createElement("div", {
|
|
248
285
|
className: "viewer-toolbar-right viewer-toolbar-group",
|
|
249
286
|
ref: rightRef
|
|
250
287
|
}, /*#__PURE__*/React.createElement(Tooltip, {
|
|
@@ -169,6 +169,27 @@
|
|
|
169
169
|
transition:all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
+
.viewer-toolbar.viewer-toolbar .ant-select.select-render-setting.ant-select-disabled .ant-select-selection-item,
|
|
173
|
+
.viewer-toolbar.viewer-toolbar .ant-select.select-render-setting.ant-select-disabled .ant-select-selection-search{
|
|
174
|
+
padding-inline-end:0;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.viewer-toolbar.viewer-toolbar .ant-select.select-render-setting.ant-select-disabled .ant-select-selection-item{
|
|
178
|
+
color:var(--color-button-icon-disabled-text);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.viewer-toolbar.viewer-toolbar .ant-select.select-render-setting.ant-select-disabled .ant-select-selection-item:hover{
|
|
182
|
+
color:var(--color-button-icon-disabled-text);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.viewer-toolbar.viewer-toolbar .ant-select.select-render-setting.ant-select-disabled .ant-select-selector{
|
|
186
|
+
border-color:var(--color-button-icon-disabled-text);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.viewer-toolbar.viewer-toolbar .ant-select.select-render-setting.ant-select-disabled .ant-select-arrow{
|
|
190
|
+
display:none;
|
|
191
|
+
}
|
|
192
|
+
|
|
172
193
|
.viewer-toolbar.viewer-toolbar .ant-select.select-render-setting .ant-select-selector{
|
|
173
194
|
border-color:#aeacae;
|
|
174
195
|
box-shadow:none;
|
|
@@ -8,13 +8,13 @@ function _regeneratorAsyncIterator(t, e) { function n(r, o, i, f) { try { var c
|
|
|
8
8
|
function _regenerator() { /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */ var e, t, r = "function" == typeof Symbol ? Symbol : {}, n = r.iterator || "@@iterator", o = r.toStringTag || "@@toStringTag"; function i(r, n, o, i) { var c = n && n.prototype instanceof Generator ? n : Generator, u = Object.create(c.prototype); return _regeneratorDefine2(u, "_invoke", function (r, n, o) { var i, c, u, f = 0, p = o || [], y = !1, G = { p: 0, n: 0, v: e, a: d, f: d.bind(e, 4), d: function d(t, r) { return i = t, c = 0, u = e, G.n = r, a; } }; function d(r, n) { for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) { var o, i = p[t], d = G.p, l = i[2]; r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0)); } if (o || r > 1) return a; throw y = !0, n; } return function (o, p, l) { if (f > 1) throw TypeError("Generator is already running"); for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) { i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u); try { if (f = 2, i) { if (c || (o = "next"), t = i[o]) { if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object"); if (!t.done) return t; u = t.value, c < 2 && (c = 0); } else 1 === c && (t = i["return"]) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1); i = e; } else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break; } catch (t) { i = e, c = 1, u = t; } finally { f = 1; } } return { value: t, done: y }; }; }(r, o, i), !0), u; } var a = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} t = Object.getPrototypeOf; var c = [][n] ? t(t([][n]())) : (_regeneratorDefine2(t = {}, n, function () { return this; }), t), u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c); function f(e) { return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine2(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e; } return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine2(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine2(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine2(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine2(u), _regeneratorDefine2(u, o, "Generator"), _regeneratorDefine2(u, n, function () { return this; }), _regeneratorDefine2(u, "toString", function () { return "[object Generator]"; }), (_regenerator = function _regenerator() { return { w: i, m: f }; })(); }
|
|
9
9
|
function _regeneratorDefine2(e, r, n, t) { var i = Object.defineProperty; try { i({}, "", {}); } catch (e) { i = 0; } _regeneratorDefine2 = function _regeneratorDefine(e, r, n, t) { function o(r, n) { _regeneratorDefine2(e, r, function (e) { return this._invoke(r, n, e); }); } r ? i ? i(e, r, { value: n, enumerable: !t, configurable: !t, writable: !t }) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2)); }, _regeneratorDefine2(e, r, n, t); }
|
|
10
10
|
function _OverloadYield(e, d) { this.v = e, this.k = d; }
|
|
11
|
-
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
12
|
-
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
13
11
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
14
12
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
15
13
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
16
14
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
17
15
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
16
|
+
function asyncGeneratorStep(n, t, e, r, o, a, c) { try { var i = n[a](c), u = i.value; } catch (n) { return void e(n); } i.done ? t(u) : Promise.resolve(u).then(r, o); }
|
|
17
|
+
function _asyncToGenerator(n) { return function () { var t = this, e = arguments; return new Promise(function (r, o) { var a = n.apply(t, e); function _next(n) { asyncGeneratorStep(a, r, o, _next, _throw, "next", n); } function _throw(n) { asyncGeneratorStep(a, r, o, _next, _throw, "throw", n); } _next(void 0); }); }; }
|
|
18
18
|
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
19
19
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
20
20
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
@@ -24,13 +24,12 @@ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
|
24
24
|
import { LoadSpec, VolumeLoaderContext } from "@aics/vole-core";
|
|
25
25
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
26
26
|
import { Box3, Vector3 } from "three";
|
|
27
|
-
import { AXIS_TO_LOADER_PRIORITY, CACHE_MAX_SIZE,
|
|
27
|
+
import { AXIS_TO_LOADER_PRIORITY, CACHE_MAX_SIZE, getDefaultViewerChannelSettings, QUEUE_MAX_LOW_PRIORITY_SIZE, QUEUE_MAX_SIZE } from "../shared/constants";
|
|
28
28
|
import { ViewMode } from "../shared/enums";
|
|
29
29
|
import { useConstructor, useRefWithSetter } from "../shared/utils/hooks";
|
|
30
30
|
import PlayControls from "../shared/utils/playControls";
|
|
31
31
|
import SceneStore from "../shared/utils/sceneStore";
|
|
32
32
|
import { makeChannelIndexGrouping } from "../shared/utils/viewerChannelSettings";
|
|
33
|
-
import { initializeOneChannelSetting } from "../shared/utils/viewerState";
|
|
34
33
|
import { select, useViewerState } from "../state/store";
|
|
35
34
|
export var ImageLoadStatus = /*#__PURE__*/function (ImageLoadStatus) {
|
|
36
35
|
ImageLoadStatus[ImageLoadStatus["REQUESTED"] = 0] = "REQUESTED";
|
|
@@ -57,10 +56,14 @@ var CHANNEL_RELOAD = 0;
|
|
|
57
56
|
*/
|
|
58
57
|
var useEffectEventRef = function useEffectEventRef(callback) {
|
|
59
58
|
var callbackRef = useRef(callback);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
callbackRef.current = callback;
|
|
60
|
+
return useCallback(function () {
|
|
61
|
+
var _callbackRef$current;
|
|
62
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
63
|
+
args[_key] = arguments[_key];
|
|
64
|
+
}
|
|
65
|
+
return (_callbackRef$current = callbackRef.current) === null || _callbackRef$current === void 0 ? void 0 : _callbackRef$current.call.apply(_callbackRef$current, [callbackRef].concat(args));
|
|
66
|
+
}, [callbackRef]);
|
|
64
67
|
};
|
|
65
68
|
|
|
66
69
|
/**
|
|
@@ -76,7 +79,7 @@ var useEffectEventRef = function useEffectEventRef(callback) {
|
|
|
76
79
|
var useVolume = function useVolume(scenePaths, options) {
|
|
77
80
|
var channelSettings = useViewerState(select("channelSettings"));
|
|
78
81
|
var changeViewerSetting = useViewerState(select("changeViewerSetting"));
|
|
79
|
-
var
|
|
82
|
+
var initChannelSettings = useViewerState(select("initChannelSettings"));
|
|
80
83
|
var onErrorRef = useEffectEventRef(options === null || options === void 0 ? void 0 : options.onError);
|
|
81
84
|
var onChannelLoadedRef = useEffectEventRef(options === null || options === void 0 ? void 0 : options.onChannelLoaded);
|
|
82
85
|
var onChangeSceneRef = useEffectEventRef(options === null || options === void 0 ? void 0 : options.onChangeScene);
|
|
@@ -173,9 +176,8 @@ var useVolume = function useVolume(scenePaths, options) {
|
|
|
173
176
|
}));
|
|
174
177
|
}, [channelVersionsRef, setChannelVersions]);
|
|
175
178
|
var onError = useCallback(function (e) {
|
|
176
|
-
var _onErrorRef$current;
|
|
177
179
|
setLoadThrewError(true);
|
|
178
|
-
|
|
180
|
+
onErrorRef(e);
|
|
179
181
|
throw e;
|
|
180
182
|
}, [onErrorRef]);
|
|
181
183
|
|
|
@@ -185,10 +187,9 @@ var useVolume = function useVolume(scenePaths, options) {
|
|
|
185
187
|
channelGroupedByType = _useState10[0],
|
|
186
188
|
setChannelGroupedByType = _useState10[1];
|
|
187
189
|
var onChannelDataLoaded = useCallback(function (aimg, channelIndex) {
|
|
188
|
-
var _onChannelLoadedRef$c;
|
|
189
190
|
// let the hook caller know that this channel has loaded
|
|
190
191
|
var isInitialLoad = channelVersionsRef.current[channelIndex] === CHANNEL_INITIAL_LOAD;
|
|
191
|
-
|
|
192
|
+
onChannelLoadedRef(aimg, channelIndex, isInitialLoad);
|
|
192
193
|
|
|
193
194
|
// set this channel as loaded
|
|
194
195
|
var newVersions = channelVersionsRef.current.slice();
|
|
@@ -200,34 +201,23 @@ var useVolume = function useVolume(scenePaths, options) {
|
|
|
200
201
|
playControls.onImageLoaded();
|
|
201
202
|
}
|
|
202
203
|
}, [channelVersionsRef, onChannelLoadedRef, playControls, setChannelVersions]);
|
|
204
|
+
var setChannelStateForNewImage = useCallback(function (channelNames) {
|
|
205
|
+
var _useViewerState$getSt = useViewerState.getState(),
|
|
206
|
+
useDefaultViewerChannelSettings = _useViewerState$getSt.useDefaultViewerChannelSettings;
|
|
207
|
+
var viewerChannelSettings = useDefaultViewerChannelSettings ? getDefaultViewerChannelSettings() : options === null || options === void 0 ? void 0 : options.viewerChannelSettings;
|
|
208
|
+
var grouping = makeChannelIndexGrouping(channelNames, viewerChannelSettings);
|
|
209
|
+
setChannelGroupedByType(grouping);
|
|
210
|
+
return initChannelSettings(channelNames, viewerChannelSettings);
|
|
211
|
+
}, [initChannelSettings, options === null || options === void 0 ? void 0 : options.viewerChannelSettings]);
|
|
203
212
|
|
|
204
213
|
// effect to start the initial load of the image
|
|
205
214
|
useEffect(function () {
|
|
206
|
-
var channelSettings = useViewerState.getState().channelSettings;
|
|
207
215
|
setChannelVersions(new Array(channelVersionsRef.current.length).fill(CHANNEL_INITIAL_LOAD));
|
|
208
216
|
setLoadThrewError(false);
|
|
209
217
|
inInitialLoadRef.current = true;
|
|
210
|
-
var setChannelStateForNewImage = function setChannelStateForNewImage(channelNames) {
|
|
211
|
-
var _useViewerState$getSt = useViewerState.getState(),
|
|
212
|
-
useDefaultViewerChannelSettings = _useViewerState$getSt.useDefaultViewerChannelSettings;
|
|
213
|
-
var viewerChannelSettings = useDefaultViewerChannelSettings ? getDefaultViewerChannelSettings() : options === null || options === void 0 ? void 0 : options.viewerChannelSettings;
|
|
214
|
-
var grouping = makeChannelIndexGrouping(channelNames, viewerChannelSettings);
|
|
215
|
-
setChannelGroupedByType(grouping);
|
|
216
|
-
var newChannelSettings = channelNames.map(function (name, index) {
|
|
217
|
-
var _channelSettings$inde;
|
|
218
|
-
var color = getDefaultChannelColor(index);
|
|
219
|
-
var channelSetting = (_channelSettings$inde = channelSettings[index]) !== null && _channelSettings$inde !== void 0 ? _channelSettings$inde : initializeOneChannelSetting(name, index, color, viewerChannelSettings);
|
|
220
|
-
return _objectSpread(_objectSpread({}, channelSetting), {}, {
|
|
221
|
-
name: name
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
replaceAllChannelSettings(newChannelSettings);
|
|
225
|
-
return newChannelSettings;
|
|
226
|
-
};
|
|
227
218
|
var openImage = /*#__PURE__*/function () {
|
|
228
219
|
var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
|
|
229
|
-
var
|
|
230
|
-
var scene, time, loadSpec, aimg, channelNames, newChannelSettings, requiredLoadSpec, requiredChannelsToLoad, _useViewerState$getSt2, useDefaultViewerChannelSettings, viewerChannelSettings, maskChannelName, maskChannelIndex, viewMode, slice, onCreateScene;
|
|
220
|
+
var scene, time, loadSpec, aimg, channelNames, newChannelSettings, requiredLoadSpec, requiredChannelsToLoad, _useViewerState$getSt2, useDefaultViewerChannelSettings, viewerChannelSettings, maskChannelName, maskChannelIndex, viewMode, slice;
|
|
231
221
|
return _regeneratorRuntime().wrap(function _callee$(_context) {
|
|
232
222
|
while (1) switch (_context.prev = _context.next) {
|
|
233
223
|
case 0:
|
|
@@ -243,7 +233,7 @@ var useVolume = function useVolume(scenePaths, options) {
|
|
|
243
233
|
newChannelSettings = setChannelStateForNewImage(channelNames);
|
|
244
234
|
setChannelVersions(new Array(channelNames.length).fill(CHANNEL_INITIAL_LOAD));
|
|
245
235
|
setImage(aimg);
|
|
246
|
-
|
|
236
|
+
onCreateImageRef(aimg);
|
|
247
237
|
playControls.stepAxis = function (axis) {
|
|
248
238
|
var time = useViewerState.getState().time;
|
|
249
239
|
var slice = useViewerState.getState().slice;
|
|
@@ -289,11 +279,10 @@ var useVolume = function useVolume(scenePaths, options) {
|
|
|
289
279
|
|
|
290
280
|
// initiate loading only after setting up new channel settings,
|
|
291
281
|
// in case the loader callback fires before the state is set
|
|
292
|
-
onCreateScene = onChangeSceneRef.current;
|
|
293
282
|
sceneLoader.loadScene(scene, aimg, requiredLoadSpec, {
|
|
294
|
-
onCreateScene:
|
|
283
|
+
onCreateScene: onChangeSceneRef
|
|
295
284
|
})["catch"](onError);
|
|
296
|
-
case
|
|
285
|
+
case 26:
|
|
297
286
|
case "end":
|
|
298
287
|
return _context.stop();
|
|
299
288
|
}
|
|
@@ -304,7 +293,7 @@ var useVolume = function useVolume(scenePaths, options) {
|
|
|
304
293
|
};
|
|
305
294
|
}();
|
|
306
295
|
openImage();
|
|
307
|
-
}, [sceneLoader, onError, onCreateImageRef, onChangeSceneRef, onChannelLoadedRef, channelVersionsRef, setChannelVersions, playControls, setIsLoading, onChannelDataLoaded, changeViewerSetting,
|
|
296
|
+
}, [sceneLoader, onError, onCreateImageRef, onChangeSceneRef, onChannelLoadedRef, channelVersionsRef, setChannelVersions, playControls, setIsLoading, onChannelDataLoaded, changeViewerSetting, initChannelSettings, setChannelStateForNewImage, options === null || options === void 0 ? void 0 : options.viewerChannelSettings]);
|
|
308
297
|
// of the above dependencies, we expect only `sceneLoader` to change.
|
|
309
298
|
|
|
310
299
|
var setTime = useCallback(function (view3d, time) {
|
|
@@ -315,13 +304,26 @@ var useVolume = function useVolume(scenePaths, options) {
|
|
|
315
304
|
}, [image, onError, setIsLoading, inInitialLoadRef]);
|
|
316
305
|
var setScene = useCallback(function (scene) {
|
|
317
306
|
if (image && !inInitialLoadRef.current) {
|
|
318
|
-
var onCreateScene =
|
|
307
|
+
var onCreateScene = function onCreateScene(volume, sceneIndex, loadSpec) {
|
|
308
|
+
setChannelStateForNewImage(volume.imageInfo.channelNames);
|
|
309
|
+
volume.updateChannelCount();
|
|
310
|
+
var prevChannelVersions = channelVersionsRef.current;
|
|
311
|
+
var newChannelVersions;
|
|
312
|
+
var addedChannelCount = volume.imageInfo.numChannels - prevChannelVersions.length;
|
|
313
|
+
if (addedChannelCount > 0) {
|
|
314
|
+
newChannelVersions = prevChannelVersions.concat(Array(addedChannelCount).fill(CHANNEL_INITIAL_LOAD));
|
|
315
|
+
} else {
|
|
316
|
+
newChannelVersions = prevChannelVersions.slice(0, volume.imageInfo.numChannels);
|
|
317
|
+
}
|
|
318
|
+
setChannelVersions(newChannelVersions);
|
|
319
|
+
onChangeSceneRef(volume, sceneIndex, loadSpec);
|
|
320
|
+
};
|
|
319
321
|
sceneLoader.loadScene(scene, image, undefined, {
|
|
320
322
|
onCreateScene: onCreateScene
|
|
321
323
|
})["catch"](onError);
|
|
322
324
|
setIsLoading(LoadType.SCENE);
|
|
323
325
|
}
|
|
324
|
-
}, [image,
|
|
326
|
+
}, [image, sceneLoader, onError, setIsLoading, setChannelStateForNewImage, channelVersionsRef, setChannelVersions, onChangeSceneRef]);
|
|
325
327
|
return useMemo(function () {
|
|
326
328
|
return {
|
|
327
329
|
image: image,
|
|
@@ -166,6 +166,8 @@ export var getDefaultViewerState = function getDefaultViewerState() {
|
|
|
166
166
|
scene: 0,
|
|
167
167
|
singleChannelMode: false,
|
|
168
168
|
singleChannelIndex: 0,
|
|
169
|
+
useExactScaleLevel: false,
|
|
170
|
+
scaleLevelIndex: 0,
|
|
169
171
|
// Do not override camera position, target, etc. by default;
|
|
170
172
|
// instead, let the viewer apply default camera settings based on the view mode.
|
|
171
173
|
// This prevents a bug where the camera's position and view mode are set to
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
1
3
|
function _regeneratorRuntime() { "use strict"; var r = _regenerator(), e = r.m(_regeneratorRuntime), t = (Object.getPrototypeOf ? Object.getPrototypeOf(e) : e.__proto__).constructor; function n(r) { var e = "function" == typeof r && r.constructor; return !!e && (e === t || "GeneratorFunction" === (e.displayName || e.name)); } var o = { "throw": 1, "return": 2, "break": 3, "continue": 3 }; function a(r) { var e, t; return function (n) { e || (e = { stop: function stop() { return t(n.a, 2); }, "catch": function _catch() { return n.v; }, abrupt: function abrupt(r, e) { return t(n.a, o[r], e); }, delegateYield: function delegateYield(r, o, a) { return e.resultName = o, t(n.d, _regeneratorValues(r), a); }, finish: function finish(r) { return t(n.f, r); } }, t = function t(r, _t, o) { n.p = e.prev, n.n = e.next; try { return r(_t, o); } finally { e.next = n.n; } }), e.resultName && (e[e.resultName] = n.v, e.resultName = void 0), e.sent = n.v, e.next = n.n; try { return r.call(this, e); } finally { n.p = e.prev, n.n = e.next; } }; } return (_regeneratorRuntime = function _regeneratorRuntime() { return { wrap: function wrap(e, t, n, o) { return r.w(a(e), t, n, o && o.reverse()); }, isGeneratorFunction: n, mark: r.m, awrap: function awrap(r, e) { return new _OverloadYield(r, e); }, AsyncIterator: _regeneratorAsyncIterator, async: function async(r, e, t, o, u) { return (n(e) ? _regeneratorAsyncGen : _regeneratorAsync)(a(r), e, t, o, u); }, keys: _regeneratorKeys, values: _regeneratorValues }; })(); }
|
|
2
4
|
function _regeneratorValues(e) { if (null != e) { var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"], r = 0; if (t) return t.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) return { next: function next() { return e && r >= e.length && (e = void 0), { value: e && e[r++], done: !e }; } }; } throw new TypeError(_typeof(e) + " is not iterable"); }
|
|
3
5
|
function _regeneratorKeys(e) { var n = Object(e), r = []; for (var t in n) r.unshift(t); return function e() { for (; r.length;) if ((t = r.pop()) in n) return e.value = t, e.done = !1, e; return e.done = !0, e; }; }
|
|
@@ -16,7 +18,7 @@ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r),
|
|
|
16
18
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
17
19
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
18
20
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
19
|
-
import { VolumeFileFormat } from "@aics/vole-core";
|
|
21
|
+
import { createDefaultMetadata, VolumeFileFormat } from "@aics/vole-core";
|
|
20
22
|
var SceneStore = /*#__PURE__*/function () {
|
|
21
23
|
function SceneStore(context, paths) {
|
|
22
24
|
_classCallCheck(this, SceneStore);
|
|
@@ -77,8 +79,8 @@ var SceneStore = /*#__PURE__*/function () {
|
|
|
77
79
|
key: "loadScene",
|
|
78
80
|
value: function () {
|
|
79
81
|
var _loadScene = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(scene, image, loadSpec, options) {
|
|
80
|
-
var _options$onCreateScen;
|
|
81
|
-
var loader, spec;
|
|
82
|
+
var _spec$channels, _options$onCreateScen;
|
|
83
|
+
var loader, spec, imageInfo, maxTime, adjustedSpec;
|
|
82
84
|
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
83
85
|
while (1) switch (_context2.prev = _context2.next) {
|
|
84
86
|
case 0:
|
|
@@ -91,10 +93,19 @@ var SceneStore = /*#__PURE__*/function () {
|
|
|
91
93
|
_context2.next = 7;
|
|
92
94
|
return loader.createImageInfo(spec);
|
|
93
95
|
case 7:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
imageInfo = _context2.sent.imageInfo;
|
|
97
|
+
image.imageInfo.imageInfo = imageInfo;
|
|
98
|
+
image.imageMetadata = createDefaultMetadata(imageInfo);
|
|
99
|
+
maxTime = imageInfo.multiscaleLevelDims[imageInfo.multiscaleLevel].shape[0] - 1;
|
|
100
|
+
adjustedSpec = _objectSpread(_objectSpread({}, spec), {}, {
|
|
101
|
+
channels: (_spec$channels = spec.channels) === null || _spec$channels === void 0 ? void 0 : _spec$channels.filter(function (channelIndex) {
|
|
102
|
+
return channelIndex < imageInfo.channelNames.length;
|
|
103
|
+
}),
|
|
104
|
+
time: Math.min(spec.time, maxTime)
|
|
105
|
+
});
|
|
106
|
+
options === null || options === void 0 || (_options$onCreateScen = options.onCreateScene) === null || _options$onCreateScen === void 0 || _options$onCreateScen.call(options, image, scene, adjustedSpec);
|
|
107
|
+
loader.loadVolumeData(image, adjustedSpec, options === null || options === void 0 ? void 0 : options.onChannelLoaded);
|
|
108
|
+
case 14:
|
|
98
109
|
case "end":
|
|
99
110
|
return _context2.stop();
|
|
100
111
|
}
|
|
@@ -438,7 +438,9 @@ describe("Viewer state", function () {
|
|
|
438
438
|
scene: 0,
|
|
439
439
|
cameraState: undefined,
|
|
440
440
|
singleChannelMode: false,
|
|
441
|
-
singleChannelIndex: 0
|
|
441
|
+
singleChannelIndex: 0,
|
|
442
|
+
useExactScaleLevel: false,
|
|
443
|
+
scaleLevelIndex: 0
|
|
442
444
|
};
|
|
443
445
|
var SERIALIZED_DEFAULT_VIEWER_STATE = {
|
|
444
446
|
mode: "volumetric",
|
|
@@ -459,7 +461,9 @@ describe("Viewer state", function () {
|
|
|
459
461
|
t: "0",
|
|
460
462
|
scene: "0",
|
|
461
463
|
scm: "0",
|
|
462
|
-
sci: "0"
|
|
464
|
+
sci: "0",
|
|
465
|
+
esl: "0",
|
|
466
|
+
scl: "0"
|
|
463
467
|
};
|
|
464
468
|
var CUSTOM_VIEWER_STATE = {
|
|
465
469
|
renderMode: RenderMode.pathTrace,
|
|
@@ -489,6 +493,8 @@ describe("Viewer state", function () {
|
|
|
489
493
|
scene: 3,
|
|
490
494
|
singleChannelMode: true,
|
|
491
495
|
singleChannelIndex: 3,
|
|
496
|
+
useExactScaleLevel: true,
|
|
497
|
+
scaleLevelIndex: 3,
|
|
492
498
|
cameraState: {
|
|
493
499
|
position: [-1.05, -4, 45],
|
|
494
500
|
target: [0, 0, 0],
|
|
@@ -517,6 +523,8 @@ describe("Viewer state", function () {
|
|
|
517
523
|
scene: "3",
|
|
518
524
|
scm: "1",
|
|
519
525
|
sci: "3",
|
|
526
|
+
esl: "1",
|
|
527
|
+
scl: "3",
|
|
520
528
|
cam: "pos:-1.05:-4:45,tar:0:0:0,up:0:1:0,ort:3.534,fov:43.5"
|
|
521
529
|
};
|
|
522
530
|
describe("serializeViewerState", function () {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
-
var _ViewerChannelSetting, _ViewerChannelSetting2, _ViewerChannelSetting3, _ViewerChannelSetting4, _ViewerChannelSetting5, _ViewerChannelSetting6, _ViewerChannelSetting7, _ViewerChannelSetting8, _ViewerChannelSetting9, _ViewerChannelSetting10, _ViewerChannelSetting11, _ViewerChannelSetting12, _ViewerChannelSetting13, _ViewerChannelSetting14, _ViewerStateKeys$View, _ViewerStateKeys$Mode, _ViewerStateKeys$Mask, _ViewerStateKeys$Imag, _ViewerStateKeys$Axes, _ViewerStateKeys$Boun, _ViewerStateKeys$Sing, _ViewerStateKeys$Sing2, _ViewerStateKeys$Boun2, _ViewerStateKeys$Back, _ViewerStateKeys$Auto, _ViewerStateKeys$Brig, _ViewerStateKeys$Dens, _ViewerStateKeys$Leve, _ViewerStateKeys$Inte, _ViewerStateKeys$Regi, _ViewerStateKeys$Slic, _ViewerStateKeys$Time, _ViewerStateKeys$Scen, _ViewerStateKeys$Came;
|
|
2
|
+
var _ViewerChannelSetting, _ViewerChannelSetting2, _ViewerChannelSetting3, _ViewerChannelSetting4, _ViewerChannelSetting5, _ViewerChannelSetting6, _ViewerChannelSetting7, _ViewerChannelSetting8, _ViewerChannelSetting9, _ViewerChannelSetting10, _ViewerChannelSetting11, _ViewerChannelSetting12, _ViewerChannelSetting13, _ViewerChannelSetting14, _ViewerStateKeys$View, _ViewerStateKeys$Mode, _ViewerStateKeys$Mask, _ViewerStateKeys$Imag, _ViewerStateKeys$Axes, _ViewerStateKeys$Boun, _ViewerStateKeys$Sing, _ViewerStateKeys$Sing2, _ViewerStateKeys$Boun2, _ViewerStateKeys$Back, _ViewerStateKeys$Auto, _ViewerStateKeys$Brig, _ViewerStateKeys$Dens, _ViewerStateKeys$Leve, _ViewerStateKeys$Inte, _ViewerStateKeys$Regi, _ViewerStateKeys$Slic, _ViewerStateKeys$Time, _ViewerStateKeys$Scen, _ViewerStateKeys$UseE, _ViewerStateKeys$Scal, _ViewerStateKeys$Came;
|
|
3
3
|
function _regeneratorRuntime() { "use strict"; var r = _regenerator(), e = r.m(_regeneratorRuntime), t = (Object.getPrototypeOf ? Object.getPrototypeOf(e) : e.__proto__).constructor; function n(r) { var e = "function" == typeof r && r.constructor; return !!e && (e === t || "GeneratorFunction" === (e.displayName || e.name)); } var o = { "throw": 1, "return": 2, "break": 3, "continue": 3 }; function a(r) { var e, t; return function (n) { e || (e = { stop: function stop() { return t(n.a, 2); }, "catch": function _catch() { return n.v; }, abrupt: function abrupt(r, e) { return t(n.a, o[r], e); }, delegateYield: function delegateYield(r, o, a) { return e.resultName = o, t(n.d, _regeneratorValues(r), a); }, finish: function finish(r) { return t(n.f, r); } }, t = function t(r, _t, o) { n.p = e.prev, n.n = e.next; try { return r(_t, o); } finally { e.next = n.n; } }), e.resultName && (e[e.resultName] = n.v, e.resultName = void 0), e.sent = n.v, e.next = n.n; try { return r.call(this, e); } finally { n.p = e.prev, n.n = e.next; } }; } return (_regeneratorRuntime = function _regeneratorRuntime() { return { wrap: function wrap(e, t, n, o) { return r.w(a(e), t, n, o && o.reverse()); }, isGeneratorFunction: n, mark: r.m, awrap: function awrap(r, e) { return new _OverloadYield(r, e); }, AsyncIterator: _regeneratorAsyncIterator, async: function async(r, e, t, o, u) { return (n(e) ? _regeneratorAsyncGen : _regeneratorAsync)(a(r), e, t, o, u); }, keys: _regeneratorKeys, values: _regeneratorValues }; })(); }
|
|
4
4
|
function _regeneratorValues(e) { if (null != e) { var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"], r = 0; if (t) return t.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) return { next: function next() { return e && r >= e.length && (e = void 0), { value: e && e[r++], done: !e }; } }; } throw new TypeError(_typeof(e) + " is not iterable"); }
|
|
5
5
|
function _regeneratorKeys(e) { var n = Object(e), r = []; for (var t in n) r.unshift(t); return function e() { for (; r.length;) if ((t = r.pop()) in n) return e.value = t, e.done = !1, e; return e.done = !0, e; }; }
|
|
@@ -113,6 +113,8 @@ export var ViewerStateKeys = /*#__PURE__*/function (ViewerStateKeys) {
|
|
|
113
113
|
ViewerStateKeys["CameraState"] = "cam";
|
|
114
114
|
ViewerStateKeys["SingleChannelMode"] = "scm";
|
|
115
115
|
ViewerStateKeys["SingleChannelIndex"] = "sci";
|
|
116
|
+
ViewerStateKeys["UseExactScaleLevel"] = "esl";
|
|
117
|
+
ViewerStateKeys["ScaleLevelIndex"] = "scl";
|
|
116
118
|
return ViewerStateKeys;
|
|
117
119
|
}({});
|
|
118
120
|
export var CameraTransformKeys = /*#__PURE__*/function (CameraTransformKeys) {
|
|
@@ -272,6 +274,8 @@ _ViewerStateKeys$Regi = ViewerStateKeys.Region;
|
|
|
272
274
|
_ViewerStateKeys$Slic = ViewerStateKeys.Slice;
|
|
273
275
|
_ViewerStateKeys$Time = ViewerStateKeys.Time;
|
|
274
276
|
_ViewerStateKeys$Scen = ViewerStateKeys.Scene;
|
|
277
|
+
_ViewerStateKeys$UseE = ViewerStateKeys.UseExactScaleLevel;
|
|
278
|
+
_ViewerStateKeys$Scal = ViewerStateKeys.ScaleLevelIndex;
|
|
275
279
|
_ViewerStateKeys$Came = ViewerStateKeys.CameraState;
|
|
276
280
|
/** Serialized version of `ViewerState`. */
|
|
277
281
|
export var ViewerStateParams = /*#__PURE__*/_createClass(function ViewerStateParams() {
|
|
@@ -325,6 +329,10 @@ export var ViewerStateParams = /*#__PURE__*/_createClass(function ViewerStatePar
|
|
|
325
329
|
_defineProperty(this, _ViewerStateKeys$Time, undefined);
|
|
326
330
|
/** Scene number, for multiscene images. 0 by default. */
|
|
327
331
|
_defineProperty(this, _ViewerStateKeys$Scen, undefined);
|
|
332
|
+
/** Whether to use an exact scale level index. 0 by default. */
|
|
333
|
+
_defineProperty(this, _ViewerStateKeys$UseE, undefined);
|
|
334
|
+
/** The exact scale level index to use, if `UseExactScaleLevel` is 1. 0 by default. */
|
|
335
|
+
_defineProperty(this, _ViewerStateKeys$Scal, undefined);
|
|
328
336
|
/**
|
|
329
337
|
* Camera transform settings, as a list of `key:value` pairs separated by commas.
|
|
330
338
|
* Valid keys are defined in `CameraTransformKeys`:
|
|
@@ -952,6 +960,8 @@ export function deserializeViewerState(params) {
|
|
|
952
960
|
renderMode: parseStringEnum(params[ViewerStateKeys.Mode], RenderMode),
|
|
953
961
|
singleChannelMode: parseStringBoolean(params[ViewerStateKeys.SingleChannelMode]),
|
|
954
962
|
singleChannelIndex: parseStringInt(params[ViewerStateKeys.SingleChannelIndex], 0, Number.POSITIVE_INFINITY),
|
|
963
|
+
useExactScaleLevel: parseStringBoolean(params[ViewerStateKeys.UseExactScaleLevel]),
|
|
964
|
+
scaleLevelIndex: parseStringInt(params[ViewerStateKeys.ScaleLevelIndex], 0, Number.MAX_SAFE_INTEGER),
|
|
955
965
|
cameraState: parseCameraState(params[ViewerStateKeys.CameraState])
|
|
956
966
|
};
|
|
957
967
|
|
|
@@ -983,11 +993,15 @@ export function deserializeViewerState(params) {
|
|
|
983
993
|
* @returns A `ViewerStateParams` object with the serialized parameters. Undefined values are removed.
|
|
984
994
|
*/
|
|
985
995
|
export function serializeViewerState(state, removeDefaults) {
|
|
986
|
-
var _state$maskAlpha, _state$brightness, _state$density, _state$levels, _state$time, _state$scene, _state$singleChannelI, _result;
|
|
996
|
+
var _state$maskAlpha, _state$brightness, _state$density, _state$levels, _state$time, _state$scene, _state$singleChannelI, _state$scaleLevelInde, _result;
|
|
987
997
|
if (removeDefaults) {
|
|
988
998
|
state = removeMatchingProperties(state, getDefaultViewerState());
|
|
999
|
+
// special case: if there's an explicit scale level but it's not being used, no reason to include it
|
|
1000
|
+
if (state.scaleLevelIndex !== undefined && state.useExactScaleLevel === undefined) {
|
|
1001
|
+
delete state.scaleLevelIndex;
|
|
1002
|
+
}
|
|
989
1003
|
}
|
|
990
|
-
var result = (_result = {}, _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_result, ViewerStateKeys.Mode, state.renderMode), ViewerStateKeys.Mask, (_state$maskAlpha = state.maskAlpha) === null || _state$maskAlpha === void 0 ? void 0 : _state$maskAlpha.toString()), ViewerStateKeys.Image, state.imageType), ViewerStateKeys.Axes, serializeBoolean(state.showAxes)), ViewerStateKeys.BoundingBox, serializeBoolean(state.showBoundingBox)), ViewerStateKeys.BoundingBoxColor, state.boundingBoxColor && colorArrayToHex(state.boundingBoxColor)), ViewerStateKeys.BackgroundColor, state.backgroundColor && colorArrayToHex(state.backgroundColor)), ViewerStateKeys.Autorotate, serializeBoolean(state.autorotate)), ViewerStateKeys.Brightness, (_state$brightness = state.brightness) === null || _state$brightness === void 0 ? void 0 : _state$brightness.toString()), ViewerStateKeys.Density, (_state$density = state.density) === null || _state$density === void 0 ? void 0 : _state$density.toString()), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_result, ViewerStateKeys.Interpolation, serializeBoolean(state.interpolationEnabled)), ViewerStateKeys.Region, state.region && serializeRegion(state.region)), ViewerStateKeys.Slice, state.slice && serializeSlice(state.slice)), ViewerStateKeys.Levels, (_state$levels = state.levels) === null || _state$levels === void 0 ? void 0 : _state$levels.join(",")), ViewerStateKeys.Time, (_state$time = state.time) === null || _state$time === void 0 ? void 0 : _state$time.toString()), ViewerStateKeys.Scene, (_state$scene = state.scene) === null || _state$scene === void 0 ? void 0 : _state$scene.toString()), ViewerStateKeys.SingleChannelMode, serializeBoolean(state.singleChannelMode)), ViewerStateKeys.SingleChannelIndex, (_state$singleChannelI = state.singleChannelIndex) === null || _state$singleChannelI === void 0 ? void 0 : _state$singleChannelI.toString()), ViewerStateKeys.CameraState, state.cameraState && serializeCameraState(state.cameraState, removeDefaults, state.viewMode)));
|
|
1004
|
+
var result = (_result = {}, _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_result, ViewerStateKeys.Mode, state.renderMode), ViewerStateKeys.Mask, (_state$maskAlpha = state.maskAlpha) === null || _state$maskAlpha === void 0 ? void 0 : _state$maskAlpha.toString()), ViewerStateKeys.Image, state.imageType), ViewerStateKeys.Axes, serializeBoolean(state.showAxes)), ViewerStateKeys.BoundingBox, serializeBoolean(state.showBoundingBox)), ViewerStateKeys.BoundingBoxColor, state.boundingBoxColor && colorArrayToHex(state.boundingBoxColor)), ViewerStateKeys.BackgroundColor, state.backgroundColor && colorArrayToHex(state.backgroundColor)), ViewerStateKeys.Autorotate, serializeBoolean(state.autorotate)), ViewerStateKeys.Brightness, (_state$brightness = state.brightness) === null || _state$brightness === void 0 ? void 0 : _state$brightness.toString()), ViewerStateKeys.Density, (_state$density = state.density) === null || _state$density === void 0 ? void 0 : _state$density.toString()), _defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_defineProperty(_result, ViewerStateKeys.Interpolation, serializeBoolean(state.interpolationEnabled)), ViewerStateKeys.Region, state.region && serializeRegion(state.region)), ViewerStateKeys.Slice, state.slice && serializeSlice(state.slice)), ViewerStateKeys.Levels, (_state$levels = state.levels) === null || _state$levels === void 0 ? void 0 : _state$levels.join(",")), ViewerStateKeys.Time, (_state$time = state.time) === null || _state$time === void 0 ? void 0 : _state$time.toString()), ViewerStateKeys.Scene, (_state$scene = state.scene) === null || _state$scene === void 0 ? void 0 : _state$scene.toString()), ViewerStateKeys.SingleChannelMode, serializeBoolean(state.singleChannelMode)), ViewerStateKeys.SingleChannelIndex, (_state$singleChannelI = state.singleChannelIndex) === null || _state$singleChannelI === void 0 ? void 0 : _state$singleChannelI.toString()), ViewerStateKeys.UseExactScaleLevel, serializeBoolean(state.useExactScaleLevel)), ViewerStateKeys.ScaleLevelIndex, (_state$scaleLevelInde = state.scaleLevelIndex) === null || _state$scaleLevelInde === void 0 ? void 0 : _state$scaleLevelInde.toString()), _defineProperty(_result, ViewerStateKeys.CameraState, state.cameraState && serializeCameraState(state.cameraState, removeDefaults, state.viewMode)));
|
|
991
1005
|
var viewModeToViewParam = _defineProperty(_defineProperty(_defineProperty(_defineProperty({}, ViewMode.threeD, "3D"), ViewMode.xy, "Z"), ViewMode.xz, "Y"), ViewMode.yz, "X");
|
|
992
1006
|
result[ViewerStateKeys.View] = state.viewMode && viewModeToViewParam[state.viewMode];
|
|
993
1007
|
return removeUndefinedProperties(result);
|
|
@@ -6,14 +6,15 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
|
|
|
6
6
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
7
|
import { create } from "zustand";
|
|
8
8
|
import { subscribeWithSelector } from "zustand/middleware";
|
|
9
|
-
import { getDefaultViewerState } from "../shared/constants";
|
|
9
|
+
import { getDefaultChannelColor, getDefaultViewerState } from "../shared/constants";
|
|
10
|
+
import { initializeOneChannelSetting } from "../shared/utils/viewerState";
|
|
10
11
|
import { createResetSlice } from "./reset";
|
|
11
12
|
import { validateState, validateStateValue } from "./util";
|
|
12
|
-
var createViewerStateStore = function createViewerStateStore(set) {
|
|
13
|
-
for (var _len = arguments.length, etc = new Array(_len >
|
|
14
|
-
etc[_key -
|
|
13
|
+
var createViewerStateStore = function createViewerStateStore(set, get) {
|
|
14
|
+
for (var _len = arguments.length, etc = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
|
|
15
|
+
etc[_key - 2] = arguments[_key];
|
|
15
16
|
}
|
|
16
|
-
return _objectSpread(_objectSpread(_objectSpread({}, createResetSlice.apply(void 0, [set].concat(etc))), getDefaultViewerState()), {}, {
|
|
17
|
+
return _objectSpread(_objectSpread(_objectSpread({}, createResetSlice.apply(void 0, [set, get].concat(etc))), getDefaultViewerState()), {}, {
|
|
17
18
|
channelSettings: [],
|
|
18
19
|
changeViewerSetting: function changeViewerSetting(key, value) {
|
|
19
20
|
return set(function (state) {
|
|
@@ -41,6 +42,21 @@ var createViewerStateStore = function createViewerStateStore(set) {
|
|
|
41
42
|
channelSettings: channelSettings
|
|
42
43
|
});
|
|
43
44
|
},
|
|
45
|
+
initChannelSettings: function initChannelSettings(names, settings) {
|
|
46
|
+
var currentSettings = get().channelSettings;
|
|
47
|
+
var channelSettings = names.map(function (name, index) {
|
|
48
|
+
var _currentSettings$inde;
|
|
49
|
+
var color = getDefaultChannelColor(index);
|
|
50
|
+
var channelSetting = (_currentSettings$inde = currentSettings[index]) !== null && _currentSettings$inde !== void 0 ? _currentSettings$inde : initializeOneChannelSetting(name, index, color, settings);
|
|
51
|
+
return _objectSpread(_objectSpread({}, channelSetting), {}, {
|
|
52
|
+
name: name
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
set({
|
|
56
|
+
channelSettings: channelSettings
|
|
57
|
+
});
|
|
58
|
+
return channelSettings;
|
|
59
|
+
},
|
|
44
60
|
applyColorPresets: function applyColorPresets(colors) {
|
|
45
61
|
set(function (_ref2) {
|
|
46
62
|
var channelSettings = _ref2.channelSettings;
|
|
@@ -77,7 +93,9 @@ export var selectViewerSettings = function selectViewerSettings(store) {
|
|
|
77
93
|
scene: store.scene,
|
|
78
94
|
cameraState: store.cameraState,
|
|
79
95
|
singleChannelMode: store.singleChannelMode,
|
|
80
|
-
singleChannelIndex: store.singleChannelIndex
|
|
96
|
+
singleChannelIndex: store.singleChannelIndex,
|
|
97
|
+
useExactScaleLevel: store.useExactScaleLevel,
|
|
98
|
+
scaleLevelIndex: store.scaleLevelIndex
|
|
81
99
|
};
|
|
82
100
|
};
|
|
83
101
|
|
|
@@ -139,7 +139,28 @@ export var subscribeImageToState = function subscribeImageToState(store, view3d,
|
|
|
139
139
|
// interpolation
|
|
140
140
|
store.subscribe(select("interpolationEnabled"), function (enabled) {
|
|
141
141
|
return view3d.setInterpolationEnabled(image, enabled);
|
|
142
|
-
}, REF_EQ),
|
|
142
|
+
}, REF_EQ), store.subscribe(function (_ref3) {
|
|
143
|
+
var useExactScaleLevel = _ref3.useExactScaleLevel,
|
|
144
|
+
scaleLevelIndex = _ref3.scaleLevelIndex;
|
|
145
|
+
return {
|
|
146
|
+
useExactScaleLevel: useExactScaleLevel,
|
|
147
|
+
scaleLevelIndex: scaleLevelIndex
|
|
148
|
+
};
|
|
149
|
+
}, function (_ref4) {
|
|
150
|
+
var useExactScaleLevel = _ref4.useExactScaleLevel,
|
|
151
|
+
scaleLevelIndex = _ref4.scaleLevelIndex;
|
|
152
|
+
if (useExactScaleLevel) {
|
|
153
|
+
image.updateRequiredData({
|
|
154
|
+
useExplicitLevel: true,
|
|
155
|
+
multiscaleLevel: scaleLevelIndex
|
|
156
|
+
});
|
|
157
|
+
} else {
|
|
158
|
+
image.updateRequiredData({
|
|
159
|
+
useExplicitLevel: false,
|
|
160
|
+
multiscaleLevel: undefined
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}, DEEP_EQ),
|
|
143
164
|
// clipping
|
|
144
165
|
store.subscribe(selectAxisClipUpdateInfo("x"), axisClipUpdater("x"), DEEP_EQ), store.subscribe(selectAxisClipUpdateInfo("y"), axisClipUpdater("y"), DEEP_EQ), store.subscribe(selectAxisClipUpdateInfo("z"), axisClipUpdater("z"), DEEP_EQ)
|
|
145
166
|
|
|
@@ -40,7 +40,9 @@ var arbitraryViewerState = function arbitraryViewerState() {
|
|
|
40
40
|
scene: 3,
|
|
41
41
|
singleChannelMode: true,
|
|
42
42
|
singleChannelIndex: 3,
|
|
43
|
-
cameraState: undefined
|
|
43
|
+
cameraState: undefined,
|
|
44
|
+
useExactScaleLevel: true,
|
|
45
|
+
scaleLevelIndex: 3
|
|
44
46
|
};
|
|
45
47
|
};
|
|
46
48
|
var arbitraryChannelState = function arbitraryChannelState() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aics/vole-app",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "web view of cell volume images",
|
|
5
5
|
"main": "es/index.js",
|
|
6
6
|
"module": "es/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"author": "Megan Riel-Mehan",
|
|
46
46
|
"license": "ISC",
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@aics/vole-core": "^4.
|
|
48
|
+
"@aics/vole-core": "^4.8.2",
|
|
49
49
|
"@ant-design/icons": "^5.2.5",
|
|
50
50
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
|
51
51
|
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { VolumeDims } from "@aics/vole-core/es/types/VolumeDims";
|
|
1
2
|
import React from "react";
|
|
2
3
|
import "./styles.css";
|
|
3
4
|
type ToolbarProps = {
|
|
@@ -6,6 +7,8 @@ type ToolbarProps = {
|
|
|
6
7
|
hasCellId: boolean;
|
|
7
8
|
hasParentImage: boolean;
|
|
8
9
|
canPathTrace: boolean;
|
|
10
|
+
multiscaleDims?: VolumeDims[];
|
|
11
|
+
multiscaleIndex?: number;
|
|
9
12
|
resetCamera: () => void;
|
|
10
13
|
downloadScreenshot: () => void;
|
|
11
14
|
resetToSavedViewerState: () => void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type RawArrayLoaderOptions, type View3d, type Volume } from "@aics/vole-core";
|
|
1
|
+
import { LoadSpec, type RawArrayLoaderOptions, type View3d, type Volume } from "@aics/vole-core";
|
|
2
2
|
import type { AxisName } from "../shared/types";
|
|
3
3
|
import PlayControls from "../shared/utils/playControls";
|
|
4
4
|
import type { ChannelGrouping, ViewerChannelSettings } from "../shared/utils/viewerChannelSettings";
|
|
@@ -7,7 +7,7 @@ export type UseVolumeOptions = {
|
|
|
7
7
|
/** Callback called just once when the volume is created. */
|
|
8
8
|
onCreateImage?: (image: Volume) => void;
|
|
9
9
|
/** Callback called on any scene change, including the initial image load. */
|
|
10
|
-
onChangeScene?: (image: Volume, sceneIndex: number) => void;
|
|
10
|
+
onChangeScene?: (image: Volume, sceneIndex: number, loadSpec: LoadSpec) => void;
|
|
11
11
|
/** Callback for when a single channel of the volume has loaded. */
|
|
12
12
|
onChannelLoaded?: (image: Volume, channelIndex: number, isInitialLoad: boolean) => void;
|
|
13
13
|
/** Callback for when image loading encounters an error. */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { LoadSpec, PrefetchDirection, RawArrayLoaderOptions, Volume, VolumeLoaderContext } from "@aics/vole-core";
|
|
2
2
|
import type { ThreadableVolumeLoader } from "@aics/vole-core/es/types/loaders/IVolumeLoader";
|
|
3
3
|
export type LoadSceneOptions = {
|
|
4
|
-
onCreateScene?: (volume: Volume, sceneIndex: number) => void;
|
|
4
|
+
onCreateScene?: (volume: Volume, sceneIndex: number, loadSpec: LoadSpec) => void;
|
|
5
5
|
onChannelLoaded?: (volume: Volume, channelIndex: number) => void;
|
|
6
6
|
};
|
|
7
7
|
export default class SceneStore {
|
|
@@ -50,7 +50,9 @@ export declare enum ViewerStateKeys {
|
|
|
50
50
|
Scene = "scene",
|
|
51
51
|
CameraState = "cam",
|
|
52
52
|
SingleChannelMode = "scm",
|
|
53
|
-
SingleChannelIndex = "sci"
|
|
53
|
+
SingleChannelIndex = "sci",
|
|
54
|
+
UseExactScaleLevel = "esl",
|
|
55
|
+
ScaleLevelIndex = "scl"
|
|
54
56
|
}
|
|
55
57
|
export declare enum CameraTransformKeys {
|
|
56
58
|
/** Camera position in 3D coordinates. */
|
|
@@ -230,6 +232,10 @@ export declare class ViewerStateParams {
|
|
|
230
232
|
[ViewerStateKeys.Time]?: string;
|
|
231
233
|
/** Scene number, for multiscene images. 0 by default. */
|
|
232
234
|
[ViewerStateKeys.Scene]?: string;
|
|
235
|
+
/** Whether to use an exact scale level index. 0 by default. */
|
|
236
|
+
[ViewerStateKeys.UseExactScaleLevel]?: string;
|
|
237
|
+
/** The exact scale level index to use, if `UseExactScaleLevel` is 1. 0 by default. */
|
|
238
|
+
[ViewerStateKeys.ScaleLevelIndex]?: string;
|
|
233
239
|
/**
|
|
234
240
|
* Camera transform settings, as a list of `key:value` pairs separated by commas.
|
|
235
241
|
* Valid keys are defined in `CameraTransformKeys`:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ColorArray } from "../shared/utils/colorRepresentations";
|
|
2
|
+
import type { ViewerChannelSettings } from "../shared/utils/viewerChannelSettings";
|
|
2
3
|
import { type ResetStateSlice } from "./reset";
|
|
3
4
|
import type { ChannelState, ViewerState } from "./types";
|
|
4
5
|
export type ViewerStateActions = {
|
|
@@ -8,6 +9,7 @@ export type ViewerStateActions = {
|
|
|
8
9
|
}>) => void;
|
|
9
10
|
changeChannelSetting: <K extends keyof ChannelState>(index: number | number[], value: Partial<Record<K, ChannelState[K]>>) => void;
|
|
10
11
|
replaceAllChannelSettings: (channelSettings: ChannelState[]) => void;
|
|
12
|
+
initChannelSettings: (names: string[], settings?: ViewerChannelSettings) => ChannelState[];
|
|
11
13
|
applyColorPresets: (colors: ColorArray[]) => void;
|
|
12
14
|
};
|
|
13
15
|
export type ViewerStore = ViewerState & ViewerStateActions & ResetStateSlice & {
|