@aics/vole-app 2.15.0 → 3.1.1
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/ChannelUpdater.js +21 -3
- package/es/aics-image-viewer/components/App/index.js +156 -199
- package/es/aics-image-viewer/components/CellViewerCanvasWrapper/index.js +10 -9
- package/es/aics-image-viewer/components/ChannelsWidget.js +35 -22
- package/es/aics-image-viewer/components/ChannelsWidgetRow/index.js +27 -71
- package/es/aics-image-viewer/components/ChannelsWidgetRow/styles.css +0 -6
- package/es/aics-image-viewer/components/ColorPicker.js +1 -1
- package/es/aics-image-viewer/components/ControlPanel/index.js +5 -4
- package/es/aics-image-viewer/components/CustomizeWidget.js +12 -8
- package/es/aics-image-viewer/components/ErrorAlert/index.js +4 -4
- package/es/aics-image-viewer/components/GlobalVolumeControls.js +12 -10
- package/es/aics-image-viewer/components/StyleProvider/index.js +4 -2
- package/es/aics-image-viewer/components/TfEditor/index.js +304 -154
- package/es/aics-image-viewer/components/TfEditor/styles.css +53 -31
- package/es/aics-image-viewer/components/Toolbar/DownloadButton.js +1 -1
- package/es/aics-image-viewer/components/Toolbar/index.js +18 -16
- package/es/aics-image-viewer/components/shared/SharedCheckBox.js +1 -1
- package/es/aics-image-viewer/components/shared/SliderRow/styles.css +1 -0
- package/es/aics-image-viewer/components/shared/SmarterSlider.js +1 -1
- package/es/aics-image-viewer/components/shared/ViewerIcon.js +1 -1
- package/es/aics-image-viewer/components/useVolume.js +59 -58
- package/es/aics-image-viewer/shared/constants.js +2 -2
- package/es/aics-image-viewer/shared/utils/controlPointsToLut.js +57 -24
- package/es/aics-image-viewer/shared/utils/sceneStore.js +5 -3
- package/es/aics-image-viewer/shared/utils/storage.js +238 -0
- package/es/aics-image-viewer/shared/utils/test/storage.test.js +264 -0
- package/es/aics-image-viewer/shared/utils/test/urlParsing.test.js +240 -108
- package/es/aics-image-viewer/shared/utils/test/viewerChannelSettings.test.js +1 -1
- package/es/aics-image-viewer/shared/utils/urlParsing.js +278 -153
- package/es/aics-image-viewer/shared/utils/viewerState.js +4 -24
- package/es/aics-image-viewer/state/reset.js +111 -0
- package/es/aics-image-viewer/state/store.js +90 -0
- package/es/aics-image-viewer/state/subscribers.js +153 -0
- package/es/aics-image-viewer/state/test/reset.test.js +247 -0
- package/es/aics-image-viewer/state/util.js +71 -0
- package/es/index.js +3 -3
- package/package.json +18 -11
- package/type-declarations/aics-image-viewer/components/App/ChannelUpdater.d.ts +2 -4
- package/type-declarations/aics-image-viewer/components/App/types.d.ts +3 -3
- package/type-declarations/aics-image-viewer/components/AxisClipSliders/index.d.ts +6 -6
- package/type-declarations/aics-image-viewer/components/CellViewerCanvasWrapper/index.d.ts +5 -14
- package/type-declarations/aics-image-viewer/components/ChannelsWidget.d.ts +3 -6
- package/type-declarations/aics-image-viewer/components/ChannelsWidgetRow/index.d.ts +3 -6
- package/type-declarations/aics-image-viewer/components/ColorPicker.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/ControlPanel/index.d.ts +6 -7
- package/type-declarations/aics-image-viewer/components/CustomizeWidget.d.ts +2 -8
- package/type-declarations/aics-image-viewer/components/ErrorAlert/index.d.ts +4 -0
- package/type-declarations/aics-image-viewer/components/GlobalVolumeControls.d.ts +2 -9
- package/type-declarations/aics-image-viewer/components/MetadataViewer/index.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/StyleProvider/index.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/TfEditor/index.d.ts +10 -3
- package/type-declarations/aics-image-viewer/components/Toolbar/index.d.ts +3 -12
- package/type-declarations/aics-image-viewer/components/shared/SliderRow/index.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/shared/SmarterSlider.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/shared/ViewerIcon.d.ts +1 -1
- package/type-declarations/aics-image-viewer/components/useVolume.d.ts +7 -4
- package/type-declarations/aics-image-viewer/shared/constants.d.ts +5 -5
- package/type-declarations/aics-image-viewer/shared/types.d.ts +1 -1
- package/type-declarations/aics-image-viewer/shared/utils/controlPointsToLut.d.ts +9 -5
- package/type-declarations/aics-image-viewer/shared/utils/firebase/index.d.ts +1 -1
- package/type-declarations/aics-image-viewer/shared/utils/hooks.d.ts +1 -1
- package/type-declarations/aics-image-viewer/shared/utils/playControls.d.ts +1 -1
- package/type-declarations/aics-image-viewer/shared/utils/sceneStore.d.ts +8 -4
- package/type-declarations/aics-image-viewer/shared/utils/storage.d.ts +15 -0
- package/type-declarations/aics-image-viewer/shared/utils/urlParsing.d.ts +94 -31
- package/type-declarations/aics-image-viewer/shared/utils/viewerChannelSettings.d.ts +39 -1
- package/type-declarations/aics-image-viewer/shared/utils/viewerState.d.ts +3 -6
- package/type-declarations/aics-image-viewer/state/reset.d.ts +29 -0
- package/type-declarations/aics-image-viewer/state/store.d.ts +30 -0
- package/type-declarations/aics-image-viewer/state/subscribers.d.ts +4 -0
- package/type-declarations/aics-image-viewer/state/types.d.ts +46 -0
- package/type-declarations/aics-image-viewer/state/util.d.ts +8 -0
- package/type-declarations/index.d.ts +4 -4
- package/es/aics-image-viewer/components/ViewerStateProvider/ResetStateProvider.js +0 -163
- package/es/aics-image-viewer/components/ViewerStateProvider/index.js +0 -259
- package/type-declarations/aics-image-viewer/components/ViewerStateProvider/ResetStateProvider.d.ts +0 -34
- package/type-declarations/aics-image-viewer/components/ViewerStateProvider/index.d.ts +0 -33
- package/type-declarations/aics-image-viewer/components/ViewerStateProvider/types.d.ts +0 -107
- /package/es/aics-image-viewer/{components/ViewerStateProvider → state}/types.js +0 -0
|
@@ -1,3 +1,9 @@
|
|
|
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
|
+
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; }
|
|
3
|
+
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; }
|
|
4
|
+
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; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
|
|
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); }
|
|
1
7
|
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
2
8
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
3
9
|
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; } }
|
|
@@ -6,17 +12,22 @@ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(
|
|
|
6
12
|
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; }
|
|
7
13
|
import { Lut } from "@aics/vole-core";
|
|
8
14
|
import { useEffect } from "react";
|
|
9
|
-
import {
|
|
15
|
+
import { useShallow } from "zustand/shallow";
|
|
16
|
+
import { binIndexedControlPointsToLut, rampToControlPoints } from "../../shared/utils/controlPointsToLut";
|
|
17
|
+
import { useViewerState } from "../../state/store";
|
|
10
18
|
/**
|
|
11
19
|
* A component that doesn't render anything, but reacts to the provided `ChannelState`
|
|
12
20
|
* and keeps it in sync with the viewer.
|
|
13
21
|
*/
|
|
14
22
|
var ChannelUpdater = function ChannelUpdater(_ref) {
|
|
15
23
|
var index = _ref.index,
|
|
16
|
-
channelState = _ref.channelState,
|
|
17
24
|
view3d = _ref.view3d,
|
|
18
25
|
image = _ref.image,
|
|
19
26
|
version = _ref.version;
|
|
27
|
+
var channelStateSelector = useShallow(function (state) {
|
|
28
|
+
return state.channelSettings[index];
|
|
29
|
+
});
|
|
30
|
+
var channelState = useViewerState(channelStateSelector);
|
|
20
31
|
var volumeEnabled = channelState.volumeEnabled,
|
|
21
32
|
isosurfaceEnabled = channelState.isosurfaceEnabled,
|
|
22
33
|
isovalue = channelState.isovalue,
|
|
@@ -73,8 +84,15 @@ var ChannelUpdater = function ChannelUpdater(_ref) {
|
|
|
73
84
|
if (useControlPoints && controlPoints.length < 2) {
|
|
74
85
|
return;
|
|
75
86
|
}
|
|
87
|
+
var histogram = currentImage.getHistogram(index);
|
|
76
88
|
var controlPointsToUse = useControlPoints ? controlPoints : rampToControlPoints(ramp);
|
|
77
|
-
|
|
89
|
+
// Convert control points from raw intensity values to histogram bin indices
|
|
90
|
+
var binIndexedControlPoints = controlPointsToUse.map(function (cp) {
|
|
91
|
+
return _objectSpread(_objectSpread({}, cp), {}, {
|
|
92
|
+
x: histogram.findFractionalBinOfValue(cp.x)
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
var gradient = binIndexedControlPointsToLut(binIndexedControlPoints);
|
|
78
96
|
currentImage.setLut(index, gradient);
|
|
79
97
|
view3d.updateLuts(currentImage);
|
|
80
98
|
}, [controlPoints, ramp, useControlPoints, index, view3d]);
|
|
@@ -15,25 +15,23 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
|
|
|
15
15
|
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; } }
|
|
16
16
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
17
17
|
// 3rd Party Imports
|
|
18
|
-
import {
|
|
18
|
+
import { View3d } from "@aics/vole-core";
|
|
19
19
|
import { Layout } from "antd";
|
|
20
20
|
import { debounce, isEqual } from "lodash";
|
|
21
|
-
import React, { useCallback,
|
|
22
|
-
import { AXIS_MARGIN_DEFAULT, CLIPPING_PANEL_HEIGHT_DEFAULT, CLIPPING_PANEL_HEIGHT_TALL, CONTROL_PANEL_CLOSE_WIDTH,
|
|
23
|
-
import { ImageType,
|
|
24
|
-
import {
|
|
25
|
-
import { colorArrayToFloats } from "../../shared/utils/colorRepresentations";
|
|
26
|
-
import { controlPointsToRamp, initializeLut, rampToControlPoints, remapControlPointsForChannel } from "../../shared/utils/controlPointsToLut";
|
|
21
|
+
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
22
|
+
import { AXIS_MARGIN_DEFAULT, CLIPPING_PANEL_HEIGHT_DEFAULT, CLIPPING_PANEL_HEIGHT_TALL, CONTROL_PANEL_CLOSE_WIDTH, getDefaultViewerChannelSettings, getDefaultViewerState, SCALE_BAR_MARGIN_DEFAULT } from "../../shared/constants";
|
|
23
|
+
import { ImageType, ViewMode } from "../../shared/enums";
|
|
24
|
+
import { controlPointsToRamp, initializeLut } from "../../shared/utils/controlPointsToLut";
|
|
27
25
|
import { useConstructor } from "../../shared/utils/hooks";
|
|
28
|
-
import { alphaSliderToImageValue, brightnessSliderToImageValue, densitySliderToImageValue, gammaSliderToImageValues } from "../../shared/utils/sliderValuesToImageValues";
|
|
29
26
|
import { findFirstChannelMatch } from "../../shared/utils/viewerChannelSettings";
|
|
27
|
+
import { select, useViewerState } from "../../state/store";
|
|
28
|
+
import { subscribeImageToState, subscribeViewToState } from "../../state/subscribers";
|
|
30
29
|
import useVolume, { ImageLoadStatus } from "../useVolume";
|
|
31
30
|
import CellViewerCanvasWrapper from "../CellViewerCanvasWrapper";
|
|
32
31
|
import ControlPanel from "../ControlPanel";
|
|
33
32
|
import { useErrorAlert } from "../ErrorAlert";
|
|
34
33
|
import StyleProvider from "../StyleProvider";
|
|
35
34
|
import Toolbar from "../Toolbar";
|
|
36
|
-
import { ViewerStateContext } from "../ViewerStateProvider";
|
|
37
35
|
import ChannelUpdater from "./ChannelUpdater";
|
|
38
36
|
import "../../assets/styles/globals.css";
|
|
39
37
|
import "./styles.css";
|
|
@@ -106,31 +104,37 @@ var setIndicatorPositions = function setIndicatorPositions(view3d, panelOpen, ha
|
|
|
106
104
|
view3d.setScaleBarPosition(scaleBarX, scaleBarY);
|
|
107
105
|
};
|
|
108
106
|
var App = function App(props) {
|
|
109
|
-
var _props$showError,
|
|
107
|
+
var _props$showError, _props$viewerChannelS, _scenes$length, _scenes2, _image$imageInfo$volu, _image$imageInfo$subr, _image$imageInfo$time, _props$transform2, _props$transform4;
|
|
110
108
|
props = _objectSpread(_objectSpread({}, defaultProps), props);
|
|
111
109
|
|
|
112
110
|
// State management /////////////////////////////////////////////////////////
|
|
113
|
-
var
|
|
114
|
-
var
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
111
|
+
var imageType = useViewerState(select("imageType"));
|
|
112
|
+
var viewMode = useViewerState(select("viewMode"));
|
|
113
|
+
var scene = useViewerState(select("scene"));
|
|
114
|
+
var time = useViewerState(select("time"));
|
|
115
|
+
var showAxes = useViewerState(select("showAxes"));
|
|
116
|
+
var channelSettings = useViewerState(select("channelSettings"));
|
|
117
|
+
var changeChannelSetting = useViewerState(select("changeChannelSetting"));
|
|
118
|
+
var applyColorPresets = useViewerState(select("applyColorPresets"));
|
|
119
|
+
var resetToSavedState = useViewerState(select("resetToSavedViewerState"));
|
|
120
|
+
var resetToSavedViewerState = useCallback(function () {
|
|
121
|
+
return resetToSavedState(props.viewerSettings, props.viewerChannelSettings);
|
|
122
|
+
}, [resetToSavedState, props.viewerSettings, props.viewerChannelSettings]);
|
|
123
|
+
|
|
124
|
+
// Apply viewer settings to state that have changed since the last prop
|
|
125
|
+
var prevViewerSettingsPropsRef = useRef();
|
|
126
|
+
if (props.viewerSettings && !isEqual(props.viewerSettings, prevViewerSettingsPropsRef.current)) {
|
|
127
|
+
for (var _i = 0, _arr = Object.keys(props.viewerSettings); _i < _arr.length; _i++) {
|
|
128
|
+
var _prevViewerSettingsPr, _prevViewerSettingsPr2;
|
|
129
|
+
var key = _arr[_i];
|
|
130
|
+
var value = props.viewerSettings[key];
|
|
131
|
+
var lastValue = (_prevViewerSettingsPr = (_prevViewerSettingsPr2 = prevViewerSettingsPropsRef.current) === null || _prevViewerSettingsPr2 === void 0 ? void 0 : _prevViewerSettingsPr2[key]) !== null && _prevViewerSettingsPr !== void 0 ? _prevViewerSettingsPr : undefined;
|
|
132
|
+
if (value !== undefined && !isEqual(value, lastValue)) {
|
|
133
|
+
useViewerState.getState().changeViewerSetting(key, value);
|
|
134
|
+
}
|
|
132
135
|
}
|
|
133
|
-
|
|
136
|
+
prevViewerSettingsPropsRef.current = props.viewerSettings;
|
|
137
|
+
}
|
|
134
138
|
var view3d = useConstructor(function () {
|
|
135
139
|
return new View3d();
|
|
136
140
|
});
|
|
@@ -156,11 +160,11 @@ var App = function App(props) {
|
|
|
156
160
|
}, [view3d, showError]);
|
|
157
161
|
var imageUrlRef = useRef("");
|
|
158
162
|
var scenesRef = useRef([]);
|
|
159
|
-
var
|
|
160
|
-
imageUrl =
|
|
161
|
-
parentImageUrl =
|
|
162
|
-
rawData =
|
|
163
|
-
rawDims =
|
|
163
|
+
var _props = props,
|
|
164
|
+
imageUrl = _props.imageUrl,
|
|
165
|
+
parentImageUrl = _props.parentImageUrl,
|
|
166
|
+
rawData = _props.rawData,
|
|
167
|
+
rawDims = _props.rawDims;
|
|
164
168
|
var scenes = useMemo(function () {
|
|
165
169
|
if (rawData && rawDims) {
|
|
166
170
|
return [{
|
|
@@ -181,21 +185,31 @@ var App = function App(props) {
|
|
|
181
185
|
return result;
|
|
182
186
|
}
|
|
183
187
|
}, [imageUrl, parentImageUrl, rawData, rawDims, imageType]);
|
|
184
|
-
var maskChannelName = (
|
|
188
|
+
var maskChannelName = (_props$viewerChannelS = props.viewerChannelSettings) === null || _props$viewerChannelS === void 0 ? void 0 : _props$viewerChannelS.maskChannelName;
|
|
185
189
|
|
|
186
190
|
// we need to keep track of channel ranges for remapping control points
|
|
187
191
|
var channelRangesRef = useRef([]);
|
|
192
|
+
var removePreviousImage = useRef(undefined);
|
|
193
|
+
var _props2 = props,
|
|
194
|
+
onImageTitleChange = _props2.onImageTitleChange;
|
|
188
195
|
var onCreateImage = useCallback(function (newImage) {
|
|
189
|
-
var _newImage$imageInfo$c;
|
|
196
|
+
var _removePreviousImage$, _newImage$imageInfo$c;
|
|
197
|
+
(_removePreviousImage$ = removePreviousImage.current) === null || _removePreviousImage$ === void 0 || _removePreviousImage$.call(removePreviousImage);
|
|
190
198
|
if (newImage === null) {
|
|
191
199
|
return;
|
|
192
200
|
}
|
|
201
|
+
var _useViewerState$getSt = useViewerState.getState(),
|
|
202
|
+
channelState = _useViewerState$getSt.channelSettings;
|
|
193
203
|
var channelNames = newImage.channelNames;
|
|
194
|
-
channelRangesRef.current =
|
|
195
|
-
|
|
204
|
+
channelRangesRef.current = channelNames.map(function (_, i) {
|
|
205
|
+
var _channelState$i;
|
|
206
|
+
return (_channelState$i = channelState[i]) !== null && _channelState$i !== void 0 && _channelState$i.keepIntensityRange ? channelRangesRef.current[i] : undefined;
|
|
207
|
+
});
|
|
208
|
+
var _useViewerState$getSt2 = useViewerState.getState(),
|
|
209
|
+
useDefaultViewerChannelSettings = _useViewerState$getSt2.useDefaultViewerChannelSettings;
|
|
210
|
+
var viewerChannelSettings = useDefaultViewerChannelSettings ? getDefaultViewerChannelSettings() : props.viewerChannelSettings;
|
|
196
211
|
|
|
197
212
|
// If the image has channel color metadata, apply those colors now
|
|
198
|
-
var viewerChannelSettings = getCurrentViewerChannelSettings();
|
|
199
213
|
var channelColorMeta = (_newImage$imageInfo$c = newImage.imageInfo.channelColors) === null || _newImage$imageInfo$c === void 0 ? void 0 : _newImage$imageInfo$c.map(function (color, index) {
|
|
200
214
|
// Filter out channels that have colors in `viewerChannelSettings`
|
|
201
215
|
if (viewerChannelSettings === undefined) {
|
|
@@ -222,7 +236,7 @@ var App = function App(props) {
|
|
|
222
236
|
channels: newImage.channelNames.map(function (name, index) {
|
|
223
237
|
var _channelColorMeta$ind;
|
|
224
238
|
// TODO do we really need to be searching by name here?
|
|
225
|
-
var ch =
|
|
239
|
+
var ch = channelState.find(function (channel) {
|
|
226
240
|
return channel.name === name;
|
|
227
241
|
});
|
|
228
242
|
if (!ch) {
|
|
@@ -237,55 +251,72 @@ var App = function App(props) {
|
|
|
237
251
|
};
|
|
238
252
|
})
|
|
239
253
|
});
|
|
240
|
-
onImageTitleChange === null || onImageTitleChange === void 0 || onImageTitleChange(newImage.imageInfo.imageInfo.name);
|
|
241
254
|
view3d.updateActiveChannels(newImage);
|
|
242
|
-
|
|
255
|
+
var unsubscribeView = subscribeViewToState(useViewerState, view3d);
|
|
256
|
+
var unsubscribeImage = subscribeImageToState(useViewerState, view3d, newImage);
|
|
257
|
+
removePreviousImage.current = function () {
|
|
258
|
+
unsubscribeView();
|
|
259
|
+
unsubscribeImage();
|
|
260
|
+
view3d.removeAllVolumes();
|
|
261
|
+
removePreviousImage.current = undefined;
|
|
262
|
+
};
|
|
263
|
+
}, [props.viewerChannelSettings, view3d, changeChannelSetting]);
|
|
264
|
+
var _useState = useState(undefined),
|
|
265
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
266
|
+
loadedScene = _useState2[0],
|
|
267
|
+
setLoadedScene = _useState2[1];
|
|
268
|
+
var onChangeScene = useCallback(function (image, sceneIndex) {
|
|
269
|
+
onImageTitleChange === null || onImageTitleChange === void 0 || onImageTitleChange(image.imageInfo.imageInfo.name);
|
|
270
|
+
setLoadedScene(sceneIndex);
|
|
271
|
+
}, [onImageTitleChange]);
|
|
243
272
|
var onChannelLoaded = useCallback(function (image, channelIndex, isInitialLoad) {
|
|
244
|
-
// TODO this was once a search by name - is that still necessary or will
|
|
245
|
-
|
|
246
|
-
var
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
273
|
+
// TODO this was once a search by name - is that still necessary or will
|
|
274
|
+
// the index always be correct?
|
|
275
|
+
var _useViewerState$getSt3 = useViewerState.getState(),
|
|
276
|
+
channelsToResetOnLoad = _useViewerState$getSt3.channelsToResetOnLoad,
|
|
277
|
+
useDefaultViewerChannelSettings = _useViewerState$getSt3.useDefaultViewerChannelSettings,
|
|
278
|
+
channelSettings = _useViewerState$getSt3.channelSettings;
|
|
279
|
+
var channelState = channelSettings[channelIndex];
|
|
280
|
+
var viewerChannelSettings = useDefaultViewerChannelSettings ? getDefaultViewerChannelSettings() : props.viewerChannelSettings;
|
|
250
281
|
var thisChannel = image.getChannel(channelIndex);
|
|
251
|
-
var noLut = !
|
|
252
|
-
|
|
282
|
+
var noLut = !channelState || !channelState.controlPoints || !channelState.ramp;
|
|
283
|
+
var hasOldRange = channelRangesRef.current[channelIndex] !== undefined;
|
|
284
|
+
var canInitializeToExistingRange = (channelState === null || channelState === void 0 ? void 0 : channelState.keepIntensityRange) && hasOldRange;
|
|
285
|
+
// True if we are loading new data and the old range cannot or should not
|
|
286
|
+
// be kept (no saved range or keeping intensities is disabled).
|
|
287
|
+
var needsInitializeToDefaults = isInitialLoad && !canInitializeToExistingRange;
|
|
288
|
+
if (needsInitializeToDefaults || noLut || channelsToResetOnLoad.includes(channelIndex)) {
|
|
289
|
+
var _initSettings$isovalu;
|
|
253
290
|
// This channel needs its LUT initialized
|
|
254
|
-
var _initializeLut = initializeLut(image, channelIndex,
|
|
291
|
+
var _initializeLut = initializeLut(image, channelIndex, viewerChannelSettings),
|
|
255
292
|
ramp = _initializeLut.ramp,
|
|
256
293
|
controlPoints = _initializeLut.controlPoints;
|
|
257
|
-
|
|
294
|
+
|
|
295
|
+
// Initialize isovalue to channel settings or default to midpoint of data range
|
|
296
|
+
var name = image.channelNames[channelIndex];
|
|
297
|
+
var initSettings = viewerChannelSettings && findFirstChannelMatch(name, channelIndex, viewerChannelSettings);
|
|
298
|
+
var defaultIsovalue = thisChannel.rawMin + (thisChannel.rawMax - thisChannel.rawMin) / 2;
|
|
299
|
+
var isovalue = (_initSettings$isovalu = initSettings === null || initSettings === void 0 ? void 0 : initSettings.isovalue) !== null && _initSettings$isovalu !== void 0 ? _initSettings$isovalu : defaultIsovalue;
|
|
258
300
|
changeChannelSetting(channelIndex, {
|
|
259
301
|
controlPoints: controlPoints,
|
|
260
302
|
ramp: controlPointsToRamp(ramp),
|
|
261
303
|
// set the default range of the transfer function editor to cover the full range of the data type
|
|
262
|
-
plotMin:
|
|
263
|
-
plotMax:
|
|
264
|
-
isovalue:
|
|
304
|
+
plotMin: thisChannel.rawMin,
|
|
305
|
+
plotMax: thisChannel.rawMax,
|
|
306
|
+
isovalue: isovalue
|
|
265
307
|
});
|
|
266
308
|
} else {
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
} else {
|
|
279
|
-
// ramp was just automatically remapped - update in state
|
|
280
|
-
var _ramp = controlPointsToRamp(thisChannel.lut.controlPoints);
|
|
281
|
-
// now manually remap control points using the channel's old range
|
|
282
|
-
var _controlPoints = thisChannelSettings.controlPoints;
|
|
283
|
-
var remappedControlPoints = remapControlPointsForChannel(_controlPoints, oldRange, thisChannel);
|
|
284
|
-
changeChannelSetting(channelIndex, {
|
|
285
|
-
controlPoints: remappedControlPoints,
|
|
286
|
-
ramp: _ramp
|
|
287
|
-
});
|
|
288
|
-
}
|
|
309
|
+
// Expand the plot min and max to include the current data range as
|
|
310
|
+
// needed. This keeps the domain visually consistent when replaying
|
|
311
|
+
// through time or Z slices.
|
|
312
|
+
//
|
|
313
|
+
// NOTE: This must use the most up-to-date channel plot range, because
|
|
314
|
+
// onChannelLoaded can be called multiple times per channel during
|
|
315
|
+
// loading.
|
|
316
|
+
changeChannelSetting(channelIndex, {
|
|
317
|
+
plotMin: Math.min(thisChannel.rawMin, channelState.plotMin),
|
|
318
|
+
plotMax: Math.max(thisChannel.rawMax, channelState.plotMax)
|
|
319
|
+
});
|
|
289
320
|
}
|
|
290
321
|
|
|
291
322
|
// save the channel's new range for remapping next time
|
|
@@ -298,14 +329,16 @@ var App = function App(props) {
|
|
|
298
329
|
if (image.isLoaded()) {
|
|
299
330
|
view3d.updateActiveChannels(image);
|
|
300
331
|
}
|
|
301
|
-
}, [view3d,
|
|
332
|
+
}, [view3d, changeChannelSetting, maskChannelName, props.viewerChannelSettings]);
|
|
302
333
|
var onError = useCallback(function (error) {
|
|
303
334
|
showError(error);
|
|
304
335
|
onImageTitleChange === null || onImageTitleChange === void 0 || onImageTitleChange(undefined);
|
|
305
336
|
}, [showError, onImageTitleChange]);
|
|
306
337
|
var volume = useVolume(scenes, {
|
|
338
|
+
viewerChannelSettings: props.viewerChannelSettings,
|
|
307
339
|
onCreateImage: onCreateImage,
|
|
308
340
|
onChannelLoaded: onChannelLoaded,
|
|
341
|
+
onChangeScene: onChangeScene,
|
|
309
342
|
onError: onError,
|
|
310
343
|
maskChannelName: maskChannelName
|
|
311
344
|
});
|
|
@@ -327,26 +360,25 @@ var App = function App(props) {
|
|
|
327
360
|
var numTimesteps = (_image$imageInfo$time = image === null || image === void 0 ? void 0 : image.imageInfo.times) !== null && _image$imageInfo$time !== void 0 ? _image$imageInfo$time : 1;
|
|
328
361
|
|
|
329
362
|
// const [channelGroupedByType, setChannelGroupedByType] = useState<ChannelGrouping>({});
|
|
330
|
-
var
|
|
363
|
+
var _useState3 = useState(function () {
|
|
331
364
|
return window.innerWidth < CONTROL_PANEL_CLOSE_WIDTH;
|
|
332
365
|
}),
|
|
333
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
334
|
-
controlPanelClosed = _useState2[0],
|
|
335
|
-
setControlPanelClosed = _useState2[1];
|
|
336
|
-
// Only allow auto-close once while the screen is too narrow.
|
|
337
|
-
var _useState3 = useState(false),
|
|
338
366
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
367
|
+
controlPanelClosed = _useState4[0],
|
|
368
|
+
setControlPanelClosed = _useState4[1];
|
|
369
|
+
// Only allow auto-close once while the screen is too narrow.
|
|
370
|
+
var _useState5 = useState(false),
|
|
342
371
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
343
|
-
|
|
344
|
-
|
|
372
|
+
hasAutoClosedControlPanel = _useState6[0],
|
|
373
|
+
setHasAutoClosedControlPanel = _useState6[1];
|
|
374
|
+
var _useState7 = useState(true),
|
|
375
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
376
|
+
clippingPanelOpen = _useState8[0],
|
|
377
|
+
setClippingPanelOpen = _useState8[1];
|
|
345
378
|
var clippingPanelOpenTimeout = useRef(0);
|
|
346
379
|
|
|
347
380
|
// Imperative callbacks /////////////////////////////////////////////////////
|
|
348
381
|
|
|
349
|
-
var viewerSettings = viewerState.current;
|
|
350
382
|
var saveIsosurface = useCallback(function (channelIndex, type) {
|
|
351
383
|
if (image) view3d.saveChannelIsosurface(image, channelIndex, type);
|
|
352
384
|
}, [image, view3d]);
|
|
@@ -358,21 +390,24 @@ var App = function App(props) {
|
|
|
358
390
|
anchor.click();
|
|
359
391
|
});
|
|
360
392
|
}, [view3d]);
|
|
361
|
-
var
|
|
393
|
+
var _props3 = props,
|
|
394
|
+
metadataFormatter = _props3.metadataFormatter;
|
|
395
|
+
var metadata = useMemo(function () {
|
|
362
396
|
var imageMetadata = image === null || image === void 0 ? void 0 : image.imageMetadata;
|
|
363
397
|
if (imageMetadata && metadataFormatter) {
|
|
364
398
|
imageMetadata = metadataFormatter(imageMetadata);
|
|
365
399
|
}
|
|
400
|
+
var propsMetadata = props.metadata;
|
|
366
401
|
var sceneMeta;
|
|
367
|
-
if (Array.isArray(
|
|
402
|
+
if (Array.isArray(propsMetadata)) {
|
|
368
403
|
// If metadata is an array, try to index it by scene
|
|
369
|
-
if (
|
|
370
|
-
sceneMeta =
|
|
404
|
+
if (propsMetadata.length >= numScenes && loadedScene !== undefined) {
|
|
405
|
+
sceneMeta = propsMetadata[loadedScene];
|
|
371
406
|
} else {
|
|
372
|
-
sceneMeta =
|
|
407
|
+
sceneMeta = propsMetadata[0];
|
|
373
408
|
}
|
|
374
409
|
} else {
|
|
375
|
-
sceneMeta =
|
|
410
|
+
sceneMeta = propsMetadata;
|
|
376
411
|
}
|
|
377
412
|
if (imageMetadata && Object.keys(imageMetadata).length > 0) {
|
|
378
413
|
return _objectSpread({
|
|
@@ -382,11 +417,11 @@ var App = function App(props) {
|
|
|
382
417
|
var _sceneMeta;
|
|
383
418
|
return (_sceneMeta = sceneMeta) !== null && _sceneMeta !== void 0 ? _sceneMeta : {};
|
|
384
419
|
}
|
|
385
|
-
}, [metadata, metadataFormatter, image,
|
|
420
|
+
}, [props.metadata, metadataFormatter, image, loadedScene, numScenes]);
|
|
386
421
|
useEffect(function () {
|
|
387
422
|
var hasTime = numTimesteps > 1;
|
|
388
423
|
var hasScenes = numScenes > 1;
|
|
389
|
-
var mode3d =
|
|
424
|
+
var mode3d = viewMode === ViewMode.threeD;
|
|
390
425
|
setIndicatorPositions(view3d, clippingPanelOpen, hasTime, hasScenes, mode3d);
|
|
391
426
|
|
|
392
427
|
// Hide indicators while clipping panel is in motion - otherwise they pop to the right place prematurely
|
|
@@ -398,12 +433,12 @@ var App = function App(props) {
|
|
|
398
433
|
clippingPanelOpenTimeout.current = window.setTimeout(function () {
|
|
399
434
|
view3d.setShowScaleBar(true);
|
|
400
435
|
view3d.setShowTimestepIndicator(true);
|
|
401
|
-
if (
|
|
436
|
+
if (showAxes) {
|
|
402
437
|
view3d.setShowAxis(true);
|
|
403
438
|
}
|
|
404
439
|
}, CLIPPING_PANEL_ANIMATION_DURATION_MS);
|
|
405
440
|
}
|
|
406
|
-
}, [view3d, numTimesteps, numScenes,
|
|
441
|
+
}, [view3d, numTimesteps, numScenes, viewMode, showAxes, clippingPanelOpen]);
|
|
407
442
|
|
|
408
443
|
// Effects //////////////////////////////////////////////////////////////////
|
|
409
444
|
|
|
@@ -425,6 +460,8 @@ var App = function App(props) {
|
|
|
425
460
|
return window.removeEventListener("resize", onResizeDebounced);
|
|
426
461
|
};
|
|
427
462
|
}, [hasAutoClosedControlPanel]);
|
|
463
|
+
var _props4 = props,
|
|
464
|
+
onControlPanelToggle = _props4.onControlPanelToggle;
|
|
428
465
|
useEffect(function () {
|
|
429
466
|
return onControlPanelToggle && onControlPanelToggle(controlPanelClosed);
|
|
430
467
|
}, [controlPanelClosed, onControlPanelToggle]);
|
|
@@ -447,36 +484,17 @@ var App = function App(props) {
|
|
|
447
484
|
};
|
|
448
485
|
|
|
449
486
|
// Effects to imperatively sync `viewerSettings` to `view3d`
|
|
450
|
-
|
|
451
|
-
view3d.setCameraMode(viewerSettings.viewMode);
|
|
452
|
-
view3d.resize(null);
|
|
453
|
-
}, [viewerSettings.viewMode, view3d]);
|
|
454
|
-
useImageEffect(function (_currentImage) {
|
|
455
|
-
if (viewerSettings.cameraState) {
|
|
456
|
-
view3d.setCameraState(viewerSettings.cameraState);
|
|
457
|
-
}
|
|
458
|
-
}, [viewerSettings.cameraState, view3d]);
|
|
459
|
-
useImageEffect(function (_currentImage) {
|
|
460
|
-
return view3d.setAutoRotate(viewerSettings.autorotate);
|
|
461
|
-
}, [viewerSettings.autorotate, view3d]);
|
|
462
|
-
useImageEffect(function (_currentImage) {
|
|
463
|
-
return view3d.setShowAxis(viewerSettings.showAxes);
|
|
464
|
-
}, [viewerSettings.showAxes, view3d]);
|
|
465
|
-
useImageEffect(function (_currentImage) {
|
|
466
|
-
return view3d.setBackgroundColor(colorArrayToFloats(viewerSettings.backgroundColor));
|
|
467
|
-
}, [viewerSettings.backgroundColor, view3d]);
|
|
468
|
-
useImageEffect(function (currentImage) {
|
|
469
|
-
return view3d.setBoundingBoxColor(currentImage, colorArrayToFloats(viewerSettings.boundingBoxColor));
|
|
470
|
-
}, [viewerSettings.boundingBoxColor, view3d]);
|
|
471
|
-
useImageEffect(function (currentImage) {
|
|
472
|
-
return view3d.setShowBoundingBox(currentImage, viewerSettings.showBoundingBox);
|
|
473
|
-
}, [viewerSettings.showBoundingBox, view3d]);
|
|
487
|
+
|
|
474
488
|
useImageEffect(function (image) {
|
|
475
489
|
// Check whether any channels are marked to be reset and apply it.
|
|
476
|
-
var
|
|
490
|
+
var viewerState = useViewerState.getState();
|
|
491
|
+
var channelsToReset = viewerState.channelsToReset,
|
|
492
|
+
onResetChannel = viewerState.onResetChannel,
|
|
493
|
+
useDefaultViewerChannelSettings = viewerState.useDefaultViewerChannelSettings;
|
|
494
|
+
var viewerChannelSettings = useDefaultViewerChannelSettings ? getDefaultViewerChannelSettings() : props.viewerChannelSettings;
|
|
477
495
|
for (var i = 0; i < channelSettings.length; i++) {
|
|
478
|
-
if (
|
|
479
|
-
var _initializeLut2 = initializeLut(image, i,
|
|
496
|
+
if (channelsToReset.includes(i)) {
|
|
497
|
+
var _initializeLut2 = initializeLut(image, i, viewerChannelSettings),
|
|
480
498
|
ramp = _initializeLut2.ramp,
|
|
481
499
|
controlPoints = _initializeLut2.controlPoints;
|
|
482
500
|
changeChannelSetting(i, {
|
|
@@ -486,40 +504,15 @@ var App = function App(props) {
|
|
|
486
504
|
onResetChannel(i);
|
|
487
505
|
}
|
|
488
506
|
}
|
|
489
|
-
}, [changeChannelSetting, channelSettings,
|
|
490
|
-
useImageEffect(function (currentImage) {
|
|
491
|
-
var renderMode = viewerSettings.renderMode;
|
|
492
|
-
view3d.setMaxProjectMode(currentImage, renderMode === RenderMode.maxProject);
|
|
493
|
-
view3d.setVolumeRenderMode(renderMode === RenderMode.pathTrace ? RENDERMODE_PATHTRACE : RENDERMODE_RAYMARCH);
|
|
494
|
-
view3d.updateActiveChannels(currentImage);
|
|
495
|
-
}, [viewerSettings.renderMode, view3d]);
|
|
496
|
-
useImageEffect(function (currentImage) {
|
|
497
|
-
view3d.updateMaskAlpha(currentImage, alphaSliderToImageValue(viewerSettings.maskAlpha));
|
|
498
|
-
view3d.updateActiveChannels(currentImage);
|
|
499
|
-
}, [viewerSettings.maskAlpha, view3d]);
|
|
500
|
-
useImageEffect(function (_currentImage) {
|
|
501
|
-
var brightness = brightnessSliderToImageValue(viewerSettings.brightness);
|
|
502
|
-
view3d.updateExposure(brightness);
|
|
503
|
-
}, [viewerSettings.brightness, view3d]);
|
|
504
|
-
useImageEffect(function (currentImage) {
|
|
505
|
-
var density = densitySliderToImageValue(viewerSettings.density);
|
|
506
|
-
view3d.updateDensity(currentImage, density);
|
|
507
|
-
}, [viewerSettings.density, view3d]);
|
|
508
|
-
useImageEffect(function (currentImage) {
|
|
509
|
-
var imageValues = gammaSliderToImageValues(viewerSettings.levels);
|
|
510
|
-
view3d.setGamma(currentImage, imageValues.min, imageValues.scale, imageValues.max);
|
|
511
|
-
}, [viewerSettings.levels, view3d]);
|
|
507
|
+
}, [changeChannelSetting, channelSettings, props.viewerChannelSettings]);
|
|
512
508
|
|
|
513
509
|
// `time` and `scene` have their own special handlers via `volume`, since they both trigger loads
|
|
514
510
|
useEffect(function () {
|
|
515
|
-
return setTime(view3d,
|
|
516
|
-
}, [view3d,
|
|
511
|
+
return setTime(view3d, time);
|
|
512
|
+
}, [view3d, time, setTime]);
|
|
517
513
|
useEffect(function () {
|
|
518
|
-
return setScene(
|
|
519
|
-
}, [
|
|
520
|
-
useImageEffect(function (currentImage) {
|
|
521
|
-
return view3d.setInterpolationEnabled(currentImage, viewerSettings.interpolationEnabled);
|
|
522
|
-
}, [viewerSettings.interpolationEnabled, view3d]);
|
|
514
|
+
return setScene(scene);
|
|
515
|
+
}, [scene, setScene]);
|
|
523
516
|
useImageEffect(function (currentImage) {
|
|
524
517
|
var _props$transform;
|
|
525
518
|
return view3d.setVolumeTranslation(currentImage, ((_props$transform = props.transform) === null || _props$transform === void 0 ? void 0 : _props$transform.translation) || [0, 0, 0]);
|
|
@@ -528,43 +521,6 @@ var App = function App(props) {
|
|
|
528
521
|
var _props$transform3;
|
|
529
522
|
return view3d.setVolumeRotation(currentImage, ((_props$transform3 = props.transform) === null || _props$transform3 === void 0 ? void 0 : _props$transform3.rotation) || [0, 0, 0]);
|
|
530
523
|
}, [(_props$transform4 = props.transform) === null || _props$transform4 === void 0 ? void 0 : _props$transform4.rotation, view3d]);
|
|
531
|
-
var usePerAxisClippingUpdater = function usePerAxisClippingUpdater(axis, _ref, slice, viewMode) {
|
|
532
|
-
var _ref2 = _slicedToArray(_ref, 2),
|
|
533
|
-
minval = _ref2[0],
|
|
534
|
-
maxval = _ref2[1];
|
|
535
|
-
useImageEffect(
|
|
536
|
-
// Logic to determine axis clipping range, for each of x,y,z,3d slider:
|
|
537
|
-
// if slider was same as active axis view mode: [viewerSettings.slice[axis], viewerSettings.slice[axis] + 1.0/volumeSize[axis]]
|
|
538
|
-
// if in 3d mode: viewerSettings.region[axis]
|
|
539
|
-
// else: [0,1]
|
|
540
|
-
function (currentImage) {
|
|
541
|
-
var isOrthoAxis = false;
|
|
542
|
-
var axismin = 0.0;
|
|
543
|
-
var axismax = 1.0;
|
|
544
|
-
if (viewMode === ViewMode.threeD) {
|
|
545
|
-
axismin = minval;
|
|
546
|
-
axismax = maxval;
|
|
547
|
-
isOrthoAxis = false;
|
|
548
|
-
} else {
|
|
549
|
-
isOrthoAxis = activeAxisMap[viewMode] === axis;
|
|
550
|
-
var oneSlice = 1 / currentImage.imageInfo.volumeSize[axis];
|
|
551
|
-
axismin = isOrthoAxis ? slice : 0.0;
|
|
552
|
-
axismax = isOrthoAxis ? slice + oneSlice : 1.0;
|
|
553
|
-
if (axis === "z" && viewMode === ViewMode.xy) {
|
|
554
|
-
view3d.setZSlice(currentImage, Math.floor(slice * currentImage.imageInfo.volumeSize.z));
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
// view3d wants the coordinates in the -0.5 to 0.5 range
|
|
558
|
-
view3d.setAxisClip(currentImage, axis, axismin - 0.5, axismax - 0.5, isOrthoAxis);
|
|
559
|
-
view3d.setCameraMode(viewMode);
|
|
560
|
-
// TODO under some circumstances, this effect will trigger a load. Ideally, this would be reflected in the load
|
|
561
|
-
// state managed by `useVolume`. This is complicated by the fact that the relevant methods (`setAxisClip` and
|
|
562
|
-
// `setZSlice`) don't provide a channel load callback like other load-triggering methods (e.g. `setTime`).
|
|
563
|
-
}, [axis, minval, maxval, slice, viewMode]);
|
|
564
|
-
};
|
|
565
|
-
usePerAxisClippingUpdater("x", viewerSettings.region.x, viewerSettings.slice.x, viewMode);
|
|
566
|
-
usePerAxisClippingUpdater("y", viewerSettings.region.y, viewerSettings.slice.y, viewMode);
|
|
567
|
-
usePerAxisClippingUpdater("z", viewerSettings.region.z, viewerSettings.slice.z, viewMode);
|
|
568
524
|
|
|
569
525
|
// Rendering ////////////////////////////////////////////////////////////////
|
|
570
526
|
|
|
@@ -582,10 +538,10 @@ var App = function App(props) {
|
|
|
582
538
|
style: {
|
|
583
539
|
height: props.appHeight
|
|
584
540
|
}
|
|
585
|
-
}, channelSettings.map(function (
|
|
541
|
+
}, channelSettings.map(function (_ref, index) {
|
|
542
|
+
var name = _ref.name;
|
|
586
543
|
return /*#__PURE__*/React.createElement(ChannelUpdater, {
|
|
587
|
-
key: "".concat(index, "_").concat(
|
|
588
|
-
channelState: channelState,
|
|
544
|
+
key: "".concat(index, "_").concat(name),
|
|
589
545
|
index: index,
|
|
590
546
|
view3d: view3d,
|
|
591
547
|
image: image,
|
|
@@ -615,7 +571,7 @@ var App = function App(props) {
|
|
|
615
571
|
saveIsosurface: saveIsosurface,
|
|
616
572
|
onApplyColorPresets: applyColorPresets,
|
|
617
573
|
viewerChannelSettings: props.viewerChannelSettings,
|
|
618
|
-
|
|
574
|
+
metadata: metadata
|
|
619
575
|
})), /*#__PURE__*/React.createElement(Layout, {
|
|
620
576
|
className: "cell-viewer-wrapper",
|
|
621
577
|
style: {
|
|
@@ -629,6 +585,7 @@ var App = function App(props) {
|
|
|
629
585
|
canPathTrace: view3d ? view3d.hasWebGL2() : false,
|
|
630
586
|
resetCamera: resetCamera,
|
|
631
587
|
downloadScreenshot: saveScreenshot,
|
|
588
|
+
resetToSavedViewerState: resetToSavedViewerState,
|
|
632
589
|
visibleControls: visibleControls
|
|
633
590
|
}), /*#__PURE__*/React.createElement(CellViewerCanvasWrapper, {
|
|
634
591
|
view3d: view3d,
|