@aics/vole-app 3.2.3 → 3.3.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.
Files changed (36) hide show
  1. package/LICENSE +21 -25
  2. package/es/aics-image-viewer/components/App/index.js +18 -12
  3. package/es/aics-image-viewer/components/AxisClipSliders/index.js +2 -1
  4. package/es/aics-image-viewer/components/ChannelsWidget.js +2 -2
  5. package/es/aics-image-viewer/components/ControlPanel/index.js +15 -11
  6. package/es/aics-image-viewer/components/ControlPanel/styles.css +5 -5
  7. package/es/aics-image-viewer/components/ErrorAlert/index.js +102 -65
  8. package/es/aics-image-viewer/components/ErrorAlert/styles.css +40 -7
  9. package/es/aics-image-viewer/components/StyleProvider/index.js +65 -27
  10. package/es/aics-image-viewer/components/TfEditor/index.js +8 -1
  11. package/es/aics-image-viewer/components/Toolbar/index.js +65 -7
  12. package/es/aics-image-viewer/components/Toolbar/styles.css +22 -110
  13. package/es/aics-image-viewer/components/shared/ControlPanelRow/styles.css +1 -1
  14. package/es/aics-image-viewer/components/useVolume.js +45 -40
  15. package/es/aics-image-viewer/shared/constants.js +3 -1
  16. package/es/aics-image-viewer/shared/utils/playControls.js +12 -1
  17. package/es/aics-image-viewer/shared/utils/sceneStore.js +26 -7
  18. package/es/aics-image-viewer/shared/utils/test/urlParsing.test.js +10 -2
  19. package/es/aics-image-viewer/shared/utils/urlParsing.js +17 -3
  20. package/es/aics-image-viewer/shared/utils/viewerChannelSettings.js +3 -4
  21. package/es/aics-image-viewer/state/store.js +24 -6
  22. package/es/aics-image-viewer/state/subscribers.js +22 -1
  23. package/es/aics-image-viewer/state/test/reset.test.js +3 -1
  24. package/package.json +5 -5
  25. package/type-declarations/aics-image-viewer/components/App/types.d.ts +2 -2
  26. package/type-declarations/aics-image-viewer/components/ControlPanel/index.d.ts +4 -5
  27. package/type-declarations/aics-image-viewer/components/ErrorAlert/index.d.ts +8 -5
  28. package/type-declarations/aics-image-viewer/components/Toolbar/index.d.ts +4 -0
  29. package/type-declarations/aics-image-viewer/components/useVolume.d.ts +3 -3
  30. package/type-declarations/aics-image-viewer/shared/constants.d.ts +1 -1
  31. package/type-declarations/aics-image-viewer/shared/utils/playControls.d.ts +1 -0
  32. package/type-declarations/aics-image-viewer/shared/utils/sceneStore.d.ts +3 -2
  33. package/type-declarations/aics-image-viewer/shared/utils/urlParsing.d.ts +7 -1
  34. package/type-declarations/aics-image-viewer/state/store.d.ts +2 -0
  35. package/type-declarations/aics-image-viewer/state/types.d.ts +2 -0
  36. package/LICENSE.txt +0 -26
@@ -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, getDefaultChannelColor, getDefaultViewerChannelSettings, QUEUE_MAX_LOW_PRIORITY_SIZE, QUEUE_MAX_SIZE } from "../shared/constants";
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
- useEffect(function () {
61
- callbackRef.current = callback;
62
- }, [callback]);
63
- return callbackRef;
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 replaceAllChannelSettings = useViewerState(select("replaceAllChannelSettings"));
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);
@@ -107,6 +110,9 @@ var useVolume = function useVolume(scenePaths, options) {
107
110
  setPlayingAxis(axis);
108
111
  // prioritize prefetching along the playing axis
109
112
  sceneLoader.setPrefetchPriority(axis ? [AXIS_TO_LOADER_PRIORITY[axis]] : []);
113
+ sceneLoader.updateFetchOptions({
114
+ onlyPriorityDirections: isPlaying
115
+ });
110
116
  // sync multichannel loading so we don't show loaded channels one at a time
111
117
  sceneLoader.syncMultichannelLoading(isPlaying);
112
118
  if (image) {
@@ -173,9 +179,8 @@ var useVolume = function useVolume(scenePaths, options) {
173
179
  }));
174
180
  }, [channelVersionsRef, setChannelVersions]);
175
181
  var onError = useCallback(function (e) {
176
- var _onErrorRef$current;
177
182
  setLoadThrewError(true);
178
- (_onErrorRef$current = onErrorRef.current) === null || _onErrorRef$current === void 0 || _onErrorRef$current.call(onErrorRef, e);
183
+ onErrorRef(e);
179
184
  throw e;
180
185
  }, [onErrorRef]);
181
186
 
@@ -185,10 +190,9 @@ var useVolume = function useVolume(scenePaths, options) {
185
190
  channelGroupedByType = _useState10[0],
186
191
  setChannelGroupedByType = _useState10[1];
187
192
  var onChannelDataLoaded = useCallback(function (aimg, channelIndex) {
188
- var _onChannelLoadedRef$c;
189
193
  // let the hook caller know that this channel has loaded
190
194
  var isInitialLoad = channelVersionsRef.current[channelIndex] === CHANNEL_INITIAL_LOAD;
191
- (_onChannelLoadedRef$c = onChannelLoadedRef.current) === null || _onChannelLoadedRef$c === void 0 || _onChannelLoadedRef$c.call(onChannelLoadedRef, aimg, channelIndex, isInitialLoad);
195
+ onChannelLoadedRef(aimg, channelIndex, isInitialLoad);
192
196
 
193
197
  // set this channel as loaded
194
198
  var newVersions = channelVersionsRef.current.slice();
@@ -200,34 +204,23 @@ var useVolume = function useVolume(scenePaths, options) {
200
204
  playControls.onImageLoaded();
201
205
  }
202
206
  }, [channelVersionsRef, onChannelLoadedRef, playControls, setChannelVersions]);
207
+ var setChannelStateForNewImage = useCallback(function (channelNames) {
208
+ var _useViewerState$getSt = useViewerState.getState(),
209
+ useDefaultViewerChannelSettings = _useViewerState$getSt.useDefaultViewerChannelSettings;
210
+ var viewerChannelSettings = useDefaultViewerChannelSettings ? getDefaultViewerChannelSettings() : options === null || options === void 0 ? void 0 : options.viewerChannelSettings;
211
+ var grouping = makeChannelIndexGrouping(channelNames, viewerChannelSettings);
212
+ setChannelGroupedByType(grouping);
213
+ return initChannelSettings(channelNames, viewerChannelSettings);
214
+ }, [initChannelSettings, options === null || options === void 0 ? void 0 : options.viewerChannelSettings]);
203
215
 
204
216
  // effect to start the initial load of the image
205
217
  useEffect(function () {
206
- var channelSettings = useViewerState.getState().channelSettings;
207
218
  setChannelVersions(new Array(channelVersionsRef.current.length).fill(CHANNEL_INITIAL_LOAD));
208
219
  setLoadThrewError(false);
209
220
  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
221
  var openImage = /*#__PURE__*/function () {
228
222
  var _ref3 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
229
- var _onCreateImageRef$cur;
230
- var scene, time, loadSpec, aimg, channelNames, newChannelSettings, requiredLoadSpec, requiredChannelsToLoad, _useViewerState$getSt2, useDefaultViewerChannelSettings, viewerChannelSettings, maskChannelName, maskChannelIndex, viewMode, slice, onCreateScene;
223
+ var scene, time, loadSpec, aimg, channelNames, newChannelSettings, requiredLoadSpec, requiredChannelsToLoad, _useViewerState$getSt2, useDefaultViewerChannelSettings, viewerChannelSettings, maskChannelName, maskChannelIndex, viewMode, slice;
231
224
  return _regeneratorRuntime().wrap(function _callee$(_context) {
232
225
  while (1) switch (_context.prev = _context.next) {
233
226
  case 0:
@@ -243,7 +236,7 @@ var useVolume = function useVolume(scenePaths, options) {
243
236
  newChannelSettings = setChannelStateForNewImage(channelNames);
244
237
  setChannelVersions(new Array(channelNames.length).fill(CHANNEL_INITIAL_LOAD));
245
238
  setImage(aimg);
246
- (_onCreateImageRef$cur = onCreateImageRef.current) === null || _onCreateImageRef$cur === void 0 || _onCreateImageRef$cur.call(onCreateImageRef, aimg);
239
+ onCreateImageRef(aimg);
247
240
  playControls.stepAxis = function (axis) {
248
241
  var time = useViewerState.getState().time;
249
242
  var slice = useViewerState.getState().slice;
@@ -289,11 +282,10 @@ var useVolume = function useVolume(scenePaths, options) {
289
282
 
290
283
  // initiate loading only after setting up new channel settings,
291
284
  // in case the loader callback fires before the state is set
292
- onCreateScene = onChangeSceneRef.current;
293
285
  sceneLoader.loadScene(scene, aimg, requiredLoadSpec, {
294
- onCreateScene: onCreateScene
286
+ onCreateScene: onChangeSceneRef
295
287
  })["catch"](onError);
296
- case 27:
288
+ case 26:
297
289
  case "end":
298
290
  return _context.stop();
299
291
  }
@@ -304,7 +296,7 @@ var useVolume = function useVolume(scenePaths, options) {
304
296
  };
305
297
  }();
306
298
  openImage();
307
- }, [sceneLoader, onError, onCreateImageRef, onChangeSceneRef, onChannelLoadedRef, channelVersionsRef, setChannelVersions, playControls, setIsLoading, onChannelDataLoaded, changeViewerSetting, replaceAllChannelSettings, options === null || options === void 0 ? void 0 : options.viewerChannelSettings]);
299
+ }, [sceneLoader, onError, onCreateImageRef, onChangeSceneRef, onChannelLoadedRef, channelVersionsRef, setChannelVersions, playControls, setIsLoading, onChannelDataLoaded, changeViewerSetting, initChannelSettings, setChannelStateForNewImage, options === null || options === void 0 ? void 0 : options.viewerChannelSettings]);
308
300
  // of the above dependencies, we expect only `sceneLoader` to change.
309
301
 
310
302
  var setTime = useCallback(function (view3d, time) {
@@ -315,13 +307,26 @@ var useVolume = function useVolume(scenePaths, options) {
315
307
  }, [image, onError, setIsLoading, inInitialLoadRef]);
316
308
  var setScene = useCallback(function (scene) {
317
309
  if (image && !inInitialLoadRef.current) {
318
- var onCreateScene = onChangeSceneRef.current;
310
+ var onCreateScene = function onCreateScene(volume, sceneIndex, loadSpec) {
311
+ setChannelStateForNewImage(volume.imageInfo.channelNames);
312
+ volume.updateChannelCount();
313
+ var prevChannelVersions = channelVersionsRef.current;
314
+ var newChannelVersions;
315
+ var addedChannelCount = volume.imageInfo.numChannels - prevChannelVersions.length;
316
+ if (addedChannelCount > 0) {
317
+ newChannelVersions = prevChannelVersions.concat(Array(addedChannelCount).fill(CHANNEL_INITIAL_LOAD));
318
+ } else {
319
+ newChannelVersions = prevChannelVersions.slice(0, volume.imageInfo.numChannels);
320
+ }
321
+ setChannelVersions(newChannelVersions);
322
+ onChangeSceneRef(volume, sceneIndex, loadSpec);
323
+ };
319
324
  sceneLoader.loadScene(scene, image, undefined, {
320
325
  onCreateScene: onCreateScene
321
326
  })["catch"](onError);
322
327
  setIsLoading(LoadType.SCENE);
323
328
  }
324
- }, [image, onError, sceneLoader, setIsLoading, inInitialLoadRef, onChangeSceneRef]);
329
+ }, [image, sceneLoader, onError, setIsLoading, setChannelStateForNewImage, channelVersionsRef, setChannelVersions, onChangeSceneRef]);
325
330
  return useMemo(function () {
326
331
  return {
327
332
  image: image,
@@ -31,7 +31,7 @@ export var TFEDITOR_DEFAULT_COLOR = [255, 255, 255];
31
31
  export var TFEDITOR_MAX_BIN = 255;
32
32
  export var CACHE_MAX_SIZE = 1000000000;
33
33
  export var QUEUE_MAX_SIZE = 10;
34
- export var QUEUE_MAX_LOW_PRIORITY_SIZE = 4;
34
+ export var QUEUE_MAX_LOW_PRIORITY_SIZE = 6;
35
35
 
36
36
  /** Maps an axis the user can "play" through to the direction to prefetch while playing that axis */
37
37
  export var AXIS_TO_LOADER_PRIORITY = {
@@ -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
@@ -13,6 +13,7 @@ var PlayControls = /*#__PURE__*/function () {
13
13
  _defineProperty(this, "playWaitingForLoad", false);
14
14
  _defineProperty(this, "playHolding", false);
15
15
  _defineProperty(this, "playTimeoutId", 0);
16
+ _defineProperty(this, "lastStepTime", 0);
16
17
  }
17
18
  return _createClass(PlayControls, [{
18
19
  key: "setPlayingAxis",
@@ -28,11 +29,18 @@ var PlayControls = /*#__PURE__*/function () {
28
29
  if (!this.playingAxis || this.playHolding || !this.stepAxis) {
29
30
  return;
30
31
  }
31
- // If the volume is not loaded, wait for it to load before continuing
32
32
  if (!((_this$getVolumeIsLoad = this.getVolumeIsLoaded) !== null && _this$getVolumeIsLoad !== void 0 && _this$getVolumeIsLoad.call(this))) {
33
33
  this.playWaitingForLoad = true;
34
34
  return;
35
35
  }
36
+
37
+ // Enforce minimum interval between frame *presentations* (not requests).
38
+ // lastStepTime is set in onImageLoaded when a frame's data arrives.
39
+ var delay = PLAY_STEP_INTERVAL_MS - (performance.now() - this.lastStepTime);
40
+ if (delay > 0) {
41
+ this.playTimeoutId = window.setTimeout(this.playStep.bind(this), delay);
42
+ return;
43
+ }
36
44
  this.stepAxis(this.playingAxis);
37
45
  this.playTimeoutId = window.setTimeout(this.playStep.bind(this), PLAY_STEP_INTERVAL_MS);
38
46
  }
@@ -41,6 +49,9 @@ var PlayControls = /*#__PURE__*/function () {
41
49
  }, {
42
50
  key: "onImageLoaded",
43
51
  value: function onImageLoaded() {
52
+ // Record when the frame was presented, so scheduleNextStep enforces
53
+ // PLAY_STEP_INTERVAL_MS between presentations (not between requests).
54
+ this.lastStepTime = performance.now();
44
55
  if (this.playWaitingForLoad) {
45
56
  this.playWaitingForLoad = false;
46
57
  this.playStep();
@@ -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
- image.imageInfo.imageInfo = _context2.sent.imageInfo;
95
- options === null || options === void 0 || (_options$onCreateScen = options.onCreateScene) === null || _options$onCreateScen === void 0 || _options$onCreateScen.call(options, image, scene);
96
- loader.loadVolumeData(image, spec, options === null || options === void 0 ? void 0 : options.onChannelLoaded);
97
- case 10:
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
  }
@@ -147,6 +158,14 @@ var SceneStore = /*#__PURE__*/function () {
147
158
  currentLoader.setPrefetchPriority(priority);
148
159
  }
149
160
  }
161
+ }, {
162
+ key: "updateFetchOptions",
163
+ value: function updateFetchOptions(fetchOptions) {
164
+ var currentLoader = this.loaders[this.currentScene];
165
+ if (currentLoader) {
166
+ currentLoader.updateFetchOptions(fetchOptions);
167
+ }
168
+ }
150
169
  }]);
151
170
  }();
152
171
  export { SceneStore as default };
@@ -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);
@@ -87,12 +87,11 @@ export function findFirstChannelMatch(channel, channelIndex, settings) {
87
87
  }
88
88
  export function getDisplayName(name, index, settings) {
89
89
  if (settings) {
90
+ var _c$name;
90
91
  var c = findFirstChannelMatch(name, index, settings);
91
- if (c) {
92
- return c.name || name;
93
- }
92
+ return (_c$name = c === null || c === void 0 ? void 0 : c.name) !== null && _c$name !== void 0 ? _c$name : name;
94
93
  }
95
- return name;
94
+ return name !== null && name !== void 0 ? name : index.toString();
96
95
  }
97
96
  export function makeChannelIndexGrouping(channels, settings) {
98
97
  if (!channels) {
@@ -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 > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
14
- etc[_key - 1] = arguments[_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.2.3",
3
+ "version": "3.3.1",
4
4
  "description": "web view of cell volume images",
5
5
  "main": "es/index.js",
6
6
  "module": "es/index.js",
@@ -25,6 +25,7 @@
25
25
  "gh-build-nightly": "webpack --config webpack.dev.js --env env=production basename=/vole-app/",
26
26
  "gh-build-release": "webpack --config webpack.dev.js --env env=production basename=/website-3d-cell-viewer-release/",
27
27
  "s3-build": "webpack --config webpack.dev.js --env env=production",
28
+ "release-build": "webpack --config webpack.dev.js --env env=production",
28
29
  "docker-build": "webpack --config webpack.common.js --env env=production",
29
30
  "dev": "webpack --config webpack.dev.js --env env=dev",
30
31
  "lint": "eslint --config ./.eslintrc --ignore-path ./.eslintignore --ext .jsx --ext .js --ext .ts --ext .tsx ./",
@@ -43,9 +44,9 @@
43
44
  "checks": "npm run lint && npm run typeCheck && npm run test"
44
45
  },
45
46
  "author": "Megan Riel-Mehan",
46
- "license": "ISC",
47
+ "license": "BSD-3-Clause",
47
48
  "dependencies": {
48
- "@aics/vole-core": "^4.6.4",
49
+ "@aics/vole-core": "^4.9.1",
49
50
  "@ant-design/icons": "^5.2.5",
50
51
  "@fortawesome/fontawesome-svg-core": "^6.5.2",
51
52
  "@fortawesome/free-solid-svg-icons": "^6.5.2",
@@ -65,8 +66,7 @@
65
66
  "peerDependencies": {
66
67
  "antd": "^5.16.2",
67
68
  "react": "18.x",
68
- "react-dom": "18.x",
69
- "three": "^0.171.0"
69
+ "react-dom": "18.x"
70
70
  },
71
71
  "devDependencies": {
72
72
  "@babel/cli": "^7.14.5",
@@ -5,7 +5,7 @@ import type { ViewerChannelSettings } from "../../shared/utils/viewerChannelSett
5
5
  import type { ViewerState } from "../../state/types";
6
6
  /** `typeof useEffect`, but the effect handler takes a `Volume` as an argument */
7
7
  export type UseImageEffectType = (effect: (image: Volume) => void | (() => void), deps: React.DependencyList) => void;
8
- type ControlNames = "alphaMaskSlider" | "autoRotateButton" | "axisClipSliders" | "brightnessSlider" | "backgroundColorPicker" | "boundingBoxColorPicker" | "colorPresetsDropdown" | "densitySlider" | "levelsSliders" | "interpolationControl" | "saveSurfaceButtons" | "fovCellSwitchControls" | "viewModeRadioButtons" | "resetCameraButton" | "showAxesButton" | "showBoundingBoxButton" | "metadataViewer";
8
+ type ControlNames = "alphaMaskSlider" | "autoRotateButton" | "axisClipSliders" | "brightnessSlider" | "backgroundColorPicker" | "boundingBoxColorPicker" | "colorPresetsDropdown" | "densitySlider" | "levelsSliders" | "interpolationControl" | "saveSurfaceButtons" | "fovCellSwitchControls" | "viewModeRadioButtons" | "resetCameraButton" | "showAxesButton" | "showBoundingBoxButton" | "metadataViewer" | "scaleLevelControls";
9
9
  /** Show/hide different elements of the UI */
10
10
  export type ControlVisibilityFlags = {
11
11
  [K in ControlNames]: boolean;
@@ -41,7 +41,7 @@ export interface AppProps {
41
41
  view3dRef?: MutableRefObject<View3d | null>;
42
42
  metadataFormatter?: (metadata: MetadataRecord) => MetadataRecord;
43
43
  onControlPanelToggle?: (collapsed: boolean) => void;
44
- showError?: (error: any) => void;
44
+ showError?: (error: unknown, image?: Volume) => void;
45
45
  onImageTitleChange?: (title: string | undefined) => void;
46
46
  }
47
47
  export {};