@haniffalab/cherita-react 0.2.0-dev.2024-09-26.775b9a06 → 0.2.0-dev.2024-09-26.d9293c4c
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/App.scss +77 -8
- package/dist/components/Offcanvas/index.js +6 -2
- package/dist/components/dotplot/Dotplot.js +11 -0
- package/dist/components/heatmap/Heatmap.js +11 -0
- package/dist/components/matrixplot/Matrixplot.js +11 -0
- package/dist/components/obs-list/ObsItem.js +394 -0
- package/dist/components/obs-list/ObsList.js +116 -299
- package/dist/components/obs-list/ObsToolbar.js +76 -0
- package/dist/components/scatterplot/Legend.js +4 -3
- package/dist/components/scatterplot/Scatterplot.js +99 -39
- package/dist/components/scatterplot/Toolbox.js +3 -2
- package/dist/components/var-list/VarItem.js +313 -0
- package/dist/components/var-list/VarList.js +50 -148
- package/dist/components/violin/Violin.js +18 -1
- package/dist/constants/constants.js +2 -1
- package/dist/context/DatasetContext.js +10 -2
- package/dist/context/FilterContext.js +76 -0
- package/dist/helpers/map-helper.js +20 -15
- package/dist/index.js +7 -0
- package/dist/utils/VirtualizedList.js +69 -0
- package/dist/utils/requests.js +2 -2
- package/dist/utils/string.js +18 -0
- package/package.json +3 -2
- package/dist/components/obs-list/ObsValueList.js +0 -101
|
@@ -19,10 +19,12 @@ var _SpatialControls = require("./SpatialControls");
|
|
|
19
19
|
var _Toolbox = require("./Toolbox");
|
|
20
20
|
var _constants = require("../../constants/constants");
|
|
21
21
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
22
|
+
var _FilterContext = require("../../context/FilterContext");
|
|
22
23
|
var _colorHelper = require("../../helpers/color-helper");
|
|
23
24
|
var _mapHelper = require("../../helpers/map-helper");
|
|
24
25
|
var _zarrHelper = require("../../helpers/zarr-helper");
|
|
25
26
|
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
27
|
+
var _string = require("../../utils/string");
|
|
26
28
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
27
29
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
28
30
|
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); }
|
|
@@ -36,16 +38,19 @@ const INITIAL_VIEW_STATE = {
|
|
|
36
38
|
pitch: 0,
|
|
37
39
|
bearing: 0
|
|
38
40
|
};
|
|
41
|
+
const EPSILON = 1e-6;
|
|
39
42
|
function Scatterplot(_ref) {
|
|
40
|
-
var _dataset$selectedObs, _dataset$selectedObs2, _dataset$
|
|
43
|
+
var _dataset$selectedObs, _dataset$selectedObs2, _dataset$selectedObs7, _dataset$selectedObs11, _dataset$selectedObs12, _dataset$selectedObs13, _dataset$selectedObs15, _features$features2, _obsmData$serverError, _xData$serverError, _obsData$serverError, _labelObsData$serverE, _obsmData$data;
|
|
41
44
|
let {
|
|
42
45
|
radius = 30
|
|
43
46
|
} = _ref;
|
|
44
47
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
45
48
|
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
49
|
+
const filterDispatch = (0, _FilterContext.useFilteredDataDispatch)();
|
|
46
50
|
const {
|
|
47
51
|
getColor
|
|
48
52
|
} = (0, _colorHelper.useColor)();
|
|
53
|
+
const deckRef = (0, _react.useRef)(null);
|
|
49
54
|
const [viewState, setViewState] = (0, _react.useState)(INITIAL_VIEW_STATE);
|
|
50
55
|
const [isRendering, setIsRendering] = (0, _react.useState)(true);
|
|
51
56
|
const [data, setData] = (0, _react.useState)({
|
|
@@ -72,7 +77,7 @@ function Scatterplot(_ref) {
|
|
|
72
77
|
});
|
|
73
78
|
const [obsParams, setObsParams] = (0, _react.useState)({
|
|
74
79
|
url: dataset.url,
|
|
75
|
-
path: "obs/" + ((_dataset$selectedObs = dataset.selectedObs) === null || _dataset$selectedObs === void 0 ? void 0 : _dataset$selectedObs.name) + (((_dataset$selectedObs2 = dataset.selectedObs) === null || _dataset$selectedObs2 === void 0 ? void 0 : _dataset$selectedObs2.type) === _constants.OBS_TYPES.
|
|
80
|
+
path: "obs/" + ((_dataset$selectedObs = dataset.selectedObs) === null || _dataset$selectedObs === void 0 ? void 0 : _dataset$selectedObs.name) + (((_dataset$selectedObs2 = dataset.selectedObs) === null || _dataset$selectedObs2 === void 0 ? void 0 : _dataset$selectedObs2.type) === _constants.OBS_TYPES.CATEGORICAL ? "/codes" : "")
|
|
76
81
|
});
|
|
77
82
|
const [labelObsParams, setLabelObsParams] = (0, _react.useState)([]);
|
|
78
83
|
|
|
@@ -107,7 +112,7 @@ function Scatterplot(_ref) {
|
|
|
107
112
|
var _dataset$selectedObs3, _dataset$selectedObs4;
|
|
108
113
|
return {
|
|
109
114
|
...p,
|
|
110
|
-
path: "obs/" + ((_dataset$selectedObs3 = dataset.selectedObs) === null || _dataset$selectedObs3 === void 0 ? void 0 : _dataset$selectedObs3.name) + (((_dataset$selectedObs4 = dataset.selectedObs) === null || _dataset$selectedObs4 === void 0 ? void 0 : _dataset$selectedObs4.type) === _constants.OBS_TYPES.
|
|
115
|
+
path: "obs/" + ((_dataset$selectedObs3 = dataset.selectedObs) === null || _dataset$selectedObs3 === void 0 ? void 0 : _dataset$selectedObs3.name) + (((_dataset$selectedObs4 = dataset.selectedObs) === null || _dataset$selectedObs4 === void 0 ? void 0 : _dataset$selectedObs4.type) === _constants.OBS_TYPES.CATEGORICAL ? "/codes" : "")
|
|
111
116
|
};
|
|
112
117
|
});
|
|
113
118
|
}, [dataset.selectedObs]);
|
|
@@ -115,7 +120,7 @@ function Scatterplot(_ref) {
|
|
|
115
120
|
setLabelObsParams(_lodash.default.map(dataset.labelObs, obs => {
|
|
116
121
|
return {
|
|
117
122
|
url: dataset.url,
|
|
118
|
-
path: "obs/" + obs.name + (obs.type === _constants.OBS_TYPES.
|
|
123
|
+
path: "obs/" + obs.name + (obs.type === _constants.OBS_TYPES.CATEGORICAL ? "/codes" : ""),
|
|
119
124
|
key: obs.name
|
|
120
125
|
};
|
|
121
126
|
}));
|
|
@@ -145,6 +150,7 @@ function Scatterplot(_ref) {
|
|
|
145
150
|
|
|
146
151
|
(0, _react.useEffect)(() => {
|
|
147
152
|
if (!obsmData.isPending && !obsmData.serverError) {
|
|
153
|
+
var _deckRef$current, _deckRef$current2;
|
|
148
154
|
setIsRendering(true);
|
|
149
155
|
setData(d => {
|
|
150
156
|
return {
|
|
@@ -157,7 +163,10 @@ function Scatterplot(_ref) {
|
|
|
157
163
|
latitude,
|
|
158
164
|
longitude,
|
|
159
165
|
zoom
|
|
160
|
-
} = mapHelper.fitBounds(obsmData.data
|
|
166
|
+
} = mapHelper.fitBounds(obsmData.data, {
|
|
167
|
+
width: deckRef === null || deckRef === void 0 || (_deckRef$current = deckRef.current) === null || _deckRef$current === void 0 || (_deckRef$current = _deckRef$current.deck) === null || _deckRef$current === void 0 ? void 0 : _deckRef$current.width,
|
|
168
|
+
height: deckRef === null || deckRef === void 0 || (_deckRef$current2 = deckRef.current) === null || _deckRef$current2 === void 0 || (_deckRef$current2 = _deckRef$current2.deck) === null || _deckRef$current2 === void 0 ? void 0 : _deckRef$current2.height
|
|
169
|
+
});
|
|
161
170
|
setViewState(v => {
|
|
162
171
|
return {
|
|
163
172
|
...v,
|
|
@@ -176,12 +185,16 @@ function Scatterplot(_ref) {
|
|
|
176
185
|
});
|
|
177
186
|
}
|
|
178
187
|
}, [dataset.selectedObsm, obsmData.data, obsmData.isPending, obsmData.serverError]);
|
|
179
|
-
const
|
|
188
|
+
const getBounds = (0, _react.useCallback)(() => {
|
|
189
|
+
var _deckRef$current3, _deckRef$current4;
|
|
180
190
|
const {
|
|
181
191
|
latitude,
|
|
182
192
|
longitude,
|
|
183
193
|
zoom
|
|
184
|
-
} = new _mapHelper.MapHelper().fitBounds(data.positions
|
|
194
|
+
} = new _mapHelper.MapHelper().fitBounds(data.positions, {
|
|
195
|
+
width: deckRef === null || deckRef === void 0 || (_deckRef$current3 = deckRef.current) === null || _deckRef$current3 === void 0 || (_deckRef$current3 = _deckRef$current3.deck) === null || _deckRef$current3 === void 0 ? void 0 : _deckRef$current3.width,
|
|
196
|
+
height: deckRef === null || deckRef === void 0 || (_deckRef$current4 = deckRef.current) === null || _deckRef$current4 === void 0 || (_deckRef$current4 = _deckRef$current4.deck) === null || _deckRef$current4 === void 0 ? void 0 : _deckRef$current4.height
|
|
197
|
+
});
|
|
185
198
|
return {
|
|
186
199
|
latitude,
|
|
187
200
|
longitude,
|
|
@@ -247,17 +260,37 @@ function Scatterplot(_ref) {
|
|
|
247
260
|
}, [dataset.colorEncoding, obsData.data, obsData.isPending, obsData.serverError, dataset.sliceBy.obs]);
|
|
248
261
|
const isCategorical = (0, _react.useMemo)(() => {
|
|
249
262
|
if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
|
|
250
|
-
var _dataset$selectedObs5;
|
|
251
|
-
return ((_dataset$selectedObs5 = dataset.selectedObs) === null || _dataset$selectedObs5 === void 0 ? void 0 : _dataset$selectedObs5.type) === _constants.OBS_TYPES.CATEGORICAL;
|
|
263
|
+
var _dataset$selectedObs5, _dataset$selectedObs6;
|
|
264
|
+
return ((_dataset$selectedObs5 = dataset.selectedObs) === null || _dataset$selectedObs5 === void 0 ? void 0 : _dataset$selectedObs5.type) === _constants.OBS_TYPES.CATEGORICAL || ((_dataset$selectedObs6 = dataset.selectedObs) === null || _dataset$selectedObs6 === void 0 ? void 0 : _dataset$selectedObs6.type) === _constants.OBS_TYPES.BOOLEAN;
|
|
252
265
|
} else {
|
|
253
266
|
return false;
|
|
254
267
|
}
|
|
255
|
-
}, [dataset.colorEncoding, (_dataset$
|
|
268
|
+
}, [dataset.colorEncoding, (_dataset$selectedObs7 = dataset.selectedObs) === null || _dataset$selectedObs7 === void 0 ? void 0 : _dataset$selectedObs7.type]);
|
|
269
|
+
const isInBins = (v, binEdges, indices) => {
|
|
270
|
+
const lastEdge = _lodash.default.last(binEdges);
|
|
271
|
+
const allButLastEdges = _lodash.default.initial(binEdges);
|
|
272
|
+
// add epsilon to last edge to include the last value
|
|
273
|
+
const modifiedBinEdges = [...allButLastEdges, [lastEdge[0], lastEdge[1] + EPSILON]];
|
|
274
|
+
const binIndices = _lodash.default.difference(_lodash.default.range(binEdges.length), indices);
|
|
275
|
+
const ranges = _lodash.default.at(modifiedBinEdges, binIndices);
|
|
276
|
+
return _lodash.default.some(ranges, range => _lodash.default.inRange(v, ...range));
|
|
277
|
+
};
|
|
256
278
|
const isInSlice = (0, _react.useCallback)((index, values, positions) => {
|
|
279
|
+
var _dataset$selectedObs9, _dataset$selectedObs10;
|
|
257
280
|
let inSlice = true;
|
|
258
|
-
if (
|
|
259
|
-
var _dataset$
|
|
260
|
-
inSlice &= !_lodash.default.includes((_dataset$
|
|
281
|
+
if (isCategorical && values) {
|
|
282
|
+
var _dataset$selectedObs8;
|
|
283
|
+
inSlice &= !_lodash.default.includes((_dataset$selectedObs8 = dataset.selectedObs) === null || _dataset$selectedObs8 === void 0 ? void 0 : _dataset$selectedObs8.omit, values[index]);
|
|
284
|
+
} else if ((dataset.sliceBy.obs || dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && ((_dataset$selectedObs9 = dataset.selectedObs) === null || _dataset$selectedObs9 === void 0 ? void 0 : _dataset$selectedObs9.type) === _constants.OBS_TYPES.CONTINUOUS) && !!((_dataset$selectedObs10 = dataset.selectedObs) !== null && _dataset$selectedObs10 !== void 0 && _dataset$selectedObs10.omit.length) && values) {
|
|
285
|
+
if (dataset.selectedObs.type === _constants.OBS_TYPES.CATEGORICAL) {
|
|
286
|
+
inSlice &= !_lodash.default.includes(dataset.selectedObs.omit, values[index]);
|
|
287
|
+
} else if (dataset.selectedObs.type === _constants.OBS_TYPES.CONTINUOUS) {
|
|
288
|
+
if (Number.isNaN(values[index])) {
|
|
289
|
+
inSlice &= !_lodash.default.includes(dataset.selectedObs.omit, -1);
|
|
290
|
+
} else {
|
|
291
|
+
inSlice &= isInBins(values[index], dataset.selectedObs.bins.binEdges, _lodash.default.without(dataset.selectedObs.omit, -1));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
261
294
|
}
|
|
262
295
|
if (dataset.sliceBy.polygons && positions) {
|
|
263
296
|
inSlice &= _lodash.default.some(features === null || features === void 0 ? void 0 : features.features, (_f, i) => {
|
|
@@ -265,7 +298,7 @@ function Scatterplot(_ref) {
|
|
|
265
298
|
});
|
|
266
299
|
}
|
|
267
300
|
return inSlice;
|
|
268
|
-
}, [(_dataset$
|
|
301
|
+
}, [dataset.colorEncoding, (_dataset$selectedObs11 = dataset.selectedObs) === null || _dataset$selectedObs11 === void 0 || (_dataset$selectedObs11 = _dataset$selectedObs11.bins) === null || _dataset$selectedObs11 === void 0 ? void 0 : _dataset$selectedObs11.binEdges, (_dataset$selectedObs12 = dataset.selectedObs) === null || _dataset$selectedObs12 === void 0 ? void 0 : _dataset$selectedObs12.omit, (_dataset$selectedObs13 = dataset.selectedObs) === null || _dataset$selectedObs13 === void 0 ? void 0 : _dataset$selectedObs13.type, dataset.sliceBy.obs, dataset.sliceBy.polygons, features.features, isCategorical]);
|
|
269
302
|
const {
|
|
270
303
|
filteredIndices,
|
|
271
304
|
valueMin,
|
|
@@ -293,8 +326,8 @@ function Scatterplot(_ref) {
|
|
|
293
326
|
slicedLength: filtered.length
|
|
294
327
|
};
|
|
295
328
|
} else if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
|
|
296
|
-
var _dataset$
|
|
297
|
-
const isContinuous = ((_dataset$
|
|
329
|
+
var _dataset$selectedObs14;
|
|
330
|
+
const isContinuous = ((_dataset$selectedObs14 = dataset.selectedObs) === null || _dataset$selectedObs14 === void 0 ? void 0 : _dataset$selectedObs14.type) === _constants.OBS_TYPES.CONTINUOUS;
|
|
298
331
|
const {
|
|
299
332
|
filtered,
|
|
300
333
|
filteredIndices
|
|
@@ -322,7 +355,13 @@ function Scatterplot(_ref) {
|
|
|
322
355
|
slicedLength: data.values.length
|
|
323
356
|
};
|
|
324
357
|
}
|
|
325
|
-
}, [data.positions, data.sliceValues, data.values, dataset.colorEncoding, (_dataset$
|
|
358
|
+
}, [data.positions, data.sliceValues, data.values, dataset.colorEncoding, (_dataset$selectedObs15 = dataset.selectedObs) === null || _dataset$selectedObs15 === void 0 ? void 0 : _dataset$selectedObs15.type, isInSlice]);
|
|
359
|
+
(0, _react.useEffect)(() => {
|
|
360
|
+
filterDispatch({
|
|
361
|
+
type: "set.obs.indices",
|
|
362
|
+
indices: dataset.sliceBy.obs || dataset.sliceBy.polygons ? filteredIndices : null
|
|
363
|
+
});
|
|
364
|
+
}, [dataset.sliceBy.obs, dataset.sliceBy.polygons, filterDispatch, filteredIndices]);
|
|
326
365
|
(0, _react.useEffect)(() => {
|
|
327
366
|
dispatch({
|
|
328
367
|
type: "set.controls.valueRange",
|
|
@@ -408,20 +447,40 @@ function Scatterplot(_ref) {
|
|
|
408
447
|
}
|
|
409
448
|
setSelectedFeatureIndexes(f => info.object ? info.layer.id === "cherita-layer-draw" ? [info.index] : f : []);
|
|
410
449
|
}
|
|
450
|
+
const getLabel = function (o, v) {
|
|
451
|
+
let isVar = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
|
|
452
|
+
if (isVar || o.type === _constants.OBS_TYPES.CONTINUOUS) {
|
|
453
|
+
return "".concat(o.name, ": ").concat((0, _string.prettyNumerical)(parseFloat(v)));
|
|
454
|
+
} else {
|
|
455
|
+
return "".concat(o.name, ": ").concat(o.codesMap[v]);
|
|
456
|
+
}
|
|
457
|
+
};
|
|
411
458
|
const getTooltip = _ref4 => {
|
|
412
459
|
let {
|
|
413
460
|
object,
|
|
414
461
|
index
|
|
415
462
|
} = _ref4;
|
|
416
|
-
|
|
417
|
-
|
|
463
|
+
if (!object) return;
|
|
464
|
+
const text = [];
|
|
465
|
+
if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && dataset.selectedObs && !_lodash.default.some(dataset.labelObs, {
|
|
466
|
+
name: dataset.selectedObs.name
|
|
467
|
+
})) {
|
|
468
|
+
var _obsData$data;
|
|
469
|
+
text.push(getLabel(dataset.selectedObs, (_obsData$data = obsData.data) === null || _obsData$data === void 0 ? void 0 : _obsData$data[index]));
|
|
470
|
+
}
|
|
471
|
+
if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR && dataset.selectedVar) {
|
|
472
|
+
var _xData$data;
|
|
473
|
+
text.push(getLabel(dataset.selectedVar, (_xData$data = xData.data) === null || _xData$data === void 0 ? void 0 : _xData$data[index], true));
|
|
474
|
+
}
|
|
475
|
+
if (dataset.labelObs.length) {
|
|
476
|
+
text.push(..._lodash.default.map(labelObsData, (v, k) => {
|
|
418
477
|
const labelObs = _lodash.default.find(dataset.labelObs, o => o.name === k);
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
478
|
+
return getLabel(labelObs, v[index]);
|
|
479
|
+
}));
|
|
480
|
+
}
|
|
481
|
+
if (!text.length) return;
|
|
482
|
+
return {
|
|
483
|
+
text: text.length ? _lodash.default.compact(text).join("\n") : null
|
|
425
484
|
};
|
|
426
485
|
};
|
|
427
486
|
const isPending = (isRendering || xData.isPending || obsmData.isPending) && !obsmData.isPending;
|
|
@@ -448,14 +507,15 @@ function Scatterplot(_ref) {
|
|
|
448
507
|
isDragging
|
|
449
508
|
} = _ref5;
|
|
450
509
|
return mode !== _editModes.ViewMode ? "crosshair" : isDragging ? "grabbing" : "grab";
|
|
451
|
-
}
|
|
510
|
+
},
|
|
511
|
+
ref: deckRef
|
|
452
512
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpatialControls.SpatialControls, {
|
|
453
513
|
mode: mode,
|
|
454
514
|
setMode: setMode,
|
|
455
515
|
features: features,
|
|
456
516
|
setFeatures: setFeatures,
|
|
457
517
|
selectedFeatureIndexes: selectedFeatureIndexes,
|
|
458
|
-
resetBounds: () => setViewState(
|
|
518
|
+
resetBounds: () => setViewState(getBounds()),
|
|
459
519
|
increaseZoom: () => setViewState(v => ({
|
|
460
520
|
...v,
|
|
461
521
|
zoom: v.zoom + 1
|
|
@@ -464,20 +524,20 @@ function Scatterplot(_ref) {
|
|
|
464
524
|
...v,
|
|
465
525
|
zoom: v.zoom - 1
|
|
466
526
|
}))
|
|
467
|
-
}), error && !isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
468
|
-
className: "cherita-alert",
|
|
469
|
-
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Alert, {
|
|
470
|
-
variant: "danger",
|
|
471
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFontawesome.FontAwesomeIcon, {
|
|
472
|
-
icon: _freeSolidSvgIcons.faTriangleExclamation
|
|
473
|
-
}), "Error loading data"]
|
|
474
|
-
})
|
|
475
527
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
476
528
|
className: "cherita-spatial-footer",
|
|
477
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
529
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
530
|
+
className: "cherita-toolbox-footer",
|
|
531
|
+
children: [error && !isPending && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Alert, {
|
|
532
|
+
variant: "danger",
|
|
533
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFontawesome.FontAwesomeIcon, {
|
|
534
|
+
icon: _freeSolidSvgIcons.faTriangleExclamation
|
|
535
|
+
}), "\xA0Error loading data"]
|
|
536
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbox.Toolbox, {
|
|
537
|
+
mode: dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? dataset.selectedVar.name : dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS ? dataset.selectedObs.name : null,
|
|
538
|
+
obsLength: parseInt((_obsmData$data = obsmData.data) === null || _obsmData$data === void 0 ? void 0 : _obsmData$data.length),
|
|
539
|
+
slicedLength: parseInt(slicedLength)
|
|
540
|
+
})]
|
|
481
541
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Legend.Legend, {
|
|
482
542
|
isCategorical: isCategorical,
|
|
483
543
|
min: min,
|
|
@@ -9,6 +9,7 @@ var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
|
|
|
9
9
|
var _reactFontawesome = require("@fortawesome/react-fontawesome");
|
|
10
10
|
var _Button = _interopRequireDefault(require("react-bootstrap/Button"));
|
|
11
11
|
var _ButtonGroup = _interopRequireDefault(require("react-bootstrap/ButtonGroup"));
|
|
12
|
+
var _string = require("../../utils/string");
|
|
12
13
|
var _ObsmList = require("../obsm-list/ObsmList");
|
|
13
14
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
14
15
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -28,10 +29,10 @@ function Toolbox(_ref) {
|
|
|
28
29
|
}), " ", mode]
|
|
29
30
|
}), (mode || !Number.isNaN(obsLength)) && (mode !== null && !Number.isNaN(slicedLength) && slicedLength !== obsLength ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Button.default, {
|
|
30
31
|
size: "sm",
|
|
31
|
-
children: [
|
|
32
|
+
children: [(0, _string.prettyNumerical)(slicedLength), " out of", " ", (0, _string.prettyNumerical)(obsLength), " cells"]
|
|
32
33
|
}) : /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Button.default, {
|
|
33
34
|
size: "sm",
|
|
34
|
-
children: [
|
|
35
|
+
children: [(0, _string.prettyNumerical)(obsLength), " cells"]
|
|
35
36
|
}))]
|
|
36
37
|
})
|
|
37
38
|
});
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.VarItem = VarItem;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
|
|
9
|
+
var _reactFontawesome = require("@fortawesome/react-fontawesome");
|
|
10
|
+
var _iconsMaterial = require("@mui/icons-material");
|
|
11
|
+
var _xCharts = require("@mui/x-charts");
|
|
12
|
+
var _colorPalettes = require("@mui/x-charts/colorPalettes");
|
|
13
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
14
|
+
var _reactBootstrap = require("react-bootstrap");
|
|
15
|
+
var _constants = require("../../constants/constants");
|
|
16
|
+
var _DatasetContext = require("../../context/DatasetContext");
|
|
17
|
+
var _FilterContext = require("../../context/FilterContext");
|
|
18
|
+
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
19
|
+
var _requests = require("../../utils/requests");
|
|
20
|
+
var _string = require("../../utils/string");
|
|
21
|
+
var _VirtualizedList = require("../../utils/VirtualizedList");
|
|
22
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
23
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
24
|
+
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); }
|
|
25
|
+
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; }
|
|
26
|
+
function VarHistogram(_ref) {
|
|
27
|
+
var _fetchedData$bin_edge;
|
|
28
|
+
let {
|
|
29
|
+
item
|
|
30
|
+
} = _ref;
|
|
31
|
+
const ENDPOINT = "var/histograms";
|
|
32
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
33
|
+
const filteredData = (0, _FilterContext.useFilteredData)();
|
|
34
|
+
const isSliced = dataset.sliceBy.obs || dataset.sliceBy.polygons;
|
|
35
|
+
const [params, setParams] = (0, _react.useState)({
|
|
36
|
+
url: dataset.url,
|
|
37
|
+
var_index: item.matrix_index,
|
|
38
|
+
obs_indices: isSliced && Array.from(filteredData.obsIndices || [])
|
|
39
|
+
});
|
|
40
|
+
(0, _react.useEffect)(() => {
|
|
41
|
+
setParams(p => {
|
|
42
|
+
return {
|
|
43
|
+
...p,
|
|
44
|
+
obs_indices: isSliced && Array.from(filteredData.obsIndices || [])
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
}, [filteredData.obsIndices, isSliced]);
|
|
48
|
+
const {
|
|
49
|
+
fetchedData,
|
|
50
|
+
isPending,
|
|
51
|
+
serverError
|
|
52
|
+
} = (0, _requests.useDebouncedFetch)(ENDPOINT, params, {
|
|
53
|
+
refetchOnMount: false
|
|
54
|
+
});
|
|
55
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
56
|
+
className: "feature-histogram-container m-2",
|
|
57
|
+
children: isPending ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingLinear, {}) : !serverError && fetchedData ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
58
|
+
className: "feature-histogram",
|
|
59
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_xCharts.SparkLineChart, {
|
|
60
|
+
plotType: "bar",
|
|
61
|
+
data: fetchedData.log10,
|
|
62
|
+
margin: {
|
|
63
|
+
top: 0,
|
|
64
|
+
right: 0,
|
|
65
|
+
bottom: 0,
|
|
66
|
+
left: 0
|
|
67
|
+
},
|
|
68
|
+
colors: isSliced ? _colorPalettes.mangoFusionPalette : _colorPalettes.blueberryTwilightPalette,
|
|
69
|
+
showHighlight: true,
|
|
70
|
+
showTooltip: true,
|
|
71
|
+
valueFormatter: (v, _ref2) => {
|
|
72
|
+
let {
|
|
73
|
+
dataIndex
|
|
74
|
+
} = _ref2;
|
|
75
|
+
return "".concat((0, _string.prettyNumerical)(fetchedData.hist[dataIndex]));
|
|
76
|
+
},
|
|
77
|
+
xAxis: {
|
|
78
|
+
data: _lodash.default.range((_fetchedData$bin_edge = fetchedData.bin_edges) === null || _fetchedData$bin_edge === void 0 ? void 0 : _fetchedData$bin_edge.length) || null,
|
|
79
|
+
valueFormatter: v => "Bin [".concat((0, _string.prettyNumerical)(fetchedData.bin_edges[v][0]), ", ").concat((0, _string.prettyNumerical)(fetchedData.bin_edges[v][1])).concat(v === fetchedData.bin_edges.length - 1 ? "]" : ")")
|
|
80
|
+
},
|
|
81
|
+
slotProps: {
|
|
82
|
+
popper: {
|
|
83
|
+
className: "feature-histogram-tooltip"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
}) : null
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function VarDiseaseInfoItem(item) {
|
|
91
|
+
var _item$metadata;
|
|
92
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.ListGroup.Item, {
|
|
93
|
+
className: "feature-disease-info",
|
|
94
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
95
|
+
children: [item.disease_name, " ", /*#__PURE__*/(0, _jsxRuntime.jsx)("br", {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Table, {
|
|
96
|
+
striped: true,
|
|
97
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("tbody", {
|
|
98
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("tr", {
|
|
99
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("td", {
|
|
100
|
+
children: "Confidence"
|
|
101
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("td", {
|
|
102
|
+
children: item.confidence || "unknown"
|
|
103
|
+
})]
|
|
104
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("tr", {
|
|
105
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("td", {
|
|
106
|
+
children: ["Organ", item.organs.length > 1 ? "s" : ""]
|
|
107
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("td", {
|
|
108
|
+
children: item.organs.map(o => o.name).join(", ")
|
|
109
|
+
})]
|
|
110
|
+
}), !!((_item$metadata = item.metadata) !== null && _item$metadata !== void 0 && _item$metadata.length) && item.metadata.map(m => {
|
|
111
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("tr", {
|
|
112
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("td", {
|
|
113
|
+
children: m.key
|
|
114
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("td", {
|
|
115
|
+
children: m.value
|
|
116
|
+
})]
|
|
117
|
+
});
|
|
118
|
+
})]
|
|
119
|
+
})
|
|
120
|
+
})]
|
|
121
|
+
})
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function VarDiseaseInfo(_ref3) {
|
|
125
|
+
let {
|
|
126
|
+
data
|
|
127
|
+
} = _ref3;
|
|
128
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
129
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.ListGroup, {
|
|
130
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_VirtualizedList.VirtualizedList, {
|
|
131
|
+
getDataAtIndex: index => data[index],
|
|
132
|
+
count: data.length,
|
|
133
|
+
estimateSize: 70,
|
|
134
|
+
maxHeight: "40vh",
|
|
135
|
+
ItemComponent: VarDiseaseInfoItem
|
|
136
|
+
})
|
|
137
|
+
})
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function SingleSelectionItem(_ref4) {
|
|
141
|
+
let {
|
|
142
|
+
item,
|
|
143
|
+
isActive,
|
|
144
|
+
selectVar,
|
|
145
|
+
removeVar,
|
|
146
|
+
isDiseaseGene
|
|
147
|
+
} = _ref4;
|
|
148
|
+
const ENDPOINT = "disease/gene";
|
|
149
|
+
const [openInfo, setOpenInfo] = (0, _react.useState)(false);
|
|
150
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
151
|
+
const params = {
|
|
152
|
+
geneName: item.name,
|
|
153
|
+
diseaseDatasets: dataset.diseaseDatasets
|
|
154
|
+
};
|
|
155
|
+
const isNotInData = item.matrix_index === -1;
|
|
156
|
+
const {
|
|
157
|
+
fetchedData,
|
|
158
|
+
isPending,
|
|
159
|
+
serverError
|
|
160
|
+
} = (0, _requests.useFetch)(ENDPOINT, params);
|
|
161
|
+
const hasDiseaseInfo = !isPending && !serverError && !!fetchedData.length;
|
|
162
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
163
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
164
|
+
className: "d-flex justify-content-between ".concat(hasDiseaseInfo ? "cursor-pointer" : ""),
|
|
165
|
+
onClick: () => {
|
|
166
|
+
setOpenInfo(o => !o);
|
|
167
|
+
},
|
|
168
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
169
|
+
className: "d-flex justify-content-between align-items-center w-100",
|
|
170
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
171
|
+
children: item.name
|
|
172
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
173
|
+
className: "d-flex align-items-center gap-1",
|
|
174
|
+
children: [hasDiseaseInfo && /*#__PURE__*/(0, _jsxRuntime.jsx)(_iconsMaterial.MoreVert, {}), !isDiseaseGene && /*#__PURE__*/(0, _jsxRuntime.jsx)(VarHistogram, {
|
|
175
|
+
item: item
|
|
176
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Button, {
|
|
177
|
+
type: "button",
|
|
178
|
+
variant: isActive ? "primary" : isNotInData ? "outline-secondary" : "outline-primary",
|
|
179
|
+
className: "m-0 p-0 px-1",
|
|
180
|
+
onClick: e => {
|
|
181
|
+
e.stopPropagation();
|
|
182
|
+
selectVar();
|
|
183
|
+
},
|
|
184
|
+
disabled: isNotInData,
|
|
185
|
+
title: isNotInData ? "Not present in data" : "Set as color encoding",
|
|
186
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFontawesome.FontAwesomeIcon, {
|
|
187
|
+
icon: _freeSolidSvgIcons.faDroplet
|
|
188
|
+
})
|
|
189
|
+
}, item.matrix_index), !isDiseaseGene && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Button, {
|
|
190
|
+
type: "button",
|
|
191
|
+
className: "m-0 p-0 px-1",
|
|
192
|
+
variant: "outline-secondary",
|
|
193
|
+
title: "Remove from list",
|
|
194
|
+
onClick: e => {
|
|
195
|
+
e.stopPropagation();
|
|
196
|
+
removeVar();
|
|
197
|
+
},
|
|
198
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactFontawesome.FontAwesomeIcon, {
|
|
199
|
+
icon: _freeSolidSvgIcons.faTrash
|
|
200
|
+
})
|
|
201
|
+
})]
|
|
202
|
+
})]
|
|
203
|
+
})
|
|
204
|
+
}), hasDiseaseInfo && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Collapse, {
|
|
205
|
+
in: openInfo,
|
|
206
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
207
|
+
className: "mt-2",
|
|
208
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(VarDiseaseInfo, {
|
|
209
|
+
data: fetchedData
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
})]
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function MultipleSelectionItem(_ref5) {
|
|
216
|
+
let {
|
|
217
|
+
item,
|
|
218
|
+
isActive,
|
|
219
|
+
toggleVar
|
|
220
|
+
} = _ref5;
|
|
221
|
+
const isNotInData = item.matrix_index === -1;
|
|
222
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
|
|
223
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
224
|
+
className: "d-flex",
|
|
225
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
226
|
+
className: "flex-grow-1",
|
|
227
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Button, {
|
|
228
|
+
type: "button",
|
|
229
|
+
variant: isActive ? "primary" : "outline-primary",
|
|
230
|
+
className: "m-0 p-0 px-1",
|
|
231
|
+
onClick: toggleVar,
|
|
232
|
+
disabled: isNotInData,
|
|
233
|
+
title: isNotInData ? "Not present in data" : "",
|
|
234
|
+
children: item.name
|
|
235
|
+
}, item.matrix_index)
|
|
236
|
+
})
|
|
237
|
+
})
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
function VarItem(_ref6) {
|
|
241
|
+
let {
|
|
242
|
+
item,
|
|
243
|
+
active,
|
|
244
|
+
setVarButtons,
|
|
245
|
+
mode = _constants.SELECTION_MODES.SINGLE,
|
|
246
|
+
isDiseaseGene = false
|
|
247
|
+
} = _ref6;
|
|
248
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
249
|
+
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
250
|
+
const selectVar = v => {
|
|
251
|
+
if (mode === _constants.SELECTION_MODES.SINGLE) {
|
|
252
|
+
dispatch({
|
|
253
|
+
type: "select.var",
|
|
254
|
+
var: v
|
|
255
|
+
});
|
|
256
|
+
dispatch({
|
|
257
|
+
type: "set.colorEncoding",
|
|
258
|
+
value: "var"
|
|
259
|
+
});
|
|
260
|
+
} else if (mode === _constants.SELECTION_MODES.MULTIPLE) {
|
|
261
|
+
dispatch({
|
|
262
|
+
type: "select.multivar",
|
|
263
|
+
var: v
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
const removeVar = v => {
|
|
268
|
+
setVarButtons(b => {
|
|
269
|
+
return b.filter(i => i.name !== v.name);
|
|
270
|
+
});
|
|
271
|
+
if (mode === _constants.SELECTION_MODES.SINGLE) {
|
|
272
|
+
if (active === v.matrix_index) {
|
|
273
|
+
dispatch({
|
|
274
|
+
type: "deselect.var"
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
} else if (mode === _constants.SELECTION_MODES.MULTIPLE) {
|
|
278
|
+
if (active.includes(v.matrix_index)) {
|
|
279
|
+
dispatch({
|
|
280
|
+
type: "deselect.multivar",
|
|
281
|
+
var: v
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
const toggleVar = v => {
|
|
287
|
+
if (active.includes(v.matrix_index)) {
|
|
288
|
+
dispatch({
|
|
289
|
+
type: "deselect.multivar",
|
|
290
|
+
var: v
|
|
291
|
+
});
|
|
292
|
+
} else {
|
|
293
|
+
selectVar(v);
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
if (item && mode === _constants.SELECTION_MODES.SINGLE) {
|
|
297
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(SingleSelectionItem, {
|
|
298
|
+
item: item,
|
|
299
|
+
isActive: dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR && active === item.matrix_index,
|
|
300
|
+
selectVar: () => selectVar(item),
|
|
301
|
+
removeVar: () => removeVar(item),
|
|
302
|
+
isDiseaseGene: isDiseaseGene
|
|
303
|
+
});
|
|
304
|
+
} else if (mode === _constants.SELECTION_MODES.MULTIPLE) {
|
|
305
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(MultipleSelectionItem, {
|
|
306
|
+
item: item,
|
|
307
|
+
isActive: item.matrix_index !== -1 && _lodash.default.includes(active, item.matrix_index),
|
|
308
|
+
toggleVar: () => toggleVar(item)
|
|
309
|
+
});
|
|
310
|
+
} else {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
}
|