@haniffalab/cherita-react 0.2.0-dev.2024-12-16.f6e39628 → 0.2.0-dev.2024-12-16.f02cfae4
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/dist/components/full-page/FullPage.js +50 -6
- package/dist/components/obs-list/ObsItem.js +11 -5
- package/dist/components/obs-list/ObsList.js +8 -2
- package/dist/components/pseudospatial/Pseudospatial.js +215 -0
- package/dist/components/pseudospatial/PseudospatialControls.js +12 -0
- package/dist/components/pseudospatial/PseudospatialToolbar.js +155 -0
- package/dist/components/scatterplot/Scatterplot.js +100 -153
- package/dist/components/var-list/VarItem.js +20 -8
- package/dist/components/var-list/VarList.js +106 -22
- package/dist/components/var-list/VarListToolbar.js +101 -0
- package/dist/components/var-list/VarSet.js +1 -0
- package/dist/constants/constants.js +26 -1
- package/dist/context/DatasetContext.js +90 -3
- package/dist/context/FilterContext.js +1 -0
- package/dist/css/cherita.css +39 -0
- package/dist/css/cherita.css.map +1 -1
- package/dist/helpers/color-helper.js +12 -8
- package/dist/helpers/zarr-helper.js +2 -0
- package/dist/index.js +19 -0
- package/dist/utils/ImageViewer.js +40 -0
- package/dist/{components/scatterplot → utils}/Legend.js +12 -7
- package/dist/utils/requests.js +8 -6
- package/dist/utils/string.js +3 -3
- package/dist/utils/zarrData.js +101 -0
- package/package.json +2 -2
- package/scss/cherita.scss +39 -0
|
@@ -4,12 +4,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.FullPage = FullPage;
|
|
7
|
+
exports.FullPagePseudospatial = FullPagePseudospatial;
|
|
8
|
+
exports.FullPageScatterplot = FullPageScatterplot;
|
|
7
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
10
|
var _reactBootstrap = require("react-bootstrap");
|
|
9
11
|
var _constants = require("../../constants/constants");
|
|
10
12
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
11
13
|
var _ObsList = require("../obs-list/ObsList");
|
|
12
14
|
var _offcanvas = require("../offcanvas");
|
|
15
|
+
var _Pseudospatial = require("../pseudospatial/Pseudospatial");
|
|
13
16
|
var _Scatterplot = require("../scatterplot/Scatterplot");
|
|
14
17
|
var _ScatterplotControls = require("../scatterplot/ScatterplotControls");
|
|
15
18
|
var _SearchBar = require("../search-bar/SearchBar");
|
|
@@ -17,7 +20,11 @@ var _VarList = require("../var-list/VarList");
|
|
|
17
20
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
18
21
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
19
22
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
20
|
-
function FullPage(
|
|
23
|
+
function FullPage(_ref) {
|
|
24
|
+
let {
|
|
25
|
+
children,
|
|
26
|
+
...props
|
|
27
|
+
} = _ref;
|
|
21
28
|
const targetRef = (0, _react.useRef)();
|
|
22
29
|
const [showObs, setShowObs] = (0, _react.useState)(false);
|
|
23
30
|
const [showObsm, setShowObsm] = (0, _react.useState)(false);
|
|
@@ -94,17 +101,15 @@ function FullPage(props) {
|
|
|
94
101
|
})]
|
|
95
102
|
})
|
|
96
103
|
})
|
|
97
|
-
}),
|
|
98
|
-
className: "cherita-container-scatterplot",
|
|
99
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Scatterplot.Scatterplot, {})
|
|
100
|
-
})]
|
|
104
|
+
}), children]
|
|
101
105
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
102
106
|
className: "cherita-app-var",
|
|
103
107
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Card, {
|
|
104
108
|
className: "cherita-app-features",
|
|
105
109
|
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Card.Body, {
|
|
106
110
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_SearchBar.SearchBar, {
|
|
107
|
-
searchDiseases: true
|
|
111
|
+
searchDiseases: true,
|
|
112
|
+
searchVar: true
|
|
108
113
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_VarList.VarNamesList, {
|
|
109
114
|
mode: _constants.SELECTION_MODES.SINGLE
|
|
110
115
|
})]
|
|
@@ -130,4 +135,43 @@ function FullPage(props) {
|
|
|
130
135
|
})
|
|
131
136
|
})
|
|
132
137
|
});
|
|
138
|
+
}
|
|
139
|
+
function FullPageScatterplot(props) {
|
|
140
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(FullPage, {
|
|
141
|
+
...props,
|
|
142
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Scatterplot.Scatterplot, {})
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
function FullPagePseudospatial(props) {
|
|
146
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(FullPage, {
|
|
147
|
+
...props,
|
|
148
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
149
|
+
className: "container-fluid h-100",
|
|
150
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
151
|
+
className: "row",
|
|
152
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
153
|
+
className: "col-12 col-lg-7",
|
|
154
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Scatterplot.Scatterplot, {})
|
|
155
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
156
|
+
className: "col-12 col-lg-5",
|
|
157
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
158
|
+
className: "container-fluid h-100 d-flex align-itemms-center justify-content-center",
|
|
159
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
160
|
+
className: "row w-100 py-3",
|
|
161
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
162
|
+
className: "col-12",
|
|
163
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
164
|
+
className: "p-2",
|
|
165
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Pseudospatial.Pseudospatial, {})
|
|
166
|
+
})
|
|
167
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
168
|
+
className: "col-12",
|
|
169
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Pseudospatial.PseudospatialImage, {})
|
|
170
|
+
})]
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
})]
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
});
|
|
133
177
|
}
|
|
@@ -128,9 +128,15 @@ function CategoricalItem(_ref) {
|
|
|
128
128
|
y: "0",
|
|
129
129
|
width: "10",
|
|
130
130
|
height: "10",
|
|
131
|
-
fill: `rgb(${getColor(
|
|
132
|
-
|
|
133
|
-
|
|
131
|
+
fill: `rgb(${getColor({
|
|
132
|
+
value: (code - min) / (max - min),
|
|
133
|
+
categorical: true,
|
|
134
|
+
grayOut: isOmitted,
|
|
135
|
+
grayParams: {
|
|
136
|
+
alpha: 1
|
|
137
|
+
},
|
|
138
|
+
colorEncoding: "obs"
|
|
139
|
+
})})`
|
|
134
140
|
})
|
|
135
141
|
})
|
|
136
142
|
})]
|
|
@@ -211,7 +217,7 @@ function ObsContinuousStats(_ref3) {
|
|
|
211
217
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
212
218
|
const params = {
|
|
213
219
|
url: dataset.url,
|
|
214
|
-
|
|
220
|
+
obsColname: obs.name
|
|
215
221
|
};
|
|
216
222
|
const {
|
|
217
223
|
fetchedData,
|
|
@@ -309,7 +315,7 @@ function ContinuousObs(_ref4) {
|
|
|
309
315
|
const binnedObs = binContinuous(obs);
|
|
310
316
|
const params = {
|
|
311
317
|
url: dataset.url,
|
|
312
|
-
|
|
318
|
+
obsCol: binnedObs.name,
|
|
313
319
|
thresholds: binnedObs.bins.thresholds,
|
|
314
320
|
nBins: binnedObs.bins.nBins
|
|
315
321
|
};
|
|
@@ -45,7 +45,13 @@ function ObsColsList(_ref) {
|
|
|
45
45
|
});
|
|
46
46
|
(0, _react.useEffect)(() => {
|
|
47
47
|
if (!isPending && !serverError) {
|
|
48
|
-
|
|
48
|
+
let filteredData = fetchedData;
|
|
49
|
+
if (dataset.obsCols) {
|
|
50
|
+
filteredData = _lodash.default.filter(filteredData, d => {
|
|
51
|
+
return _lodash.default.includes(dataset.obsCols, d.name);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
setObsCols(_lodash.default.keyBy(_lodash.default.map(filteredData, d => {
|
|
49
55
|
return {
|
|
50
56
|
...d,
|
|
51
57
|
codesMap: _lodash.default.invert(d.codes),
|
|
@@ -53,7 +59,7 @@ function ObsColsList(_ref) {
|
|
|
53
59
|
};
|
|
54
60
|
}), "name"));
|
|
55
61
|
}
|
|
56
|
-
}, [fetchedData, isPending, serverError]);
|
|
62
|
+
}, [dataset.obsCols, fetchedData, isPending, serverError]);
|
|
57
63
|
|
|
58
64
|
// @TODO: fix re-rendering performance issue
|
|
59
65
|
(0, _react.useEffect)(() => {
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.Pseudospatial = Pseudospatial;
|
|
7
|
+
exports.PseudospatialImage = PseudospatialImage;
|
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
10
|
+
var _reactBootstrap = require("react-bootstrap");
|
|
11
|
+
var _reactPlotly = _interopRequireDefault(require("react-plotly.js"));
|
|
12
|
+
var _PseudospatialToolbar = require("./PseudospatialToolbar");
|
|
13
|
+
var _constants = require("../../constants/constants");
|
|
14
|
+
var _DatasetContext = require("../../context/DatasetContext");
|
|
15
|
+
var _colorHelper = require("../../helpers/color-helper");
|
|
16
|
+
var _ImageViewer = require("../../utils/ImageViewer");
|
|
17
|
+
var _Legend = require("../../utils/Legend");
|
|
18
|
+
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
19
|
+
var _requests = require("../../utils/requests");
|
|
20
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
21
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
23
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
24
|
+
function usePseudospatialData(plotType) {
|
|
25
|
+
const ENDPOINT = "pseudospatial";
|
|
26
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
27
|
+
const baseParams = (0, _react.useMemo)(() => {
|
|
28
|
+
return {
|
|
29
|
+
url: dataset.url,
|
|
30
|
+
maskSet: dataset.pseudospatial.maskSet,
|
|
31
|
+
maskValues: dataset.pseudospatial.maskValues,
|
|
32
|
+
varNamesCol: dataset.varNamesCol,
|
|
33
|
+
showColorbar: false,
|
|
34
|
+
format: "json"
|
|
35
|
+
};
|
|
36
|
+
}, [dataset.url, dataset.pseudospatial.maskSet, dataset.pseudospatial.maskValues, dataset.varNamesCol]);
|
|
37
|
+
const getPlotParams = (0, _react.useCallback)(() => {
|
|
38
|
+
if (plotType === _constants.PSEUDOSPATIAL_PLOT_TYPES.GENE) {
|
|
39
|
+
return {
|
|
40
|
+
varKey: dataset.selectedVar?.isSet ? {
|
|
41
|
+
name: dataset.selectedVar?.name,
|
|
42
|
+
indices: dataset.selectedVar?.vars.map(v => v.index)
|
|
43
|
+
} : dataset.selectedVar?.index,
|
|
44
|
+
...(dataset.sliceBy.obs ? {
|
|
45
|
+
obsCol: dataset.selectedObs,
|
|
46
|
+
obsValues: !dataset.selectedObs?.omit.length ? null : _lodash.default.difference(_lodash.default.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c])
|
|
47
|
+
} : {})
|
|
48
|
+
};
|
|
49
|
+
} else if (plotType === _constants.PSEUDOSPATIAL_PLOT_TYPES.CATEGORICAL) {
|
|
50
|
+
return {
|
|
51
|
+
obsCol: dataset.selectedObs,
|
|
52
|
+
obsValues: !dataset.selectedObs?.omit.length ? null : _lodash.default.difference(_lodash.default.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c]),
|
|
53
|
+
mode: dataset.pseudospatial.categoricalMode
|
|
54
|
+
};
|
|
55
|
+
} else if (plotType === "continuous") {
|
|
56
|
+
return {
|
|
57
|
+
obsCol: dataset.selectedObs,
|
|
58
|
+
obsValues: !dataset.selectedObs?.omit.length ? null : _lodash.default.difference(_lodash.default.values(dataset.selectedObs?.codes), dataset.selectedObs?.omit).map(c => dataset.selectedObs?.codesMap[c])
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}, [dataset.pseudospatial.categoricalMode, dataset.selectedObs, dataset.selectedVar?.index, dataset.selectedVar?.isSet, dataset.selectedVar?.name, dataset.selectedVar?.vars, dataset.sliceBy.obs, plotType]);
|
|
62
|
+
const params = (0, _react.useMemo)(() => {
|
|
63
|
+
return {
|
|
64
|
+
...baseParams,
|
|
65
|
+
...getPlotParams()
|
|
66
|
+
};
|
|
67
|
+
}, [baseParams, getPlotParams]);
|
|
68
|
+
return (0, _requests.useDebouncedFetch)(ENDPOINT + "/" + plotType, params, 500, {
|
|
69
|
+
enabled: !!plotType && !!dataset.pseudospatial.maskSet
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function Pseudospatial(_ref) {
|
|
73
|
+
let {
|
|
74
|
+
showLegend = true,
|
|
75
|
+
sharedScaleRange = false
|
|
76
|
+
} = _ref;
|
|
77
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
78
|
+
const [data, setData] = (0, _react.useState)([]);
|
|
79
|
+
const [layout, setLayout] = (0, _react.useState)({});
|
|
80
|
+
const {
|
|
81
|
+
getColor
|
|
82
|
+
} = (0, _colorHelper.useColor)();
|
|
83
|
+
const colorscale = (0, _react.useRef)(dataset.controls.colorScale);
|
|
84
|
+
const plotType = dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? _constants.PSEUDOSPATIAL_PLOT_TYPES.GENE : dataset.selectedObs?.type === _constants.OBS_TYPES.CATEGORICAL || dataset.selectedObs?.type === _constants.OBS_TYPES.BOOLEAN ? _constants.PSEUDOSPATIAL_PLOT_TYPES.CATEGORICAL : dataset.selectedObs?.type === _constants.OBS_TYPES.CONTINUOUS ? _constants.PSEUDOSPATIAL_PLOT_TYPES.CONTINUOUS : _constants.PSEUDOSPATIAL_PLOT_TYPES.MASKS;
|
|
85
|
+
const updateColorscale = (0, _react.useCallback)(colorscale => {
|
|
86
|
+
setLayout(l => {
|
|
87
|
+
return {
|
|
88
|
+
...l,
|
|
89
|
+
coloraxis: {
|
|
90
|
+
...l.coloraxis,
|
|
91
|
+
colorscale: colorscale
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
setData(d => {
|
|
96
|
+
const min = layout?.coloraxis?.cmin;
|
|
97
|
+
const max = layout?.coloraxis?.cmax;
|
|
98
|
+
return _lodash.default.map(d, trace => {
|
|
99
|
+
const v = trace.meta.value;
|
|
100
|
+
if (v === null) {
|
|
101
|
+
return trace;
|
|
102
|
+
}
|
|
103
|
+
const color = (0, _colorHelper.rgbToHex)(getColor({
|
|
104
|
+
value: (v - min) / (max - min)
|
|
105
|
+
}));
|
|
106
|
+
return {
|
|
107
|
+
...trace,
|
|
108
|
+
fillcolor: color,
|
|
109
|
+
line: {
|
|
110
|
+
...trace.line,
|
|
111
|
+
color: color
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}, [getColor, layout?.coloraxis?.cmax, layout?.coloraxis?.cmin]);
|
|
117
|
+
const {
|
|
118
|
+
fetchedData,
|
|
119
|
+
isPending,
|
|
120
|
+
serverError
|
|
121
|
+
} = usePseudospatialData(plotType);
|
|
122
|
+
(0, _react.useEffect)(() => {
|
|
123
|
+
if (!isPending && !serverError) {
|
|
124
|
+
setData(fetchedData.data);
|
|
125
|
+
setLayout(fetchedData.layout);
|
|
126
|
+
updateColorscale(colorscale.current);
|
|
127
|
+
}
|
|
128
|
+
}, [fetchedData, isPending, serverError, sharedScaleRange, updateColorscale]);
|
|
129
|
+
(0, _react.useEffect)(() => {
|
|
130
|
+
colorscale.current = dataset.controls.colorScale;
|
|
131
|
+
updateColorscale(colorscale.current);
|
|
132
|
+
}, [dataset.controls.colorScale, updateColorscale]);
|
|
133
|
+
(0, _react.useEffect)(() => {
|
|
134
|
+
if (sharedScaleRange) {
|
|
135
|
+
const {
|
|
136
|
+
min,
|
|
137
|
+
max
|
|
138
|
+
} = {
|
|
139
|
+
min: dataset.controls.range[0] * (dataset.controls.valueRange[1] - dataset.controls.valueRange[0]) + dataset.controls.valueRange[0],
|
|
140
|
+
max: dataset.controls.range[1] * (dataset.controls.valueRange[1] - dataset.controls.valueRange[0]) + dataset.controls.valueRange[0]
|
|
141
|
+
};
|
|
142
|
+
setData(d => {
|
|
143
|
+
return _lodash.default.map(d, trace => {
|
|
144
|
+
const v = trace.meta.value;
|
|
145
|
+
if (v === null) {
|
|
146
|
+
return trace;
|
|
147
|
+
}
|
|
148
|
+
const color = (0, _colorHelper.rgbToHex)(getColor({
|
|
149
|
+
value: (v - min) / (max - min)
|
|
150
|
+
}));
|
|
151
|
+
return {
|
|
152
|
+
...trace,
|
|
153
|
+
fillcolor: color,
|
|
154
|
+
line: {
|
|
155
|
+
...trace.line,
|
|
156
|
+
color: color
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
setLayout(l => {
|
|
162
|
+
return {
|
|
163
|
+
...l,
|
|
164
|
+
coloraxis: {
|
|
165
|
+
...l.coloraxis,
|
|
166
|
+
cmin: min,
|
|
167
|
+
cmax: max
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}, [dataset.controls.range, dataset.controls.valueMax, dataset.controls.valueMin, dataset.controls.valueRange, getColor, sharedScaleRange]);
|
|
173
|
+
const hasSelections = !!plotType && !!dataset.pseudospatial.maskSet;
|
|
174
|
+
if (!serverError) {
|
|
175
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
176
|
+
className: "cherita-pseudospatial position-relative",
|
|
177
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_PseudospatialToolbar.PseudospatialToolbar, {
|
|
178
|
+
plotType: plotType
|
|
179
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
180
|
+
children: [hasSelections && isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingSpinner, {}), hasSelections && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactPlotly.default, {
|
|
181
|
+
data: data,
|
|
182
|
+
layout: layout,
|
|
183
|
+
useResizeHandler: true,
|
|
184
|
+
className: "cherita-pseudospatial-plot",
|
|
185
|
+
config: {
|
|
186
|
+
displaylogo: false
|
|
187
|
+
}
|
|
188
|
+
}), hasSelections && showLegend && /*#__PURE__*/(0, _jsxRuntime.jsx)(_Legend.Legend, {
|
|
189
|
+
min: layout?.coloraxis?.cmin,
|
|
190
|
+
max: layout?.coloraxis?.cmax
|
|
191
|
+
})]
|
|
192
|
+
})]
|
|
193
|
+
});
|
|
194
|
+
} else {
|
|
195
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
196
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Alert, {
|
|
197
|
+
variant: "danger",
|
|
198
|
+
children: serverError.message
|
|
199
|
+
})
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// @TODO: explore making it a minimap
|
|
205
|
+
function PseudospatialImage() {
|
|
206
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
207
|
+
if (dataset.imageUrl) {
|
|
208
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_ImageViewer.ImageViewer, {
|
|
209
|
+
src: dataset.imageUrl,
|
|
210
|
+
alt: "Pseudospatial reference image"
|
|
211
|
+
});
|
|
212
|
+
} else {
|
|
213
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.PseudospatialControls = PseudospatialControls;
|
|
7
|
+
var _react = _interopRequireDefault(require("react"));
|
|
8
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
|
+
function PseudospatialControls() {
|
|
11
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {});
|
|
12
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.PseudospatialToolbar = PseudospatialToolbar;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
9
|
+
var _reactBootstrap = require("react-bootstrap");
|
|
10
|
+
var _constants = require("../../constants/constants");
|
|
11
|
+
var _DatasetContext = require("../../context/DatasetContext");
|
|
12
|
+
var _requests = require("../../utils/requests");
|
|
13
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
15
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
16
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
17
|
+
function CategoricalMode() {
|
|
18
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
19
|
+
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
20
|
+
const modeList = _lodash.default.map(_constants.PSEUDOSPATIAL_CATEGORICAL_MODES, (m, key) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Item, {
|
|
21
|
+
active: dataset.pseudospatial.categoricalMode === m,
|
|
22
|
+
onClick: () => {
|
|
23
|
+
dispatch({
|
|
24
|
+
type: "set.pseudospatial.categoricalMode",
|
|
25
|
+
categoricalMode: m.value
|
|
26
|
+
});
|
|
27
|
+
},
|
|
28
|
+
children: _lodash.default.capitalize(m.name)
|
|
29
|
+
}, key));
|
|
30
|
+
const mode = _lodash.default.find(_constants.PSEUDOSPATIAL_CATEGORICAL_MODES, {
|
|
31
|
+
value: dataset.pseudospatial.categoricalMode
|
|
32
|
+
});
|
|
33
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Dropdown, {
|
|
34
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Toggle, {
|
|
35
|
+
variant: "light",
|
|
36
|
+
children: _lodash.default.capitalize(mode.name)
|
|
37
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Menu, {
|
|
38
|
+
children: modeList
|
|
39
|
+
})]
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function MaskSet() {
|
|
43
|
+
const ENDPOINT = "masks";
|
|
44
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
45
|
+
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
46
|
+
const [maskSets, setMaskSets] = (0, _react.useState)(null);
|
|
47
|
+
const [params, setParams] = (0, _react.useState)({
|
|
48
|
+
url: dataset.url
|
|
49
|
+
});
|
|
50
|
+
(0, _react.useEffect)(() => {
|
|
51
|
+
setParams(p => {
|
|
52
|
+
return {
|
|
53
|
+
...p,
|
|
54
|
+
url: dataset.url
|
|
55
|
+
};
|
|
56
|
+
});
|
|
57
|
+
}, [dataset.url]);
|
|
58
|
+
const {
|
|
59
|
+
fetchedData,
|
|
60
|
+
isPending,
|
|
61
|
+
serverError
|
|
62
|
+
} = (0, _requests.useFetch)(ENDPOINT, params);
|
|
63
|
+
(0, _react.useEffect)(() => {
|
|
64
|
+
if (!isPending && !serverError) {
|
|
65
|
+
setMaskSets(fetchedData);
|
|
66
|
+
}
|
|
67
|
+
}, [fetchedData, isPending, serverError]);
|
|
68
|
+
const maskSetList = _lodash.default.map(maskSets, (ms, key) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Item, {
|
|
69
|
+
active: dataset.pseudospatial.maskSet === key,
|
|
70
|
+
onClick: () => {
|
|
71
|
+
dispatch({
|
|
72
|
+
type: "set.pseudospatial.maskSet",
|
|
73
|
+
maskSet: key
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
children: _lodash.default.capitalize(key)
|
|
77
|
+
}, key));
|
|
78
|
+
const handleMaskChange = mask => {
|
|
79
|
+
let newMasks = dataset.pseudospatial.maskValues || maskSets?.[dataset.pseudospatial?.maskSet];
|
|
80
|
+
newMasks = newMasks.includes(mask) ? newMasks.filter(m => m !== mask) : [...newMasks, mask];
|
|
81
|
+
if (!_lodash.default.difference(maskSets?.[dataset.pseudospatial?.maskSet], newMasks).length) {
|
|
82
|
+
newMasks = null;
|
|
83
|
+
}
|
|
84
|
+
dispatch({
|
|
85
|
+
type: "set.pseudospatial.maskValues",
|
|
86
|
+
maskValues: newMasks
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
const toggleMasks = () => {
|
|
90
|
+
if (!dataset.pseudospatial.maskValues || dataset.pseudospatial.maskValues?.length === maskSets?.[dataset.pseudospatial?.maskSet]?.length) {
|
|
91
|
+
dispatch({
|
|
92
|
+
type: "set.pseudospatial.maskValues",
|
|
93
|
+
maskValues: []
|
|
94
|
+
});
|
|
95
|
+
} else {
|
|
96
|
+
dispatch({
|
|
97
|
+
type: "set.pseudospatial.maskValues",
|
|
98
|
+
maskValues: null
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
const masksList = _lodash.default.map(maskSets?.[dataset.pseudospatial?.maskSet], mask => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.ItemText, {
|
|
103
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Form.Check, {
|
|
104
|
+
type: "checkbox",
|
|
105
|
+
label: mask,
|
|
106
|
+
checked: !dataset.pseudospatial.maskValues || dataset.pseudospatial.maskValues.includes(mask),
|
|
107
|
+
onChange: () => handleMaskChange(mask)
|
|
108
|
+
})
|
|
109
|
+
}, mask));
|
|
110
|
+
const nMasks = dataset.pseudospatial.maskValues ? dataset.pseudospatial.maskValues?.length : maskSets?.[dataset.pseudospatial?.maskSet]?.length || "No";
|
|
111
|
+
const toggleAllChecked = !dataset.pseudospatial.maskValues || dataset.pseudospatial.maskValues?.length === maskSets?.[dataset.pseudospatial?.maskSet]?.length;
|
|
112
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
113
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Dropdown, {
|
|
114
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Toggle, {
|
|
115
|
+
variant: "light",
|
|
116
|
+
children: _lodash.default.capitalize(dataset.pseudospatial.maskSet || "Select a mask set")
|
|
117
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Dropdown.Menu, {
|
|
118
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Header, {
|
|
119
|
+
children: "Mask set"
|
|
120
|
+
}), maskSetList]
|
|
121
|
+
})]
|
|
122
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Dropdown, {
|
|
123
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Dropdown.Toggle, {
|
|
124
|
+
variant: "light",
|
|
125
|
+
children: [nMasks, " masks selected"]
|
|
126
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Dropdown.Menu, {
|
|
127
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Header, {
|
|
128
|
+
children: "Masks"
|
|
129
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.ItemText, {
|
|
130
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Form.Check, {
|
|
131
|
+
type: "checkbox",
|
|
132
|
+
label: "Toggle all",
|
|
133
|
+
checked: toggleAllChecked,
|
|
134
|
+
onChange: toggleMasks
|
|
135
|
+
})
|
|
136
|
+
}, "toggle-all"), masksList]
|
|
137
|
+
})]
|
|
138
|
+
})]
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// @TODO: add colormap, colorbar slider
|
|
143
|
+
function PseudospatialToolbar(_ref) {
|
|
144
|
+
let {
|
|
145
|
+
plotType
|
|
146
|
+
} = _ref;
|
|
147
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
148
|
+
className: "cherita-pseudospatial-toolbar",
|
|
149
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.ButtonGroup, {
|
|
150
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(MaskSet, {})
|
|
151
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.ButtonGroup, {
|
|
152
|
+
children: plotType === _constants.PSEUDOSPATIAL_PLOT_TYPES.CATEGORICAL && /*#__PURE__*/(0, _jsxRuntime.jsx)(CategoricalMode, {})
|
|
153
|
+
})]
|
|
154
|
+
});
|
|
155
|
+
}
|