@haniffalab/cherita-react 0.2.0-dev.2024-05-21.ca7d726c → 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 +67 -12
- 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 +251 -93
- package/dist/components/obs-list/ObsValueList.js +101 -0
- package/dist/components/obsm-list/ObsmList.js +25 -16
- package/dist/components/scatterplot/Legend.js +28 -36
- package/dist/components/scatterplot/Scatterplot.js +303 -119
- package/dist/components/scatterplot/ScatterplotControls.js +93 -0
- package/dist/components/scatterplot/SpatialControls.js +172 -0
- package/dist/components/scatterplot/Toolbox.js +18 -72
- 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 +102 -40
- 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,51 +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
|
|
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");
|
|
17
17
|
var _Legend = require("./Legend");
|
|
18
|
+
var _SpatialControls = require("./SpatialControls");
|
|
19
|
+
var _Toolbox = require("./Toolbox");
|
|
18
20
|
var _constants = require("../../constants/constants");
|
|
19
21
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
22
|
+
var _colorHelper = require("../../helpers/color-helper");
|
|
20
23
|
var _mapHelper = require("../../helpers/map-helper");
|
|
21
24
|
var _zarrHelper = require("../../helpers/zarr-helper");
|
|
22
|
-
var
|
|
23
|
-
var _LoadingSpinner = require("../../utils/LoadingSpinner");
|
|
25
|
+
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
24
26
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
25
|
-
function _interopRequireDefault(
|
|
27
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
26
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); }
|
|
27
|
-
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; }
|
|
28
30
|
window.deck.log.level = 1;
|
|
29
|
-
function ScatterplotControls() {
|
|
30
|
-
const dataset = (0, _DatasetContext.useDataset)();
|
|
31
|
-
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
32
|
-
const colormapList = _constants.PLOTLY_COLORSCALES.map(item => /*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default.Item, {
|
|
33
|
-
active: dataset.controls.colorScale === item,
|
|
34
|
-
onClick: () => {
|
|
35
|
-
dispatch({
|
|
36
|
-
type: "set.controls.colorScale",
|
|
37
|
-
colorScale: item
|
|
38
|
-
});
|
|
39
|
-
},
|
|
40
|
-
children: item
|
|
41
|
-
}, item));
|
|
42
|
-
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_Dropdown.default, {
|
|
43
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default.Toggle, {
|
|
44
|
-
id: "dropdownColorscale",
|
|
45
|
-
variant: "light",
|
|
46
|
-
children: dataset.controls.colorScale
|
|
47
|
-
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Dropdown.default.Menu, {
|
|
48
|
-
children: colormapList
|
|
49
|
-
})]
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
31
|
const INITIAL_VIEW_STATE = {
|
|
53
32
|
longitude: 0,
|
|
54
33
|
latitude: 0,
|
|
@@ -57,31 +36,32 @@ const INITIAL_VIEW_STATE = {
|
|
|
57
36
|
pitch: 0,
|
|
58
37
|
bearing: 0
|
|
59
38
|
};
|
|
60
|
-
const DEFAULT_DATA_POINT = {
|
|
61
|
-
value: null,
|
|
62
|
-
position: null,
|
|
63
|
-
color: null
|
|
64
|
-
};
|
|
65
39
|
function Scatterplot(_ref) {
|
|
66
|
-
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;
|
|
67
41
|
let {
|
|
68
42
|
radius = 30
|
|
69
43
|
} = _ref;
|
|
70
44
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
45
|
+
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
71
46
|
const {
|
|
72
|
-
getScale,
|
|
73
47
|
getColor
|
|
74
48
|
} = (0, _colorHelper.useColor)();
|
|
75
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);
|
|
76
60
|
const [features, setFeatures] = (0, _react.useState)({
|
|
77
61
|
type: "FeatureCollection",
|
|
78
62
|
features: []
|
|
79
63
|
});
|
|
80
|
-
const [mode, setMode] = (0, _react.useState)(() => _editModes.ViewMode);
|
|
81
64
|
const [selectedFeatureIndexes, setSelectedFeatureIndexes] = (0, _react.useState)([]);
|
|
82
|
-
const [featureState, setFeatureState] = (0, _react.useState)([]);
|
|
83
|
-
const [scale, setScale] = (0, _react.useState)(() => getScale());
|
|
84
|
-
const [data, setData] = (0, _react.useState)([]);
|
|
85
65
|
const [obsmParams, setObsmParams] = (0, _react.useState)({
|
|
86
66
|
url: dataset.url,
|
|
87
67
|
path: "obsm/" + dataset.selectedObsm
|
|
@@ -92,8 +72,9 @@ function Scatterplot(_ref) {
|
|
|
92
72
|
});
|
|
93
73
|
const [obsParams, setObsParams] = (0, _react.useState)({
|
|
94
74
|
url: dataset.url,
|
|
95
|
-
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")
|
|
96
76
|
});
|
|
77
|
+
const [labelObsParams, setLabelObsParams] = (0, _react.useState)([]);
|
|
97
78
|
|
|
98
79
|
// needs to be wrapped in useMemo as it is an array an could cause an infinite loop otherwise
|
|
99
80
|
const xSelection = (0, _react.useMemo)(() => {
|
|
@@ -103,6 +84,7 @@ function Scatterplot(_ref) {
|
|
|
103
84
|
const obsmData = (0, _zarrHelper.useZarr)(obsmParams, null, _zarrHelper.GET_OPTIONS);
|
|
104
85
|
const xData = (0, _zarrHelper.useZarr)(xParams, xSelection, _zarrHelper.GET_OPTIONS);
|
|
105
86
|
const obsData = (0, _zarrHelper.useZarr)(obsParams, null, _zarrHelper.GET_OPTIONS);
|
|
87
|
+
const labelObsData = (0, _zarrHelper.useMultipleZarr)(labelObsParams, _zarrHelper.GET_OPTIONS);
|
|
106
88
|
(0, _react.useEffect)(() => {
|
|
107
89
|
setObsmParams(p => {
|
|
108
90
|
return {
|
|
@@ -122,13 +104,22 @@ function Scatterplot(_ref) {
|
|
|
122
104
|
}, [dataset.selectedVar]);
|
|
123
105
|
(0, _react.useEffect)(() => {
|
|
124
106
|
setObsParams(p => {
|
|
125
|
-
var _dataset$
|
|
107
|
+
var _dataset$selectedObs3, _dataset$selectedObs4;
|
|
126
108
|
return {
|
|
127
109
|
...p,
|
|
128
|
-
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")
|
|
129
111
|
};
|
|
130
112
|
});
|
|
131
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]);
|
|
132
123
|
(0, _react.useEffect)(() => {
|
|
133
124
|
setObsmParams(p => {
|
|
134
125
|
return {
|
|
@@ -154,12 +145,12 @@ function Scatterplot(_ref) {
|
|
|
154
145
|
|
|
155
146
|
(0, _react.useEffect)(() => {
|
|
156
147
|
if (!obsmData.isPending && !obsmData.serverError) {
|
|
148
|
+
setIsRendering(true);
|
|
157
149
|
setData(d => {
|
|
158
|
-
return
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
});
|
|
150
|
+
return {
|
|
151
|
+
...d,
|
|
152
|
+
positions: obsmData.data
|
|
153
|
+
};
|
|
163
154
|
});
|
|
164
155
|
const mapHelper = new _mapHelper.MapHelper();
|
|
165
156
|
const {
|
|
@@ -176,129 +167,322 @@ function Scatterplot(_ref) {
|
|
|
176
167
|
};
|
|
177
168
|
});
|
|
178
169
|
} else if (!obsmData.isPending && obsmData.serverError) {
|
|
170
|
+
setIsRendering(true);
|
|
179
171
|
setData(d => {
|
|
180
|
-
return
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
});
|
|
172
|
+
return {
|
|
173
|
+
...d,
|
|
174
|
+
positions: []
|
|
175
|
+
};
|
|
185
176
|
});
|
|
186
177
|
}
|
|
187
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]);
|
|
188
191
|
(0, _react.useEffect)(() => {
|
|
189
|
-
if (dataset.colorEncoding ===
|
|
192
|
+
if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR) {
|
|
193
|
+
setIsRendering(true);
|
|
190
194
|
if (!xData.isPending && !xData.serverError) {
|
|
191
|
-
|
|
192
|
-
setScale(() => s);
|
|
195
|
+
// @TODO: add condition to check obs slicing
|
|
193
196
|
setData(d => {
|
|
194
|
-
return
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}, d === null || d === void 0 ? void 0 : d[index], DEFAULT_DATA_POINT);
|
|
199
|
-
});
|
|
197
|
+
return {
|
|
198
|
+
...d,
|
|
199
|
+
values: xData.data
|
|
200
|
+
};
|
|
200
201
|
});
|
|
201
202
|
} else if (!xData.isPending && xData.serverError) {
|
|
202
|
-
const s = getScale();
|
|
203
|
-
setScale(() => s);
|
|
204
203
|
setData(d => {
|
|
205
|
-
return
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}, e, DEFAULT_DATA_POINT);
|
|
210
|
-
});
|
|
204
|
+
return {
|
|
205
|
+
...d,
|
|
206
|
+
values: []
|
|
207
|
+
};
|
|
211
208
|
});
|
|
212
209
|
}
|
|
213
210
|
}
|
|
214
|
-
}, [dataset.colorEncoding, xData.data, xData.isPending, xData.serverError,
|
|
211
|
+
}, [dataset.colorEncoding, xData.data, xData.isPending, xData.serverError, getColor]);
|
|
215
212
|
(0, _react.useEffect)(() => {
|
|
216
|
-
if (dataset.colorEncoding ===
|
|
213
|
+
if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
|
|
214
|
+
setIsRendering(true);
|
|
217
215
|
if (!obsData.isPending && !obsData.serverError) {
|
|
218
|
-
const s = getScale(obsData.data);
|
|
219
|
-
setScale(() => s);
|
|
220
216
|
setData(d => {
|
|
221
|
-
return
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}, d === null || d === void 0 ? void 0 : d[index], DEFAULT_DATA_POINT);
|
|
226
|
-
});
|
|
217
|
+
return {
|
|
218
|
+
...d,
|
|
219
|
+
values: obsData.data
|
|
220
|
+
};
|
|
227
221
|
});
|
|
228
222
|
} else if (!obsData.isPending && obsData.serverError) {
|
|
229
|
-
const s = getScale();
|
|
230
|
-
setScale(() => s);
|
|
231
223
|
setData(d => {
|
|
232
|
-
return
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}, e, DEFAULT_DATA_POINT);
|
|
237
|
-
});
|
|
224
|
+
return {
|
|
225
|
+
...d,
|
|
226
|
+
values: []
|
|
227
|
+
};
|
|
238
228
|
});
|
|
239
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
|
+
};
|
|
240
324
|
}
|
|
241
|
-
}, [
|
|
242
|
-
|
|
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)(() => {
|
|
243
347
|
return [new _layers.ScatterplotLayer({
|
|
244
348
|
id: "cherita-layer-scatterplot",
|
|
245
|
-
|
|
349
|
+
pickable: true,
|
|
350
|
+
data: data.positions,
|
|
246
351
|
radiusScale: radius,
|
|
247
352
|
radiusMinPixels: 1,
|
|
248
|
-
getPosition: d => d
|
|
249
|
-
getFillColor:
|
|
250
|
-
getRadius: 1
|
|
353
|
+
getPosition: d => d,
|
|
354
|
+
getFillColor: getFillColor,
|
|
355
|
+
getRadius: 1,
|
|
356
|
+
updateTriggers: {
|
|
357
|
+
getFillColor: getFillColor
|
|
358
|
+
}
|
|
251
359
|
}), new _layers2.EditableGeoJsonLayer({
|
|
252
360
|
id: "cherita-layer-draw",
|
|
253
361
|
data: features,
|
|
254
362
|
mode: mode,
|
|
255
363
|
selectedFeatureIndexes,
|
|
256
|
-
onEdit:
|
|
364
|
+
onEdit: _ref3 => {
|
|
257
365
|
let {
|
|
258
366
|
updatedData,
|
|
259
367
|
editType,
|
|
260
368
|
editContext
|
|
261
|
-
} =
|
|
369
|
+
} = _ref3;
|
|
262
370
|
setFeatures(updatedData);
|
|
263
371
|
let updatedSelectedFeatureIndexes = selectedFeatureIndexes;
|
|
264
|
-
setFeatureState({
|
|
265
|
-
data: updatedData
|
|
266
|
-
});
|
|
267
372
|
if (editType === "addFeature") {
|
|
268
|
-
// when a drawing is complete, the value of editType becomes addFeature
|
|
269
373
|
const {
|
|
270
374
|
featureIndexes
|
|
271
|
-
} = editContext;
|
|
375
|
+
} = editContext;
|
|
272
376
|
updatedSelectedFeatureIndexes = [...selectedFeatureIndexes, ...featureIndexes];
|
|
273
377
|
}
|
|
274
|
-
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
|
+
}
|
|
275
391
|
}
|
|
276
392
|
})];
|
|
277
|
-
}, [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]);
|
|
278
404
|
function onLayerClick(info) {
|
|
279
405
|
if (mode !== _editModes.ViewMode) {
|
|
280
406
|
// don't change selection while editing
|
|
281
407
|
return;
|
|
282
408
|
}
|
|
283
|
-
setSelectedFeatureIndexes(info.object ? [info.index] : []);
|
|
409
|
+
setSelectedFeatureIndexes(f => info.object ? info.layer.id === "cherita-layer-draw" ? [info.index] : f : []);
|
|
284
410
|
}
|
|
285
|
-
|
|
286
|
-
|
|
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);
|
|
287
429
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
288
430
|
className: "cherita-scatterplot",
|
|
289
|
-
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, {
|
|
290
434
|
viewState: viewState,
|
|
291
435
|
onViewStateChange: e => setViewState(e.viewState),
|
|
292
|
-
controller:
|
|
436
|
+
controller: {
|
|
437
|
+
doubleClickZoom: mode === _editModes.ViewMode
|
|
438
|
+
},
|
|
293
439
|
layers: layers,
|
|
294
|
-
onClick: onLayerClick
|
|
295
|
-
|
|
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
|
+
}
|
|
452
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_SpatialControls.SpatialControls, {
|
|
296
453
|
mode: mode,
|
|
297
454
|
setMode: setMode,
|
|
298
|
-
features:
|
|
299
|
-
setFeatures: setFeatures
|
|
300
|
-
|
|
301
|
-
|
|
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
|
+
})]
|
|
302
486
|
})]
|
|
303
487
|
});
|
|
304
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;
|