@aics/vole-app 2.14.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/Globals.d.js +0 -0
- package/es/aics-image-viewer/components/App/index.js +36 -7
- package/es/aics-image-viewer/components/ChannelsWidgetRow/index.js +38 -20
- package/es/aics-image-viewer/components/GlobalVolumeControls.js +3 -2
- package/es/aics-image-viewer/components/shared/SliderRow/index.js +8 -3
- package/es/aics-image-viewer/components/shared/SliderRow/styles.css +6 -0
- package/package.json +2 -2
- package/type-declarations/aics-image-viewer/components/shared/SliderRow/index.d.ts +2 -1
package/es/Globals.d.js
ADDED
|
File without changes
|
|
@@ -26,6 +26,7 @@ import { colorArrayToFloats } from "../../shared/utils/colorRepresentations";
|
|
|
26
26
|
import { controlPointsToRamp, initializeLut, rampToControlPoints, remapControlPointsForChannel } from "../../shared/utils/controlPointsToLut";
|
|
27
27
|
import { useConstructor } from "../../shared/utils/hooks";
|
|
28
28
|
import { alphaSliderToImageValue, brightnessSliderToImageValue, densitySliderToImageValue, gammaSliderToImageValues } from "../../shared/utils/sliderValuesToImageValues";
|
|
29
|
+
import { findFirstChannelMatch } from "../../shared/utils/viewerChannelSettings";
|
|
29
30
|
import useVolume, { ImageLoadStatus } from "../useVolume";
|
|
30
31
|
import CellViewerCanvasWrapper from "../CellViewerCanvasWrapper";
|
|
31
32
|
import ControlPanel from "../ControlPanel";
|
|
@@ -185,14 +186,41 @@ var App = function App(props) {
|
|
|
185
186
|
// we need to keep track of channel ranges for remapping control points
|
|
186
187
|
var channelRangesRef = useRef([]);
|
|
187
188
|
var onCreateImage = useCallback(function (newImage) {
|
|
189
|
+
var _newImage$imageInfo$c;
|
|
188
190
|
if (newImage === null) {
|
|
189
191
|
return;
|
|
190
192
|
}
|
|
191
|
-
|
|
193
|
+
var channelNames = newImage.channelNames;
|
|
194
|
+
channelRangesRef.current = new Array(channelNames.length).fill(undefined);
|
|
192
195
|
var channelSettings = viewerState.current.channelSettings;
|
|
196
|
+
|
|
197
|
+
// If the image has channel color metadata, apply those colors now
|
|
198
|
+
var viewerChannelSettings = getCurrentViewerChannelSettings();
|
|
199
|
+
var channelColorMeta = (_newImage$imageInfo$c = newImage.imageInfo.channelColors) === null || _newImage$imageInfo$c === void 0 ? void 0 : _newImage$imageInfo$c.map(function (color, index) {
|
|
200
|
+
// Filter out channels that have colors in `viewerChannelSettings`
|
|
201
|
+
if (viewerChannelSettings === undefined) {
|
|
202
|
+
return color;
|
|
203
|
+
}
|
|
204
|
+
var settings = findFirstChannelMatch(channelNames[index], index, viewerChannelSettings);
|
|
205
|
+
if ((settings === null || settings === void 0 ? void 0 : settings.color) !== undefined) {
|
|
206
|
+
return undefined;
|
|
207
|
+
} else {
|
|
208
|
+
return color;
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
if (Array.isArray(channelColorMeta)) {
|
|
212
|
+
channelColorMeta.forEach(function (color, index) {
|
|
213
|
+
if (Array.isArray(color) && index < channelNames.length) {
|
|
214
|
+
changeChannelSetting(index, {
|
|
215
|
+
color: color
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
193
220
|
view3d.addVolume(newImage, {
|
|
194
221
|
// Immediately passing down channel parameters isn't strictly necessary, but keeps things looking consistent on load
|
|
195
|
-
channels: newImage.channelNames.map(function (name) {
|
|
222
|
+
channels: newImage.channelNames.map(function (name, index) {
|
|
223
|
+
var _channelColorMeta$ind;
|
|
196
224
|
// TODO do we really need to be searching by name here?
|
|
197
225
|
var ch = channelSettings.find(function (channel) {
|
|
198
226
|
return channel.name === name;
|
|
@@ -205,13 +233,13 @@ var App = function App(props) {
|
|
|
205
233
|
isosurfaceEnabled: ch.isosurfaceEnabled,
|
|
206
234
|
isovalue: ch.isovalue,
|
|
207
235
|
isosurfaceOpacity: ch.opacity,
|
|
208
|
-
color: ch.color
|
|
236
|
+
color: (_channelColorMeta$ind = channelColorMeta === null || channelColorMeta === void 0 ? void 0 : channelColorMeta[index]) !== null && _channelColorMeta$ind !== void 0 ? _channelColorMeta$ind : ch.color
|
|
209
237
|
};
|
|
210
238
|
})
|
|
211
239
|
});
|
|
212
240
|
onImageTitleChange === null || onImageTitleChange === void 0 || onImageTitleChange(newImage.imageInfo.imageInfo.name);
|
|
213
241
|
view3d.updateActiveChannels(newImage);
|
|
214
|
-
}, [view3d, viewerState, onImageTitleChange]);
|
|
242
|
+
}, [view3d, viewerState, onImageTitleChange, changeChannelSetting, getCurrentViewerChannelSettings]);
|
|
215
243
|
var onChannelLoaded = useCallback(function (image, channelIndex, isInitialLoad) {
|
|
216
244
|
// TODO this was once a search by name - is that still necessary or will the index always be correct?
|
|
217
245
|
var thisChannelSettings = channelSettings[channelIndex];
|
|
@@ -226,13 +254,14 @@ var App = function App(props) {
|
|
|
226
254
|
var _initializeLut = initializeLut(image, channelIndex, getCurrentViewerChannelSettings()),
|
|
227
255
|
ramp = _initializeLut.ramp,
|
|
228
256
|
controlPoints = _initializeLut.controlPoints;
|
|
229
|
-
var
|
|
257
|
+
var range = DTYPE_RANGE[thisChannel.dtype];
|
|
230
258
|
changeChannelSetting(channelIndex, {
|
|
231
259
|
controlPoints: controlPoints,
|
|
232
260
|
ramp: controlPointsToRamp(ramp),
|
|
233
261
|
// set the default range of the transfer function editor to cover the full range of the data type
|
|
234
|
-
plotMin:
|
|
235
|
-
plotMax:
|
|
262
|
+
plotMin: range.min,
|
|
263
|
+
plotMax: range.max,
|
|
264
|
+
isovalue: range.min + (range.max - range.min) / 2
|
|
236
265
|
});
|
|
237
266
|
} else {
|
|
238
267
|
// This channel has already been initialized, but its LUT was just remapped and we need to update some things
|
|
@@ -4,9 +4,9 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
|
|
|
4
4
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
5
5
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
6
6
|
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
7
|
-
import { Button, Checkbox, List } from "antd";
|
|
7
|
+
import { Button, Checkbox, InputNumber, List } from "antd";
|
|
8
8
|
import React, { useCallback, useState } from "react";
|
|
9
|
-
import { ISOSURFACE_OPACITY_SLIDER_MAX } from "../../shared/constants";
|
|
9
|
+
import { DTYPE_RANGE, ISOSURFACE_OPACITY_SLIDER_MAX } from "../../shared/constants";
|
|
10
10
|
import { colorArrayToObject, colorObjectToArray } from "../../shared/utils/colorRepresentations";
|
|
11
11
|
import ColorPicker from "../ColorPicker";
|
|
12
12
|
import SliderRow from "../shared/SliderRow";
|
|
@@ -37,20 +37,6 @@ var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
|
|
|
37
37
|
isosurfaceEnabled: target.checked
|
|
38
38
|
});
|
|
39
39
|
};
|
|
40
|
-
var onIsovalueChange = function onIsovalueChange(_ref3) {
|
|
41
|
-
var _ref4 = _slicedToArray(_ref3, 1),
|
|
42
|
-
newValue = _ref4[0];
|
|
43
|
-
return changeSettingForThisChannel({
|
|
44
|
-
isovalue: newValue
|
|
45
|
-
});
|
|
46
|
-
};
|
|
47
|
-
var onOpacityChange = function onOpacityChange(_ref5) {
|
|
48
|
-
var _ref6 = _slicedToArray(_ref5, 1),
|
|
49
|
-
newValue = _ref6[0];
|
|
50
|
-
return changeSettingForThisChannel({
|
|
51
|
-
opacity: newValue / ISOSURFACE_OPACITY_SLIDER_MAX
|
|
52
|
-
});
|
|
53
|
-
};
|
|
54
40
|
var onColorChange = function onColorChange(newRGB, _oldRGB, index) {
|
|
55
41
|
var color = colorObjectToArray(newRGB);
|
|
56
42
|
props.changeChannelSetting(index, {
|
|
@@ -112,17 +98,49 @@ var ChannelsWidgetRow = function ChannelsWidgetRow(props) {
|
|
|
112
98
|
});
|
|
113
99
|
};
|
|
114
100
|
var renderSurfaceControls = function renderSurfaceControls() {
|
|
101
|
+
var range = DTYPE_RANGE[props.channelDataForChannel.dtype];
|
|
115
102
|
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(SliderRow, {
|
|
116
103
|
label: "Isovalue",
|
|
117
|
-
|
|
104
|
+
min: range.min,
|
|
105
|
+
max: range.max,
|
|
118
106
|
start: channelState.isovalue,
|
|
119
|
-
onChange:
|
|
107
|
+
onChange: function onChange(_ref3) {
|
|
108
|
+
var _ref4 = _slicedToArray(_ref3, 1),
|
|
109
|
+
isovalue = _ref4[0];
|
|
110
|
+
return changeSettingForThisChannel({
|
|
111
|
+
isovalue: isovalue
|
|
112
|
+
});
|
|
113
|
+
},
|
|
120
114
|
formatInteger: true
|
|
121
|
-
}
|
|
115
|
+
}, /*#__PURE__*/React.createElement(InputNumber, {
|
|
116
|
+
value: channelState.isovalue,
|
|
117
|
+
onChange: function onChange(isovalue) {
|
|
118
|
+
return isovalue !== null && changeSettingForThisChannel({
|
|
119
|
+
isovalue: isovalue
|
|
120
|
+
});
|
|
121
|
+
},
|
|
122
|
+
formatter: function formatter(v) {
|
|
123
|
+
return v === undefined ? "" : Number(v).toFixed(0);
|
|
124
|
+
},
|
|
125
|
+
min: range.min,
|
|
126
|
+
max: range.max,
|
|
127
|
+
size: "small",
|
|
128
|
+
controls: false,
|
|
129
|
+
style: {
|
|
130
|
+
width: "64px",
|
|
131
|
+
marginLeft: "8px"
|
|
132
|
+
}
|
|
133
|
+
})), /*#__PURE__*/React.createElement(SliderRow, {
|
|
122
134
|
label: "Opacity",
|
|
123
135
|
max: ISOSURFACE_OPACITY_SLIDER_MAX,
|
|
124
136
|
start: channelState.opacity * ISOSURFACE_OPACITY_SLIDER_MAX,
|
|
125
|
-
onChange:
|
|
137
|
+
onChange: function onChange(_ref5) {
|
|
138
|
+
var _ref6 = _slicedToArray(_ref5, 1),
|
|
139
|
+
opacity = _ref6[0];
|
|
140
|
+
return changeSettingForThisChannel({
|
|
141
|
+
opacity: opacity / ISOSURFACE_OPACITY_SLIDER_MAX
|
|
142
|
+
});
|
|
143
|
+
},
|
|
126
144
|
formatInteger: true
|
|
127
145
|
}), /*#__PURE__*/React.createElement("div", {
|
|
128
146
|
className: "button-row"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { Checkbox } from "antd";
|
|
2
|
+
import React from "react";
|
|
3
3
|
import SliderRow from "./shared/SliderRow";
|
|
4
4
|
import { connectToViewerState } from "./ViewerStateProvider";
|
|
5
5
|
var GlobalVolumeControls = function GlobalVolumeControls(props) {
|
|
@@ -26,7 +26,8 @@ var GlobalVolumeControls = function GlobalVolumeControls(props) {
|
|
|
26
26
|
paddingBottom: 22
|
|
27
27
|
}
|
|
28
28
|
}, showControls.alphaMaskSlider && createSliderRow("mask cell", maskAlpha, 100, "maskAlpha"), showControls.brightnessSlider && createSliderRow("brightness", brightness, 100, "brightness"), showControls.densitySlider && createSliderRow("density", density, 100, "density"), showControls.levelsSliders && createSliderRow("levels", levels, 255, "levels"), showControls.interpolationControl && /*#__PURE__*/React.createElement(SliderRow, {
|
|
29
|
-
label: "interpolate"
|
|
29
|
+
label: "interpolate",
|
|
30
|
+
hideSlider: true
|
|
30
31
|
}, /*#__PURE__*/React.createElement(Checkbox, {
|
|
31
32
|
checked: props.interpolationEnabled,
|
|
32
33
|
onChange: function onChange(_ref) {
|
|
@@ -8,15 +8,18 @@ var INTEGER_FORMATTER = {
|
|
|
8
8
|
|
|
9
9
|
/** A component to ensure a single unified style across the many labeled slider rows in the control panel */
|
|
10
10
|
var SliderRow = function SliderRow(props) {
|
|
11
|
+
var _props$min;
|
|
11
12
|
return /*#__PURE__*/React.createElement("div", {
|
|
12
13
|
className: "viewer-control-row"
|
|
13
14
|
}, /*#__PURE__*/React.createElement("div", {
|
|
14
15
|
className: "control-name"
|
|
15
16
|
}, props.label), /*#__PURE__*/React.createElement("div", {
|
|
16
17
|
className: "control"
|
|
17
|
-
}, props.start
|
|
18
|
+
}, props.start !== undefined && !props.hideSlider && /*#__PURE__*/React.createElement("div", {
|
|
19
|
+
className: "control-slider"
|
|
20
|
+
}, /*#__PURE__*/React.createElement(SmarterSlider, {
|
|
18
21
|
range: {
|
|
19
|
-
min: 0,
|
|
22
|
+
min: (_props$min = props.min) !== null && _props$min !== void 0 ? _props$min : 0,
|
|
20
23
|
max: props.max
|
|
21
24
|
},
|
|
22
25
|
start: props.start,
|
|
@@ -26,6 +29,8 @@ var SliderRow = function SliderRow(props) {
|
|
|
26
29
|
format: props.formatInteger ? INTEGER_FORMATTER : undefined,
|
|
27
30
|
onUpdate: props.onUpdate,
|
|
28
31
|
onChange: props.onChange
|
|
29
|
-
}))
|
|
32
|
+
})), props.children && /*#__PURE__*/React.createElement("div", {
|
|
33
|
+
className: "control-extra"
|
|
34
|
+
}, props.children)));
|
|
30
35
|
};
|
|
31
36
|
export default SliderRow;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aics/vole-app",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.15.0",
|
|
4
4
|
"description": "web view of cell volume images",
|
|
5
5
|
"repository": "github:allen-cell-animated/vole-app",
|
|
6
6
|
"main": "es/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"author": "Megan Riel-Mehan",
|
|
42
42
|
"license": "ISC",
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@aics/vole-core": "^4.1
|
|
44
|
+
"@aics/vole-core": "^4.3.1",
|
|
45
45
|
"@ant-design/icons": "^5.2.5",
|
|
46
46
|
"@fortawesome/fontawesome-svg-core": "^6.5.2",
|
|
47
47
|
"@fortawesome/free-solid-svg-icons": "^6.5.2",
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import React from "react";
|
|
2
1
|
import { NouisliderProps } from "nouislider-react";
|
|
2
|
+
import React from "react";
|
|
3
3
|
import "./styles.css";
|
|
4
4
|
type SliderRowProps = {
|
|
5
5
|
label: React.ReactNode;
|
|
6
6
|
start?: number | number[];
|
|
7
7
|
step?: number;
|
|
8
8
|
formatInteger?: boolean;
|
|
9
|
+
min?: number;
|
|
9
10
|
max?: number;
|
|
10
11
|
onUpdate?: NouisliderProps["onUpdate"];
|
|
11
12
|
onChange?: NouisliderProps["onChange"];
|