@haniffalab/cherita-react 2.0.0 → 2.1.0
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/cjs/components/dotplot/Dotplot.js +4 -5
- package/dist/cjs/components/dotplot/DotplotControls.js +7 -3
- package/dist/cjs/components/heatmap/Heatmap.js +4 -5
- package/dist/cjs/components/icons/HeatmapIcon.js +2 -2
- package/dist/cjs/components/matrixplot/Matrixplot.js +4 -5
- package/dist/cjs/components/obs-list/ObsItem.js +7 -7
- package/dist/cjs/components/offcanvas/OffCanvas.js +7 -4
- package/dist/cjs/components/plot/PlotTypeSelector.js +49 -10
- package/dist/cjs/components/pseudospatial/Pseudospatial.js +8 -5
- package/dist/cjs/components/scatterplot/Scatterplot.js +134 -136
- package/dist/cjs/components/scatterplot/ScatterplotLayer.js +144 -0
- package/dist/cjs/components/scatterplot/SpatialControls.js +7 -4
- package/dist/cjs/components/scatterplot/Toolbox.js +8 -4
- package/dist/cjs/components/search-bar/SearchBar.js +51 -29
- package/dist/cjs/components/search-bar/SearchInfo.js +2 -2
- package/dist/cjs/components/search-bar/SearchResults.js +9 -6
- package/dist/cjs/components/toolbar/Toolbar.js +10 -65
- package/dist/cjs/components/var-list/VarItem.js +4 -6
- package/dist/cjs/components/var-list/VarList.js +17 -9
- package/dist/cjs/components/var-list/VarListToolbar.js +1 -1
- package/dist/cjs/components/var-list/VarSet.js +7 -5
- package/dist/cjs/components/violin/Violin.js +6 -7
- package/dist/cjs/constants/constants.js +6 -3
- package/dist/cjs/context/DatasetContext.js +11 -2
- package/dist/cjs/context/SettingsContext.js +27 -2
- package/dist/cjs/helpers/color-helper.js +17 -12
- package/dist/cjs/index.js +0 -7
- package/dist/cjs/utils/Legend.js +6 -5
- package/dist/cjs/utils/requests.js +2 -2
- package/dist/cjs/views/ObservationFeature/StandardView.js +1 -1
- package/dist/cjs/views/PerturbationMap/ObsExplorer.js +11 -9
- package/dist/cjs/views/PerturbationMap/StandardView.js +2 -1
- package/dist/cjs/workers/scatterplotData.js +16 -0
- package/dist/esm/components/dotplot/Dotplot.js +5 -6
- package/dist/esm/components/dotplot/DotplotControls.js +6 -3
- package/dist/esm/components/heatmap/Heatmap.js +5 -6
- package/dist/esm/components/icons/HeatmapIcon.js +2 -2
- package/dist/esm/components/matrixplot/Matrixplot.js +5 -6
- package/dist/esm/components/obs-list/ObsItem.js +7 -7
- package/dist/esm/components/offcanvas/OffCanvas.js +7 -4
- package/dist/esm/components/plot/PlotTypeSelector.js +49 -10
- package/dist/esm/components/pseudospatial/Pseudospatial.js +8 -5
- package/dist/esm/components/scatterplot/Scatterplot.js +132 -134
- package/dist/esm/components/scatterplot/ScatterplotLayer.js +137 -0
- package/dist/esm/components/scatterplot/SpatialControls.js +7 -4
- package/dist/esm/components/scatterplot/Toolbox.js +8 -4
- package/dist/esm/components/search-bar/SearchBar.js +52 -30
- package/dist/esm/components/search-bar/SearchInfo.js +2 -2
- package/dist/esm/components/search-bar/SearchResults.js +9 -6
- package/dist/esm/components/toolbar/Toolbar.js +9 -63
- package/dist/esm/components/var-list/VarItem.js +4 -6
- package/dist/esm/components/var-list/VarList.js +17 -9
- package/dist/esm/components/var-list/VarListToolbar.js +1 -1
- package/dist/esm/components/var-list/VarSet.js +7 -5
- package/dist/esm/components/violin/Violin.js +7 -8
- package/dist/esm/constants/constants.js +5 -2
- package/dist/esm/context/DatasetContext.js +11 -2
- package/dist/esm/context/SettingsContext.js +27 -2
- package/dist/esm/helpers/color-helper.js +17 -12
- package/dist/esm/index.js +0 -1
- package/dist/esm/utils/Legend.js +6 -5
- package/dist/esm/utils/requests.js +2 -2
- package/dist/esm/views/ObservationFeature/StandardView.js +1 -1
- package/dist/esm/views/PerturbationMap/ObsExplorer.js +11 -9
- package/dist/esm/views/PerturbationMap/StandardView.js +2 -1
- package/dist/esm/workers/scatterplotData.js +10 -0
- package/package.json +6 -3
|
@@ -176,7 +176,7 @@ function SettingsProvider(_ref2) {
|
|
|
176
176
|
|
|
177
177
|
// If the buster is not set or does not match the current package version,
|
|
178
178
|
// reset localSettings to avoid stale data
|
|
179
|
-
if (!buster || buster !== "2.
|
|
179
|
+
if (!buster || buster !== "2.1.0") {
|
|
180
180
|
localSettings = {};
|
|
181
181
|
}
|
|
182
182
|
const initSettings = (0, _react.useRef)(initializer({
|
|
@@ -201,7 +201,7 @@ function SettingsProvider(_ref2) {
|
|
|
201
201
|
if (canOverrideSettings && settings) {
|
|
202
202
|
try {
|
|
203
203
|
localStorage.setItem(DATASET_STORAGE_KEY, JSON.stringify(_objectSpread({
|
|
204
|
-
buster: "2.
|
|
204
|
+
buster: "2.1.0" || '0.0.0',
|
|
205
205
|
timestamp: Date.now()
|
|
206
206
|
}, _lodash.default.omit(settings, 'data'))));
|
|
207
207
|
} catch (err) {
|
|
@@ -345,6 +345,31 @@ function settingsReducer(settings, action) {
|
|
|
345
345
|
}));
|
|
346
346
|
}
|
|
347
347
|
}
|
|
348
|
+
case 'select.multivar.batch':
|
|
349
|
+
{
|
|
350
|
+
const newVars = [];
|
|
351
|
+
let newVarData = {};
|
|
352
|
+
_lodash.default.forEach(action.vars, v => {
|
|
353
|
+
const inMultiVar = settings.selectedMultiVar.some(mv => mv.name === v.name);
|
|
354
|
+
if (!inMultiVar) {
|
|
355
|
+
const {
|
|
356
|
+
settings: varSettings,
|
|
357
|
+
data: varData
|
|
358
|
+
} = splitVar(v);
|
|
359
|
+
newVars.push(varSettings);
|
|
360
|
+
newVarData = _objectSpread(_objectSpread({}, newVarData), varData);
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
if (!newVars.length) {
|
|
364
|
+
return validateSettings(_objectSpread({}, settings));
|
|
365
|
+
}
|
|
366
|
+
return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
|
|
367
|
+
selectedMultiVar: [...settings.selectedMultiVar, ...newVars],
|
|
368
|
+
data: _objectSpread(_objectSpread({}, settings.data), {}, {
|
|
369
|
+
vars: _objectSpread(_objectSpread({}, settings.data.vars), newVarData)
|
|
370
|
+
})
|
|
371
|
+
}));
|
|
372
|
+
}
|
|
348
373
|
case 'deselect.multivar':
|
|
349
374
|
{
|
|
350
375
|
return validateSettings(_objectSpread(_objectSpread({}, settings), {}, {
|
|
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.useColor = exports.rgbToHex = void 0;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _colorscales = require("../constants/colorscales");
|
|
9
|
+
var _constants = require("../constants/constants");
|
|
9
10
|
var _SettingsContext = require("../context/SettingsContext");
|
|
10
|
-
const GRAY = [214, 212, 212];
|
|
11
11
|
const parseHexColor = color => {
|
|
12
12
|
const r = parseInt(color === null || color === void 0 ? void 0 : color.substring(1, 3), 16);
|
|
13
13
|
const g = parseInt(color === null || color === void 0 ? void 0 : color.substring(3, 5), 16);
|
|
@@ -40,34 +40,39 @@ const rgbToHex = color => {
|
|
|
40
40
|
return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
|
|
41
41
|
};
|
|
42
42
|
exports.rgbToHex = rgbToHex;
|
|
43
|
-
const useColor =
|
|
43
|
+
const useColor = _ref => {
|
|
44
|
+
let {
|
|
45
|
+
isCategorical = false,
|
|
46
|
+
colorscale = null
|
|
47
|
+
} = _ref;
|
|
44
48
|
const settings = (0, _SettingsContext.useSettings)();
|
|
45
|
-
const
|
|
49
|
+
const colormap = (0, _react.useMemo)(() => {
|
|
50
|
+
return colorscale || _colorscales.COLORSCALES[isCategorical ? 'Accent' : settings.controls.colorScale];
|
|
51
|
+
}, [colorscale, isCategorical, settings.controls.colorScale]);
|
|
52
|
+
const getColor = (0, _react.useCallback)(_ref2 => {
|
|
46
53
|
let {
|
|
47
54
|
value,
|
|
48
|
-
categorical = false,
|
|
49
55
|
grayOut = false,
|
|
50
56
|
grayParams: {
|
|
51
|
-
alpha =
|
|
52
|
-
gray =
|
|
57
|
+
alpha = _constants.GRAY_ALPHA,
|
|
58
|
+
gray = _constants.GRAY_MIX
|
|
53
59
|
} = {},
|
|
54
|
-
colorEncoding = settings.colorEncoding
|
|
55
|
-
|
|
56
|
-
} = _ref;
|
|
57
|
-
const colormap = colorscale || _colorscales.COLORSCALES[categorical ? 'Accent' : settings.controls.colorScale];
|
|
60
|
+
colorEncoding = settings.colorEncoding
|
|
61
|
+
} = _ref2;
|
|
58
62
|
if (colorEncoding) {
|
|
59
63
|
if (grayOut) {
|
|
60
64
|
// Mix color with gray manually instead of chroma.mix to get better performance with deck.gl
|
|
61
65
|
const rgb = computeColor(colormap, value);
|
|
62
|
-
return [rgb[0] * (1 - gray) + GRAY[0] * gray, rgb[1] * (1 - gray) + GRAY[1] * gray, rgb[2] * (1 - gray) + GRAY[2] * gray, 255 * alpha];
|
|
66
|
+
return [rgb[0] * (1 - gray) + _constants.GRAY[0] * gray, rgb[1] * (1 - gray) + _constants.GRAY[1] * gray, rgb[2] * (1 - gray) + _constants.GRAY[2] * gray, 255 * alpha];
|
|
63
67
|
} else {
|
|
64
68
|
return [...computeColor(colormap, value), 255];
|
|
65
69
|
}
|
|
66
70
|
} else {
|
|
67
71
|
return null;
|
|
68
72
|
}
|
|
69
|
-
}, [settings.colorEncoding,
|
|
73
|
+
}, [settings.colorEncoding, colormap]);
|
|
70
74
|
return {
|
|
75
|
+
colormap,
|
|
71
76
|
getColor
|
|
72
77
|
};
|
|
73
78
|
};
|
package/dist/cjs/index.js
CHANGED
|
@@ -147,12 +147,6 @@ Object.defineProperty(exports, "SearchBar", {
|
|
|
147
147
|
return _SearchBar.SearchBar;
|
|
148
148
|
}
|
|
149
149
|
});
|
|
150
|
-
Object.defineProperty(exports, "Toolbar", {
|
|
151
|
-
enumerable: true,
|
|
152
|
-
get: function () {
|
|
153
|
-
return _Toolbar.Toolbar;
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
150
|
Object.defineProperty(exports, "VIOLIN_MODES", {
|
|
157
151
|
enumerable: true,
|
|
158
152
|
get: function () {
|
|
@@ -192,7 +186,6 @@ var _Pseudospatial = require("./components/pseudospatial/Pseudospatial");
|
|
|
192
186
|
var _Scatterplot = require("./components/scatterplot/Scatterplot");
|
|
193
187
|
var _ScatterplotControls = require("./components/scatterplot/ScatterplotControls");
|
|
194
188
|
var _SearchBar = require("./components/search-bar/SearchBar");
|
|
195
|
-
var _Toolbar = require("./components/toolbar/Toolbar");
|
|
196
189
|
var _VarList = require("./components/var-list/VarList");
|
|
197
190
|
var _Violin = require("./components/violin/Violin");
|
|
198
191
|
var _ViolinControls = require("./components/violin/ViolinControls");
|
package/dist/cjs/utils/Legend.js
CHANGED
|
@@ -25,13 +25,14 @@ function Legend(_ref) {
|
|
|
25
25
|
const settings = (0, _SettingsContext.useSettings)();
|
|
26
26
|
const {
|
|
27
27
|
getColor
|
|
28
|
-
} = (0, _colorHelper.useColor)(
|
|
28
|
+
} = (0, _colorHelper.useColor)({
|
|
29
|
+
isCategorical,
|
|
30
|
+
colorscale
|
|
31
|
+
});
|
|
29
32
|
const spanList = (0, _react.useMemo)(() => {
|
|
30
33
|
return _lodash.default.range(100).map(i => {
|
|
31
34
|
var color = (0, _colorHelper.rgbToHex)(getColor({
|
|
32
|
-
value: i / 100
|
|
33
|
-
categorical: isCategorical,
|
|
34
|
-
colorscale: colorscale
|
|
35
|
+
value: i / 100
|
|
35
36
|
}));
|
|
36
37
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
|
|
37
38
|
className: "grad-step",
|
|
@@ -40,7 +41,7 @@ function Legend(_ref) {
|
|
|
40
41
|
}
|
|
41
42
|
}, i);
|
|
42
43
|
});
|
|
43
|
-
}, [
|
|
44
|
+
}, [getColor]);
|
|
44
45
|
if (settings.colorEncoding && !isCategorical) {
|
|
45
46
|
var _settings$selectedVar, _settings$selectedObs;
|
|
46
47
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
@@ -15,8 +15,8 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
|
|
|
15
15
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
16
16
|
async function fetchData(endpoint, params) {
|
|
17
17
|
let signal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
18
|
-
let
|
|
19
|
-
let
|
|
18
|
+
let apiUrl = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
|
|
19
|
+
let ms = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 300000;
|
|
20
20
|
apiUrl = apiUrl || process.env.REACT_APP_API_URL;
|
|
21
21
|
const controller = new AbortController();
|
|
22
22
|
const timeout = setTimeout(() => {
|
|
@@ -109,7 +109,7 @@ function StandardView(_ref) {
|
|
|
109
109
|
default:
|
|
110
110
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Scatterplot.Scatterplot, _objectSpread({}, commonProps));
|
|
111
111
|
}
|
|
112
|
-
}, [plotType]);
|
|
112
|
+
}, [plotType, props]);
|
|
113
113
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
114
114
|
className: "cherita-app",
|
|
115
115
|
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_DatasetContext.DatasetProvider, _objectSpread(_objectSpread({}, props), {}, {
|
|
@@ -149,7 +149,9 @@ function ObsExplorer() {
|
|
|
149
149
|
selectedObsIndex
|
|
150
150
|
} = (0, _SettingsContext.useSettings)();
|
|
151
151
|
const {
|
|
152
|
-
obsExplorer = {}
|
|
152
|
+
obsExplorer = {},
|
|
153
|
+
obsLabel,
|
|
154
|
+
valueLabel
|
|
153
155
|
} = (0, _DatasetContext.useDataset)();
|
|
154
156
|
(0, _parquetData.useParquet)(); // initialize duckdb instance
|
|
155
157
|
|
|
@@ -160,9 +162,9 @@ function ObsExplorer() {
|
|
|
160
162
|
serverError
|
|
161
163
|
} = (0, _zarrData.useObsColsData)(obsExplorer === null || obsExplorer === void 0 ? void 0 : obsExplorer.obsCols);
|
|
162
164
|
if (selectedObsIndex == null) {
|
|
163
|
-
return /*#__PURE__*/(0, _jsxRuntime.
|
|
165
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
164
166
|
className: "my-4 text-muted",
|
|
165
|
-
children: "Select a point in the scatterplot to view details about the
|
|
167
|
+
children: ["Select a point in the scatterplot or search for ", obsLabel.plural, " to view details about the ", obsLabel.singular, " perturbation."]
|
|
166
168
|
});
|
|
167
169
|
}
|
|
168
170
|
if (isPending) {
|
|
@@ -184,8 +186,8 @@ function ObsExplorer() {
|
|
|
184
186
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("h2", {
|
|
185
187
|
className: "fw-bold mb-2",
|
|
186
188
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
|
|
187
|
-
title: /*#__PURE__*/(0, _jsxRuntime.
|
|
188
|
-
children: "This panel shows metadata and predicted downstream effects for the selected
|
|
189
|
+
title: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
190
|
+
children: ["This panel shows metadata and predicted downstream effects for the selected ", obsLabel.singular, " perturbation across the atlas."]
|
|
189
191
|
}),
|
|
190
192
|
placement: "right",
|
|
191
193
|
arrow: true,
|
|
@@ -200,8 +202,8 @@ function ObsExplorer() {
|
|
|
200
202
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("h5", {
|
|
201
203
|
className: "fw-bold mb-2",
|
|
202
204
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
|
|
203
|
-
title: /*#__PURE__*/(0, _jsxRuntime.
|
|
204
|
-
children: "These values describe how the selected
|
|
205
|
+
title: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
206
|
+
children: ["These values describe how the selected ", obsLabel.singular, ' ', "perturbation is annotated in the atlas, including lineage, biological context, and summary scores used in the perturbation landscape."]
|
|
205
207
|
}),
|
|
206
208
|
placement: "right",
|
|
207
209
|
arrow: true,
|
|
@@ -255,8 +257,8 @@ function ObsExplorer() {
|
|
|
255
257
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)("h5", {
|
|
256
258
|
className: "fw-bold mb-2 d-flex align-items-center justify-content-between",
|
|
257
259
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Tooltip.default, {
|
|
258
|
-
title: /*#__PURE__*/(0, _jsxRuntime.
|
|
259
|
-
children: "This table shows
|
|
260
|
+
title: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
261
|
+
children: ["This table shows ", obsLabel.plural, " predicted to change", ' ', valueLabel, " in response to the selected perturbation. Results can be sorted and explored to identify affected pathways and regulatory programs."]
|
|
260
262
|
}),
|
|
261
263
|
placement: "right",
|
|
262
264
|
arrow: true,
|
|
@@ -51,7 +51,8 @@ function StandardView(_ref) {
|
|
|
51
51
|
setShowSearch: setShowObsExplorer,
|
|
52
52
|
setShowControls: setShowControls,
|
|
53
53
|
isFullscreen: true,
|
|
54
|
-
pointInteractionEnabled: true
|
|
54
|
+
pointInteractionEnabled: true,
|
|
55
|
+
isSearchObs: true
|
|
55
56
|
})
|
|
56
57
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
57
58
|
className: "cherita-app-sidebar p-3",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createScatterplotWorker = createScatterplotWorker;
|
|
7
|
+
const WORKER_CODE = "\nfunction computeBitmask(indices, length) {\n if (indices === null) return new Uint8Array(length).fill(1);\n const bitmask = new Uint8Array(length);\n for (const idx of indices) {\n bitmask[idx] = 1;\n }\n return bitmask;\n}\n\nself.onmessage = ({ data }) => {\n // compute and transfer only updated data\n const msg = {};\n const transfer = [];\n\n if (data.positions) {\n const positions = new Float32Array(data.positions.flat());\n msg.positions = positions;\n msg.count = data.positions.length;\n transfer.push(positions.buffer);\n }\n\n if (data.values) {\n const values = new Float32Array(data.values);\n msg.values = values;\n transfer.push(values.buffer);\n }\n\n if (data.obsIndices !== undefined && !!data.length) {\n const bitmask = computeBitmask(data.obsIndices, data.length);\n msg.indexEnabledBitmask = bitmask;\n transfer.push(bitmask.buffer);\n }\n\n self.postMessage(msg, transfer);\n};\n";
|
|
8
|
+
function createScatterplotWorker() {
|
|
9
|
+
const blob = new Blob([WORKER_CODE], {
|
|
10
|
+
type: 'application/javascript'
|
|
11
|
+
});
|
|
12
|
+
const url = URL.createObjectURL(blob);
|
|
13
|
+
const worker = new Worker(url);
|
|
14
|
+
URL.revokeObjectURL(url);
|
|
15
|
+
return worker;
|
|
16
|
+
}
|
|
@@ -7,7 +7,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
7
7
|
import _ from 'lodash';
|
|
8
8
|
import { Button } from 'react-bootstrap';
|
|
9
9
|
import Plot from 'react-plotly.js';
|
|
10
|
-
import { PLOTLY_MODEBAR_BUTTONS } from '../../constants/constants';
|
|
10
|
+
import { PLOT_TYPES, PLOTLY_MODEBAR_BUTTONS } from '../../constants/constants';
|
|
11
11
|
import { useDataset } from '../../context/DatasetContext';
|
|
12
12
|
import { useFilteredData } from '../../context/FilterContext';
|
|
13
13
|
import { useSettings, useSettingsDispatch } from '../../context/SettingsContext';
|
|
@@ -23,7 +23,6 @@ export function Dotplot(_ref) {
|
|
|
23
23
|
setShowCategories,
|
|
24
24
|
setShowSearch,
|
|
25
25
|
setShowControls,
|
|
26
|
-
plotType,
|
|
27
26
|
setPlotType,
|
|
28
27
|
isFullscreen = false
|
|
29
28
|
} = _ref;
|
|
@@ -153,7 +152,7 @@ export function Dotplot(_ref) {
|
|
|
153
152
|
return /*#__PURE__*/_jsx(PlotAlert, {
|
|
154
153
|
variant: "info",
|
|
155
154
|
heading: "Set up your dotplot",
|
|
156
|
-
plotType:
|
|
155
|
+
plotType: PLOT_TYPES.DOTPLOT,
|
|
157
156
|
setPlotType: setPlotType,
|
|
158
157
|
children: /*#__PURE__*/_jsxs("p", {
|
|
159
158
|
className: "p-0 m-0",
|
|
@@ -161,8 +160,8 @@ export function Dotplot(_ref) {
|
|
|
161
160
|
variant: "link",
|
|
162
161
|
className: "border-0 p-0 align-baseline",
|
|
163
162
|
onClick: setShowSearch,
|
|
164
|
-
children:
|
|
165
|
-
}) :
|
|
163
|
+
children: dataset.varLabel.plural
|
|
164
|
+
}) : dataset.varLabel.plural, ' ', "to display their ", dataset.valueLabel, " across groups, then choose a", ' ', showCategoriesBtn ? /*#__PURE__*/_jsx(Button, {
|
|
166
165
|
variant: "link",
|
|
167
166
|
className: "border-0 p-0 align-baseline",
|
|
168
167
|
onClick: setShowCategories,
|
|
@@ -174,7 +173,7 @@ export function Dotplot(_ref) {
|
|
|
174
173
|
return /*#__PURE__*/_jsx(PlotAlert, {
|
|
175
174
|
variant: "danger",
|
|
176
175
|
heading: "Error displaying the dotplot",
|
|
177
|
-
plotType:
|
|
176
|
+
plotType: PLOT_TYPES.DOTPLOT,
|
|
178
177
|
setPlotType: setPlotType,
|
|
179
178
|
children: serverError.message || 'An unexpected error occurred while generating the plot.'
|
|
180
179
|
});
|
|
@@ -4,13 +4,16 @@ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object
|
|
|
4
4
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
5
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
6
6
|
import { useEffect, useState } from 'react';
|
|
7
|
+
import _ from 'lodash';
|
|
7
8
|
import { Button, Form, InputGroup } from 'react-bootstrap';
|
|
9
|
+
import { useDataset } from '../../context/DatasetContext';
|
|
8
10
|
import { useSettings, useSettingsDispatch } from '../../context/SettingsContext';
|
|
9
11
|
import { ColorscaleSelect, ScaleSelect } from '../controls/Controls';
|
|
10
12
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
11
13
|
export function DotplotControls() {
|
|
12
14
|
const settings = useSettings();
|
|
13
15
|
const dispatch = useSettingsDispatch();
|
|
16
|
+
const dataset = useDataset();
|
|
14
17
|
const [controls, setControls] = useState({
|
|
15
18
|
expressionCutoff: settings.controls.expressionCutoff,
|
|
16
19
|
colorAxis: {
|
|
@@ -91,8 +94,8 @@ export function DotplotControls() {
|
|
|
91
94
|
plot: "dotplot"
|
|
92
95
|
}), /*#__PURE__*/_jsxs(Form.Group, {
|
|
93
96
|
className: "mb-2",
|
|
94
|
-
children: [/*#__PURE__*/
|
|
95
|
-
children: "
|
|
97
|
+
children: [/*#__PURE__*/_jsxs(Form.Label, {
|
|
98
|
+
children: [_.capitalize(dataset.valueLabel), " Cutoff"]
|
|
96
99
|
}), /*#__PURE__*/_jsxs(InputGroup, {
|
|
97
100
|
children: [/*#__PURE__*/_jsx(Form.Control, {
|
|
98
101
|
size: "sm",
|
|
@@ -119,7 +122,7 @@ export function DotplotControls() {
|
|
|
119
122
|
children: /*#__PURE__*/_jsx(Form.Check, {
|
|
120
123
|
type: "switch",
|
|
121
124
|
id: "meanOnlyExpressed",
|
|
122
|
-
label: "Average only above cutoff",
|
|
125
|
+
label: "Average only above ".concat(dataset.valueLabel, " cutoff"),
|
|
123
126
|
checked: settings.controls.meanOnlyExpressed,
|
|
124
127
|
onChange: () => {
|
|
125
128
|
dispatch({
|
|
@@ -7,7 +7,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
7
7
|
import _ from 'lodash';
|
|
8
8
|
import { Button } from 'react-bootstrap';
|
|
9
9
|
import Plot from 'react-plotly.js';
|
|
10
|
-
import { PLOTLY_MODEBAR_BUTTONS } from '../../constants/constants';
|
|
10
|
+
import { PLOT_TYPES, PLOTLY_MODEBAR_BUTTONS } from '../../constants/constants';
|
|
11
11
|
import { useDataset } from '../../context/DatasetContext';
|
|
12
12
|
import { useFilteredData } from '../../context/FilterContext';
|
|
13
13
|
import { useSettings } from '../../context/SettingsContext';
|
|
@@ -23,7 +23,6 @@ export function Heatmap(_ref) {
|
|
|
23
23
|
setShowCategories,
|
|
24
24
|
setShowSearch,
|
|
25
25
|
setShowControls,
|
|
26
|
-
plotType,
|
|
27
26
|
setPlotType,
|
|
28
27
|
isFullscreen = false
|
|
29
28
|
} = _ref;
|
|
@@ -127,7 +126,7 @@ export function Heatmap(_ref) {
|
|
|
127
126
|
return /*#__PURE__*/_jsx(PlotAlert, {
|
|
128
127
|
variant: "info",
|
|
129
128
|
heading: "Set up your heatmap",
|
|
130
|
-
plotType:
|
|
129
|
+
plotType: PLOT_TYPES.HEATMAP,
|
|
131
130
|
setPlotType: setPlotType,
|
|
132
131
|
children: /*#__PURE__*/_jsxs("p", {
|
|
133
132
|
className: "p-0 m-0",
|
|
@@ -135,8 +134,8 @@ export function Heatmap(_ref) {
|
|
|
135
134
|
variant: "link",
|
|
136
135
|
className: "border-0 p-0 align-baseline",
|
|
137
136
|
onClick: setShowSearch,
|
|
138
|
-
children:
|
|
139
|
-
}) :
|
|
137
|
+
children: dataset.varLabel.plural
|
|
138
|
+
}) : dataset.varLabel.plural, ' ', "to display their ", dataset.valueLabel, ", then choose a", ' ', showCategoriesBtn ? /*#__PURE__*/_jsx(Button, {
|
|
140
139
|
variant: "link",
|
|
141
140
|
className: "border-0 p-0 align-baseline",
|
|
142
141
|
onClick: setShowCategories,
|
|
@@ -148,7 +147,7 @@ export function Heatmap(_ref) {
|
|
|
148
147
|
return /*#__PURE__*/_jsx(PlotAlert, {
|
|
149
148
|
variant: "danger",
|
|
150
149
|
heading: "Error displaying the heatmap",
|
|
151
|
-
plotType:
|
|
150
|
+
plotType: PLOT_TYPES.HEATMAP,
|
|
152
151
|
setPlotType: setPlotType,
|
|
153
152
|
children: serverError.message || 'An unexpected error occurred while generating the plot.'
|
|
154
153
|
});
|
|
@@ -14,8 +14,8 @@ export default function HeatmapIcon(_ref) {
|
|
|
14
14
|
gap = 1
|
|
15
15
|
} = _ref,
|
|
16
16
|
props = _objectWithoutProperties(_ref, _excluded);
|
|
17
|
-
const rows = 6; //
|
|
18
|
-
const cols = 8; //
|
|
17
|
+
const rows = 6; // features
|
|
18
|
+
const cols = 8; // observations
|
|
19
19
|
|
|
20
20
|
// Example expression pattern for visual clusters
|
|
21
21
|
const expressionLevels = [[1, 0.8, 0.2, 0.2, 0.5, 0.9, 1, 0.7], [0.9, 0.7, 0.1, 0.2, 0.4, 0.8, 0.9, 0.6], [0.1, 0.2, 0.8, 0.9, 0.7, 0.2, 0.1, 0.3], [0.2, 0.3, 0.9, 1, 0.8, 0.3, 0.2, 0.4], [0.5, 0.6, 0.2, 0.1, 0.9, 0.7, 0.6, 0.8], [0.6, 0.7, 0.3, 0.2, 0.8, 0.6, 0.7, 0.9]];
|
|
@@ -7,7 +7,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
7
7
|
import _ from 'lodash';
|
|
8
8
|
import { Button } from 'react-bootstrap';
|
|
9
9
|
import Plot from 'react-plotly.js';
|
|
10
|
-
import { PLOTLY_MODEBAR_BUTTONS } from '../../constants/constants';
|
|
10
|
+
import { PLOT_TYPES, PLOTLY_MODEBAR_BUTTONS } from '../../constants/constants';
|
|
11
11
|
import { useDataset } from '../../context/DatasetContext';
|
|
12
12
|
import { useFilteredData } from '../../context/FilterContext';
|
|
13
13
|
import { useSettings } from '../../context/SettingsContext';
|
|
@@ -23,7 +23,6 @@ export function Matrixplot(_ref) {
|
|
|
23
23
|
setShowCategories,
|
|
24
24
|
setShowSearch,
|
|
25
25
|
setShowControls,
|
|
26
|
-
plotType,
|
|
27
26
|
setPlotType,
|
|
28
27
|
isFullscreen = false
|
|
29
28
|
} = _ref;
|
|
@@ -128,7 +127,7 @@ export function Matrixplot(_ref) {
|
|
|
128
127
|
return /*#__PURE__*/_jsx(PlotAlert, {
|
|
129
128
|
variant: "info",
|
|
130
129
|
heading: "Set up your matrix plot",
|
|
131
|
-
plotType:
|
|
130
|
+
plotType: PLOT_TYPES.MATRIXPLOT,
|
|
132
131
|
setPlotType: setPlotType,
|
|
133
132
|
children: /*#__PURE__*/_jsxs("p", {
|
|
134
133
|
className: "p-0 m-0",
|
|
@@ -141,15 +140,15 @@ export function Matrixplot(_ref) {
|
|
|
141
140
|
variant: "link",
|
|
142
141
|
className: "border-0 p-0 align-baseline",
|
|
143
142
|
onClick: setShowSearch,
|
|
144
|
-
children:
|
|
145
|
-
}) :
|
|
143
|
+
children: dataset.varLabel.plural
|
|
144
|
+
}) : dataset.varLabel.plural, ' ', "to display the matrix plot."]
|
|
146
145
|
})
|
|
147
146
|
});
|
|
148
147
|
} else {
|
|
149
148
|
return /*#__PURE__*/_jsx(PlotAlert, {
|
|
150
149
|
variant: "danger",
|
|
151
150
|
heading: "Error displaying the matrix plot",
|
|
152
|
-
plotType:
|
|
151
|
+
plotType: PLOT_TYPES.MATRIXPLOT,
|
|
153
152
|
setPlotType: setPlotType,
|
|
154
153
|
children: serverError.message || 'An unexpected error occurred while generating the plot.'
|
|
155
154
|
});
|
|
@@ -158,7 +158,10 @@ function CategoricalItem(_ref2) {
|
|
|
158
158
|
} = useDataset();
|
|
159
159
|
const {
|
|
160
160
|
getColor
|
|
161
|
-
} = useColor(
|
|
161
|
+
} = useColor({
|
|
162
|
+
isCategorical: true,
|
|
163
|
+
colorscale: useUnsColors ? colors : null
|
|
164
|
+
});
|
|
162
165
|
return /*#__PURE__*/_jsx("div", {
|
|
163
166
|
className: "virtualized-list-wrapper ps-1",
|
|
164
167
|
children: /*#__PURE__*/_jsx(ListGroup.Item, {
|
|
@@ -253,17 +256,14 @@ function CategoricalItem(_ref2) {
|
|
|
253
256
|
y: "0",
|
|
254
257
|
width: "10",
|
|
255
258
|
height: "10",
|
|
256
|
-
fill: "rgb(".concat(getColor(
|
|
257
|
-
value: (code - min) / (max - min),
|
|
258
|
-
categorical: true,
|
|
259
|
+
fill: "rgb(".concat(getColor({
|
|
260
|
+
value: (code - min) / Math.max(max - min, 1e-6),
|
|
259
261
|
grayOut: isOmitted,
|
|
260
262
|
grayParams: {
|
|
261
263
|
alpha: 1
|
|
262
264
|
},
|
|
263
265
|
colorEncoding: 'obs'
|
|
264
|
-
},
|
|
265
|
-
colorscale: colors
|
|
266
|
-
} : {})), ")")
|
|
266
|
+
}), ")")
|
|
267
267
|
})
|
|
268
268
|
})
|
|
269
269
|
}) : null]
|
|
@@ -10,6 +10,7 @@ function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i
|
|
|
10
10
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
11
11
|
import Offcanvas from 'react-bootstrap/Offcanvas';
|
|
12
12
|
import { SELECTION_MODES } from '../../constants/constants';
|
|
13
|
+
import { useDataset } from '../../context/DatasetContext';
|
|
13
14
|
import { ObsExplorer } from '../../views/PerturbationMap/ObsExplorer';
|
|
14
15
|
import { ObsColsList } from '../obs-list/ObsList';
|
|
15
16
|
import { ObsmKeysList } from '../obsm-list/ObsmList';
|
|
@@ -61,14 +62,15 @@ export function OffcanvasVars(_ref3) {
|
|
|
61
62
|
handleClose,
|
|
62
63
|
mode = SELECTION_MODES.MULTIPLE
|
|
63
64
|
} = _ref3;
|
|
65
|
+
const dataset = useDataset();
|
|
64
66
|
return /*#__PURE__*/_jsxs(Offcanvas, {
|
|
65
67
|
show: show,
|
|
66
68
|
onHide: handleClose,
|
|
67
69
|
className: "offcanvas-vars",
|
|
68
70
|
children: [/*#__PURE__*/_jsx(Offcanvas.Header, {
|
|
69
71
|
closeButton: true,
|
|
70
|
-
children: /*#__PURE__*/
|
|
71
|
-
children: "
|
|
72
|
+
children: /*#__PURE__*/_jsxs(Offcanvas.Title, {
|
|
73
|
+
children: ["Search for ", dataset.varLabel.plural]
|
|
72
74
|
})
|
|
73
75
|
}), /*#__PURE__*/_jsx(Offcanvas.Body, {
|
|
74
76
|
children: /*#__PURE__*/_jsxs("div", {
|
|
@@ -111,13 +113,14 @@ export function OffcanvasObsExplorer(_ref5) {
|
|
|
111
113
|
handleClose
|
|
112
114
|
} = _ref5,
|
|
113
115
|
props = _objectWithoutProperties(_ref5, _excluded3);
|
|
116
|
+
const dataset = useDataset();
|
|
114
117
|
return /*#__PURE__*/_jsxs(Offcanvas, {
|
|
115
118
|
show: show,
|
|
116
119
|
onHide: handleClose,
|
|
117
120
|
children: [/*#__PURE__*/_jsx(Offcanvas.Header, {
|
|
118
121
|
closeButton: true,
|
|
119
|
-
children: /*#__PURE__*/
|
|
120
|
-
children: "
|
|
122
|
+
children: /*#__PURE__*/_jsxs(Offcanvas.Title, {
|
|
123
|
+
children: ["Search for ", dataset.obsLabel.plural]
|
|
121
124
|
})
|
|
122
125
|
}), /*#__PURE__*/_jsx(Offcanvas.Body, {
|
|
123
126
|
className: "p-1",
|
|
@@ -5,6 +5,7 @@ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol"
|
|
|
5
5
|
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
6
6
|
import { useState } from 'react';
|
|
7
7
|
import { PLOT_TYPES } from '../../constants/constants';
|
|
8
|
+
import { useDataset } from '../../context/DatasetContext';
|
|
8
9
|
import { StyledTooltip } from '../../utils/StyledTooltip';
|
|
9
10
|
import DotPlotIcon from '../icons/DotPlotIcon';
|
|
10
11
|
import HeatmapIcon from '../icons/HeatmapIcon';
|
|
@@ -16,33 +17,67 @@ const plotTypes = [{
|
|
|
16
17
|
type: PLOT_TYPES.SCATTERPLOT,
|
|
17
18
|
icon: ScatterplotIcon,
|
|
18
19
|
name: 'Scatterplot',
|
|
19
|
-
description:
|
|
20
|
+
description: _ref => {
|
|
21
|
+
let {
|
|
22
|
+
obsLabel
|
|
23
|
+
} = _ref;
|
|
24
|
+
return "Displays ".concat(obsLabel.plural, " in 2D based on dimensionality reduction.");
|
|
25
|
+
}
|
|
20
26
|
}, {
|
|
21
27
|
type: PLOT_TYPES.MATRIXPLOT,
|
|
22
28
|
icon: MatrixPlotIcon,
|
|
23
29
|
name: 'Matrix Plot',
|
|
24
|
-
description:
|
|
30
|
+
description: _ref2 => {
|
|
31
|
+
let {
|
|
32
|
+
varLabel,
|
|
33
|
+
valueLabel
|
|
34
|
+
} = _ref2;
|
|
35
|
+
return "Shows ".concat(valueLabel, " values of ").concat(varLabel.plural, " across categories.");
|
|
36
|
+
}
|
|
25
37
|
}, {
|
|
26
38
|
type: PLOT_TYPES.DOTPLOT,
|
|
27
39
|
icon: DotPlotIcon,
|
|
28
40
|
name: 'Dot Plot',
|
|
29
|
-
description:
|
|
41
|
+
description: _ref3 => {
|
|
42
|
+
let {
|
|
43
|
+
varLabel,
|
|
44
|
+
valueLabel
|
|
45
|
+
} = _ref3;
|
|
46
|
+
return "Shows proportion and ".concat(valueLabel, " of ").concat(varLabel.plural, " across groups.");
|
|
47
|
+
}
|
|
30
48
|
}, {
|
|
31
49
|
type: PLOT_TYPES.HEATMAP,
|
|
32
50
|
icon: HeatmapIcon,
|
|
33
51
|
name: 'Heatmap',
|
|
34
|
-
description:
|
|
52
|
+
description: _ref4 => {
|
|
53
|
+
let {
|
|
54
|
+
varLabel,
|
|
55
|
+
valueLabel
|
|
56
|
+
} = _ref4;
|
|
57
|
+
return "Visualises ".concat(valueLabel, " of ").concat(varLabel.plural, " as a colour-coded matrix.");
|
|
58
|
+
}
|
|
35
59
|
}, {
|
|
36
60
|
type: PLOT_TYPES.VIOLINPLOT,
|
|
37
61
|
icon: ViolinPlotIcon,
|
|
38
62
|
name: 'Violin Plot',
|
|
39
|
-
description:
|
|
63
|
+
description: _ref5 => {
|
|
64
|
+
let {
|
|
65
|
+
obsLabel,
|
|
66
|
+
valueLabel
|
|
67
|
+
} = _ref5;
|
|
68
|
+
return "Displays distribution of ".concat(valueLabel, " across ").concat(obsLabel.plural, ".");
|
|
69
|
+
}
|
|
40
70
|
}];
|
|
41
|
-
export function PlotTypeSelector(
|
|
71
|
+
export function PlotTypeSelector(_ref6) {
|
|
42
72
|
let {
|
|
43
73
|
currentType,
|
|
44
74
|
onChange
|
|
45
|
-
} =
|
|
75
|
+
} = _ref6;
|
|
76
|
+
const {
|
|
77
|
+
obsLabel,
|
|
78
|
+
varLabel,
|
|
79
|
+
valueLabel
|
|
80
|
+
} = useDataset();
|
|
46
81
|
const [hoveredMap, setHoveredMap] = useState({});
|
|
47
82
|
const handleMouseEnter = type => setHoveredMap(prev => _objectSpread(_objectSpread({}, prev), {}, {
|
|
48
83
|
[type]: true
|
|
@@ -52,13 +87,13 @@ export function PlotTypeSelector(_ref) {
|
|
|
52
87
|
}));
|
|
53
88
|
return /*#__PURE__*/_jsx("div", {
|
|
54
89
|
className: "d-flex gap-2 justify-content-between",
|
|
55
|
-
children: plotTypes.map(
|
|
90
|
+
children: plotTypes.map(_ref7 => {
|
|
56
91
|
let {
|
|
57
92
|
type,
|
|
58
93
|
icon: Icon,
|
|
59
94
|
name,
|
|
60
95
|
description
|
|
61
|
-
} =
|
|
96
|
+
} = _ref7;
|
|
62
97
|
const isActive = currentType === type;
|
|
63
98
|
const hovered = hoveredMap[type] || false;
|
|
64
99
|
const colour = isActive ? '#005a86' : hovered ? '#0071a7' : '#000';
|
|
@@ -66,7 +101,11 @@ export function PlotTypeSelector(_ref) {
|
|
|
66
101
|
title: /*#__PURE__*/_jsxs(_Fragment, {
|
|
67
102
|
children: [/*#__PURE__*/_jsx("strong", {
|
|
68
103
|
children: name
|
|
69
|
-
}), /*#__PURE__*/_jsx("br", {}), description
|
|
104
|
+
}), /*#__PURE__*/_jsx("br", {}), description({
|
|
105
|
+
obsLabel,
|
|
106
|
+
varLabel,
|
|
107
|
+
valueLabel
|
|
108
|
+
})]
|
|
70
109
|
}),
|
|
71
110
|
placement: "bottom",
|
|
72
111
|
slotProps: {
|