@haniffalab/cherita-react 1.3.0-dev.2025-06-04.6573608f → 1.3.0-dev.2025-06-06.0b38976b
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/assets/images/plots/dotplot.svg +152 -0
- package/dist/assets/images/plots/heatmap.svg +193 -0
- package/dist/assets/images/plots/matrixplot.svg +275 -0
- package/dist/assets/images/plots/scatterplot.svg +198 -0
- package/dist/assets/images/plots/violin.svg +50 -0
- package/dist/cjs/components/scatterplot/Scatterplot.js +77 -91
- package/dist/esm/components/scatterplot/Scatterplot.js +77 -91
- package/package.json +4 -3
|
@@ -34,7 +34,7 @@ const INITIAL_VIEW_STATE = {
|
|
|
34
34
|
bearing: 0
|
|
35
35
|
};
|
|
36
36
|
export function Scatterplot(_ref) {
|
|
37
|
-
var _settings$
|
|
37
|
+
var _settings$selectedObs2, _settings$selectedObs5, _features$features2, _obsmData$serverError, _xData$serverError, _obsData$serverError, _labelObsData$serverE, _settings$selectedVar, _settings$selectedObs6, _data$positions;
|
|
38
38
|
let {
|
|
39
39
|
radius = null,
|
|
40
40
|
setShowObs,
|
|
@@ -55,13 +55,12 @@ export function Scatterplot(_ref) {
|
|
|
55
55
|
const deckRef = useRef(null);
|
|
56
56
|
const [viewState, setViewState] = useState(INITIAL_VIEW_STATE);
|
|
57
57
|
const [isRendering, setIsRendering] = useState(true);
|
|
58
|
+
const [radiusScale, setRadiusScale] = useState(radius || 1);
|
|
59
|
+
const [isPending, setIsPending] = useState(false);
|
|
58
60
|
const [data, setData] = useState({
|
|
59
|
-
ids: [],
|
|
60
61
|
positions: [],
|
|
61
|
-
values: []
|
|
62
|
-
sliceValues: []
|
|
62
|
+
values: []
|
|
63
63
|
});
|
|
64
|
-
const [radiusScale, setRadiusScale] = useState(radius || 1);
|
|
65
64
|
|
|
66
65
|
// EditableGeoJsonLayer
|
|
67
66
|
const [mode, setMode] = useState(() => ViewMode);
|
|
@@ -88,21 +87,34 @@ export function Scatterplot(_ref) {
|
|
|
88
87
|
return rs;
|
|
89
88
|
}, [radius]);
|
|
90
89
|
useEffect(() => {
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
if (obsmData.isPending || settings.colorEncoding === COLOR_ENCODINGS.VAR && xData.isPending || settings.colorEncoding === COLOR_ENCODINGS.OBS && obsData.isPending) {
|
|
91
|
+
setIsPending(true);
|
|
92
|
+
} else {
|
|
93
|
+
setIsPending(false);
|
|
94
94
|
setData(d => {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
95
|
+
let values = d.values;
|
|
96
|
+
if (settings.colorEncoding === COLOR_ENCODINGS.VAR) {
|
|
97
|
+
values = !xData.serverError ? xData.data : values;
|
|
98
|
+
} else if (settings.colorEncoding === COLOR_ENCODINGS.OBS) {
|
|
99
|
+
values = !obsData.serverError ? obsData.data : values;
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
positions: !obsmData.serverError ? obsmData.data : d.positions,
|
|
103
|
+
values: values
|
|
104
|
+
};
|
|
98
105
|
});
|
|
106
|
+
}
|
|
107
|
+
}, [obsData.data, obsData.isPending, obsData.serverError, obsmData.data, obsmData.isPending, obsmData.serverError, settings.colorEncoding, xData.data, xData.isPending, xData.serverError]);
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (data.positions && !!data.positions.length) {
|
|
110
|
+
var _deckRef$current, _deckRef$current2;
|
|
99
111
|
const mapHelper = new MapHelper();
|
|
100
112
|
const {
|
|
101
113
|
latitude,
|
|
102
114
|
longitude,
|
|
103
115
|
zoom,
|
|
104
116
|
bounds
|
|
105
|
-
} = mapHelper.fitBounds(
|
|
117
|
+
} = mapHelper.fitBounds(data.positions, {
|
|
106
118
|
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,
|
|
107
119
|
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
|
|
108
120
|
});
|
|
@@ -114,15 +126,8 @@ export function Scatterplot(_ref) {
|
|
|
114
126
|
zoom: zoom
|
|
115
127
|
});
|
|
116
128
|
});
|
|
117
|
-
} else if (!obsmData.isPending && obsmData.serverError) {
|
|
118
|
-
setIsRendering(true);
|
|
119
|
-
setData(d => {
|
|
120
|
-
return _objectSpread(_objectSpread({}, d), {}, {
|
|
121
|
-
positions: []
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
129
|
}
|
|
125
|
-
}, [settings.selectedObsm, getRadiusScale, obsmData.data, obsmData.isPending, obsmData.serverError]);
|
|
130
|
+
}, [settings.selectedObsm, getRadiusScale, obsmData.data, obsmData.isPending, obsmData.serverError, data.positions]);
|
|
126
131
|
const getBounds = useCallback(() => {
|
|
127
132
|
var _deckRef$current3, _deckRef$current4;
|
|
128
133
|
const {
|
|
@@ -139,65 +144,47 @@ export function Scatterplot(_ref) {
|
|
|
139
144
|
zoom
|
|
140
145
|
};
|
|
141
146
|
}, [data.positions]);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (!obsData.isPending && !obsData.serverError) {
|
|
165
|
-
setData(d => {
|
|
166
|
-
return _objectSpread(_objectSpread({}, d), {}, {
|
|
167
|
-
values: obsData.data
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
} else if (!obsData.isPending && obsData.serverError) {
|
|
171
|
-
setData(d => {
|
|
172
|
-
return _objectSpread(_objectSpread({}, d), {}, {
|
|
173
|
-
values: []
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
} else if (settings.colorEncoding === COLOR_ENCODINGS.VAR && settings.sliceBy.obs) {
|
|
178
|
-
if (!obsData.isPending && !obsData.serverError) {
|
|
179
|
-
setData(d => {
|
|
180
|
-
return _objectSpread(_objectSpread({}, d), {}, {
|
|
181
|
-
sliceValues: obsData.data
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
} else if (!obsData.isPending && obsData.serverError) {
|
|
185
|
-
setData(d => {
|
|
186
|
-
return _objectSpread(_objectSpread({}, d), {}, {
|
|
187
|
-
sliceValues: []
|
|
188
|
-
});
|
|
189
|
-
});
|
|
190
|
-
}
|
|
147
|
+
|
|
148
|
+
// Make stable references for getOriginalIndex and sortedIndexMap
|
|
149
|
+
const identityGetOriginalIndex = useCallback(i => i, []);
|
|
150
|
+
const identitySortedIndexMap = useMemo(() => ({
|
|
151
|
+
get: key => key
|
|
152
|
+
}), []);
|
|
153
|
+
const {
|
|
154
|
+
sortedData,
|
|
155
|
+
getOriginalIndex,
|
|
156
|
+
sortedIndexMap
|
|
157
|
+
} = useMemo(() => {
|
|
158
|
+
var _settings$selectedObs;
|
|
159
|
+
if ((settings.colorEncoding === COLOR_ENCODINGS.VAR || settings.colorEncoding === COLOR_ENCODINGS.OBS && ((_settings$selectedObs = settings.selectedObs) === null || _settings$selectedObs === void 0 ? void 0 : _settings$selectedObs.type) === OBS_TYPES.CONTINUOUS) && data.positions && data.values && data.positions.length === data.values.length) {
|
|
160
|
+
const sortedIndices = _.map(data.values, (_v, i) => i).sort((a, b) => data.values[a] - data.values[b]);
|
|
161
|
+
const sortedIndexMap = new Map(_.map(sortedIndices, (originalIndex, sortedIndex) => [originalIndex, sortedIndex]));
|
|
162
|
+
return {
|
|
163
|
+
sortedData: _.mapValues(data, (v, _k) => {
|
|
164
|
+
return v ? _.at(v, sortedIndices) : v;
|
|
165
|
+
}),
|
|
166
|
+
getOriginalIndex: i => sortedIndices[i],
|
|
167
|
+
sortedIndexMap: sortedIndexMap
|
|
168
|
+
};
|
|
191
169
|
}
|
|
192
|
-
|
|
170
|
+
return {
|
|
171
|
+
sortedData: data,
|
|
172
|
+
getOriginalIndex: identityGetOriginalIndex,
|
|
173
|
+
// return original index
|
|
174
|
+
sortedIndexMap: identitySortedIndexMap // return original index
|
|
175
|
+
};
|
|
176
|
+
}, [data, identityGetOriginalIndex, identitySortedIndexMap, settings.colorEncoding, (_settings$selectedObs2 = settings.selectedObs) === null || _settings$selectedObs2 === void 0 ? void 0 : _settings$selectedObs2.type]);
|
|
177
|
+
const sortedObsIndices = useMemo(() => {
|
|
178
|
+
return obsIndices ? new Set(Array.from(obsIndices, i => sortedIndexMap.get(i))) : obsIndices;
|
|
179
|
+
}, [obsIndices, sortedIndexMap]);
|
|
193
180
|
const isCategorical = useMemo(() => {
|
|
194
181
|
if (settings.colorEncoding === COLOR_ENCODINGS.OBS) {
|
|
195
|
-
var _settings$
|
|
196
|
-
return ((_settings$
|
|
182
|
+
var _settings$selectedObs3, _settings$selectedObs4;
|
|
183
|
+
return ((_settings$selectedObs3 = settings.selectedObs) === null || _settings$selectedObs3 === void 0 ? void 0 : _settings$selectedObs3.type) === OBS_TYPES.CATEGORICAL || ((_settings$selectedObs4 = settings.selectedObs) === null || _settings$selectedObs4 === void 0 ? void 0 : _settings$selectedObs4.type) === OBS_TYPES.BOOLEAN;
|
|
197
184
|
} else {
|
|
198
185
|
return false;
|
|
199
186
|
}
|
|
200
|
-
}, [settings.colorEncoding, (_settings$
|
|
187
|
+
}, [settings.colorEncoding, (_settings$selectedObs5 = settings.selectedObs) === null || _settings$selectedObs5 === void 0 ? void 0 : _settings$selectedObs5.type]);
|
|
201
188
|
useEffect(() => {
|
|
202
189
|
dispatch({
|
|
203
190
|
type: "set.controls.valueRange",
|
|
@@ -215,27 +202,27 @@ export function Scatterplot(_ref) {
|
|
|
215
202
|
let {
|
|
216
203
|
index
|
|
217
204
|
} = _ref2;
|
|
218
|
-
const grayOut =
|
|
205
|
+
const grayOut = isPending || sortedObsIndices && !sortedObsIndices.has(index);
|
|
219
206
|
return getColor({
|
|
220
|
-
value: (
|
|
207
|
+
value: (sortedData.values[index] - min) / (max - min),
|
|
221
208
|
categorical: isCategorical,
|
|
222
209
|
grayOut: grayOut
|
|
223
210
|
}) || [0, 0, 0, 100];
|
|
224
|
-
}, [
|
|
211
|
+
}, [isPending, sortedObsIndices, getColor, sortedData.values, min, max, isCategorical]);
|
|
225
212
|
|
|
226
213
|
// @TODO: add support for pseudospatial hover to reflect in radius
|
|
227
214
|
const getRadius = useCallback((_d, _ref3) => {
|
|
228
215
|
let {
|
|
229
216
|
index
|
|
230
217
|
} = _ref3;
|
|
231
|
-
const grayOut =
|
|
218
|
+
const grayOut = sortedObsIndices && !sortedObsIndices.has(index);
|
|
232
219
|
return grayOut ? 1 : 3;
|
|
233
|
-
}, [
|
|
220
|
+
}, [sortedObsIndices]);
|
|
234
221
|
const memoizedLayers = useMemo(() => {
|
|
235
222
|
return [new ScatterplotLayer({
|
|
236
223
|
id: "cherita-layer-scatterplot",
|
|
237
224
|
pickable: true,
|
|
238
|
-
data:
|
|
225
|
+
data: sortedData.positions,
|
|
239
226
|
radiusScale: radiusScale,
|
|
240
227
|
radiusMinPixels: 1,
|
|
241
228
|
getPosition: d => d,
|
|
@@ -279,7 +266,7 @@ export function Scatterplot(_ref) {
|
|
|
279
266
|
}
|
|
280
267
|
}
|
|
281
268
|
})];
|
|
282
|
-
}, [
|
|
269
|
+
}, [sortedData.positions, features, getFillColor, getRadius, mode, radiusScale, selectedFeatureIndexes]);
|
|
283
270
|
const layers = useDeferredValue(mode === ViewMode ? memoizedLayers.reverse() : memoizedLayers); // draw scatterplot on top of polygons when in ViewMode
|
|
284
271
|
|
|
285
272
|
useEffect(() => {
|
|
@@ -322,21 +309,21 @@ export function Scatterplot(_ref) {
|
|
|
322
309
|
if (settings.colorEncoding === COLOR_ENCODINGS.OBS && settings.selectedObs && !_.some(settings.labelObs, {
|
|
323
310
|
name: settings.selectedObs.name
|
|
324
311
|
})) {
|
|
325
|
-
var
|
|
326
|
-
text.push(getLabel(settings.selectedObs, (
|
|
312
|
+
var _data$values;
|
|
313
|
+
text.push(getLabel(settings.selectedObs, (_data$values = data.values) === null || _data$values === void 0 ? void 0 : _data$values[getOriginalIndex(index)]));
|
|
327
314
|
}
|
|
328
315
|
if (settings.colorEncoding === COLOR_ENCODINGS.VAR && settings.selectedVar) {
|
|
329
|
-
var
|
|
330
|
-
text.push(getLabel(settings.selectedVar, (
|
|
316
|
+
var _data$values2;
|
|
317
|
+
text.push(getLabel(settings.selectedVar, (_data$values2 = data.values) === null || _data$values2 === void 0 ? void 0 : _data$values2[getOriginalIndex(index)], true));
|
|
331
318
|
}
|
|
332
319
|
if (settings.labelObs.length) {
|
|
333
320
|
text.push(..._.map(labelObsData.data, (v, k) => {
|
|
334
321
|
const labelObs = _.find(settings.labelObs, o => o.name === k);
|
|
335
|
-
return getLabel(labelObs, v[index]);
|
|
322
|
+
return getLabel(labelObs, v[getOriginalIndex(index)]);
|
|
336
323
|
}));
|
|
337
324
|
}
|
|
338
325
|
if (!text.length) return;
|
|
339
|
-
const grayOut =
|
|
326
|
+
const grayOut = sortedObsIndices && !sortedObsIndices.has(index);
|
|
340
327
|
return {
|
|
341
328
|
text: text.length ? _.compact(text).join("\n") : null,
|
|
342
329
|
className: grayOut ? "tooltip-grayout" : "deck-tooltip",
|
|
@@ -349,8 +336,7 @@ export function Scatterplot(_ref) {
|
|
|
349
336
|
}
|
|
350
337
|
};
|
|
351
338
|
};
|
|
352
|
-
const
|
|
353
|
-
const error = settings.selectedObsm && ((_obsmData$serverError = obsmData.serverError) === null || _obsmData$serverError === void 0 ? void 0 : _obsmData$serverError.length) || settings.colorEncoding === COLOR_ENCODINGS.VAR && ((_xData$serverError = xData.serverError) === null || _xData$serverError === void 0 ? void 0 : _xData$serverError.length) || settings.colorEncoding === COLOR_ENCODINGS.OBS && ((_obsData$serverError = obsData.serverError) === null || _obsData$serverError === void 0 ? void 0 : _obsData$serverError.length) || settings.labelObs.lengh && ((_labelObsData$serverE = labelObsData.serverError) === null || _labelObsData$serverE === void 0 ? void 0 : _labelObsData$serverE.length);
|
|
339
|
+
const error = settings.selectedObsm && ((_obsmData$serverError = obsmData.serverError) === null || _obsmData$serverError === void 0 ? void 0 : _obsmData$serverError.length) || settings.colorEncoding === COLOR_ENCODINGS.VAR && ((_xData$serverError = xData.serverError) === null || _xData$serverError === void 0 ? void 0 : _xData$serverError.length) || settings.colorEncoding === COLOR_ENCODINGS.OBS && ((_obsData$serverError = obsData.serverError) === null || _obsData$serverError === void 0 ? void 0 : _obsData$serverError.length) || settings.labelObs.length && ((_labelObsData$serverE = labelObsData.serverError) === null || _labelObsData$serverE === void 0 ? void 0 : _labelObsData$serverE.length);
|
|
354
340
|
return /*#__PURE__*/React.createElement("div", {
|
|
355
341
|
className: "cherita-container-scatterplot"
|
|
356
342
|
}, /*#__PURE__*/React.createElement("div", {
|
|
@@ -397,13 +383,13 @@ export function Scatterplot(_ref) {
|
|
|
397
383
|
className: "cherita-spatial-footer"
|
|
398
384
|
}, /*#__PURE__*/React.createElement("div", {
|
|
399
385
|
className: "cherita-toolbox-footer"
|
|
400
|
-
}, error && !
|
|
386
|
+
}, !!error && !isRendering && /*#__PURE__*/React.createElement(Alert, {
|
|
401
387
|
variant: "danger"
|
|
402
388
|
}, /*#__PURE__*/React.createElement(FontAwesomeIcon, {
|
|
403
389
|
icon: faTriangleExclamation
|
|
404
390
|
}), "\xA0Error loading data"), /*#__PURE__*/React.createElement(Toolbox, {
|
|
405
|
-
mode: settings.colorEncoding === COLOR_ENCODINGS.VAR ? (_settings$selectedVar = settings.selectedVar) === null || _settings$selectedVar === void 0 ? void 0 : _settings$selectedVar.name : settings.colorEncoding === COLOR_ENCODINGS.OBS ? (_settings$
|
|
406
|
-
obsLength: parseInt((
|
|
391
|
+
mode: settings.colorEncoding === COLOR_ENCODINGS.VAR ? (_settings$selectedVar = settings.selectedVar) === null || _settings$selectedVar === void 0 ? void 0 : _settings$selectedVar.name : settings.colorEncoding === COLOR_ENCODINGS.OBS ? (_settings$selectedObs6 = settings.selectedObs) === null || _settings$selectedObs6 === void 0 ? void 0 : _settings$selectedObs6.name : null,
|
|
392
|
+
obsLength: parseInt((_data$positions = data.positions) === null || _data$positions === void 0 ? void 0 : _data$positions.length),
|
|
407
393
|
slicedLength: parseInt(slicedLength)
|
|
408
394
|
})), /*#__PURE__*/React.createElement(Legend, {
|
|
409
395
|
isCategorical: isCategorical,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@haniffalab/cherita-react",
|
|
3
|
-
"version": "1.3.0-dev.2025-06-
|
|
3
|
+
"version": "1.3.0-dev.2025-06-06.0b38976b",
|
|
4
4
|
"author": "Haniffa Lab",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -90,7 +90,8 @@
|
|
|
90
90
|
"build:babel": "npm run build:esm && npm run build:cjs",
|
|
91
91
|
"build:scss": "sass --load-path=node_modules src/scss/cherita-bootstrap.scss dist/css/cherita.css",
|
|
92
92
|
"copy:scss": "cpx 'src/scss/**/*' 'scss'",
|
|
93
|
-
"
|
|
93
|
+
"copy:assets": "cpx 'src/assets/**/*' 'dist/assets'",
|
|
94
|
+
"build": "npm run build:babel && npm run build:scss && npm run copy:scss && npm run copy:assets",
|
|
94
95
|
"test": "jest --watchAll",
|
|
95
96
|
"test:ci": "jest --coverage --ci --no-watch",
|
|
96
97
|
"lint:scss": "stylelint 'src/**/*.scss' --fix",
|
|
@@ -126,5 +127,5 @@
|
|
|
126
127
|
"url": "https://github.com/haniffalab/cherita-react/issues"
|
|
127
128
|
},
|
|
128
129
|
"homepage": "https://github.com/haniffalab/cherita-react#readme",
|
|
129
|
-
"prereleaseSha": "
|
|
130
|
+
"prereleaseSha": "0b38976bfa4499c6f24545ed2f278f078633d27b"
|
|
130
131
|
}
|