@haniffalab/cherita-react 1.3.0 → 1.3.1-dev.2025-10-29.6de4119f
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/README.md +1 -1
- package/dist/cjs/components/controls/Controls.js +38 -30
- package/dist/cjs/components/dotplot/Dotplot.js +85 -57
- package/dist/cjs/components/dotplot/DotplotControls.js +103 -83
- package/dist/cjs/components/full-page/FullPage.js +167 -114
- package/dist/cjs/components/full-page/PlotAlert.js +45 -0
- package/dist/cjs/components/full-page/PlotTypeSelector.js +102 -0
- package/dist/cjs/components/heatmap/Heatmap.js +83 -53
- package/dist/cjs/components/heatmap/HeatmapControls.js +6 -3
- package/dist/cjs/components/icons/DotPlotIcon.js +64 -0
- package/dist/cjs/components/icons/HeatmapIcon.js +45 -0
- package/dist/cjs/components/icons/MatrixPlotIcon.1.js +57 -0
- package/dist/cjs/components/icons/MatrixPlotIcon.js +59 -0
- package/dist/cjs/components/icons/ScatterplotIcon.1.js +164 -0
- package/dist/cjs/components/icons/ScatterplotIcon.js +144 -0
- package/dist/cjs/components/icons/ViolinPlotIcon.js +42 -0
- package/dist/cjs/components/matrixplot/Matrixplot.js +83 -54
- package/dist/cjs/components/matrixplot/MatrixplotControls.js +8 -5
- package/dist/cjs/components/obs-list/ObsItem.js +305 -216
- package/dist/cjs/components/obs-list/ObsList.js +164 -128
- package/dist/cjs/components/obs-list/ObsToolbar.js +2 -3
- package/dist/cjs/components/obsm-list/ObsmList.js +67 -28
- package/dist/cjs/components/offcanvas/index.js +62 -27
- package/dist/cjs/components/pseudospatial/Pseudospatial.js +132 -76
- package/dist/cjs/components/pseudospatial/PseudospatialToolbar.js +122 -74
- package/dist/cjs/components/scatterplot/Scatterplot.js +223 -175
- package/dist/cjs/components/scatterplot/ScatterplotControls.js +45 -31
- package/dist/cjs/components/scatterplot/SpatialControls.js +143 -116
- package/dist/cjs/components/scatterplot/Toolbox.js +41 -30
- package/dist/cjs/components/search-bar/SearchBar.js +176 -120
- package/dist/cjs/components/search-bar/SearchInfo.js +79 -85
- package/dist/cjs/components/search-bar/SearchResults.js +93 -71
- package/dist/cjs/components/toolbar/Toolbar.js +111 -0
- package/dist/cjs/components/var-list/VarItem.js +131 -103
- package/dist/cjs/components/var-list/VarList.js +96 -74
- package/dist/cjs/components/var-list/VarListToolbar.js +59 -54
- package/dist/cjs/components/var-list/VarSet.js +126 -108
- package/dist/cjs/components/violin/Violin.js +124 -81
- package/dist/cjs/components/violin/ViolinControls.js +8 -5
- package/dist/cjs/constants/colorscales.js +19 -19
- package/dist/cjs/constants/constants.js +54 -39
- package/dist/cjs/context/DatasetContext.js +27 -17
- package/dist/cjs/context/FilterContext.js +11 -9
- package/dist/cjs/context/SettingsContext.js +339 -125
- package/dist/cjs/context/ZarrDataContext.js +6 -5
- package/dist/cjs/helpers/color-helper.js +2 -2
- package/dist/cjs/helpers/map-helper.js +2 -1
- package/dist/cjs/helpers/zarr-helper.js +3 -3
- package/dist/cjs/index.js +15 -21
- package/dist/cjs/utils/Filter.js +16 -11
- package/dist/cjs/utils/Histogram.js +35 -33
- package/dist/cjs/utils/ImageViewer.js +11 -8
- package/dist/cjs/utils/Legend.js +37 -30
- package/dist/cjs/utils/LoadingIndicators.js +15 -13
- package/dist/cjs/utils/Resolver.js +213 -0
- package/dist/cjs/utils/Skeleton.js +10 -10
- package/dist/cjs/utils/StyledTooltip.js +44 -0
- package/dist/cjs/utils/VirtualizedList.js +36 -29
- package/dist/cjs/utils/errors.js +15 -15
- package/dist/cjs/utils/requests.js +21 -9
- package/dist/cjs/utils/search.js +4 -4
- package/dist/cjs/utils/string.js +6 -6
- package/dist/cjs/utils/zarrData.js +20 -21
- package/dist/css/cherita.css +188 -65
- package/dist/css/cherita.css.map +1 -1
- package/dist/esm/components/controls/Controls.js +43 -35
- package/dist/esm/components/dotplot/Dotplot.js +93 -64
- package/dist/esm/components/dotplot/DotplotControls.js +106 -85
- package/dist/esm/components/full-page/FullPage.js +180 -124
- package/dist/esm/components/full-page/PlotAlert.js +39 -0
- package/dist/esm/components/full-page/PlotTypeSelector.js +95 -0
- package/dist/esm/components/heatmap/Heatmap.js +91 -60
- package/dist/esm/components/heatmap/HeatmapControls.js +8 -4
- package/dist/esm/components/icons/DotPlotIcon.js +58 -0
- package/dist/esm/components/icons/HeatmapIcon.js +39 -0
- package/dist/esm/components/icons/MatrixPlotIcon.1.js +51 -0
- package/dist/esm/components/icons/MatrixPlotIcon.js +53 -0
- package/dist/esm/components/icons/ScatterplotIcon.1.js +158 -0
- package/dist/esm/components/icons/ScatterplotIcon.js +138 -0
- package/dist/esm/components/icons/ViolinPlotIcon.js +36 -0
- package/dist/esm/components/matrixplot/Matrixplot.js +91 -61
- package/dist/esm/components/matrixplot/MatrixplotControls.js +10 -6
- package/dist/esm/components/obs-list/ObsItem.js +320 -228
- package/dist/esm/components/obs-list/ObsList.js +179 -142
- package/dist/esm/components/obs-list/ObsToolbar.js +3 -3
- package/dist/esm/components/obsm-list/ObsmList.js +71 -32
- package/dist/esm/components/offcanvas/index.js +68 -33
- package/dist/esm/components/pseudospatial/Pseudospatial.js +145 -88
- package/dist/esm/components/pseudospatial/PseudospatialToolbar.js +127 -78
- package/dist/esm/components/scatterplot/Scatterplot.js +243 -194
- package/dist/esm/components/scatterplot/ScatterplotControls.js +50 -35
- package/dist/esm/components/scatterplot/SpatialControls.js +155 -127
- package/dist/esm/components/scatterplot/Toolbox.js +44 -32
- package/dist/esm/components/search-bar/SearchBar.js +187 -130
- package/dist/esm/components/search-bar/SearchInfo.js +86 -91
- package/dist/esm/components/search-bar/SearchResults.js +100 -77
- package/dist/esm/components/toolbar/Toolbar.js +101 -0
- package/dist/esm/components/var-list/VarItem.js +142 -113
- package/dist/esm/components/var-list/VarList.js +108 -88
- package/dist/esm/components/var-list/VarListToolbar.js +64 -58
- package/dist/esm/components/var-list/VarSet.js +134 -115
- package/dist/esm/components/violin/Violin.js +135 -91
- package/dist/esm/components/violin/ViolinControls.js +10 -6
- package/dist/esm/constants/colorscales.js +19 -19
- package/dist/esm/constants/constants.js +53 -38
- package/dist/esm/context/DatasetContext.js +34 -23
- package/dist/esm/context/FilterContext.js +11 -8
- package/dist/esm/context/SettingsContext.js +341 -126
- package/dist/esm/context/ZarrDataContext.js +8 -6
- package/dist/esm/helpers/color-helper.js +5 -5
- package/dist/esm/helpers/map-helper.js +4 -3
- package/dist/esm/helpers/zarr-helper.js +6 -6
- package/dist/esm/index.js +22 -22
- package/dist/esm/utils/Filter.js +22 -17
- package/dist/esm/utils/Histogram.js +39 -37
- package/dist/esm/utils/ImageViewer.js +12 -8
- package/dist/esm/utils/Legend.js +44 -36
- package/dist/esm/utils/LoadingIndicators.js +16 -13
- package/dist/esm/utils/Resolver.js +201 -0
- package/dist/esm/utils/Skeleton.js +11 -10
- package/dist/esm/utils/StyledTooltip.js +38 -0
- package/dist/esm/utils/VirtualizedList.js +37 -29
- package/dist/esm/utils/errors.js +15 -15
- package/dist/esm/utils/requests.js +24 -12
- package/dist/esm/utils/search.js +7 -7
- package/dist/esm/utils/string.js +7 -7
- package/dist/esm/utils/zarrData.js +27 -28
- package/package.json +24 -10
- package/scss/cherita-bootstrap.scss +2 -2
- package/scss/cherita.scss +65 -17
- package/scss/components/accordions.scss +15 -2
- package/scss/components/layouts.scss +116 -30
- package/scss/components/lists.scss +16 -5
- package/scss/components/plotly.scss +40 -23
- package/scss/components/plots.scss +14 -1
- package/dist/cjs/components/full-page/FullPagePseudospatial.js +0 -157
- package/dist/esm/components/full-page/FullPagePseudospatial.js +0 -149
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
3
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
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
|
+
import { useState } from 'react';
|
|
7
|
+
import { PLOT_TYPES } from '../../constants/constants';
|
|
8
|
+
import { StyledTooltip } from '../../utils/StyledTooltip';
|
|
9
|
+
import DotPlotIcon from '../icons/DotPlotIcon';
|
|
10
|
+
import HeatmapIcon from '../icons/HeatmapIcon';
|
|
11
|
+
import MatrixPlotIcon from '../icons/MatrixPlotIcon';
|
|
12
|
+
import ScatterplotIcon from '../icons/ScatterplotIcon';
|
|
13
|
+
import ViolinPlotIcon from '../icons/ViolinPlotIcon';
|
|
14
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
|
+
const plotTypes = [{
|
|
16
|
+
type: PLOT_TYPES.SCATTERPLOT,
|
|
17
|
+
icon: ScatterplotIcon,
|
|
18
|
+
name: 'Scatterplot',
|
|
19
|
+
description: 'Displays cells in 2D based on dimensionality reduction.'
|
|
20
|
+
}, {
|
|
21
|
+
type: PLOT_TYPES.MATRIXPLOT,
|
|
22
|
+
icon: MatrixPlotIcon,
|
|
23
|
+
name: 'Matrix Plot',
|
|
24
|
+
description: 'Shows expression values of genes across categories.'
|
|
25
|
+
}, {
|
|
26
|
+
type: PLOT_TYPES.DOTPLOT,
|
|
27
|
+
icon: DotPlotIcon,
|
|
28
|
+
name: 'Dot Plot',
|
|
29
|
+
description: 'Shows proportion and expression of genes across groups.'
|
|
30
|
+
}, {
|
|
31
|
+
type: PLOT_TYPES.HEATMAP,
|
|
32
|
+
icon: HeatmapIcon,
|
|
33
|
+
name: 'Heatmap',
|
|
34
|
+
description: 'Visualises gene expression or feature activity as a colour-coded matrix.'
|
|
35
|
+
}, {
|
|
36
|
+
type: PLOT_TYPES.VIOLINPLOT,
|
|
37
|
+
icon: ViolinPlotIcon,
|
|
38
|
+
name: 'Violin Plot',
|
|
39
|
+
description: 'Displays distribution of gene expression across categories.'
|
|
40
|
+
}];
|
|
41
|
+
export function PlotTypeSelector(_ref) {
|
|
42
|
+
let {
|
|
43
|
+
currentType,
|
|
44
|
+
onChange
|
|
45
|
+
} = _ref;
|
|
46
|
+
const [hoveredMap, setHoveredMap] = useState({});
|
|
47
|
+
const handleMouseEnter = type => setHoveredMap(prev => _objectSpread(_objectSpread({}, prev), {}, {
|
|
48
|
+
[type]: true
|
|
49
|
+
}));
|
|
50
|
+
const handleMouseLeave = type => setHoveredMap(prev => _objectSpread(_objectSpread({}, prev), {}, {
|
|
51
|
+
[type]: false
|
|
52
|
+
}));
|
|
53
|
+
return /*#__PURE__*/_jsx("div", {
|
|
54
|
+
className: "d-flex gap-2 justify-content-between",
|
|
55
|
+
children: plotTypes.map(_ref2 => {
|
|
56
|
+
let {
|
|
57
|
+
type,
|
|
58
|
+
icon: Icon,
|
|
59
|
+
name,
|
|
60
|
+
description
|
|
61
|
+
} = _ref2;
|
|
62
|
+
const isActive = currentType === type;
|
|
63
|
+
const hovered = hoveredMap[type] || false;
|
|
64
|
+
const colour = isActive ? '#005a86' : hovered ? '#0071a7' : '#000';
|
|
65
|
+
return /*#__PURE__*/_jsx(StyledTooltip, {
|
|
66
|
+
title: /*#__PURE__*/_jsxs(_Fragment, {
|
|
67
|
+
children: [/*#__PURE__*/_jsx("strong", {
|
|
68
|
+
children: name
|
|
69
|
+
}), /*#__PURE__*/_jsx("br", {}), description]
|
|
70
|
+
}),
|
|
71
|
+
placement: "bottom",
|
|
72
|
+
slotProps: {
|
|
73
|
+
popper: {
|
|
74
|
+
modifiers: [{
|
|
75
|
+
name: 'offset',
|
|
76
|
+
options: {
|
|
77
|
+
offset: [0, -12]
|
|
78
|
+
}
|
|
79
|
+
}]
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
83
|
+
onMouseEnter: () => handleMouseEnter(type),
|
|
84
|
+
onMouseLeave: () => handleMouseLeave(type),
|
|
85
|
+
onClick: () => onChange(type),
|
|
86
|
+
className: "plotselector-icon".concat(isActive ? ' active' : ''),
|
|
87
|
+
children: /*#__PURE__*/_jsx(Icon, {
|
|
88
|
+
size: 34,
|
|
89
|
+
colour: colour
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
}, type);
|
|
93
|
+
})
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -3,18 +3,32 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
3
3
|
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
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
|
-
import
|
|
7
|
-
import _ from
|
|
8
|
-
import {
|
|
9
|
-
import Plot from
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
6
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
7
|
+
import _ from 'lodash';
|
|
8
|
+
import { Button } from 'react-bootstrap';
|
|
9
|
+
import Plot from 'react-plotly.js';
|
|
10
|
+
import { PLOTLY_MODEBAR_BUTTONS } from '../../constants/constants';
|
|
11
|
+
import { useDataset } from '../../context/DatasetContext';
|
|
12
|
+
import { useFilteredData } from '../../context/FilterContext';
|
|
13
|
+
import { useSettings } from '../../context/SettingsContext';
|
|
14
|
+
import { LoadingSpinner } from '../../utils/LoadingIndicators';
|
|
15
|
+
import { useDebouncedFetch } from '../../utils/requests';
|
|
16
|
+
import { useSelectedMultiVar, useSelectedObs } from '../../utils/Resolver';
|
|
17
|
+
import { PlotAlert } from '../full-page/PlotAlert';
|
|
18
|
+
import { ControlsPlotlyToolbar, ObsPlotlyToolbar, VarPlotlyToolbar } from '../toolbar/Toolbar';
|
|
19
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
|
+
export function Heatmap(_ref) {
|
|
21
|
+
let {
|
|
22
|
+
showObsBtn = false,
|
|
23
|
+
showVarsBtn = false,
|
|
24
|
+
showCtrlsBtn = false,
|
|
25
|
+
setShowObs,
|
|
26
|
+
setShowVars,
|
|
27
|
+
setShowControls,
|
|
28
|
+
plotType,
|
|
29
|
+
setPlotType
|
|
30
|
+
} = _ref;
|
|
31
|
+
const ENDPOINT = 'heatmap';
|
|
18
32
|
const dataset = useDataset();
|
|
19
33
|
const settings = useSettings();
|
|
20
34
|
const {
|
|
@@ -25,44 +39,26 @@ export function Heatmap() {
|
|
|
25
39
|
const [data, setData] = useState([]);
|
|
26
40
|
const [layout, setLayout] = useState({});
|
|
27
41
|
const [hasSelections, setHasSelections] = useState(false);
|
|
28
|
-
const
|
|
42
|
+
const selectedObs = useSelectedObs();
|
|
43
|
+
const selectedMultiVar = useSelectedMultiVar();
|
|
44
|
+
const params = useMemo(() => ({
|
|
29
45
|
url: dataset.url,
|
|
30
|
-
obsCol:
|
|
31
|
-
obsValues: !(
|
|
32
|
-
|
|
33
|
-
return (_settings$selectedObs4 = settings.selectedObs) === null || _settings$selectedObs4 === void 0 ? void 0 : _settings$selectedObs4.codesMap[c];
|
|
34
|
-
}),
|
|
35
|
-
varKeys: settings.selectedMultiVar.map(i => i.isSet ? {
|
|
46
|
+
obsCol: selectedObs,
|
|
47
|
+
obsValues: !(selectedObs !== null && selectedObs !== void 0 && selectedObs.omit.length) ? null : _.difference(selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.values, selectedObs === null || selectedObs === void 0 ? void 0 : selectedObs.omit),
|
|
48
|
+
varKeys: selectedMultiVar.map(i => i.isSet ? {
|
|
36
49
|
name: i.name,
|
|
37
50
|
indices: i.vars.map(v => v.index)
|
|
38
51
|
} : i.index),
|
|
39
52
|
obsIndices: isSliced ? [...(obsIndices || [])] : null,
|
|
40
53
|
varNamesCol: dataset.varNamesCol
|
|
41
|
-
});
|
|
54
|
+
}), [dataset.url, dataset.varNamesCol, isSliced, obsIndices, selectedMultiVar, selectedObs]);
|
|
42
55
|
useEffect(() => {
|
|
43
|
-
if (
|
|
56
|
+
if (selectedObs && selectedMultiVar.length) {
|
|
44
57
|
setHasSelections(true);
|
|
45
58
|
} else {
|
|
46
59
|
setHasSelections(false);
|
|
47
60
|
}
|
|
48
|
-
|
|
49
|
-
var _settings$selectedObs5, _settings$selectedObs6, _settings$selectedObs7;
|
|
50
|
-
return _objectSpread(_objectSpread({}, p), {}, {
|
|
51
|
-
url: dataset.url,
|
|
52
|
-
obsCol: settings.selectedObs,
|
|
53
|
-
obsValues: !((_settings$selectedObs5 = settings.selectedObs) !== null && _settings$selectedObs5 !== void 0 && _settings$selectedObs5.omit.length) ? null : _.difference(_.values((_settings$selectedObs6 = settings.selectedObs) === null || _settings$selectedObs6 === void 0 ? void 0 : _settings$selectedObs6.codes), (_settings$selectedObs7 = settings.selectedObs) === null || _settings$selectedObs7 === void 0 ? void 0 : _settings$selectedObs7.omit).map(c => {
|
|
54
|
-
var _settings$selectedObs8;
|
|
55
|
-
return (_settings$selectedObs8 = settings.selectedObs) === null || _settings$selectedObs8 === void 0 ? void 0 : _settings$selectedObs8.codesMap[c];
|
|
56
|
-
}),
|
|
57
|
-
varKeys: settings.selectedMultiVar.map(i => i.isSet ? {
|
|
58
|
-
name: i.name,
|
|
59
|
-
indices: i.vars.map(v => v.index)
|
|
60
|
-
} : i.index),
|
|
61
|
-
obsIndices: isSliced ? [...(obsIndices || [])] : null,
|
|
62
|
-
varNamesCol: dataset.varNamesCol
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
}, [settings.selectedMultiVar, settings.selectedObs, dataset.url, dataset.varNamesCol, obsIndices, isSliced]);
|
|
61
|
+
}, [selectedMultiVar, selectedObs, dataset.url, dataset.varNamesCol, obsIndices, isSliced]);
|
|
66
62
|
const updateColorscale = useCallback(colorscale => {
|
|
67
63
|
setLayout(l => {
|
|
68
64
|
return _objectSpread(_objectSpread({}, l), {}, {
|
|
@@ -77,41 +73,76 @@ export function Heatmap() {
|
|
|
77
73
|
isPending,
|
|
78
74
|
serverError
|
|
79
75
|
} = useDebouncedFetch(ENDPOINT, params, 500, {
|
|
80
|
-
|
|
76
|
+
isEnabled: params => !!params.obsCol && !!params.varKeys.length
|
|
81
77
|
});
|
|
82
78
|
useEffect(() => {
|
|
83
|
-
if (hasSelections && !isPending && !serverError) {
|
|
79
|
+
if (hasSelections && !!fetchedData && !isPending && !serverError) {
|
|
84
80
|
setData(fetchedData.data);
|
|
85
81
|
setLayout(fetchedData.layout);
|
|
86
82
|
updateColorscale(colorscale.current);
|
|
83
|
+
} else {
|
|
84
|
+
setData([]);
|
|
85
|
+
setLayout({});
|
|
87
86
|
}
|
|
88
87
|
}, [fetchedData, hasSelections, isPending, serverError, updateColorscale]);
|
|
89
88
|
useEffect(() => {
|
|
90
89
|
colorscale.current = settings.controls.colorScale;
|
|
91
90
|
updateColorscale(colorscale.current);
|
|
92
91
|
}, [settings.controls.colorScale, updateColorscale]);
|
|
92
|
+
const customModeBarButtons = _.compact([showObsBtn && ObsPlotlyToolbar({
|
|
93
|
+
onClick: setShowObs
|
|
94
|
+
}), showVarsBtn && VarPlotlyToolbar({
|
|
95
|
+
onClick: setShowVars
|
|
96
|
+
}), showCtrlsBtn && ControlsPlotlyToolbar({
|
|
97
|
+
onClick: setShowControls
|
|
98
|
+
})]);
|
|
99
|
+
const modeBarButtons = customModeBarButtons.length ? [customModeBarButtons, PLOTLY_MODEBAR_BUTTONS] : [PLOTLY_MODEBAR_BUTTONS];
|
|
93
100
|
if (!serverError) {
|
|
94
101
|
if (hasSelections) {
|
|
95
|
-
return /*#__PURE__*/
|
|
96
|
-
className: "cherita-heatmap position-relative"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
103
|
+
className: "cherita-plot cherita-heatmap position-relative",
|
|
104
|
+
children: [isPending && /*#__PURE__*/_jsx(LoadingSpinner, {}), /*#__PURE__*/_jsx(Plot, {
|
|
105
|
+
data: data,
|
|
106
|
+
layout: layout,
|
|
107
|
+
useResizeHandler: true,
|
|
108
|
+
style: {
|
|
109
|
+
width: '100%',
|
|
110
|
+
height: '100%'
|
|
111
|
+
},
|
|
112
|
+
config: {
|
|
113
|
+
displaylogo: false,
|
|
114
|
+
modeBarButtons: modeBarButtons
|
|
115
|
+
}
|
|
116
|
+
})]
|
|
117
|
+
});
|
|
106
118
|
}
|
|
107
|
-
return /*#__PURE__*/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
119
|
+
return /*#__PURE__*/_jsx(PlotAlert, {
|
|
120
|
+
variant: "info",
|
|
121
|
+
heading: "Set up your heatmap",
|
|
122
|
+
plotType: plotType,
|
|
123
|
+
setPlotType: setPlotType,
|
|
124
|
+
children: /*#__PURE__*/_jsxs("p", {
|
|
125
|
+
className: "p-0 m-0",
|
|
126
|
+
children: ["Select one or more", ' ', showVarsBtn ? /*#__PURE__*/_jsx(Button, {
|
|
127
|
+
variant: "link",
|
|
128
|
+
className: "border-0 p-0 align-baseline",
|
|
129
|
+
onClick: setShowVars,
|
|
130
|
+
children: "features"
|
|
131
|
+
}) : 'features', ' ', "to display their expression, then choose a", ' ', showObsBtn ? /*#__PURE__*/_jsx(Button, {
|
|
132
|
+
variant: "link",
|
|
133
|
+
className: "border-0 p-0 align-baseline",
|
|
134
|
+
onClick: setShowObs,
|
|
135
|
+
children: "category"
|
|
136
|
+
}) : 'category', ' ', "to group observations in the heatmap."]
|
|
137
|
+
})
|
|
138
|
+
});
|
|
112
139
|
} else {
|
|
113
|
-
return /*#__PURE__*/
|
|
114
|
-
variant: "danger"
|
|
115
|
-
|
|
140
|
+
return /*#__PURE__*/_jsx(PlotAlert, {
|
|
141
|
+
variant: "danger",
|
|
142
|
+
heading: "Error displaying the heatmap",
|
|
143
|
+
plotType: plotType,
|
|
144
|
+
setPlotType: setPlotType,
|
|
145
|
+
children: serverError.message || 'An unexpected error occurred while generating the plot.'
|
|
146
|
+
});
|
|
116
147
|
}
|
|
117
148
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { Form } from 'react-bootstrap';
|
|
2
|
+
import { ColorscaleSelect } from '../controls/Controls';
|
|
3
|
+
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
4
4
|
export function HeatmapControls() {
|
|
5
|
-
return /*#__PURE__*/
|
|
5
|
+
return /*#__PURE__*/_jsx(_Fragment, {
|
|
6
|
+
children: /*#__PURE__*/_jsx(Form, {
|
|
7
|
+
children: /*#__PURE__*/_jsx(ColorscaleSelect, {})
|
|
8
|
+
})
|
|
9
|
+
});
|
|
6
10
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const _excluded = ["size", "colour", "gap"];
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
6
|
+
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); }
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
9
|
+
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; }
|
|
10
|
+
export default function DotPlotIcon(_ref) {
|
|
11
|
+
let {
|
|
12
|
+
size = 40,
|
|
13
|
+
colour = '#000',
|
|
14
|
+
gap = 20
|
|
15
|
+
} = _ref,
|
|
16
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
17
|
+
const rows = 3;
|
|
18
|
+
const cols = 3;
|
|
19
|
+
|
|
20
|
+
// Define two radii: small and large
|
|
21
|
+
const smallR = 10;
|
|
22
|
+
const largeR = 16;
|
|
23
|
+
|
|
24
|
+
// Indices for large circles
|
|
25
|
+
const largeIndices = [1, 4, 5, 6, 7];
|
|
26
|
+
|
|
27
|
+
// Indices for semi-transparent circles
|
|
28
|
+
const semiTransparentIndices = [0, 4, 8];
|
|
29
|
+
const circles = [];
|
|
30
|
+
for (let row = 0; row < rows; row++) {
|
|
31
|
+
for (let col = 0; col < cols; col++) {
|
|
32
|
+
const index = row * cols + col;
|
|
33
|
+
const r = largeIndices.includes(index) ? largeR : smallR;
|
|
34
|
+
circles.push({
|
|
35
|
+
cx: col * (2 * largeR + gap) + largeR,
|
|
36
|
+
cy: row * (2 * largeR + gap) + largeR,
|
|
37
|
+
r,
|
|
38
|
+
fill: colour,
|
|
39
|
+
fillOpacity: semiTransparentIndices.includes(index) ? 0.5 : 1
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const viewBoxSize = (cols - 1) * (2 * largeR + gap) + 2 * largeR;
|
|
44
|
+
return /*#__PURE__*/_jsx("svg", _objectSpread(_objectSpread({
|
|
45
|
+
width: size,
|
|
46
|
+
height: size,
|
|
47
|
+
viewBox: "0 0 ".concat(viewBoxSize, " ").concat(viewBoxSize),
|
|
48
|
+
xmlns: "http://www.w3.org/2000/svg"
|
|
49
|
+
}, props), {}, {
|
|
50
|
+
children: circles.map((circle, i) => /*#__PURE__*/_jsx("circle", {
|
|
51
|
+
cx: circle.cx,
|
|
52
|
+
cy: circle.cy,
|
|
53
|
+
r: circle.r,
|
|
54
|
+
fill: circle.fill,
|
|
55
|
+
fillOpacity: circle.fillOpacity
|
|
56
|
+
}, i))
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
const _excluded = ["size", "colour", "gap"];
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
6
|
+
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); }
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
9
|
+
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; }
|
|
10
|
+
export default function HeatmapIcon(_ref) {
|
|
11
|
+
let {
|
|
12
|
+
size = 40,
|
|
13
|
+
colour = '#000',
|
|
14
|
+
gap = 1
|
|
15
|
+
} = _ref,
|
|
16
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
17
|
+
const rows = 6; // genes
|
|
18
|
+
const cols = 8; // cells
|
|
19
|
+
|
|
20
|
+
// Example expression pattern for visual clusters
|
|
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]];
|
|
22
|
+
const cellWidth = (size - (cols - 1) * gap) / cols;
|
|
23
|
+
const cellHeight = (size - (rows - 1) * gap) / rows;
|
|
24
|
+
return /*#__PURE__*/_jsx("svg", _objectSpread(_objectSpread({
|
|
25
|
+
width: size,
|
|
26
|
+
height: size,
|
|
27
|
+
viewBox: "0 0 ".concat(size, " ").concat(size),
|
|
28
|
+
xmlns: "http://www.w3.org/2000/svg"
|
|
29
|
+
}, props), {}, {
|
|
30
|
+
children: expressionLevels.map((row, rowIndex) => row.map((value, colIndex) => /*#__PURE__*/_jsx("rect", {
|
|
31
|
+
x: colIndex * (cellWidth + gap),
|
|
32
|
+
y: rowIndex * (cellHeight + gap),
|
|
33
|
+
width: cellWidth,
|
|
34
|
+
height: cellHeight,
|
|
35
|
+
fill: colour,
|
|
36
|
+
fillOpacity: value
|
|
37
|
+
}, "".concat(rowIndex, "-").concat(colIndex))))
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const _excluded = ["size", "colour", "gap"];
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
6
|
+
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); }
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
9
|
+
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; }
|
|
10
|
+
export default function MatrixPlotIcon(_ref) {
|
|
11
|
+
let {
|
|
12
|
+
size = 40,
|
|
13
|
+
colour = '#000',
|
|
14
|
+
gap = 2
|
|
15
|
+
} = _ref,
|
|
16
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
17
|
+
const rows = 4;
|
|
18
|
+
const cols = 4;
|
|
19
|
+
const squareSize = (size - gap * (cols - 1)) / cols;
|
|
20
|
+
const squares = [];
|
|
21
|
+
for (let row = 0; row < rows; row++) {
|
|
22
|
+
for (let col = 0; col < cols; col++) {
|
|
23
|
+
squares.push({
|
|
24
|
+
x: col * (squareSize + gap),
|
|
25
|
+
y: row * (squareSize + gap)
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const semiTransparentSquares = [0, 5, 10, 15];
|
|
30
|
+
return /*#__PURE__*/_jsx("svg", _objectSpread(_objectSpread({
|
|
31
|
+
width: size,
|
|
32
|
+
height: size,
|
|
33
|
+
viewBox: "0 0 ".concat(size, " ").concat(size),
|
|
34
|
+
xmlns: "http://www.w3.org/2000/svg"
|
|
35
|
+
}, props), {}, {
|
|
36
|
+
children: squares.map((_ref2, i) => {
|
|
37
|
+
let {
|
|
38
|
+
x,
|
|
39
|
+
y
|
|
40
|
+
} = _ref2;
|
|
41
|
+
return /*#__PURE__*/_jsx("rect", {
|
|
42
|
+
x: x,
|
|
43
|
+
y: y,
|
|
44
|
+
width: squareSize,
|
|
45
|
+
height: squareSize,
|
|
46
|
+
fill: colour,
|
|
47
|
+
fillOpacity: semiTransparentSquares.includes(i) ? 0.5 : 1
|
|
48
|
+
}, i);
|
|
49
|
+
})
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const _excluded = ["size", "colour", "gap"];
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
6
|
+
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); }
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
function _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var n = Object.getOwnPropertySymbols(e); for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }
|
|
9
|
+
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; }
|
|
10
|
+
export default function MatrixPlotIcon(_ref) {
|
|
11
|
+
let {
|
|
12
|
+
size = 40,
|
|
13
|
+
colour = '#000',
|
|
14
|
+
gap = 2
|
|
15
|
+
} = _ref,
|
|
16
|
+
props = _objectWithoutProperties(_ref, _excluded);
|
|
17
|
+
const rows = 3;
|
|
18
|
+
const cols = 3;
|
|
19
|
+
const squareSize = (size - gap * (cols - 1)) / cols;
|
|
20
|
+
const squares = [];
|
|
21
|
+
for (let row = 0; row < rows; row++) {
|
|
22
|
+
for (let col = 0; col < cols; col++) {
|
|
23
|
+
squares.push({
|
|
24
|
+
x: col * (squareSize + gap),
|
|
25
|
+
y: row * (squareSize + gap)
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Example: corners semi-transparent
|
|
31
|
+
const semiTransparentSquares = [0, 2, 6, 8];
|
|
32
|
+
return /*#__PURE__*/_jsx("svg", _objectSpread(_objectSpread({
|
|
33
|
+
width: size,
|
|
34
|
+
height: size,
|
|
35
|
+
viewBox: "0 0 ".concat(size, " ").concat(size),
|
|
36
|
+
xmlns: "http://www.w3.org/2000/svg"
|
|
37
|
+
}, props), {}, {
|
|
38
|
+
children: squares.map((_ref2, i) => {
|
|
39
|
+
let {
|
|
40
|
+
x,
|
|
41
|
+
y
|
|
42
|
+
} = _ref2;
|
|
43
|
+
return /*#__PURE__*/_jsx("rect", {
|
|
44
|
+
x: x,
|
|
45
|
+
y: y,
|
|
46
|
+
width: squareSize,
|
|
47
|
+
height: squareSize,
|
|
48
|
+
fill: colour,
|
|
49
|
+
fillOpacity: semiTransparentSquares.includes(i) ? 0.5 : 1
|
|
50
|
+
}, i);
|
|
51
|
+
})
|
|
52
|
+
}));
|
|
53
|
+
}
|