@haniffalab/cherita-react 0.2.0-dev.2024-12-16.f02cfae4 → 0.2.0-dev.2024-12-16.67617f27
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/components/dotplot/Dotplot.js +6 -1
- package/dist/components/full-page/FullPage.js +31 -1
- package/dist/components/heatmap/Heatmap.js +6 -1
- package/dist/components/matrixplot/Matrixplot.js +6 -1
- package/dist/components/obs-list/ObsItem.js +65 -21
- package/dist/components/obs-list/ObsList.js +19 -3
- package/dist/components/pseudospatial/Pseudospatial.js +5 -1
- package/dist/components/pseudospatial/PseudospatialToolbar.js +3 -1
- package/dist/components/scatterplot/Scatterplot.js +7 -99
- package/dist/components/var-list/VarItem.js +18 -48
- package/dist/components/var-list/VarList.js +4 -2
- package/dist/components/violin/Violin.js +7 -2
- package/dist/css/cherita.css +5 -0
- package/dist/css/cherita.css.map +1 -1
- package/dist/index.js +6 -0
- package/dist/utils/Filter.js +129 -0
- package/dist/utils/Histogram.js +54 -0
- package/dist/utils/VirtualizedList.js +2 -2
- package/dist/utils/requests.js +8 -2
- package/dist/utils/search.js +4 -2
- package/dist/utils/string.js +4 -0
- package/package.json +2 -2
- package/scss/cherita.scss +5 -0
|
@@ -9,6 +9,7 @@ var _lodash = _interopRequireDefault(require("lodash"));
|
|
|
9
9
|
var _reactBootstrap = require("react-bootstrap");
|
|
10
10
|
var _reactPlotly = _interopRequireDefault(require("react-plotly.js"));
|
|
11
11
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
12
|
+
var _FilterContext = require("../../context/FilterContext");
|
|
12
13
|
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
13
14
|
var _requests = require("../../utils/requests");
|
|
14
15
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -18,6 +19,8 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
18
19
|
function Dotplot() {
|
|
19
20
|
const ENDPOINT = "dotplot";
|
|
20
21
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
22
|
+
const filteredData = (0, _FilterContext.useFilteredData)();
|
|
23
|
+
const isSliced = dataset.sliceBy.obs || dataset.sliceBy.polygons;
|
|
21
24
|
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
22
25
|
const colorscale = (0, _react.useRef)(dataset.controls.colorScale);
|
|
23
26
|
const [data, setData] = (0, _react.useState)([]);
|
|
@@ -31,6 +34,7 @@ function Dotplot() {
|
|
|
31
34
|
name: i.name,
|
|
32
35
|
indices: i.vars.map(v => v.index)
|
|
33
36
|
} : i.index),
|
|
37
|
+
obsIndices: isSliced ? [...(filteredData.obsIndices || [])] : null,
|
|
34
38
|
standardScale: dataset.controls.standardScale,
|
|
35
39
|
meanOnlyExpressed: dataset.controls.meanOnlyExpressed,
|
|
36
40
|
expressionCutoff: dataset.controls.expressionCutoff,
|
|
@@ -54,13 +58,14 @@ function Dotplot() {
|
|
|
54
58
|
name: i.name,
|
|
55
59
|
indices: i.vars.map(v => v.index)
|
|
56
60
|
} : i.index),
|
|
61
|
+
obsIndices: isSliced ? [...(filteredData.obsIndices || [])] : null,
|
|
57
62
|
standardScale: dataset.controls.standardScale,
|
|
58
63
|
meanOnlyExpressed: dataset.controls.meanOnlyExpressed,
|
|
59
64
|
expressionCutoff: dataset.controls.expressionCutoff,
|
|
60
65
|
varNamesCol: dataset.varNamesCol
|
|
61
66
|
};
|
|
62
67
|
});
|
|
63
|
-
}, [dataset.url, dataset.selectedObs, dataset.selectedMultiVar, dataset.controls.standardScale, dataset.controls.meanOnlyExpressed, dataset.controls.expressionCutoff, dataset.varNamesCol]);
|
|
68
|
+
}, [dataset.url, dataset.selectedObs, dataset.selectedMultiVar, dataset.controls.standardScale, dataset.controls.meanOnlyExpressed, dataset.controls.expressionCutoff, dataset.varNamesCol, isSliced, filteredData.obsIndices]);
|
|
64
69
|
const updateColorscale = (0, _react.useCallback)(colorscale => {
|
|
65
70
|
setLayout(l => {
|
|
66
71
|
return {
|
|
@@ -4,12 +4,16 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.FullPage = FullPage;
|
|
7
|
+
exports.FullPagePlots = FullPagePlots;
|
|
7
8
|
exports.FullPagePseudospatial = FullPagePseudospatial;
|
|
8
9
|
exports.FullPageScatterplot = FullPageScatterplot;
|
|
9
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
10
11
|
var _reactBootstrap = require("react-bootstrap");
|
|
11
12
|
var _constants = require("../../constants/constants");
|
|
12
13
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
14
|
+
var _Dotplot = require("../dotplot/Dotplot");
|
|
15
|
+
var _Heatmap = require("../heatmap/Heatmap");
|
|
16
|
+
var _Matrixplot = require("../matrixplot/Matrixplot");
|
|
13
17
|
var _ObsList = require("../obs-list/ObsList");
|
|
14
18
|
var _offcanvas = require("../offcanvas");
|
|
15
19
|
var _Pseudospatial = require("../pseudospatial/Pseudospatial");
|
|
@@ -17,12 +21,14 @@ var _Scatterplot = require("../scatterplot/Scatterplot");
|
|
|
17
21
|
var _ScatterplotControls = require("../scatterplot/ScatterplotControls");
|
|
18
22
|
var _SearchBar = require("../search-bar/SearchBar");
|
|
19
23
|
var _VarList = require("../var-list/VarList");
|
|
24
|
+
var _Violin = require("../violin/Violin");
|
|
20
25
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
21
26
|
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); }
|
|
22
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 && {}.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; }
|
|
23
28
|
function FullPage(_ref) {
|
|
24
29
|
let {
|
|
25
30
|
children,
|
|
31
|
+
varMode = _constants.SELECTION_MODES.SINGLE,
|
|
26
32
|
...props
|
|
27
33
|
} = _ref;
|
|
28
34
|
const targetRef = (0, _react.useRef)();
|
|
@@ -111,7 +117,7 @@ function FullPage(_ref) {
|
|
|
111
117
|
searchDiseases: true,
|
|
112
118
|
searchVar: true
|
|
113
119
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_VarList.VarNamesList, {
|
|
114
|
-
mode:
|
|
120
|
+
mode: varMode
|
|
115
121
|
})]
|
|
116
122
|
})
|
|
117
123
|
})
|
|
@@ -174,4 +180,28 @@ function FullPagePseudospatial(props) {
|
|
|
174
180
|
})
|
|
175
181
|
})
|
|
176
182
|
});
|
|
183
|
+
}
|
|
184
|
+
function FullPagePlots(props) {
|
|
185
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(FullPage, {
|
|
186
|
+
...props,
|
|
187
|
+
varMode: _constants.SELECTION_MODES.MULTIPLE,
|
|
188
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
189
|
+
className: "container-fluid w-100 h-100 d-flex flex-column overflow-y-auto",
|
|
190
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
191
|
+
className: "row flex-grow-1",
|
|
192
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Heatmap.Heatmap, {})
|
|
193
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
194
|
+
className: "row flex-grow-1",
|
|
195
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Matrixplot.Matrixplot, {})
|
|
196
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
197
|
+
className: "row flex-grow-1",
|
|
198
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Dotplot.Dotplot, {})
|
|
199
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
200
|
+
className: "row flex-grow-1",
|
|
201
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Violin.Violin, {
|
|
202
|
+
mode: _constants.VIOLIN_MODES.GROUPBY
|
|
203
|
+
})
|
|
204
|
+
})]
|
|
205
|
+
})
|
|
206
|
+
});
|
|
177
207
|
}
|
|
@@ -9,6 +9,7 @@ var _lodash = _interopRequireDefault(require("lodash"));
|
|
|
9
9
|
var _reactBootstrap = require("react-bootstrap");
|
|
10
10
|
var _reactPlotly = _interopRequireDefault(require("react-plotly.js"));
|
|
11
11
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
12
|
+
var _FilterContext = require("../../context/FilterContext");
|
|
12
13
|
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
13
14
|
var _requests = require("../../utils/requests");
|
|
14
15
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -18,6 +19,8 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
18
19
|
function Heatmap() {
|
|
19
20
|
const ENDPOINT = "heatmap";
|
|
20
21
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
22
|
+
const filteredData = (0, _FilterContext.useFilteredData)();
|
|
23
|
+
const isSliced = dataset.sliceBy.obs || dataset.sliceBy.polygons;
|
|
21
24
|
const colorscale = (0, _react.useRef)(dataset.controls.colorScale);
|
|
22
25
|
const [data, setData] = (0, _react.useState)([]);
|
|
23
26
|
const [layout, setLayout] = (0, _react.useState)({});
|
|
@@ -30,6 +33,7 @@ function Heatmap() {
|
|
|
30
33
|
name: i.name,
|
|
31
34
|
indices: i.vars.map(v => v.index)
|
|
32
35
|
} : i.index),
|
|
36
|
+
obsIndices: isSliced ? [...(filteredData.obsIndices || [])] : null,
|
|
33
37
|
varNamesCol: dataset.varNamesCol
|
|
34
38
|
});
|
|
35
39
|
(0, _react.useEffect)(() => {
|
|
@@ -48,10 +52,11 @@ function Heatmap() {
|
|
|
48
52
|
name: i.name,
|
|
49
53
|
indices: i.vars.map(v => v.index)
|
|
50
54
|
} : i.index),
|
|
55
|
+
obsIndices: isSliced ? [...(filteredData.obsIndices || [])] : null,
|
|
51
56
|
varNamesCol: dataset.varNamesCol
|
|
52
57
|
};
|
|
53
58
|
});
|
|
54
|
-
}, [dataset.selectedMultiVar, dataset.selectedObs, dataset.url, dataset.varNamesCol]);
|
|
59
|
+
}, [dataset.selectedMultiVar, dataset.selectedObs, dataset.url, dataset.varNamesCol, filteredData.obsIndices, isSliced]);
|
|
55
60
|
const updateColorscale = (0, _react.useCallback)(colorscale => {
|
|
56
61
|
setLayout(l => {
|
|
57
62
|
return {
|
|
@@ -9,6 +9,7 @@ var _lodash = _interopRequireDefault(require("lodash"));
|
|
|
9
9
|
var _reactBootstrap = require("react-bootstrap");
|
|
10
10
|
var _reactPlotly = _interopRequireDefault(require("react-plotly.js"));
|
|
11
11
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
12
|
+
var _FilterContext = require("../../context/FilterContext");
|
|
12
13
|
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
13
14
|
var _requests = require("../../utils/requests");
|
|
14
15
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
@@ -18,6 +19,8 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
18
19
|
function Matrixplot() {
|
|
19
20
|
const ENDPOINT = "matrixplot";
|
|
20
21
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
22
|
+
const filteredData = (0, _FilterContext.useFilteredData)();
|
|
23
|
+
const isSliced = dataset.sliceBy.obs || dataset.sliceBy.polygons;
|
|
21
24
|
const colorscale = (0, _react.useRef)(dataset.controls.colorScale);
|
|
22
25
|
const [data, setData] = (0, _react.useState)([]);
|
|
23
26
|
const [layout, setLayout] = (0, _react.useState)({});
|
|
@@ -30,6 +33,7 @@ function Matrixplot() {
|
|
|
30
33
|
name: i.name,
|
|
31
34
|
indices: i.vars.map(v => v.index)
|
|
32
35
|
} : i.index),
|
|
36
|
+
obsIndices: isSliced ? [...(filteredData.obsIndices || [])] : null,
|
|
33
37
|
standardScale: dataset.controls.standardScale,
|
|
34
38
|
varNamesCol: dataset.varNamesCol
|
|
35
39
|
});
|
|
@@ -49,11 +53,12 @@ function Matrixplot() {
|
|
|
49
53
|
name: i.name,
|
|
50
54
|
indices: i.vars.map(v => v.index)
|
|
51
55
|
} : i.index),
|
|
56
|
+
obsIndices: isSliced ? [...(filteredData.obsIndices || [])] : null,
|
|
52
57
|
standardScale: dataset.controls.standardScale,
|
|
53
58
|
varNamesCol: dataset.varNamesCol
|
|
54
59
|
};
|
|
55
60
|
});
|
|
56
|
-
}, [dataset.controls.standardScale, dataset.selectedMultiVar, dataset.selectedObs, dataset.url, dataset.varNamesCol]);
|
|
61
|
+
}, [dataset.controls.standardScale, dataset.selectedMultiVar, dataset.selectedObs, dataset.url, dataset.varNamesCol, filteredData.obsIndices, isSliced]);
|
|
57
62
|
const updateColorscale = (0, _react.useCallback)(colorscale => {
|
|
58
63
|
setLayout(l => {
|
|
59
64
|
return {
|
|
@@ -11,8 +11,11 @@ var _xCharts = require("@mui/x-charts");
|
|
|
11
11
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
12
12
|
var _reactBootstrap = require("react-bootstrap");
|
|
13
13
|
var _ObsToolbar = require("./ObsToolbar");
|
|
14
|
+
var _constants = require("../../constants/constants");
|
|
14
15
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
16
|
+
var _FilterContext = require("../../context/FilterContext");
|
|
15
17
|
var _colorHelper = require("../../helpers/color-helper");
|
|
18
|
+
var _Histogram = require("../../utils/Histogram");
|
|
16
19
|
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
17
20
|
var _requests = require("../../utils/requests");
|
|
18
21
|
var _string = require("../../utils/string");
|
|
@@ -22,8 +25,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
22
25
|
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); }
|
|
23
26
|
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; }
|
|
24
27
|
const N_BINS = 5;
|
|
25
|
-
function binContinuous(data) {
|
|
26
|
-
let nBins = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : N_BINS;
|
|
28
|
+
function binContinuous(data, nBins) {
|
|
27
29
|
const binSize = (data.max - data.min) * (1 / nBins);
|
|
28
30
|
const thresholds = _lodash.default.range(nBins + 1).map(b => {
|
|
29
31
|
return data.min + binSize * b;
|
|
@@ -40,21 +42,42 @@ function binContinuous(data) {
|
|
|
40
42
|
bins: bins
|
|
41
43
|
};
|
|
42
44
|
}
|
|
43
|
-
function binDiscrete(data) {
|
|
44
|
-
let nBins = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : N_BINS;
|
|
45
|
-
const binSize = _lodash.default.round(data.n_values * (1 / nBins));
|
|
46
|
-
const bins = {
|
|
47
|
-
nBins: nBins,
|
|
48
|
-
binSize: binSize
|
|
49
|
-
};
|
|
50
|
-
return {
|
|
51
|
-
...data,
|
|
52
|
-
bins: bins
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
45
|
function getContinuousLabel(code, binEdges) {
|
|
56
46
|
return `[ ${(0, _string.formatNumerical)(binEdges[code][0])}, ${(0, _string.formatNumerical)(binEdges[code][1], _string.FORMATS.EXPONENTIAL)}${code === binEdges.length - 1 ? " ]" : " )"}`;
|
|
57
47
|
}
|
|
48
|
+
const useObsHistogram = obs => {
|
|
49
|
+
const ENDPOINT = "obs/histograms";
|
|
50
|
+
const dataset = (0, _DatasetContext.useDataset)();
|
|
51
|
+
const filteredData = (0, _FilterContext.useFilteredData)();
|
|
52
|
+
const isSliced = dataset.sliceBy.obs || dataset.sliceBy.polygons;
|
|
53
|
+
const [params, setParams] = (0, _react.useState)({
|
|
54
|
+
url: dataset.url,
|
|
55
|
+
obsCol: _lodash.default.omit(obs, "omit"),
|
|
56
|
+
// avoid re-rendering when toggling unselected obs
|
|
57
|
+
varKey: dataset.selectedVar?.isSet ? {
|
|
58
|
+
name: dataset.selectedVar?.name,
|
|
59
|
+
indices: dataset.selectedVar?.vars.map(v => v.index)
|
|
60
|
+
} : dataset.selectedVar?.index,
|
|
61
|
+
obsIndices: isSliced ? [...(filteredData.obsIndices || [])] : null
|
|
62
|
+
});
|
|
63
|
+
(0, _react.useEffect)(() => {
|
|
64
|
+
setParams(p => {
|
|
65
|
+
return {
|
|
66
|
+
...p,
|
|
67
|
+
obsCol: _lodash.default.omit(obs, "omit"),
|
|
68
|
+
varKey: dataset.selectedVar?.isSet ? {
|
|
69
|
+
name: dataset.selectedVar?.name,
|
|
70
|
+
indices: dataset.selectedVar?.vars.map(v => v.index)
|
|
71
|
+
} : dataset.selectedVar?.index,
|
|
72
|
+
obsIndices: isSliced ? [...(filteredData.obsIndices || [])] : null
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
}, [dataset.selectedVar?.index, dataset.selectedVar?.isSet, dataset.selectedVar?.name, dataset.selectedVar?.vars, filteredData.obsIndices, isSliced, obs]);
|
|
76
|
+
return (0, _requests.useFetch)(ENDPOINT, params, {
|
|
77
|
+
enabled: !!dataset.selectedVar && dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR,
|
|
78
|
+
refetchOnMount: false
|
|
79
|
+
});
|
|
80
|
+
};
|
|
58
81
|
function CategoricalItem(_ref) {
|
|
59
82
|
let {
|
|
60
83
|
value,
|
|
@@ -66,12 +89,18 @@ function CategoricalItem(_ref) {
|
|
|
66
89
|
min,
|
|
67
90
|
max,
|
|
68
91
|
onChange,
|
|
92
|
+
histogramData = {
|
|
93
|
+
data: null,
|
|
94
|
+
isPending: false,
|
|
95
|
+
altColor: false
|
|
96
|
+
},
|
|
69
97
|
showColor = true
|
|
70
98
|
} = _ref;
|
|
71
99
|
const {
|
|
72
100
|
getColor
|
|
73
101
|
} = (0, _colorHelper.useColor)();
|
|
74
102
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.ListGroup.Item, {
|
|
103
|
+
className: "obs-item",
|
|
75
104
|
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
76
105
|
className: "d-flex align-items-center",
|
|
77
106
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
@@ -85,7 +114,11 @@ function CategoricalItem(_ref) {
|
|
|
85
114
|
})
|
|
86
115
|
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
87
116
|
className: "d-flex align-items-center",
|
|
88
|
-
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(
|
|
117
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Histogram.Histogram, {
|
|
118
|
+
data: histogramData.data,
|
|
119
|
+
isPending: histogramData.isPending,
|
|
120
|
+
altColor: histogramData.altColor
|
|
121
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
89
122
|
className: "pl-1 m-0",
|
|
90
123
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_material.Tooltip, {
|
|
91
124
|
title: `${(0, _string.formatNumerical)(pct, _string.FORMATS.EXPONENTIAL)}%`,
|
|
@@ -115,7 +148,7 @@ function CategoricalItem(_ref) {
|
|
|
115
148
|
})]
|
|
116
149
|
})
|
|
117
150
|
})
|
|
118
|
-
}), showColor
|
|
151
|
+
}), showColor ? /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
119
152
|
className: "pl-1",
|
|
120
153
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("svg", {
|
|
121
154
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -139,7 +172,7 @@ function CategoricalItem(_ref) {
|
|
|
139
172
|
})})`
|
|
140
173
|
})
|
|
141
174
|
})
|
|
142
|
-
})]
|
|
175
|
+
}) : null]
|
|
143
176
|
})]
|
|
144
177
|
})
|
|
145
178
|
}, value);
|
|
@@ -160,6 +193,8 @@ function CategoricalObs(_ref2) {
|
|
|
160
193
|
const totalCounts = _lodash.default.sum(_lodash.default.values(obs.value_counts));
|
|
161
194
|
const min = _lodash.default.min(_lodash.default.values(obs.codes));
|
|
162
195
|
const max = _lodash.default.max(_lodash.default.values(obs.codes));
|
|
196
|
+
const isSliced = dataset.sliceBy.obs || dataset.sliceBy.polygons;
|
|
197
|
+
const obsHistograms = useObsHistogram(obs);
|
|
163
198
|
(0, _react.useEffect)(() => {
|
|
164
199
|
if (dataset.selectedObs?.name === obs.name) {
|
|
165
200
|
const selectedObsData = _lodash.default.omit(dataset.selectedObs, ["omit"]);
|
|
@@ -178,16 +213,25 @@ function CategoricalObs(_ref2) {
|
|
|
178
213
|
}
|
|
179
214
|
}
|
|
180
215
|
}, [dataset.selectedObs, dispatch, obs, obs.name, updateObs]);
|
|
181
|
-
const getDataAtIndex = index => {
|
|
216
|
+
const getDataAtIndex = (0, _react.useCallback)(index => {
|
|
182
217
|
return {
|
|
183
218
|
value: obs.values[index],
|
|
184
219
|
code: obs.codes[obs.values[index]],
|
|
185
220
|
value_counts: obs.value_counts[obs.values[index]],
|
|
186
221
|
pct: obs.value_counts[obs.values[index]] / totalCounts * 100,
|
|
187
222
|
isOmitted: _lodash.default.includes(obs.omit, obs.codes[obs.values[index]]),
|
|
188
|
-
label: obs.values[index]
|
|
223
|
+
label: obs.values[index],
|
|
224
|
+
histogramData: dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR ? {
|
|
225
|
+
data: obsHistograms.fetchedData?.[obs.values[index]],
|
|
226
|
+
isPending: obsHistograms.isPending,
|
|
227
|
+
altColor: isSliced
|
|
228
|
+
} : {
|
|
229
|
+
data: null,
|
|
230
|
+
isPending: false
|
|
231
|
+
}
|
|
189
232
|
};
|
|
190
|
-
};
|
|
233
|
+
}, [dataset.colorEncoding, isSliced, obs.codes, obs.omit, obs.value_counts, obs.values, obsHistograms.fetchedData, obsHistograms.isPending, totalCounts]);
|
|
234
|
+
showColor &= dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS;
|
|
191
235
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactBootstrap.ListGroup, {
|
|
192
236
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.ListGroup.Item, {
|
|
193
237
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ObsToolbar.ObsToolbar, {
|
|
@@ -312,7 +356,7 @@ function ContinuousObs(_ref4) {
|
|
|
312
356
|
const ENDPOINT = "obs/bins";
|
|
313
357
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
314
358
|
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
315
|
-
const binnedObs = binContinuous(obs);
|
|
359
|
+
const binnedObs = binContinuous(obs, _lodash.default.min([N_BINS, obs.n_unique]));
|
|
316
360
|
const params = {
|
|
317
361
|
url: dataset.url,
|
|
318
362
|
obsCol: binnedObs.name,
|
|
@@ -25,6 +25,9 @@ function ObsColsList(_ref) {
|
|
|
25
25
|
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
26
26
|
const [obsCols, setObsCols] = (0, _react.useState)(null);
|
|
27
27
|
const [active, setActive] = (0, _react.useState)(dataset.selectedObs?.name);
|
|
28
|
+
const [expandedItems, setExpandedItems] = (0, _react.useState)(active ? {
|
|
29
|
+
[active]: true
|
|
30
|
+
} : {});
|
|
28
31
|
const [params, setParams] = (0, _react.useState)({
|
|
29
32
|
url: dataset.url
|
|
30
33
|
});
|
|
@@ -79,6 +82,18 @@ function ObsColsList(_ref) {
|
|
|
79
82
|
};
|
|
80
83
|
});
|
|
81
84
|
};
|
|
85
|
+
const handleAccordionToggle = itemName => {
|
|
86
|
+
_lodash.default.delay(
|
|
87
|
+
// to avoid contents of accordion disappearing while closing
|
|
88
|
+
() => {
|
|
89
|
+
setExpandedItems(prev => {
|
|
90
|
+
return {
|
|
91
|
+
...prev,
|
|
92
|
+
[itemName]: !prev[itemName]
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
}, expandedItems[itemName] ? 250 : 0);
|
|
96
|
+
};
|
|
82
97
|
const toggleAll = item => {
|
|
83
98
|
const omit = item.omit.length ? [] : _lodash.default.map(item.values, v => item.codes[v]);
|
|
84
99
|
setObsCols(o => {
|
|
@@ -168,9 +183,10 @@ function ObsColsList(_ref) {
|
|
|
168
183
|
eventKey: item.name,
|
|
169
184
|
className: active === item.name && dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && "cherita-accordion-active",
|
|
170
185
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Accordion.Header, {
|
|
186
|
+
onClick: () => handleAccordionToggle(item.name),
|
|
171
187
|
children: item.name
|
|
172
188
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Accordion.Body, {
|
|
173
|
-
children: item.type === _constants.OBS_TYPES.CATEGORICAL || item.type === _constants.OBS_TYPES.BOOLEAN ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_ObsItem.CategoricalObs, {
|
|
189
|
+
children: expandedItems[item.name] && (item.type === _constants.OBS_TYPES.CATEGORICAL || item.type === _constants.OBS_TYPES.BOOLEAN ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_ObsItem.CategoricalObs, {
|
|
174
190
|
obs: item,
|
|
175
191
|
updateObs: updateObs,
|
|
176
192
|
toggleAll: () => toggleAll(item),
|
|
@@ -187,7 +203,7 @@ function ObsColsList(_ref) {
|
|
|
187
203
|
toggleLabel: () => toggleLabel(item),
|
|
188
204
|
toggleSlice: () => toggleSlice(item),
|
|
189
205
|
toggleColor: () => toggleColor(item)
|
|
190
|
-
}, item.name)
|
|
206
|
+
}, item.name))
|
|
191
207
|
})]
|
|
192
208
|
}, item.name);
|
|
193
209
|
});
|
|
@@ -198,7 +214,7 @@ function ObsColsList(_ref) {
|
|
|
198
214
|
className: "list-group overflow-auto h-100",
|
|
199
215
|
children: [isPending && /*#__PURE__*/(0, _jsxRuntime.jsx)(_LoadingIndicators.LoadingSpinner, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactBootstrap.Accordion, {
|
|
200
216
|
flush: true,
|
|
201
|
-
defaultActiveKey: active,
|
|
217
|
+
defaultActiveKey: [active],
|
|
202
218
|
alwaysOpen: true,
|
|
203
219
|
children: obsList
|
|
204
220
|
})]
|
|
@@ -12,6 +12,7 @@ var _reactPlotly = _interopRequireDefault(require("react-plotly.js"));
|
|
|
12
12
|
var _PseudospatialToolbar = require("./PseudospatialToolbar");
|
|
13
13
|
var _constants = require("../../constants/constants");
|
|
14
14
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
15
|
+
var _FilterContext = require("../../context/FilterContext");
|
|
15
16
|
var _colorHelper = require("../../helpers/color-helper");
|
|
16
17
|
var _ImageViewer = require("../../utils/ImageViewer");
|
|
17
18
|
var _Legend = require("../../utils/Legend");
|
|
@@ -24,16 +25,19 @@ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e;
|
|
|
24
25
|
function usePseudospatialData(plotType) {
|
|
25
26
|
const ENDPOINT = "pseudospatial";
|
|
26
27
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
28
|
+
const filteredData = (0, _FilterContext.useFilteredData)();
|
|
29
|
+
const isSliced = dataset.sliceBy.obs || dataset.sliceBy.polygons;
|
|
27
30
|
const baseParams = (0, _react.useMemo)(() => {
|
|
28
31
|
return {
|
|
29
32
|
url: dataset.url,
|
|
30
33
|
maskSet: dataset.pseudospatial.maskSet,
|
|
31
34
|
maskValues: dataset.pseudospatial.maskValues,
|
|
35
|
+
obsIndices: isSliced ? [...(filteredData.obsIndices || [])] : null,
|
|
32
36
|
varNamesCol: dataset.varNamesCol,
|
|
33
37
|
showColorbar: false,
|
|
34
38
|
format: "json"
|
|
35
39
|
};
|
|
36
|
-
}, [dataset.url, dataset.pseudospatial.maskSet, dataset.pseudospatial.maskValues, dataset.varNamesCol]);
|
|
40
|
+
}, [dataset.url, dataset.pseudospatial.maskSet, dataset.pseudospatial.maskValues, dataset.varNamesCol, isSliced, filteredData.obsIndices]);
|
|
37
41
|
const getPlotParams = (0, _react.useCallback)(() => {
|
|
38
42
|
if (plotType === _constants.PSEUDOSPATIAL_PLOT_TYPES.GENE) {
|
|
39
43
|
return {
|
|
@@ -59,7 +59,9 @@ function MaskSet() {
|
|
|
59
59
|
fetchedData,
|
|
60
60
|
isPending,
|
|
61
61
|
serverError
|
|
62
|
-
} = (0, _requests.useFetch)(ENDPOINT, params
|
|
62
|
+
} = (0, _requests.useFetch)(ENDPOINT, params, {
|
|
63
|
+
refetchOnMount: false
|
|
64
|
+
});
|
|
63
65
|
(0, _react.useEffect)(() => {
|
|
64
66
|
if (!isPending && !serverError) {
|
|
65
67
|
setMaskSets(fetchedData);
|
|
@@ -11,16 +11,15 @@ var _freeSolidSvgIcons = require("@fortawesome/free-solid-svg-icons");
|
|
|
11
11
|
var _reactFontawesome = require("@fortawesome/react-fontawesome");
|
|
12
12
|
var _editModes = require("@nebula.gl/edit-modes");
|
|
13
13
|
var _layers2 = require("@nebula.gl/layers");
|
|
14
|
-
var _turf = require("@turf/turf");
|
|
15
14
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
16
15
|
var _reactBootstrap = require("react-bootstrap");
|
|
17
16
|
var _SpatialControls = require("./SpatialControls");
|
|
18
17
|
var _Toolbox = require("./Toolbox");
|
|
19
18
|
var _constants = require("../../constants/constants");
|
|
20
19
|
var _DatasetContext = require("../../context/DatasetContext");
|
|
21
|
-
var _FilterContext = require("../../context/FilterContext");
|
|
22
20
|
var _colorHelper = require("../../helpers/color-helper");
|
|
23
21
|
var _mapHelper = require("../../helpers/map-helper");
|
|
22
|
+
var _Filter = require("../../utils/Filter");
|
|
24
23
|
var _Legend = require("../../utils/Legend");
|
|
25
24
|
var _LoadingIndicators = require("../../utils/LoadingIndicators");
|
|
26
25
|
var _string = require("../../utils/string");
|
|
@@ -38,14 +37,12 @@ const INITIAL_VIEW_STATE = {
|
|
|
38
37
|
pitch: 0,
|
|
39
38
|
bearing: 0
|
|
40
39
|
};
|
|
41
|
-
const EPSILON = 1e-6;
|
|
42
40
|
function Scatterplot(_ref) {
|
|
43
41
|
let {
|
|
44
42
|
radius = 30
|
|
45
43
|
} = _ref;
|
|
46
44
|
const dataset = (0, _DatasetContext.useDataset)();
|
|
47
45
|
const dispatch = (0, _DatasetContext.useDatasetDispatch)();
|
|
48
|
-
const filterDispatch = (0, _FilterContext.useFilteredDataDispatch)();
|
|
49
46
|
const {
|
|
50
47
|
getColor
|
|
51
48
|
} = (0, _colorHelper.useColor)();
|
|
@@ -72,6 +69,12 @@ function Scatterplot(_ref) {
|
|
|
72
69
|
const labelObsData = (0, _zarrData.useLabelObsData)();
|
|
73
70
|
// @TODO: assert length of obsmData, xData, obsData is equal
|
|
74
71
|
|
|
72
|
+
const {
|
|
73
|
+
filteredIndices,
|
|
74
|
+
valueMin,
|
|
75
|
+
valueMax,
|
|
76
|
+
slicedLength
|
|
77
|
+
} = (0, _Filter.useFilter)(data, features);
|
|
75
78
|
(0, _react.useEffect)(() => {
|
|
76
79
|
if (!obsmData.isPending && !obsmData.serverError) {
|
|
77
80
|
setIsRendering(true);
|
|
@@ -187,101 +190,6 @@ function Scatterplot(_ref) {
|
|
|
187
190
|
return false;
|
|
188
191
|
}
|
|
189
192
|
}, [dataset.colorEncoding, dataset.selectedObs?.type]);
|
|
190
|
-
const isInBins = (v, binEdges, indices) => {
|
|
191
|
-
const lastEdge = _lodash.default.last(binEdges);
|
|
192
|
-
const allButLastEdges = _lodash.default.initial(binEdges);
|
|
193
|
-
// add epsilon to last edge to include the last value
|
|
194
|
-
const modifiedBinEdges = [...allButLastEdges, [lastEdge[0], lastEdge[1] + EPSILON]];
|
|
195
|
-
const binIndices = _lodash.default.difference(_lodash.default.range(binEdges.length), indices);
|
|
196
|
-
const ranges = _lodash.default.at(modifiedBinEdges, binIndices);
|
|
197
|
-
return _lodash.default.some(ranges, range => _lodash.default.inRange(v, ...range));
|
|
198
|
-
};
|
|
199
|
-
const isInSlice = (0, _react.useCallback)((index, values, positions) => {
|
|
200
|
-
let inSlice = true;
|
|
201
|
-
if (isCategorical && values) {
|
|
202
|
-
inSlice &= !_lodash.default.includes(dataset.selectedObs?.omit, values[index]);
|
|
203
|
-
} else if ((dataset.sliceBy.obs || dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS && dataset.selectedObs?.type === _constants.OBS_TYPES.CONTINUOUS) && !!dataset.selectedObs?.omit.length && values) {
|
|
204
|
-
if (dataset.selectedObs.type === _constants.OBS_TYPES.CATEGORICAL) {
|
|
205
|
-
inSlice &= !_lodash.default.includes(dataset.selectedObs.omit, values[index]);
|
|
206
|
-
} else if (dataset.selectedObs.type === _constants.OBS_TYPES.CONTINUOUS) {
|
|
207
|
-
if (isNaN(values[index])) {
|
|
208
|
-
inSlice &= !_lodash.default.includes(dataset.selectedObs.omit, -1);
|
|
209
|
-
} else {
|
|
210
|
-
inSlice &= isInBins(values[index], dataset.selectedObs.bins.binEdges, _lodash.default.without(dataset.selectedObs.omit, -1));
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
if (dataset.sliceBy.polygons && positions) {
|
|
215
|
-
inSlice &= _lodash.default.some(features?.features, (_f, i) => {
|
|
216
|
-
return (0, _turf.booleanPointInPolygon)((0, _turf.point)([positions[index][0], positions[index][1]]), features.features[i]);
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
return inSlice;
|
|
220
|
-
}, [dataset.colorEncoding, dataset.selectedObs?.bins?.binEdges, dataset.selectedObs?.omit, dataset.selectedObs?.type, dataset.sliceBy.obs, dataset.sliceBy.polygons, features.features, isCategorical]);
|
|
221
|
-
|
|
222
|
-
// @TODO: abstract filtering out of this component, maybe in FilterContext ?
|
|
223
|
-
const {
|
|
224
|
-
filteredIndices,
|
|
225
|
-
valueMin,
|
|
226
|
-
valueMax,
|
|
227
|
-
slicedLength
|
|
228
|
-
} = (0, _react.useMemo)(() => {
|
|
229
|
-
if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.VAR) {
|
|
230
|
-
const {
|
|
231
|
-
filtered,
|
|
232
|
-
filteredIndices
|
|
233
|
-
} = _lodash.default.reduce(data.values, (acc, v, i) => {
|
|
234
|
-
if (isInSlice(i, data.sliceValues, data.positions)) {
|
|
235
|
-
acc.filtered.push(v);
|
|
236
|
-
acc.filteredIndices.add(i);
|
|
237
|
-
}
|
|
238
|
-
return acc;
|
|
239
|
-
}, {
|
|
240
|
-
filtered: [],
|
|
241
|
-
filteredIndices: new Set()
|
|
242
|
-
});
|
|
243
|
-
return {
|
|
244
|
-
filteredIndices: filteredIndices,
|
|
245
|
-
valueMin: _lodash.default.min(filtered),
|
|
246
|
-
valueMax: _lodash.default.max(filtered),
|
|
247
|
-
slicedLength: filtered.length
|
|
248
|
-
};
|
|
249
|
-
} else if (dataset.colorEncoding === _constants.COLOR_ENCODINGS.OBS) {
|
|
250
|
-
const isContinuous = dataset.selectedObs?.type === _constants.OBS_TYPES.CONTINUOUS;
|
|
251
|
-
const {
|
|
252
|
-
filtered,
|
|
253
|
-
filteredIndices
|
|
254
|
-
} = _lodash.default.reduce(data.values, (acc, v, i) => {
|
|
255
|
-
if (isInSlice(i, data.values, data.positions)) {
|
|
256
|
-
acc.filtered.push(v);
|
|
257
|
-
acc.filteredIndices.add(i);
|
|
258
|
-
}
|
|
259
|
-
return acc;
|
|
260
|
-
}, {
|
|
261
|
-
filtered: [],
|
|
262
|
-
filteredIndices: new Set()
|
|
263
|
-
});
|
|
264
|
-
return {
|
|
265
|
-
filteredIndices: filteredIndices,
|
|
266
|
-
valueMin: _lodash.default.min(isContinuous ? filtered : data.values),
|
|
267
|
-
valueMax: _lodash.default.max(isContinuous ? filtered : data.values),
|
|
268
|
-
slicedLength: filtered.length
|
|
269
|
-
};
|
|
270
|
-
} else {
|
|
271
|
-
return {
|
|
272
|
-
filteredIndices: null,
|
|
273
|
-
valueMin: _lodash.default.min(data.values),
|
|
274
|
-
valueMax: _lodash.default.max(data.values),
|
|
275
|
-
slicedLength: data.values.length
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
}, [data.positions, data.sliceValues, data.values, dataset.colorEncoding, dataset.selectedObs?.type, isInSlice]);
|
|
279
|
-
(0, _react.useEffect)(() => {
|
|
280
|
-
filterDispatch({
|
|
281
|
-
type: "set.obs.indices",
|
|
282
|
-
indices: dataset.sliceBy.obs || dataset.sliceBy.polygons ? filteredIndices : null
|
|
283
|
-
});
|
|
284
|
-
}, [dataset.sliceBy.obs, dataset.sliceBy.polygons, filterDispatch, filteredIndices]);
|
|
285
193
|
(0, _react.useEffect)(() => {
|
|
286
194
|
dispatch({
|
|
287
195
|
type: "set.controls.valueRange",
|