@haniffalab/cherita-react 0.2.0-dev.2024-05-22.5ce64346 → 0.2.0-dev.2024-09-26.f9979478
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 +58 -24
- package/dist/components/Offcanvas/index.js +9 -6
- package/dist/components/dotplot/Dotplot.js +5 -189
- package/dist/components/dotplot/DotplotControls.js +197 -0
- package/dist/components/heatmap/Heatmap.js +5 -31
- package/dist/components/heatmap/HeatmapControls.js +36 -0
- package/dist/components/matrixplot/Matrixplot.js +5 -59
- package/dist/components/matrixplot/MatrixplotControls.js +65 -0
- package/dist/components/obs-list/ObsList.js +231 -113
- package/dist/components/obs-list/ObsValueList.js +101 -0
- package/dist/components/obsm-list/ObsmList.js +13 -20
- package/dist/components/scatterplot/Legend.js +28 -36
- package/dist/components/scatterplot/Scatterplot.js +302 -124
- package/dist/components/scatterplot/ScatterplotControls.js +93 -0
- package/dist/components/scatterplot/SpatialControls.js +68 -17
- package/dist/components/scatterplot/Toolbox.js +14 -18
- package/dist/components/search-bar/SearchBar.js +2 -2
- package/dist/components/search-bar/SearchResults.js +2 -2
- package/dist/components/var-list/VarList.js +51 -24
- package/dist/components/violin/Violin.js +7 -46
- package/dist/components/violin/ViolinControls.js +50 -0
- package/dist/constants/colorscales.js +28 -0
- package/dist/constants/constants.js +11 -43
- package/dist/context/DatasetContext.js +122 -23
- package/dist/helpers/color-helper.js +54 -21
- package/dist/helpers/zarr-helper.js +39 -17
- package/dist/index.js +17 -11
- package/dist/utils/LoadingIndicators.js +33 -0
- package/dist/utils/requests.js +1 -1
- package/dist/utils/search.js +4 -3
- package/package.json +10 -4
- package/dist/utils/LoadingSpinner.js +0 -44
|
@@ -4,52 +4,30 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.Scatterplot = Scatterplot;
|
|
7
|
-
exports.ScatterplotControls = ScatterplotControls;
|
|
8
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
-
var _lodash = _interopRequireDefault(require("lodash"));
|
|
10
|
-
require("bootstrap/dist/css/bootstrap.min.css");
|
|
11
|
-
var _react2 = _interopRequireDefault(require("@deck.gl/react"));
|
|
12
8
|
var _layers = require("@deck.gl/layers");
|
|
13
|
-
var
|
|
9
|
+
var _react2 = require("@deck.gl/react");
|
|
10
|
+
var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
|
|
11
|
+
var _reactFontawesome = require("@fortawesome/react-fontawesome");
|
|
14
12
|
var _editModes = require("@nebula.gl/edit-modes");
|
|
15
|
-
var
|
|
16
|
-
var
|
|
17
|
-
var
|
|
13
|
+
var _layers2 = require("@nebula.gl/layers");
|
|
14
|
+
var _turf = require("@turf/turf");
|
|
15
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
16
|
+
var _reactBootstrap = require("react-bootstrap");
|
|
18
17
|
var _Legend = require("./Legend");
|
|
18
|
+
var _SpatialControls = require("./SpatialControls");
|
|
19
|
+
var _Toolbox = require("./Toolbox");
|
|
19
20
|
var _constants = require("../../constants/constants");
|
|
20
21
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
22
|
+
var _colorHelper = require("../../helpers/color-helper");
|
|
21
23
|
var _mapHelper = require("../../helpers/map-helper");
|
|
22
24
|
var _zarrHelper = require("../../helpers/zarr-helper");
|
|
23
|
-
var
|
|
24
|
-
var _LoadingSpinner = require("../../utils/LoadingSpinner");
|
|
25
|
+
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
25
26
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
26
|
-
function _interopRequireDefault(
|
|
27
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
27
28
|
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); }
|
|
28
|
-
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 &&
|
|
29
|
+
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; }
|
|
29
30
|
window.deck.log.level = 1;
|
|
30
|
-
function ScatterplotControls() {
|
|
31
|
-
const dataset = (0, _DatasetContext.useDataset)();
|
|
32
|
-
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
33
|
-
const colormapList = _constants.PLOTLY_COLORSCALES.map(item => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default.Item, {
|
|
34
|
-
active: dataset.controls.colorScale === item,
|
|
35
|
-
onClick: () => {
|
|
36
|
-
dispatch({
|
|
37
|
-
type: "set.controls.colorScale",
|
|
38
|
-
colorScale: item
|
|
39
|
-
});
|
|
40
|
-
},
|
|
41
|
-
children: item
|
|
42
|
-
}, item));
|
|
43
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Dropdown.default, {
|
|
44
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default.Toggle, {
|
|
45
|
-
id: "dropdownColorscale",
|
|
46
|
-
variant: "light",
|
|
47
|
-
children: dataset.controls.colorScale
|
|
48
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default.Menu, {
|
|
49
|
-
children: colormapList
|
|
50
|
-
})]
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
31
|
const INITIAL_VIEW_STATE = {
|
|
54
32
|
longitude: 0,
|
|
55
33
|
latitude: 0,
|
|
@@ -58,31 +36,32 @@ const INITIAL_VIEW_STATE = {
|
|
|
58
36
|
pitch: 0,
|
|
59
37
|
bearing: 0
|
|
60
38
|
};
|
|
61
|
-
const DEFAULT_DATA_POINT = {
|
|
62
|
-
value: null,
|
|
63
|
-
position: null,
|
|
64
|
-
color: null
|
|
65
|
-
};
|
|
66
39
|
function Scatterplot(_ref) {
|
|
67
|
-
var _dataset$selectedObs;
|
|
40
|
+
var _dataset$selectedObs, _dataset$selectedObs2, _dataset$selectedObs6, _dataset$selectedObs8, _dataset$selectedObs10, _features$features2, _obsmData$serverError, _xData$serverError, _obsData$serverError, _labelObsData$serverE, _obsmData$data;
|
|
68
41
|
let {
|
|
69
42
|
radius = 30
|
|
70
43
|
} = _ref;
|
|
71
44
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
45
|
+
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
72
46
|
const {
|
|
73
|
-
getScale,
|
|
74
47
|
getColor
|
|
75
48
|
} = (0, _colorHelper.useColor)();
|
|
76
49
|
const [viewState, setViewState] = (0, _react.useState)(INITIAL_VIEW_STATE);
|
|
50
|
+
const [isRendering, setIsRendering] = (0, _react.useState)(true);
|
|
51
|
+
const [data, setData] = (0, _react.useState)({
|
|
52
|
+
ids: [],
|
|
53
|
+
positions: [],
|
|
54
|
+
values: [],
|
|
55
|
+
sliceValues: []
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// EditableGeoJsonLayer
|
|
59
|
+
const [mode, setMode] = (0, _react.useState)(() => _editModes.ViewMode);
|
|
77
60
|
const [features, setFeatures] = (0, _react.useState)({
|
|
78
61
|
type: "FeatureCollection",
|
|
79
62
|
features: []
|
|
80
63
|
});
|
|
81
|
-
const [mode, setMode] = (0, _react.useState)(() => _editModes.ViewMode);
|
|
82
64
|
const [selectedFeatureIndexes, setSelectedFeatureIndexes] = (0, _react.useState)([]);
|
|
83
|
-
const [featureState, setFeatureState] = (0, _react.useState)([]);
|
|
84
|
-
const [scale, setScale] = (0, _react.useState)(() => getScale());
|
|
85
|
-
const [data, setData] = (0, _react.useState)([]);
|
|
86
65
|
const [obsmParams, setObsmParams] = (0, _react.useState)({
|
|
87
66
|
url: dataset.url,
|
|
88
67
|
path: "obsm/" + dataset.selectedObsm
|
|
@@ -93,8 +72,9 @@ function Scatterplot(_ref) {
|
|
|
93
72
|
});
|
|
94
73
|
const [obsParams, setObsParams] = (0, _react.useState)({
|
|
95
74
|
url: dataset.url,
|
|
96
|
-
path: "obs/" + ((_dataset$selectedObs = dataset.selectedObs) === null || _dataset$selectedObs === void 0 ? void 0 : _dataset$selectedObs.name) + "/codes"
|
|
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.CONTINUOUS ? "" : "/codes")
|
|
97
76
|
});
|
|
77
|
+
const [labelObsParams, setLabelObsParams] = (0, _react.useState)([]);
|
|
98
78
|
|
|
99
79
|
// needs to be wrapped in useMemo as it is an array an could cause an infinite loop otherwise
|
|
100
80
|
const xSelection = (0, _react.useMemo)(() => {
|
|
@@ -104,6 +84,7 @@ function Scatterplot(_ref) {
|
|
|
104
84
|
const obsmData = (0, _zarrHelper.useZarr)(obsmParams, null, _zarrHelper.GET_OPTIONS);
|
|
105
85
|
const xData = (0, _zarrHelper.useZarr)(xParams, xSelection, _zarrHelper.GET_OPTIONS);
|
|
106
86
|
const obsData = (0, _zarrHelper.useZarr)(obsParams, null, _zarrHelper.GET_OPTIONS);
|
|
87
|
+
const labelObsData = (0, _zarrHelper.useMultipleZarr)(labelObsParams, _zarrHelper.GET_OPTIONS);
|
|
107
88
|
(0, _react.useEffect)(() => {
|
|
108
89
|
setObsmParams(p => {
|
|
109
90
|
return {
|
|
@@ -123,13 +104,22 @@ function Scatterplot(_ref) {
|
|
|
123
104
|
}, [dataset.selectedVar]);
|
|
124
105
|
(0, _react.useEffect)(() => {
|
|
125
106
|
setObsParams(p => {
|
|
126
|
-
var _dataset$
|
|
107
|
+
var _dataset$selectedObs3, _dataset$selectedObs4;
|
|
127
108
|
return {
|
|
128
109
|
...p,
|
|
129
|
-
path: "obs/" + ((_dataset$
|
|
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.CONTINUOUS ? "" : "/codes")
|
|
130
111
|
};
|
|
131
112
|
});
|
|
132
113
|
}, [dataset.selectedObs]);
|
|
114
|
+
(0, _react.useEffect)(() => {
|
|
115
|
+
setLabelObsParams(_lodash.default.map(dataset.labelObs, obs => {
|
|
116
|
+
return {
|
|
117
|
+
url: dataset.url,
|
|
118
|
+
path: "obs/" + obs.name + (obs.type === _constants.OBS_TYPES.CONTINUOUS ? "" : "/codes"),
|
|
119
|
+
key: obs.name
|
|
120
|
+
};
|
|
121
|
+
}));
|
|
122
|
+
}, [dataset.labelObs, dataset.url]);
|
|
133
123
|
(0, _react.useEffect)(() => {
|
|
134
124
|
setObsmParams(p => {
|
|
135
125
|
return {
|
|
@@ -155,12 +145,12 @@ function Scatterplot(_ref) {
|
|
|
155
145
|
|
|
156
146
|
(0, _react.useEffect)(() => {
|
|
157
147
|
if (!obsmData.isPending && !obsmData.serverError) {
|
|
148
|
+
setIsRendering(true);
|
|
158
149
|
setData(d => {
|
|
159
|
-
return
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
});
|
|
150
|
+
return {
|
|
151
|
+
...d,
|
|
152
|
+
positions: obsmData.data
|
|
153
|
+
};
|
|
164
154
|
});
|
|
165
155
|
const mapHelper = new _mapHelper.MapHelper();
|
|
166
156
|
const {
|
|
@@ -177,134 +167,322 @@ function Scatterplot(_ref) {
|
|
|
177
167
|
};
|
|
178
168
|
});
|
|
179
169
|
} else if (!obsmData.isPending && obsmData.serverError) {
|
|
170
|
+
setIsRendering(true);
|
|
180
171
|
setData(d => {
|
|
181
|
-
return
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
});
|
|
172
|
+
return {
|
|
173
|
+
...d,
|
|
174
|
+
positions: []
|
|
175
|
+
};
|
|
186
176
|
});
|
|
187
177
|
}
|
|
188
178
|
}, [dataset.selectedObsm, obsmData.data, obsmData.isPending, obsmData.serverError]);
|
|
179
|
+
const bounds = (0, _react.useMemo)(() => {
|
|
180
|
+
const {
|
|
181
|
+
latitude,
|
|
182
|
+
longitude,
|
|
183
|
+
zoom
|
|
184
|
+
} = new _mapHelper.MapHelper().fitBounds(data.positions);
|
|
185
|
+
return {
|
|
186
|
+
latitude,
|
|
187
|
+
longitude,
|
|
188
|
+
zoom
|
|
189
|
+
};
|
|
190
|
+
}, [data.positions]);
|
|
189
191
|
(0, _react.useEffect)(() => {
|
|
190
|
-
if (dataset.colorEncoding ===
|
|
192
|
+
if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR) {
|
|
193
|
+
setIsRendering(true);
|
|
191
194
|
if (!xData.isPending && !xData.serverError) {
|
|
192
|
-
|
|
193
|
-
setScale(() => s);
|
|
195
|
+
// @TODO: add condition to check obs slicing
|
|
194
196
|
setData(d => {
|
|
195
|
-
return
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}, d === null || d === void 0 ? void 0 : d[index], DEFAULT_DATA_POINT);
|
|
200
|
-
});
|
|
197
|
+
return {
|
|
198
|
+
...d,
|
|
199
|
+
values: xData.data
|
|
200
|
+
};
|
|
201
201
|
});
|
|
202
202
|
} else if (!xData.isPending && xData.serverError) {
|
|
203
|
-
const s = getScale();
|
|
204
|
-
setScale(() => s);
|
|
205
203
|
setData(d => {
|
|
206
|
-
return
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
}, e, DEFAULT_DATA_POINT);
|
|
211
|
-
});
|
|
204
|
+
return {
|
|
205
|
+
...d,
|
|
206
|
+
values: []
|
|
207
|
+
};
|
|
212
208
|
});
|
|
213
209
|
}
|
|
214
210
|
}
|
|
215
|
-
}, [dataset.colorEncoding, xData.data, xData.isPending, xData.serverError,
|
|
211
|
+
}, [dataset.colorEncoding, xData.data, xData.isPending, xData.serverError, getColor]);
|
|
216
212
|
(0, _react.useEffect)(() => {
|
|
217
|
-
if (dataset.colorEncoding ===
|
|
213
|
+
if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
|
|
214
|
+
setIsRendering(true);
|
|
218
215
|
if (!obsData.isPending && !obsData.serverError) {
|
|
219
|
-
const s = getScale(obsData.data);
|
|
220
|
-
setScale(() => s);
|
|
221
216
|
setData(d => {
|
|
222
|
-
return
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}, d === null || d === void 0 ? void 0 : d[index], DEFAULT_DATA_POINT);
|
|
227
|
-
});
|
|
217
|
+
return {
|
|
218
|
+
...d,
|
|
219
|
+
values: obsData.data
|
|
220
|
+
};
|
|
228
221
|
});
|
|
229
222
|
} else if (!obsData.isPending && obsData.serverError) {
|
|
230
|
-
const s = getScale();
|
|
231
|
-
setScale(() => s);
|
|
232
223
|
setData(d => {
|
|
233
|
-
return
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}, e, DEFAULT_DATA_POINT);
|
|
238
|
-
});
|
|
224
|
+
return {
|
|
225
|
+
...d,
|
|
226
|
+
values: []
|
|
227
|
+
};
|
|
239
228
|
});
|
|
240
229
|
}
|
|
230
|
+
} else if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR && dataset.sliceBy.obs) {
|
|
231
|
+
if (!obsData.isPending && !obsData.serverError) {
|
|
232
|
+
setData(d => {
|
|
233
|
+
return {
|
|
234
|
+
...d,
|
|
235
|
+
sliceValues: obsData.data
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
} else if (!obsData.isPending && obsData.serverError) {
|
|
239
|
+
setData(d => {
|
|
240
|
+
return {
|
|
241
|
+
...d,
|
|
242
|
+
sliceValues: []
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}, [dataset.colorEncoding, obsData.data, obsData.isPending, obsData.serverError, dataset.sliceBy.obs]);
|
|
248
|
+
const isCategorical = (0, _react.useMemo)(() => {
|
|
249
|
+
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;
|
|
252
|
+
} else {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
}, [dataset.colorEncoding, (_dataset$selectedObs6 = dataset.selectedObs) === null || _dataset$selectedObs6 === void 0 ? void 0 : _dataset$selectedObs6.type]);
|
|
256
|
+
const isInSlice = (0, _react.useCallback)((index, values, positions) => {
|
|
257
|
+
let inSlice = true;
|
|
258
|
+
if ((dataset.sliceBy.obs || isCategorical) && values) {
|
|
259
|
+
var _dataset$selectedObs7;
|
|
260
|
+
inSlice &= !_lodash.default.includes((_dataset$selectedObs7 = dataset.selectedObs) === null || _dataset$selectedObs7 === void 0 ? void 0 : _dataset$selectedObs7.omit, values[index]);
|
|
261
|
+
}
|
|
262
|
+
if (dataset.sliceBy.polygons && positions) {
|
|
263
|
+
inSlice &= _lodash.default.some(features === null || features === void 0 ? void 0 : features.features, (_f, i) => {
|
|
264
|
+
return (0, _turf.booleanPointInPolygon)((0, _turf.point)([positions[index][0], positions[index][1]]), features.features[i]);
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
return inSlice;
|
|
268
|
+
}, [(_dataset$selectedObs8 = dataset.selectedObs) === null || _dataset$selectedObs8 === void 0 ? void 0 : _dataset$selectedObs8.omit, dataset.sliceBy.obs, dataset.sliceBy.polygons, features.features, isCategorical]);
|
|
269
|
+
const {
|
|
270
|
+
filteredIndices,
|
|
271
|
+
valueMin,
|
|
272
|
+
valueMax,
|
|
273
|
+
slicedLength
|
|
274
|
+
} = (0, _react.useMemo)(() => {
|
|
275
|
+
if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR) {
|
|
276
|
+
const {
|
|
277
|
+
filtered,
|
|
278
|
+
filteredIndices
|
|
279
|
+
} = _lodash.default.reduce(data.values, (acc, v, i) => {
|
|
280
|
+
if (isInSlice(i, data.sliceValues, data.positions)) {
|
|
281
|
+
acc.filtered.push(v);
|
|
282
|
+
acc.filteredIndices.add(i);
|
|
283
|
+
}
|
|
284
|
+
return acc;
|
|
285
|
+
}, {
|
|
286
|
+
filtered: [],
|
|
287
|
+
filteredIndices: new Set()
|
|
288
|
+
});
|
|
289
|
+
return {
|
|
290
|
+
filteredIndices: filteredIndices,
|
|
291
|
+
valueMin: _lodash.default.min(filtered),
|
|
292
|
+
valueMax: _lodash.default.max(filtered),
|
|
293
|
+
slicedLength: filtered.length
|
|
294
|
+
};
|
|
295
|
+
} else if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
|
|
296
|
+
var _dataset$selectedObs9;
|
|
297
|
+
const isContinuous = ((_dataset$selectedObs9 = dataset.selectedObs) === null || _dataset$selectedObs9 === void 0 ? void 0 : _dataset$selectedObs9.type) === _constants.OBS_TYPES.CONTINUOUS;
|
|
298
|
+
const {
|
|
299
|
+
filtered,
|
|
300
|
+
filteredIndices
|
|
301
|
+
} = _lodash.default.reduce(data.values, (acc, v, i) => {
|
|
302
|
+
if (isInSlice(i, data.values, data.positions)) {
|
|
303
|
+
acc.filtered.push(v);
|
|
304
|
+
acc.filteredIndices.add(i);
|
|
305
|
+
}
|
|
306
|
+
return acc;
|
|
307
|
+
}, {
|
|
308
|
+
filtered: [],
|
|
309
|
+
filteredIndices: new Set()
|
|
310
|
+
});
|
|
311
|
+
return {
|
|
312
|
+
filteredIndices: filteredIndices,
|
|
313
|
+
valueMin: _lodash.default.min(isContinuous ? filtered : data.values),
|
|
314
|
+
valueMax: _lodash.default.max(isContinuous ? filtered : data.values),
|
|
315
|
+
slicedLength: filtered.length
|
|
316
|
+
};
|
|
317
|
+
} else {
|
|
318
|
+
return {
|
|
319
|
+
filteredIndices: null,
|
|
320
|
+
valueMin: _lodash.default.min(data.values),
|
|
321
|
+
valueMax: _lodash.default.max(data.values),
|
|
322
|
+
slicedLength: data.values.length
|
|
323
|
+
};
|
|
241
324
|
}
|
|
242
|
-
}, [
|
|
243
|
-
|
|
325
|
+
}, [data.positions, data.sliceValues, data.values, dataset.colorEncoding, (_dataset$selectedObs10 = dataset.selectedObs) === null || _dataset$selectedObs10 === void 0 ? void 0 : _dataset$selectedObs10.type, isInSlice]);
|
|
326
|
+
(0, _react.useEffect)(() => {
|
|
327
|
+
dispatch({
|
|
328
|
+
type: "set.controls.valueRange",
|
|
329
|
+
valueRange: [valueMin, valueMax]
|
|
330
|
+
});
|
|
331
|
+
}, [dispatch, valueMax, valueMin]);
|
|
332
|
+
const {
|
|
333
|
+
min,
|
|
334
|
+
max
|
|
335
|
+
} = {
|
|
336
|
+
min: dataset.controls.range[0] * (valueMax - valueMin) + valueMin,
|
|
337
|
+
max: dataset.controls.range[1] * (valueMax - valueMin) + valueMin
|
|
338
|
+
};
|
|
339
|
+
const getFillColor = (0, _react.useCallback)((_d, _ref2) => {
|
|
340
|
+
let {
|
|
341
|
+
index
|
|
342
|
+
} = _ref2;
|
|
343
|
+
const grayOut = filteredIndices && !filteredIndices.has(index);
|
|
344
|
+
return getColor((data.values[index] - min) / (max - min), isCategorical, grayOut);
|
|
345
|
+
}, [data.values, filteredIndices, getColor, isCategorical, max, min]);
|
|
346
|
+
const memoizedLayers = (0, _react.useMemo)(() => {
|
|
244
347
|
return [new _layers.ScatterplotLayer({
|
|
245
348
|
id: "cherita-layer-scatterplot",
|
|
246
|
-
|
|
349
|
+
pickable: true,
|
|
350
|
+
data: data.positions,
|
|
247
351
|
radiusScale: radius,
|
|
248
352
|
radiusMinPixels: 1,
|
|
249
|
-
getPosition: d => d
|
|
250
|
-
getFillColor:
|
|
251
|
-
getRadius: 1
|
|
353
|
+
getPosition: d => d,
|
|
354
|
+
getFillColor: getFillColor,
|
|
355
|
+
getRadius: 1,
|
|
356
|
+
updateTriggers: {
|
|
357
|
+
getFillColor: getFillColor
|
|
358
|
+
}
|
|
252
359
|
}), new _layers2.EditableGeoJsonLayer({
|
|
253
360
|
id: "cherita-layer-draw",
|
|
254
361
|
data: features,
|
|
255
362
|
mode: mode,
|
|
256
363
|
selectedFeatureIndexes,
|
|
257
|
-
onEdit:
|
|
364
|
+
onEdit: _ref3 => {
|
|
258
365
|
let {
|
|
259
366
|
updatedData,
|
|
260
367
|
editType,
|
|
261
368
|
editContext
|
|
262
|
-
} =
|
|
369
|
+
} = _ref3;
|
|
263
370
|
setFeatures(updatedData);
|
|
264
371
|
let updatedSelectedFeatureIndexes = selectedFeatureIndexes;
|
|
265
|
-
setFeatureState({
|
|
266
|
-
data: updatedData
|
|
267
|
-
});
|
|
268
372
|
if (editType === "addFeature") {
|
|
269
|
-
// when a drawing is complete, the value of editType becomes addFeature
|
|
270
373
|
const {
|
|
271
374
|
featureIndexes
|
|
272
|
-
} = editContext;
|
|
375
|
+
} = editContext;
|
|
273
376
|
updatedSelectedFeatureIndexes = [...selectedFeatureIndexes, ...featureIndexes];
|
|
274
377
|
}
|
|
275
|
-
setSelectedFeatureIndexes(updatedSelectedFeatureIndexes);
|
|
378
|
+
setSelectedFeatureIndexes(updatedSelectedFeatureIndexes);
|
|
379
|
+
},
|
|
380
|
+
// getFillColor: POLYGON_FILLCOLOR,
|
|
381
|
+
_subLayerProps: {
|
|
382
|
+
geojson: {
|
|
383
|
+
getFillColor: feature => {
|
|
384
|
+
if (selectedFeatureIndexes.some(i => features.features[i] === feature)) {
|
|
385
|
+
return _constants.SELECTED_POLYGON_FILLCOLOR;
|
|
386
|
+
} else {
|
|
387
|
+
return _constants.UNSELECTED_POLYGON_FILLCOLOR;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
276
391
|
}
|
|
277
392
|
})];
|
|
278
|
-
}, [data, features, mode, radius, selectedFeatureIndexes]);
|
|
393
|
+
}, [data.positions, features, getFillColor, mode, radius, selectedFeatureIndexes]);
|
|
394
|
+
const layers = (0, _react.useDeferredValue)(mode === _editModes.ViewMode ? memoizedLayers.reverse() : memoizedLayers); // draw scatterplot on top of polygons when in ViewMode
|
|
395
|
+
|
|
396
|
+
(0, _react.useEffect)(() => {
|
|
397
|
+
var _features$features;
|
|
398
|
+
if (!(features !== null && features !== void 0 && (_features$features = features.features) !== null && _features$features !== void 0 && _features$features.length)) {
|
|
399
|
+
dispatch({
|
|
400
|
+
type: "disable.slice.polygons"
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
}, [dispatch, features === null || features === void 0 || (_features$features2 = features.features) === null || _features$features2 === void 0 ? void 0 : _features$features2.length]);
|
|
279
404
|
function onLayerClick(info) {
|
|
280
405
|
if (mode !== _editModes.ViewMode) {
|
|
281
406
|
// don't change selection while editing
|
|
282
407
|
return;
|
|
283
408
|
}
|
|
284
|
-
setSelectedFeatureIndexes(info.object ? [info.index] : []);
|
|
409
|
+
setSelectedFeatureIndexes(f => info.object ? info.layer.id === "cherita-layer-draw" ? [info.index] : f : []);
|
|
285
410
|
}
|
|
286
|
-
|
|
287
|
-
|
|
411
|
+
const getTooltip = _ref4 => {
|
|
412
|
+
let {
|
|
413
|
+
object,
|
|
414
|
+
index
|
|
415
|
+
} = _ref4;
|
|
416
|
+
return object && dataset.labelObs.length && {
|
|
417
|
+
text: _lodash.default.map(labelObsData, (v, k) => {
|
|
418
|
+
const labelObs = _lodash.default.find(dataset.labelObs, o => o.name === k);
|
|
419
|
+
if (labelObs.type === _constants.OBS_TYPES.CONTINUOUS) {
|
|
420
|
+
return "".concat(k, ": ").concat(parseFloat(v === null || v === void 0 ? void 0 : v[index]).toLocaleString());
|
|
421
|
+
} else {
|
|
422
|
+
return "".concat(k, ": ").concat(labelObs.codesMap[v === null || v === void 0 ? void 0 : v[index]]);
|
|
423
|
+
}
|
|
424
|
+
}).join("\n")
|
|
425
|
+
};
|
|
426
|
+
};
|
|
427
|
+
const isPending = (isRendering || xData.isPending || obsmData.isPending) && !obsmData.isPending;
|
|
428
|
+
const error = dataset.selectedObsm && ((_obsmData$serverError = obsmData.serverError) === null || _obsmData$serverError === void 0 ? void 0 : _obsmData$serverError.length) || dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR && ((_xData$serverError = xData.serverError) === null || _xData$serverError === void 0 ? void 0 : _xData$serverError.length) || dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && ((_obsData$serverError = obsData.serverError) === null || _obsData$serverError === void 0 ? void 0 : _obsData$serverError.length) || dataset.labelObs.lengh && ((_labelObsData$serverE = labelObsData.serverError) === null || _labelObsData$serverE === void 0 ? void 0 : _labelObsData$serverE.length);
|
|
288
429
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
289
430
|
className: "cherita-scatterplot",
|
|
290
|
-
children: [
|
|
431
|
+
children: [obsmData.isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingSpinner, {
|
|
432
|
+
disableShrink: true
|
|
433
|
+
}), isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingLinear, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_react2.DeckGL, {
|
|
291
434
|
viewState: viewState,
|
|
292
435
|
onViewStateChange: e => setViewState(e.viewState),
|
|
293
|
-
controller:
|
|
436
|
+
controller: {
|
|
437
|
+
doubleClickZoom: mode === _editModes.ViewMode
|
|
438
|
+
},
|
|
294
439
|
layers: layers,
|
|
295
|
-
onClick: onLayerClick
|
|
440
|
+
onClick: onLayerClick,
|
|
441
|
+
getTooltip: getTooltip,
|
|
442
|
+
onAfterRender: () => {
|
|
443
|
+
setIsRendering(false);
|
|
444
|
+
},
|
|
445
|
+
useDevicePixels: false,
|
|
446
|
+
getCursor: _ref5 => {
|
|
447
|
+
let {
|
|
448
|
+
isDragging
|
|
449
|
+
} = _ref5;
|
|
450
|
+
return mode !== _editModes.ViewMode ? "crosshair" : isDragging ? "grabbing" : "grab";
|
|
451
|
+
}
|
|
296
452
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpatialControls.SpatialControls, {
|
|
297
453
|
mode: mode,
|
|
298
454
|
setMode: setMode,
|
|
299
|
-
features:
|
|
300
|
-
setFeatures: setFeatures
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
455
|
+
features: features,
|
|
456
|
+
setFeatures: setFeatures,
|
|
457
|
+
selectedFeatureIndexes: selectedFeatureIndexes,
|
|
458
|
+
resetBounds: () => setViewState(bounds),
|
|
459
|
+
increaseZoom: () => setViewState(v => ({
|
|
460
|
+
...v,
|
|
461
|
+
zoom: v.zoom + 1
|
|
462
|
+
})),
|
|
463
|
+
decreaseZoom: () => setViewState(v => ({
|
|
464
|
+
...v,
|
|
465
|
+
zoom: v.zoom - 1
|
|
466
|
+
}))
|
|
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
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
476
|
+
className: "cherita-spatial-footer",
|
|
477
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Toolbox.Toolbox, {
|
|
478
|
+
mode: dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? dataset.selectedVar.name : dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS ? dataset.selectedObs.name : null,
|
|
479
|
+
obsLength: parseInt((_obsmData$data = obsmData.data) === null || _obsmData$data === void 0 ? void 0 : _obsmData$data.length),
|
|
480
|
+
slicedLength: parseInt(slicedLength)
|
|
481
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Legend.Legend, {
|
|
482
|
+
isCategorical: isCategorical,
|
|
483
|
+
min: min,
|
|
484
|
+
max: max
|
|
485
|
+
})]
|
|
308
486
|
})]
|
|
309
487
|
});
|
|
310
488
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.ScatterplotControls = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _material = require("@mui/material");
|
|
9
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
10
|
+
var _reactBootstrap = require("react-bootstrap");
|
|
11
|
+
var _colorscales = require("../../constants/colorscales");
|
|
12
|
+
var _constants = require("../../constants/constants");
|
|
13
|
+
var _DatasetContext = require("../../context/DatasetContext");
|
|
14
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
|
+
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); }
|
|
17
|
+
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; }
|
|
18
|
+
const ScatterplotControls = () => {
|
|
19
|
+
var _dataset$selectedObs;
|
|
20
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
21
|
+
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
22
|
+
const [sliderValue, setSliderValue] = _react.default.useState(dataset.controls.range || [0, 1]);
|
|
23
|
+
const isCategorical = dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS ? ((_dataset$selectedObs = dataset.selectedObs) === null || _dataset$selectedObs === void 0 ? void 0 : _dataset$selectedObs.type) === _constants.OBS_TYPES.CATEGORICAL : false;
|
|
24
|
+
const colormapList = _lodash.default.keys(_colorscales.COLORSCALES).map(key => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Item, {
|
|
25
|
+
active: dataset.controls.colorScale === key,
|
|
26
|
+
onClick: () => {
|
|
27
|
+
dispatch({
|
|
28
|
+
type: "set.controls.colorScale",
|
|
29
|
+
colorScale: key
|
|
30
|
+
});
|
|
31
|
+
},
|
|
32
|
+
children: key
|
|
33
|
+
}, key));
|
|
34
|
+
const valueLabelFormat = value => {
|
|
35
|
+
return (value * (dataset.controls.valueRange[1] - dataset.controls.valueRange[0]) + dataset.controls.valueRange[0]).toFixed(2);
|
|
36
|
+
};
|
|
37
|
+
const marks = [{
|
|
38
|
+
value: 0,
|
|
39
|
+
label: valueLabelFormat(0)
|
|
40
|
+
}, {
|
|
41
|
+
value: 1,
|
|
42
|
+
label: valueLabelFormat(1)
|
|
43
|
+
}];
|
|
44
|
+
const updateSlider = (_e, value) => {
|
|
45
|
+
setSliderValue(value);
|
|
46
|
+
};
|
|
47
|
+
const updateRange = (_e, value) => {
|
|
48
|
+
setSliderValue(value);
|
|
49
|
+
dispatch({
|
|
50
|
+
type: "set.controls.range",
|
|
51
|
+
range: sliderValue
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
(0, _react.useEffect)(() => {
|
|
55
|
+
setSliderValue(dataset.controls.range);
|
|
56
|
+
}, [dataset.controls.range]);
|
|
57
|
+
const rangeSlider = /*#__PURE__*/(0, _jsxRuntime.jsxs)(_material.Box, {
|
|
58
|
+
className: "w-100",
|
|
59
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Typography, {
|
|
60
|
+
id: "colorscale-range",
|
|
61
|
+
gutterBottom: true,
|
|
62
|
+
children: "Colorscale range"
|
|
63
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Slider, {
|
|
64
|
+
"aria-labelledby": "colorscale-range",
|
|
65
|
+
min: 0,
|
|
66
|
+
max: 1,
|
|
67
|
+
step: 0.001,
|
|
68
|
+
value: sliderValue,
|
|
69
|
+
onChange: updateSlider,
|
|
70
|
+
onChangeCommitted: updateRange,
|
|
71
|
+
valueLabelDisplay: "auto",
|
|
72
|
+
getAriaValueText: valueLabelFormat,
|
|
73
|
+
valueLabelFormat: valueLabelFormat,
|
|
74
|
+
marks: marks,
|
|
75
|
+
disabled: isCategorical
|
|
76
|
+
})]
|
|
77
|
+
});
|
|
78
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
79
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.Dropdown, {
|
|
80
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Toggle, {
|
|
81
|
+
id: "dropdownColorscale",
|
|
82
|
+
variant: "light",
|
|
83
|
+
children: dataset.controls.colorScale
|
|
84
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Dropdown.Menu, {
|
|
85
|
+
children: colormapList
|
|
86
|
+
})]
|
|
87
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
88
|
+
className: "m-4",
|
|
89
|
+
children: rangeSlider
|
|
90
|
+
})]
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
exports.ScatterplotControls = ScatterplotControls;
|