@aics/vole-app 2.14.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/Globals.d.js +0 -0
- package/es/aics-image-viewer/components/App/ChannelUpdater.js +21 -3
- package/es/aics-image-viewer/components/App/index.js +184 -198
- 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 +26 -52
- 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 +15 -12
- 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/index.js +8 -3
- package/es/aics-image-viewer/components/shared/SliderRow/styles.css +7 -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 +2 -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
package/es/Globals.d.js
ADDED
|
File without changes
|
|
@@ -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,24 +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 {
|
|
26
|
+
import { findFirstChannelMatch } from "../../shared/utils/viewerChannelSettings";
|
|
27
|
+
import { select, useViewerState } from "../../state/store";
|
|
28
|
+
import { subscribeImageToState, subscribeViewToState } from "../../state/subscribers";
|
|
29
29
|
import useVolume, { ImageLoadStatus } from "../useVolume";
|
|
30
30
|
import CellViewerCanvasWrapper from "../CellViewerCanvasWrapper";
|
|
31
31
|
import ControlPanel from "../ControlPanel";
|
|
32
32
|
import { useErrorAlert } from "../ErrorAlert";
|
|
33
33
|
import StyleProvider from "../StyleProvider";
|
|
34
34
|
import Toolbar from "../Toolbar";
|
|
35
|
-
import { ViewerStateContext } from "../ViewerStateProvider";
|
|
36
35
|
import ChannelUpdater from "./ChannelUpdater";
|
|
37
36
|
import "../../assets/styles/globals.css";
|
|
38
37
|
import "./styles.css";
|
|
@@ -105,31 +104,37 @@ var setIndicatorPositions = function setIndicatorPositions(view3d, panelOpen, ha
|
|
|
105
104
|
view3d.setScaleBarPosition(scaleBarX, scaleBarY);
|
|
106
105
|
};
|
|
107
106
|
var App = function App(props) {
|
|
108
|
-
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;
|
|
109
108
|
props = _objectSpread(_objectSpread({}, defaultProps), props);
|
|
110
109
|
|
|
111
110
|
// State management /////////////////////////////////////////////////////////
|
|
112
|
-
var
|
|
113
|
-
var
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
+
}
|
|
131
135
|
}
|
|
132
|
-
|
|
136
|
+
prevViewerSettingsPropsRef.current = props.viewerSettings;
|
|
137
|
+
}
|
|
133
138
|
var view3d = useConstructor(function () {
|
|
134
139
|
return new View3d();
|
|
135
140
|
});
|
|
@@ -155,11 +160,11 @@ var App = function App(props) {
|
|
|
155
160
|
}, [view3d, showError]);
|
|
156
161
|
var imageUrlRef = useRef("");
|
|
157
162
|
var scenesRef = useRef([]);
|
|
158
|
-
var
|
|
159
|
-
imageUrl =
|
|
160
|
-
parentImageUrl =
|
|
161
|
-
rawData =
|
|
162
|
-
rawDims =
|
|
163
|
+
var _props = props,
|
|
164
|
+
imageUrl = _props.imageUrl,
|
|
165
|
+
parentImageUrl = _props.parentImageUrl,
|
|
166
|
+
rawData = _props.rawData,
|
|
167
|
+
rawDims = _props.rawDims;
|
|
163
168
|
var scenes = useMemo(function () {
|
|
164
169
|
if (rawData && rawDims) {
|
|
165
170
|
return [{
|
|
@@ -180,21 +185,58 @@ var App = function App(props) {
|
|
|
180
185
|
return result;
|
|
181
186
|
}
|
|
182
187
|
}, [imageUrl, parentImageUrl, rawData, rawDims, imageType]);
|
|
183
|
-
var maskChannelName = (
|
|
188
|
+
var maskChannelName = (_props$viewerChannelS = props.viewerChannelSettings) === null || _props$viewerChannelS === void 0 ? void 0 : _props$viewerChannelS.maskChannelName;
|
|
184
189
|
|
|
185
190
|
// we need to keep track of channel ranges for remapping control points
|
|
186
191
|
var channelRangesRef = useRef([]);
|
|
192
|
+
var removePreviousImage = useRef(undefined);
|
|
193
|
+
var _props2 = props,
|
|
194
|
+
onImageTitleChange = _props2.onImageTitleChange;
|
|
187
195
|
var onCreateImage = useCallback(function (newImage) {
|
|
196
|
+
var _removePreviousImage$, _newImage$imageInfo$c;
|
|
197
|
+
(_removePreviousImage$ = removePreviousImage.current) === null || _removePreviousImage$ === void 0 || _removePreviousImage$.call(removePreviousImage);
|
|
188
198
|
if (newImage === null) {
|
|
189
199
|
return;
|
|
190
200
|
}
|
|
191
|
-
|
|
192
|
-
|
|
201
|
+
var _useViewerState$getSt = useViewerState.getState(),
|
|
202
|
+
channelState = _useViewerState$getSt.channelSettings;
|
|
203
|
+
var channelNames = newImage.channelNames;
|
|
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;
|
|
211
|
+
|
|
212
|
+
// If the image has channel color metadata, apply those colors now
|
|
213
|
+
var channelColorMeta = (_newImage$imageInfo$c = newImage.imageInfo.channelColors) === null || _newImage$imageInfo$c === void 0 ? void 0 : _newImage$imageInfo$c.map(function (color, index) {
|
|
214
|
+
// Filter out channels that have colors in `viewerChannelSettings`
|
|
215
|
+
if (viewerChannelSettings === undefined) {
|
|
216
|
+
return color;
|
|
217
|
+
}
|
|
218
|
+
var settings = findFirstChannelMatch(channelNames[index], index, viewerChannelSettings);
|
|
219
|
+
if ((settings === null || settings === void 0 ? void 0 : settings.color) !== undefined) {
|
|
220
|
+
return undefined;
|
|
221
|
+
} else {
|
|
222
|
+
return color;
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
if (Array.isArray(channelColorMeta)) {
|
|
226
|
+
channelColorMeta.forEach(function (color, index) {
|
|
227
|
+
if (Array.isArray(color) && index < channelNames.length) {
|
|
228
|
+
changeChannelSetting(index, {
|
|
229
|
+
color: color
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
}
|
|
193
234
|
view3d.addVolume(newImage, {
|
|
194
235
|
// Immediately passing down channel parameters isn't strictly necessary, but keeps things looking consistent on load
|
|
195
|
-
channels: newImage.channelNames.map(function (name) {
|
|
236
|
+
channels: newImage.channelNames.map(function (name, index) {
|
|
237
|
+
var _channelColorMeta$ind;
|
|
196
238
|
// TODO do we really need to be searching by name here?
|
|
197
|
-
var ch =
|
|
239
|
+
var ch = channelState.find(function (channel) {
|
|
198
240
|
return channel.name === name;
|
|
199
241
|
});
|
|
200
242
|
if (!ch) {
|
|
@@ -205,58 +247,76 @@ var App = function App(props) {
|
|
|
205
247
|
isosurfaceEnabled: ch.isosurfaceEnabled,
|
|
206
248
|
isovalue: ch.isovalue,
|
|
207
249
|
isosurfaceOpacity: ch.opacity,
|
|
208
|
-
color: ch.color
|
|
250
|
+
color: (_channelColorMeta$ind = channelColorMeta === null || channelColorMeta === void 0 ? void 0 : channelColorMeta[index]) !== null && _channelColorMeta$ind !== void 0 ? _channelColorMeta$ind : ch.color
|
|
209
251
|
};
|
|
210
252
|
})
|
|
211
253
|
});
|
|
212
|
-
onImageTitleChange === null || onImageTitleChange === void 0 || onImageTitleChange(newImage.imageInfo.imageInfo.name);
|
|
213
254
|
view3d.updateActiveChannels(newImage);
|
|
214
|
-
|
|
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]);
|
|
215
272
|
var onChannelLoaded = useCallback(function (image, channelIndex, isInitialLoad) {
|
|
216
|
-
// TODO this was once a search by name - is that still necessary or will
|
|
217
|
-
|
|
218
|
-
var
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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;
|
|
222
281
|
var thisChannel = image.getChannel(channelIndex);
|
|
223
|
-
var noLut = !
|
|
224
|
-
|
|
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;
|
|
225
290
|
// This channel needs its LUT initialized
|
|
226
|
-
var _initializeLut = initializeLut(image, channelIndex,
|
|
291
|
+
var _initializeLut = initializeLut(image, channelIndex, viewerChannelSettings),
|
|
227
292
|
ramp = _initializeLut.ramp,
|
|
228
293
|
controlPoints = _initializeLut.controlPoints;
|
|
229
|
-
|
|
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;
|
|
230
300
|
changeChannelSetting(channelIndex, {
|
|
231
301
|
controlPoints: controlPoints,
|
|
232
302
|
ramp: controlPointsToRamp(ramp),
|
|
233
303
|
// set the default range of the transfer function editor to cover the full range of the data type
|
|
234
|
-
plotMin:
|
|
235
|
-
plotMax:
|
|
304
|
+
plotMin: thisChannel.rawMin,
|
|
305
|
+
plotMax: thisChannel.rawMax,
|
|
306
|
+
isovalue: isovalue
|
|
236
307
|
});
|
|
237
308
|
} else {
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
} else {
|
|
250
|
-
// ramp was just automatically remapped - update in state
|
|
251
|
-
var _ramp = controlPointsToRamp(thisChannel.lut.controlPoints);
|
|
252
|
-
// now manually remap control points using the channel's old range
|
|
253
|
-
var _controlPoints = thisChannelSettings.controlPoints;
|
|
254
|
-
var remappedControlPoints = remapControlPointsForChannel(_controlPoints, oldRange, thisChannel);
|
|
255
|
-
changeChannelSetting(channelIndex, {
|
|
256
|
-
controlPoints: remappedControlPoints,
|
|
257
|
-
ramp: _ramp
|
|
258
|
-
});
|
|
259
|
-
}
|
|
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
|
+
});
|
|
260
320
|
}
|
|
261
321
|
|
|
262
322
|
// save the channel's new range for remapping next time
|
|
@@ -269,14 +329,16 @@ var App = function App(props) {
|
|
|
269
329
|
if (image.isLoaded()) {
|
|
270
330
|
view3d.updateActiveChannels(image);
|
|
271
331
|
}
|
|
272
|
-
}, [view3d,
|
|
332
|
+
}, [view3d, changeChannelSetting, maskChannelName, props.viewerChannelSettings]);
|
|
273
333
|
var onError = useCallback(function (error) {
|
|
274
334
|
showError(error);
|
|
275
335
|
onImageTitleChange === null || onImageTitleChange === void 0 || onImageTitleChange(undefined);
|
|
276
336
|
}, [showError, onImageTitleChange]);
|
|
277
337
|
var volume = useVolume(scenes, {
|
|
338
|
+
viewerChannelSettings: props.viewerChannelSettings,
|
|
278
339
|
onCreateImage: onCreateImage,
|
|
279
340
|
onChannelLoaded: onChannelLoaded,
|
|
341
|
+
onChangeScene: onChangeScene,
|
|
280
342
|
onError: onError,
|
|
281
343
|
maskChannelName: maskChannelName
|
|
282
344
|
});
|
|
@@ -298,26 +360,25 @@ var App = function App(props) {
|
|
|
298
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;
|
|
299
361
|
|
|
300
362
|
// const [channelGroupedByType, setChannelGroupedByType] = useState<ChannelGrouping>({});
|
|
301
|
-
var
|
|
363
|
+
var _useState3 = useState(function () {
|
|
302
364
|
return window.innerWidth < CONTROL_PANEL_CLOSE_WIDTH;
|
|
303
365
|
}),
|
|
304
|
-
_useState2 = _slicedToArray(_useState, 2),
|
|
305
|
-
controlPanelClosed = _useState2[0],
|
|
306
|
-
setControlPanelClosed = _useState2[1];
|
|
307
|
-
// Only allow auto-close once while the screen is too narrow.
|
|
308
|
-
var _useState3 = useState(false),
|
|
309
366
|
_useState4 = _slicedToArray(_useState3, 2),
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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),
|
|
313
371
|
_useState6 = _slicedToArray(_useState5, 2),
|
|
314
|
-
|
|
315
|
-
|
|
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];
|
|
316
378
|
var clippingPanelOpenTimeout = useRef(0);
|
|
317
379
|
|
|
318
380
|
// Imperative callbacks /////////////////////////////////////////////////////
|
|
319
381
|
|
|
320
|
-
var viewerSettings = viewerState.current;
|
|
321
382
|
var saveIsosurface = useCallback(function (channelIndex, type) {
|
|
322
383
|
if (image) view3d.saveChannelIsosurface(image, channelIndex, type);
|
|
323
384
|
}, [image, view3d]);
|
|
@@ -329,21 +390,24 @@ var App = function App(props) {
|
|
|
329
390
|
anchor.click();
|
|
330
391
|
});
|
|
331
392
|
}, [view3d]);
|
|
332
|
-
var
|
|
393
|
+
var _props3 = props,
|
|
394
|
+
metadataFormatter = _props3.metadataFormatter;
|
|
395
|
+
var metadata = useMemo(function () {
|
|
333
396
|
var imageMetadata = image === null || image === void 0 ? void 0 : image.imageMetadata;
|
|
334
397
|
if (imageMetadata && metadataFormatter) {
|
|
335
398
|
imageMetadata = metadataFormatter(imageMetadata);
|
|
336
399
|
}
|
|
400
|
+
var propsMetadata = props.metadata;
|
|
337
401
|
var sceneMeta;
|
|
338
|
-
if (Array.isArray(
|
|
402
|
+
if (Array.isArray(propsMetadata)) {
|
|
339
403
|
// If metadata is an array, try to index it by scene
|
|
340
|
-
if (
|
|
341
|
-
sceneMeta =
|
|
404
|
+
if (propsMetadata.length >= numScenes && loadedScene !== undefined) {
|
|
405
|
+
sceneMeta = propsMetadata[loadedScene];
|
|
342
406
|
} else {
|
|
343
|
-
sceneMeta =
|
|
407
|
+
sceneMeta = propsMetadata[0];
|
|
344
408
|
}
|
|
345
409
|
} else {
|
|
346
|
-
sceneMeta =
|
|
410
|
+
sceneMeta = propsMetadata;
|
|
347
411
|
}
|
|
348
412
|
if (imageMetadata && Object.keys(imageMetadata).length > 0) {
|
|
349
413
|
return _objectSpread({
|
|
@@ -353,11 +417,11 @@ var App = function App(props) {
|
|
|
353
417
|
var _sceneMeta;
|
|
354
418
|
return (_sceneMeta = sceneMeta) !== null && _sceneMeta !== void 0 ? _sceneMeta : {};
|
|
355
419
|
}
|
|
356
|
-
}, [metadata, metadataFormatter, image,
|
|
420
|
+
}, [props.metadata, metadataFormatter, image, loadedScene, numScenes]);
|
|
357
421
|
useEffect(function () {
|
|
358
422
|
var hasTime = numTimesteps > 1;
|
|
359
423
|
var hasScenes = numScenes > 1;
|
|
360
|
-
var mode3d =
|
|
424
|
+
var mode3d = viewMode === ViewMode.threeD;
|
|
361
425
|
setIndicatorPositions(view3d, clippingPanelOpen, hasTime, hasScenes, mode3d);
|
|
362
426
|
|
|
363
427
|
// Hide indicators while clipping panel is in motion - otherwise they pop to the right place prematurely
|
|
@@ -369,12 +433,12 @@ var App = function App(props) {
|
|
|
369
433
|
clippingPanelOpenTimeout.current = window.setTimeout(function () {
|
|
370
434
|
view3d.setShowScaleBar(true);
|
|
371
435
|
view3d.setShowTimestepIndicator(true);
|
|
372
|
-
if (
|
|
436
|
+
if (showAxes) {
|
|
373
437
|
view3d.setShowAxis(true);
|
|
374
438
|
}
|
|
375
439
|
}, CLIPPING_PANEL_ANIMATION_DURATION_MS);
|
|
376
440
|
}
|
|
377
|
-
}, [view3d, numTimesteps, numScenes,
|
|
441
|
+
}, [view3d, numTimesteps, numScenes, viewMode, showAxes, clippingPanelOpen]);
|
|
378
442
|
|
|
379
443
|
// Effects //////////////////////////////////////////////////////////////////
|
|
380
444
|
|
|
@@ -396,6 +460,8 @@ var App = function App(props) {
|
|
|
396
460
|
return window.removeEventListener("resize", onResizeDebounced);
|
|
397
461
|
};
|
|
398
462
|
}, [hasAutoClosedControlPanel]);
|
|
463
|
+
var _props4 = props,
|
|
464
|
+
onControlPanelToggle = _props4.onControlPanelToggle;
|
|
399
465
|
useEffect(function () {
|
|
400
466
|
return onControlPanelToggle && onControlPanelToggle(controlPanelClosed);
|
|
401
467
|
}, [controlPanelClosed, onControlPanelToggle]);
|
|
@@ -418,36 +484,17 @@ var App = function App(props) {
|
|
|
418
484
|
};
|
|
419
485
|
|
|
420
486
|
// Effects to imperatively sync `viewerSettings` to `view3d`
|
|
421
|
-
|
|
422
|
-
view3d.setCameraMode(viewerSettings.viewMode);
|
|
423
|
-
view3d.resize(null);
|
|
424
|
-
}, [viewerSettings.viewMode, view3d]);
|
|
425
|
-
useImageEffect(function (_currentImage) {
|
|
426
|
-
if (viewerSettings.cameraState) {
|
|
427
|
-
view3d.setCameraState(viewerSettings.cameraState);
|
|
428
|
-
}
|
|
429
|
-
}, [viewerSettings.cameraState, view3d]);
|
|
430
|
-
useImageEffect(function (_currentImage) {
|
|
431
|
-
return view3d.setAutoRotate(viewerSettings.autorotate);
|
|
432
|
-
}, [viewerSettings.autorotate, view3d]);
|
|
433
|
-
useImageEffect(function (_currentImage) {
|
|
434
|
-
return view3d.setShowAxis(viewerSettings.showAxes);
|
|
435
|
-
}, [viewerSettings.showAxes, view3d]);
|
|
436
|
-
useImageEffect(function (_currentImage) {
|
|
437
|
-
return view3d.setBackgroundColor(colorArrayToFloats(viewerSettings.backgroundColor));
|
|
438
|
-
}, [viewerSettings.backgroundColor, view3d]);
|
|
439
|
-
useImageEffect(function (currentImage) {
|
|
440
|
-
return view3d.setBoundingBoxColor(currentImage, colorArrayToFloats(viewerSettings.boundingBoxColor));
|
|
441
|
-
}, [viewerSettings.boundingBoxColor, view3d]);
|
|
442
|
-
useImageEffect(function (currentImage) {
|
|
443
|
-
return view3d.setShowBoundingBox(currentImage, viewerSettings.showBoundingBox);
|
|
444
|
-
}, [viewerSettings.showBoundingBox, view3d]);
|
|
487
|
+
|
|
445
488
|
useImageEffect(function (image) {
|
|
446
489
|
// Check whether any channels are marked to be reset and apply it.
|
|
447
|
-
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;
|
|
448
495
|
for (var i = 0; i < channelSettings.length; i++) {
|
|
449
|
-
if (
|
|
450
|
-
var _initializeLut2 = initializeLut(image, i,
|
|
496
|
+
if (channelsToReset.includes(i)) {
|
|
497
|
+
var _initializeLut2 = initializeLut(image, i, viewerChannelSettings),
|
|
451
498
|
ramp = _initializeLut2.ramp,
|
|
452
499
|
controlPoints = _initializeLut2.controlPoints;
|
|
453
500
|
changeChannelSetting(i, {
|
|
@@ -457,40 +504,15 @@ var App = function App(props) {
|
|
|
457
504
|
onResetChannel(i);
|
|
458
505
|
}
|
|
459
506
|
}
|
|
460
|
-
}, [changeChannelSetting, channelSettings,
|
|
461
|
-
useImageEffect(function (currentImage) {
|
|
462
|
-
var renderMode = viewerSettings.renderMode;
|
|
463
|
-
view3d.setMaxProjectMode(currentImage, renderMode === RenderMode.maxProject);
|
|
464
|
-
view3d.setVolumeRenderMode(renderMode === RenderMode.pathTrace ? RENDERMODE_PATHTRACE : RENDERMODE_RAYMARCH);
|
|
465
|
-
view3d.updateActiveChannels(currentImage);
|
|
466
|
-
}, [viewerSettings.renderMode, view3d]);
|
|
467
|
-
useImageEffect(function (currentImage) {
|
|
468
|
-
view3d.updateMaskAlpha(currentImage, alphaSliderToImageValue(viewerSettings.maskAlpha));
|
|
469
|
-
view3d.updateActiveChannels(currentImage);
|
|
470
|
-
}, [viewerSettings.maskAlpha, view3d]);
|
|
471
|
-
useImageEffect(function (_currentImage) {
|
|
472
|
-
var brightness = brightnessSliderToImageValue(viewerSettings.brightness);
|
|
473
|
-
view3d.updateExposure(brightness);
|
|
474
|
-
}, [viewerSettings.brightness, view3d]);
|
|
475
|
-
useImageEffect(function (currentImage) {
|
|
476
|
-
var density = densitySliderToImageValue(viewerSettings.density);
|
|
477
|
-
view3d.updateDensity(currentImage, density);
|
|
478
|
-
}, [viewerSettings.density, view3d]);
|
|
479
|
-
useImageEffect(function (currentImage) {
|
|
480
|
-
var imageValues = gammaSliderToImageValues(viewerSettings.levels);
|
|
481
|
-
view3d.setGamma(currentImage, imageValues.min, imageValues.scale, imageValues.max);
|
|
482
|
-
}, [viewerSettings.levels, view3d]);
|
|
507
|
+
}, [changeChannelSetting, channelSettings, props.viewerChannelSettings]);
|
|
483
508
|
|
|
484
509
|
// `time` and `scene` have their own special handlers via `volume`, since they both trigger loads
|
|
485
510
|
useEffect(function () {
|
|
486
|
-
return setTime(view3d,
|
|
487
|
-
}, [view3d,
|
|
511
|
+
return setTime(view3d, time);
|
|
512
|
+
}, [view3d, time, setTime]);
|
|
488
513
|
useEffect(function () {
|
|
489
|
-
return setScene(
|
|
490
|
-
}, [
|
|
491
|
-
useImageEffect(function (currentImage) {
|
|
492
|
-
return view3d.setInterpolationEnabled(currentImage, viewerSettings.interpolationEnabled);
|
|
493
|
-
}, [viewerSettings.interpolationEnabled, view3d]);
|
|
514
|
+
return setScene(scene);
|
|
515
|
+
}, [scene, setScene]);
|
|
494
516
|
useImageEffect(function (currentImage) {
|
|
495
517
|
var _props$transform;
|
|
496
518
|
return view3d.setVolumeTranslation(currentImage, ((_props$transform = props.transform) === null || _props$transform === void 0 ? void 0 : _props$transform.translation) || [0, 0, 0]);
|
|
@@ -499,43 +521,6 @@ var App = function App(props) {
|
|
|
499
521
|
var _props$transform3;
|
|
500
522
|
return view3d.setVolumeRotation(currentImage, ((_props$transform3 = props.transform) === null || _props$transform3 === void 0 ? void 0 : _props$transform3.rotation) || [0, 0, 0]);
|
|
501
523
|
}, [(_props$transform4 = props.transform) === null || _props$transform4 === void 0 ? void 0 : _props$transform4.rotation, view3d]);
|
|
502
|
-
var usePerAxisClippingUpdater = function usePerAxisClippingUpdater(axis, _ref, slice, viewMode) {
|
|
503
|
-
var _ref2 = _slicedToArray(_ref, 2),
|
|
504
|
-
minval = _ref2[0],
|
|
505
|
-
maxval = _ref2[1];
|
|
506
|
-
useImageEffect(
|
|
507
|
-
// Logic to determine axis clipping range, for each of x,y,z,3d slider:
|
|
508
|
-
// if slider was same as active axis view mode: [viewerSettings.slice[axis], viewerSettings.slice[axis] + 1.0/volumeSize[axis]]
|
|
509
|
-
// if in 3d mode: viewerSettings.region[axis]
|
|
510
|
-
// else: [0,1]
|
|
511
|
-
function (currentImage) {
|
|
512
|
-
var isOrthoAxis = false;
|
|
513
|
-
var axismin = 0.0;
|
|
514
|
-
var axismax = 1.0;
|
|
515
|
-
if (viewMode === ViewMode.threeD) {
|
|
516
|
-
axismin = minval;
|
|
517
|
-
axismax = maxval;
|
|
518
|
-
isOrthoAxis = false;
|
|
519
|
-
} else {
|
|
520
|
-
isOrthoAxis = activeAxisMap[viewMode] === axis;
|
|
521
|
-
var oneSlice = 1 / currentImage.imageInfo.volumeSize[axis];
|
|
522
|
-
axismin = isOrthoAxis ? slice : 0.0;
|
|
523
|
-
axismax = isOrthoAxis ? slice + oneSlice : 1.0;
|
|
524
|
-
if (axis === "z" && viewMode === ViewMode.xy) {
|
|
525
|
-
view3d.setZSlice(currentImage, Math.floor(slice * currentImage.imageInfo.volumeSize.z));
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
// view3d wants the coordinates in the -0.5 to 0.5 range
|
|
529
|
-
view3d.setAxisClip(currentImage, axis, axismin - 0.5, axismax - 0.5, isOrthoAxis);
|
|
530
|
-
view3d.setCameraMode(viewMode);
|
|
531
|
-
// TODO under some circumstances, this effect will trigger a load. Ideally, this would be reflected in the load
|
|
532
|
-
// state managed by `useVolume`. This is complicated by the fact that the relevant methods (`setAxisClip` and
|
|
533
|
-
// `setZSlice`) don't provide a channel load callback like other load-triggering methods (e.g. `setTime`).
|
|
534
|
-
}, [axis, minval, maxval, slice, viewMode]);
|
|
535
|
-
};
|
|
536
|
-
usePerAxisClippingUpdater("x", viewerSettings.region.x, viewerSettings.slice.x, viewMode);
|
|
537
|
-
usePerAxisClippingUpdater("y", viewerSettings.region.y, viewerSettings.slice.y, viewMode);
|
|
538
|
-
usePerAxisClippingUpdater("z", viewerSettings.region.z, viewerSettings.slice.z, viewMode);
|
|
539
524
|
|
|
540
525
|
// Rendering ////////////////////////////////////////////////////////////////
|
|
541
526
|
|
|
@@ -553,10 +538,10 @@ var App = function App(props) {
|
|
|
553
538
|
style: {
|
|
554
539
|
height: props.appHeight
|
|
555
540
|
}
|
|
556
|
-
}, channelSettings.map(function (
|
|
541
|
+
}, channelSettings.map(function (_ref, index) {
|
|
542
|
+
var name = _ref.name;
|
|
557
543
|
return /*#__PURE__*/React.createElement(ChannelUpdater, {
|
|
558
|
-
key: "".concat(index, "_").concat(
|
|
559
|
-
channelState: channelState,
|
|
544
|
+
key: "".concat(index, "_").concat(name),
|
|
560
545
|
index: index,
|
|
561
546
|
view3d: view3d,
|
|
562
547
|
image: image,
|
|
@@ -586,7 +571,7 @@ var App = function App(props) {
|
|
|
586
571
|
saveIsosurface: saveIsosurface,
|
|
587
572
|
onApplyColorPresets: applyColorPresets,
|
|
588
573
|
viewerChannelSettings: props.viewerChannelSettings,
|
|
589
|
-
|
|
574
|
+
metadata: metadata
|
|
590
575
|
})), /*#__PURE__*/React.createElement(Layout, {
|
|
591
576
|
className: "cell-viewer-wrapper",
|
|
592
577
|
style: {
|
|
@@ -600,6 +585,7 @@ var App = function App(props) {
|
|
|
600
585
|
canPathTrace: view3d ? view3d.hasWebGL2() : false,
|
|
601
586
|
resetCamera: resetCamera,
|
|
602
587
|
downloadScreenshot: saveScreenshot,
|
|
588
|
+
resetToSavedViewerState: resetToSavedViewerState,
|
|
603
589
|
visibleControls: visibleControls
|
|
604
590
|
}), /*#__PURE__*/React.createElement(CellViewerCanvasWrapper, {
|
|
605
591
|
view3d: view3d,
|